made a copy
authorharris wong <hwong@ocad.ca>
Wed, 2 Jul 2008 20:56:42 +0000 (20:56 -0000)
committerharris wong <hwong@ocad.ca>
Wed, 2 Jul 2008 20:56:42 +0000 (20:56 -0000)
1587 files changed:
.htaccess [new file with mode: 0644]
404.php [new file with mode: 0644]
about.php [new file with mode: 0644]
acl.php [new file with mode: 0644]
admin/admin_delete.php [new file with mode: 0644]
admin/admin_deny.php [new file with mode: 0644]
admin/admin_email.php [new file with mode: 0644]
admin/admins/create.php [new file with mode: 0644]
admin/admins/delete.php [new file with mode: 0644]
admin/admins/detail_log.php [new file with mode: 0644]
admin/admins/edit.php [new file with mode: 0644]
admin/admins/index.php [new file with mode: 0644]
admin/admins/log.php [new file with mode: 0644]
admin/admins/my_edit.php [new file with mode: 0644]
admin/admins/my_password.php [new file with mode: 0644]
admin/admins/password.php [new file with mode: 0644]
admin/admins/reset_log.php [new file with mode: 0644]
admin/auto_enroll.php [new file with mode: 0644]
admin/auto_enroll_delete.php [new file with mode: 0644]
admin/auto_enroll_edit.php [new file with mode: 0644]
admin/auto_enroll_filter_courses.php [new file with mode: 0644]
admin/backup/create.php [new file with mode: 0644]
admin/backup/delete.php [new file with mode: 0644]
admin/backup/edit.php [new file with mode: 0644]
admin/backup/index.php [new file with mode: 0644]
admin/backup/restore.php [new file with mode: 0644]
admin/config_edit.php [new file with mode: 0644]
admin/config_template.php [new file with mode: 0644]
admin/course_categories.php [new file with mode: 0644]
admin/courses.php [new file with mode: 0644]
admin/create_category.php [new file with mode: 0644]
admin/create_course.php [new file with mode: 0644]
admin/create_user.php [new file with mode: 0644]
admin/cron.php [new file with mode: 0644]
admin/cron_config.php [new file with mode: 0644]
admin/default_preferences.php [new file with mode: 0644]
admin/delete_category.php [new file with mode: 0644]
admin/delete_course.php [new file with mode: 0644]
admin/edit_category.php [new file with mode: 0644]
admin/edit_course.php [new file with mode: 0644]
admin/edit_user.php [new file with mode: 0644]
admin/enrollment/enroll_edit.php [new file with mode: 0644]
admin/enrollment/index.php [new file with mode: 0644]
admin/enrollment/privileges.php [new file with mode: 0644]
admin/error_logging.php [new file with mode: 0644]
admin/error_logging_bundle.php [new file with mode: 0644]
admin/error_logging_details.php [new file with mode: 0644]
admin/error_logging_reset.php [new file with mode: 0644]
admin/error_logging_view.php [new file with mode: 0644]
admin/fix_content.php [new file with mode: 0644]
admin/forum_add.php [new file with mode: 0644]
admin/forum_delete.php [new file with mode: 0644]
admin/forum_edit.php [new file with mode: 0644]
admin/forums.php [new file with mode: 0644]
admin/index.php [new file with mode: 0644]
admin/instructor_login.php [new file with mode: 0644]
admin/instructor_requests.php [new file with mode: 0644]
admin/language.php [new file with mode: 0644]
admin/language_add.php [new file with mode: 0644]
admin/language_delete.php [new file with mode: 0644]
admin/language_edit.php [new file with mode: 0644]
admin/language_editor.php [new file with mode: 0644]
admin/language_import.php [new file with mode: 0644]
admin/language_term.php [new file with mode: 0644]
admin/language_translate.php [new file with mode: 0644]
admin/master_list.php [new file with mode: 0644]
admin/master_list_delete.php [new file with mode: 0644]
admin/master_list_edit.php [new file with mode: 0644]
admin/missing_language.php [new file with mode: 0644]
admin/modules/add_new.php [new file with mode: 0644]
admin/modules/create.php [new file with mode: 0644]
admin/modules/default_mods.php [new file with mode: 0644]
admin/modules/default_side.php [new file with mode: 0644]
admin/modules/details.php [new file with mode: 0644]
admin/modules/index.php [new file with mode: 0644]
admin/modules/module.template.php [new file with mode: 0644]
admin/password_user.php [new file with mode: 0644]
admin/profile_picture.php [new file with mode: 0644]
admin/rss_feeds/add_feed.php [new file with mode: 0644]
admin/rss_feeds/delete_feed.php [new file with mode: 0644]
admin/rss_feeds/edit_feed.php [new file with mode: 0644]
admin/rss_feeds/index.php [new file with mode: 0644]
admin/rss_feeds/preview.php [new file with mode: 0644]
admin/themes/delete.php [new file with mode: 0644]
admin/themes/import.php [new file with mode: 0644]
admin/themes/index.php [new file with mode: 0644]
admin/translate.php [new file with mode: 0644]
admin/translate_atutor.php [new file with mode: 0644]
admin/translator.php [new file with mode: 0644]
admin/user_enrollment.php [new file with mode: 0644]
admin/user_status.php [new file with mode: 0644]
admin/users.php [new file with mode: 0644]
assignments/add_assignment.php [new file with mode: 0644]
assignments/delete_assignment.php [new file with mode: 0644]
assignments/edit_assignment.php [new file with mode: 0644]
assignments/index.php [new file with mode: 0644]
assignments/index_instructor.php [new file with mode: 0644]
blogs/add_post.php [new file with mode: 0644]
blogs/delete_comment.php [new file with mode: 0644]
blogs/delete_post.php [new file with mode: 0644]
blogs/edit_post.php [new file with mode: 0644]
blogs/index.php [new file with mode: 0644]
blogs/post.php [new file with mode: 0644]
blogs/view.php [new file with mode: 0644]
bounce.php [new file with mode: 0644]
browse.php [new file with mode: 0644]
calendar.js [new file with mode: 0644]
chat/MachineThatGoesBing.class [new file with mode: 0644]
chat/admin.settings.default [new file with mode: 0644]
chat/atrc.gif [new file with mode: 0644]
chat/bing.php [new file with mode: 0644]
chat/bings/.html [new file with mode: 0644]
chat/bings/chime.au [new file with mode: 0644]
chat/bings/chime.wav [new file with mode: 0644]
chat/bings/taras.html [new file with mode: 0644]
chat/bings/taras.php [new file with mode: 0644]
chat/chat.php [new file with mode: 0644]
chat/display.php [new file with mode: 0644]
chat/filterHistory.php [new file with mode: 0644]
chat/help.php [new file with mode: 0644]
chat/history.php [new file with mode: 0644]
chat/include/html/chat_footer.inc.php [new file with mode: 0644]
chat/include/html/chat_header.inc.php [new file with mode: 0644]
chat/include/html/login_footer.inc.php [new file with mode: 0644]
chat/include/html/login_header.inc.php [new file with mode: 0644]
chat/index.php [new file with mode: 0644]
chat/logout.php [new file with mode: 0644]
chat/options.php [new file with mode: 0644]
chat/poster.php [new file with mode: 0644]
chat/prefs.php [new file with mode: 0644]
chat/prefs2.php [new file with mode: 0644]
chat/view_transcript.php [new file with mode: 0644]
confirm.php [new file with mode: 0644]
contact_instructor.php [new file with mode: 0644]
content.php [new file with mode: 0644]
directory.php [new file with mode: 0644]
documentation/add_note.php [new file with mode: 0644]
documentation/admin/administrators.php [new file with mode: 0644]
documentation/admin/auto_enroll.php [new file with mode: 0644]
documentation/admin/backups.php [new file with mode: 0644]
documentation/admin/categories.php [new file with mode: 0644]
documentation/admin/configuration.php [new file with mode: 0644]
documentation/admin/courses.php [new file with mode: 0644]
documentation/admin/create_patches.php [new file with mode: 0644]
documentation/admin/creating_courses.php [new file with mode: 0644]
documentation/admin/creating_themes.php [new file with mode: 0644]
documentation/admin/cron_setup.php [new file with mode: 0644]
documentation/admin/default_preferences.php [new file with mode: 0644]
documentation/admin/default_side_menu.php [new file with mode: 0644]
documentation/admin/default_student_tools.php [new file with mode: 0644]
documentation/admin/email_users.php [new file with mode: 0644]
documentation/admin/en/index.php [new file with mode: 0644]
documentation/admin/enrollment.php [new file with mode: 0644]
documentation/admin/enrollment_privileges.php [new file with mode: 0644]
documentation/admin/error_logging.php [new file with mode: 0644]
documentation/admin/feeds.php [new file with mode: 0644]
documentation/admin/forums.php [new file with mode: 0644]
documentation/admin/fr/index.php [new file with mode: 0644]
documentation/admin/google_key.php [new file with mode: 0644]
documentation/admin/importing_themes.php [new file with mode: 0644]
documentation/admin/index.php [new file with mode: 0644]
documentation/admin/installation.php [new file with mode: 0644]
documentation/admin/instructor_requests.php [new file with mode: 0644]
documentation/admin/introduction.php [new file with mode: 0644]
documentation/admin/languages.php [new file with mode: 0644]
documentation/admin/link-out.gif [new file with mode: 0644]
documentation/admin/managing_existing_themes.php [new file with mode: 0644]
documentation/admin/master_student_list.php [new file with mode: 0644]
documentation/admin/modules.php [new file with mode: 0644]
documentation/admin/my_account.php [new file with mode: 0644]
documentation/admin/new_installation.php [new file with mode: 0644]
documentation/admin/pages.inc.php [new file with mode: 0644]
documentation/admin/patcher.php [new file with mode: 0644]
documentation/admin/requirements_recommendations.php [new file with mode: 0644]
documentation/admin/styles.css [new file with mode: 0644]
documentation/admin/system_preferences.php [new file with mode: 0644]
documentation/admin/themes.php [new file with mode: 0644]
documentation/admin/troubleshooting.php [new file with mode: 0644]
documentation/admin/upgrading.php [new file with mode: 0644]
documentation/admin/users.php [new file with mode: 0644]
documentation/approve_note.php [new file with mode: 0644]
documentation/common/body_footer.inc.php [new file with mode: 0644]
documentation/common/body_header.inc.php [new file with mode: 0644]
documentation/common/folder.gif [new file with mode: 0644]
documentation/common/fr/text.php [new file with mode: 0644]
documentation/common/frame_header.php [new file with mode: 0644]
documentation/common/frame_toc.php [new file with mode: 0644]
documentation/common/link-out.gif [new file with mode: 0644]
documentation/common/paper.gif [new file with mode: 0644]
documentation/common/print.php [new file with mode: 0644]
documentation/common/search.php [new file with mode: 0644]
documentation/common/styles.css [new file with mode: 0644]
documentation/common/text.php [new file with mode: 0644]
documentation/common/vitals.inc.php [new file with mode: 0644]
documentation/config.inc.php [new file with mode: 0644]
documentation/delete_note.php [new file with mode: 0644]
documentation/developer/database.gif [new file with mode: 0644]
documentation/developer/guidelines.html [new file with mode: 0644]
documentation/developer/modules.html [new file with mode: 0644]
documentation/developer/styles.css [new file with mode: 0644]
documentation/general/browse_courses.php [new file with mode: 0644]
documentation/general/create_course.php [new file with mode: 0644]
documentation/general/en/index.php [new file with mode: 0644]
documentation/general/export_content.php [new file with mode: 0644]
documentation/general/file_storage.php [new file with mode: 0644]
documentation/general/fr/index.php [new file with mode: 0644]
documentation/general/inbox.php [new file with mode: 0644]
documentation/general/index.php [new file with mode: 0644]
documentation/general/inside_course.php [new file with mode: 0644]
documentation/general/introduction.php [new file with mode: 0644]
documentation/general/login.php [new file with mode: 0644]
documentation/general/my_courses.php [new file with mode: 0644]
documentation/general/my_start_page.php [new file with mode: 0644]
documentation/general/packages.php [new file with mode: 0644]
documentation/general/pages.inc.php [new file with mode: 0644]
documentation/general/password_reminder.php [new file with mode: 0644]
documentation/general/preferences.php [new file with mode: 0644]
documentation/general/profile.php [new file with mode: 0644]
documentation/general/register.php [new file with mode: 0644]
documentation/general/tile.php [new file with mode: 0644]
documentation/index.php [new file with mode: 0644]
documentation/index/en/index.php [new file with mode: 0644]
documentation/index/fr/index.php [new file with mode: 0644]
documentation/index/index.php [new file with mode: 0644]
documentation/index_list.php [new file with mode: 0644]
documentation/instructor/accessibility.php [new file with mode: 0644]
documentation/instructor/add_questions.php [new file with mode: 0644]
documentation/instructor/announcements.php [new file with mode: 0644]
documentation/instructor/assignments.php [new file with mode: 0644]
documentation/instructor/authenticated_access.php [new file with mode: 0644]
documentation/instructor/backups.php [new file with mode: 0644]
documentation/instructor/chat.php [new file with mode: 0644]
documentation/instructor/content.html [new file with mode: 0644]
documentation/instructor/content.php [new file with mode: 0644]
documentation/instructor/content_edit.php [new file with mode: 0644]
documentation/instructor/content_packages.php [new file with mode: 0644]
documentation/instructor/content_preview.php [new file with mode: 0644]
documentation/instructor/content_properties.php [new file with mode: 0644]
documentation/instructor/content_usage.php [new file with mode: 0644]
documentation/instructor/course_email.php [new file with mode: 0644]
documentation/instructor/creating_courses.php [new file with mode: 0644]
documentation/instructor/creating_editing_content.php [new file with mode: 0644]
documentation/instructor/creating_questions.php [new file with mode: 0644]
documentation/instructor/creating_restoring.php [new file with mode: 0644]
documentation/instructor/creating_tests_surveys.php [new file with mode: 0644]
documentation/instructor/delete_course.php [new file with mode: 0644]
documentation/instructor/downloading_uploading.php [new file with mode: 0644]
documentation/instructor/edit_delete_tests.php [new file with mode: 0644]
documentation/instructor/editing_deleting.php [new file with mode: 0644]
documentation/instructor/en/index.php [new file with mode: 0644]
documentation/instructor/enrollment.php [new file with mode: 0644]
documentation/instructor/enrollment_alumni.php [new file with mode: 0644]
documentation/instructor/enrollment_course_list.php [new file with mode: 0644]
documentation/instructor/enrollment_privileges.php [new file with mode: 0644]
documentation/instructor/extracting_zip_archives.php [new file with mode: 0644]
documentation/instructor/faq.php [new file with mode: 0644]
documentation/instructor/feeds.php [new file with mode: 0644]
documentation/instructor/file_manager.php [new file with mode: 0644]
documentation/instructor/forums.php [new file with mode: 0644]
documentation/instructor/fr/index.php [new file with mode: 0644]
documentation/instructor/glossary.php [new file with mode: 0644]
documentation/instructor/glossary_terms.php [new file with mode: 0644]
documentation/instructor/gradebook.php [new file with mode: 0644]
documentation/instructor/gradebook_add.php [new file with mode: 0644]
documentation/instructor/gradebook_edit_marks.php [new file with mode: 0644]
documentation/instructor/gradebook_external_marks.php [new file with mode: 0644]
documentation/instructor/gradebook_scales.php [new file with mode: 0644]
documentation/instructor/gradebook_update.php [new file with mode: 0644]
documentation/instructor/groups.php [new file with mode: 0644]
documentation/instructor/index.php [new file with mode: 0644]
documentation/instructor/introduction.php [new file with mode: 0644]
documentation/instructor/links.php [new file with mode: 0644]
documentation/instructor/managing_files_folders.php [new file with mode: 0644]
documentation/instructor/managing_posts.php [new file with mode: 0644]
documentation/instructor/managing_threads.php [new file with mode: 0644]
documentation/instructor/pages.inc.php [new file with mode: 0644]
documentation/instructor/polls.php [new file with mode: 0644]
documentation/instructor/preview.php [new file with mode: 0644]
documentation/instructor/properties.php [new file with mode: 0644]
documentation/instructor/question_categories.php [new file with mode: 0644]
documentation/instructor/question_database.php [new file with mode: 0644]
documentation/instructor/reading_list.php [new file with mode: 0644]
documentation/instructor/scorm_packages.php [new file with mode: 0644]
documentation/instructor/side_menu.php [new file with mode: 0644]
documentation/instructor/statistics.php [new file with mode: 0644]
documentation/instructor/student_submissions.php [new file with mode: 0644]
documentation/instructor/student_tools.php [new file with mode: 0644]
documentation/instructor/test_statistics.php [new file with mode: 0644]
documentation/instructor/tests_surveys.php [new file with mode: 0644]
documentation/instructor/tile_repository.php [new file with mode: 0644]
documentation/instructor/web_search.php [new file with mode: 0644]
documentation/link-out.gif [new file with mode: 0644]
documentation/styles.css [new file with mode: 0644]
editor/add_content.php [new file with mode: 0644]
editor/add_forum.php [new file with mode: 0644]
editor/add_news.php [new file with mode: 0644]
editor/delete_content.php [new file with mode: 0644]
editor/delete_forum.php [new file with mode: 0644]
editor/delete_news.php [new file with mode: 0644]
editor/edit_content.php [new file with mode: 0644]
editor/edit_forum.php [new file with mode: 0644]
editor/edit_news.php [new file with mode: 0644]
editor/edit_post.php [new file with mode: 0644]
editor/index.php [new file with mode: 0644]
editor/view_item.php [new file with mode: 0644]
enroll.php [new file with mode: 0644]
exestyles.css [new file with mode: 0644]
export.php [new file with mode: 0644]
faq/add_question.php [new file with mode: 0644]
faq/add_topic.php [new file with mode: 0644]
faq/delete_question.php [new file with mode: 0644]
faq/delete_topic.php [new file with mode: 0644]
faq/edit_question.php [new file with mode: 0644]
faq/edit_topic.php [new file with mode: 0644]
faq/icon.gif [new file with mode: 0644]
faq/index.php [new file with mode: 0644]
faq/index_instructor.php [new file with mode: 0644]
favicon.ico [new file with mode: 0644]
file_storage/assignment.php [new file with mode: 0644]
file_storage/comments.php [new file with mode: 0644]
file_storage/delete_comment.php [new file with mode: 0644]
file_storage/delete_revision.php [new file with mode: 0644]
file_storage/edit.php [new file with mode: 0644]
file_storage/edit_folder.php [new file with mode: 0644]
file_storage/index.php [new file with mode: 0644]
file_storage/move.php [new file with mode: 0644]
file_storage/new.php [new file with mode: 0644]
file_storage/revisions.php [new file with mode: 0644]
forum/delete_thread.php [new file with mode: 0644]
forum/index.php [new file with mode: 0644]
forum/list.php [new file with mode: 0644]
forum/lock_thread.php [new file with mode: 0644]
forum/move_thread.php [new file with mode: 0644]
forum/new_thread.php [new file with mode: 0644]
forum/stick.php [new file with mode: 0644]
forum/subscribe.php [new file with mode: 0644]
forum/subscribe_forum.php [new file with mode: 0644]
forum/view.php [new file with mode: 0644]
get.php [new file with mode: 0644]
get_acheck.php [new file with mode: 0644]
get_course_icon.php [new file with mode: 0644]
get_noid.php [new file with mode: 0644]
get_profile_img.php [new file with mode: 0644]
get_rss.php [new file with mode: 0644]
glossary/index.php [new file with mode: 0644]
go.php [new file with mode: 0644]
google_search/admin/module_prefs.php [new file with mode: 0644]
google_search/google.gif [new file with mode: 0644]
google_search/gsearch.php [new file with mode: 0644]
google_search/index.php [new file with mode: 0644]
groups.php [new file with mode: 0644]
headstuff.php [new file with mode: 0644]
help/accessibility.php [new file with mode: 0644]
help/contact_support.php [new file with mode: 0644]
help/index.php [new file with mode: 0644]
images/after.gif [new file with mode: 0644]
images/archive.gif [new file with mode: 0644]
images/arrow_ltr.gif [new file with mode: 0644]
images/arrowicon.gif [new file with mode: 0644]
images/at-logo.gif [new file with mode: 0644]
images/at-logo.v.3.gif [new file with mode: 0644]
images/bad.gif [new file with mode: 0644]
images/before.gif [new file with mode: 0644]
images/blue.gif [new file with mode: 0644]
images/calendar.gif [new file with mode: 0644]
images/changes_bullet.gif [new file with mode: 0644]
images/check.gif [new file with mode: 0644]
images/checkbox_check.gif [new file with mode: 0644]
images/checkbox_empty.gif [new file with mode: 0644]
images/checkmark.gif [new file with mode: 0644]
images/child_of.gif [new file with mode: 0644]
images/clr.gif [new file with mode: 0644]
images/content_pkg.gif [new file with mode: 0644]
images/courses/3dgraph.jpg [new file with mode: 0644]
images/courses/anotomy.jpg [new file with mode: 0644]
images/courses/art_supplies.jpg [new file with mode: 0644]
images/courses/astronaut.jpg [new file with mode: 0644]
images/courses/bar_graph.jpg [new file with mode: 0644]
images/courses/books.jpg [new file with mode: 0644]
images/courses/botany.jpg [new file with mode: 0644]
images/courses/brain2.jpg [new file with mode: 0644]
images/courses/business.jpg [new file with mode: 0644]
images/courses/business_service.jpg [new file with mode: 0644]
images/courses/caduceus.jpg [new file with mode: 0644]
images/courses/car_wireframe.jpg [new file with mode: 0644]
images/courses/cell-anatomy.jpg [new file with mode: 0644]
images/courses/chemistry.jpg [new file with mode: 0644]
images/courses/columbus.jpg [new file with mode: 0644]
images/courses/disabled_sign.gif [new file with mode: 0644]
images/courses/drafting.jpg [new file with mode: 0644]
images/courses/engine.jpg [new file with mode: 0644]
images/courses/feather-pen.jpg [new file with mode: 0644]
images/courses/fire_helmut.jpg [new file with mode: 0644]
images/courses/fractal.jpg [new file with mode: 0644]
images/courses/head_wireframe.jpg [new file with mode: 0644]
images/courses/helix.jpg [new file with mode: 0644]
images/courses/helmet.jpg [new file with mode: 0644]
images/courses/light-bulb.jpg [new file with mode: 0644]
images/courses/map.jpg [new file with mode: 0644]
images/courses/microchip.jpg [new file with mode: 0644]
images/courses/microscope.jpg [new file with mode: 0644]
images/courses/molecule.jpg [new file with mode: 0644]
images/courses/nav_wheel.jpg [new file with mode: 0644]
images/courses/normal_surfaces.jpg [new file with mode: 0644]
images/courses/pedal.jpg [new file with mode: 0644]
images/courses/pharao.jpg [new file with mode: 0644]
images/courses/pharmacy.jpg [new file with mode: 0644]
images/courses/planet-earth.jpg [new file with mode: 0644]
images/courses/police_hat.jpg [new file with mode: 0644]
images/courses/recycling.jpg [new file with mode: 0644]
images/courses/skull.jpg [new file with mode: 0644]
images/courses/skull_wireframe.jpg [new file with mode: 0644]
images/courses/sl_logo.gif [new file with mode: 0644]
images/courses/snail.jpg [new file with mode: 0644]
images/courses/sphere.jpg [new file with mode: 0644]
images/courses/sphinx.jpg [new file with mode: 0644]
images/courses/toolbox.jpg [new file with mode: 0644]
images/courses/triangle.jpg [new file with mode: 0644]
images/courses/two_roads.jpg [new file with mode: 0644]
images/edit.gif [new file with mode: 0644]
images/feedback.gif [new file with mode: 0644]
images/file.gif [new file with mode: 0644]
images/file_types/audio.gif [new file with mode: 0644]
images/file_types/binary.gif [new file with mode: 0644]
images/file_types/csv.gif [new file with mode: 0644]
images/file_types/doc.gif [new file with mode: 0644]
images/file_types/dvi.gif [new file with mode: 0644]
images/file_types/generic.gif [new file with mode: 0644]
images/file_types/image.gif [new file with mode: 0644]
images/file_types/mdb.gif [new file with mode: 0644]
images/file_types/mpp.gif [new file with mode: 0644]
images/file_types/ood.gif [new file with mode: 0644]
images/file_types/oop.gif [new file with mode: 0644]
images/file_types/oos.gif [new file with mode: 0644]
images/file_types/oot.gif [new file with mode: 0644]
images/file_types/pdf.gif [new file with mode: 0644]
images/file_types/ppt.gif [new file with mode: 0644]
images/file_types/ps.gif [new file with mode: 0644]
images/file_types/psd.gif [new file with mode: 0644]
images/file_types/qt.gif [new file with mode: 0644]
images/file_types/rtf.gif [new file with mode: 0644]
images/file_types/sql.gif [new file with mode: 0644]
images/file_types/sql2.gif [new file with mode: 0644]
images/file_types/src.gif [new file with mode: 0644]
images/file_types/swf.gif [new file with mode: 0644]
images/file_types/treeview.gif [new file with mode: 0644]
images/file_types/txt.gif [new file with mode: 0644]
images/file_types/video.gif [new file with mode: 0644]
images/file_types/viewlet.gif [new file with mode: 0644]
images/file_types/vsd.gif [new file with mode: 0644]
images/file_types/xls.gif [new file with mode: 0644]
images/file_types/xml.gif [new file with mode: 0644]
images/file_types/zip.gif [new file with mode: 0644]
images/folder.gif [new file with mode: 0644]
images/forum/19.gif [new file with mode: 0644]
images/forum/27.gif [new file with mode: 0644]
images/forum/3.gif [new file with mode: 0644]
images/forum/30.gif [new file with mode: 0644]
images/forum/51.gif [new file with mode: 0644]
images/forum/52.gif [new file with mode: 0644]
images/forum/54.gif [new file with mode: 0644]
images/forum/55.gif [new file with mode: 0644]
images/forum/56.gif [new file with mode: 0644]
images/forum/57.gif [new file with mode: 0644]
images/forum/58.gif [new file with mode: 0644]
images/forum/frown.gif [new file with mode: 0644]
images/forum/happy.gif [new file with mode: 0644]
images/forum/index.html [new file with mode: 0644]
images/forum/move.gif [new file with mode: 0644]
images/forum/ohwell.gif [new file with mode: 0644]
images/forum/smile.gif [new file with mode: 0644]
images/forum/sticky.gif [new file with mode: 0644]
images/forum/tongue.gif [new file with mode: 0644]
images/forum/topic_stick.gif [new file with mode: 0644]
images/forum/wink.gif [new file with mode: 0644]
images/glossary.gif [new file with mode: 0644]
images/glossary_small.gif [new file with mode: 0644]
images/graph.gif [new file with mode: 0644]
images/grey.gif [new file with mode: 0644]
images/help3.gif [new file with mode: 0644]
images/help4.gif [new file with mode: 0644]
images/home-acollab.gif [new file with mode: 0644]
images/home-blogs.gif [new file with mode: 0644]
images/home-chat.gif [new file with mode: 0644]
images/home-directory.gif [new file with mode: 0644]
images/home-export_content.gif [new file with mode: 0644]
images/home-file_storage.gif [new file with mode: 0644]
images/home-forums.gif [new file with mode: 0644]
images/home-glossary.gif [new file with mode: 0644]
images/home-links.gif [new file with mode: 0644]
images/home-polls.gif [new file with mode: 0644]
images/home-reading_list.gif [new file with mode: 0644]
images/home-site_map.gif [new file with mode: 0644]
images/home-tests.gif [new file with mode: 0644]
images/home-tile_search.gif [new file with mode: 0644]
images/home-tracker.gif [new file with mode: 0644]
images/icon-zip.gif [new file with mode: 0644]
images/icon_delete.gif [new file with mode: 0644]
images/icon_minipost.gif [new file with mode: 0644]
images/index.html [new file with mode: 0644]
images/lock.gif [new file with mode: 0644]
images/logo.gif [new file with mode: 0644]
images/move-down.gif [new file with mode: 0644]
images/move-up.gif [new file with mode: 0644]
images/new.gif [new file with mode: 0644]
images/pen.gif [new file with mode: 0644]
images/pen2.gif [new file with mode: 0644]
images/pen3.gif [new file with mode: 0644]
images/pub_default.jpg [new file with mode: 0644]
images/question.gif [new file with mode: 0644]
images/red.gif [new file with mode: 0644]
images/rtl_tree/index.html [new file with mode: 0644]
images/rtl_tree/tree_collapse.gif [new file with mode: 0644]
images/rtl_tree/tree_end.gif [new file with mode: 0644]
images/rtl_tree/tree_expand.gif [new file with mode: 0644]
images/rtl_tree/tree_horizontal.gif [new file with mode: 0644]
images/rtl_tree/tree_split.gif [new file with mode: 0644]
images/rtl_tree/tree_vertline.gif [new file with mode: 0644]
images/search.gif [new file with mode: 0644]
images/star.gif [new file with mode: 0644]
images/toc.gif [new file with mode: 0644]
images/topic_lock.gif [new file with mode: 0644]
images/transfer.gif [new file with mode: 0644]
images/tree/index.html [new file with mode: 0644]
images/tree/tree_collapse.gif [new file with mode: 0644]
images/tree/tree_disabled.gif [new file with mode: 0644]
images/tree/tree_end.gif [new file with mode: 0644]
images/tree/tree_expand.gif [new file with mode: 0644]
images/tree/tree_horizontal.gif [new file with mode: 0644]
images/tree/tree_space.gif [new file with mode: 0644]
images/tree/tree_split.gif [new file with mode: 0644]
images/tree/tree_vertline.gif [new file with mode: 0644]
images/unlock.gif [new file with mode: 0644]
images/x.gif [new file with mode: 0644]
inbox/export.php [new file with mode: 0644]
inbox/index.php [new file with mode: 0644]
inbox/send_message.php [new file with mode: 0644]
inbox/sent_messages.php [new file with mode: 0644]
include/classes/Backup/Backup.class.php [new file with mode: 0644]
include/classes/Backup/TableBackup.class.php [new file with mode: 0644]
include/classes/CSVExport.class.php [new file with mode: 0644]
include/classes/CSVImport.class.php [new file with mode: 0644]
include/classes/ContentManager.class.php [new file with mode: 0644]
include/classes/ErrorHandler/ErrorHandler.class.php [new file with mode: 0644]
include/classes/FileManager.class.php [new file with mode: 0644]
include/classes/Language/Language.class.php [new file with mode: 0644]
include/classes/Language/LanguageEditor.class.php [new file with mode: 0644]
include/classes/Language/LanguageManager.class.php [new file with mode: 0644]
include/classes/Language/LanguageParser.class.php [new file with mode: 0644]
include/classes/Language/LanguagesParser.class.php [new file with mode: 0644]
include/classes/Language/RemoteLanguageManager.class.php [new file with mode: 0644]
include/classes/Message/Message.class.php [new file with mode: 0644]
include/classes/Module/Module.class.php [new file with mode: 0644]
include/classes/Module/ModuleParser.class.php [new file with mode: 0644]
include/classes/Savant2/Savant2.php [new file with mode: 0644]
include/classes/Savant2/Savant2/Compiler.php [new file with mode: 0644]
include/classes/Savant2/Savant2/Error.php [new file with mode: 0644]
include/classes/Savant2/Savant2/Filter.php [new file with mode: 0644]
include/classes/Savant2/Savant2/Plugin.php [new file with mode: 0644]
include/classes/Savant2/Savant2/Savant2_Error_exception.php [new file with mode: 0644]
include/classes/Savant2/Savant2/Savant2_Error_pear.php [new file with mode: 0644]
include/classes/Savant2/Savant2/Savant2_Error_stack.php [new file with mode: 0644]
include/classes/Savant2/Savant2/Savant2_Plugin_cycle.php [new file with mode: 0644]
include/classes/Themes/ThemeParser.class.php [new file with mode: 0644]
include/classes/UrlRewrite/ContentUrl.class.php [new file with mode: 0644]
include/classes/UrlRewrite/FileStorageUrl.class.php [new file with mode: 0644]
include/classes/UrlRewrite/ForumsUrl.class.php [new file with mode: 0644]
include/classes/UrlRewrite/GlossaryUrl.class.php [new file with mode: 0644]
include/classes/UrlRewrite/TestsUrl.class.php [new file with mode: 0644]
include/classes/UrlRewrite/UrlParser.class.php [new file with mode: 0644]
include/classes/UrlRewrite/UrlRewrite.class.php [new file with mode: 0644]
include/classes/XML/XML_HTMLSax/HTMLSax/XML_HTMLSax_Decorators.php [new file with mode: 0644]
include/classes/XML/XML_HTMLSax/HTMLSax/XML_HTMLSax_States.php [new file with mode: 0644]
include/classes/XML/XML_HTMLSax/OS/Guess.php [new file with mode: 0644]
include/classes/XML/XML_HTMLSax/PEAR.php [new file with mode: 0644]
include/classes/XML/XML_HTMLSax/PEAR/Autoloader.php [new file with mode: 0644]
include/classes/XML/XML_HTMLSax/PEAR/Common.php [new file with mode: 0644]
include/classes/XML/XML_HTMLSax/PEAR/Config.php [new file with mode: 0644]
include/classes/XML/XML_HTMLSax/PEAR/Remote.php [new file with mode: 0644]
include/classes/XML/XML_HTMLSax/System.php [new file with mode: 0644]
include/classes/XML/XML_HTMLSax/XML_HTMLSax.php [new file with mode: 0644]
include/classes/cssparser.php [new file with mode: 0644]
include/classes/feedcreator.class.php [new file with mode: 0644]
include/classes/lastRSS.php [new file with mode: 0644]
include/classes/nusoap.php [new file with mode: 0644]
include/classes/pclzip.lib.php [new file with mode: 0644]
include/classes/phpmailer/atutormailer.class.php [new file with mode: 0644]
include/classes/phpmailer/class.phpmailer.php [new file with mode: 0644]
include/classes/phpmailer/class.smtp.php [new file with mode: 0644]
include/classes/phpmailer/phpmailer.lang-en.php [new file with mode: 0644]
include/classes/sqlutility.class.php [new file with mode: 0644]
include/classes/testQuestions.class.php [new file with mode: 0644]
include/classes/vcard.php [new file with mode: 0644]
include/classes/zipfile.class.php [new file with mode: 0644]
include/footer.inc.php [new file with mode: 0644]
include/header.inc.php [new file with mode: 0644]
include/html/announcements.inc.php [new file with mode: 0644]
include/html/auto_enroll_courses.inc.php [new file with mode: 0644]
include/html/auto_enroll_list_courses.inc.php [new file with mode: 0644]
include/html/browse.inc.php [new file with mode: 0644]
include/html/code_picker.inc.php [new file with mode: 0644]
include/html/copyright.inc.php [new file with mode: 0644]
include/html/course_icon.inc.php [new file with mode: 0644]
include/html/course_properties.inc.php [new file with mode: 0644]
include/html/dropdowns/glossary.inc.php [new file with mode: 0644]
include/html/dropdowns/menu_menu.inc.php [new file with mode: 0644]
include/html/dropdowns/poll.inc.php [new file with mode: 0644]
include/html/dropdowns/posts.inc.php [new file with mode: 0644]
include/html/dropdowns/related_topics.inc.php [new file with mode: 0644]
include/html/dropdowns/search.inc.php [new file with mode: 0644]
include/html/dropdowns/users_online.inc.php [new file with mode: 0644]
include/html/editor_tabs/accessibility.inc.php [new file with mode: 0644]
include/html/editor_tabs/content_code_picker.inc.php [new file with mode: 0644]
include/html/editor_tabs/edit.inc.php [new file with mode: 0644]
include/html/editor_tabs/glossary.inc.php [new file with mode: 0644]
include/html/editor_tabs/preview.inc.php [new file with mode: 0644]
include/html/editor_tabs/properties.inc.php [new file with mode: 0644]
include/html/enroll_edit.inc.php [new file with mode: 0644]
include/html/enroll_tab_functions.inc.php [new file with mode: 0644]
include/html/enrollment.inc.php [new file with mode: 0644]
include/html/filemanager_display.inc.php [new file with mode: 0644]
include/html/forum.inc.php [new file with mode: 0644]
include/html/frameset/footer.inc.php [new file with mode: 0644]
include/html/frameset/header.inc.php [new file with mode: 0644]
include/html/languages.inc.php [new file with mode: 0644]
include/html/new_thread.inc.php [new file with mode: 0644]
include/html/privileges.inc.php [new file with mode: 0644]
include/html/profile_picture.inc.php [new file with mode: 0644]
include/html/release_date.inc.php [new file with mode: 0644]
include/html/search.inc.php [new file with mode: 0644]
include/html/tests_questions.inc.php [new file with mode: 0644]
include/ims/adlcp_rootv1p2.xsd [new file with mode: 0644]
include/ims/footer.html [new file with mode: 0644]
include/ims/ims.css [new file with mode: 0644]
include/ims/ims_template.inc.php [new file with mode: 0644]
include/ims/ims_xml.xsd [new file with mode: 0644]
include/ims/imscp_rootv1p1p2.xsd [new file with mode: 0644]
include/ims/imsmd_rootv1p2p1.xsd [new file with mode: 0644]
include/index.html [new file with mode: 0644]
include/lib/admin_categories.inc.php [new file with mode: 0644]
include/lib/chat.inc.php [new file with mode: 0644]
include/lib/chat_defaults.inc.php [new file with mode: 0644]
include/lib/constants.inc.php [new file with mode: 0644]
include/lib/course.inc.php [new file with mode: 0644]
include/lib/delete_course.inc.php [new file with mode: 0644]
include/lib/editor_tab_functions.inc.php [new file with mode: 0644]
include/lib/enroll.inc.php [new file with mode: 0644]
include/lib/file_storage.inc.php [new file with mode: 0644]
include/lib/filemanager.inc.php [new file with mode: 0644]
include/lib/forums.inc.php [new file with mode: 0644]
include/lib/html_resource_parser.inc.php [new file with mode: 0644]
include/lib/likert_presets.inc.php [new file with mode: 0644]
include/lib/links.inc.php [new file with mode: 0644]
include/lib/menu_pages.php [new file with mode: 0644]
include/lib/mime.inc.php [new file with mode: 0644]
include/lib/mysql_connect.inc.php [new file with mode: 0644]
include/lib/output.inc.php [new file with mode: 0644]
include/lib/search.inc.php [new file with mode: 0644]
include/lib/test_result_functions.inc.php [new file with mode: 0644]
include/lib/theme_template.inc.php [new file with mode: 0644]
include/lib/themes.inc.php [new file with mode: 0644]
include/lib/tinymce.inc.php [new file with mode: 0644]
include/lib/tracker.inc.php [new file with mode: 0644]
include/lib/tracker2.inc.php [new file with mode: 0644]
include/lib/tracker_stats.inc.php [new file with mode: 0644]
include/lib/tracker_stats2.inc.php [new file with mode: 0644]
include/lib/utf8.php [new file with mode: 0644]
include/phpCache/ChangeLog [new file with mode: 0644]
include/phpCache/LICENSE [new file with mode: 0644]
include/phpCache/README [new file with mode: 0644]
include/phpCache/gc.php [new file with mode: 0644]
include/phpCache/phpCache.inc.php [new file with mode: 0644]
include/side_menu.inc.php [new file with mode: 0644]
include/style_popup.css [new file with mode: 0644]
include/vitals.inc.php [new file with mode: 0644]
index.php [new file with mode: 0644]
install/db/atutor_convert_db_to_utf8.sql [new file with mode: 0644]
install/db/atutor_language_text.sql [new file with mode: 0644]
install/db/atutor_schema.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.0_to_1.1.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.1_to_1.2.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.2_to_1.3.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.3.2_to_1.4.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.3_to_1.3.2.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.4.1_to_1.4.2.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.4.2_to_1.4.3.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.4.3_to_1.5.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.4_to_1.4.1.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.5.1_to_1.5.2.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.5.2_to_1.5.3.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.5.3.1_to_1.5.3.2.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.5.3.2_to_1.5.3.3.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.5.3.3_to_1.5.4.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.5.3_to_1.5.3.1.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.5.4_to_1.5.5.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.5.5_to_1.6.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.5_to_1.5.1.sql [new file with mode: 0644]
install/db/atutor_upgrade_1.6_to_1.6.1.sql [new file with mode: 0644]
install/images/bad.gif [new file with mode: 0644]
install/images/feedback.gif [new file with mode: 0644]
install/images/question.gif [new file with mode: 0644]
install/include/classes/TableConversion.class.php [new file with mode: 0644]
install/include/classes/sqlutility.php [new file with mode: 0644]
install/include/common.inc.php [new file with mode: 0644]
install/include/config_template.php [new file with mode: 0644]
install/include/footer.php [new file with mode: 0644]
install/include/header.php [new file with mode: 0644]
install/include/step1.php [new file with mode: 0644]
install/include/step2.php [new file with mode: 0644]
install/include/step3.php [new file with mode: 0644]
install/include/step4.php [new file with mode: 0644]
install/include/step5.php [new file with mode: 0644]
install/include/step6.php [new file with mode: 0644]
install/include/step7.php [new file with mode: 0644]
install/include/step8.php [new file with mode: 0644]
install/include/upgrade_header.php [new file with mode: 0644]
install/include/ustep1.php [new file with mode: 0644]
install/include/ustep2.php [new file with mode: 0644]
install/include/ustep3.php [new file with mode: 0644]
install/include/ustep4.php [new file with mode: 0644]
install/include/ustep5.php [new file with mode: 0644]
install/include/ustep6.php [new file with mode: 0644]
install/include/ustep7.php [new file with mode: 0644]
install/include/ustep_pwd_encryt.php [new file with mode: 0644]
install/index.php [new file with mode: 0644]
install/install.php [new file with mode: 0644]
install/not_installed.php [new file with mode: 0644]
install/stylesheet.css [new file with mode: 0644]
install/update_config.php [new file with mode: 0644]
install/upgrade.php [new file with mode: 0644]
jscripts/Fluid-all.js [new file with mode: 0644]
jscripts/fluid-atutor.js [new file with mode: 0644]
jscripts/fluid/Fluid.js [new file with mode: 0644]
jscripts/fluid/LayoutCustomizer.js [new file with mode: 0644]
jscripts/fluid/Lightbox.js [new file with mode: 0644]
jscripts/fluid/MultiFileUpload.js [new file with mode: 0644]
jscripts/fluid/Reorderer.js [new file with mode: 0644]
jscripts/help.js [new file with mode: 0644]
jscripts/interface.js [new file with mode: 0644]
jscripts/jquery.js [new file with mode: 0644]
jscripts/jquery/GPL-LICENSE.txt [new file with mode: 0644]
jscripts/jquery/MIT-LICENSE.txt [new file with mode: 0644]
jscripts/jquery/jARIA.js [new file with mode: 0644]
jscripts/jquery/jquery-1.2.3.js [new file with mode: 0644]
jscripts/jquery/jquery.dimensions.js [new file with mode: 0644]
jscripts/jquery/jquery.keyboard-a11y.js [new file with mode: 0644]
jscripts/jquery/jquery.tabindex.js [new file with mode: 0644]
jscripts/jquery/ui.base.js [new file with mode: 0644]
jscripts/jquery/ui.dialog.js [new file with mode: 0644]
jscripts/jquery/ui.draggable.js [new file with mode: 0644]
jscripts/jquery/ui.droppable.js [new file with mode: 0644]
jscripts/json/json2.js [new file with mode: 0644]
jscripts/tiny_mce/langs/en.js [new file with mode: 0644]
jscripts/tiny_mce/license.txt [new file with mode: 0644]
jscripts/tiny_mce/plugins/acheck/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/acheck/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/acheck/img/acheck.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/acheck/js/dialog.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/acheck/langs/en.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/acheck/langs/en_dlg.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/advhr/css/advhr.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/advhr/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/advhr/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/advhr/js/rule.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/advhr/langs/en_dlg.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/advhr/rule.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/advimage/css/advimage.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/advimage/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/advimage/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/advimage/image.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/advimage/img/sample.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/advimage/js/image.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/advimage/langs/en_dlg.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/advlink/css/advlink.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/advlink/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/advlink/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/advlink/js/advlink.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/advlink/langs/en_dlg.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/advlink/link.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/autosave/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/autosave/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/bbcode/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/bbcode/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/compat2x/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/compat2x/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/contextmenu/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/contextmenu/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/directionality/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/directionality/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/emotions.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/img/smiley-cool.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/img/smiley-cry.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/img/smiley-embarassed.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/img/smiley-foot-in-mouth.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/img/smiley-frown.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/img/smiley-innocent.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/img/smiley-kiss.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/img/smiley-laughing.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/img/smiley-money-mouth.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/img/smiley-sealed.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/img/smiley-smile.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/img/smiley-surprised.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/img/smiley-tongue-out.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/img/smiley-undecided.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/img/smiley-wink.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/img/smiley-yell.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/js/emotions.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/emotions/langs/en_dlg.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/example/dialog.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/example/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/example/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/example/img/example.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/example/js/dialog.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/example/langs/en.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/example/langs/en_dlg.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/fullpage/css/fullpage.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/fullpage/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/fullpage/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/fullpage/fullpage.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/fullpage/js/fullpage.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/fullpage/langs/en_dlg.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/fullscreen/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/fullscreen/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/fullscreen/fullscreen.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/iespell/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/iespell/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/inlinepopups/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/inlinepopups/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/button.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/window.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/inlinepopups/template.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/insertdatetime/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/insertdatetime/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/layer/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/layer/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/media/css/content.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/media/css/media.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/media/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/media/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/media/img/flash.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/media/img/flv_player.swf [new file with mode: 0644]
jscripts/tiny_mce/plugins/media/img/quicktime.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/media/img/realmedia.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/media/img/shockwave.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/media/img/trans.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/media/img/windowsmedia.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/media/js/embed.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/media/js/media.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/media/langs/en_dlg.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/media/media.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/nonbreaking/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/nonbreaking/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/noneditable/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/noneditable/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/pagebreak/css/content.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/pagebreak/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/pagebreak/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/pagebreak/img/pagebreak.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/pagebreak/img/trans.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/paste/blank.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/paste/css/blank.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/paste/css/pasteword.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/paste/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/paste/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/paste/js/pastetext.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/paste/js/pasteword.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/paste/langs/en_dlg.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/paste/pastetext.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/paste/pasteword.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/preview/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/preview/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/preview/example.html [new file with mode: 0644]
jscripts/tiny_mce/plugins/preview/jscripts/embed.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/print/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/print/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/safari/blank.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/safari/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/safari/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/save/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/save/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/searchreplace/css/searchreplace.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/searchreplace/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/searchreplace/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/searchreplace/js/searchreplace.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/searchreplace/langs/en_dlg.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/searchreplace/searchreplace.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/spellchecker/css/content.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/spellchecker/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/spellchecker/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/spellchecker/img/wline.gif [new file with mode: 0644]
jscripts/tiny_mce/plugins/style/css/props.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/style/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/style/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/style/js/props.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/style/langs/en_dlg.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/style/props.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/table/cell.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/table/css/cell.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/table/css/row.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/table/css/table.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/table/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/table/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/table/js/cell.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/table/js/merge_cells.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/table/js/row.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/table/js/table.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/table/langs/en_dlg.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/table/merge_cells.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/table/row.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/table/table.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/template/blank.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/template/css/template.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/template/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/template/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/template/js/template.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/template/langs/en_dlg.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/template/template.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/visualchars/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/visualchars/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/abbr.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/acronym.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/attributes.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/cite.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/css/attributes.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/css/popup.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/css/xhtmlxtras.css [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/del.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/editor_plugin.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/ins.htm [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/js/abbr.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/js/acronym.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/js/attributes.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/js/cite.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/js/del.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/js/element_common.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/js/ins.js [new file with mode: 0644]
jscripts/tiny_mce/plugins/xhtmlxtras/langs/en_dlg.js [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/about.htm [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/anchor.htm [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/charmap.htm [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/color_picker.htm [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/editor_template.js [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/editor_template_src.js [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/image.htm [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/img/colorpicker.jpg [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/img/icons.gif [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/js/about.js [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/js/anchor.js [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/js/charmap.js [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/js/color_picker.js [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/js/image.js [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/js/link.js [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/js/source_editor.js [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/langs/en.js [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/langs/en_dlg.js [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/link.htm [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/skins/default/content.css [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/skins/default/dialog.css [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/skins/default/img/buttons.png [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/skins/default/img/items.gif [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/skins/default/img/menu_arrow.gif [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/skins/default/img/menu_check.gif [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/skins/default/img/progress.gif [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/skins/default/img/tabs.gif [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/skins/default/ui.css [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/skins/o2k7/content.css [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/skins/o2k7/dialog.css [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg.png [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_black.png [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_silver.png [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/skins/o2k7/ui.css [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/skins/o2k7/ui_black.css [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css [new file with mode: 0644]
jscripts/tiny_mce/themes/advanced/source_editor.htm [new file with mode: 0644]
jscripts/tiny_mce/themes/simple/editor_template.js [new file with mode: 0644]
jscripts/tiny_mce/themes/simple/editor_template_src.js [new file with mode: 0644]
jscripts/tiny_mce/themes/simple/img/icons.gif [new file with mode: 0644]
jscripts/tiny_mce/themes/simple/langs/en.js [new file with mode: 0644]
jscripts/tiny_mce/themes/simple/skins/default/content.css [new file with mode: 0644]
jscripts/tiny_mce/themes/simple/skins/default/ui.css [new file with mode: 0644]
jscripts/tiny_mce/themes/simple/skins/o2k7/content.css [new file with mode: 0644]
jscripts/tiny_mce/themes/simple/skins/o2k7/img/button_bg.png [new file with mode: 0644]
jscripts/tiny_mce/themes/simple/skins/o2k7/ui.css [new file with mode: 0644]
jscripts/tiny_mce/tiny_mce.js [new file with mode: 0644]
jscripts/tiny_mce/tiny_mce_popup.js [new file with mode: 0644]
jscripts/tiny_mce/tiny_mce_src.js [new file with mode: 0644]
jscripts/tiny_mce/utils/editable_selects.js [new file with mode: 0644]
jscripts/tiny_mce/utils/form_utils.js [new file with mode: 0644]
jscripts/tiny_mce/utils/mctabs.js [new file with mode: 0644]
jscripts/tiny_mce/utils/validate.js [new file with mode: 0644]
jscripts/wz_jsgraphics.js [new file with mode: 0644]
license/gpl_licence.txt [new file with mode: 0644]
links/add.php [new file with mode: 0644]
links/index.php [new file with mode: 0644]
login.php [new file with mode: 0644]
logout.php [new file with mode: 0644]
mods/_core/backups/module.php [new file with mode: 0644]
mods/_core/backups/module.xml [new file with mode: 0644]
mods/_core/backups/module_delete.php [new file with mode: 0644]
mods/_core/cats_categories/module.php [new file with mode: 0644]
mods/_core/cats_categories/module.xml [new file with mode: 0644]
mods/_core/content/module.php [new file with mode: 0644]
mods/_core/content/module.xml [new file with mode: 0644]
mods/_core/content/module_backup.php [new file with mode: 0644]
mods/_core/content/module_delete.php [new file with mode: 0644]
mods/_core/content_packaging/module.php [new file with mode: 0644]
mods/_core/content_packaging/module.xml [new file with mode: 0644]
mods/_core/courses/module.php [new file with mode: 0644]
mods/_core/courses/module.xml [new file with mode: 0644]
mods/_core/enrolment/module.php [new file with mode: 0644]
mods/_core/enrolment/module.xml [new file with mode: 0644]
mods/_core/enrolment/module_delete.php [new file with mode: 0644]
mods/_core/file_manager/module.php [new file with mode: 0644]
mods/_core/file_manager/module.xml [new file with mode: 0644]
mods/_core/file_manager/module_backup.php [new file with mode: 0644]
mods/_core/file_manager/module_delete.php [new file with mode: 0644]
mods/_core/glossary/module.php [new file with mode: 0644]
mods/_core/glossary/module.xml [new file with mode: 0644]
mods/_core/glossary/module_backup.php [new file with mode: 0644]
mods/_core/glossary/module_delete.php [new file with mode: 0644]
mods/_core/groups/module.php [new file with mode: 0644]
mods/_core/groups/module.xml [new file with mode: 0644]
mods/_core/groups/module_backup.php [new file with mode: 0644]
mods/_core/groups/module_delete.php [new file with mode: 0644]
mods/_core/languages/module.php [new file with mode: 0644]
mods/_core/languages/module.xml [new file with mode: 0644]
mods/_core/languages/module_cron.php [new file with mode: 0644]
mods/_core/properties/module.php [new file with mode: 0644]
mods/_core/properties/module.xml [new file with mode: 0644]
mods/_core/properties/module_delete.php [new file with mode: 0644]
mods/_core/themes/module.php [new file with mode: 0644]
mods/_core/themes/module.xml [new file with mode: 0644]
mods/_core/users/module.php [new file with mode: 0644]
mods/_core/users/module.xml [new file with mode: 0644]
mods/_standard/announcements/module.php [new file with mode: 0644]
mods/_standard/announcements/module.xml [new file with mode: 0644]
mods/_standard/announcements/module_backup.php [new file with mode: 0644]
mods/_standard/announcements/module_delete.php [new file with mode: 0644]
mods/_standard/assignments/module.php [new file with mode: 0644]
mods/_standard/assignments/module.sql [new file with mode: 0644]
mods/_standard/assignments/module.xml [new file with mode: 0644]
mods/_standard/assignments/module_backup.php [new file with mode: 0644]
mods/_standard/assignments/module_delete.php [new file with mode: 0644]
mods/_standard/assignments/module_groups.php [new file with mode: 0644]
mods/_standard/blogs/module.php [new file with mode: 0644]
mods/_standard/blogs/module.xml [new file with mode: 0644]
mods/_standard/blogs/module_delete.php [new file with mode: 0644]
mods/_standard/blogs/module_groups.php [new file with mode: 0644]
mods/_standard/calendar/module.php [new file with mode: 0644]
mods/_standard/calendar/module.xml [new file with mode: 0644]
mods/_standard/calendar/module_backup.php [new file with mode: 0644]
mods/_standard/calendar/module_delete.php [new file with mode: 0644]
mods/_standard/calendar/module_groups.php [new file with mode: 0644]
mods/_standard/chat/module.php [new file with mode: 0644]
mods/_standard/chat/module.xml [new file with mode: 0644]
mods/_standard/chat/module_delete.php [new file with mode: 0644]
mods/_standard/course_email/module.php [new file with mode: 0644]
mods/_standard/course_email/module.xml [new file with mode: 0644]
mods/_standard/directory/module.php [new file with mode: 0644]
mods/_standard/directory/module.xml [new file with mode: 0644]
mods/_standard/faq/module.php [new file with mode: 0644]
mods/_standard/faq/module.xml [new file with mode: 0644]
mods/_standard/faq/module_backup.php [new file with mode: 0644]
mods/_standard/faq/module_delete.php [new file with mode: 0644]
mods/_standard/file_storage/module.php [new file with mode: 0644]
mods/_standard/file_storage/module.xml [new file with mode: 0644]
mods/_standard/file_storage/module_delete.php [new file with mode: 0644]
mods/_standard/file_storage/module_groups.php [new file with mode: 0644]
mods/_standard/forums/module.php [new file with mode: 0644]
mods/_standard/forums/module.xml [new file with mode: 0644]
mods/_standard/forums/module_delete.php [new file with mode: 0644]
mods/_standard/forums/module_groups.php [new file with mode: 0644]
mods/_standard/google_search/SOAP_Google.php [new file with mode: 0644]
mods/_standard/google_search/module.css [new file with mode: 0644]
mods/_standard/google_search/module.php [new file with mode: 0644]
mods/_standard/google_search/module.xml [new file with mode: 0644]
mods/_standard/google_search/side_menu.inc.php [new file with mode: 0644]
mods/_standard/links/module.php [new file with mode: 0644]
mods/_standard/links/module.xml [new file with mode: 0644]
mods/_standard/links/module_backup.php [new file with mode: 0644]
mods/_standard/links/module_delete.php [new file with mode: 0644]
mods/_standard/links/module_groups.php [new file with mode: 0644]
mods/_standard/patcher/README [new file with mode: 0644]
mods/_standard/patcher/classes/Patch.class.php [new file with mode: 0644]
mods/_standard/patcher/classes/PatchCreator.class.php [new file with mode: 0644]
mods/_standard/patcher/classes/PatchListParser.class.php [new file with mode: 0644]
mods/_standard/patcher/classes/PatchParser.class.php [new file with mode: 0644]
mods/_standard/patcher/include/common.inc.php [new file with mode: 0644]
mods/_standard/patcher/include/json.inc.php [new file with mode: 0644]
mods/_standard/patcher/include/patch_xml_template.inc.php [new file with mode: 0644]
mods/_standard/patcher/index_admin.php [new file with mode: 0644]
mods/_standard/patcher/module.css [new file with mode: 0644]
mods/_standard/patcher/module.php [new file with mode: 0644]
mods/_standard/patcher/module.sql [new file with mode: 0644]
mods/_standard/patcher/module.xml [new file with mode: 0644]
mods/_standard/patcher/module_install.php [new file with mode: 0644]
mods/_standard/patcher/myown_patches.php [new file with mode: 0644]
mods/_standard/patcher/patch_create.php [new file with mode: 0644]
mods/_standard/patcher/patch_creator.php [new file with mode: 0644]
mods/_standard/patcher/patch_delete.php [new file with mode: 0644]
mods/_standard/patcher/patch_edit.php [new file with mode: 0644]
mods/_standard/patcher/patch_edit_interface.tmpl.php [new file with mode: 0644]
mods/_standard/patcher/sample_patch.xml [new file with mode: 0644]
mods/_standard/patcher/sample_patch_list.xml [new file with mode: 0644]
mods/_standard/patcher/xml_special_chars.txt [new file with mode: 0644]
mods/_standard/polls/module.php [new file with mode: 0644]
mods/_standard/polls/module.xml [new file with mode: 0644]
mods/_standard/polls/module_backup.php [new file with mode: 0644]
mods/_standard/polls/module_delete.php [new file with mode: 0644]
mods/_standard/profile_pictures/module.php [new file with mode: 0644]
mods/_standard/profile_pictures/module.xml [new file with mode: 0644]
mods/_standard/reading_list/module.php [new file with mode: 0644]
mods/_standard/reading_list/module.xml [new file with mode: 0644]
mods/_standard/reading_list/module_backup.php [new file with mode: 0644]
mods/_standard/reading_list/module_delete.php [new file with mode: 0644]
mods/_standard/rss_feeds/load_file.php [new file with mode: 0644]
mods/_standard/rss_feeds/module.php [new file with mode: 0644]
mods/_standard/rss_feeds/module.xml [new file with mode: 0644]
mods/_standard/sitemap/module.php [new file with mode: 0644]
mods/_standard/sitemap/module.xml [new file with mode: 0644]
mods/_standard/statistics/module.php [new file with mode: 0644]
mods/_standard/statistics/module.xml [new file with mode: 0644]
mods/_standard/statistics/module_backup.php [new file with mode: 0644]
mods/_standard/statistics/module_delete.php [new file with mode: 0644]
mods/_standard/student_tools/module.php [new file with mode: 0644]
mods/_standard/student_tools/module.xml [new file with mode: 0644]
mods/_standard/tests/module.php [new file with mode: 0644]
mods/_standard/tests/module.xml [new file with mode: 0644]
mods/_standard/tests/module_backup.php [new file with mode: 0644]
mods/_standard/tests/module_delete.php [new file with mode: 0644]
mods/_standard/tests/module_groups.php [new file with mode: 0644]
mods/_standard/tile_search/module.php [new file with mode: 0644]
mods/_standard/tile_search/module.xml [new file with mode: 0644]
mods/_standard/tracker/module.php [new file with mode: 0644]
mods/_standard/tracker/module.xml [new file with mode: 0644]
mods/hello_world/hello_world.jpg [new file with mode: 0644]
mods/hello_world/index.php [new file with mode: 0644]
mods/hello_world/index_admin.php [new file with mode: 0644]
mods/hello_world/index_instructor.php [new file with mode: 0644]
mods/hello_world/index_mystart.php [new file with mode: 0644]
mods/hello_world/index_public.php [new file with mode: 0644]
mods/hello_world/module.css [new file with mode: 0644]
mods/hello_world/module.php [new file with mode: 0644]
mods/hello_world/module.sql [new file with mode: 0644]
mods/hello_world/module.xml [new file with mode: 0644]
mods/hello_world/module_backup.php [new file with mode: 0644]
mods/hello_world/module_cron.php [new file with mode: 0644]
mods/hello_world/module_delete.php [new file with mode: 0644]
mods/hello_world/module_install.php [new file with mode: 0644]
mods/hello_world/side_menu.inc.php [new file with mode: 0644]
mods/index.html [new file with mode: 0644]
mods/scorm_packages/module.php [new file with mode: 0644]
mods/scorm_packages/module.sql [new file with mode: 0644]
mods/scorm_packages/module.xml [new file with mode: 0644]
mods/scorm_packages/module_install.php [new file with mode: 0644]
mods/scorm_packages/possible_module_backup.php [new file with mode: 0644]
my_stats.php [new file with mode: 0644]
overlib.js [new file with mode: 0644]
overlib_mini.js [new file with mode: 0644]
overlib_mini_help.js [new file with mode: 0644]
packages/index.php [new file with mode: 0644]
packages/preferences.php [new file with mode: 0644]
password_reminder.php [new file with mode: 0644]
polls/index.php [new file with mode: 0644]
popuphelp.php [new file with mode: 0644]
profile.php [new file with mode: 0644]
reading_list/add_resource_av.php [new file with mode: 0644]
reading_list/add_resource_book.php [new file with mode: 0644]
reading_list/add_resource_file.php [new file with mode: 0644]
reading_list/add_resource_handout.php [new file with mode: 0644]
reading_list/add_resource_url.php [new file with mode: 0644]
reading_list/delete_reading.php [new file with mode: 0644]
reading_list/delete_resource.php [new file with mode: 0644]
reading_list/display_resource.php [new file with mode: 0644]
reading_list/display_resources.php [new file with mode: 0644]
reading_list/edit_reading_av.php [new file with mode: 0644]
reading_list/edit_reading_book.php [new file with mode: 0644]
reading_list/edit_reading_file.php [new file with mode: 0644]
reading_list/edit_reading_handout.php [new file with mode: 0644]
reading_list/edit_reading_url.php [new file with mode: 0644]
reading_list/index.php [new file with mode: 0644]
reading_list/index_instructor.php [new file with mode: 0644]
reading_list/new_reading_av.php [new file with mode: 0644]
reading_list/new_reading_book.php [new file with mode: 0644]
reading_list/new_reading_file.php [new file with mode: 0644]
reading_list/new_reading_handout.php [new file with mode: 0644]
reading_list/new_reading_url.php [new file with mode: 0644]
reading_list/reading_details.php [new file with mode: 0644]
readme [new file with mode: 0644]
registration.php [new file with mode: 0644]
search.php [new file with mode: 0644]
sha-1factory.js [new file with mode: 0644]
sitemap.php [new file with mode: 0644]
svn.php [new file with mode: 0644]
themes/blumin/content.tmpl.php [new file with mode: 0644]
themes/blumin/forms.css [new file with mode: 0644]
themes/blumin/ie_styles.css [new file with mode: 0644]
themes/blumin/images/arrow_ltr.gif [new file with mode: 0644]
themes/blumin/images/back.gif [new file with mode: 0644]
themes/blumin/images/continue.gif [new file with mode: 0644]
themes/blumin/images/linkOpaque.gif [new file with mode: 0644]
themes/blumin/images/linkTransparent.gif [new file with mode: 0644]
themes/blumin/images/newsitem_icon.gif [new file with mode: 0644]
themes/blumin/images/next.gif [new file with mode: 0644]
themes/blumin/images/previous.gif [new file with mode: 0644]
themes/blumin/images/resume.gif [new file with mode: 0644]
themes/blumin/images/side_arrow.gif [new file with mode: 0644]
themes/blumin/images/sort.gif [new file with mode: 0644]
themes/blumin/images/user-star.gif [new file with mode: 0644]
themes/blumin/images/user.gif [new file with mode: 0644]
themes/blumin/include/box.tmpl.php [new file with mode: 0644]
themes/blumin/include/footer.tmpl.php [new file with mode: 0644]
themes/blumin/include/header.tmpl.php [new file with mode: 0644]
themes/blumin/include/side_menu.tmpl.php [new file with mode: 0644]
themes/blumin/print.css [new file with mode: 0644]
themes/blumin/readme.txt [new file with mode: 0644]
themes/blumin/screenshot.gif [new file with mode: 0644]
themes/blumin/styles.css [new file with mode: 0644]
themes/blumin/theme.cfg.php [new file with mode: 0644]
themes/blumin/theme_info.xml [new file with mode: 0644]
themes/default/confirmmessage.tmpl.php [new file with mode: 0644]
themes/default/content.tmpl.php [new file with mode: 0644]
themes/default/errormessage.tmpl.php [new file with mode: 0644]
themes/default/feedbackmessage.tmpl.php [new file with mode: 0644]
themes/default/forms.css [new file with mode: 0644]
themes/default/ie_styles.css [new file with mode: 0644]
themes/default/images/Thumbs.db [new file with mode: 0644]
themes/default/images/arrow_ltr.gif [new file with mode: 0644]
themes/default/images/back.gif [new file with mode: 0644]
themes/default/images/continue.gif [new file with mode: 0644]
themes/default/images/guide.gif [new file with mode: 0644]
themes/default/images/linkOpaque.gif [new file with mode: 0644]
themes/default/images/linkTransparent.gif [new file with mode: 0644]
themes/default/images/newsitem_icon.gif [new file with mode: 0644]
themes/default/images/next.gif [new file with mode: 0644]
themes/default/images/pencil_bottom.gif [new file with mode: 0644]
themes/default/images/pencil_top.gif [new file with mode: 0644]
themes/default/images/pencils.gif [new file with mode: 0644]
themes/default/images/previous.gif [new file with mode: 0644]
themes/default/images/resume.gif [new file with mode: 0644]
themes/default/images/side_arrow.gif [new file with mode: 0644]
themes/default/images/sort.gif [new file with mode: 0644]
themes/default/images/tl_corner.gif [new file with mode: 0644]
themes/default/images/top.gif [new file with mode: 0644]
themes/default/images/user-star.gif [new file with mode: 0644]
themes/default/images/user.gif [new file with mode: 0644]
themes/default/include/box.tmpl.php [new file with mode: 0644]
themes/default/include/fm_footer.tmpl.php [new file with mode: 0644]
themes/default/include/fm_header.tmpl.php [new file with mode: 0644]
themes/default/include/footer.tmpl.php [new file with mode: 0644]
themes/default/include/forms.css [new file with mode: 0644]
themes/default/include/header.tmpl.php [new file with mode: 0644]
themes/default/include/side_menu.tmpl.php [new file with mode: 0644]
themes/default/index.tmpl.php [new file with mode: 0644]
themes/default/infomessage.tmpl.php [new file with mode: 0644]
themes/default/login.tmpl.php [new file with mode: 0644]
themes/default/password_change.tmpl.php [new file with mode: 0644]
themes/default/password_reminder.tmpl.php [new file with mode: 0644]
themes/default/password_reminder_feedback.tmpl.php [new file with mode: 0644]
themes/default/print.css [new file with mode: 0644]
themes/default/profile.tmpl.php [new file with mode: 0644]
themes/default/readme.txt [new file with mode: 0644]
themes/default/registration.tmpl.php [new file with mode: 0644]
themes/default/rtl.css [new file with mode: 0644]
themes/default/screenshot.gif [new file with mode: 0644]
themes/default/styles.css [new file with mode: 0644]
themes/default/test_questions/footer.tmpl.php [new file with mode: 0644]
themes/default/test_questions/header.tmpl.php [new file with mode: 0644]
themes/default/test_questions/likert.tmpl.php [new file with mode: 0644]
themes/default/test_questions/likert_qti_2p1.tmpl.php [new file with mode: 0644]
themes/default/test_questions/likert_result.tmpl.php [new file with mode: 0644]
themes/default/test_questions/likert_stats.tmpl.php [new file with mode: 0644]
themes/default/test_questions/long.tmpl.php [new file with mode: 0644]
themes/default/test_questions/long_qti_2p1.tmpl.php [new file with mode: 0644]
themes/default/test_questions/long_result.tmpl.php [new file with mode: 0644]
themes/default/test_questions/long_stats.tmpl.php [new file with mode: 0644]
themes/default/test_questions/manifest_qti_2p1.tmpl.php [new file with mode: 0644]
themes/default/test_questions/matching.tmpl.php [new file with mode: 0644]
themes/default/test_questions/matching_qti_2p1.tmpl.php [new file with mode: 0644]
themes/default/test_questions/matching_result.tmpl.php [new file with mode: 0644]
themes/default/test_questions/matching_stats.tmpl.php [new file with mode: 0644]
themes/default/test_questions/matchingdd.tmpl.php [new file with mode: 0644]
themes/default/test_questions/matchingdd_qti_2p1.tmpl.php [new file with mode: 0644]
themes/default/test_questions/matchingdd_result.tmpl.php [new file with mode: 0644]
themes/default/test_questions/matchingdd_stats.tmpl.php [new file with mode: 0644]
themes/default/test_questions/multianswer.tmpl.php [new file with mode: 0644]
themes/default/test_questions/multianswer_qti_2p1.tmpl.php [new file with mode: 0644]
themes/default/test_questions/multianswer_result.tmpl.php [new file with mode: 0644]
themes/default/test_questions/multianswer_stats.tmpl.php [new file with mode: 0644]
themes/default/test_questions/multichoice.tmpl.php [new file with mode: 0644]
themes/default/test_questions/multichoice_qti_2p1.tmpl.php [new file with mode: 0644]
themes/default/test_questions/multichoice_result.tmpl.php [new file with mode: 0644]
themes/default/test_questions/multichoice_stats.tmpl.php [new file with mode: 0644]
themes/default/test_questions/ordering.tmpl.php [new file with mode: 0644]
themes/default/test_questions/ordering_qti_2p1.tmpl.php [new file with mode: 0644]
themes/default/test_questions/ordering_result.tmpl.php [new file with mode: 0644]
themes/default/test_questions/ordering_stats.tmpl.php [new file with mode: 0644]
themes/default/test_questions/truefalse.tmpl.php [new file with mode: 0644]
themes/default/test_questions/truefalse_qti_2p1.tmpl.php [new file with mode: 0644]
themes/default/test_questions/truefalse_result.tmpl.php [new file with mode: 0644]
themes/default/test_questions/truefalse_stats.tmpl.php [new file with mode: 0644]
themes/default/theme.cfg.php [new file with mode: 0644]
themes/default/theme_info.xml [new file with mode: 0644]
themes/default/users/browse.tmpl.php [new file with mode: 0644]
themes/default/users/email_change.tmpl.php [new file with mode: 0644]
themes/default/users/index.tmpl.php [new file with mode: 0644]
themes/default/users/password_change.tmpl.php [new file with mode: 0644]
themes/default/users/preferences.tmpl.php [new file with mode: 0644]
themes/default/users/profile.tmpl.php [new file with mode: 0644]
themes/default/warningmessage.tmpl.php [new file with mode: 0644]
themes/default15/confirmmessage.tmpl.php [new file with mode: 0644]
themes/default15/content.tmpl.php [new file with mode: 0644]
themes/default15/errormessage.tmpl.php [new file with mode: 0644]
themes/default15/feedbackmessage.tmpl.php [new file with mode: 0644]
themes/default15/forms.css [new file with mode: 0644]
themes/default15/ie_styles.css [new file with mode: 0644]
themes/default15/images/arrow_ltr.gif [new file with mode: 0644]
themes/default15/images/back.gif [new file with mode: 0644]
themes/default15/images/error-large.gif [new file with mode: 0644]
themes/default15/images/guide.gif [new file with mode: 0644]
themes/default15/images/instructor.gif [new file with mode: 0644]
themes/default15/images/next.gif [new file with mode: 0644]
themes/default15/images/pen.gif [new file with mode: 0644]
themes/default15/images/pen2.gif [new file with mode: 0644]
themes/default15/images/pencils.jpg [new file with mode: 0644]
themes/default15/images/previous.gif [new file with mode: 0644]
themes/default15/images/resume.gif [new file with mode: 0644]
themes/default15/images/side_arrow.gif [new file with mode: 0644]
themes/default15/images/sort.gif [new file with mode: 0644]
themes/default15/images/user-star.gif [new file with mode: 0644]
themes/default15/images/user.gif [new file with mode: 0644]
themes/default15/include/box.tmpl.php [new file with mode: 0644]
themes/default15/include/fm_footer.tmpl.php [new file with mode: 0644]
themes/default15/include/fm_header.tmpl.php [new file with mode: 0644]
themes/default15/include/footer.tmpl.php [new file with mode: 0644]
themes/default15/include/header.tmpl.php [new file with mode: 0644]
themes/default15/index.tmpl.php [new file with mode: 0644]
themes/default15/infomessage.tmpl.php [new file with mode: 0644]
themes/default15/password_change.tmpl.php [new file with mode: 0644]
themes/default15/password_reminder_feedback.tmpl.php [new file with mode: 0644]
themes/default15/print.css [new file with mode: 0644]
themes/default15/profile.tmpl.php [new file with mode: 0644]
themes/default15/readme.txt [new file with mode: 0644]
themes/default15/rtl.css [new file with mode: 0644]
themes/default15/screenshot.gif [new file with mode: 0644]
themes/default15/styles.css [new file with mode: 0644]
themes/default15/theme.cfg.php [new file with mode: 0644]
themes/default15/warningmessage.tmpl.php [new file with mode: 0644]
themes/default_classic/ie_styles.css [new file with mode: 0644]
themes/default_classic/images/guide.gif [new file with mode: 0644]
themes/default_classic/images/user-star.gif [new file with mode: 0644]
themes/default_classic/include/footer.tmpl.php [new file with mode: 0644]
themes/default_classic/include/header.tmpl.php [new file with mode: 0644]
themes/default_classic/print.css [new file with mode: 0644]
themes/default_classic/rtl.css [new file with mode: 0644]
themes/default_classic/screenshot.gif [new file with mode: 0644]
themes/default_classic/styles.css [new file with mode: 0644]
themes/default_classic/theme.cfg.php [new file with mode: 0644]
themes/fluid/at_fluid.css [new file with mode: 0644]
themes/fluid/fluid.zip [new file with mode: 0644]
themes/fluid/forms.css [new file with mode: 0644]
themes/fluid/ie_styles.css [new file with mode: 0644]
themes/fluid/images/arrow_left.png [new file with mode: 0644]
themes/fluid/images/continue.gif [new file with mode: 0644]
themes/fluid/images/layers.png [new file with mode: 0755]
themes/fluid/images/next.gif [new file with mode: 0644]
themes/fluid/images/previous.gif [new file with mode: 0644]
themes/fluid/images/resume.gif [new file with mode: 0644]
themes/fluid/images/top.gif [new file with mode: 0644]
themes/fluid/include/box.tmpl.php [new file with mode: 0644]
themes/fluid/include/footer.tmpl.php [new file with mode: 0644]
themes/fluid/include/forms.css [new file with mode: 0644]
themes/fluid/include/header.tmpl.php [new file with mode: 0644]
themes/fluid/include/side_menu.tmpl.php [new file with mode: 0644]
themes/fluid/index.tmpl.php [new file with mode: 0644]
themes/fluid/print.css [new file with mode: 0644]
themes/fluid/save_state.php [new file with mode: 0644]
themes/fluid/screenshot.gif [new file with mode: 0644]
themes/fluid/styles.css [new file with mode: 0644]
themes/fluid/theme.cfg.php [new file with mode: 0644]
themes/fluid/theme_info.xml [new file with mode: 0644]
themes/greenmin/content.tmpl.php [new file with mode: 0644]
themes/greenmin/forms.css [new file with mode: 0644]
themes/greenmin/ie_styles.css [new file with mode: 0644]
themes/greenmin/images/Thumbs.db [new file with mode: 0644]
themes/greenmin/images/arrow_ltr.gif [new file with mode: 0644]
themes/greenmin/images/back.gif [new file with mode: 0644]
themes/greenmin/images/continue.gif [new file with mode: 0644]
themes/greenmin/images/linkOpaque.gif [new file with mode: 0644]
themes/greenmin/images/linkTransparent.gif [new file with mode: 0644]
themes/greenmin/images/newsitem_icon.gif [new file with mode: 0644]
themes/greenmin/images/next.gif [new file with mode: 0644]
themes/greenmin/images/previous.gif [new file with mode: 0644]
themes/greenmin/images/resume.gif [new file with mode: 0644]
themes/greenmin/images/side_arrow.gif [new file with mode: 0644]
themes/greenmin/images/sort.gif [new file with mode: 0644]
themes/greenmin/images/user-star.gif [new file with mode: 0644]
themes/greenmin/images/user.gif [new file with mode: 0644]
themes/greenmin/include/box.tmpl.php [new file with mode: 0644]
themes/greenmin/include/footer.tmpl.php [new file with mode: 0644]
themes/greenmin/include/header.tmpl.php [new file with mode: 0644]
themes/greenmin/include/side_menu.tmpl.php [new file with mode: 0644]
themes/greenmin/print.css [new file with mode: 0644]
themes/greenmin/readme.txt [new file with mode: 0644]
themes/greenmin/screenshot.gif [new file with mode: 0644]
themes/greenmin/styles.css [new file with mode: 0644]
themes/greenmin/theme.cfg.php [new file with mode: 0644]
themes/greenmin/theme_info.xml [new file with mode: 0644]
themes/themes_readme.txt [new file with mode: 0644]
tile.php [new file with mode: 0644]
tools/access.php [new file with mode: 0644]
tools/backup/create.php [new file with mode: 0644]
tools/backup/delete.php [new file with mode: 0644]
tools/backup/edit.php [new file with mode: 0644]
tools/backup/index.php [new file with mode: 0644]
tools/backup/restore.php [new file with mode: 0644]
tools/backup/upload.php [new file with mode: 0644]
tools/chat/delete_transcript.php [new file with mode: 0644]
tools/chat/index.php [new file with mode: 0644]
tools/chat/start_transcript.php [new file with mode: 0644]
tools/chat/view_transcript.php [new file with mode: 0644]
tools/content/index.php [new file with mode: 0644]
tools/course_email.php [new file with mode: 0644]
tools/course_properties.php [new file with mode: 0644]
tools/course_stats.php [new file with mode: 0644]
tools/course_tracker.php [new file with mode: 0644]
tools/delete_course.php [new file with mode: 0644]
tools/edit_styles.php [new file with mode: 0644]
tools/enrollment/create_course_list.php [new file with mode: 0644]
tools/enrollment/enroll_edit.php [new file with mode: 0644]
tools/enrollment/export_course_list.php [new file with mode: 0644]
tools/enrollment/import_course_list.php [new file with mode: 0644]
tools/enrollment/index.php [new file with mode: 0644]
tools/enrollment/privileges.php [new file with mode: 0644]
tools/enrollment/verify_list.php [new file with mode: 0644]
tools/filemanager/delete.php [new file with mode: 0644]
tools/filemanager/edit.php [new file with mode: 0644]
tools/filemanager/index.php [new file with mode: 0644]
tools/filemanager/move.php [new file with mode: 0644]
tools/filemanager/new.php [new file with mode: 0644]
tools/filemanager/preview.php [new file with mode: 0644]
tools/filemanager/preview_top.php [new file with mode: 0644]
tools/filemanager/rename.php [new file with mode: 0644]
tools/filemanager/top.php [new file with mode: 0644]
tools/filemanager/upload.php [new file with mode: 0644]
tools/filemanager/zip.php [new file with mode: 0644]
tools/forums/index.php [new file with mode: 0644]
tools/glossary/add.php [new file with mode: 0644]
tools/glossary/delete.php [new file with mode: 0644]
tools/glossary/edit.php [new file with mode: 0644]
tools/glossary/index.php [new file with mode: 0644]
tools/groups/create.php [new file with mode: 0644]
tools/groups/create_automatic.php [new file with mode: 0644]
tools/groups/create_manual.php [new file with mode: 0644]
tools/groups/delete_group.php [new file with mode: 0644]
tools/groups/delete_type.php [new file with mode: 0644]
tools/groups/edit_group.php [new file with mode: 0644]
tools/groups/edit_type.php [new file with mode: 0644]
tools/groups/index.php [new file with mode: 0644]
tools/groups/members.php [new file with mode: 0644]
tools/ims/ims_export.php [new file with mode: 0644]
tools/ims/ims_import.php [new file with mode: 0644]
tools/ims/index.php [new file with mode: 0644]
tools/index.php [new file with mode: 0644]
tools/links/add.php [new file with mode: 0644]
tools/links/categories.php [new file with mode: 0644]
tools/links/categories_create.php [new file with mode: 0644]
tools/links/categories_delete.php [new file with mode: 0644]
tools/links/categories_edit.php [new file with mode: 0644]
tools/links/delete.php [new file with mode: 0644]
tools/links/edit.php [new file with mode: 0644]
tools/links/index.php [new file with mode: 0644]
tools/modules.php [new file with mode: 0644]
tools/my_tests.php [new file with mode: 0644]
tools/news/index.php [new file with mode: 0644]
tools/packages/delete.php [new file with mode: 0644]
tools/packages/import.php [new file with mode: 0644]
tools/packages/index.php [new file with mode: 0644]
tools/packages/lib.inc.php [new file with mode: 0644]
tools/packages/scorm-1.2/images/active.png [new file with mode: 0644]
tools/packages/scorm-1.2/images/asset.png [new file with mode: 0644]
tools/packages/scorm-1.2/images/browsed.png [new file with mode: 0644]
tools/packages/scorm-1.2/images/busy.png [new file with mode: 0644]
tools/packages/scorm-1.2/images/completed.png [new file with mode: 0644]
tools/packages/scorm-1.2/images/failed.png [new file with mode: 0644]
tools/packages/scorm-1.2/images/incomplete.png [new file with mode: 0644]
tools/packages/scorm-1.2/images/not-attempted.png [new file with mode: 0644]
tools/packages/scorm-1.2/images/passed.png [new file with mode: 0644]
tools/packages/scorm-1.2/import.php [new file with mode: 0644]
tools/packages/scorm-1.2/java/ATutorApiAdapterApplet.jar [new file with mode: 0644]
tools/packages/scorm-1.2/java/ATutorApiAdapterApplet.java [new file with mode: 0644]
tools/packages/scorm-1.2/java/PfPLMS-API-adapter-core.jar [new file with mode: 0644]
tools/packages/scorm-1.2/java/gnu.jar [new file with mode: 0644]
tools/packages/scorm-1.2/learner_view.php [new file with mode: 0644]
tools/packages/scorm-1.2/lib.inc.php [new file with mode: 0644]
tools/packages/scorm-1.2/read.php [new file with mode: 0644]
tools/packages/scorm-1.2/settings.php [new file with mode: 0644]
tools/packages/scorm-1.2/view.inc.php [new file with mode: 0644]
tools/packages/scorm-1.2/view.php [new file with mode: 0644]
tools/packages/scorm-1.2/write.php [new file with mode: 0644]
tools/packages/settings.php [new file with mode: 0644]
tools/polls/add.php [new file with mode: 0644]
tools/polls/delete.php [new file with mode: 0644]
tools/polls/edit.php [new file with mode: 0644]
tools/polls/index.php [new file with mode: 0644]
tools/prog.php [new file with mode: 0644]
tools/side_menu.php [new file with mode: 0644]
tools/take_test.php [new file with mode: 0644]
tools/take_test_q.php [new file with mode: 0644]
tools/test_intro.php [new file with mode: 0644]
tools/tests/add_test_questions.php [new file with mode: 0644]
tools/tests/add_test_questions_confirm.php [new file with mode: 0644]
tools/tests/create_question_likert.php [new file with mode: 0644]
tools/tests/create_question_long.php [new file with mode: 0644]
tools/tests/create_question_matching.php [new file with mode: 0644]
tools/tests/create_question_matchingdd.php [new file with mode: 0644]
tools/tests/create_question_multi.php [new file with mode: 0644]
tools/tests/create_question_multianswer.php [new file with mode: 0644]
tools/tests/create_question_multichoice.php [new file with mode: 0644]
tools/tests/create_question_ordering.php [new file with mode: 0644]
tools/tests/create_question_tf.php [new file with mode: 0644]
tools/tests/create_question_truefalse.php [new file with mode: 0644]
tools/tests/create_test.php [new file with mode: 0644]
tools/tests/dd.php [new file with mode: 0644]
tools/tests/delete_question.php [new file with mode: 0644]
tools/tests/delete_result.php [new file with mode: 0644]
tools/tests/delete_test.php [new file with mode: 0644]
tools/tests/edit_question_likert.php [new file with mode: 0644]
tools/tests/edit_question_long.php [new file with mode: 0644]
tools/tests/edit_question_matching.php [new file with mode: 0644]
tools/tests/edit_question_matchingdd.php [new file with mode: 0644]
tools/tests/edit_question_multi.php [new file with mode: 0644]
tools/tests/edit_question_multianswer.php [new file with mode: 0644]
tools/tests/edit_question_multichoice.php [new file with mode: 0644]
tools/tests/edit_question_ordering.php [new file with mode: 0644]
tools/tests/edit_question_tf.php [new file with mode: 0644]
tools/tests/edit_question_truefalse.php [new file with mode: 0644]
tools/tests/edit_test.php [new file with mode: 0644]
tools/tests/form_editor.php [new file with mode: 0644]
tools/tests/index.php [new file with mode: 0644]
tools/tests/preview.php [new file with mode: 0644]
tools/tests/preview_question.php [new file with mode: 0644]
tools/tests/question_cats.php [new file with mode: 0644]
tools/tests/question_cats_delete.php [new file with mode: 0644]
tools/tests/question_cats_manage.php [new file with mode: 0644]
tools/tests/question_db.php [new file with mode: 0644]
tools/tests/question_remove.php [new file with mode: 0644]
tools/tests/questions.php [new file with mode: 0644]
tools/tests/results.php [new file with mode: 0644]
tools/tests/results_all.php [new file with mode: 0644]
tools/tests/results_all_csv.php [new file with mode: 0644]
tools/tests/results_all_quest.php [new file with mode: 0644]
tools/tests/results_quest_long.php [new file with mode: 0644]
tools/tests/view_results.php [new file with mode: 0644]
tools/tile/import.php [new file with mode: 0644]
tools/tile/index.php [new file with mode: 0644]
tools/tracker.php [new file with mode: 0644]
tools/tracker/export.php [new file with mode: 0644]
tools/tracker/index.php [new file with mode: 0644]
tools/tracker/page_student_stats.php [new file with mode: 0644]
tools/tracker/reset.php [new file with mode: 0644]
tools/tracker/student_usage.php [new file with mode: 0644]
tools/view_results.php [new file with mode: 0644]
users/browse.php [new file with mode: 0644]
users/contact_instructor.php [new file with mode: 0644]
users/course_stats.php [new file with mode: 0644]
users/create_course.php [new file with mode: 0644]
users/email_change.php [new file with mode: 0644]
users/index.php [new file with mode: 0644]
users/password_change.php [new file with mode: 0644]
users/preferences.php [new file with mode: 0644]
users/private_enroll.php [new file with mode: 0644]
users/profile.php [new file with mode: 0644]
users/profile_picture.php [new file with mode: 0644]
users/prog.php [new file with mode: 0644]
users/remove_course.php [new file with mode: 0644]
users/request_instructor.php [new file with mode: 0644]
users/search.php [new file with mode: 0644]

diff --git a/.htaccess b/.htaccess
new file mode 100644 (file)
index 0000000..d5abcdb
--- /dev/null
+++ b/.htaccess
@@ -0,0 +1,101 @@
+# BEGIN ATutor
+<IfModule mod_rewrite.c>
+RewriteEngine On
+
+#Forums rules
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule (.*)/forum/([0-9]+)/([0-9]+)/?$ go.php/$1/forum/view.php/fid/$2/pid/$3/ [L]
+
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule (.*)/forum/([0-9]+)/([0-9]+)/(([0-9]+)\.html)$ go.php/$1/forum/view.php/fid/$2/pid/$3/page/$4 [L]
+
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule (.*)/forum/([0-9]+)/?$ go.php/$1/forum/index.php/fid/$2/ [L]
+
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule (.*)/forum/([0-9]+)/([0-9+])\.html$ go.php/$1/forum/index.php/fid/$2/page/$3 [L]
+
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule (.*)/forum/?$ go.php/$1/forum/list.php [L]
+
+#Content rule
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule (.*)/content/([0-9]+)/?$ go.php/$1/content.php/cid/$2 [L]
+
+#File storage rule
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule (.*)/file_storage/?$ go.php/$1/file_storage/index.php [L]
+
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule (.*)/file_storage/([0-9]+)/([0-9]+)/?$ go.php/$1/file_storage/index.php/ot/$2/oid/$3/ [L]
+
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule (.*)/file_storage/([0-9]+)/([0-9]+)/([0-9]+)/?$ go.php/$1/file_storage/index.php/ot/$2/oid/$3/folder/$4/ [L]
+
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule (.*)/file_storage/comments/([0-9]+)/([0-9]+)/([0-9]+)/?$ go.php/$1/file_storage/comments.php/ot/$2/oid/$3/id/$4/ [L]
+
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule (.*)/file_storage/revisions/([0-9]+)/([0-9]+)/([0-9]+)/?$ go.php/$1/file_storage/revisions.php/ot/$2/oid/$3/id/$4/ [L]
+
+#Tests and Survey
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule (.*)/tests_surveys/([0-9]+)/?$ go.php/$1/tools/test_intro.php/tid/$2/ [L]
+
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule (.*)/tests_surveys/([0-9]+)/(begin|cancel)/?$ go.php/$1/tools/test_intro.php/tid/$2/action/$3/ [L]
+
+#Glossary
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule (.*)/glossary/?$ go.php/$1/glossary/index.php [L]
+
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule (.*)/glossary/(.*)/?$ go.php/$1/glossary/index.php/p/$2/ [L]
+
+#Handles the removal of index.php
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule ^([^/^.]+)/?$ go.php/$1/index.php [L]
+
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule ^([^/^.]+)/(([^/^.]+)|((mods|tools)/([^/^.]+)))/$ go.php/$1/$2/index.php [L]
+
+#Handles the removal of .php
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule ^([^/]+)/([^/^.]+)/?$ go.php/$1/$2.php [L]
+
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule ^([^/]+)/(((mods)/[^/^.]+)|([^/^.]+))/([^/^.]+)/?$ go.php/$1/$2/$6.php [L]
+
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule ^([^/]+)/tools/tests/questions/tid/([0-9]+)/?$ go.php/$1/tools/tests/questions.php/tid/$2/ [L]
+
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule ^([^/]+)/(((mods)/[^/^.]+)|([^/^.]+))/([^/^.]+)/([^\.]+)$ go.php/$1/$2/$6.php/$7 [L]
+
+#Default rule
+RewriteCond     %{REQUEST_FILENAME}     !-f
+RewriteCond     %{REQUEST_FILENAME}     !-d
+RewriteRule (.*) go.php/$1 [L]
+</IfModule>
+# END ATutor
diff --git a/404.php b/404.php
new file mode 100644 (file)
index 0000000..8feb648
--- /dev/null
+++ b/404.php
@@ -0,0 +1,25 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', 'include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+require (AT_INCLUDE_PATH.'header.inc.php');
+
+$_info = array('404_BLURB', htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES));
+$msg->printInfos($_info);
+
+$msg->printAll();
+
+require (AT_INCLUDE_PATH.'footer.inc.php'); 
+?>
\ No newline at end of file
diff --git a/about.php b/about.php
new file mode 100644 (file)
index 0000000..ac4efd6
--- /dev/null
+++ b/about.php
@@ -0,0 +1,26 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+$_user_location        = 'public';
+
+define('AT_INCLUDE_PATH', 'include/');
+require(AT_INCLUDE_PATH.'/vitals.inc.php');
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<p><?php echo _AT('atutor_is');  ?></p>
+
+<?php echo _AT('atutor_links');  ?>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/acl.php b/acl.php
new file mode 100644 (file)
index 0000000..f7909e4
--- /dev/null
+++ b/acl.php
@@ -0,0 +1,16 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id: login.php 6575 2006-08-22 18:12:30Z joel $
+
+require('bounce.php');
+?>
\ No newline at end of file
diff --git a/admin/admin_delete.php b/admin/admin_delete.php
new file mode 100644 (file)
index 0000000..f6fb30d
--- /dev/null
@@ -0,0 +1,159 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+/* linked from admin/users.php                                  */
+/* deletes a user from the system.                              */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_USERS);
+
+function delete_user($id) {
+       global $db, $msg;
+
+       //make sure not instructor of a course
+       $sql    = "SELECT course_id FROM ".TABLE_PREFIX."courses WHERE member_id=$id";
+       $result = mysql_query($sql, $db);
+       if (($row = mysql_fetch_assoc($result))) {
+               /*$msg->addError('NODELETE_USER');
+               header('Location: '.AT_BASE_HREF.'users.php');
+               exit;*/
+               return;
+       }
+
+       $sql    = "DELETE FROM ".TABLE_PREFIX."course_enrollment WHERE member_id=$id";
+       mysql_query($sql, $db);
+       write_to_log(AT_ADMIN_LOG_DELETE, 'course_enrollment', mysql_affected_rows($db), $sql);
+
+       $sql    = "DELETE FROM ".TABLE_PREFIX."forums_accessed WHERE member_id=$id";
+       mysql_query($sql, $db);
+       write_to_log(AT_ADMIN_LOG_DELETE, 'forums_accessed', mysql_affected_rows($db), $sql);
+
+       $sql    = "DELETE FROM ".TABLE_PREFIX."forums_subscriptions WHERE member_id=$id";
+       mysql_query($sql, $db);
+       write_to_log(AT_ADMIN_LOG_DELETE, 'forums_subscriptions', mysql_affected_rows($db), $sql);
+
+
+       /****/
+       /* delete forum threads block: */
+               /* delete the thread replies: */
+               $sql    = "SELECT COUNT(*) AS cnt, parent_id, forum_id FROM ".TABLE_PREFIX."forums_threads WHERE member_id=$id AND parent_id<>0 GROUP BY parent_id";
+               $result = mysql_query($sql, $db);
+               while ($row = mysql_fetch_assoc($result)) {
+                       /* update the forum posts counter */
+                       $sql = "UPDATE ".TABLE_PREFIX."forums SET num_posts=num_posts - $row[cnt], last_post=last_post WHERE forum_id=$row[forum_id]";
+                       mysql_query($sql, $db);
+                       write_to_log(AT_ADMIN_LOG_UPDATE, 'forums', mysql_affected_rows($db), $sql);
+                       
+                       /* update the topics reply counter */
+                       $sql = "UPDATE ".TABLE_PREFIX."forums_threads SET num_comments=num_comments-$row[cnt], last_comment=last_comment, date=date WHERE post_id=$row[parent_id]";
+                       mysql_query($sql, $db);
+                       write_to_log(AT_ADMIN_LOG_UPDATE, 'forums_threads', mysql_affected_rows($db), $sql);
+               }
+
+               /* delete threads this member started: */
+               $sql    = "SELECT post_id, forum_id, num_comments FROM ".TABLE_PREFIX."forums_threads WHERE member_id=$id AND parent_id=0";
+               $result = mysql_query($sql, $db);
+               while ($row = mysql_fetch_assoc($result)) {
+                       /* update the forum posts and topics counters */
+                       $num_posts = $row['num_comments'] + 1;
+                       $sql = "UPDATE ".TABLE_PREFIX."forums SET num_topics=num_topics-1, num_posts=num_posts - $num_posts, last_post=last_post WHERE forum_id=$row[forum_id]";
+                       mysql_query($sql, $db);
+                       write_to_log(AT_ADMIN_LOG_UPDATE, 'forums', mysql_affected_rows($db), $sql);
+
+                       /* delete the replies */
+                       $sql = "DELETE FROM ".TABLE_PREFIX."forums_threads WHERE parent_id=$row[post_id]";
+                       mysql_query($sql, $db);
+                       write_to_log(AT_ADMIN_LOG_DELETE, 'forums_threads', mysql_affected_rows($db), $sql);
+               }
+               /* delete the actual threads */
+               $sql    = "DELETE FROM ".TABLE_PREFIX."forums_threads WHERE member_id=$id";
+               mysql_query($sql, $db);
+               write_to_log(AT_ADMIN_LOG_DELETE, 'forums_threads', mysql_affected_rows($db), $sql);
+
+       /* end delete forum threads block. */
+       /****/
+
+       $sql    = "DELETE FROM ".TABLE_PREFIX."instructor_approvals WHERE member_id=$id";
+       mysql_query($sql, $db);
+       write_to_log(AT_ADMIN_LOG_DELETE, 'instructor_approvals', mysql_affected_rows($db), $sql);
+
+       $sql    = "DELETE FROM ".TABLE_PREFIX."messages WHERE from_member_id=$id OR to_member_id=$id";
+       mysql_query($sql, $db);
+       write_to_log(AT_ADMIN_LOG_DELETE, 'messages', mysql_affected_rows($db), $sql);
+
+       $sql    = "DELETE FROM ".TABLE_PREFIX."polls_members WHERE member_id=$id";
+       mysql_query($sql, $db);
+       write_to_log(AT_ADMIN_LOG_DELETE, 'polls_members', mysql_affected_rows($db), $sql);
+
+       $sql    = "DELETE FROM ".TABLE_PREFIX."tests_answers WHERE member_id=$id";
+       mysql_query($sql, $db);
+       write_to_log(AT_ADMIN_LOG_DELETE, 'tests_answers', mysql_affected_rows($db), $sql);
+
+       $sql    = "DELETE FROM ".TABLE_PREFIX."tests_results WHERE member_id=$id";
+       mysql_query($sql, $db);
+       write_to_log(AT_ADMIN_LOG_DELETE, 'tests_results', mysql_affected_rows($db), $sql);
+
+       $sql    = "DELETE FROM ".TABLE_PREFIX."users_online WHERE member_id=$id";
+       mysql_query($sql, $db);
+       write_to_log(AT_ADMIN_LOG_DELETE, 'users_online', mysql_affected_rows($db), $sql);
+
+       $sql    = "DELETE FROM ".TABLE_PREFIX."members WHERE member_id=$id";
+       mysql_query($sql, $db);
+       write_to_log(AT_ADMIN_LOG_DELETE, 'members', mysql_affected_rows($db), $sql);
+
+       $sql    = "DELETE FROM ".TABLE_PREFIX."member_track WHERE member_id=$id";
+       mysql_query($sql, $db);
+       write_to_log(AT_ADMIN_LOG_DELETE, 'member_track', mysql_affected_rows($db), $sql);
+
+       return;
+}
+
+$ids = explode(',', $_REQUEST['id']);
+
+if (isset($_POST['submit_yes'])) {
+       
+       foreach($ids as $id) {
+               delete_user(intval($id));
+       }
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       if (isset($_POST['ml']) && $_REQUEST['ml']) {
+               header('Location: '.AT_BASE_HREF.'admin/master_list.php');
+       } else {
+               header('Location: '.AT_BASE_HREF.'admin/users.php');
+       }
+       exit;
+} else if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       if (isset($_POST['ml']) && $_REQUEST['ml']) {
+               header('Location: '.AT_BASE_HREF.'admin/master_list.php');
+       } else {
+               header('Location: '.AT_BASE_HREF.'admin/users.php');
+       }
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+$names = get_login($ids);
+$names_html = '<ul>'.html_get_list($names).'</ul>';
+$hidden_vars['id'] =  implode(',', array_keys($names));
+$hidden_vars['ml'] = intval($_REQUEST['ml']);
+
+$confirm = array('DELETE_USER', $names_html);
+$msg->addConfirm($confirm, $hidden_vars);
+$msg->printConfirm();
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+
+?>
\ No newline at end of file
diff --git a/admin/admin_deny.php b/admin/admin_deny.php
new file mode 100644 (file)
index 0000000..df2c810
--- /dev/null
@@ -0,0 +1,151 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_USERS);
+
+//check valid requester id
+$request_id = intval($_REQUEST['id']);
+$sql   = "SELECT * FROM ".TABLE_PREFIX."members WHERE member_id=".$request_id;
+$result        = mysql_query($sql, $db);
+if (!($row = mysql_fetch_array($result))) {
+       require(AT_INCLUDE_PATH.'header.inc.php'); 
+       echo _AT('no_user_found');
+       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+       exit;
+}
+
+// message options
+$msg_options = array (_AT('leave_blank'),
+                       _AT('instructor_request_denymsg1'),
+                       _AT('instructor_request_denymsg2'),
+                       _AT('instructor_request_denymsg3'),
+                       _AT('instructor_request_denymsg4'),
+                       _AT('other'));
+$other_option = count($msg_options)-1;
+
+if (isset($_POST['submit'])) {
+       $sql = 'DELETE FROM '.TABLE_PREFIX.'instructor_approvals WHERE member_id='.$request_id;
+       $result = mysql_query($sql, $db);
+       write_to_log(AT_ADMIN_LOG_DELETE, 'instructor_approvals', mysql_affected_rows($db), $sql);
+
+       $msg->addFeedback('PROFILE_UPDATED_ADMIN');
+
+       /* notify the users that they have been denied: */
+       $sql   = "SELECT email, first_name, last_name FROM ".TABLE_PREFIX."members WHERE member_id=".$_POST['id'];
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_array($result)) {
+               $to_email = $row['email'];
+
+               $message = _AT('instructor_request_deny', AT_BASE_HREF)." \n";
+               if ($_POST['msg_option'] == $other_option) {
+                       $message.=addslashes($_POST['other_msg']);
+               } else if ($_POST['msg_option']) {
+                       $message.= '\n'.$msg_options[$_POST['msg_option']];
+               }
+
+               if ($to_email != '') {
+                       
+                       require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+
+                       $mail = new ATutorMailer;
+
+                       $mail->From     = $_config['contact_email'];
+                       $mail->AddAddress($to_email);
+                       $mail->Subject = _AT('instructor_request');
+                       $mail->Body    = $message;
+
+                       if(!$mail->Send()) {
+                          //echo 'There was an error sending the message';
+                          $msg->printErrors('SENDING_ERROR');
+                          exit;
+                       }
+
+                       unset($mail);
+               }
+       }
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       Header('Location: index.php');
+       exit;
+} else if ($_POST['cancel']) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php');
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+$sql   = "SELECT email, first_name, last_name FROM ".TABLE_PREFIX."members WHERE member_id=".$request_id;
+$result = mysql_query($sql, $db);
+
+if ($row = mysql_fetch_array($result)) {
+       $username = '';
+       if ($row['first_name']!="") {
+               $username .= $row['first_name'].' ';
+       }
+
+       if ($row['last_name']!="") {
+               $username .= $row['last_name'].' ';
+       }
+       $username .= $row['email'];
+} else {
+       require(AT_INCLUDE_PATH.'header.inc.php'); 
+       echo _AT('no_user_found');
+       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+       exit;
+}
+?>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">
+<input type="hidden" name="action" value="process" />
+<input type="hidden" name="id" value="<?php echo $request_id; ?>" />
+
+<div class="input-form">
+       <div class="row">
+               <label for="confirm">
+               <?php 
+               echo _AT('confirm_deny_instructor');
+               echo "<ul><li>$username</li></ul>"; 
+               ?>
+               </label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('instructor_request_enterdenymsg'); ?><br />
+
+               <?php 
+                       $radio_buttons = '';
+                       $i = 0;
+                       echo '<input type="radio" name="msg_option" id="c'.$i.'" value="'.$i.'" checked="checked" /><label for="c'.$i.'">'.$msg_options[$i].'</label><br />';
+
+                       $num_msgs = count($msg_options) - 1;
+                       for ($i = 1; $i<$num_msgs; $i++) {
+                               echo '<input type="radio" name="msg_option" id="c'.$i.'" value="'.$i.'" /><label for="c'.$i.'">'.$msg_options[$i].'</label><br />';
+                       }
+
+                       echo '<input type="radio" name="msg_option" id="c'.$i.'" value="'.$i.'" /><label for="c'.$i.'">'.$msg_options[$i].'</label>';
+               ?>
+               <input type="text" class="formfield" name="other_msg" id="other_msg" size="30" onmousedown="document.form['c<?php echo $other_option; ?>'].checked = true;">
+               <br />
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('deny'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/admin_email.php b/admin/admin_email.php
new file mode 100644 (file)
index 0000000..4a78841
--- /dev/null
@@ -0,0 +1,132 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_USERS);
+
+if ($_POST['cancel']) {
+       $msg->addFeedback('CANCELLED');
+
+       header('Location: users.php#feedback');
+       exit;
+} else if ($_POST['submit']) {
+       $missing_fields = array();
+
+       $_POST['subject'] = trim($_POST['subject']);
+       $_POST['body'] = trim($_POST['body']);
+
+       if (($_POST['to'] == '') || ($_POST['to'] == 0)) {
+               $missing_fields[] = _AT('to');
+       }
+
+       if ($_POST['subject'] == '') {
+               $missing_fields[] = _AT('subject');
+       }
+
+       if ($_POST['body'] == '') {
+               $missing_fields[] = _AT('body');
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+       if (!$msg->containsErrors()) {
+               if ($_POST['to'] == 1) {
+                       // choose all instructors
+                       $sql    = "SELECT * FROM ".TABLE_PREFIX."members WHERE status = ".AT_STATUS_INSTRUCTOR;
+               } else if ($_POST['to'] == 2) {
+                       // choose all students
+                       $sql    = "SELECT * FROM ".TABLE_PREFIX."members WHERE status = ".AT_STATUS_STUDENT;
+               } else {
+                       // choose all members
+                       $sql    = "SELECT * FROM ".TABLE_PREFIX."members WHERE status = ".AT_STATUS_INSTRUCTOR." OR status = ".AT_STATUS_STUDENT;
+               }
+               
+               $result = mysql_query($sql,$db);
+
+               require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+
+               $mail = new ATutorMailer;
+
+               while ($row = mysql_fetch_assoc($result)) {
+                       $mail->AddBCC($row['email']);
+               }
+
+
+               $mail->From     = $_config['contact_email'];
+               $mail->FromName = $_config['site_name'];
+               $mail->AddAddress($_config['contact_email']);
+               $mail->Subject = $stripslashes($_POST['subject']);
+               $mail->Body    = $stripslashes($_POST['body']);
+
+               if(!$mail->Send()) {
+                  //echo 'There was an error sending the message';
+                  $msg->printErrors('SENDING_ERROR');
+                  exit;
+               }
+               unset($mail);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: users.php');
+               exit;
+       }
+}
+
+$title = _AT('admin_email');
+
+$onload = 'document.form.subject.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$sql   = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."members ORDER BY login";
+$result = mysql_query($sql,$db);
+$row   = mysql_fetch_array($result);
+if ($row['cnt'] == 0) {
+       $msg->printErrors('NO_MEMBERS');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+?>
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">
+<input type="hidden" name="admin" value="admin" />
+
+<div class="input-form">
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><?php echo  _AT('to'); ?><br />
+               <input type="radio" name="to" value="3" checked="checked" id="all" /><label for="all"><?php echo _AT('all_users'); ?></label>  
+         <input type="radio" name="to" value="1" id="inst" <?php if ($_POST['to'] == AT_STATUS_INSTRUCTOR) { echo 'checked="checked"'; } ?> /><label for="inst"><?php echo  _AT('instructors'); ?></label>
+         <input type="radio" name="to" value="2" id="stud" <?php if ($_POST['to'] == AT_STATUS_STUDENT) { echo 'checked="checked"'; } ?> /><label for="stud"><?php echo  _AT('students'); ?></label>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="subject"><?php echo _AT('subject'); ?></label><br />
+               <input type="text" name="subject" size="40" id="subject" value="<?php echo $_POST['subject']; ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="body"><?php echo _AT('body'); ?></label><br />
+               <textarea cols="55" rows="18" name="body" id="body"><?php echo $_POST['body']; ?></textarea>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('send'); ?>" accesskey="s" /> 
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/admins/create.php b/admin/admins/create.php
new file mode 100644 (file)
index 0000000..d887e8e
--- /dev/null
@@ -0,0 +1,228 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       $missing_fields = array();\r
+\r
+       /* login validation */\r
+       if ($_POST['login'] == '') {\r
+               $missing_fields[] = _AT('login_name');\r
+       } else {\r
+               /* check for special characters */\r
+               if (!(eregi("^[a-zA-Z0-9_]([a-zA-Z0-9_])*$", $_POST['login']))) {\r
+                       $msg->addError('LOGIN_CHARS');\r
+               } else {\r
+                       $result = mysql_query("SELECT * FROM ".TABLE_PREFIX."members WHERE login='$_POST[login]'",$db);\r
+                       if (mysql_num_rows($result) != 0) {\r
+                               $msg->addError('LOGIN_EXISTS');\r
+                       } \r
+                                               \r
+                       $result = mysql_query("SELECT * FROM ".TABLE_PREFIX."admins WHERE login='$_POST[login]'",$db);\r
+                       if (mysql_num_rows($result) != 0) {\r
+                               $msg->addError('LOGIN_EXISTS');\r
+                       }\r
+               }\r
+       }\r
+\r
+       /* password check: password is verified front end by javascript. here is to handle the errors from javascript */\r
+       if ($_POST['password_error'] <> "")\r
+       {\r
+               $pwd_errors = explode(",", $_POST['password_error']);\r
+\r
+               foreach ($pwd_errors as $pwd_error)\r
+               {\r
+                       if ($pwd_error == "missing_password")\r
+                               $missing_fields[] = _AT('password');\r
+                       else\r
+                               $msg->addError($pwd_error);\r
+               }\r
+       }\r
+\r
+       /* email validation */\r
+       if ($_POST['email'] == '') {\r
+               $missing_fields[] = _AT('email');\r
+       } else if (!eregi("^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$", $_POST['email'])) {\r
+               $msg->addError('EMAIL_INVALID');\r
+       }\r
+       $result = mysql_query("SELECT * FROM ".TABLE_PREFIX."members WHERE email LIKE '$_POST[email]'",$db);\r
+       if (mysql_num_rows($result) != 0) {\r
+               $valid = 'no';\r
+               $msg->addError('EMAIL_EXISTS');\r
+       }\r
+\r
+       $priv = 0;\r
+       if (isset($_POST['priv_admin'])) {\r
+               // overrides all above.\r
+               $priv = AT_ADMIN_PRIV_ADMIN;\r
+       } else if (isset($_POST['privs'])) {\r
+               foreach ($_POST['privs'] as $value) {\r
+                       $priv += intval($value);\r
+               }\r
+       }\r
+       $_POST['privs'] = $priv;\r
+\r
+       if ($missing_fields) {\r
+               $missing_fields = implode(', ', $missing_fields);\r
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               $_POST['login']     = $addslashes($_POST['login']);\r
+               $password  = $addslashes($_POST['form_password_hidden']);\r
+               $_POST['real_name'] = $addslashes($_POST['real_name']);\r
+               $_POST['email']     = $addslashes($_POST['email']);\r
+\r
+               $admin_lang = $_config['default_language']; \r
+\r
+               $sql    = "INSERT INTO ".TABLE_PREFIX."admins\r
+                                (login,\r
+                                 password,\r
+                                 real_name,\r
+                                 email,\r
+                                 language,\r
+                                 privileges,\r
+                                 last_login)\r
+                         VALUES ('$_POST[login]', \r
+                                 '$password', \r
+                                 '$_POST[real_name]', \r
+                                 '$_POST[email]', \r
+                                 '$admin_lang', \r
+                                 $priv, \r
+                                 0)";\r
+               $result = mysql_query($sql, $db) or die(mysql_error());\r
+\r
+               $sql    = "INSERT INTO ".TABLE_PREFIX."admins\r
+                                (login,\r
+                                 password,\r
+                                 real_name,\r
+                                 email,\r
+                                 language,\r
+                                 privileges,\r
+                                 last_login)\r
+                         VALUES ('$_POST[login]', \r
+                                 '********', \r
+                                 '$_POST[real_name]', \r
+                                 '$_POST[email]', \r
+                                 '$admin_lang', \r
+                                 $priv, \r
+                                 0)";\r
+                                 \r
+               write_to_log(AT_ADMIN_LOG_INSERT, 'admins', mysql_affected_rows($db), $sql);\r
+\r
+               $msg->addFeedback('ADMIN_CREATED');\r
+               header('Location: index.php');\r
+               exit;\r
+       }\r
+       $_POST['login']             = $stripslashes($_POST['login']);\r
+       $_POST['real_name']         = $stripslashes($_POST['real_name']);\r
+       $_POST['email']             = $stripslashes($_POST['email']);\r
+} \r
+\r
+$onload = 'document.form.login.focus();';\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+?>\r
+<script language="JavaScript" src="sha-1factory.js" type="text/javascript"></script>\r
+\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">\r
+<input type="hidden" name="form_password_hidden" value="" />\r
+<input type="hidden" name="password_error" value="" />\r
+\r
+<div class="input-form">\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="login"><?php echo _AT('login_name'); ?></label><br />\r
+               <input type="text" name="login" id="login" size="25" value="<?php echo htmlspecialchars($_POST['login']); ?>" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="password"><?php echo _AT('password'); ?></label><br />\r
+               <input type="password" name="password" id="password" size="25" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="password2"><?php echo _AT('confirm_password'); ?></label><br />\r
+               <input type="password" name="confirm_password" id="password2" size="25" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <label for="real_name"><?php echo _AT('real_name'); ?></label><br />\r
+               <input type="text" name="real_name" id="real_name" size="30" value="<?php echo htmlspecialchars($_POST['real_name']); ?>" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="email"><?php echo _AT('email'); ?></label><br />\r
+               <input type="text" name="email" id="email" size="30" value="<?php echo htmlspecialchars($_POST['email']); ?>" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <?php echo _AT('privileges'); ?><br />\r
+               <input type="checkbox" name="priv_admin" value="1" id="priv_admin" <?php if ($_POST['priv_admin']) { echo 'checked="checked"'; } ?> /><label for="priv_admin"><?php echo _AT('priv_admin_super'); ?></label><br /><br />\r
+\r
+               <?php\r
+                       $module_list = $moduleFactory->getModules(AT_MODULE_STATUS_ENABLED, 0, TRUE);\r
+                       $keys = array_keys($module_list);\r
+               ?>\r
+\r
+               <?php foreach ($keys as $module_name): ?>\r
+                       <?php $module =& $module_list[$module_name]; ?>\r
+                       <?php if (!($module->getAdminPrivilege() > 1)) { continue; } ?>\r
+                               <input type="checkbox" name="privs[]" value="<?php echo $module->getAdminPrivilege(); ?>" id="priv_<?php echo $module->getAdminPrivilege(); ?>" <?php if (query_bit($_POST['privs'], $module->getAdminPrivilege())) { echo 'checked="checked"'; }  ?> /><label for="priv_<?php echo $module->getAdminPrivilege(); ?>"><?php echo $module->getName() ?></label><br />\r
+               <?php endforeach; ?>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" onClick="return encrypt_password();" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<script language="JavaScript" src="sha-1factory.js" type="text/javascript"></script>\r
+\r
+<script type="text/javascript">\r
+function encrypt_password()\r
+{\r
+       document.form.password_error.value = "";\r
+\r
+       err = verify_password(document.form.password.value, document.form.confirm_password.value);\r
+       \r
+       if (err.length > 0)\r
+       {\r
+               document.form.password_error.value = err;\r
+       }\r
+       else\r
+       {\r
+               document.form.form_password_hidden.value = hex_sha1(document.form.password.value);\r
+               document.form.password.value = "";\r
+               document.form.confirm_password.value = "";\r
+               if (document.form.priv_admin.checked == true) \r
+               {\r
+                       return confirm('<?php echo _AT('confirm_admin_create'); ?>');\r
+               } \r
+               else \r
+               {\r
+                       return true;\r
+               }\r
+       }\r
+}\r
+</script>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>\r
diff --git a/admin/admins/delete.php b/admin/admins/delete.php
new file mode 100644 (file)
index 0000000..36e05f5
--- /dev/null
@@ -0,0 +1,59 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);\r
+\r
+$_GET['login'] = $addslashes($_GET['login']);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       $_POST['login'] = $addslashes($_POST['login']);\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."admins WHERE login='$_POST[login]'";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       write_to_log(AT_ADMIN_LOG_DELETE, 'admins', mysql_affected_rows($db), $sql);\r
+\r
+       $msg->addFeedback('ADMIN_DELETED');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+?>\r
+<?php require(AT_INCLUDE_PATH.'header.inc.php'); ?>\r
+<?php\r
+\r
+if (!strcasecmp($_GET['login'], $_SESSION['login'])) {\r
+       $msg->addError('CANNOT_DELETE_OWN_ACCOUNT');\r
+       $msg->printErrors();\r
+       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+\r
+$sql = "SELECT * FROM ".TABLE_PREFIX."admins WHERE login='$_GET[login]'";\r
+$result = mysql_query($sql, $db);\r
+if (!($row = mysql_fetch_assoc($result))) {\r
+       echo _AT('no_user_found');\r
+} else {\r
+       $hidden_vars['login'] = $_GET['login'];\r
+       $confirm = array('DELETE_ADMIN', $row['login']);\r
+       $msg->addConfirm($confirm, $hidden_vars);\r
+       $msg->printConfirm();\r
+}\r
+?>\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/admins/detail_log.php b/admin/admins/detail_log.php
new file mode 100644 (file)
index 0000000..9ee3af4
--- /dev/null
@@ -0,0 +1,86 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);\r
+\r
+if (isset($_POST['submit'])) {\r
+       header('Location: log.php?p='.$_POST['p'].SEP.'login='.$_POST['login']);\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$offset = $_GET['offset'] - 1;\r
+$col = $addslashes($_GET['col']);\r
+$order = $addslashes($_GET['order']);\r
+\r
+$login_where = '';\r
+if (isset($_GET['login']) && $_GET['login']) {\r
+       $_GET['login'] = $addslashes($_GET['login']);\r
+\r
+       $login_where = ' WHERE login=\''.$_GET['login'].'\'';\r
+}\r
+\r
+$sql = "SELECT * FROM ".TABLE_PREFIX."admin_log $login_where ORDER BY `time` DESC LIMIT $offset,1";\r
+$result = mysql_query($sql, $db);\r
+$row = mysql_fetch_assoc($result);\r
+\r
+$operations[AT_ADMIN_LOG_UPDATE] = _AT('update_to');\r
+$operations[AT_ADMIN_LOG_DELETE] = _AT('delete_from');\r
+$operations[AT_ADMIN_LOG_INSERT] = _AT('insert_into');\r
+$operations[AT_ADMIN_LOG_REPLACE] = _AT('replace_into');\r
+$operations[AT_ADMIN_LOG_OTHER] = _AT('other');\r
+\r
+?>\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<input type="hidden" name="p" value="<?php echo $_GET['p']; ?>" />\r
+<input type="hidden" name="login" value="<?php echo $_GET['login']; ?>" />\r
+<div class="input-form">\r
+       <div class="row">\r
+               <?php echo _AT('date'); ?><br />\r
+               <?php echo $row['time']; ?>\r
+       </div>\r
+       <div class="row">\r
+               <?php echo _AT('login_name'); ?><br />\r
+               <?php echo $row['login']; ?>\r
+       </div>\r
+       <div class="row">\r
+               <?php echo _AT('action'); ?><br />\r
+               <?php echo $operations[$row['operation']]; ?>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <?php echo _AT('database_table'); ?><br />\r
+               <?php echo TABLE_PREFIX . $row['table']; ?>\r
+       </div>\r
+       <div class="row">\r
+               <?php echo _AT('affected_entries'); ?><br />\r
+               <?php echo $row['num_affected']; ?>\r
+       </div>\r
+       <div class="row">\r
+               <?php echo _AT('details'); ?><br />\r
+               <kbd>\r
+                       <?php echo htmlspecialchars(wordwrap($row['details'], 80, "\n", TRUE)); ?>\r
+               </kbd>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('back'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/admins/edit.php b/admin/admins/edit.php
new file mode 100644 (file)
index 0000000..1cd0c3e
--- /dev/null
@@ -0,0 +1,155 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);\r
+\r
+if ($_GET['login'] == $_SESSION['login']) {\r
+       $msg->addError('ADMIN_EDIT_OWN_ACCOUNT');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       $missing_fields = array();\r
+\r
+       /* email validation */\r
+       if ($_POST['email'] == '') {\r
+               $missing_fields[] = _AT('email');\r
+       } else if (!eregi("^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$", $_POST['email'])) {\r
+               $msg->addError('EMAIL_INVALID');\r
+       }\r
+       $result = mysql_query("SELECT * FROM ".TABLE_PREFIX."members WHERE email LIKE '$_POST[email]'",$db);\r
+       if (mysql_num_rows($result) != 0) {\r
+               $valid = 'no';\r
+               $msg->addError('EMAIL_EXISTS');\r
+       }\r
+\r
+       $priv = 0;\r
+\r
+       if (isset($_POST['priv_admin'])) {\r
+               // overrides all above.\r
+               $priv = AT_ADMIN_PRIV_ADMIN;\r
+       } else if (isset($_POST['privs'])) {\r
+               foreach ($_POST['privs'] as $value) {\r
+                       $priv += intval($value);\r
+               }\r
+       }\r
+       $_POST['privs'] = $priv;\r
+\r
+       if ($missing_fields) {\r
+               $missing_fields = implode(', ', $missing_fields);\r
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               $_POST['login']     = $addslashes($_POST['login']);\r
+               $_POST['real_name'] = $addslashes($_POST['real_name']);\r
+               $_POST['email']     = $addslashes($_POST['email']);\r
+\r
+               $sql    = "UPDATE ".TABLE_PREFIX."admins SET real_name='$_POST[real_name]', email='$_POST[email]', `privileges`=$priv, last_login=last_login WHERE login='$_POST[login]'";\r
+               $result = mysql_query($sql, $db);\r
+\r
+               $sql    = "UPDATE ".TABLE_PREFIX."admins SET real_name='$_POST[real_name]', email='$_POST[email]', `privileges`=$priv WHERE login='$_POST[login]'";\r
+\r
+               write_to_log(AT_ADMIN_LOG_UPDATE, 'admins', mysql_affected_rows($db), $sql);\r
+\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+               header('Location: index.php');\r
+               exit;\r
+       }\r
+       $_POST['login']             = $stripslashes($_POST['login']);\r
+       $_POST['real_name']         = $stripslashes($_POST['real_name']);\r
+       $_POST['email']             = $stripslashes($_POST['email']);\r
+} \r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+\r
+$_GET['login'] = $addslashes($_REQUEST['login']);\r
+\r
+$sql = "SELECT * FROM ".TABLE_PREFIX."admins WHERE login='$_GET[login]'";\r
+$result = mysql_query($sql, $db);\r
+if (!($row = mysql_fetch_assoc($result))) {\r
+       $msg->addError('USER_NOT_FOUND');\r
+       $msg->printErrors();\r
+       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+if (!isset($_POST['submit'])) {\r
+       $_POST = $row;\r
+       if (query_bit($row['privileges'], AT_ADMIN_PRIV_ADMIN)) {\r
+               $_POST['priv_admin'] = 1;\r
+       }\r
+       $_POST['privs'] = intval($row['privileges']);\r
+}\r
+\r
+?>\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">\r
+<input type="hidden" name="login" value="<?php echo $row['login']; ?>" />\r
+<div class="input-form">\r
+       <div class="row">\r
+               <h3><?php echo $row['login']; ?></h3>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <label for="real_name"><?php echo _AT('real_name'); ?></label><br />\r
+               <input type="text" name="real_name" id="real_name" size="30" value="<?php echo htmlspecialchars($_POST['real_name']); ?>" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="email"><?php echo _AT('email'); ?></label><br />\r
+               <input type="text" name="email" id="email" size="30" value="<?php echo htmlspecialchars($_POST['email']); ?>" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <?php echo _AT('privileges'); ?><br />\r
+               <input type="checkbox" name="priv_admin" value="1" id="priv_admin" <?php if ($_POST['priv_admin']) { echo 'checked="checked"'; } ?> /><label for="priv_admin"><?php echo _AT('priv_admin_super'); ?></label><br /><br />\r
+\r
+               <?php\r
+                       $module_list = $moduleFactory->getModules(AT_MODULE_STATUS_ENABLED, 0, TRUE);\r
+                       $keys = array_keys($module_list);\r
+               ?>\r
+\r
+               <?php foreach ($keys as $module_name): ?>\r
+                       <?php $module =& $module_list[$module_name]; ?>\r
+                       <?php if (!($module->getAdminPrivilege() > 1)) { continue; } ?>\r
+                               <input type="checkbox" name="privs[]" value="<?php echo $module->getAdminPrivilege(); ?>" id="priv_<?php echo $module->getAdminPrivilege(); ?>" <?php if (query_bit($_POST['privs'], $module->getAdminPrivilege())) { echo 'checked="checked"'; }  ?> /><label for="priv_<?php echo $module->getAdminPrivilege(); ?>"><?php echo $module->getName(); ?></label><br />\r
+               <?php endforeach; ?>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" <?php if ($_POST['priv_admin'] != 1) { echo 'onclick="return checkAdmin();"'; } ?> />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<script language="javascript" type="text/javascript">\r
+// <!--\r
+function checkAdmin() {\r
+       if (document.form.priv_admin.checked == true) {\r
+               return confirm('<?php echo _AT('confirm_admin_create'); ?>');\r
+       } else {\r
+               return true;\r
+       }\r
+}\r
+// -->\r
+</script>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/admins/index.php b/admin/admins/index.php
new file mode 100644 (file)
index 0000000..d6f36bf
--- /dev/null
@@ -0,0 +1,138 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);\r
+\r
+if (isset($_GET['delete'], $_GET['login'])) {\r
+       header('Location: delete.php?login='.$_GET['login']);\r
+       exit;\r
+} else if (isset($_GET['view_log'], $_GET['login'])) {\r
+       header('Location: log.php?login='.$_GET['login']);\r
+       exit;\r
+} else if (isset($_GET['password'], $_GET['login'])) {\r
+       header('Location: password.php?login='.$_GET['login']);\r
+       exit;\r
+} else if (isset($_GET['edit'], $_GET['login'])) {\r
+       header('Location: edit.php?login='.$_GET['login']);\r
+       exit;\r
+} else if ((isset($_GET['edit']) || isset($_GET['delete']) || isset($_GET['view_log']))) {\r
+       $msg->addError('NO_ITEM_SELECTED');\r
+}\r
+\r
+$id = $_GET['id'];\r
+$L = $_GET['L'];\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+\r
+\r
+$orders = array('asc' => 'desc', 'desc' => 'asc');\r
+$cols   = array('login' => 1, 'real_name' => 1, 'email' => 1, 'last_login' => 1);\r
+\r
+if (isset($_GET['asc'])) {\r
+       $order = 'asc';\r
+       $col   = isset($cols[$_GET['asc']]) ? $_GET['asc'] : 'login';\r
+} else if (isset($_GET['desc'])) {\r
+       $order = 'desc';\r
+       $col   = isset($cols[$_GET['desc']]) ? $_GET['desc'] : 'login';\r
+} else {\r
+       // no order set\r
+       $order = 'asc';\r
+       $col   = 'login';\r
+}\r
+\r
+?>\r
+\r
+<form name="form" method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<table summary="" class="data" rules="cols" align="center" style="width: 90%;">\r
+<colgroup>\r
+       <?php if ($col == 'login'): ?>\r
+               <col />\r
+               <col class="sort" />\r
+               <col span="4" />\r
+       <?php elseif($col == 'real_name'): ?>\r
+               <col span="2" />\r
+               <col class="sort" />\r
+               <col span="3" />\r
+       <?php elseif($col == 'email'): ?>\r
+               <col span="3" />\r
+               <col class="sort" />\r
+               <col span="2" />\r
+       <?php elseif($col == 'last_login'): ?>\r
+               <col span="4" />\r
+               <col class="sort" />\r
+               <col />\r
+       <?php endif; ?>\r
+</colgroup>\r
+<thead>\r
+<tr>\r
+       <th scope="col">&nbsp;</th>\r
+       <th scope="col"><a href="admin/admins/index.php?<?php echo $orders[$order]; ?>=login<?php echo $page_string; ?>"><?php echo _AT('login_name');        ?></a></th>\r
+       <th scope="col"><a href="admin/admins/index.php?<?php echo $orders[$order]; ?>=real_name<?php echo $page_string; ?>"><?php echo _AT('real_name');   ?></a></th>\r
+       <th scope="col"><a href="admin/admins/index.php?<?php echo $orders[$order]; ?>=email<?php echo $page_string; ?>"><?php echo _AT('email');           ?></a></th>\r
+       <th scope="col"><a href="admin/admins/index.php?<?php echo $orders[$order]; ?>=last_login<?php echo $page_string; ?>"><?php echo _AT('last_login'); ?></a></th>\r
+       <th scope="col"><?php echo _AT('account_status'); ?></th>\r
+</tr>\r
+</thead>\r
+<tfoot>\r
+<tr>\r
+       <td colspan="6">\r
+               <input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" />\r
+               <input type="submit" name="view_log" value="<?php echo _AT('view_log'); ?>" />\r
+               <input type="submit" name="password" value="<?php echo _AT('password'); ?>" />\r
+               <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" />\r
+       </td>\r
+</tr>\r
+</tfoot>\r
+<tbody>\r
+<?php\r
+       $offset = ($page-1)*$results_per_page;\r
+\r
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."admins ORDER BY $col $order";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       if (mysql_num_rows($result) == 0) { ?>\r
+       <tr>\r
+               <td colspan="6"><?php echo _AT('no_admins_found'); ?></td>\r
+       </tr><?php\r
+       } else {\r
+               while ($row = mysql_fetch_assoc($result)): ?>\r
+                       <tr onmousedown="document.form['m<?php echo $row['login']; ?>'].checked = true;rowselect(this);" id="r_<?php echo $row['login']; ?>">\r
+                               <td><input type="radio" name="login" value="<?php echo $row['login']; ?>" id="m<?php echo $row['login']; ?>" /></td>\r
+                               <td><label for="m<?php echo $row['login']; ?>"><?php echo $row['login'];      ?></label></td>\r
+                               <td><?php echo $row['real_name'];  ?></td>\r
+                               <td><?php echo $row['email'];      ?></td>\r
+                               <td><?php \r
+                                       if ($row['last_login'] == '0000-00-00 00:00:00') {\r
+                                               echo _AT('never');\r
+                                       } else {\r
+                                               echo $row['last_login'];\r
+                                       } ?></td>\r
+                               <td><?php \r
+                                       if ($row['privileges'] == 1) { \r
+                                               echo _AT('priv_admin_super');\r
+                                       } else if ($row['privileges'] > 0) {\r
+                                               echo _AT('active_admin');\r
+                                       } else {\r
+                                               echo _AT('inactive_admin');\r
+                                       }\r
+                                ?> </td>\r
+                       </tr>\r
+               <?php endwhile; ?>\r
+       <?php } ?>\r
+</tbody>\r
+</table>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/admins/log.php b/admin/admins/log.php
new file mode 100644 (file)
index 0000000..8557e62
--- /dev/null
@@ -0,0 +1,99 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$operations[AT_ADMIN_LOG_UPDATE] = _AT('update_to');\r
+$operations[AT_ADMIN_LOG_DELETE] = _AT('delete_from');\r
+$operations[AT_ADMIN_LOG_INSERT] = _AT('insert_into');\r
+$operations[AT_ADMIN_LOG_REPLACE] = _AT('replace_into');\r
+$operations[AT_ADMIN_LOG_OTHER] = _AT('other');\r
+\r
+$login_where = '';\r
+if (isset($_GET['login']) && $_GET['login']) {\r
+       $_GET['login'] = $addslashes($_GET['login']);\r
+\r
+       $login_where = ' WHERE login=\''.$_GET['login'].'\'';\r
+}\r
+\r
+$sql   = "SELECT COUNT(login) FROM ".TABLE_PREFIX."admin_log $login_where";\r
+$result = mysql_query($sql, $db);\r
+\r
+if (($row = mysql_fetch_assoc($result))==0) {\r
+       echo '<tr><td colspan="7" class="row1">'._AT('no_log_found_').'</td></tr>';\r
+       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+\r
+       $num_results = $row[0];\r
+       $results_per_page = 50;\r
+       $num_pages = max(ceil($num_results / $results_per_page), 1);\r
+       $page = intval($_GET['p']);\r
+       if (!$page) {\r
+               $page = 1;\r
+       }       \r
+       $count = (($page-1) * $results_per_page) + 1;\r
+\r
+       echo '<div class="paging">';\r
+       echo '<ul>';\r
+       for ($i=1; $i<=$num_pages; $i++) {\r
+               echo '<li>';\r
+               if ($i == $page) {\r
+                       echo '<a class="current" href="'.$_SERVER['PHP_SELF'].'?p='.$i.SEP.'login='.$_GET['login'].'"><em>'.$i.'</em></a>';\r
+               } else {\r
+                       echo '<a href="'.$_SERVER['PHP_SELF'].'?p='.$i.SEP.'login='.$_GET['login'].'#list">'.$i.'</a>';\r
+               }\r
+               echo '</li>';\r
+       }\r
+       echo '</ul>';\r
+       echo '</div>';\r
+\r
+       $offset = ($page-1)*$results_per_page;\r
+\r
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."admin_log $login_where ORDER BY `time` DESC LIMIT $offset, $results_per_page";\r
+       $result = mysql_query($sql, $db);\r
+?>\r
+<table summary="" class="data" rules="cols" align="center">\r
+<thead>\r
+<tr>\r
+       <th scope="col"><?php echo _AT('date');           ?></th>\r
+       <th scope="col"><?php echo _AT('login_name');     ?></th>\r
+       <th scope="col"><?php echo _AT('action');         ?></th>\r
+       <th scope="col"><?php echo _AT('database_table'); ?></th>\r
+</tr>\r
+</thead>\r
+<tbody>\r
+<?php if (mysql_num_rows($result) > 0) : ?>\r
+       <?php while ($row = mysql_fetch_assoc($result)): ?>\r
+               <?php $offset++; ?>\r
+               <tr onmousedown="document.location='<?php echo AT_BASE_HREF; ?>admin/admins/detail_log.php?offset=<?php echo $offset.SEP.'p='.$page.SEP.'login='.$_GET['login']; ?>'" title="<?php echo _AT('view_details'); ?>">\r
+                       <td><a href="<?php echo AT_BASE_HREF; ?>admin/admins/detail_log.php?offset=<?php echo $offset.SEP.'p='.$page.SEP.'login='.$_GET['login']; ?>"><?php echo $row['time']; ?></a></td>\r
+                       <td><?php echo $row['login']; ?></td>\r
+                       <td><?php echo $operations[$row['operation']]; ?></td>\r
+                       <td><?php echo $row['table']; ?></td>\r
+               </tr>\r
+       <?php endwhile; ?>\r
+<?php else: ?>\r
+<tr>\r
+       <td colspan="4"><?php echo _AT('none_found'); ?></td>\r
+</tr>\r
+<?php endif; ?>\r
+</tbody>\r
+</table>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/admins/my_edit.php b/admin/admins/my_edit.php
new file mode 100644 (file)
index 0000000..b917ddc
--- /dev/null
@@ -0,0 +1,94 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate();\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.AT_BASE_HREF.'admin/index.php');\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       $missing_fields = array();\r
+\r
+       /* email validation */\r
+       if ($_POST['email'] == '') {\r
+               $missing_fields[] = _AT('email');\r
+       } else if (!eregi("^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$", $_POST['email'])) {\r
+               $msg->addError('EMAIL_INVALID');\r
+       }\r
+       $result = mysql_query("SELECT * FROM ".TABLE_PREFIX."members WHERE email LIKE '$_POST[email]'",$db);\r
+       if (mysql_num_rows($result) != 0) {\r
+               $valid = 'no';\r
+               $msg->addError('EMAIL_EXISTS');\r
+       }\r
+\r
+       if ($missing_fields) {\r
+               $missing_fields = implode(', ', $missing_fields);\r
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+//             $_POST['password']  = $addslashes($_POST['password']);\r
+               $_POST['real_name'] = $addslashes($_POST['real_name']);\r
+               $_POST['email']     = $addslashes($_POST['email']);\r
+\r
+               $sql    = "UPDATE ".TABLE_PREFIX."admins SET real_name='$_POST[real_name]', email='$_POST[email]', last_login=last_login WHERE login='$_SESSION[login]'";\r
+               $result = mysql_query($sql, $db);\r
+\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+               header('Location: '.AT_BASE_HREF.'admin/index.php');\r
+               exit;\r
+       }\r
+       $_POST['real_name']         = $stripslashes($_POST['real_name']);\r
+       $_POST['email']             = $stripslashes($_POST['email']);\r
+} \r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+\r
+$sql = "SELECT real_name, email FROM ".TABLE_PREFIX."admins WHERE login='$_SESSION[login]'";\r
+$result = mysql_query($sql, $db);\r
+if (!($row = mysql_fetch_assoc($result))) {\r
+       $msg->addError('USER_NOT_FOUND');\r
+       $msg->printErrors();\r
+       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+if (!isset($_POST['submit'])) {\r
+       $_POST = $row;\r
+//     $_POST['confirm_password'] = $_POST['password'];\r
+}\r
+\r
+?>\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<div class="input-form">\r
+       <div class="row">\r
+               <label for="real_name"><?php echo _AT('real_name'); ?></label><br />\r
+               <input type="text" name="real_name" id="real_name" size="30" value="<?php echo htmlspecialchars($_POST['real_name']); ?>" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="email"><?php echo _AT('email'); ?></label><br />\r
+               <input type="text" name="email" id="email" size="30" value="<?php echo htmlspecialchars($_POST['email']); ?>" />\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/admins/my_password.php b/admin/admins/my_password.php
new file mode 100644 (file)
index 0000000..8a378fe
--- /dev/null
@@ -0,0 +1,78 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+if ($_SESSION['valid_user'] !== true) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $info = array('INVALID_USER', $_SESSION['course_id']);
+       $msg->printInfos($info);
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'admin/index.php');
+       exit;
+}
+
+if (isset($_POST['submit'])) {
+       if (!empty($_POST['form_old_password_hidden'])) {
+               //check if old password entered is correct
+               $sql    = "SELECT password FROM ".TABLE_PREFIX."admins WHERE login='$_SESSION[login]'";
+               $result = mysql_query($sql,$db);
+               if ($row = mysql_fetch_assoc($result)) {
+                       if ($row['password'] != $_POST['form_old_password_hidden']) {
+                               $msg->addError('WRONG_PASSWORD');
+                               Header('Location: my_password.php');
+                               exit;
+                       }
+               }
+       } else {
+               $msg->addError(array('EMPTY_FIELDS', _AT('password')));
+               header('Location: my_password.php');
+               exit;
+       }
+
+       // new password check
+       if ($_POST['password_error'] <> "")
+       {
+               $pwd_errors = explode(",", $_POST['password_error']);
+
+               foreach ($pwd_errors as $pwd_error)
+               {
+                       if ($pwd_error == "missing_password")
+                               $missing_fields[] = _AT('password');
+                       else
+                               $msg->addError($pwd_error);
+               }
+       }
+
+       if (!$msg->containsErrors()) {                  
+               $password   = addslashes($_POST['form_password_hidden']);
+
+               $sql    = "UPDATE ".TABLE_PREFIX."admins SET password='$password', last_login=last_login WHERE login='$_SESSION[login]'";
+               $result = mysql_query($sql, $db);
+
+               $msg->addFeedback('PASSWORD_CHANGED');
+               header('Location: '.AT_BASE_HREF.'admin/index.php');
+               exit;
+       }
+}
+
+/* template starts here */
+$savant->display('users/password_change.tmpl.php');
+
+?>
\ No newline at end of file
diff --git a/admin/admins/password.php b/admin/admins/password.php
new file mode 100644 (file)
index 0000000..48fb488
--- /dev/null
@@ -0,0 +1,126 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_USERS);
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'admin/admins/index.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       /* password check: password is verified front end by javascript. here is to handle the errors from javascript */
+       if ($_POST['password_error'] <> "")
+       {
+               $pwd_errors = explode(",", $_POST['password_error']);
+
+               foreach ($pwd_errors as $pwd_error)
+               {
+                       if ($pwd_error == "missing_password")
+                               $missing_fields[] = _AT('password');
+                       else
+                               $msg->addError($pwd_error);
+               }
+       }
+
+       if (!$msg->containsErrors()) {
+               $password     = $addslashes($_POST['form_password_hidden']);
+
+               $sql    = "UPDATE ".TABLE_PREFIX."admins SET password='$password', last_login=last_login WHERE login='$_POST[login]'";
+               $result = mysql_query($sql, $db);
+
+               $sql    = "UPDATE ".TABLE_PREFIX."admins SET password='********' WHERE login='$_POST[login]'";
+               write_to_log(AT_ADMIN_LOG_UPDATE, 'admins', mysql_affected_rows($db), $sql);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: '.AT_BASE_HREF.'admin/admins/index.php');
+               exit;
+       }
+       $_POST['login'] = $stripslashes($_POST['login']);
+}
+
+
+$_GET['login'] = $addslashes($_REQUEST['login']);
+
+$sql = "SELECT login FROM ".TABLE_PREFIX."admins WHERE login='$_GET[login]'";
+$result = mysql_query($sql, $db);
+if (!($row = mysql_fetch_assoc($result))) {
+       $msg->addError('USER_NOT_FOUND');
+       $msg->printErrors();
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+if (!isset($_POST['submit'])) {
+       $_POST = $row;
+
+       if (query_bit($row['privileges'], AT_ADMIN_PRIV_ADMIN)) {
+               $_POST['priv_admin'] = 1;
+       }
+       $_POST['privs'] = intval($row['privileges']);
+}
+
+$onload = 'document.form.password1.focus();';
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<script language="JavaScript" src="sha-1factory.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+function encrypt_password()
+{
+       document.form.password_error.value = "";
+
+       err = verify_password(document.form.password1.value, document.form.confirm_password.value);
+       
+       if (err.length > 0)
+       {
+               document.form.password_error.value = err;
+       }
+       else
+       {
+               document.form.form_password_hidden.value = hex_sha1(document.form.password1.value);
+               document.form.password1.value = "";
+               document.form.confirm_password.value = "";
+       }
+}
+</script>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">
+       <input type="hidden" name="login" value="<?php echo $row['login']; ?>" />
+       <input type="hidden" name="form_password_hidden" value="" />
+       <input type="hidden" name="password_error" value="" />
+
+       <div class="input-form">
+               <div class="row">
+                       <h3><?php echo htmlspecialchars($row['login']); ?></h3>
+               </div>
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="form_password1"><?php echo _AT('password'); ?></label><br />
+                       <input type="password" name="password1" id="password1" size="15" />
+               </div>
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="form_password2"><?php echo _AT('confirm_password'); ?></label><br />
+                       <input type="password" name="confirm_password" id="confirm_password" size="15" />
+               </div>
+
+               <div class="row buttons">
+                       <input type="submit" name="submit" value="<?php echo _AT('submit'); ?>" accesskey="s" onclick="encrypt_password();" />
+                       <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+               </div>
+       </div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/admins/reset_log.php b/admin/admins/reset_log.php
new file mode 100644 (file)
index 0000000..4e981cd
--- /dev/null
@@ -0,0 +1,46 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: ./log.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       //clean up the db\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."admin_log";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       write_to_log(AT_ADMIN_LOG_DELETE, 'admin_log', mysql_affected_rows($db), $sql);\r
+\r
+       $msg->addFeedback('ADMIN_LOG_RESET');\r
+       header('Location: ./log.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+//print confirmation\r
+$hidden_vars['all'] = TRUE;\r
+\r
+$confirm = array('RESET_ADMIN_LOG', $_SERVER['PHP_SELF']);\r
+$msg->addConfirm($confirm, $hidden_vars);\r
+$msg->printConfirm();\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/admin/auto_enroll.php b/admin/auto_enroll.php
new file mode 100644 (file)
index 0000000..665513c
--- /dev/null
@@ -0,0 +1,91 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id: auto_enroll.php 7208 2008-02-20 16:07:24Z cindy $\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'lib/themes.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);\r
+\r
+if (isset($_POST['delete'], $_POST['auto_enroll_id'])) {\r
+       header('Location: auto_enroll_delete.php?auto_enroll_id='.$_POST['auto_enroll_id']);\r
+       exit;\r
+} else if (isset($_POST['edit'], $_POST['auto_enroll_id'])) {\r
+       header('Location: auto_enroll_edit.php?auto_enroll_id='.$_POST['auto_enroll_id']);\r
+       exit;\r
+} else if (!empty($_POST)) {\r
+       $msg->addError('NO_ITEM_SELECTED');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+\r
+?>\r
+<form name="form" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<table summary="" class="data" rules="cols" align="center" style="width: 70%;">\r
+\r
+<thead>\r
+<tr>\r
+       <th scope="col">&nbsp;</th>\r
+       <th scope="col"><?php echo _AT('name'); ?></th>\r
+       <th scope="col"><?php echo _AT('courses'); ?></th>\r
+       <th scope="col"><?php echo _AT('url'); ?></th>\r
+</tr>\r
+</thead>\r
+<tfoot>\r
+<tr>\r
+       <td colspan="4">\r
+               <div class="row buttons">\r
+               <input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /> \r
+               </div>\r
+       </td>\r
+</tr>\r
+</tfoot>\r
+<tbody>\r
+<?php\r
+$sql   = "SELECT * FROM ".TABLE_PREFIX."auto_enroll ae ORDER BY name";\r
+$result = mysql_query($sql, $db) or die(mysql_error());\r
+\r
+if ($row = mysql_fetch_assoc($result)): ?>\r
+       <?php\r
+       do {\r
+               $courses = "";\r
+               $sql_courses = "SELECT c.title FROM ". TABLE_PREFIX."auto_enroll_courses aec, " . \r
+                                        TABLE_PREFIX ."courses c \r
+                         WHERE aec.auto_enroll_id = ". $row["auto_enroll_id"] . "\r
+                           AND aec.course_id = c.course_id\r
+                         ORDER BY c.title";\r
+\r
+               $result_courses = mysql_query($sql_courses, $db) or die(mysql_error());\r
+\r
+               while ($row_courses = mysql_fetch_assoc($result_courses))\r
+                       $courses .= $row_courses["title"] . "<br>";\r
+       ?>\r
+               <tr onmousedown="document.form['m<?php echo $row['auto_enroll_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $row['auto_enroll_id']; ?>">\r
+                       <td width="10"><input type="radio" name="auto_enroll_id" value="<?php echo $row['auto_enroll_id']; ?>" id="m<?php echo $row['auto_enroll_id']; ?>" /></td>\r
+                       <td><label for="m<?php echo $row['auto_enroll_id']; ?>"><?php if ($row['name']=="") echo _AT('na'); else echo $row['name']; ?></label></td>\r
+                       <td><?php echo $courses; ?></td>\r
+                       <td nowrap><?php echo $_base_href. "registration.php?en_id=". $row['associate_string']; ?></td>\r
+               </tr>\r
+       <?php } while ($row = mysql_fetch_assoc($result)); ?>\r
+<?php else: ?>\r
+       <tr>\r
+               <td colspan="4"><?php echo _AT('none_found'); ?></td>\r
+       </tr>\r
+<?php endif; ?>\r
+</tbody>\r
+</table>\r
+\r
+</form>\r
+\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/auto_enroll_delete.php b/admin/auto_enroll_delete.php
new file mode 100644 (file)
index 0000000..9f4f8b0
--- /dev/null
@@ -0,0 +1,66 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id: auto_enroll_delete.php 7208 2008-02-20 16:07:24Z cindy $\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: auto_enroll.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       /* delete has been confirmed, delete this category */\r
+       $auto_enroll_id = intval($_POST['auto_enroll_id']);\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."auto_enroll WHERE auto_enroll_id=$auto_enroll_id";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       write_to_log(AT_ADMIN_LOG_DELETE, 'auto_enroll', mysql_affected_rows($db), $sql);\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."auto_enroll_courses WHERE auto_enroll_id=$auto_enroll_id";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       write_to_log(AT_ADMIN_LOG_DELETE, 'auto_enroll_courses', mysql_affected_rows($db), $sql);\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: auto_enroll.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+       $_GET['auto_enroll_id'] = intval($_GET['auto_enroll_id']); \r
+\r
+       $sql = "SELECT * FROM ".TABLE_PREFIX."auto_enroll WHERE auto_enroll_id=$_GET[auto_enroll_id]";\r
+       $result = mysql_query($sql,$db) or die(mysql_error());\r
+\r
+       if (mysql_num_rows($result) == 0) {\r
+               $msg->printErrors('ITEM_NOT_FOUND');\r
+       } else {\r
+               $row = mysql_fetch_assoc($result);\r
+               \r
+               $hidden_vars['name']= $row['name'];\r
+               $hidden_vars['auto_enroll_id']  = $row['auto_enroll_id'];\r
+\r
+//             $confirm = array('DELETE_AUTO_ENROLL', AT_print($row['name'], 'auto_enroll.name'));\r
+               $confirm = array('DELETE_AUTO_ENROLL', $row['name']);\r
+               $msg->addConfirm($confirm, $hidden_vars);\r
+               \r
+               $msg->printConfirm();\r
+       }\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+\r
+?>
\ No newline at end of file
diff --git a/admin/auto_enroll_edit.php b/admin/auto_enroll_edit.php
new file mode 100644 (file)
index 0000000..4e8b9b1
--- /dev/null
@@ -0,0 +1,252 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id: auto_enroll_create.php 7208 2008-02-20 16:07:24Z cindy $\r
+//phpinfo();\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+//require(AT_INCLUDE_PATH.'lib/themes.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);\r
+\r
+function get_random_string ($minlength, $maxlength)\r
+{\r
+       $charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";\r
+       \r
+       if ($minlength > $maxlength) \r
+               $length = mt_rand ($maxlength, $minlength);\r
+       else \r
+               $length = mt_rand ($minlength, $maxlength);\r
+       \r
+       for ($i=0; $i<$length; $i++) \r
+               $key .= $charset[(mt_rand(0,(strlen($charset)-1)))];\r
+       \r
+       return $key;\r
+}\r
+\r
+// Main process\r
+if (isset($_REQUEST['auto_enroll_id'])) $auto_enroll_id = $_REQUEST['auto_enroll_id'];\r
+else $auto_enroll_id = 0;\r
+\r
+if (isset($_POST['save']) || isset($_POST['add'])) \r
+{\r
+       /* insert or update a category */\r
+//     $cat_parent_id  = intval($_POST['cat_parent_id']);\r
+       $name       = trim($_POST['name']);\r
+\r
+       $name  = $addslashes($name);\r
+\r
+       $name = validate_length($name, 50);\r
+\r
+       if (isset($_POST['add']) && !$_POST['add_ids'])\r
+                       $msg->addError('NO_ITEM_SELECTED');\r
+                       \r
+       if (!$msg->containsErrors()) \r
+       {\r
+               if ($auto_enroll_id == 0)\r
+               {\r
+                       $sql = "INSERT INTO ".TABLE_PREFIX."auto_enroll(associate_string, name) \r
+                               VALUES ('". get_random_string(6, 10) ."', '". $name ."')";\r
+                       $result = mysql_query($sql, $db) or die(mysql_error());\r
+                       $auto_enroll_id = mysql_insert_id($db);\r
+                       write_to_log(AT_ADMIN_LOG_INSERT, 'auto_enroll', mysql_affected_rows($db), $sql);\r
+               }\r
+               else\r
+               {\r
+                       $sql = "UPDATE ".TABLE_PREFIX."auto_enroll\r
+                                  SET name = '". $name ."'\r
+                                WHERE auto_enroll_id = ".$auto_enroll_id;\r
+                       \r
+                       $result = mysql_query($sql, $db);\r
+\r
+                       write_to_log(AT_ADMIN_LOG_UPDATE, 'auto_enroll', mysql_affected_rows($db), $sql);\r
+               }\r
+               \r
+               if (isset($_POST['add'])) \r
+               {\r
+                       foreach ($_POST['add_ids'] as $elem) \r
+                       {\r
+                               $sql = "SELECT count(*) cnt FROM ".TABLE_PREFIX."auto_enroll_courses\r
+                                        WHERE auto_enroll_id = ".$auto_enroll_id ."\r
+                                          AND course_id = ". $elem;\r
+                               $result = mysql_query($sql, $db) or die(mysql_error());\r
+                               $row = mysql_fetch_assoc($result);\r
+                               \r
+                               if ($row["cnt"] == 0)\r
+                               {\r
+                                       $sql = "INSERT INTO ".TABLE_PREFIX."auto_enroll_courses (auto_enroll_id, course_id)\r
+                                               VALUES (" . $auto_enroll_id .", " . $elem . ")";\r
+                                       $result = mysql_query($sql, $db) or die(mysql_error());\r
+                       \r
+                                       write_to_log(AT_ADMIN_LOG_INSERT, 'auto_enroll_courses', mysql_affected_rows($db), $sql);\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+\r
+               if (isset($_POST["save"]))\r
+               {\r
+                       header('Location: auto_enroll.php');\r
+                       exit;\r
+               }\r
+       }\r
+} \r
+else if (isset($_POST['delete'])) \r
+{\r
+       if (!$_POST['delete_ids'])\r
+               $msg->addError('NO_ITEM_SELECTED');\r
+               \r
+       if (!$msg->containsErrors()) \r
+       {\r
+               foreach ($_POST['delete_ids'] as $elem) \r
+               {\r
+                       $sql = "DELETE FROM ".TABLE_PREFIX."auto_enroll_courses\r
+                               WHERE auto_enroll_courses_id = " . $elem;\r
+//                     print $sql."<br>";\r
+                       $result = mysql_query($sql, $db) or die(mysql_error());\r
+               }\r
+\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+               \r
+               write_to_log(AT_ADMIN_LOG_DELETE, 'auto_enroll_courses', mysql_affected_rows($db), $sql);\r
+       }\r
+}\r
+else if (isset($_POST['cancel'])) \r
+{\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: auto_enroll.php');\r
+       exit;\r
+}\r
+\r
+/* $categories[category_id] = array(cat_name, cat_parent, num_courses, [array(children)]) */\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+$msg->printAll();\r
+\r
+// existing auto enrollment\r
+if ($auto_enroll_id > 0)\r
+{\r
+       $sql = "SELECT * FROM ".TABLE_PREFIX."auto_enroll\r
+                WHERE auto_enroll_id = " . $auto_enroll_id;\r
+\r
+       $result = mysql_query($sql, $db) or die(mysql_error());\r
+       $row = mysql_fetch_assoc($result);\r
+}\r
+?>\r
+\r
+<form action ="<?php echo $_SERVER['PHP_SELF']; ?>?auto_enroll_id=<?php echo $auto_enroll_id; ?>" method="post" name="form">\r
+<input type="hidden" name="form_submit" value="1" />\r
+\r
+<div class="input-form">\r
+       <div class="row">\r
+               <h4><label for="name"><?php echo _AT('title'); ?></label><br /></h4>\r
+               <input type="text" id="name" name="name" size="30" value="<?php echo htmlspecialchars($row['name']); ?>" />\r
+       </div>\r
+\r
+<?php\r
+$existing_courses = array();\r
+\r
+$cats  = array();\r
+$cats[0] = _AT('cats_uncategorized');\r
+\r
+$sql = "SELECT cat_id, cat_name FROM ".TABLE_PREFIX."course_cats";\r
+$result = mysql_query($sql,$db);\r
+while($row = mysql_fetch_array($result)) {\r
+       $cats[$row['cat_id']] = $row['cat_name'];\r
+}\r
+\r
+// display existing courses if auto_enroll_id is given\r
+// don't display this section when creating new record\r
+?>\r
+       <div class="row">\r
+               <h4><?php echo _AT('course_to_auto_enroll'); ?><br /></h4>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <table summary="" class="data" rules="cols" align="left" style="width: 95%;">\r
+               \r
+               <thead>\r
+               <tr>\r
+                       <th scope="col"><input type="checkbox" value="<?php echo _AT('select_all'); ?>" id="all_delete" title="<?php echo _AT('select_all'); ?>" name="selectall_delete" onclick="CheckAll('delete_ids[]', 'selectall_delete');" /></th>\r
+                       <th scope="col"><?php echo _AT('title'); ?></th>\r
+                       <th scope="col"><?php echo _AT('category'); ?></th>\r
+               </tr>\r
+               </thead>\r
+\r
+               <tfoot>\r
+               <tr>\r
+                       <td colspan="4">\r
+                               <div class="buttons" style="float:left">\r
+                               <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /> \r
+                               </div>\r
+                       </td>\r
+               </tr>\r
+               </tfoot>\r
+\r
+               <tbody>\r
+<?php\r
+$num_of_rows = 0;\r
+\r
+if ($auto_enroll_id > 0)\r
+{\r
+       $sql_courses = "SELECT auto_enroll_courses.auto_enroll_courses_id auto_enroll_courses_id, \r
+                              auto_enroll_courses.course_id,\r
+                              courses.cat_id,\r
+                              courses.title title\r
+                         FROM " . TABLE_PREFIX."auto_enroll_courses auto_enroll_courses, " . TABLE_PREFIX ."courses courses \r
+                        where auto_enroll_courses.auto_enroll_id=".$auto_enroll_id .\r
+                      "   and auto_enroll_courses.course_id = courses.course_id";\r
+\r
+       $result_courses = mysql_query($sql_courses, $db) or die(mysql_error());\r
+       \r
+       $num_of_rows = mysql_num_rows($result_courses);\r
+       \r
+       if ($row_courses = mysql_fetch_assoc($result_courses))\r
+       do {\r
+               $existing_courses[] = $row_courses["course_id"];\r
+       ?>\r
+                       <tr onmousedown="document.form['m<?php echo $row_courses['auto_enroll_courses_id']; ?>'].checked = !document.form['m<?php echo $row_courses['auto_enroll_courses_id']; ?>'].checked; togglerowhighlight(this, 'm<?php echo $row_courses['auto_enroll_courses_id']; ?>');" id="rm<?php echo $row_courses['auto_enroll_courses_id']; ?>">\r
+                               <td width="10"><label for="tm<?php echo $row_courses['auto_enroll_courses_id']; ?>"><input type="checkbox" name="delete_ids[]" value="<?php echo $row_courses['auto_enroll_courses_id']; ?>" id="m<?php echo $row_courses['auto_enroll_courses_id']; ?>" onmouseup="this.checked=!this.checked" /></label></td>\r
+                               <td id="tm<?php echo $row_courses['auto_enroll_courses_id']; ?>"><?php echo $row_courses['title']; ?></td>\r
+                               <td><?php echo $cats[$row_courses['cat_id']]; ?></td>\r
+                       </tr>\r
+       <?php } while ($row_courses = mysql_fetch_assoc($result_courses)); ?>\r
+<?php \r
+}\r
+\r
+if ($num_of_rows == 0 || !isset($auto_enroll_id))\r
+{ \r
+?>\r
+                       <tr>\r
+                               <td colspan="3"><?php echo _AT('none_found'); ?></td>\r
+                       </tr>\r
+<?php \r
+}\r
+?>\r
+               </tbody>\r
+       </table>\r
+       </div>\r
+\r
+       <div class="row">\r
+               &nbsp;\r
+       </div>\r
+       \r
+       <div class="row buttons">\r
+               <input type="submit" name="save" value="<?php echo _AT('save'); ?>" accesskey="s" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>"  />\r
+       </div>\r
+</div>\r
+\r
+<? require("auto_enroll_filter_courses.php"); ?>\r
+\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>\r
diff --git a/admin/auto_enroll_filter_courses.php b/admin/auto_enroll_filter_courses.php
new file mode 100644 (file)
index 0000000..14d0524
--- /dev/null
@@ -0,0 +1,215 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+require(AT_INCLUDE_PATH.'lib/admin_categories.inc.php');\r
+\r
+if ($_POST['reset_filter']) { unset($_POST); }\r
+\r
+$page_string = '';\r
+\r
+if (isset($_POST['access']) && in_array($_POST['access'], array('public','private','protected'))) {\r
+       $page_string .= SEP.'access='.$_POST['access'];\r
+       $sql_access = "='{$_POST['access']}'";\r
+} else {\r
+       $sql_access     = '<>-1';\r
+       $_POST['access'] = '';\r
+}\r
+\r
+if (isset($_POST['category']) && ($_POST['category'] > -1)) {\r
+       $_POST['category'] = intval($_POST['category']);\r
+       $page_string .= SEP.'category='.$_POST['category'];\r
+       $sql_category = '='.$_POST['category'];\r
+} else {\r
+       $sql_category     = '<>-1';\r
+       $_POST['category'] = -1; // all (because 0 = uncategorized)\r
+}\r
+\r
+if (isset($_POST['include']) && $_POST['include'] == 'one') {\r
+       $checked_include_one = ' checked="checked"';\r
+       $page_string .= SEP.'include=one';\r
+} else {\r
+       $_POST['include'] = 'all';\r
+       $checked_include_all = ' checked="checked"';\r
+       $page_string .= SEP.'include=all';\r
+}\r
+\r
+if (!empty($_POST['search'])) {\r
+       $page_string .= SEP.'search='.urlencode($stripslashes($_POST['search']));\r
+       $search = $addslashes($_POST['search']);\r
+       $search = explode(' ', $search);\r
+\r
+       if ($_POST['include'] == 'all') {\r
+               $predicate = 'AND ';\r
+       } else {\r
+               $predicate = 'OR ';\r
+       }\r
+\r
+       $sql_search = '';\r
+       foreach ($search as $term) {\r
+               $term = trim($term);\r
+               $term = str_replace(array('%','_'), array('\%', '\_'), $term);\r
+               if ($term) {\r
+                       $term = '%'.$term.'%';\r
+                       $sql_search .= "((title LIKE '$term') OR (description LIKE '$term')) $predicate";\r
+               }\r
+       }\r
+       $sql_search = '('.substr($sql_search, 0, -strlen($predicate)).')';\r
+} else {\r
+       $sql_search = '1';\r
+}\r
+\r
+$sql   = "SELECT * FROM ".TABLE_PREFIX."courses WHERE access $sql_access AND cat_id $sql_category AND $sql_search AND hide=0 ORDER BY title";\r
+$courses_result = mysql_query($sql, $db);\r
+\r
+// calculate number of results found\r
+$num_results = mysql_num_rows($courses_result);\r
+\r
+while ($row = mysql_fetch_assoc($courses_result)) \r
+       if (in_array($row['course_id'], $existing_courses)) $num_results--;\r
+\r
+if ($num_results > 0) mysql_data_seek($courses_result, 0);\r
+\r
+// get the categories <select>, if there are any.\r
+// we need ob_start/ob_clean, because select_categories() outputs directly.\r
+// we do this so that if there are no categories, then the option doesn't appear.\r
+ob_start();\r
+select_categories(get_categories(), 0, $_POST['category'], false);\r
+$categories_select = ob_get_contents();\r
+ob_clean();\r
+\r
+$has_categories = false;\r
+if ($categories_select != '<option value="0"></option>') {\r
+       $has_categories = true;\r
+}\r
+\r
+?>\r
+       <div class="input-form">\r
+               <div class="row">\r
+                       <h4><?php echo _AT('results_found', $num_results); ?></h4>\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <?php echo _AT('access'); ?><br />\r
+                       <input type="radio" name="access" value="private" id="s1" <?php if ($_POST['access'] == 'private') { echo 'checked="checked"'; } ?> /><label for="s1"><?php echo _AT('private'); ?></label> \r
+\r
+                       <input type="radio" name="access" value="protected" id="s2" <?php if ($_POST['access'] == 'protected') { echo 'checked="checked"'; } ?> /><label for="s2"><?php echo _AT('protected'); ?></label>\r
+\r
+                       <input type="radio" name="access" value="public" id="s3" <?php if ($_POST['access'] == 'public') { echo 'checked="checked"'; } ?> /><label for="s3"><?php echo _AT('public'); ?></label>\r
+\r
+                       <input type="radio" name="access" value="" id="s" <?php if ($_POST['access'] == '') { echo 'checked="checked"'; } ?> /><label for="s"><?php echo _AT('all'); ?></label>\r
+               </div>\r
+\r
+               <?php if ($has_categories): ?>\r
+               <div class="row">\r
+                       <label for="category"><?php echo _AT('category'); ?></label><br/>\r
+                       <select name="category" id="category">\r
+                               <option value="-1">- - - <?php echo _AT('cats_all'); ?> - - -</option>\r
+                               <option value="0" <?php if ($_POST['category'] == 0) { echo 'selected="selected"'; } ?>>- - - <?php echo _AT('cats_uncategorized'); ?> - - -</option>\r
+                               <?php echo $categories_select; ?>\r
+                       </select>\r
+               </div>\r
+               <?php endif; ?>\r
+\r
+               <div class="row">\r
+                       <label for="search"><?php echo _AT('search'); ?> (<?php echo _AT('title').', '._AT('description'); ?>)</label><br />\r
+\r
+                       <input type="text" name="search" id="search" size="40" value="<?php echo htmlspecialchars($_POST['search']); ?>" />\r
+                       <br/>\r
+                       <?php echo _AT('search_match'); ?>:\r
+                       <input type="radio" name="include" value="all" id="match_all" <?php echo $checked_include_all; ?> /><label for="match_all"><?php echo _AT('search_all_words'); ?></label> \r
+                       <input type="radio" name="include" value="one" id="match_one" <?php echo $checked_include_one; ?> /><label for="match_one"><?php echo _AT('search_any_word'); ?></label>\r
+               </div>\r
+\r
+               <div class="row buttons">\r
+                       <input type="submit" name="filter" value="<?php echo _AT('filter'); ?>"/>\r
+                       <input type="submit" name="reset_filter" value="<?php echo _AT('reset_filter'); ?>"/>\r
+               </div>\r
+\r
+               <div class="row">\r
+               <table summary="" class="data" rules="cols" align="left" style="width: 95%;">\r
+               \r
+               <thead>\r
+               <tr>\r
+                       <th scope="col"><input type="checkbox" value="<?php echo _AT('select_all'); ?>" id="all_add" title="<?php echo _AT('select_all'); ?>" name="selectall_add" onclick="CheckAll('add_ids[]', 'selectall_add');" /></th>\r
+                       <th scope="col"><?php echo _AT('title'); ?></th>\r
+                       <th scope="col"><?php echo _AT('category'); ?></th>\r
+               </tr>\r
+               </thead>\r
+\r
+               <tfoot>\r
+               <tr>\r
+                       <td colspan="4">\r
+                               <div class="buttons" style="float:left">\r
+                               <input type="submit" name="add" value="<?php echo _AT('add'); ?>" /> \r
+                               </div>\r
+                       </td>\r
+               </tr>\r
+               </tfoot>\r
+\r
+               <tbody>\r
+<?php\r
+if ($num_results == 0)\r
+{\r
+?>\r
+               <tr>\r
+                       <td colspan="3"><?php echo _AT('none_found'); ?></td>\r
+               </tr>\r
+<?php \r
+}\r
+else if ($row = mysql_fetch_assoc($courses_result)) \r
+       do {\r
+               if (!in_array($row['course_id'], $existing_courses))\r
+               {\r
+       ?>\r
+               <tr onmousedown="document.form['a<?php echo $row['course_id']; ?>'].checked = !document.form['a<?php echo $row['course_id']; ?>'].checked; togglerowhighlight(this, 'a<?php echo $row['course_id']; ?>');" id="ra<?php echo $row['course_id']; ?>">\r
+                       <td width="10"><label for="ta<?php echo $row['course_id']; ?>"><input type="checkbox" name="add_ids[]" value="<?php echo $row['course_id']; ?>" id="a<?php echo $row['course_id']; ?>" onmouseup="this.checked=!this.checked" /></label></td>\r
+                       <td id="ta<?php echo $row['course_id']; ?>"><?php echo $row['title']; ?></td>\r
+                       <td><?php echo $cats[$row['cat_id']]; ?></td>\r
+               </tr>\r
+       <?php \r
+               }\r
+       } while ($row = mysql_fetch_assoc($courses_result)); \r
+?>\r
+               </tbody>\r
+       </table>\r
+       </div>\r
+       \r
+       <div class="row">\r
+               &nbsp;\r
+       </div>\r
+</div>\r
+\r
+<script language="JavaScript" type="text/javascript">\r
+//<!--\r
+function CheckAll(element_name, selectall_name) {\r
+//     alert(document.form.elements.length);\r
+       for (var i=0;i<document.form.elements.length;i++)       {\r
+               var e = document.form.elements[i];\r
+               if ((e.name == element_name) && (e.type=='checkbox')) {\r
+                       e.checked = eval("document.form." + selectall_name + ".checked");\r
+                       togglerowhighlight(document.getElementById("r" + e.id), e.id);\r
+               }\r
+       }\r
+}\r
+\r
+function togglerowhighlight(obj, boxid) {\r
+       if (document.getElementById(boxid).checked) {\r
+               obj.className = 'selected';\r
+       } else {\r
+               obj.className = '';\r
+       }\r
+}\r
+//-->\r
+</script>\r
diff --git a/admin/backup/create.php b/admin/backup/create.php
new file mode 100644 (file)
index 0000000..b969f9b
--- /dev/null
@@ -0,0 +1,85 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_BACKUPS);\r
+\r
+$page = 'backups';\r
+$_user_location = 'admin';\r
+\r
+$course = $_POST['course'];\r
+require(AT_INCLUDE_PATH.'classes/Backup/Backup.class.php');\r
+\r
+$Backup =& new Backup($db);\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+\r
+       $Backup->setCourseID($_POST['course']);\r
+       $error = $Backup->create($_POST['description']);\r
+       if ($error !== FALSE) {\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+               header('Location: index.php');\r
+               exit;\r
+       }\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+?>\r
+\r
+\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+\r
+<div class="input-form">\r
+       <div class="row">\r
+               <p><?php echo _AT('create_backup_about', AT_COURSE_BACKUPS); ?></p>\r
+       </div>\r
+\r
+       <?php if ($system_courses): ?>\r
+               <?php if (isset($_POST['submit']) && ($Backup->getNumAvailable() >= AT_COURSE_BACKUPS)): ?>\r
+                       <div class="row">\r
+                               <p><strong><?php echo _AT('max_backups_reached'); ?></strong></p>\r
+                       </div>\r
+               <?php else: ?>\r
+                       <div class="row">\r
+                               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="courses"><?php echo _AT('course'); ?></label><br />\r
+                               <select name="course" id="courses"><?php\r
+                                       foreach ($system_courses as $id => $course) {\r
+                                               echo '<option value="'.$id.'">'.$course['title'].'</option>';\r
+                                       }\r
+                               ?>\r
+                               </select>\r
+                       </div>\r
+                       <div class="row">\r
+                               <label for="desc"><?php echo _AT('optional_description'); ?></label><br />\r
+                               <textarea cols="35" rows="2" id="desc" name="description" scroll="no"></textarea>\r
+                       </div>\r
+                       <div class="row buttons">\r
+                               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>"  /> <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>"  />\r
+                       </div>\r
+               <?php endif; ?>\r
+       <?php else: ?>\r
+               <div class="row">\r
+                       <p><?php echo _AT('no_courses_found'); ?></p>\r
+               </div>\r
+       <?php endif; ?>\r
+</div>\r
+</form>\r
+\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php');  ?>
\ No newline at end of file
diff --git a/admin/backup/delete.php b/admin/backup/delete.php
new file mode 100644 (file)
index 0000000..cd13c9f
--- /dev/null
@@ -0,0 +1,45 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_BACKUPS);\r
+\r
+$page = 'backups';\r
+$_user_location = 'admin';\r
+\r
+if (isset($_POST['submit_yes'])) {\r
+       require_once(AT_INCLUDE_PATH.'classes/Backup/Backup.class.php');\r
+\r
+       $Backup =& new Backup($db, $_POST['course']);\r
+       $Backup->delete($_POST['backup_id']);\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: index.php');\r
+       exit;\r
+} else if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$hidden_vars['backup_id'] = $_GET['backup_id'];\r
+$hidden_vars['course']    = $_GET['course'];\r
+$msg->addConfirm('DELETE', $hidden_vars);\r
+$msg->printConfirm();\r
+\r
+require (AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/admin/backup/edit.php b/admin/backup/edit.php
new file mode 100644 (file)
index 0000000..ddab10f
--- /dev/null
@@ -0,0 +1,68 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_BACKUPS);\r
+\r
+$page = 'backups';\r
+$_user_location = 'admin';\r
+\r
+require(AT_INCLUDE_PATH.'classes/Backup/Backup.class.php');\r
+\r
+$_SESSION['done'] = 0;\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+} \r
+\r
+$Backup =& new Backup($db, $_REQUEST['course']);\r
+$backup_row = $Backup->getRow($_REQUEST['backup_id']);\r
+\r
+if (isset($_POST['edit'])) {\r
+       $Backup->edit($_POST['backup_id'], $_POST['new_description']);\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: index.php');\r
+       exit;\r
+} \r
+\r
+//check for errors\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+?>\r
+\r
+<form name="form1" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" enctype="multipart/form-data" onsubmit="">\r
+<input type="hidden" name="backup_id" value="<?php echo $_GET['backup_id']; ?>" />\r
+<input type="hidden" name="course" value="<?php echo $_GET['course']; ?>" />\r
+\r
+<div class="input-form">\r
+       <div class="row">\r
+               <?php echo _AT('file_name'); ?><br />\r
+               <?php echo _AT('edit_backup', $backup_row['file_name']); ?>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <label for="desc"><?php echo _AT('description'); ?></label><br />\r
+               <textarea cols="30" rows="2" name="new_description" id="desc"><?php echo $backup_row['description']; ?></textarea>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="edit" value="<?php echo _AT('save'); ?>" /> <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php');  ?>
\ No newline at end of file
diff --git a/admin/backup/index.php b/admin/backup/index.php
new file mode 100644 (file)
index 0000000..433a121
--- /dev/null
@@ -0,0 +1,120 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_BACKUPS);
+
+require(AT_INCLUDE_PATH.'classes/Backup/Backup.class.php');
+require(AT_INCLUDE_PATH.'lib/filemanager.inc.php');
+
+if (isset($_POST['backup_id'])) {
+       $ids = explode('_', $_POST['backup_id']);
+       $backup_id = $ids[0];
+       $course    = $ids[1];
+}
+
+if (isset($_POST['restore'], $backup_id)) {
+       header('Location: restore.php?backup_id=' . $backup_id . SEP . 'course=' . $course);
+       exit;
+
+} else if (isset($_POST['download'], $backup_id)) {
+       $Backup =& new Backup($db, $course);
+       $Backup->download($backup_id);
+       exit; // never reached
+
+} else if (isset($_POST['delete'], $backup_id)) {
+       header('Location: delete.php?backup_id=' . $backup_id . SEP . 'course=' . $course);
+       exit;
+
+} else if (isset($_POST['edit'], $backup_id)) {
+       header('Location: edit.php?backup_id=' . $backup_id . SEP . 'course=' . $course);
+       exit;
+} else if (!empty($_POST) && !$backup_id) {
+       $msg->addError('NO_ITEM_SELECTED');
+}
+
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<form name="form1" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<input type="hidden" name="course" value="<?php echo $_REQUEST['course']; ?>" />
+       
+<table class="data" summary="" rules="groups" style="width: 90%">
+<thead>
+       <tr>
+               <th><?php echo _AT('file_name');    ?></th>
+               <th><?php echo _AT('date_created'); ?></th>
+               <th><?php echo _AT('file_size');    ?></th>
+               <th><?php echo _AT('description');  ?></th>
+       </tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="4"><input type="submit" name="restore" value="<?php echo _AT('restore'); ?>" /> 
+                                 <input type="submit" name="download" value="<?php echo _AT('download'); ?>" />  
+                                 <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /> 
+                                 <input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /></td>
+</tr>
+</tfoot>
+<tbody>
+<?php
+       $num_backups = 0;
+       $Backup =& new Backup($db);
+
+       if (isset($_REQUEST['course']) && $_REQUEST['course']) {
+               $course = intval($_REQUEST['course']);
+               $sql    = "SELECT course_id, title FROM ".TABLE_PREFIX."courses WHERE course_id=$course ORDER BY title";
+       } else {
+               $sql    = "SELECT course_id, title FROM ".TABLE_PREFIX."courses ORDER BY title";
+       }
+       $result = mysql_query($sql, $db);
+       while ($course = mysql_fetch_assoc($result)) {
+
+               $Backup->setCourseID($course['course_id']);
+               $list = $Backup->getAvailableList();
+
+               echo '<tr><th colspan="4">'.$course['title'].'</th></tr>';
+
+               if (empty($list)) { ?>
+                       <tr>
+                               <td colspan="4"><?php echo _AT('none_found'); ?></td>
+                       </tr><?php
+                       $num_backups ++;
+
+               } else {
+
+                       foreach ($list as $row) {
+                               echo '<tr onmousedown="document.form1[\'c'.$row['backup_id'].'_'.$row['course_id'].'\'].checked = true; rowselect(this);" id="r_'.$row['backup_id'].'"><td><input type="radio" value="'.$row['backup_id'].'_'.$row['course_id'].'" name="backup_id" id="c'.$row['backup_id'].'_'.$row['course_id'].'" />';
+                               echo '<label for="c'.$row['backup_id'].'_'.$row['course_id'].'">'.$row['file_name'].'</label></td>';
+                               echo '<td>'.AT_date(_AT('filemanager_date_format'), $row['date_timestamp'], AT_DATE_UNIX_TIMESTAMP).'</td>';
+                               echo '<td align="right">'.get_human_size($row['file_size']).'</td>';
+                               echo '<td>'.$row['description'].'</td>';
+                               echo '</tr>';
+                               $num_backups ++;
+                       }
+               }
+       }
+?>
+<?php if (!$num_backups): ?>
+       <tr>
+               <td colspan="4"><?php echo _AT('none_found'); ?></td>
+       </tr>
+<?php endif; ?>
+</tbody>
+</table>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php');  ?>
\ No newline at end of file
diff --git a/admin/backup/restore.php b/admin/backup/restore.php
new file mode 100644 (file)
index 0000000..bb7a340
--- /dev/null
@@ -0,0 +1,124 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_BACKUPS);
+
+require(AT_INCLUDE_PATH.'lib/filemanager.inc.php');
+require(AT_INCLUDE_PATH.'classes/Backup/Backup.class.php');
+
+$page = 'backups';
+$_user_location = 'admin';
+
+if (!isset($_REQUEST['backup_id'])) {
+       header('Location: index.php');
+       exit;
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       if (!$_POST['material']) {
+               $msg->addError(array('EMPTY_FIELDS', _AT('material')));
+       }
+
+       if (!$msg->containsErrors()) {
+               $Backup =& new Backup($db, $_POST['in_course']);
+               $Backup->restore($_POST['material'], $_POST['action'], $_POST['backup_id'], $_POST['course']);
+
+               $msg->addFeedBack('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: index.php');
+               exit;
+       }
+} 
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$Backup =& new Backup($db, $_REQUEST['course']);
+
+$row = $Backup->getRow($_REQUEST['backup_id']);
+
+?>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">
+       <input type="hidden" name="course" value="<?php echo $_REQUEST['course']; ?>" />
+       <input type="hidden" name="backup_id" value="<?php echo $_REQUEST['backup_id']; ?>" />
+
+<div class="input-form">
+       <div class="row">
+               <p><?php echo _AT('restore_backup_about'); ?></p>
+       </div>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><?php echo _AT('material'); ?><br />
+       
+               <input type="checkbox" value="1" name="all" id="all" onclick="javascript:selectAll();" /><label for="all"><?php echo _AT('material_select_all'); ?></label><br /><br />
+
+               <?php
+               $modules = $moduleFactory->getModules(AT_MODULE_STATUS_ENABLED | AT_MODULE_STATUS_DISABLED, 0, TRUE);
+               $keys = array_keys($modules);
+               $i = 0;
+               ?>
+               <?php foreach($keys as $module_name): ?>
+                       <?php $module =& $modules[$module_name]; ?>
+                       <?php if ($module->isBackupable()): ?>
+                               <input type="checkbox" value="1" name="material[<?php echo $module_name; ?>]" id="m<?php echo ++$i; ?>" /><label for="m<?php echo $i; ?>"><?php echo $module->getName(); ?></label><br />
+                       <?php endif; ?>
+               <?php endforeach; ?>
+
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="course"><?php echo _AT('course'); ?></label><br />
+               
+                       <select name="in_course" id="course"><?php
+                                       foreach ($system_courses as $id => $course) {
+                                               echo '<option value="'.$id.'">'.$course['title'].'</option>';
+                                       }
+                       ?></select>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('action'); ?><br />
+               <input type="radio" checked="checked" name="action" value="append" id="append" /><label for="append"><?php echo _AT('append_content'); ?></label><br />
+               
+               <input type="radio" name="action" value="overwrite" id="overwrite" /><label for="overwrite"><?php echo _AT('overwite_content'); ?></label><br />
+               <br />
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('restore'); ?>" /> <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+</div>
+</form>
+<?php $i=0; ?>
+<script language="javascript" type="text/javascript">
+       
+       function selectAll() {
+               if (document.form.all.checked == true) {
+                       <?php foreach($keys as $module_name): $module =& $modules[$module_name]; if ($module->isBackupable()): ?>
+                               document.form.m<?php echo ++$i; ?>.checked = true;
+                       <?php endif; endforeach; ?>
+               } else {
+                       <?php $i=0;?>
+                       <?php foreach($keys as $module_name): $module =& $modules[$module_name]; if ($module->isBackupable()): ?>
+                               document.form.m<?php echo ++$i; ?>.checked = false;
+                       <?php endif; endforeach; ?>
+
+               }
+       }
+</script>
+<?php require (AT_INCLUDE_PATH.'footer.inc.php');  ?>
\ No newline at end of file
diff --git a/admin/config_edit.php b/admin/config_edit.php
new file mode 100644 (file)
index 0000000..daa9263
--- /dev/null
@@ -0,0 +1,351 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);
+
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $missing_fields = array();
+
+       $_POST['site_name']          = trim($_POST['site_name']);
+       $_POST['home_url']           = trim($_POST['home_url']);
+       $_POST['default_language']   = trim($_POST['default_language']);
+       $_POST['contact_email']      = trim($_POST['contact_email']);
+       $_POST['max_file_size']      = intval($_POST['max_file_size']);
+       $_POST['max_file_size']      = max(0, $_POST['max_file_size']);
+       $_POST['max_course_size']    = intval($_POST['max_course_size']);
+       $_POST['max_course_size']    = max(0, $_POST['max_course_size']);
+       $_POST['max_course_float']   = intval($_POST['max_course_float']);
+       $_POST['max_course_float']   = max(0, $_POST['max_course_float']);
+       $_POST['master_list']        = intval($_POST['master_list']);
+       $_POST['email_confirmation'] = intval($_POST['email_confirmation']);
+       $_POST['email_notification'] = intval($_POST['email_notification']);
+       $_POST['sent_msgs_ttl']      = intval($_POST['sent_msgs_ttl']);
+       $_POST['allow_instructor_requests'] = intval($_POST['allow_instructor_requests']);
+       $_POST['auto_approve_instructors']  = intval($_POST['auto_approve_instructors']);
+       $_POST['theme_categories']          = intval($_POST['theme_categories']);
+       $_POST['user_notes']                = intval($_POST['user_notes']);
+       $_POST['illegal_extentions']        = str_replace(array('  ', ' '), array(' ','|'), $_POST['illegal_extentions']);
+       $_POST['cache_dir']                 = trim($_POST['cache_dir']);
+       $_POST['course_backups']            = intval($_POST['course_backups']);
+       $_POST['course_backups']            = max(0, $_POST['course_backups']);
+       $_POST['check_version']             = $_POST['check_version'] ? 1 : 0;
+       $_POST['fs_versioning']             = $_POST['fs_versioning'] ? 1 : 0;
+       $_POST['enable_mail_queue']         = $_POST['enable_mail_queue'] ? 1 : 0;
+       $_POST['display_name_format']       = intval($_POST['display_name_format']);
+       $_POST['pretty_url']                            = intval($_POST['pretty_url']);
+       $_POST['course_dir_name']                       = intval($_POST['course_dir_name']);
+       
+       //apache_mod_rewrite can only be enabled if pretty_url is.
+       if ($_POST['pretty_url']==1){
+               $_POST['apache_mod_rewrite']            = intval($_POST['apache_mod_rewrite']);
+       } else {
+               $_POST['apache_mod_rewrite'] = 0;
+       }
+
+       if (!isset($display_name_formats[$_POST['display_name_format']])) {
+               $_POST['display_name_format'] = $_config_defaults['display_name_format'];
+       }
+
+       //check that all values have been set   
+       if (!$_POST['site_name']) {
+               $missing_fields[] = _AT('site_name');
+       }
+
+       /* email check */
+       if (!$_POST['contact_email']) {
+               $missing_fields[] = _AT('contact_email');
+       } else if (!eregi("^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$", $_POST['contact_email'])) {
+               $msg->addError('EMAIL_INVALID');        
+       }
+
+       if ($_POST['cache_dir']) {
+               if (!is_dir($_POST['cache_dir'])) {
+                       $msg->addError('CACHE_DIR_NOT_EXIST');
+               } else if (!is_writable($_POST['cache_dir'])){
+                       $msg->addError('CACHE_DIR_NOT_WRITEABLE');
+               }
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['site_name']     = $addslashes($_POST['site_name']);
+               $_POST['home_url']      = $addslashes($_POST['home_url']);
+               $_POST['default_language']      = $addslashes($_POST['default_language']);
+               $_POST['contact_email'] = $addslashes($_POST['contact_email']);
+               $_POST['time_zone']     = $addslashes($_POST['time_zone']);
+
+               foreach ($_config as $name => $value) {
+                       // the isset() is needed to avoid overridding settings that don't get set here (ie. modules)
+                       if (isset($_POST[$name]) && (stripslashes($_POST[$name]) != $value) && (stripslashes($_POST[$name]) != $_config_defaults[$name])) {
+                               $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('$name', '$_POST[$name]')";
+                               mysql_query($sql, $db);
+                               write_to_log(AT_ADMIN_LOG_REPLACE, 'config', mysql_affected_rows($db), $sql);
+                       } else if (isset($_POST[$name]) && (stripslashes($_POST[$name]) == $_config_defaults[$name])) {
+                               $sql = "DELETE FROM ".TABLE_PREFIX."config WHERE name='$name'";
+                               mysql_query($sql, $db);
+                               write_to_log(AT_ADMIN_LOG_DELETE, 'config', mysql_affected_rows($db), $sql);
+                       }
+               }
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+
+               // special case: disabling the mail queue should flush all queued mail:
+               if (!$_POST['enable_mail_queue'] && $_POST['old_enable_mail_queue']) {
+                       require_once(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+                       $mail = new ATutorMailer;
+                       $mail->SendQueue();
+               }
+
+               header('Location: '.$_SERVER['PHP_SELF']);
+               exit;
+       }
+}
+
+$onload = 'document.form.sitename.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if (!isset($_POST['submit'])) {
+
+} else {
+       $defaults = $_POST;
+}
+?>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">
+<div class="input-form">
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="sitename"><?php echo _AT('site_name'); ?></label><br />
+               <input type="text" name="site_name" size="40" maxlength="60" id="sitename" value="<?php if (!empty($_POST['site_name'])) { echo $stripslashes(htmlspecialchars($_POST['site_name'])); } else { echo $_config['site_name']; } ?>" />
+       </div>
+
+       <div class="row">
+               <label for="home_url"><?php echo _AT('home_url'); ?></label><br />
+
+               <input type="text" name="home_url" size="50" maxlength="60" id="home_url" value="<?php if (!empty($_POST['home_url'])) { echo $stripslashes(htmlspecialchars($_POST['home_url'])); } else { echo $_config['home_url']; } ?>"  />
+       </div>
+
+       <div class="row">
+               <label for="default_lang"><?php echo _AT('default_language'); ?></label><br />
+
+               <?php if (!empty($_POST['default_language'])) { 
+                               $select_lang = $_POST['default_language']; 
+                       } else { 
+                               $select_lang = $_config['default_language'];
+                       } ?>
+               <?php if ($disabled): ?>
+                       <select name="default_language" id="default_lang" disabled="disabled"><option><?php echo $select_lang; ?></option></select>
+               <?php else: ?>
+                       <?php $languageManager->printDropdown($select_lang, 'default_language', 'default_lang'); ?>
+               <?php endif; ?>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="cemail"><?php echo _AT('contact_email'); ?></label><br />
+               <input type="text" name="contact_email" id="cemail" size="40" value="<?php if (!empty($_POST['email'])) { echo $stripslashes(htmlspecialchars($_POST['email'])); } else { echo $_config['contact_email']; } ?>"  />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="time_zone"><?php echo _AT('time_zone'); ?></label><br />
+                       <?php
+                               $sql = "SELECT Name FROM mysql.time_zone_name ORDER BY Name";
+                               $result = @mysql_query($sql, $db);
+                       ?>
+                       <?php if ($result && mysql_num_rows($result)): ?>
+                               <select name="time_zone" id="time_zone">
+                                       <option value="" <?php if (!$_config['time_zone']) { echo 'selected="selected"'; } ?>><?php echo _AT('use_system_time'); ?></option>
+                                       <option value=""></option>
+                                       <?php while ($row = mysql_fetch_assoc($result)): ?>
+                                               <option <?php if ($_config['time_zone'] == $row['Name']) { echo 'selected="selected"'; } ?>><?php echo $row['Name']; ?></option>
+                                       <?php endwhile; ?>
+                               </select>
+                       <?php else: ?>
+                               <?php echo _AT('time_zones_not_supported'); ?>
+                       <?php endif; ?>
+       </div>
+
+       <div class="row">
+               <label for="maxfile"><?php echo _AT('maximum_file_size'); ?></label> (<?php echo _AT('default'); ?>: <?php echo $_config_defaults['max_file_size']; ?>)<br />
+               <input type="text" size="10" name="max_file_size" id="maxfile" value="<?php if (!empty($_POST['max_file_size'])) { echo $stripslashes(htmlspecialchars($_POST['max_file_size'])); } else { echo $_config['max_file_size']; } ?>"  /> <?php echo _AT('bytes'); ?>
+       </div>
+
+       <div class="row">
+               <label for="maxcourse"><?php echo _AT('maximum_course_size'); ?></label> (<?php echo _AT('default'); ?>: <?php echo $_config_defaults['max_course_size']; ?>)<br />
+               <input type="text" size="10" name="max_course_size" id="maxcourse" value="<?php if (!empty($_POST['max_course_size'])) { echo $stripslashes(htmlspecialchars($_POST['max_course_size'])); } else { echo $_config['max_course_size']; } ?>"  /> <?php echo _AT('bytes'); ?>
+       </div>
+
+       <div class="row">
+               <label for="float"><?php echo _AT('maximum_course_float'); ?></label> (<?php echo _AT('default'); ?>: <?php echo $_config_defaults['max_course_float']; ?>)<br />
+               <input type="text" size="10" name="max_course_float" id="float" value="<?php if (!empty($_POST['max_course_float'])) { echo $stripslashes(htmlspecialchars($_POST['max_course_float'])); } else { echo $_config['max_course_float']; } ?>"  /> <?php echo _AT('bytes'); ?>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('display_name_format'); ?> (<?php echo _AT('default'); ?>: <em><?php echo _AT($display_name_formats[$_config_defaults['display_name_format']], _AT('login_name'), _AT('first_name'), _AT('second_name'), _AT('last_name')); ?></em>)<br />
+               <?php foreach ($display_name_formats as $key => $value): ?>
+                       <input type="radio" name="display_name_format" value="<?php echo $key; ?>" id="dnf<?php echo $key; ?>" <?php if ($_config['display_name_format'] == $key) { echo 'checked="checked"'; }?> /><label for="dnf<?php echo $key; ?>"><em><?php echo _AT($value, _AT('login_name'), _AT('first_name'), _AT('second_name'), _AT('last_name')); ?></em></label><br />
+               <?php endforeach; ?>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('master_list_authentication'); ?> (<?php echo _AT('default'); ?>: <?php echo ($_config_defaults['master_list'] ? _AT('enable') : _AT('disable')); ?>)<br />
+               <input type="radio" name="master_list" value="1" id="ml_y" <?php if ($_config['master_list']) { echo 'checked="checked"'; }?>  /><label for="ml_y"><?php echo _AT('enable'); ?></label> 
+
+               <input type="radio" name="master_list" value="0" id="ml_n" <?php if(!$_config['master_list']) { echo 'checked="checked"'; }?>  /><label for="ml_n"><?php echo $disable_on . _AT('disable') . $disable_off; ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('require_email_confirmation'); ?> (<?php echo _AT('default'); ?>: <?php echo ($_config_defaults['require_email_confirmation'] ? _AT('enable') : _AT('disable')); ?>)<br />
+               <input type="radio" name="email_confirmation" value="1" id="ec_y" <?php if ($_config['email_confirmation']) { echo 'checked="checked"'; }?>  /><label for="ec_y"><?php echo _AT('enable'); ?></label> <input type="radio" name="email_confirmation" value="0" id="ec_n" <?php if(!$_config['email_confirmation']) { echo 'checked="checked"'; }?>  /><label for="ec_n"><?php echo _AT('disable'); ?></label>
+       </div>
+               
+       <div class="row">
+               <?php echo _AT('allow_instructor_requests'); ?> (<?php echo _AT('default'); ?>: <?php echo ($_config_defaults['allow_instructor_requests'] ? _AT('enable') : _AT('disable')); ?>)<br />
+               <input type="radio" name="allow_instructor_requests" value="1" id="air_y" <?php if($_config['allow_instructor_requests']) { echo 'checked="checked"'; }?>  /><label for="air_y"><?php echo _AT('enable'); ?></label> <input type="radio" name="allow_instructor_requests" value="0" id="air_n" <?php if(!$_config['allow_instructor_requests']) { echo 'checked="checked"'; }?>  /><label for="air_n"><?php echo _AT('disable'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('instructor_request_email_notification'); ?> (<?php echo _AT('default'); ?>: <?php echo ($_config_defaults['email_notification'] ? _AT('enable') : _AT('disable')); ?>)<br />
+               <input type="radio" name="email_notification" value="1" id="en_y" <?php if ($_config['email_notification']) { echo 'checked="checked"'; }?>  /><label for="en_y"><?php echo _AT('enable'); ?></label> <input type="radio" name="email_notification" value="0" id="en_n" <?php if(!$_config['email_notification']) { echo 'checked="checked"'; }?>  /><label for="en_n"><?php echo _AT('disable'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('auto_approve_instructors'); ?> (<?php echo _AT('default'); ?>: <?php echo ($_config_defaults['auto_approve_instructors'] ? _AT('enable') : _AT('disable')); ?>)<br />
+               <input type="radio" name="auto_approve_instructors" value="1" id="aai_y" <?php if($_config['auto_approve_instructors']) { echo 'checked="checked"'; }?>  /><label for="aai_y"><?php echo _AT('enable'); ?></label> <input type="radio" name="auto_approve_instructors" value="0" id="aai_n" <?php if(!$_config['auto_approve_instructors']) { echo 'checked="checked"'; }?>  /><label for="aai_n"><?php echo _AT('disable'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('theme_specific_categories'); ?> (<?php echo _AT('default'); ?>: <?php echo ($_config_defaults['theme_categories'] ? _AT('enable') : _AT('disable')); ?>)<br />
+               <input type="radio" name="theme_categories" value="1" id="tc_y" <?php if($_config['theme_categories']) { echo 'checked="checked"'; }?>  /><label for="tc_y"><?php echo _AT('enable'); ?></label> <input type="radio" name="theme_categories" value="0" id="tc_n" <?php if(!$_config['theme_categories']) { echo 'checked="checked"'; }?>  /><label for="tc_n"><?php echo _AT('disable'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('user_contributed_notes'); ?> (<?php echo _AT('default'); ?>: <?php echo ($_config_defaults['user_notes'] ? _AT('enable') : _AT('disable')); ?>)<br />
+               <input type="radio" name="user_notes" value="1" id="un_y" <?php if($_config['user_notes']) { echo 'checked="checked"'; }?>  /><label for="un_y"><?php echo _AT('enable'); ?></label> <input type="radio" name="user_notes" value="0" id="un_n" <?php if(!$_config['user_notes']) { echo 'checked="checked"'; }?>  /><label for="un_n"><?php echo _AT('disable'); ?></label>
+       </div>
+
+       <div class="row">
+               <label for="ext"><?php echo _AT('illegal_file_extensions'); ?></label><br />
+               <textarea name="illegal_extentions" cols="24" id="ext" rows="2" class="formfield" ><?php if ($_config['illegal_extentions']) { echo str_replace('|',' ',$_config['illegal_extentions']); }?></textarea>
+       </div>
+
+       <div class="row">
+               <label for="cache"><?php echo _AT('cache_directory'); ?></label><br />
+               <input type="text" name="cache_dir" id="cache" size="40" value="<?php if (!empty($_POST['cache_dir'])) { echo $stripslashes(htmlspecialchars($_POST['cache_dir'])); } else { echo $_config['cache_dir']; } ?>"  />
+       </div>
+
+       <div class="row">
+               <label for="course_backups"><?php echo _AT('course_backups'); ?></label> (<?php echo _AT('default'); ?>: <?php echo $_config_defaults['course_backups']; ?>)<br />
+               <input type="text" size="2" name="course_backups" id="course_backups" value="<?php if (!empty($_POST['course_backups'])) { echo $stripslashes(htmlspecialchars($_POST['course_backups'])); } else { echo $_config['course_backups']; } ?>"  />
+       </div>
+
+       <div class="row">
+               <label for="sent_msgs_ttl"><?php echo _AT('sent_msgs_ttl_text'); ?></label> (<?php echo _AT('default'); ?>: <?php echo $_config_defaults['sent_msgs_ttl']; ?>)<br />
+               <input type="text" size="3" name="sent_msgs_ttl" id="sent_msgs_ttl" value="<?php if (!empty($_POST['sent_msgs_ttl'])) { echo intval($_POST['sent_msgs_ttl']); } else { echo $_config['sent_msgs_ttl']; } ?>"  />
+       </div>
+
+       <div class="row">
+               <?php echo _AT('auto_check_new_version'); ?> (<?php echo _AT('default'); ?>: <?php echo ($_config_defaults['check_version'] ? _AT('enable') : _AT('disable')); ?>)<br />
+               <input type="radio" name="check_version" value="1" id="cv_y" <?php if($_config['check_version']) { echo 'checked="checked"'; }?>  /><label for="cv_y"><?php echo _AT('enable'); ?></label> <input type="radio" name="check_version" value="0" id="cv_n" <?php if(!$_config['check_version']) { echo 'checked="checked"'; }?>  /><label for="cv_n"><?php echo _AT('disable'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('file_storage_version_control'); ?> (<?php echo _AT('default'); ?>: <?php echo ($_config_defaults['fs_versioning'] ? _AT('enable') : _AT('disable')); ?>)<br />
+               <input type="radio" name="fs_versioning" value="1" id="cf_y" <?php if($_config['fs_versioning']) { echo 'checked="checked"'; }?>  /><label for="cf_y"><?php echo _AT('enable'); ?></label> <input type="radio" name="fs_versioning" value="0" id="cf_n" <?php if(!$_config['fs_versioning']) { echo 'checked="checked"'; }?>  /><label for="cf_n"><?php echo _AT('disable'); ?></label>
+       </div>
+
+       <div class="row">
+               <input type="hidden" name="old_enable_mail_queue" value="<?php echo $_config['enable_mail_queue']; ?>" />
+               <?php echo _AT('enable_mail_queue'); ?> (<?php echo _AT('default'); ?>: <?php echo ($_config_defaults['enable_mail_queue'] ? _AT('enable') : _AT('disable')); ?>)<br />
+               <?php echo _AT('mail_queue_cron'); ?><br />
+               <?php if (!$_config['last_cron'] || (time() - (int) $_config['last_cron'] > 2 * 60 * 60)): ?>
+                       <input type="radio" name="enable_mail_queue" value="1" disabled="disabled" /><?php echo _AT('enable'); ?> <input type="radio" name="enable_mail_queue" value="0" id="mq_n" checked="checked" /><label for="mq_n"><?php echo _AT('disable'); ?></label>
+               <?php else: ?>
+                       <input type="radio" name="enable_mail_queue" value="1" id="mq_y" <?php if($_config['enable_mail_queue']) { echo 'checked="checked"'; }?>  /><label for="mq_y"><?php echo _AT('enable'); ?></label> <input type="radio" name="enable_mail_queue" value="0" id="mq_n" <?php if(!$_config['enable_mail_queue']) { echo 'checked="checked"'; }?>  /><label for="mq_n"><?php echo _AT('disable'); ?></label>
+               <?php endif; ?>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('auto_install_languages'); ?> (<?php echo _AT('default'); ?>: <?php echo ($_config_defaults['auto_install_languages'] ? _AT('enable') : _AT('disable')); ?>)<br />
+               <?php echo _AT('auto_install_languages_cron'); ?><br />
+               <?php if (!$_config['last_cron'] || (time() - (int) $_config['last_cron'] > 2 * 60 * 60)): ?>
+                       <input type="radio" name="auto_install_languages" value="1" disabled="disabled" /><?php echo _AT('enable'); ?> <input type="radio" name="auto_install_languages" value="0" id="ai_n" checked="checked" /><label for="ai_n"><?php echo _AT('disable'); ?></label>
+               <?php else: ?>
+                       <input type="radio" name="auto_install_languages" value="1" id="ai_y" <?php if($_config['auto_install_languages']) { echo 'checked="checked"'; }?>  /><label for="ai_y"><?php echo _AT('enable'); ?></label> <input type="radio" name="auto_install_languages" value="0" id="ai_n" <?php if(!$_config['auto_install_languages']) { echo 'checked="checked"'; }?>  /><label for="ai_n"><?php echo _AT('disable'); ?></label>
+               <?php endif; ?>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('pretty_url'); ?> (<?php echo _AT('default'); ?>: <?php echo ($_config_defaults['pretty_url'] ? _AT('enable') : _AT('disable')); ?>)<br />
+               <input type="radio" name="pretty_url" value="1" id="pu_y" <?php if($_config['pretty_url']) { echo 'checked="checked"'; }?> onclick="apache_mod_rewrite_toggler(true);"/><label for="pu_y"><?php echo _AT('enable'); ?></label> <input type="radio" name="pretty_url" value="0" id="pu_n" <?php if(!$_config['pretty_url']) { echo 'checked="checked"'; }?> onclick="apache_mod_rewrite_toggler(false);"/><label for="pu_n"><?php echo _AT('disable'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('course_dir_name'); ?> (<?php echo _AT('default'); ?>: <?php echo ($_config_defaults['course_dir_name'] ? _AT('enable') : _AT('disable')); ?>)<br />
+               <input type="radio" name="course_dir_name" value="1" id="cdn_y" <?php if($_config['course_dir_name']) { echo 'checked="checked"'; }?> /><label for="cdn_y"><?php echo _AT('enable'); ?></label> <input type="radio" name="course_dir_name" value="0" id="cdn_n" <?php if(!$_config['course_dir_name']) { echo 'checked="checked"'; }?>  /><label for="cdn_n"><?php echo _AT('disable'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('apache_mod_rewrite'); ?><br />
+               <?php if (in_array('mod_rewrite', apache_get_modules())): ?>
+                       <?php echo _AT('mod_rewrite'); ?> (<?php echo _AT('default'); ?>: <?php echo ($_config_defaults['apache_mod_rewrite'] ? _AT('enable') : _AT('disable')); ?>)<br />
+                       <input type="radio" name="apache_mod_rewrite" value="1" id="mr_y" <?php if($_config['apache_mod_rewrite']) { echo 'checked="checked"'; }?> /><label for="mr_y"><?php echo _AT('enable'); ?></label> <input type="radio" name="apache_mod_rewrite" value="0" id="mr_n" <?php if(!$_config['apache_mod_rewrite']) { echo 'checked="checked"'; }?>  /><label for="mr_n"><?php echo _AT('disable'); ?></label>
+               <?php else: ?>
+                       <?php echo _AT('mod_rewrite'); ?> (<?php echo _AT('default'); ?>: <?php echo ($_config_defaults['apache_mod_rewrite'] ? _AT('enable') : _AT('disable')); ?>)<br />
+                       <input type="radio" name="apache_mod_rewrite" value="1" id="mr_y" disabled="disabled" /><label for="mr_y"><?php echo _AT('enable'); ?></label> <input type="radio" name="apache_mod_rewrite" value="0" id="mr_n" checked="checked" /><label for="mr_n"><?php echo _AT('disable'); ?></label>
+               <?php endif; ?>
+       </div>
+
+       <div class="row buttons">
+                       <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s"  />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>"  />
+       </div>
+</div>
+</form>
+
+
+<script type="text/javascript">
+       function apache_mod_rewrite_toggler(enabled){
+               var obj_y = document.getElementById('mr_y');
+               var obj_n = document.getElementById('mr_n');
+               if(enabled==true) {
+                       obj_y.disabled = "";    
+               } else if (enabled==false){
+                       obj_y.disabled = "disabled";
+                       obj_n.checked = "checked";
+               }
+       }
+
+       //Validate apache_mod data
+       var pu_n = document.getElementById('pu_n');
+       var obj_y = document.getElementById('mr_y');
+       var obj_n = document.getElementById('mr_n');
+       if (pu_n.checked == true){
+               obj_y.disabled = "disabled";
+               obj_n.checked = "checked";
+       }
+</script>
+
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/config_template.php b/admin/config_template.php
new file mode 100644 (file)
index 0000000..3d80bdb
--- /dev/null
@@ -0,0 +1,139 @@
+<?php 
+/************************************************************************/
+/* ATutor                                                               */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton */
+/* http://atutor.ca                                                     */
+/*                                                                      */
+/* 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.                        */
+/************************************************************************/
+{GENERATED_COMMENTS}
+/************************************************************************/
+/************************************************************************/
+
+/* the database user name                                               */
+define('DB_USER',                      '{USER}');
+
+/* the database password                                                */
+define('DB_PASSWORD',                  '{PASSWORD}');
+
+/* the database host                                                    */
+define('DB_HOST',                      '{HOST}');
+
+/* the database tcp/ip port                                             */
+define('DB_PORT',                      '{PORT}');
+
+/* the database name                                                    */
+define('DB_NAME',                      '{DBNAME}');
+
+/* The prefix to add to table names to avoid conflicts with existing    */
+/* tables. Default: AT_                                                 */
+define('TABLE_PREFIX',                 '{TABLE_PREFIX}');
+
+/* The email that will be used as the return email when needed and when */
+/* instructor account requests are made.                                */
+define('EMAIL',                         '{EMAIL}');
+
+/* do you want to receive emails when new instructor accounts           */
+/* require approval                                                     */
+define('EMAIL_NOTIFY',                 {EMAIL_NOTIFY});
+
+/* allow regular account users to request their account to be           */
+/* upgraded to instructor accounts.                                     */
+define('ALLOW_INSTRUCTOR_REQUESTS',    {INSTRUCTOR_REQUESTS});
+
+/* If ALLOW_INSTRUCTOR_REQUESTS is true then you can have the           */
+/* requests approved instantly, otherwise each request will             */
+/* have to be approved manually by the admin.                           */
+define('AUTO_APPROVE_INSTRUCTORS',     {APPROVE_INSTRUCTORS});
+
+/************************************************************************/
+/* File manager options:                                                */
+
+/* Default maximum allowable file size in Bytes to upload:              */
+/* Will not override the upload_max_filesize in php.ini                 */
+$MaxFileSize   =   {MAX_FILE_SIZE}; /* 1 MB */
+
+/* Default total maximum allowable course size in Bytes:                */
+/* When this number is exceeded, no more uploads will be allowed        */
+$MaxCourseSize =  {MAX_COURSE_SIZE}; /* 10 MB */
+
+/* Soft limit threshold:                                                */
+/* How much a course can be over, while still allowing the              */
+/* upload to finish.                                                    */
+/* Therefore the real course limit is                                   */
+/* \$MaxCourseSize + \$MaxCourseFloat, but when the float gets          */
+/* used then no more uploads will be allowed.                           */
+$MaxCourseFloat =  {MAX_COURSE_FLOAT}; /* 2 MB */
+
+/* Illegal file types, by extension. Include any extensions             */
+/* you do not want to allow for uploading. (Just the extention          */
+/* without the leading dot.)                                            */
+$IllegalExtentions = array({ILL_EXT});
+
+/* The name of your course website.                                     */
+/* Example: Acme University's Course Server                             */
+/* Single quotes will have to be escaped with a slash: \'.              */
+define('SITE_NAME', '{SITE_NAME}');
+
+/* link for the 'home' menu item.  Will not show if empty */
+define('HOME_URL', '{HOME_URL}');
+
+/* Default language to use, if not browser-defined or                   */
+/* user-defined. 'en' is always available. Any other language           */
+/* specified must already exist in the database.                        */
+/* Default language: en                                                 */
+define('DEFAULT_LANGUAGE',             '{DEFAULT_LANGUAGE}');
+
+/* Where the cache directory should be created. On a Windows            */
+/* machine the path should look like C:\Windows\temp\. Path             */
+/* must end in a slash. The directory must already exist.               */
+/* Make empty or comment out to disable cacheing.                       */
+/* Back slashes must be escaped if at the end: ex: ..tmp\\');           */
+define('CACHE_DIR', '{CACHE_DIR}');
+
+/* Where the course content files are located.  This includes all file  */
+/* manager and imported files.  If security is a concern, it is         */
+/* recommended that the content directory be moved outside of the web  */
+/* accessible area.                                                                                                            */
+define('AT_CONTENT_DIR', '{CONTENT_DIR}');
+
+/* Whether or not to use the default php.ini SMTP settings.             */
+/* If false, then mail will try to be sent using sendmail.              */
+define('MAIL_USE_SMTP', {MAIL_USE_SMTP});
+
+/* Whether or not to enable theme specific categories and disable the   */
+/* personal theme preference.                                           */
+define('AT_ENABLE_CATEGORY_THEMES',      {THEME_CATEGORIES});
+
+/* How many backup files can be stored per course.                      */
+define('AT_COURSE_BACKUPS', {COURSE_BACKUPS});
+
+/* Whether or not to require email confirmation to validate accounts    */
+define('AT_EMAIL_CONFIRMATION', {EMAIL_CONFIRMATION});
+
+/* Whether or not to enable master list authentication.                 */
+/* If enabled, only new accounts that validate against the master list  */
+/* will be created. The master list is flexible and can be used for any */
+/* fields.                                                              */
+define('AT_MASTER_LIST', {MASTER_LIST});
+
+/* Whether or not to show the ongoing tests box on the home page.       */
+/* Default: TRUE (on)                                                   */
+define('AT_SHOW_TEST_BOX', TRUE);
+
+/* Whether or not to use the AT_CONTENT_DIR as a protected directory.   */
+/* The if set to FALSE then the content directory will be hard coded    */
+/* to ATutor_install_dir/content/ and AT_CONTENT_DIR will be ignored.   */
+/* This option is used for compatability with IIS and Apache 2.         */
+define('AT_FORCE_GET_FILE', {GET_FILE});
+
+/* Whether or not to allow user notes in the handbook.                  */
+define('AT_ENABLE_HANDBOOK_NOTES', {USER_NOTES});
+
+/* DO NOT ALTER THIS LAST LINE                                          */
+define('AT_INSTALL', true);
+
+?>
\ No newline at end of file
diff --git a/admin/course_categories.php b/admin/course_categories.php
new file mode 100644 (file)
index 0000000..948f209
--- /dev/null
@@ -0,0 +1,91 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'lib/themes.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_CATEGORIES);\r
+\r
+if (isset($_POST['delete'], $_POST['cat_id'])) {\r
+       header('Location: delete_category.php?cat_id='.$_POST['cat_id']);\r
+       exit;\r
+} else if (isset($_POST['edit'], $_POST['cat_id'])) {\r
+       header('Location: edit_category.php?cat_id='.$_POST['cat_id']);\r
+       exit;\r
+} else if (!empty($_POST)) {\r
+       $msg->addError('NO_ITEM_SELECTED');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+\r
+?>\r
+<form name="form" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<table summary="" class="data" rules="cols" align="center" style="width: 70%;">\r
+\r
+<thead>\r
+<tr>\r
+       <th scope="col">&nbsp;</th>\r
+       <th scope="col"><?php echo _AT('name'); ?></th>\r
+       <th scope="col"><?php echo _AT('parent'); ?></th>\r
+<?php if (defined('AT_ENABLE_CATEGORY_THEMES') && AT_ENABLE_CATEGORY_THEMES) : ?>\r
+       <th scope="col"><?php echo _AT('theme'); ?></th>\r
+<?php endif; ?>\r
+</tr>\r
+</thead>\r
+<tfoot>\r
+<tr>\r
+       <td colspan="4">\r
+               <div class="row buttons">\r
+               <input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /> \r
+               </div>\r
+       </td>\r
+</tr>\r
+</tfoot>\r
+<tbody>\r
+<?php\r
+$sql   = "SELECT * FROM ".TABLE_PREFIX."course_cats ORDER BY cat_name";\r
+$result = mysql_query($sql, $db);\r
+if ($row = mysql_fetch_assoc($result)): ?>\r
+       <?php\r
+       do {\r
+               $parent_cat_name = '';\r
+               if ($row['cat_parent']) {\r
+                       $sql_cat        = "SELECT cat_name FROM ".TABLE_PREFIX."course_cats WHERE cat_id=".$row['cat_parent'];\r
+                       $result_cat = mysql_query($sql_cat, $db);\r
+                       $row_cat = mysql_fetch_assoc($result_cat);\r
+                       $parent_cat_name = $row_cat['cat_name'];\r
+               } \r
+       ?>\r
+               <tr onmousedown="document.form['m<?php echo $row['cat_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $row['cat_id']; ?>">\r
+                       <td width="10"><input type="radio" name="cat_id" value="<?php echo $row['cat_id']; ?>" id="m<?php echo $row['cat_id']; ?>" /></td>\r
+                       <td><label for="m<?php echo $row['cat_id']; ?>"><?php echo AT_print($row['cat_name'], 'course_cats.cat_name'); ?></label></td>\r
+                       <td><?php echo AT_print($parent_cat_name, 'course_cats.cat_name'); ?></td>\r
+                       <?php if (defined('AT_ENABLE_CATEGORY_THEMES') && AT_ENABLE_CATEGORY_THEMES) : ?>\r
+                               <td><?php echo AT_print(get_theme_name($row['theme']), 'themes.title'); ?></td>\r
+                       <?php endif; ?>\r
+\r
+               </tr>\r
+       <?php } while ($row = mysql_fetch_assoc($result)); ?>\r
+<?php else: ?>\r
+       <tr>\r
+               <td colspan="3"><?php echo _AT('none_found'); ?></td>\r
+       </tr>\r
+<?php endif; ?>\r
+</tbody>\r
+</table>\r
+\r
+</form>\r
+\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/courses.php b/admin/courses.php
new file mode 100644 (file)
index 0000000..bb19287
--- /dev/null
@@ -0,0 +1,208 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_COURSES);
+
+if (isset($_GET['view'], $_GET['id'])) {
+       header('Location: instructor_login.php?course='.$_GET['id']);
+       exit;
+} else if (isset($_GET['edit'], $_GET['id'])) {
+       header('Location: edit_course.php?course='.$_GET['id']);
+       exit;
+} else if (isset($_GET['backups'], $_GET['id'])) {
+       header('Location: backup/index.php?course='.$_GET['id']);
+       exit;
+} else if (isset($_GET['delete'], $_GET['id'])) {
+       header('Location: delete_course.php?course='.$_GET['id']);
+       exit;
+}  else if (isset($_GET['delete']) || isset($_GET['backups']) || isset($_GET['edit']) || isset($_GET['view'])) {
+       $msg->addError('NO_ITEM_SELECTED');
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+$page_string = '';
+
+if ($_GET['reset_filter']) {
+       unset($_GET);
+}
+
+$orders = array('asc' => 'desc', 'desc' => 'asc');
+$cols   = array('title' => 1, 'login' => 1, 'access' => 1, 'created_date' => 1, 'cat_name' => 1);
+$_access = array('public', 'protected', 'private');
+
+if (isset($_GET['asc'])) {
+       $order = 'asc';
+       $col   = isset($cols[$_GET['asc']]) ? $_GET['asc'] : 'title';
+} else if (isset($_GET['desc'])) {
+       $order = 'desc';
+       $col   = isset($cols[$_GET['desc']]) ? $_GET['desc'] : 'title';
+} else {
+       // no order set
+       $order = 'asc';
+       $col   = 'title';
+}
+
+if (isset($_GET['access']) && ($_GET['access'] != '') && isset($_access[$_GET['access']])) {
+       $access = 'C.access = \'' . $_access[$_GET['access']].'\'';
+       $page_string .= SEP.'access='.$_GET['access'];
+} else {
+       $access = '1';
+}
+
+if ($_GET['search']) {
+       $page_string .= SEP.'search='.urlencode($_GET['search']);
+       $search = $addslashes($_GET['search']);
+       $search = str_replace(array('%','_'), array('\%', '\_'), $search);
+       $search = '%'.$search.'%';
+       $search = "((C.title LIKE '$search') OR (C.description LIKE '$search'))";
+} else {
+       $search = '1';
+}
+
+// get number of courses on the system
+$sql   = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."courses C WHERE 1 AND $access AND $search";
+$result = mysql_query($sql, $db);
+$row = mysql_fetch_assoc($result);
+$num_results = $row['cnt'];
+
+$results_per_page = 100;
+$num_pages = max(ceil($num_results / $results_per_page), 1);
+$page = intval($_GET['p']);
+if (!$page) {
+       $page = 1;
+}      
+$count  = (($page-1) * $results_per_page) + 1;
+$offset = ($page-1)*$results_per_page;
+
+${'highlight_'.$col} = ' style="background-color: #fff;"';
+
+$sql    = "SELECT COUNT(*) AS cnt, approved, course_id FROM ".TABLE_PREFIX."course_enrollment WHERE approved='y' OR approved='a' GROUP BY course_id, approved";
+$result = mysql_query($sql, $db);
+while ($row = mysql_fetch_assoc($result)) {
+       if ($row['approved'] == 'y') {
+               $row['cnt']--; // remove the instructor
+       }
+       $enrolled[$row['course_id']][$row['approved']] = $row['cnt'];
+}
+
+$sql   = "SELECT C.*, M.login, T.cat_name FROM ".TABLE_PREFIX."members M INNER JOIN ".TABLE_PREFIX."courses C USING (member_id) LEFT JOIN ".TABLE_PREFIX."course_cats T USING (cat_id) WHERE 1 AND $access AND $search ORDER BY $col $order LIMIT $offset, $results_per_page";
+$result = mysql_query($sql, $db);
+
+$num_rows = mysql_num_rows($result);
+?>
+
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+       <div class="input-form">
+               <div class="row">
+                       <h3><?php echo _AT('results_found', $num_results); ?></h3>
+               </div>
+
+               <div class="row">
+                       <?php echo _AT('access'); ?><br />
+
+                       <input type="radio" name="access" value="0" id="s0" <?php if ($_GET['access'] == 0) { echo 'checked="checked"'; } ?> /><label for="s0"><?php echo _AT('public'); ?></label> 
+
+                       <input type="radio" name="access" value="1" id="s1" <?php if ($_GET['access'] == 1) { echo 'checked="checked"'; } ?> /><label for="s1"><?php echo _AT('protected'); ?></label> 
+
+                       <input type="radio" name="access" value="2" id="s2" <?php if ($_GET['access'] == 2) { echo 'checked="checked"'; } ?> /><label for="s2"><?php echo _AT('private'); ?></label>
+
+                       <input type="radio" name="access" value="" id="s" <?php if ($_GET['access'] == '') { echo 'checked="checked"'; } ?> /><label for="s"><?php echo _AT('all'); ?></label>
+               </div>
+
+               <div class="row">
+                       <label for="search"><?php echo _AT('search'); ?> (<?php echo _AT('title').', '._AT('description'); ?>)</label><br />
+                       <input type="text" name="search" id="search" size="20" value="<?php echo htmlspecialchars($_GET['search']); ?>" />
+               </div>
+
+               <div class="row buttons">
+                       <input type="submit" name="filter" value="<?php echo _AT('filter'); ?>" />
+                       <input type="submit" name="reset_filter" value="<?php echo _AT('reset_filter'); ?>" />
+               </div>
+       </div>
+</form>
+
+<?php print_paginator($page, $num_results, $page_string . SEP . $order .'='. $col, $results_per_page); ?>
+
+<form name="form" method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+
+<table class="data" summary="" rules="cols">
+<colgroup>
+       <?php if ($col == 'title'): ?>
+               <col />
+               <col class="sort" />
+               <col span="6" />
+       <?php elseif($col == 'login'): ?>
+               <col span="2" />
+               <col class="sort" />
+               <col span="5" />
+       <?php elseif($col == 'access'): ?>
+               <col span="3" />
+               <col class="sort" />
+               <col span="4" />
+       <?php elseif($col == 'created_date'): ?>
+               <col span="4" />
+               <col class="sort" />
+               <col span="3" />
+       <?php elseif($col == 'cat_name'): ?>
+               <col span="5" />
+               <col class="sort" />
+               <col span="2" />
+       <?php endif; ?>
+</colgroup>
+<thead>
+<tr>
+       <th scope="col">&nbsp;</th>
+       <th scope="col"><a href="admin/courses.php?<?php echo $orders[$order]; ?>=title<?php echo $page_string; ?>"><?php echo _AT('title');               ?></a></th>
+       <th scope="col"><a href="admin/courses.php?<?php echo $orders[$order]; ?>=login<?php echo $page_string; ?>"><?php echo _AT('Instructor');          ?></a></th>
+       <th scope="col"><a href="admin/courses.php?<?php echo $orders[$order]; ?>=access<?php echo $page_string; ?>"><?php echo _AT('access');             ?></a></th>
+       <th scope="col"><a href="admin/courses.php?<?php echo $orders[$order]; ?>=created_date<?php echo $page_string; ?>"><?php echo _AT('created_date'); ?></a></th>
+       <th scope="col"><a href="admin/courses.php?<?php echo $orders[$order]; ?>=cat_name<?php echo $page_string; ?>"><?php echo _AT('category'); ?></a></th>
+       <th scope="col"><?php echo _AT('enrolled'); ?></th>
+       <th scope="col"><?php echo _AT('alumni'); ?></th>
+</tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="8"><input type="submit" name="view" value="<?php echo _AT('view'); ?>" /> 
+                                       <input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> 
+                                       <input type="submit" name="backups" value="<?php echo _AT('backups'); ?>" /> 
+                                       <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /></td>
+</tr>
+</tfoot>
+<tbody>
+<?php if ($num_rows): ?>
+       <?php while ($row = mysql_fetch_assoc($result)): ?>
+               <tr onmousedown="document.form['m<?php echo $row['course_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $row['course_id']; ?>">
+                       <td><input type="radio" name="id" value="<?php echo $row['course_id']; ?>" id="m<?php echo $row['course_id']; ?>" /></td>
+                       <td><label for="m<?php echo $row['course_id']; ?>"><?php echo AT_print($row['title'], 'courses.title'); ?></label></td>
+                       <td><?php echo AT_print($row['login'],'members.login'); ?></td>
+                       <td><?php echo _AT($row['access']); ?></td>
+                       <td><?php echo AT_date($startend_date_long_format, $row['created_date'], AT_DATE_UNIX_TIMESTAMP); ?></td>
+                       <td><?php echo ($row['cat_name'] ? $row['cat_name'] : '-')?></td>
+                       <td><?php echo ($enrolled[$row['course_id']]['y'] ? $enrolled[$row['course_id']]['y'] : 0); ?></td>
+                       <td><?php echo ($enrolled[$row['course_id']]['a'] ? $enrolled[$row['course_id']]['a'] : 0); ?></td>
+               </tr>
+       <?php endwhile; ?>
+<?php else: ?>
+       <tr>
+               <td colspan="8"><?php echo _AT('none_found'); ?></td>
+       </tr>
+<?php endif; ?>
+</tbody>
+</table>
+</form>
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/create_category.php b/admin/create_category.php
new file mode 100644 (file)
index 0000000..91c02ea
--- /dev/null
@@ -0,0 +1,138 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'lib/themes.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_CATEGORIES);\r
+\r
+require(AT_INCLUDE_PATH.'lib/admin_categories.inc.php');\r
+\r
+if (isset($_POST['submit'])) {\r
+       /* insert or update a category */\r
+       $cat_id                 = intval($_POST['cat_id']);\r
+       $cat_parent_id  = intval($_POST['cat_parent_id']);\r
+       $cat_name       = trim($_POST['cat_name']);\r
+\r
+       $cat_name  = $addslashes($cat_name);\r
+       $cat_theme = $addslashes($_POST['cat_theme']);\r
+\r
+       if ($cat_name == '') {\r
+               $msg->addError(array('EMPTY_FIELDS', _AT('title')));\r
+       }\r
+       $cat_name = validate_length($cat_name, 100);\r
+\r
+       if ($_POST['theme_parent']) {\r
+               $sql    = "SELECT theme FROM ".TABLE_PREFIX."course_cats WHERE cat_id=$cat_parent_id";\r
+               $result = mysql_query($sql, $db);\r
+               if ($row = mysql_fetch_assoc($result)) {\r
+                       $cat_theme = $row['theme'];\r
+               }\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+\r
+               $sql = "INSERT INTO ".TABLE_PREFIX."course_cats VALUES (NULL, '$cat_name', $cat_parent_id, '$cat_theme')";\r
+               $result = mysql_query($sql, $db);\r
+               $cat_id = mysql_insert_id($db);\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+               \r
+               write_to_log(AT_ADMIN_LOG_INSERT, 'course_cats', mysql_affected_rows($db), $sql);\r
+\r
+               header('Location: course_categories.php');\r
+               exit;\r
+       }\r
+} else if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: course_categories.php');\r
+       exit;\r
+}\r
+\r
+/* $categories[category_id] = array(cat_name, cat_parent, num_courses, [array(children)]) */\r
+$categories = get_categories();\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+$msg->printAll();\r
+\r
+?>\r
+\r
+<form action ="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">\r
+<input type="hidden" name="cat_id" value="<?php echo $cat_id; ?>" />\r
+<input type="hidden" name="form_submit" value="1" />\r
+\r
+<div class="input-form">\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="category_name"><?php echo _AT('title'); ?></label><br />\r
+               <input type="text" id="category_name" name="cat_name" size="30" value="<?php echo htmlspecialchars($categories[$cat_id]['cat_name']); ?>" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="category_parent"><?php echo _AT('cats_parent_category'); ?></label><br />\r
+               <select name="cat_parent_id" id="category_parent"><?php\r
+\r
+                               if ($pcat_id) {\r
+                                       $current_cat_id = $pcat_id;\r
+                                       $exclude = false; /* don't exclude the children */\r
+                               } else {\r
+                                       $current_cat_id = $cat_id;\r
+                                       $exclude = true; /* exclude the children */\r
+                               }\r
+\r
+                               echo '<option value="0">&nbsp;&nbsp;&nbsp;[ '._AT('cats_none').' ]&nbsp;&nbsp;&nbsp;</option>';\r
+                               echo '<option value="0"></option>';\r
+\r
+                               /* @See: include/lib/admin_categories */\r
+                               select_categories($categories, 0, $current_cat_id, $exclude);\r
+                       ?></select>\r
+       </div>\r
+\r
+<?php if (defined('AT_ENABLE_CATEGORY_THEMES') && AT_ENABLE_CATEGORY_THEMES) : ?>\r
+       <div class="row">\r
+               <label for="category_theme"><?php echo _AT('cat_theme'); ?></label><br />\r
+               <select name="cat_theme" id="category_theme"><?php\r
+\r
+                               echo '<option value="0">&nbsp;&nbsp;&nbsp;[ '._AT('cats_none').' ]&nbsp;&nbsp;&nbsp;</option>';\r
+\r
+                               $_themes = get_enabled_themes();\r
+                               foreach ($_themes as $theme) {\r
+                                       $theme = trim($theme);\r
+                                       $theme_dir = get_folder($theme);\r
+                                       if ($theme_dir == $categories[$cat_id]['theme']) {\r
+                                               echo '<option value="'.$theme_dir.'" selected="selected">'.$theme.'</option>';\r
+                                       } else {\r
+                                               echo '<option value="'.$theme_dir.'">'.$theme.'</option>';\r
+                                       }\r
+                               }\r
+\r
+                       ?></select>\r
+                       <?php if ($cat_id && is_array($categories[$cat_id]['children']) && count($categories[$cat_id]['children'])): ?>\r
+                               <br />\r
+                               <input type="checkbox" name="theme_children" id="theme_children" value="1" /><label for="theme_children"><?php echo _AT('apply_theme_subcategories'); ?></label>\r
+                       <?php endif; ?>\r
+                       <?php if ($categories[$cat_id]['cat_parent'] || $pcat_id): ?>\r
+                               <br />\r
+                               <input type="checkbox" name="theme_parent" id="theme_parent" value="1" /><label for="theme_parent"><?php echo _AT('use_parent_theme'); ?></label>\r
+                       <?php endif; ?>\r
+                       <br /><br />\r
+       </div>\r
+<?php endif; ?>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>"  />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/create_course.php b/admin/create_course.php
new file mode 100644 (file)
index 0000000..6fbfa81
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_COURSES);
+       
+require(AT_INCLUDE_PATH.'classes/Backup/Backup.class.php');
+require(AT_INCLUDE_PATH.'lib/course.inc.php');
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'admin/courses.php');
+       exit;
+} else if (isset($_POST['form_course']) && !isset($_POST['setvisual'])) {
+       $errors = add_update_course($_POST, TRUE);
+
+       if ($errors !== FALSE) {
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: '.AT_BASE_HREF.'admin/courses.php');
+               exit;   
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+$msg->printAll();
+
+$course = 0;
+$isadmin   = TRUE;
+
+require(AT_INCLUDE_PATH.'html/course_properties.inc.php');
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+
+?>
\ No newline at end of file
diff --git a/admin/create_user.php b/admin/create_user.php
new file mode 100644 (file)
index 0000000..43f8994
--- /dev/null
@@ -0,0 +1,248 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_USERS);\r
+\r
+if (isset($_POST['cancel'])) {\r
+       header('Location: '.AT_BASE_HREF.'admin/users.php');\r
+       exit;\r
+}\r
+\r
+if (isset($_POST['submit'])) {\r
+       $missing_fields = array();\r
+\r
+       //check if student id (public field) is already being used\r
+       if (!$_POST['overwrite'] && !empty($_POST['student_id'])) {\r
+               $result = mysql_query("SELECT * FROM ".TABLE_PREFIX."master_list WHERE public_field='$_POST[student_id]' && member_id<>0",$db);\r
+               if (mysql_num_rows($result) != 0) {\r
+                       $msg->addError('CREATE_MASTER_USED');\r
+               }\r
+       }\r
+\r
+       /* login name check */\r
+       if ($_POST['login'] == '') {\r
+               $missing_fields[] = _AT('login_name');\r
+       } else {\r
+               /* check for special characters */\r
+               if (!(eregi("^[a-zA-Z0-9_.-]([a-zA-Z0-9_.-])*$", $_POST['login']))) {\r
+                       $msg->addError('LOGIN_CHARS');\r
+               } else {\r
+                       $result = mysql_query("SELECT * FROM ".TABLE_PREFIX."members WHERE login='$_POST[login]'",$db);\r
+                       if (mysql_num_rows($result) != 0) {\r
+                               $valid = 'no';\r
+                               $msg->addError('LOGIN_EXISTS');\r
+                       }  else {\r
+                               $result = mysql_query("SELECT * FROM ".TABLE_PREFIX."admins WHERE login='$_POST[login]'",$db);\r
+                               if (mysql_num_rows($result) != 0) {\r
+                                       $msg->addError('LOGIN_EXISTS');\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       /* password check:      */\r
+       $_POST['password'] = $_POST['form_password_hidden'];\r
+\r
+       /* password check: password is verified front end by javascript. here is to handle the errors from javascript */\r
+       if ($_POST['password_error'] <> "")\r
+       {\r
+               $pwd_errors = explode(",", $_POST['password_error']);\r
+\r
+               foreach ($pwd_errors as $pwd_error)\r
+               {\r
+                       if ($pwd_error == "missing_password")\r
+                               $missing_fields[] = _AT('password');\r
+                       else\r
+                               $msg->addError($pwd_error);\r
+               }\r
+       }\r
+\r
+       /* email check */\r
+       if ($_POST['email'] == '') {\r
+               $missing_fields[] = _AT('email');\r
+       } else if (!eregi("^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$", $_POST['email'])) {\r
+               $msg->addError('EMAIL_INVALID');\r
+       }\r
+\r
+       $_POST['email'] = $addslashes($_POST['email']);\r
+       $result = mysql_query("SELECT member_id FROM ".TABLE_PREFIX."members WHERE email LIKE '$_POST[email]'",$db);\r
+       if (mysql_num_rows($result) != 0) {\r
+               $msg->addError('EMAIL_EXISTS');\r
+       }\r
+\r
+       if (!$_POST['first_name']) {\r
+               $missing_fields[] = _AT('first_name');\r
+       }\r
+\r
+       if (!$_POST['last_name']) {\r
+               $missing_fields[] = _AT('last_name');\r
+       }\r
+\r
+       $_POST['first_name'] = str_replace('<', '', $_POST['first_name']);\r
+       $_POST['second_name'] = str_replace('<', '', $_POST['second_name']);\r
+       $_POST['last_name'] = str_replace('<', '', $_POST['last_name']);\r
+\r
+       // check if first+last is unique\r
+       if ($_POST['first_name'] && $_POST['last_name']) {\r
+               $first_name_sql  = $addslashes($_POST['first_name']);\r
+               $last_name_sql   = $addslashes($_POST['last_name']);\r
+               $second_name_sql = $addslashes($_POST['second_name']);\r
+\r
+               $sql = "SELECT member_id FROM ".TABLE_PREFIX."members WHERE first_name='$first_name_sql' AND second_name='$second_name_sql' AND last_name='$last_name_sql' LIMIT 1";\r
+               $result = mysql_query($sql, $db);\r
+               if (mysql_fetch_assoc($result)) {\r
+                       $msg->addError('FIRST_LAST_NAME_UNIQUE');\r
+               }\r
+       }\r
+\r
+\r
+       $_POST['login'] = strtolower($_POST['login']);\r
+\r
+       //check date of birth\r
+       $mo = intval($_POST['month']);\r
+       $day = intval($_POST['day']);\r
+       $yr = intval($_POST['year']);\r
+\r
+       /* let's us take (one or) two digit years (ex. 78 = 1978, 3 = 2003) */\r
+       if ($yr < date('y')) { \r
+               $yr += 2000; \r
+       } else if ($yr < 1900) { \r
+               $yr += 1900; \r
+       } \r
+\r
+       $dob = $yr.'-'.$mo.'-'.$day;\r
+\r
+       if ($mo && $day && $yr && !checkdate($mo, $day, $yr)) { \r
+               $msg->addError('DOB_INVALID');\r
+       } else if (!$mo || !$day || !$yr) {\r
+               $dob = '0000-00-00';\r
+               $yr = $mo = $day = 0;\r
+       }\r
+\r
+       if ($missing_fields) {\r
+               $missing_fields = implode(', ', $missing_fields);\r
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               if (($_POST['website']) && (!ereg('://',$_POST['website']))) { \r
+                       $_POST['website'] = 'http://' . $_POST['website']; \r
+               }\r
+               if ($_POST['website'] == 'http://') { \r
+                       $_POST['website'] = ''; \r
+               }\r
+               $_POST['postal'] = strtoupper(trim($_POST['postal']));\r
+       \r
+               if (isset($_POST['private_email'])) {\r
+                       $_POST['private_email'] = 1;\r
+               } else {\r
+                       $_POST['private_email'] = 0;\r
+               }\r
+               $_POST['password']   = $addslashes($_POST['password']);\r
+               $_POST['website']    = $addslashes($_POST['website']);\r
+               $_POST['first_name'] = $addslashes($_POST['first_name']);\r
+               $_POST['second_name']  = $addslashes($_POST['second_name']);\r
+               $_POST['last_name']  = $addslashes($_POST['last_name']);\r
+               $_POST['address']    = $addslashes($_POST['address']);\r
+               $_POST['postal']     = $addslashes($_POST['postal']);\r
+               $_POST['city']       = $addslashes($_POST['city']);\r
+               $_POST['province']   = $addslashes($_POST['province']);\r
+               $_POST['country']    = $addslashes($_POST['country']);\r
+               $_POST['phone']      = $addslashes($_POST['phone']);\r
+               $_POST['status']     = intval($_POST['status']);\r
+               $_POST['gender']     = $addslashes($_POST['gender']);\r
+\r
+               $now = date('Y-m-d H:i:s'); // we use this later for the email confirmation.\r
+\r
+               /* insert into the db. (the last 0 for status) */\r
+               $sql = "INSERT INTO ".TABLE_PREFIX."members VALUES (NULL,'$_POST[login]','$_POST[password]','$_POST[email]','$_POST[website]','$_POST[first_name]', '$_POST[second_name]', '$_POST[last_name]', '$dob', '$_POST[gender]', '$_POST[address]','$_POST[postal]','$_POST[city]','$_POST[province]','$_POST[country]', '$_POST[phone]',$_POST[status], '$_config[pref_defaults]', '$now','$_config[default_language]', $_config[pref_inbox_notify], $_POST[private_email], '0000-00-00 00:00:00')";\r
+\r
+               $result = mysql_query($sql, $db);\r
+\r
+               $m_id   = mysql_insert_id($db);\r
+               if (!$result) {\r
+                       require(AT_INCLUDE_PATH.'header.inc.php');\r
+                       $msg->addError('DB_NOT_UPDATED');\r
+                       $msg->printAll();\r
+                       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+                       exit;\r
+               }\r
+\r
+               if (defined('AT_MASTER_LIST') && AT_MASTER_LIST) {\r
+                       $student_id  = $addslashes($_POST['student_id']);\r
+                       $student_pin = md5($addslashes($_POST['student_pin']));\r
+                       if ($student_id) {\r
+                               $sql = "UPDATE ".TABLE_PREFIX."master_list SET member_id=$m_id WHERE public_field='$student_id'";\r
+                               mysql_query($sql, $db);\r
+                               if (mysql_affected_rows($db) == 0) {\r
+                                       $sql = "REPLACE INTO ".TABLE_PREFIX."master_list VALUES ('$student_id', '$student_pin', $m_id)";\r
+                                       mysql_query($sql, $db);\r
+                               }\r
+                       }\r
+               }\r
+\r
+\r
+               if ($_POST['pref'] == 'access') {\r
+                       $_SESSION['member_id'] = $m_id;\r
+                       save_prefs();\r
+                       unset($_SESSION['member_id']);\r
+               }\r
+\r
+\r
+               require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');\r
+               $mail = new ATutorMailer();\r
+               $mail->AddAddress($_POST['email']);\r
+               $mail->From    = $_config['contact_email'];\r
+               \r
+               if (defined('AT_EMAIL_CONFIRMATION') && AT_EMAIL_CONFIRMATION && ($_POST['status'] == AT_STATUS_UNCONFIRMED)) {\r
+                       $code = substr(md5($_POST['email'] . $now . $m_id), 0, 10);\r
+                       $confirmation_link = AT_BASE_HREF . 'confirm.php?id='.$m_id.SEP.'m='.$code;\r
+\r
+                       /* send the email confirmation message: */\r
+                       $mail->Subject = $_config['site_name'] . ': ' . _AT('email_confirmation_subject');\r
+                       $body .= _AT('admin_new_account_confirm', $_config['site_name'], $confirmation_link)."\n\n";\r
+\r
+               } else {\r
+                       $mail->Subject = $_config['site_name'].": "._AT('account_information');\r
+                       $body .= _AT('admin_new_account', $_config['site_name'])."\n\n";\r
+               }\r
+               $body .= _AT('web_site') .' : '.AT_BASE_HREF."\n";\r
+               $body .= _AT('login_name') .' : '.$_POST['login'] . "\n";\r
+//             $body .= _AT('password') .' : '.$_POST['password'] . "\n";\r
+               $mail->Body    = $body;\r
+               $mail->Send();\r
+\r
+               $msg->addFeedback('PROFILE_CREATED_ADMIN');\r
+               header('Location: '.AT_BASE_HREF.'admin/users.php');\r
+               exit;\r
+       }\r
+}\r
+\r
+$onload = 'document.form.login.focus();';\r
+\r
+$savant->assign('languageManager', $languageManager);\r
+\r
+if (!isset($_POST['status'])) {\r
+       if (defined('AT_EMAIL_CONFIRMATION') && AT_EMAIL_CONFIRMATION) {\r
+               $_POST['status'] = AT_STATUS_UNCONFIRMED;\r
+       } else {\r
+               $_POST['status'] = AT_STATUS_STUDENT;\r
+       }\r
+}\r
+\r
+$savant->display('registration.tmpl.php');\r
+\r
+?>
\ No newline at end of file
diff --git a/admin/cron.php b/admin/cron.php
new file mode 100644 (file)
index 0000000..7f42e76
--- /dev/null
@@ -0,0 +1,34 @@
+<?php\r
+$_user_location        = 'public';\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH . 'vitals.inc.php');\r
+\r
+// authenticate $_config['cron_key']\r
+if (!isset($_config['cron_key']) || empty($_config['cron_key']) || ($_config['cron_key'] != $_GET['k'])) {\r
+       // not authenticated\r
+       exit;\r
+}\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('last_cron', '".time()."')";\r
+mysql_query($sql, $db);\r
+\r
+$module_list = $moduleFactory->getModules(AT_MODULE_STATUS_ENABLED, AT_MODULE_TYPE_CORE + AT_MODULE_TYPE_STANDARD + AT_MODULE_TYPE_EXTRA);\r
+$keys = array_keys($module_list);\r
+\r
+foreach($keys as $dir_name) {\r
+       $module =& $module_list[$dir_name];\r
+       \r
+       if (!$module->getCronInterval()) {\r
+               continue;\r
+       }\r
+\r
+       $module->runCron();\r
+}\r
+\r
+//     run the mail queue last\r
+if ($_config['enable_mail_queue']) {\r
+       require_once(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');\r
+       $mail = new ATutorMailer;\r
+       $mail->SendQueue();\r
+}\r
+?>
\ No newline at end of file
diff --git a/admin/cron_config.php b/admin/cron_config.php
new file mode 100644 (file)
index 0000000..ed5d647
--- /dev/null
@@ -0,0 +1,25 @@
+<?php\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);\r
+\r
+if (!isset($_config['cron_key']) || !$_config['cron_key']) {\r
+       $_config['cron_key'] = strtoupper(substr(str_replace(array('l','o','0','i'), array(), md5(time())), 0, 6));\r
+       $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('cron_key', '{$_config['cron_key']}')";\r
+       mysql_query($sql, $db);\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+?>\r
+\r
+<div class="input-form">\r
+       <div class="row">\r
+               <p><?php echo _AT('cron_url_usage'); ?></p>\r
+       </div>\r
+       <div class="row">\r
+               <?php echo _AT('cron_url'); ?><br />\r
+               <code><?php echo AT_BASE_HREF; ?>admin/cron.php?k=<?php echo $_config['cron_key']; ?></code>\r
+       </div>\r
+</div>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/default_preferences.php b/admin/default_preferences.php
new file mode 100644 (file)
index 0000000..f9baf86
--- /dev/null
@@ -0,0 +1,141 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: $
+
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);
+
+if (isset($_GET['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: users.php');
+       exit;
+}
+
+if (isset($_GET['submit'])) {
+       
+       $_GET['mnot']              = intval($_GET['mnot']);
+       $_GET['numbering']         = intval($_GET['numbering']);
+       $_GET['use_jump_redirect'] = intval($_GET['use_jump_redirect']);
+       $_GET['form_focus']        = intval($_GET['form_focus']);
+       $_GET['content_editor']    = intval($_GET['content_editor']);
+
+       $default_theme = get_default_theme();
+
+       $pref_defaults = array('PREF_THEME'=>$default_theme['dir_name'], 'PREF_NUMBERING'=>$_GET['numbering'], 'PREF_JUMP_REDIRECT'=>$_GET['use_jump_redirect'], 'PREF_FORM_FOCUS'=>$_GET['form_focus'], 'PREF_CONTENT_EDITOR' => $_GET['content_editor']);
+
+       $pref_defaults = serialize($pref_defaults);
+
+       if (!($_config_defaults['pref_defaults'] == $pref_defaults) && (strlen($pref_defaults) < 256)) {
+               $sql    = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('pref_defaults','$pref_defaults')";
+       } else if ($_config_defaults['pref_defaults'] == $pref_defaults) {
+               $sql    = "DELETE FROM ".TABLE_PREFIX."config WHERE name='pref_defaults'";
+       }
+       $result = mysql_query($sql, $db);
+
+       $sql    = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('pref_inbox_notify','$_GET[mnot]')";
+       $result = mysql_query($sql, $db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: '.$_SERVER['PHP_SELF']);
+       exit;
+}
+
+$pref_defaults = unserialize($_config['pref_defaults']);
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get" name="prefs">
+<div class="input-form">
+
+       <div class="row">
+               <?php echo _AT('inbox_notification'); ?><br />
+               <?php
+                       $yes = '';
+                       $no  = '';
+                       if ($_config['pref_inbox_notify']) {
+                               $yes = ' checked="checked"';
+                       } else {
+                               $no  = ' checked="checked"';
+                       }
+               ?>
+               <input type="radio" name="mnot" id="mnot_yes" value="1" <?php echo $yes; ?> /><label for="mnot_yes"><?php echo _AT('enable'); ?></label> 
+               <input type="radio" name="mnot" id="mnot_no" value="0" <?php echo $no; ?> /><label for="mnot_no"><?php echo _AT('disable'); ?></label>          
+       </div>
+
+       <div class="row">
+               <?php echo _AT('show_numbers');  ?><br />
+               <?php
+                       $num = '';  $num2 = '';
+                       if ($pref_defaults['PREF_NUMBERING'] == 1) {
+                               $num = ' checked="checked"';
+                       } else {
+                               $num2 = ' checked="checked"';
+                       }
+                       ?><input type="radio" name ="numbering" id="num_en" value="1" <?php echo $num; ?> /><label for="num_en"><?php echo _AT('enable');  ?></label> 
+                       <input type="radio" name ="numbering" id="num_dis" value="0" <?php echo $num2; ?> /><label for="num_dis"><?php echo _AT('disable');  ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('jump_redirect'); ?><br />
+               <?php
+                       $num = '';  $num2 = '';
+                       if ($pref_defaults['PREF_JUMP_REDIRECT'] == 1) {
+                               $num = ' checked="checked"';
+                       } else {
+                               $num2 = ' checked="checked"';
+                       }
+                       ?><input type="radio" name ="use_jump_redirect" id="jump_en" value="1" <?php echo $num; ?> /><label for="jump_en"><?php echo _AT('enable');  ?></label> 
+                       <input type="radio" name ="use_jump_redirect" id="jump_dis" value="0" <?php echo $num2; ?> /><label for="jump_dis"><?php echo _AT('disable');  ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('form_focus');  ?><br />
+               <?php
+                       $num = '';  $num2 = '';
+                       if ($pref_defaults['PREF_FORM_FOCUS'] == 1) {
+                               $num = ' checked="checked"';
+                       } else {
+                               $num2 = ' checked="checked"';
+                       }
+                       ?><input type="radio" name ="form_focus" id="focus_on" value="1" <?php echo $num; ?> /><label for="focus_on"><?php echo _AT('enable');  ?></label> 
+                       <input type="radio" name ="form_focus" id="focus_off" value="0" <?php echo $num2; ?> /><label for="focus_off"><?php echo _AT('disable');  ?></label>
+       </div>
+
+       <div class="row">
+               <?php
+                       $num0 = $num1 = $num2 = '';
+                       if ($pref_defaults['PREF_CONTENT_EDITOR'] == 1) {
+                               $num1 = ' checked="checked"';
+                       } else if ($pref_defaults['PREF_CONTENT_EDITOR'] == 2) {
+                               $num2 = ' checked="checked"';
+                       } else {
+                               $num0 = ' checked="checked"';
+                       }
+               ?>
+               <?php echo _AT('content_editor'); ?><br />
+               <input type="radio" name="content_editor" id="ce_0" value="0" <?php echo $num0; ?>/><label for="ce_0"><?php echo _AT('plain_text');?></label>
+               <input type="radio" name="content_editor" id="ce_1" value="1" <?php echo $num1; ?>/><label for="ce_1"><?php echo _AT('html'); ?></label>
+               <input type="radio" name="content_editor" id="ce_2" value="2" <?php echo $num2; ?>/><label for="ce_2"><?php echo _AT('html') . ' - '. _AT('visual_editor'); ?></label>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>"  />
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/delete_category.php b/admin/delete_category.php
new file mode 100644 (file)
index 0000000..b6d4761
--- /dev/null
@@ -0,0 +1,67 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_CATEGORIES);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: course_categories.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       /* delete has been confirmed, delete this category */\r
+       $cat_id = intval($_POST['cat_id']);\r
+\r
+       if (!is_array($categories[$cat_id]['children'])) {\r
+               $sql = "DELETE FROM ".TABLE_PREFIX."course_cats WHERE cat_id=$cat_id";\r
+               $result = mysql_query($sql, $db);\r
+\r
+               write_to_log(AT_ADMIN_LOG_DELETE, 'course_cats', mysql_affected_rows($db), $sql);\r
+\r
+               $sql = "UPDATE ".TABLE_PREFIX."courses SET cat_id=0 WHERE cat_id=$cat_id";\r
+               $result = mysql_query($sql, $db);\r
+\r
+               write_to_log(AT_ADMIN_LOG_DELETE, 'courses', mysql_affected_rows($db), $sql);\r
+\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+               header('Location: course_categories.php');\r
+               exit;\r
+       }\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+       $_GET['cat_id'] = intval($_GET['cat_id']); \r
+\r
+       $sql = "SELECT * FROM ".TABLE_PREFIX."course_cats WHERE cat_id=$_GET[cat_id]";\r
+       $result = mysql_query($sql,$db);\r
+\r
+       if (mysql_num_rows($result) == 0) {\r
+               $msg->printErrors('ITEM_NOT_FOUND');\r
+       } else {\r
+               $row = mysql_fetch_assoc($result);\r
+               \r
+               $hidden_vars['cat_name']= $row['cat_name'];\r
+               $hidden_vars['cat_id']  = $row['cat_id'];\r
+\r
+               $confirm = array('DELETE_CATEGORY', AT_print($row['cat_name'], 'course_cats.cat_name'));\r
+               $msg->addConfirm($confirm, $hidden_vars);\r
+               \r
+               $msg->printConfirm();\r
+       }\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+\r
+?>
\ No newline at end of file
diff --git a/admin/delete_course.php b/admin/delete_course.php
new file mode 100644 (file)
index 0000000..6b23800
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg GayJoel Kronenberg & Heidi Hazelton */
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_COURSES);
+
+$course = intval($_REQUEST['course']);
+
+if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: courses.php');
+       exit;
+} else if (isset($_POST['step']) && ($_POST['step'] == 2) && isset($_POST['submit_yes'])) {
+       require(AT_INCLUDE_PATH.'lib/filemanager.inc.php');
+       require(AT_INCLUDE_PATH.'lib/delete_course.inc.php');
+
+       delete_course($course, $entire_course = true, $rel_path = '../'); // delete the course
+       cache_purge('system_courses','system_courses'); // purge the system_courses cache (if successful)
+       
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: courses.php');
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+if (!isset($_POST['step'])) {
+       $hidden_vars['step']   = 1;
+       $hidden_vars['course'] = $course;
+       $msg->addConfirm(array('DELETE_COURSE_1', $system_courses[$course]['title']), $hidden_vars);
+       $msg->printConfirm();
+} else if ($_POST['step'] == 1) {
+       $hidden_vars['step']   = 2;
+       $hidden_vars['course'] = $course;
+       $msg->addConfirm(array('DELETE_COURSE_2', $system_courses[$course]['title']), $hidden_vars);
+       $msg->printConfirm();
+}
+
+require(AT_INCLUDE_PATH.'footer.inc.php'); 
+?>
\ No newline at end of file
diff --git a/admin/edit_category.php b/admin/edit_category.php
new file mode 100644 (file)
index 0000000..23028b9
--- /dev/null
@@ -0,0 +1,146 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'lib/themes.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_CATEGORIES);\r
+\r
+require(AT_INCLUDE_PATH.'lib/admin_categories.inc.php');\r
+\r
+$cat_id = intval($_REQUEST['cat_id']);\r
+\r
+if (isset($_POST['submit'])) {\r
+       $cat_name = $addslashes($_POST['cat_name']);\r
+       $cat_theme = $addslashes($_POST['cat_theme']);\r
+       $cat_parent_id = intval($_POST['cat_parent_id']);\r
+\r
+       if ($_POST['theme_parent']) {\r
+               // get the theme of the parent category.\r
+\r
+               $sql    = "SELECT theme FROM ".TABLE_PREFIX."course_cats WHERE cat_id=$cat_parent_id";\r
+               $result = mysql_query($sql, $db);\r
+               if ($row = mysql_fetch_assoc($result)) {\r
+                       $cat_theme = $row['theme'];\r
+               }\r
+       }\r
+       if ($cat_name == '') {\r
+               $msg->addError(array('EMPTY_FIELDS', _AT('title')));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+\r
+               if ($_POST['theme_children']) {\r
+                       // apply this theme to all the sub-categories recursively.\r
+                       $children = recursive_get_subcategories($cat_id);\r
+                       $children = implode(',', $children);\r
+\r
+                       if ($children) {\r
+                               $sql = "UPDATE ".TABLE_PREFIX."course_cats SET theme='$cat_theme' WHERE cat_id IN ($children)";\r
+                               $result = mysql_query($sql, $db);\r
+\r
+                               write_to_log(AT_ADMIN_LOG_UPDATE, 'course_cats', mysql_affected_rows($db), $sql);\r
+                       }\r
+               }\r
+\r
+               $sql = "UPDATE ".TABLE_PREFIX."course_cats SET cat_parent=$cat_parent_id, cat_name='$cat_name', theme='$cat_theme' WHERE cat_id=$cat_id";\r
+               $result = mysql_query($sql, $db);\r
+\r
+               write_to_log(AT_ADMIN_LOG_UPDATE, 'course_cats', mysql_affected_rows($db), $sql);\r
+\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+\r
+               header('Location: course_categories.php');\r
+               exit;\r
+       }\r
+} else if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: course_categories.php');\r
+       exit;\r
+}\r
+\r
+/* get all the categories: */\r
+/* $categories[category_id] = array(cat_name, cat_parent, num_courses, [array(children)]) */\r
+$categories = get_categories();\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+$msg->printAll();\r
+\r
+?>\r
+\r
+<form action ="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">\r
+<input type="hidden" name="cat_id" value="<?php echo $cat_id; ?>" />\r
+<input type="hidden" name="form_submit" value="1" />\r
+\r
+<div class="input-form">\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="category_name"><?php echo _AT('title'); ?></label><br />\r
+               <input type="text" id="category_name" name="cat_name" size="30" value="<?php echo htmlspecialchars($categories[$cat_id]['cat_name']); ?>" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="category_parent"><?php echo _AT('cats_parent_category'); ?></label><br />\r
+               <select name="cat_parent_id" id="category_parent"><?php\r
+\r
+                               $current_cat_id = $cat_id;\r
+                               $exclude = true; /* exclude the children */\r
+                               echo '<option value="0">&nbsp;&nbsp;&nbsp;[ '._AT('cats_none').' ]&nbsp;&nbsp;&nbsp;</option>';\r
+                               echo '<option value="0"></option>';\r
+\r
+                               /* @See: include/lib/admin_categories */\r
+                               select_categories($categories, 0, $current_cat_id, $exclude);\r
+                       ?></select>\r
+       </div>\r
+\r
+\r
+<?php if (defined('AT_ENABLE_CATEGORY_THEMES') && AT_ENABLE_CATEGORY_THEMES) : ?>\r
+       <div class="row">\r
+               <label for="category_theme"><?php echo _AT('cat_theme'); ?></label><br />\r
+               <select name="cat_theme" id="category_theme"><?php\r
+\r
+                               echo '<option value="0">&nbsp;&nbsp;&nbsp;[ '._AT('cats_none').' ]&nbsp;&nbsp;&nbsp;</option>';\r
+\r
+                               $_themes = get_enabled_themes();\r
+                               foreach ($_themes as $theme) {\r
+                                       $theme = trim($theme);\r
+                                       $theme_dir = get_folder($theme);\r
+                                       $theme_info = get_themes_info($theme_dir);\r
+                                       if ($theme_info['dir_name'] == $categories[$cat_id]['theme']) {\r
+                                               echo '<option value="'.$theme_info['dir_name'].'" selected="selected">'.$theme.'</option>';\r
+                                       } else {\r
+                                               echo '<option value="'.$theme_info['dir_name'].'">'.$theme.'</option>';\r
+                                       }\r
+                               }\r
+\r
+                       ?></select>\r
+                       <?php if ($cat_id && is_array($categories[$cat_id]['children']) && count($categories[$cat_id]['children'])): ?>\r
+                               <br />\r
+                               <input type="checkbox" name="theme_children" id="theme_children" value="1" /><label for="theme_children"><?php echo _AT('apply_theme_subcategories'); ?></label>\r
+                       <?php endif; ?>\r
+                       <?php if ($categories[$cat_id]['cat_parent']): ?>\r
+                               <br />\r
+                               <input type="checkbox" name="theme_parent" id="theme_parent" value="1" /><label for="theme_parent"><?php echo _AT('use_parent_theme'); ?></label>\r
+                       <?php endif; ?>\r
+                       <br /><br />\r
+       </div>\r
+<?php endif; ?>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>"  />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/edit_course.php b/admin/edit_course.php
new file mode 100644 (file)
index 0000000..0d73363
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_COURSES);
+
+require(AT_INCLUDE_PATH.'classes/Backup/Backup.class.php');
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: courses.php');
+       exit;
+} else if (isset($_POST['course']) && !isset($_POST['setvisual'])) {
+       require(AT_INCLUDE_PATH.'lib/course.inc.php');
+       $errors = add_update_course($_POST, TRUE);
+
+       if (is_numeric($errors)) {
+               $msg->addFeedback('COURSE_PROPERTIES');
+               header('Location: '.AT_BASE_HREF.'admin/courses.php');
+               exit;
+       }
+
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+$msg->printAll();
+
+$course = intval($_REQUEST['course']);
+$isadmin   = TRUE;
+
+
+require(AT_INCLUDE_PATH.'html/course_properties.inc.php');
+
+require(AT_INCLUDE_PATH.'footer.inc.php'); 
+?>
\ No newline at end of file
diff --git a/admin/edit_user.php b/admin/edit_user.php
new file mode 100644 (file)
index 0000000..2e89991
--- /dev/null
@@ -0,0 +1,260 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_USERS);\r
+\r
+if (isset($_POST['cancel'])) {\r
+       if (isset($_POST['ml']) && $_REQUEST['ml']) {\r
+               header('Location: '.AT_BASE_HREF.'admin/master_list.php');\r
+       } else {\r
+               header('Location: '.AT_BASE_HREF.'admin/users.php');\r
+       }\r
+       exit;\r
+}\r
+\r
+if (isset($_POST['submit'])) {\r
+       $missing_fields = array();\r
+\r
+       $id = intval($_POST['id']);\r
+\r
+       //check if student id (public field) is already being used\r
+       if (!$_POST['overwrite'] && !empty($_POST['student_id'])) {\r
+               $result = mysql_query("SELECT public_field FROM ".TABLE_PREFIX."master_list WHERE public_field='$_POST[student_id]' AND member_id<>0 AND member_id<>$id",$db);\r
+               if (mysql_num_rows($result) != 0) {\r
+                       $msg->addError('CREATE_MASTER_USED');\r
+               }\r
+       }\r
+\r
+       /* email check */\r
+       if ($_POST['email'] == '') {\r
+               $missing_fields[] = _AT('email');\r
+       } else if (!eregi("^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$", $_POST['email'])) {\r
+               $msg->addError('EMAIL_INVALID');\r
+       }\r
+       $result = mysql_query("SELECT * FROM ".TABLE_PREFIX."members WHERE email LIKE '$_POST[email]' AND member_id <> $id",$db);\r
+\r
+       if (mysql_num_rows($result) != 0) {\r
+               $valid = 'no';\r
+               $msg->addError('EMAIL_EXISTS');\r
+       }\r
+\r
+       if (!$_POST['first_name']) { \r
+               $missing_fields[] = _AT('first_name');\r
+       }\r
+\r
+       if (!$_POST['last_name']) { \r
+               $missing_fields[] = _AT('last_name');\r
+       }\r
+\r
+       $_POST['first_name'] = str_replace('<', '', $_POST['first_name']);\r
+       $_POST['second_name'] = str_replace('<', '', $_POST['second_name']);\r
+       $_POST['last_name'] = str_replace('<', '', $_POST['last_name']);\r
+\r
+       // check if first+last is unique\r
+       if ($_POST['first_name'] && $_POST['last_name']) {\r
+               $first_name_sql  = $addslashes($_POST['first_name']);\r
+               $last_name_sql   = $addslashes($_POST['last_name']);\r
+               $second_name_sql = $addslashes($_POST['second_name']);\r
+\r
+               $sql = "SELECT member_id FROM ".TABLE_PREFIX."members WHERE first_name='$first_name_sql' AND second_name='$second_name_sql' AND last_name='$last_name_sql' AND member_id<>$id LIMIT 1";\r
+               $result = mysql_query($sql, $db);\r
+               if (mysql_fetch_assoc($result)) {\r
+                       $msg->addError('FIRST_LAST_NAME_UNIQUE');\r
+               }\r
+       }\r
+\r
+       \r
+       //check date of birth\r
+       $mo = intval($_POST['month']);\r
+       $day = intval($_POST['day']);\r
+       $yr = intval($_POST['year']);\r
+\r
+       /* let's us take (one or) two digit years (ex. 78 = 1978, 3 = 2003) */\r
+       if ($yr < date('y')) { \r
+               $yr += 2000; \r
+       } else if ($yr < 1900) { \r
+               $yr += 1900; \r
+       } \r
+\r
+       $dob = $yr.'-'.$mo.'-'.$day;\r
+\r
+       if ($mo && $day && $yr && !checkdate($mo, $day, $yr)) { \r
+               $msg->addError('DOB_INVALID');\r
+       } else if (!$mo || !$day || !$yr) {\r
+               $dob = '0000-00-00';\r
+               $yr = $mo = $day = 0;\r
+       }\r
+\r
+\r
+       if ($missing_fields) {\r
+               $missing_fields = implode(', ', $missing_fields);\r
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               if (isset($_POST['profile_pic_delete'])) {\r
+                       profile_image_delete($id);\r
+               }\r
+               if (($_POST['website']) && (!ereg("://",$_POST['website']))) { \r
+                       $_POST['website'] = "http://".$_POST['website']; \r
+               }\r
+               if ($_POST['website'] == 'http://') { \r
+                       $_POST['website'] = ''; \r
+               }\r
+               $_POST['postal'] = strtoupper(trim($_POST['postal']));\r
+\r
+               if (isset($_POST['private_email'])) {\r
+                       $_POST['private_email'] = 1;\r
+               } else {\r
+                       $_POST['private_email'] = 0;\r
+               }\r
+\r
+               //$_POST['password']   = $addslashes($_POST['password']);\r
+               $_POST['website']    = $addslashes($_POST['website']);\r
+               $_POST['first_name'] = $addslashes($_POST['first_name']);\r
+               $_POST['second_name'] = $addslashes($_POST['second_name']);\r
+               $_POST['last_name']  = $addslashes($_POST['last_name']);\r
+               $_POST['address']    = $addslashes($_POST['address']);\r
+               $_POST['postal']     = $addslashes($_POST['postal']);\r
+               $_POST['city']       = $addslashes($_POST['city']);\r
+               $_POST['province']   = $addslashes($_POST['province']);\r
+               $_POST['country']    = $addslashes($_POST['country']);\r
+               $_POST['phone']      = $addslashes($_POST['phone']);\r
+               $_POST['status']     = intval($_POST['status']);\r
+               $_POST['old_status']     = intval($_POST['old_status']);\r
+               $_POST['gender']     = $addslashes($_POST['gender']);\r
+\r
+               /* insert into the db. (the last 0 for status) */\r
+               $sql = "UPDATE ".TABLE_PREFIX."members SET      email      = '$_POST[email]',\r
+                                                                                                       website    = '$_POST[website]',\r
+                                                                                                       first_name = '$_POST[first_name]',\r
+                                                                                                       second_name= '$_POST[second_name]',\r
+                                                                                                       last_name  = '$_POST[last_name]', \r
+                                                                                                       dob      = '$dob',\r
+                                                                                                       gender   = '$_POST[gender]', \r
+                                                                                                       address  = '$_POST[address]',\r
+                                                                                                       postal   = '$_POST[postal]',\r
+                                                                                                       city     = '$_POST[city]',\r
+                                                                                                       province = '$_POST[province]',\r
+                                                                                                       country  = '$_POST[country]', \r
+                                                                                                       phone    = '$_POST[phone]',\r
+                                                                                                       status   = $_POST[status],\r
+                                                                                                       language = '$_SESSION[lang]', \r
+                                                                                                       private_email = $_POST[private_email],\r
+                                                                                                       creation_date=creation_date,\r
+                                                                                                       last_login=last_login\r
+                               WHERE member_id = $id";\r
+               $result = mysql_query($sql, $db);\r
+               if (!$result) {\r
+                       require(AT_INCLUDE_PATH.'header.inc.php');\r
+                       $msg->addError('DB_NOT_UPDATED');\r
+                       $msg->printAll();\r
+                       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+                       exit;\r
+               }\r
+\r
+\r
+               if (defined('AT_MASTER_LIST') && AT_MASTER_LIST) {\r
+                       $_POST['student_id'] = $addslashes($_POST['student_id']);\r
+                       $student_pin = sha1($addslashes($_POST['student_pin']));\r
+\r
+                       //if changed, delete old stud id\r
+                       if (!empty($_POST['old_student_id']) && $_POST['old_student_id'] != $_POST['student_id']) {\r
+                               $sql = "DELETE FROM ".TABLE_PREFIX."master_list WHERE public_field=".$_POST['old_student_id']." AND member_id=$id";\r
+                               $result = mysql_query($sql, $db);\r
+                       }\r
+                       //if new is set\r
+                       if (!empty($_POST['student_id']) && $_POST['old_student_id'] != $_POST['student_id']) {\r
+                               $sql = "REPLACE INTO ".TABLE_PREFIX."master_list VALUES ('$_POST[student_id]', '', $id)";\r
+                               $result = mysql_query($sql, $db);\r
+                       }\r
+               }\r
+\r
+\r
+               if (defined('AT_EMAIL_CONFIRMATION') && AT_EMAIL_CONFIRMATION && ($_POST['status'] == AT_STATUS_UNCONFIRMED) && ($_POST['old_status'] != AT_STATUS_UNCONFIRMED)) {\r
+\r
+                       $sql    = "SELECT email, creation_date FROM ".TABLE_PREFIX."members WHERE member_id=$id";\r
+                       $result = mysql_query($sql, $db);\r
+                       $row    = mysql_fetch_assoc($result);\r
+\r
+                       $code = substr(md5($row['email'] . $row['creation_date']. $id), 0, 10);\r
+                       $confirmation_link = AT_BASE_HREF . 'confirm.php?id='.$id.SEP.'m='.$code;\r
+\r
+                       /* send the email confirmation message: */\r
+                       require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');\r
+                       $mail = new ATutorMailer();\r
+\r
+                       $mail->AddAddress($row['email']);\r
+                       $mail->From    = $_config['contact_email'];\r
+                       $mail->Subject = $_config['site_name'] . ' - ' . _AT('email_confirmation_subject');\r
+                       $mail->Body    = _AT('email_confirmation_message', $_config['site_name'], $confirmation_link);\r
+\r
+                       $mail->Send();\r
+               }\r
+\r
+               $msg->addFeedback('PROFILE_UPDATED_ADMIN');\r
+               if (isset($_POST['ml']) && $_REQUEST['ml']) {\r
+                       header('Location: '.AT_BASE_HREF.'admin/master_list.php');\r
+               } else {\r
+                       header('Location: '.AT_BASE_HREF.'admin/users.php');\r
+               }\r
+               exit;\r
+       }\r
+}\r
+\r
+$id = intval($_REQUEST['id']);\r
+\r
+if (empty($_POST)) {\r
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."members WHERE member_id = $id";\r
+       $result = mysql_query($sql, $db);\r
+       if (!($row = mysql_fetch_assoc($result))) {\r
+               require(AT_INCLUDE_PATH.'header.inc.php');      \r
+               $msg->addError('USER_NOT_FOUND');       \r
+               $msg->printAll();\r
+               require(AT_INCLUDE_PATH.'footer.inc.php'); \r
+               exit;\r
+       }\r
+       \r
+       $_POST  = $row;\r
+       list($_POST['year'],$_POST['month'],$_POST['day']) = explode('-', $row['dob']);\r
+       //$_POST['password2']  = $_POST['password'];\r
+       $_POST['old_status'] = $_POST['status'];\r
+\r
+       if (admin_authenticate(AT_ADMIN_PRIV_USERS, TRUE) && defined('AT_MASTER_LIST') && AT_MASTER_LIST) {\r
+               $sql    = "SELECT public_field FROM ".TABLE_PREFIX."master_list WHERE member_id=$id";\r
+               $result = mysql_query($sql, $db);\r
+               if ($row = mysql_fetch_assoc($result)) {\r
+                       $_POST['old_student_id'] = $row['public_field'];\r
+                       $_POST['student_id'] = $row['public_field'];\r
+               }\r
+       }\r
+}\r
+\r
+$savant->assign('languageManager', $languageManager);\r
+\r
+if (isset($_REQUEST['ml']) && $_REQUEST['ml']) {\r
+       // redirect back to the master list\r
+       $savant->assign('ml', 1);\r
+} else {\r
+       $savant->assign('ml', 0);\r
+}\r
+\r
+\r
+/* HAVE TO SEND MEMBER_ID THROUGH FORM AS A HIDDEN POST VARIABLE!!! */\r
+/* PUT IN IF LOOP THAT LETS YOU SEE STATUS RADIO BUTTONS */\r
+$savant->display('registration.tmpl.php');\r
+\r
+?>
\ No newline at end of file
diff --git a/admin/enrollment/enroll_edit.php b/admin/enrollment/enroll_edit.php
new file mode 100644 (file)
index 0000000..de76a2b
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+admin_authenticate(AT_ADMIN_PRIV_ENROLLMENT);
+
+$course_id = intval($_REQUEST['course_id']);
+
+require(AT_INCLUDE_PATH.'html/enroll_edit.inc.php');
+exit;
+?>
\ No newline at end of file
diff --git a/admin/enrollment/index.php b/admin/enrollment/index.php
new file mode 100644 (file)
index 0000000..6251b9d
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+admin_authenticate(AT_ADMIN_PRIV_ENROLLMENT);
+
+if (!isset($_REQUEST['course_id'])) {
+       $sql = "SELECT course_id FROM ".TABLE_PREFIX."courses ORDER BY title LIMIT 1";
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)) {
+               $course_id = intval($row['course_id']);
+       } else {
+               require(AT_INCLUDE_PATH.'header.inc.php');              
+               echo _AT('none_found');
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+} else {
+       $course_id = intval($_REQUEST['course_id']);
+}
+if (isset($system_courses[$course_id]['member_id'])) {
+       require(AT_INCLUDE_PATH.'html/enrollment.inc.php');
+}
+exit;
+?>
\ No newline at end of file
diff --git a/admin/enrollment/privileges.php b/admin/enrollment/privileges.php
new file mode 100644 (file)
index 0000000..2dde790
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+admin_authenticate(AT_ADMIN_PRIV_ENROLLMENT);
+
+$course_id = intval($_REQUEST['course_id']);
+
+require(AT_INCLUDE_PATH.'html/privileges.inc.php');
+exit;
+?>
\ No newline at end of file
diff --git a/admin/error_logging.php b/admin/error_logging.php
new file mode 100644 (file)
index 0000000..d211a55
--- /dev/null
@@ -0,0 +1,176 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+
+<form name="form" method="post" action="admin/error_logging_details.php">
+<table class="data" summary="" rules="cols">
+<thead>
+<tr>
+       <th><?php echo _AT('profile');   ?></th>
+       <th><?php echo _AT('date');      ?></th>
+       <th><?php echo _AT('bug_count'); ?></th>
+</tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="3">
+               <input type="submit" name="view" value="<?php echo _AT('view_profile_bugs'); ?>" /> 
+               <input type="submit" name="delete" value="<?php echo _AT('delete_profile'); ?>" />
+       </td>
+</tr>
+</tfoot>
+<tbody>
+<?php
+               
+               $dir_ = AT_CONTENT_DIR . 'logs';
+               if (!is_dir($dir_)) {
+                       mkdir($dir_);
+               }
+
+               if (!($dir = @opendir($dir_))) {
+                       $msg->printNoLookupFeedback('Could not access /content/logs. Check that the permission for the <strong>Server</string> user are r+w to it');
+                       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+                       
+                       exit;
+               }
+               
+               /**
+                * Run through the logs directory and lets get all the profiles of all the logs of all the dates, sort
+                * by primary key as date, secondary key is profile name
+                */ 
+               $logdirs;
+                
+               // loop through folder to get files and directory listing
+               while (($file = readdir($dir)) !== false) {
+
+                       /* if the name is not a directory */
+                       if( ($file == '.') || ($file == '..')) {
+                               continue;
+                       }
+
+                       if (is_dir($dir_ . '/' . $file)) {
+                               $logdirs{$file} = $file; // store the day log dir
+                       }
+               }
+               closedir($dir); // clean it up
+
+               if (empty($logdirs)) { ?>
+                       <tr>
+                               <td colspan="3"><?php echo _AT('none_found'); ?></td>
+                       </tr>
+               <?php
+               } else {
+               
+                       $count_ = 1;
+                       foreach ($logdirs as $row => $val) {
+                               $log_profiles; // store all the profiles under the dir /content/logs/$val
+                               $log_profiles_bug_count; // store the amount of bugs per profile
+                               
+                               if (!($dir = opendir($dir_ . '/' . $val))) {
+                                       $msg->printNoLookupFeedback('Could not access /content/logs/' . $val . '. Check that the permission for the <strong>Server</string> user are r+w to it');
+                                       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+                       
+                                       exit;
+                               }
+                               // Open a read pointer to run through each log date directory getting all the profiles
+                               while (($file = readdir($dir)) !== false) {
+               
+                                       if (($file == '.') || ($file == '..') || is_dir($file)) {
+                                               continue;
+                                       }
+               
+                                       if (strpos($file, 'profile')    !== false) { // found a profile, store its md5 key identifier
+                                               $tmp_ = substr($file, strpos($file, '_') + 1);
+                                               $tmp_ = substr($tmp_, 0, strpos($tmp_, '.log.php'));
+                                               $log_profiles{$file} = $tmp_;
+                                       }
+                                       
+                               }
+                               closedir($dir); // clean it up
+                               
+                               /**
+                                * Open a read pointer to run through each log date directory getting all the bugs associated
+                                * all the profiles in $log_profiles
+                                */
+                               if (empty($log_profiles)) { 
+                                       $msg->printNoLookupFeedback('Warning. No profile found in ' . $dir_ . '/' . $val);
+                                       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+                       
+                                       exit;
+                               }
+                       
+                               foreach ($log_profiles as $elem => $val_) {
+                                       $count = 0;
+                                       
+                                       /* for each profile get the number of bugs associated with it */
+                                       if (!($dir = opendir($dir_ . '/' . $val))) {
+                                               $msg->printNoLookupFeedback('Could not access /content/logs' . $val . '. Check that the permission for the <strong>Server</string> user are r+w to it');
+                                               require(AT_INCLUDE_PATH.'footer.inc.php'); 
+                       
+                                               exit;
+                                       }
+                                       
+                                       while (($file = readdir($dir)) !== false) {
+                       
+                                               // make sure we ignore profiles too!, just look at bug files
+                                               if( ($file == '.') || ($file == '..') || is_dir($file) || (strpos($file, 'profile') !== false)) {
+                                                       continue;
+                                               }
+
+                                               // found a bug that maps to $val_ md5 profile identifer
+                                               if (strpos($file, $val_)        !== false) { 
+                                                       $count++;
+                                               }
+                                       }
+                                       closedir($dir);
+
+                                       // store the amount of bugs associated with profile
+                                       $log_profiles_bug_count{$val}[$val_] = $count;
+                               }
+                               $log_profiles = array();
+                       }
+                       /**
+                        * At this point ($log_profiles => key) = ($log_profiles_bug_count => key).
+                        *
+                        * Lets print out <td> rows corresponding to all profiles found in the following format:
+                        *
+                        * Profile name, profile date, profile bug count. 
+                        */             
+                       foreach ($log_profiles_bug_count as $day => $profile) :
+                                foreach ($profile as $stamp => $total) :
+                       ?>
+                                       <tr onmousedown="document.form['<?php echo $stamp.$day; ?>'].checked = true;rowselect(this);" id="r_<?php echo $stamp.$day; ?>">
+                                               <td><input type="radio" id="<?php echo $stamp.$day; ?>" value="<?php echo $stamp.':'.$day; ?>" name="data" /><label for="<?php echo $stamp.$day; ?>"><?php echo $count_; ?></label></td>
+                                               <td><?php echo $day; ?></td>
+                                               <td><?php echo $total; ?></td>
+                                       </tr>
+                       <?php
+                                       $count_++;
+                               endforeach;
+                       endforeach;
+               }
+       
+?>
+</tbody>
+</table>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/error_logging_bundle.php b/admin/error_logging_bundle.php
new file mode 100644 (file)
index 0000000..4f211ac
--- /dev/null
@@ -0,0 +1,283 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);
+
+if (isset($_POST['back'])) {
+       header('Location: error_logging.php');
+       exit;
+}
+
+if (isset($_POST['step2'])) { // e-mail bundle
+
+       if ($_POST['email_add'] == '') {
+               $msg->addError(array('EMPTY_FIELDS', _AT('recipient_address')));
+
+               header('Location: ' . $_SERVER['PHP_SELF']);
+               exit;
+       }
+       /* First lets check if they selected any profiles to bundle, run through $POST['file(\d)'] */
+       foreach($_POST as $elem => $val) {
+               if (strpos($elem, 'file') !== false) {
+                       $found = true;
+                       
+                       $work = $val;
+                       
+                       $date = substr($work, 0, strpos($work, ':'));
+                       $id = substr($work, strpos($work, ':') + 1);
+                       /* Parse the variable */
+                       $profiles{$id} = $date;
+               }
+       }
+       
+       if ($found === true) {
+               require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+               require(AT_INCLUDE_PATH.'classes/zipfile.class.php');
+       
+               $mail = new ATutorMailer;
+       
+               $zipfile = new zipfile();
+
+               $dir_ = AT_CONTENT_DIR . 'logs';
+
+               foreach($profiles as $elem => $val) {
+                       $store_some;
+
+                       // read the dir where this profile and its associated log files are located
+                       if (!($dir = opendir($dir_ . '/' . $val))) {
+                                       $msg->printNoLookupFeedback('Could not access /content/logs/' . $val . '. Check that the permission for the <strong>Server</string> user are r+w to it');
+                                       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+                       
+                                       exit;
+                               }
+                               // Open a read pointer to run through each log date directory getting all the profiles
+                               while (($file = readdir($dir)) !== false) {
+               
+                                       if (($file == '.') || ($file == '..') || is_dir($file)) {
+                                               continue;
+                                       }
+               
+                                       // any files mathcing the $elem key correspond to this profile
+                                       if (strpos($file, $elem)        !== false) { 
+                                               $store_some{$dir_ . '/'.  $val . '/' . $file} = $file;
+                                       }
+                                       
+                               }
+                               closedir($dir); // clean it up
+                               
+                               // The dir pointer is closed lets add to the zip
+                               foreach($store_some as $val_ => $e)
+                                       $zipfile->add_file(file_get_contents($val_), $e);
+               }
+               
+               $zipfile->close();
+
+               if ($file_handle = fopen($dir_ . '/bundle.log', "w")) {
+                               if (!fwrite($file_handle, $zipfile->get_file())) { }
+               } else { }
+               fclose($file_handle);
+
+               $mail->From = $_config['contact_email'];
+               $mail->addAddress($_POST['email_add']);
+               $mail->Subject = _AT('log_file_bundle');
+               $mail->Body    = _AT('see_attached');
+               $mail->AddAttachment($dir_ . '/bundle.log');
+       
+               // clean up the file at the redirection point
+               if(!$mail->Send()) {
+                  $msg->addError('SENDING_ERROR');
+                  /* Make sure the tmp bundle file never exists past the lifetime of the bundle manager page */
+                  unlink($dir_ . '/bundle.log');
+                  header('Location: ' . $_SERVER['PHP_SELF']);
+                  exit;
+               }
+               unset($mail);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               /* Make sure the tmp bundle file never exists past the lifetime of the bundle manager page */
+               unlink($dir_ . '/bundle.log');
+               header('Location: error_logging.php');
+               exit;
+       } else {
+               $msg->addError('NO_LOGS_SELECTED');
+               header('Location: ' . $_SERVER['PHP_SELF']);
+               exit;
+       }
+} // else step 1
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$msg->printAll();
+
+
+?>
+<h3><?php echo _AT('profile_bundle_select'); ?></h3>
+
+<p><?php echo _AT('admin_bundle_instructions'); ?></p>
+
+<form name="form1" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<table class="data" summary="" rules="cols">
+<thead>
+<tr>
+       <th span="col"><?php echo _AT('profile');   ?></th>
+       <th span="col"><?php echo _AT('date');      ?></th>
+       <th span="col"><?php echo _AT('bug_count'); ?></th>
+</tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="3">
+               <label for="email" ><?php echo _AT('recipient_address'); ?></label><br />
+               <input type="text" id="email" name="email_add" value="" />
+               <input type="submit" name="step2" value="<?php echo _AT('send_bundle'); ?>" />
+               <input type="submit" name="back" value="<?php echo _AT('back_to_main'); ?>" />          
+       </td>
+</tr>
+</tfoot>
+<tbody>
+<?php
+       
+       $dir_ = AT_CONTENT_DIR . 'logs';
+               
+               if (!($dir = opendir($dir_))) {
+                       $msg->printNoLookupFeedback('Could not access /content/logs. Check that the permission for the <strong>Server</string> user are r+w to it');
+                       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+                       
+                       exit;
+               }
+               
+               /**
+                * Run through the logs directory and lets get all the profiles of all the logs of all the dates, sort
+                * by primary key as date, secondary key is profile name
+                */ 
+               $logdirs;
+                
+               // loop through folder to get files and directory listing
+               while (($file = readdir($dir)) !== false) {
+
+                       /* if the name is not a directory */
+                       if( ($file == '.') || ($file == '..')) {
+                               continue;
+                       }
+
+                       if (is_dir($dir_ . '/' . $file)) {
+                               $logdirs{$file} = $file; // store the day log dir
+                       }
+               }
+               closedir($dir); // clean it up
+
+               if (empty($logdirs)) { ?>
+                       <tr>
+                               <td colspan="3"><?php echo _AT('none_found'); ?></td>
+                       </tr>
+               <?php
+               } else {
+               
+                       $count_ = 1;
+                       foreach ($logdirs as $row => $val) {
+                               $log_profiles; // store all the profiles under the dir /content/logs/$val
+                               $log_profiles_bug_count; // store the amount of bugs per profile
+                               
+                               if (!($dir = opendir($dir_ . '/' . $val))) {
+                                       $msg->printNoLookupFeedback('Could not access /content/logs/' . $val . '. Check that the permission for the <strong>Server</string> user are r+w to it');
+                                       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+                       
+                                       exit;
+                               }
+                               // Open a read pointer to run through each log date directory getting all the profiles
+                               while (($file = readdir($dir)) !== false) {
+               
+                                       if (($file == '.') || ($file == '..') || is_dir($file)) {
+                                               continue;
+                                       }
+               
+                                       if (strpos($file, 'profile')    !== false) { // found a profile, store its md5 key identifier
+                                               $tmp_ = substr($file, strpos($file, '_') + 1);
+                                               $tmp_ = substr($tmp_, 0, strpos($tmp_, '.log.php'));
+                                               $log_profiles{$file} = $tmp_;
+                                       }
+                                       
+                               }
+                               closedir($dir); // clean it up
+                               
+                               /**
+                                * Open a read pointer to run through each log date directory getting all the bugs associated
+                                * all the profiles in $log_profiles
+                                */
+                               if (empty($log_profiles)) { 
+                                       $msg->printNoLookupFeedback('Warning. No profile found in ' . $dir_ . '/' . $val);
+                                       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+                       
+                                       exit;
+                               }
+                       
+                               foreach ($log_profiles as $elem => $val_) {
+                                       $count = 0;
+                                       
+                                       /* for each profile get the number of bugs associated with it */
+                                       if (!($dir = opendir($dir_ . '/' . $val))) {
+                                               $msg->printNoLookupFeedback('Could not access /content/logs' . $val . '. Check that the permission for the <strong>Server</string> user are r+w to it');
+                                               require(AT_INCLUDE_PATH.'footer.inc.php'); 
+                       
+                                               exit;
+                                       }
+                                       
+                                       while (($file = readdir($dir)) !== false) {
+                       
+                                               // make sure we ignore profiles too!, just look at bug files
+                                               if( ($file == '.') || ($file == '..') || is_dir($file) || (strpos($file, 'profile') !== false)) {
+                                                       continue;
+                                               }
+
+                                               // found a bug that maps to $val_ md5 profile identifer
+                                               if (strpos($file, $val_)        !== false) { 
+                                                       $count++;
+                                               }
+                                       }
+                                       closedir($dir);
+
+                                       // store the amount of bugs associated with profile
+                                       $log_profiles_bug_count{$val}[$val_] = $count;
+                               }
+                               $log_profiles = array();
+                       }
+                       /**
+                        * At this point ($log_profiles => key) = ($log_profiles_bug_count => key).
+                        *
+                        * Lets print out <td> rows corresponding to all profiles found in the following format:
+                        *
+                        * Profile name, profile date, profile bug count. 
+                        */             
+                       foreach ($log_profiles_bug_count as $day => $profile) :
+                                foreach ($profile as $stamp => $total) :
+                       ?>
+                                       <tr onmousedown="document.form1['<?php echo $stamp.$day; ?>'].checked = !document.form1['<?php echo $stamp.$day; ?>'].checked;">
+                                               <td><input type="checkbox" id="<?php echo $stamp.$day; ?>" value="<?php echo $day.':'.$stamp; ?>" name="file<?php echo $count_; ?>" onmouseup="this.checked=!this.checked" /><?php echo $count_; ?></td>                                        
+                                               <td><?php echo $day; ?></td>
+                                               <td><?php echo $total; ?></td>
+                                       </tr>
+                       <?php
+                                       $count_++;
+                               endforeach;
+                       endforeach;
+               }
+       
+?>
+</tbody>
+</table>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/error_logging_details.php b/admin/error_logging_details.php
new file mode 100644 (file)
index 0000000..af4ff2c
--- /dev/null
@@ -0,0 +1,194 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);
+
+if (!isset($_POST['data'])) {
+       $msg->addError('NO_PROFILE_SELECTED');
+       header('Location: error_logging.php');
+       exit;
+} // else we have a profile we can work with
+
+if (isset($_POST['delete'])) {
+
+       $key = substr($_POST['data'], 0, strpos($_POST['data'], ':'));
+       $date = substr($_POST['data'], strpos($_POST['data'], ':') + 1);
+       $dir_ = AT_CONTENT_DIR . 'logs/' . $date;
+       $delete_store;
+       
+       if (!($dir = opendir($dir_))) {
+                       $msg->printNoLookupFeedback('Could not access /content/logs/' . $date . '. Check that the permission for the <strong>Server</string> user are r+w to it');
+                       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+                       
+                       exit;
+               }
+       
+       $cnt = 0;       
+       // Open a read pointer to run through each log date directory getting all the profiles
+       while (($file = readdir($dir)) !== false) {
+               
+               if (($file == '.') || ($file == '..') || is_dir($file)) {
+                       continue;
+               }
+               
+               if (strpos($file, $key) !== false) { // found a bug associated with our profile key
+                       $delete_store{$file} = $file;
+               } else {
+                       $cnt++;
+               }
+                                       
+       }
+       closedir($dir); // clean it up
+       
+       if (count($delete_store) > 0) {
+               // Now run through the files and unlink them all
+               foreach($delete_store as $elem => $val) 
+                       unlink($dir_ . '/' . $elem);
+       }
+               
+       // remove the directory as well if there are no oother profiles in it
+       if ($cnt == 0) {
+               rmdir($dir_);
+       }
+       
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: error_logging.php');
+       exit;
+} 
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if (isset($_POST['view'])) {
+       // Grab all the bugs associated with this $_POST['data'] corresponding md5 key
+       $key = substr($_POST['data'], 0, strpos($_POST['data'], ':'));
+       $date = substr($_POST['data'], strpos($_POST['data'], ':') + 1);
+       $dir_ = AT_CONTENT_DIR . 'logs/' . $date;
+       $log_profiles_bugs;
+               
+       ?>
+
+       <form name="form" method="post" action="<?php echo 'admin/error_logging_view.php'; ?>">
+       
+       <table class="data" summary="" rules="cols">
+       <thead>
+       <tr>
+               <th scope="col"><?php echo _AT('bug_identifier'); ?></th>
+               <th scope="col"><?php echo _AT('timestamp');      ?></th>
+       </tr>
+       </thead>
+       <tfoot>
+       <tr>
+               <td colspan="2">
+                       <input type="hidden" name="profile_id" value="<?php echo $key; ?>"/>
+                       <input type="hidden" name="profile_date" value="<?php echo $date; ?>"/>
+                       <input type="submit" name="view" value="<?php echo _AT('view_selected_bugs'); ?>" />
+                       <input type="submit" name="back" value="<?php echo _AT('back_to_main'); ?>" />
+               </td>
+       </tr>
+       </tfoot>
+       <tbody>
+       <?php
+               if (!($dir = opendir($dir_))) {
+                       $msg->printNoLookupFeedback('Could not access /content/logs/' . $date . '. Check that the permission for the <strong>Server</string> user are r+w to it');
+                       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+                       
+                       exit;
+               }
+               
+               // Open a read pointer to run through each log date directory getting all the profiles
+               while (($file = readdir($dir)) !== false) {
+               
+                       if (($file == '.') || ($file == '..') || is_dir($file) || (strpos($file, 'profile')     !== false)) {
+                               continue;
+                       }
+               
+                       if (strpos($file, $key) !== false) { // found a bug associated with our profile key
+                               $log_profile_bugs{$file} = $file;
+                       }
+                                       
+               }
+               closedir($dir); // clean it up          
+               
+               if (empty($log_profile_bugs)) { ?>
+                       <tr>
+                               <td align="center" colspan="2"><small><?php echo _AT('none_found'); ?></small></td>
+                       </tr>
+                       <tr><td height="1" class="row2" colspan="2"></td></tr>
+               <?php
+               } else {
+                       $count = 0;
+                       
+                       $id_cnt = 1; // give each bug an easier to understand id onscreen
+                       foreach ($log_profile_bugs as $elem => $lm) {
+                               // construct timestamp from millis since epoch in bug identifier
+                               $timestamp = substr($lm, strpos($lm, '_') + 1);
+                               $timestamp = substr($timestamp, 0, strpos($lm, '_') + 2);
+                       
+                               $timestamp = AT_Date(_AT('inbox_date_format'), $timestamp, AT_DATE_UNIX_TIMESTAMP);
+                       
+                               $str_prefix = substr($lm, 0, strpos($lm, '_'));
+                       ?>
+                               <tr onmousedown="document.form['q<?php echo $lm; ?>'].checked = !document.form['q<?php echo $lm; ?>'].checked;">
+                                       <td><input type="checkbox" value="<?php echo $date . '/' . $lm; ?>" name="file<?php echo $count; ?>" id="q<?php echo $lm; ?>" onmouseup="this.checked=!this.checked" /><?php echo $id_cnt . '_' . $str_prefix; ?></td>
+                                       <td><?php echo $timestamp; ?></td>
+                               </tr>
+                               <?php $count++; $id_cnt++;
+                       }
+               }
+               ?>
+               </tbody>
+               </table>
+
+               </form>
+       <?php
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+               
+} else if (isset($_POST['delete'])) {
+       $key = substr($_POST['data'], 0, strpos($_POST['data'], ':'));
+       $date = substr($_POST['data'], strpos($_POST['data'], ':') + 1);
+       $dir_ = AT_CONTENT_DIR . 'logs/' . $date;
+       $delete_store;
+       
+       if (!($dir = opendir($dir_))) {
+                       $msg->printNoLookupFeedback('Could not access /content/logs/' . $date . '. Check that the permission for the <strong>Server</string> user are r+w to it');
+                       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+                       
+                       exit;
+               }
+               
+       // Open a read pointer to run through each log date directory getting all the profiles
+       while (($file = readdir($dir)) !== false) {
+               
+               if (($file == '.') || ($file == '..') || is_dir($file)) {
+                       continue;
+               }
+               
+               if (strpos($file, $key) !== false) { // found a bug associated with our profile key
+                       $delete_store{$file} = $file;
+               }
+                                       
+       }
+       closedir($dir); // clean it up
+       
+       // Now run through the files and unlink them all
+       foreach($delete_store as $elem => $val) 
+               unlink($dir_ . '/' . $elem);
+               
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: ' . $_SERVER['PHP_SELF']);
+}
+?>
\ No newline at end of file
diff --git a/admin/error_logging_reset.php b/admin/error_logging_reset.php
new file mode 100644 (file)
index 0000000..b078e5b
--- /dev/null
@@ -0,0 +1,49 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: ./error_logging.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       \r
+       //clean up the db\r
+       require(AT_INCLUDE_PATH.'lib/filemanager.inc.php');\r
+\r
+       if (($result = clr_dir(AT_CONTENT_DIR . 'logs/'))) {\r
+               $msg->addFeedback('ERROR_LOG_RESET');\r
+       } else {\r
+               $msg->addError('ERROR_LOG_NOT_RESET');\r
+       }\r
+\r
+       header('Location: ./error_logging.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+//print confirmation\r
+$hidden_vars['all'] = TRUE;\r
+\r
+$confirm = array('RESET_ERROR_LOG', $_SERVER['PHP_SELF']);\r
+$msg->addConfirm($confirm, $hidden_vars);\r
+$msg->printConfirm();\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/admin/error_logging_view.php b/admin/error_logging_view.php
new file mode 100644 (file)
index 0000000..fea6884
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);
+
+if (isset($_POST['back'])) {
+       header('Location: error_logging.php');
+       exit;
+}
+
+$files = array();
+if (isset($_POST['view'])) { // check if a bug was selected
+       foreach($_POST as $elem => $val) {
+               $str_ = substr($elem, 0, 4);
+               if ($str_  == 'file') {
+                       $files[] = $elem;
+               }
+       }
+       if (empty($files)) {
+               $msg->addError('NO_LOG_SELECTED');
+               header('Location: error_logging.php');
+               exit;
+       }
+}
+
+$back_ref = $_POST['profile_id'] . ':' . $_POST['profile_date'];
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+<form name="form" method="post" action="<?php echo 'admin/error_logging_details.php'; ?>">
+<input type="hidden" name="data" value="<?php echo $back_ref; ?>" />
+<input type="hidden" name="view" value="<?php echo ''; ?>" />
+
+<div class="input-form">
+       <div class="row">
+               <h3><?php echo _AT('viewing_errors'); ?></h3>
+       </div><?php
+
+       foreach ($files as $file) {
+               if (isset($_POST[$file])) {
+                       $dump = @file_get_contents(AT_CONTENT_DIR . 'logs/' . $_POST[$file]);   
+                       if ($dump !== false) { ?>
+
+                               <div class="row">
+                                       <?php echo $dump; ?>
+                               </div><?php
+
+                       } else {
+                               $msg->printErrors(array('CANNOT_READ_FILE', AT_CONTENT_DIR . 'logs/' . $_POST[$file]));
+                       }
+               }       
+       } ?>
+
+       <div class="row buttons">
+               <input type="submit" name="back" value="<?php echo _AT('back_to_profile'); ?>" />  
+       </div>
+</div>
+</form>
+
+<?php  require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/fix_content.php b/admin/fix_content.php
new file mode 100644 (file)
index 0000000..21db2d0
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+echo '<div style="padding-left: 30px;"><pre>';
+
+echo "cpID\torder\t cID";
+
+$sql    = "SELECT content_id, content_parent_id, ordering, course_id FROM ".TABLE_PREFIX."content ORDER BY course_id, content_parent_id, ordering";
+$result = mysql_query($sql, $db);
+while ($row = mysql_fetch_assoc($result)) {
+       if ($current_course_id != $row['course_id']) {
+               echo "\n\n-- course id $row[course_id]\n\n";
+               $current_course_id = $row['course_id'];
+               unset($current_parent_id);
+               unset($ordering);
+       }
+       echo $row['content_parent_id'] . "\t" . $row['ordering'] . "\t" . $row['content_id'];
+       if ($current_parent_id != $row['content_parent_id']) {
+               $current_parent_id = $row['content_parent_id'];
+               $ordering = 1;
+       }
+
+       if ($row['ordering'] != $ordering) {
+               echo "\t mismatch : expecting $ordering [fixed]";
+               $sql = "UPDATE ".TABLE_PREFIX."content SET ordering=$ordering WHERE content_id=$row[content_id]";
+               mysql_query($sql, $db);
+               write_to_log(AT_ADMIN_LOG_UPDATE, 'content', mysql_affected_rows($db), $sql);
+       }
+
+        echo "\n";
+
+       $ordering++;
+}
+
+echo' </pre></div>';
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/admin/forum_add.php b/admin/forum_add.php
new file mode 100644 (file)
index 0000000..5eb734b
--- /dev/null
@@ -0,0 +1,112 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_FORUMS);
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'admin/forums.php');
+       exit;
+} else if (isset($_POST['add_forum'])) {
+       $missing_fields = array();
+
+       if (empty($_POST['title'])) {
+               $missing_fields[] = _AT('title');
+       } 
+
+       if (empty($_POST['courses'])) {
+               $missing_fields[] = _AT('courses');
+       } 
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       $_POST['edit'] = intval($_POST['edit']);
+
+       if (!($msg->containsErrors())) {
+               //add forum
+               $sql    = "INSERT INTO ".TABLE_PREFIX."forums (title, description, mins_to_edit) VALUES ('" . $_POST['title'] . "','" . $_POST['description'] ."', $_POST[edit])";
+               $result = mysql_query($sql, $db);
+               $forum_id = mysql_insert_id($db);
+               write_to_log(AT_ADMIN_LOG_INSERT, 'forums', mysql_affected_rows($db), $sql);
+
+               //for each course, add an entry to the forums_courses table
+               foreach ($_POST['courses'] as $course) {
+                       $sql    = "INSERT INTO ".TABLE_PREFIX."forums_courses VALUES (" . $forum_id . "," . $course . ")";
+                       $result = mysql_query($sql, $db);
+                       write_to_log(AT_ADMIN_LOG_INSERT, 'forums_courses', mysql_affected_rows($db), $sql);
+               }
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               if($course =="0"){
+                       $msg->addFeedback('FORUM_POSTING');
+               }
+               header('Location: '.AT_BASE_HREF.'admin/forums.php');
+               exit;
+       }
+}
+
+$onload = 'document.form.title.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="add_forum" value="true">
+
+<div class="input-form">
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php echo _AT('title'); ?></label><br />
+               <input type="text" name="title" size="40" id="title" value="<?php echo $_POST['title']; ?>" />
+       </div>
+
+       <div class="row">
+               <label for="body"><?php echo _AT('description'); ?></label><br />
+               <textarea name="description" cols="45" rows="2" id="body" wrap="wrap"><?php echo $_POST['description']; ?></textarea>
+       </div>
+
+       <div class="row">
+               <label for="edit"><?php echo _AT('allow_editing'); ?></label><br />
+               <input type="text" name="edit" size="3" id="edit" value="<?php echo intval($row['mins_to_edit']); ?>" /> <?php echo _AT('in_minutes'); ?>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="courses"><?php echo _AT('courses'); ?></label><br />
+               <?php if ($system_courses): ?>
+                       <select name="courses[]" id="courses" multiple="multiple" size="5"><?php
+               
+                               $sql = "SELECT course_id, title FROM ".TABLE_PREFIX."courses ORDER BY title";
+                               $result = mysql_query($sql, $db);
+                               while ($row = mysql_fetch_assoc($result)) {
+                                       echo '<option value="'.$row['course_id'].'">'.$row['title'].'</option>';                
+                               }
+                               ?>
+                       </select>
+               <?php else: ?>
+                       <span id="courses"><?php echo _AT('no_courses_found'); ?></span>
+               <?php endif; ?>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" /> 
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/forum_delete.php b/admin/forum_delete.php
new file mode 100644 (file)
index 0000000..7daab0c
--- /dev/null
@@ -0,0 +1,77 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+admin_authenticate(AT_ADMIN_PRIV_FORUMS);\r
+\r
+require(AT_INCLUDE_PATH.'lib/forums.inc.php');\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: forums.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       $forum_id = intval($_POST['forum']);\r
+\r
+       $sql    = "SELECT post_id FROM ".TABLE_PREFIX."forums_threads WHERE forum_id=$forum_id";\r
+       $result = mysql_query($sql, $db);\r
+       while ($row = mysql_fetch_array($result)) {\r
+               $sql     = "DELETE FROM ".TABLE_PREFIX."forums_accessed WHERE post_id=$row[post_id]";\r
+               $result2 = mysql_query($sql, $db);\r
+       }\r
+\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."forums_subscriptions WHERE forum_id=$forum_id";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."forums_threads WHERE forum_id=$forum_id";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."forums_courses WHERE forum_id=$forum_id";\r
+       $result = mysql_query($sql, $db);\r
+       write_to_log(AT_ADMIN_LOG_DELETE, 'forums_courses', mysql_affected_rows($db), $sql);\r
+\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."forums WHERE forum_id=$forum_id";\r
+       $result = mysql_query($sql, $db);\r
+       write_to_log(AT_ADMIN_LOG_DELETE, 'forums', mysql_affected_rows($db), $sql);\r
+       \r
+       $sql = "OPTIMIZE TABLE ".TABLE_PREFIX."forums_threads";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: forums.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+\r
+       $_GET['forum'] = intval($_GET['forum']); \r
+\r
+       $row = get_forum($_GET['forum']);\r
+\r
+       if (!is_array($row)) {\r
+               $msg->addError('FORUM_NOT_FOUND');\r
+               $msg->printErrors();\r
+       } else {\r
+\r
+               $hidden_vars['delete_forum'] = TRUE;\r
+               $hidden_vars['forum'] = $_GET['forum'];\r
+               $msg->addConfirm(array('DELETE_FORUM', AT_print($row['title'], 'forums.title')), $hidden_vars);\r
+               $msg->printConfirm();\r
+       }\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php'); \r
+\r
+?>
\ No newline at end of file
diff --git a/admin/forum_edit.php b/admin/forum_edit.php
new file mode 100644 (file)
index 0000000..734aa30
--- /dev/null
@@ -0,0 +1,167 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+admin_authenticate(AT_ADMIN_PRIV_FORUMS);
+
+require(AT_INCLUDE_PATH.'lib/forums.inc.php');
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'admin/forums.php');
+       exit;
+} else if (isset($_POST['edit_forum'])) {
+       $missing_fields = array();
+       if (empty($_POST['title'])) {
+               $missing_fields[] = _AT('title');
+       }
+
+       if (empty($_POST['courses'])) {
+               $missing_fields[] = _AT('courses');
+       } 
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       if (!($msg->containsErrors())) {
+
+               //update forum
+               $forum_id = intval($_POST['forum']);
+               $_POST['title']  = $addslashes($_POST['title']);
+               $_POST['edit'] = intval($_POST['edit']);
+               $_POST['description']  = $addslashes($_POST['description']);
+
+               $sql    = "UPDATE ".TABLE_PREFIX."forums SET title='" . $_POST['title'] . "', description='" . $_POST['description'] . "', last_post=last_post, mins_to_edit=$_POST[edit] WHERE forum_id=".$forum_id;
+               $result = mysql_query($sql, $db);
+               write_to_log(AT_ADMIN_LOG_UPDATE, 'forums', mysql_affected_rows($db), $sql);
+
+               // unsubscribe all the members who are NOT in $_POST['courses']
+               $courses_list = implode(',', $_POST['courses']);
+
+               // list of all the students who are in other courses as well
+               $sql     = "SELECT member_id FROM ".TABLE_PREFIX."course_enrollment WHERE course_id IN ($courses_list)";
+               $result2 = mysql_query($sql, $db);
+               while ($row2 = mysql_fetch_assoc($result2)) {
+                       $students[] = $row2['member_id'];
+               }
+
+               // list of students who must REMAIN subscribed!
+               $students_list = implode(',', $students);
+
+               if ($students_list) {
+                       // remove the subscriptions
+                       $sql    = "SELECT post_id FROM ".TABLE_PREFIX."forums_threads WHERE forum_id=$forum_id";
+                       $result2 = mysql_query($sql, $db);
+                       while ($row2 = mysql_fetch_assoc($result2)) {
+                               $sql     = "DELETE FROM ".TABLE_PREFIX."forums_accessed WHERE post_id=$row2[post_id] AND member_id NOT IN ($students_list)";
+                               $result3 = mysql_query($sql, $db);
+                       }
+
+                       $sql     = "DELETE FROM ".TABLE_PREFIX."forums_subscriptions WHERE forum_id=$forum_id AND member_id NOT IN ($students_list)";
+                       $result3 = mysql_query($sql, $db);
+               }
+
+               $sql = "DELETE FROM ".TABLE_PREFIX."forums_courses WHERE forum_id=$forum_id AND course_id NOT IN ($courses_list)";
+               $result = mysql_query($sql, $db);
+               write_to_log(AT_ADMIN_LOG_DELETE, 'forums_courses', mysql_affected_rows($db), $sql);
+
+               //update forums_courses
+               if (in_array('0', $_POST['courses'])) {
+                       //general course - used by all.  put one entry in forums_courses w/ course_id=0
+                       $sql    = "REPLACE INTO ".TABLE_PREFIX."forums_courses VALUES (" . $_POST['forum'] . ", 0)";
+                       $result = mysql_query($sql, $db);
+                       write_to_log(AT_ADMIN_LOG_REPLACE, 'forums_courses', mysql_affected_rows($db), $sql);
+               } else {
+                       foreach ($_POST['courses'] as $course) {
+                               $sql    = "REPLACE INTO ".TABLE_PREFIX."forums_courses VALUES (" . $_POST['forum'] . "," . $course . ")";
+                               $result = mysql_query($sql, $db);
+                               write_to_log(AT_ADMIN_LOG_REPLACE, 'forums_courses', mysql_affected_rows($db), $sql);
+                       }
+               }
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: '.AT_BASE_HREF.'admin/forums.php');
+               exit;
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+if (!($forum = @get_forum($_GET['forum']))) {
+       //no such forum
+       $msg->addError('FORUM_NOT_FOUND');
+       $msg->printAll();
+} else {
+       $msg->printAll();
+
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."forums_courses WHERE forum_id=$forum[forum_id]";
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_assoc($result)) {
+               $courses[] = $row['course_id'];         
+       }
+?>
+       <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+       <input type="hidden" name="edit_forum" value="true">
+       <input type="hidden" name="forum" value="<?php echo $_REQUEST['forum']; ?>">
+
+<div class="input-form">
+       <div class="row">
+               <label for="title"><div class="required" title="<?php echo _AT('required_field'); ?>">*</div><?php  echo _AT('title'); ?></label><br />
+               <input type="text" name="title" size="40" id="title" value="<?php echo $forum['title']?>" />
+       </div>
+
+       <div class="row">
+               <label for="body"><?php echo _AT('description'); ?></label><br />
+               <textarea name="description" cols="45" rows="5" id="body" wrap="wrap"><?php echo $forum['description']?></textarea>
+       </div>
+
+       <div class="row">
+               <label for="edit"><?php echo _AT('allow_editing'); ?></label><br />
+               <input type="text" name="edit" size="3" id="edit" value="<?php echo intval($forum['mins_to_edit']); ?>" /> <?php echo _AT('in_minutes'); ?>
+       </div>
+
+       <div class="row">
+               <label for="courses"><div class="required" title="<?php echo _AT('required_field'); ?>">*</div><?php echo _AT('courses'); ?></label><br />
+               <select name="courses[]" id="courses" multiple="multiple" size="5"><?php
+                       /*
+                       echo '<option value="0"';
+                       if ($courses[0] == 0) {
+                               echo ' selected="selected"';
+                       }
+                       echo '> '._AT('all').' </option>';
+                       */
+                       $sql = "SELECT course_id, title FROM ".TABLE_PREFIX."courses ORDER BY title";
+                       $result = mysql_query($sql, $db);
+                       while ($row = mysql_fetch_assoc($result)) {
+                               if (in_array($row['course_id'], $courses) ) {
+                                       echo '<option value="'.$row['course_id'].'" selected="selected">'.$row['title'].'</option>';            
+                               } else {
+                                       echo '<option value="'.$row['course_id'].'">'.$row['title'].'</option>';
+                               }
+                       }
+                       ?></select>
+       </div>
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php  echo _AT('submit'); ?>" accesskey="s" /> <input type="submit" name="cancel" value="<?php  echo _AT('cancel'); ?>" />
+       </div>
+</div>
+       </form>
+<?php
+}
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/admin/forums.php b/admin/forums.php
new file mode 100644 (file)
index 0000000..e28f3bc
--- /dev/null
@@ -0,0 +1,109 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+admin_authenticate(AT_ADMIN_PRIV_FORUMS);\r
+\r
+if (isset($_GET['edit'], $_GET['id'])) {\r
+       header('Location: forum_edit.php?forum='.$_GET['id']);\r
+       exit;\r
+} else if (isset($_GET['delete'], $_GET['id'])) {\r
+       header('Location: forum_delete.php?forum='.$_GET['id']);\r
+       exit;\r
+} else if (isset($_GET['delete']) || isset($_GET['edit'])) {\r
+       $msg->addError('NO_ITEM_SELECTED');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'lib/forums.inc.php');\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+\r
+?>\r
+<form name="form" method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<table class="data" summary="" rules="groups" style="width: 90%">\r
+<thead>\r
+<tr>\r
+       <th scope="col">&nbsp;</th>\r
+       <th scope="col"><?php echo _AT('title');       ?></th>\r
+       <th scope="col"><?php echo _AT('description'); ?></th>\r
+       <th scope="col"><?php echo _AT('courses');     ?></th>\r
+</tr>\r
+</thead>\r
+<tfoot>\r
+<tr>\r
+       <td colspan="4"><input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /></td>\r
+</tr>\r
+</tfoot>\r
+<tbody>\r
+<tr>\r
+       <th colspan="4"><?php echo _AT('shared_forums'); ?></th>\r
+</tr>\r
+<?php\r
+\r
+\r
+       $all_forums    = get_forums(0);\r
+       $num_shared    = count($all_forums['shared']);\r
+       $num_nonshared = count($all_forums['nonshared']);\r
+\r
+       if ($num_shared) {\r
+               foreach ($all_forums['shared'] as $forum) {\r
+                       echo '<tr onmousedown="document.form[\'f'.$forum['forum_id'].'\'].checked = true; rowselect(this);"  id="r_'.$forum['forum_id'].'">';\r
+                       echo '<td><input type="radio" name="id" value="'. $forum['forum_id'].'" id="f'.$forum['forum_id'].'"></td>';\r
+                       echo '  <td><label for="f'.$forum['forum_id'].'">' . $forum['title'] . '</label></td>';\r
+                       echo '  <td>' . $forum['description'] . '</td>';\r
+                       echo '  <td>';\r
+\r
+                       $courses = array();\r
+                       $sql = "SELECT F.course_id FROM ".TABLE_PREFIX."forums_courses F WHERE F.forum_id=$forum[forum_id]";\r
+                       $c_result = mysql_query($sql, $db);\r
+                       while ($course = mysql_fetch_assoc($c_result)) {\r
+                               $courses[] = $system_courses[$course['course_id']]['title'];\r
+                       }\r
+                       natcasesort($courses);\r
+                       echo implode(', ', $courses);\r
+                       echo '</td>';\r
+                       echo '</tr>';\r
+               }\r
+       } else {\r
+               echo '<tr>';\r
+               echo '  <td colspan="4"><em>' . _AT('no_forums') . '</em></td>';\r
+               echo '</tr>';\r
+       }\r
+?>\r
+</tbody>\r
+<tbody>\r
+       <tr>\r
+               <th colspan="4"><?php echo _AT('unshared_forums'); ?></th>\r
+       </tr>\r
+<?php if ($num_nonshared) : ?>\r
+       <?php foreach ($all_forums['nonshared'] as $forum) : ?>\r
+               <tr onmousedown="document.form['f<?php echo $forum['forum_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $forum['forum_id']; ?>">\r
+                       <td><input type="radio" name="id" value="<?php echo $forum['forum_id']; ?>" id="f<?php echo $forum['forum_id']; ?>" /></td>\r
+                       <td><label for="f<?php echo $forum['forum_id']; ?>"><?php echo $forum['title']; ?></label></td>\r
+                       <td><?php echo $forum['description']; ?></td>\r
+                       <td><?php echo $system_courses[$forum['course_id']]['title']; ?></td>\r
+               </tr>\r
+       <?php endforeach; ?>\r
+<?php else: ?>\r
+       <tr>\r
+               <td colspan="4"><em><?php echo _AT('no_forums'); ?></em></td>\r
+       </tr>\r
+<?php endif; ?>\r
+</tbody>\r
+</table>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/index.php b/admin/index.php
new file mode 100644 (file)
index 0000000..35674a7
--- /dev/null
@@ -0,0 +1,218 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate();
+
+if (defined('AT_DEVEL_TRANSLATE') && AT_DEVEL_TRANSLATE) { 
+       $msg->addWarning('TRANSLATE_ON');       
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if ($_config['check_version']) {
+       $request = @file('http://atutor.ca/check_atutor_version.php?return');
+       if ($request && version_compare(VERSION, $request[0], '<')) {
+               $msg->printFeedbacks('ATUTOR_UPDATE_AVAILABLE');
+       }
+}
+?>
+
+<div style="width: 40%; float: right; padding-top: 4px; padding-left: 10px;">
+
+       <?php if ($_config['allow_instructor_requests'] && admin_authenticate(AT_ADMIN_PRIV_USERS, AT_PRIV_RETURN)): ?> 
+               <?php
+                       $sql    = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."instructor_approvals";
+                       $result = mysql_query($sql, $db);
+                       $row    = mysql_fetch_assoc($result);
+               ?>
+       <div class="input-form" style="width: 98%;">
+               <form method="get" action="admin/instructor_requests.php">
+                       <div class="row">
+                               <h3><?php echo _AT('instructor_requests'); ?></h3>
+                               <p><?php echo _AT('instructor_requests_text', $row['cnt']); ?></p>
+                       </div>
+
+                       <div class="row buttons">
+                               <input type="submit" name="submit" value="<?php echo _AT('view'); ?>" />
+                       </div>
+               </form>
+       </div>
+       <?php endif; ?>
+
+       <?php 
+
+
+       $update_server = "update.atutor.ca"; 
+
+       $file = fsockopen ($update_server, 80, $errno, $errstr, 15);
+       
+       if ($file) 
+       {
+               // get patch list
+               $patch_folder = "http://" . $update_server . '/patch/' . str_replace('.', '_', VERSION) . '/';
+
+               $patch_list_xml = @file_get_contents($patch_folder . 'patch_list.xml');
+               
+               if ($patch_list_xml) 
+               {
+                       require_once('../mods/_standard/patcher/classes/PatchListParser.class.php');
+                       $patchListParser =& new PatchListParser();
+                       $patchListParser->parse($patch_list_xml);
+                       $patch_list_array = $patchListParser->getMyParsedArrayForVersion(VERSION);
+                       
+                       foreach ($patch_list_array as $row_num => $patch)
+                               $patch_ids .= '\'' . $patch['atutor_patch_id'] . '\', ';
+                               
+                       $sql = "select count(*) cnt_installed_patches from ".TABLE_PREFIX."patches " .
+                              "where atutor_patch_id in (" . substr($patch_ids, 0, -2) .")".
+                              " and status like '%Installed'";
+               
+                       $result = mysql_query($sql, $db) or die(mysql_error());
+                       $row = mysql_fetch_assoc($result);
+                       
+                       $cnt = count($patch_list_array) - $row['cnt_installed_patches'];
+                       
+                       if ($cnt > 0)
+                       {
+               ?>
+       <div class="input-form" style="width: 98%;">
+               <form method="get" action="mods/_standard/patcher/index_admin.php">
+                       <div class="row">
+                               <h3><?php echo _AT('available_patches'); ?></h3>
+                               <p><?php echo _AT('available_patches_text', $cnt); ?></p>
+                       </div>
+
+                       <div class="row buttons">
+                               <input type="submit" name="submit" value="<?php echo _AT('view'); ?>" />
+                       </div>
+               </form>
+       </div>
+       <?php 
+                       }
+               }
+       } 
+
+       ?>
+
+       <div class="input-form" style="width: 98%">
+               <?php
+                       if (!isset($_config['db_size']) || ($_config['db_size_ttl'] < time())) {
+                               $_config['db_size'] = 0;
+                               $sql = 'SHOW TABLE STATUS';
+                               $result = mysql_query($sql, $db);
+                               while($row = mysql_fetch_assoc($result)) {
+                                       $_config['db_size'] += $row['Data_length']+$row['Index_length'];
+                               }
+
+                               $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('db_size', '{$_config['db_size']}')";
+                               mysql_query($sql, $db);
+
+                               // get disk usage if we're on *nix
+                               if (DIRECTORY_SEPARATOR == '/') {
+                                       $du = shell_exec('du -sk '.escapeshellcmd(AT_CONTENT_DIR));
+                                       if ($du) {
+                                               $_config['du_size'] = (int) $du;
+                                               $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('du_size', '{$_config['du_size']}')";
+                                               mysql_query($sql, $db);
+                                       }
+                               }
+
+                               $ttl = time() + 24 * 60 * 60; // every 1 day.
+                               $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('db_size_ttl', '$ttl')";
+                               mysql_query($sql, $db);
+                       }
+
+                       $sql = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."courses";
+                       $result = mysql_query($sql, $db);
+                       $row = mysql_fetch_assoc($result);
+                       $num_courses = $row['cnt'];
+
+                       $sql = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."members";
+                       $result = mysql_query($sql, $db);
+                       $row = mysql_fetch_assoc($result);
+                       $num_users = $row['cnt'];
+
+                       $sql = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."admins";
+                       $result = mysql_query($sql, $db);
+                       $row = mysql_fetch_assoc($result);
+                       $num_users += $row['cnt'];
+
+                       $sql = "SELECT VERSION()";
+                       $result = mysql_query($sql, $db);
+                       $row = mysql_fetch_array($result);
+                       $mysql_version = $row[0];
+               ?>
+
+               <div class="row">
+                       <h3><?php echo _AT('statistics_information'); ?></h3>
+
+                       <dl class="col-list">
+                               <?php if ($_config['db_size']): ?>
+                                       <dt><?php echo _AT('database'); ?>:</dt>
+                                       <dd><?php echo number_format($_config['db_size']/AT_KBYTE_SIZE/AT_KBYTE_SIZE,2); ?> <acronym title="<?php echo _AT('megabytes'); ?>"><?php echo _AT('mb'); ?></acronym></dd>
+                               <?php endif; ?>
+
+                               <?php if ($_config['du_size']): ?>
+                                       <dt><?php echo _AT('disk_usage'); ?>:</dt>
+                                       <dd><?php echo number_format($_config['du_size']/AT_KBYTE_SIZE,2); ?> <acronym title="<?php echo _AT('megabytes'); ?>"><?php echo _AT('mb'); ?></acronym></dd>
+                               <?php endif; ?>
+
+                               <dt><?php echo _AT('courses'); ?>:</dt>
+                               <dd><?php echo $num_courses; ?></dd>
+
+                               <dt><?php echo _AT('users'); ?>:</dt>
+                               <dd><?php echo $num_users; ?></dd>
+
+                               <dt><?php echo _AT('atutor_version'); ?>:</dt>
+                               <dd><?php echo _AT('atutor_version_text', VERSION, urlencode(VERSION)); ?></dd>
+
+                               <dt><?php echo _AT('php_version'); ?>:</dt>
+                               <dd><?php echo PHP_VERSION; ?></dd>
+
+                               <dt><?php echo _AT('mysql_version'); ?>:</dt>
+                               <dd><?php echo $mysql_version; ?></dd>
+
+                               <dt><?php echo _AT('os'); ?>:</dt>
+                               <dd><?php echo php_uname('s') . ' ' . php_uname('r'); ?></dd>
+                       </dl>
+               </div>
+       </div>
+
+</div>
+
+<div style="width: 55%;">
+       <?php
+       $path_length = strlen($_base_path);
+
+       echo '<ol id="tools" style="margin-right: 0px;">';
+       foreach ($_top_level_pages as $page_info) {
+               echo '<li class="top-tool"><a href="' . $page_info['url'] . '">' . $page_info['title'] . '</a>  ';
+
+               $page_info['url'] = substr($page_info['url'], $path_length);
+
+               if ($_pages[$page_info['url']]['children']) {
+                       echo '<ul class="child-top-tool">';
+                       foreach ($_pages[$page_info['url']]['children'] as $child) {
+                               echo ' <li class="child-tool"><a href="'.$child.'">'._AT($_pages[$child]['title_var']).'</a></li>';
+                       }
+                       echo '</ul>';
+               }
+               echo '</li>';
+       }
+       echo '</ol>';
+?>
+</div>
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/instructor_login.php b/admin/instructor_login.php
new file mode 100644 (file)
index 0000000..b922938
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_COURSES);
+
+if (isset($_POST['submit_yes'])) {
+       $_POST['course'] = intval($_POST['course']);
+
+       $admin_login = $_SESSION['login'];
+
+       $sql = "SELECT M.member_id, M.login, M.preferences, M.language FROM ".TABLE_PREFIX."members M, ".TABLE_PREFIX."courses C WHERE C.course_id=".$_POST['course']." and C.member_id=M.member_id";
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)) {
+               $_SESSION['course_id']  = 0;
+               $_SESSION['login']              = $row['login'];
+               $_SESSION['valid_user'] = true;
+               $_SESSION['member_id']  = intval($row['member_id']);
+               assign_session_prefs(unserialize(stripslashes($row['preferences'])));
+               $_SESSION['is_guest']   = 0;
+               $_SESSION['lang']               = $row['language'];
+               $_SESSION['is_super_admin'] = $admin_login;
+               session_write_close();
+
+               header('Location: '.AT_BASE_HREF.'bounce.php?course='.$_POST['course']);
+               exit;
+       }
+} else if (isset($_POST['submit_no'])) {
+
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'admin/courses.php');
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+       $sql = "SELECT * FROM ".TABLE_PREFIX."courses WHERE course_id=".$_REQUEST['course'];
+       $result = mysql_query($sql, $db);
+       $row = mysql_fetch_array($result);
+
+       $hidden_vars['course'] = $_GET['course'];
+
+       $msg->addConfirm(array('LOGIN_INSTRUCTOR', SITE_NAME, $row['title']), $hidden_vars);
+       $msg->printConfirm();
+
+require(AT_INCLUDE_PATH.'footer.inc.php'); 
+?>
\ No newline at end of file
diff --git a/admin/instructor_requests.php b/admin/instructor_requests.php
new file mode 100644 (file)
index 0000000..73b7b05
--- /dev/null
@@ -0,0 +1,129 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+$_user_location = 'admin';
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_USERS);
+
+if (isset($_GET['deny']) && isset($_GET['id'])) {
+       header('Location: admin_deny.php?id='.$_GET['id']);
+       exit;
+       /*
+       $sql = 'DELETE FROM '.TABLE_PREFIX.'instructor_approvals WHERE member_id='.intval($_GET['id']);
+       $result = mysql_query($sql, $db);
+
+       write_to_log(AT_ADMIN_LOG_DELETE, 'instructor_approvals', mysql_affected_rows($db), $sql);
+       */
+
+} else if (isset($_GET['approve']) && isset($_GET['id'])) {
+       $id = intval($_GET['id']);
+
+       $sql = 'DELETE FROM '.TABLE_PREFIX.'instructor_approvals WHERE member_id='.$id;
+       $result = mysql_query($sql, $db);
+
+       write_to_log(AT_ADMIN_LOG_DELETE, 'instructor_approvals', mysql_affected_rows($db), $sql);
+
+       $sql = 'UPDATE '.TABLE_PREFIX.'members SET status='.AT_STATUS_INSTRUCTOR.', creation_date=creation_date, last_login=last_login WHERE member_id='.$id;
+       $result = mysql_query($sql, $db);
+
+       write_to_log(AT_ADMIN_LOG_UPDATE, 'members', mysql_affected_rows($db), $sql);
+
+       /* notify the users that they have been approved: */
+       $sql   = "SELECT email, first_name, last_name FROM ".TABLE_PREFIX."members WHERE member_id=$id";
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)) {
+               $to_email = $row['email'];
+
+               if ($row['first_name']!="" || $row['last_name']!="") {
+                       $tmp_message  = $row['first_name'].' '.$row['last_name'].",\n\n";               
+               }       
+               $tmp_message .= _AT('instructor_request_reply', AT_BASE_HREF);
+
+               if ($to_email != '') {
+                       require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+
+                       $mail = new ATutorMailer;
+
+                       $mail->From     = $_config['contact_email'];
+                       $mail->AddAddress($to_email);
+                       $mail->Subject = _AT('instructor_request');
+                       $mail->Body    = $tmp_message;
+
+                       if(!$mail->Send()) {
+                          //echo 'There was an error sending the message';
+                          $msg->printErrors('SENDING_ERROR');
+                          exit;
+                       }
+
+                       unset($mail);
+               }
+       }
+
+       $msg->addFeedback('PROFILE_UPDATED_ADMIN');
+} else if (!empty($_GET) && !$_GET['submit']) {
+       $msg->addError('NO_ITEM_SELECTED');
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+$sql   = "SELECT M.login, M.first_name, M.last_name, M.email, M.member_id, A.* FROM ".TABLE_PREFIX."members M, ".TABLE_PREFIX."instructor_approvals A WHERE A.member_id=M.member_id ORDER BY M.login";
+$result = mysql_query($sql, $db);
+$num_pending = mysql_num_rows($result);
+?>
+
+<form name="form" method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<table class="data" summary="" rules="cols">
+<thead>
+<tr>
+       <th scope="col">&nbsp;</th>
+       <th scope="col"><?php echo _AT('login_name');     ?></th>
+       <th scope="col"><?php echo _AT('first_name');   ?></th>
+       <th scope="col"><?php echo _AT('last_name');    ?></th>
+       <th scope="col"><?php echo _AT('email');        ?></th>
+       <th scope="col"><?php echo _AT('notes');        ?></th>
+</tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="6">
+       <input type="submit" name="deny" value="<?php echo _AT('deny'); ?>" /> 
+       <input type="submit" name="approve" value="<?php echo _AT('approve'); ?>" /></td>
+</tr>
+</tfoot>
+<tbody>
+<?php
+       if ($row = mysql_fetch_assoc($result)) {
+               do {
+                       echo '<tr onmousedown="document.form[\'i'.$row['member_id'].'\'].checked = true;rowselect(this);" id="r_'.$row['member_id'].'">';
+                       echo '<td><input type="radio" name="id" value="'.$row['member_id'].'" id="i'.$row['member_id'].'" /></td>';
+                       echo '<td><label for="i'.$row['member_id'].'">'.AT_print($row['login'], 'members.login').'</label></td>';
+                       echo '<td>'.AT_print($row['first_name'], 'members.first_name').'</td>';
+                       echo '<td>'.AT_print($row['last_name'], 'members.last_name').'</td>';
+                       echo '<td>'.AT_print($row['email'], 'members.email').'</td>';
+                       
+                       echo '<td>'.AT_print($row['notes'], 'instructor_approvals.notes').'</td>';
+
+                       echo '</tr>';
+               } while ($row = mysql_fetch_assoc($result));
+       } else {
+               echo '<tr><td colspan="6">'._AT('none_found').'</td></tr>';
+       }
+?>
+</tbody>
+</table>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/language.php b/admin/language.php
new file mode 100644 (file)
index 0000000..7c54da8
--- /dev/null
@@ -0,0 +1,99 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_LANGUAGES);
+
+require_once(AT_INCLUDE_PATH.'classes/Language/LanguageEditor.class.php');
+require_once(AT_INCLUDE_PATH.'classes/Language/LanguagesParser.class.php');
+
+if ( (isset($_POST['delete']) || isset($_POST['export']) || isset($_POST['edit'])) && !isset($_POST['id'])){
+       $msg->addError('NO_ITEM_SELECTED');
+} else if (isset($_POST['delete'])) {
+       // check if this language is the only one that exists:
+       if ($languageManager->getNumLanguages() == 1) {
+               $msg->addError('LAST_LANGUAGE');
+       } else {
+               header('Location: language_delete.php?lang_code='.$_POST['id']);
+               exit;
+       }
+} else if (isset($_POST['export'])) {
+       $language =& $languageManager->getLanguage($_POST['id']);
+       if ($language === FALSE) {
+               $msg->addError('ITEM_NOT_FOUND');
+       } else {
+               $languageEditor =& new LanguageEditor($language);
+               $languageEditor->export();
+       }
+} else if (isset($_POST['edit'])) {
+       header('Location: language_edit.php?lang_code='.$_POST['id']);
+       exit;
+}
+
+if (AT_DEVEL_TRANSLATE == 1) { 
+       $msg->addWarning('TRANSLATE_ON');       
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+
+<form name="form" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+
+<table summary="" class="data" rules="cols">
+<colgroup>
+       <col />
+       <col class="sort" />
+       <col span="3" />
+</colgroup>
+<thead>
+<tr>
+       <th scope="col">&nbsp;</th>
+       <th scope="col"><?php echo _AT('name_in_language'); ?></th>
+       <th scope="col"><?php echo _AT('name_in_english'); ?></th>
+       <th scope="col"><?php echo _AT('lang_code'); ?></th>
+       <th scope="col"><?php echo _AT('charset'); ?></th>
+</tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="5">
+               <?php if (defined('AT_DEVEL_TRANSLATE') && AT_DEVEL_TRANSLATE): ?>
+                       <input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" />  
+                       <input type="submit" name="export" value="<?php echo _AT('export'); ?>"  /> 
+                       <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /> 
+                       <?php echo _AT('or'); ?> <a href="admin/language_add.php"><?php echo _AT('add_a_new_language'); ?></a>
+               <?php else: ?>
+                       <input type="submit" name="export" value="<?php echo _AT('export'); ?>" /> 
+                       <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" />
+               <?php endif; ?>
+       </td>
+</tr>
+</tfoot>
+<tbody>
+       <?php foreach ($languageManager->getAvailableLanguages() as $codes): ?>
+               <?php $language = current($codes); ?>
+               <tr onmousedown="document.form['m<?php echo $language->getCode(); ?>'].checked = true; rowselect(this);" id="r_<?php echo $language->getCode(); ?>">
+                       <td><input type="radio" name="id" value="<?php echo $language->getCode(); ?>" id="m<?php echo $language->getCode(); ?>" /></td>
+                       <td><label for="m<?php echo $language->getCode(); ?>"><?php echo $language->getNativeName(); ?></label></td>
+                       <td><?php echo $language->getEnglishName(); ?></td>
+                       <td><?php echo strtolower($language->getCode()); ?></td>
+                       <td><?php echo strtolower($language->getCharacterSet()); ?></td>
+               </tr>
+       <?php endforeach; ?>
+</tbody>
+</table>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/language_add.php b/admin/language_add.php
new file mode 100644 (file)
index 0000000..b7d7a9b
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_LANGUAGES);
+if (!AT_DEVEL_TRANSLATE) { exit; }
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: language.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       require_once(AT_INCLUDE_PATH . 'classes/Language/LanguageEditor.class.php'); 
+       
+       if ($languageManager->exists($_POST['code'], $_POST['locale'])) {
+               $msg->addError('LANG_EXISTS');
+       } else {
+               $state = LanguageEditor::addLanguage($_POST, $db);
+       }
+
+       if (!$msg->containsErrors() && $state !== FALSE) {
+               $msg->addFeedback('LANG_ADDED');
+               header('Location: language.php');
+               exit;
+       } 
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); ?>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<input type="hidden" name="import" value="1" />
+<div class="input-form" style="width:60%">
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="code"><?php echo _AT('lang_code'); ?></label><br />
+               <input id="code" name="code" type="text" size="2" maxlength="2" class="formfield" value="<?php echo $_POST['code']; ?>" />
+       </div>
+
+       <div class="row">
+               <label for="locale"><?php echo _AT('locale'); ?></label><br />
+               <input id="locale" name="locale" type="text" size="2" maxlength="2" class="formfield" value="<?php echo $_POST['locale']; ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="charset"><?php echo _AT('charset'); ?></label><br />
+               <input id="charset" name="charset" type="text" size="31" maxlength="20" class="formfield" value="<?php echo $_POST['charset']; ?>" />
+       </div>
+
+       <div class="row">
+               <label for="ltr"><?php echo _AT('direction'); ?></label><br />
+               <?php 
+                       if ($_POST['direction'] == 'rtl') { 
+                               $rtl = 'checked="checked"';  
+                               $ltr='';  
+                       } else { 
+                               $rtl = '';  
+                               $ltr='checked="checked"'; 
+                       }
+               ?>
+               <input id="ltr" name="direction" type="radio" value="ltr" <?php echo $ltr; ?> /><label for="ltr"><?php echo _AT('ltr'); ?></label>, <input id="rtl" name="direction" type="radio" value="rtl" <?php echo $rtl; ?> /><label for="rtl"><?php echo _AT('rtl'); ?></label>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="reg_exp"><?php echo _AT('reg_exp'); ?></label><br />
+               <input id="reg_exp" name="reg_exp" type="text" size="31" class="formfield" value="<?php echo $_POST['reg_exp']; ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="nname"><?php echo _AT('name_in_language'); ?></label><br />
+               <input id="nname" name="native_name" type="text" size="31" maxlength="20" class="formfield" value="<?php echo $_POST['native_name']; ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="ename"><?php echo _AT('name_in_english'); ?></label><br />
+               <input id="ename" name="english_name" type="text" size="31" maxlength="20" class="formfield" value="<?php echo $_POST['english_name'];?>" />
+       </div>
+
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('submit'); ?>" /> <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />           
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php');  ?>
\ No newline at end of file
diff --git a/admin/language_delete.php b/admin/language_delete.php
new file mode 100644 (file)
index 0000000..5aaf79f
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_LANGUAGES);
+
+if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       //shozub -- is this supposed to be lang_codeinstead of delete_lang???
+       header('Location: language.php?lang_code='.$_POST['delete_lang']);
+       exit;
+}
+
+if (isset($_POST['submit_yes'])) {
+       require_once(AT_INCLUDE_PATH . 'classes/Language/LanguageEditor.class.php');
+
+       $lang =& $languageManager->getLanguage($_POST['lang_code']);
+       $languageEditor =& new LanguageEditor($lang);
+       $languageEditor->deleteLanguage();
+
+       $msg->addFeedback('LANG_DELETED');
+       header('Location: language.php');
+       exit;
+}
+
+
+$language =& $languageManager->getLanguage($_GET['lang_code']);
+if ($language === FALSE) {
+       $msg->addError('ITEM_NOT_FOUND'); // Originally AT_LANG_NOT_FOUND, make error code
+
+       header('Location: language.php?lang_code='.$_POST['delete_lang']);
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+$hidden_vars['lang_code'] = $_GET['lang_code'];
+
+$confirm = array('DELETE_LANG', $language->getEnglishName());
+$msg->addConfirm($confirm, $hidden_vars);
+$msg->printConfirm();
+       
+require(AT_INCLUDE_PATH.'footer.inc.php'); 
+
+?>
\ No newline at end of file
diff --git a/admin/language_edit.php b/admin/language_edit.php
new file mode 100644 (file)
index 0000000..320bcae
--- /dev/null
@@ -0,0 +1,122 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_LANGUAGES);
+if (!AT_DEVEL_TRANSLATE) { exit; }
+
+require_once(AT_INCLUDE_PATH . 'classes/Language/LanguageEditor.class.php'); 
+
+$lang =& $languageManager->getLanguage($_GET['lang_code']);
+if ($lang === FALSE) {
+       require(AT_INCLUDE_PATH.'header.inc.php'); 
+       echo '<h3>'._AT('edit_language').'</h3>';
+       $msg->addError('NO_LANGUAGE');
+       
+       $msg->printAll();
+
+       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+       exit;
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: language.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $languageEditor =& new LanguageEditor($_GET['lang_code']);
+       $state = $languageEditor->updateLanguage($_POST, $languageManager->exists($_POST['code'], $_POST['locale']));
+
+       if (!$msg->containsErrors() && $state !== FALSE) {
+               $msg->addFeedback('LANG_UPDATED');
+               header('Location: language.php');
+               exit;
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+
+$msg->printAll();
+
+if (!isset($_POST['submit'])) {
+       $_POST['code']         = $lang->getParentCode();
+       $_POST['locale']       = $lang->getLocale();
+       $_POST['charset']      = $lang->getCharacterSet();
+       $_POST['direction']    = $lang->getDirection();
+       $_POST['reg_exp']      = $lang->getRegularExpression();
+       $_POST['native_name']  = $lang->getNativeName();
+       $_POST['english_name'] = $lang->getEnglishName();
+}
+
+?>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF'] . '?lang_code=' . $_GET['lang_code']; ?>">
+
+<input type="hidden" name="old_code" value="<?php echo $lang->getCode(); ?>" />
+
+<div class="input-form" style="width:60%">
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="code"><?php echo _AT('lang_code'); ?></label><br />
+               <input id="code" name="code" type="text" size="2" maxlength="2" class="formfield" value="<?php echo $_POST['code']; ?>" />
+       </div>
+
+       <div class="row">
+               <label for="locale"><?php echo _AT('locale'); ?></label><br />
+               <input id="locale" name="locale" type="text" size="2" maxlength="2" class="formfield" value="<?php echo $_POST['locale']; ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="charset"><?php echo _AT('charset'); ?></label><br />
+               <input id="charset" name="charset" type="text" size="31" maxlength="20" class="formfield" value="<?php echo $_POST['charset']; ?>" />
+       </div>
+
+       <div class="row">
+               <label for="ltr"><?php echo _AT('direction'); ?></label><br />
+               <?php 
+                       if ($_POST['direction'] == 'rtl') { 
+                               $rtl = 'checked="checked"';  
+                               $ltr='';  
+                       } else { 
+                               $rtl = '';  
+                               $ltr='checked="checked"'; 
+                       }
+               ?>
+               <input id="ltr" name="direction" type="radio" value="ltr" <?php echo $ltr; ?> /><label for="ltr"><?php echo _AT('ltr'); ?></label>, <input id="rtl" name="direction" type="radio" value="rtl" <?php echo $rtl; ?> /><label for="rtl"><?php echo _AT('rtl'); ?></label>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="reg_exp"><?php echo _AT('reg_exp'); ?></label><br />
+               <input id="reg_exp" name="reg_exp" type="text" size="31" class="formfield" value="<?php echo $_POST['reg_exp']; ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="nname"><?php echo _AT('name_in_language'); ?></label><br />
+               <input id="nname" name="native_name" type="text" size="31" maxlength="20" class="formfield" value="<?php echo $_POST['native_name']; ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="ename"><?php echo _AT('name_in_english'); ?></label><br />
+               <input id="ename" name="english_name" type="text" size="31" maxlength="20" class="formfield" value="<?php echo $_POST['english_name'];?>" />
+       </div>
+
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('submit'); ?>" /> <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />           
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php');  ?>
\ No newline at end of file
diff --git a/admin/language_editor.php b/admin/language_editor.php
new file mode 100644 (file)
index 0000000..162f65a
--- /dev/null
@@ -0,0 +1,166 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+/**
+ * BEWARE OF THE HACKS USED TO IMPLEMENT THIS FEATURE:
+ *
+ * this page is to allow admins to edit/customize their language
+ * and save the changes made in a way that allows the upgrading of
+ * ATutor without the loss of that language. It also allows customized
+ * language to be reverted back to its original form.
+ *
+ * since we couldn't change the database as it would break backwards
+ * compatability, none of the fields could be changed which means
+ * that the only way to store the extra language would be by reusing
+ * the `variable` field, which is part of the PK.
+ *
+ * reusing the `variable` is a huge hack and doesn't correctly support
+ * module language as there is nothing enfocing storing module language
+ * in an independant way. ideally there would be another field in the
+ * database designating custom or not and the `variable` field would
+ * be removed completely since it doesn't have much effect any more.
+ *
+ * custom language is stored as `_c_template` and `_c_msgs` for template
+ * and feedback messages, respectively. Why use "_c" as the prefix?
+ * because it comes before "_t" and _m" in the alphabet. This lets us
+ * sort the language by `variable` and limit it to one result. That is 
+ * how the custom language terms are retrieved in place of default
+ * language.
+ *
+ * another oddity is that although custom language text isn't deleted
+ * upon upgrades, the language definitions are, which means those terms
+ * cannot be edited until after the language pack is reinstalled.
+ * this also means that if a term has changed the system might be unaware
+ * of new replacement tokens and could break.
+ *
+ */
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_LANGUAGES);
+
+if (defined('AT_DEVEL_TRANSLATE') && AT_DEVEL_TRANSLATE) {
+       $msg->addWarning('TRANSLATE_ON');
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$_variables = array('template' => '_template', 'feedback' => '_msgs');
+$_c_variables = array('template' => '_c_template', 'feedback' => '_c_msgs');
+
+$sql_search = '';
+if (isset($_GET['filter'], $_GET['search'])) {
+       $_GET['search'] = trim($addslashes($_GET['search']));
+       $words = explode(' ', $_GET['search']);
+       foreach ($words as $key => $word) {
+               // search `term` and `text` only
+               if ($strlen($word) > 1) {
+                       $word = str_replace(array('%','_'), array('\%', '\_'), $word);
+                       $words[$key] = "(CAST(`term` AS CHAR) LIKE '%$word%' OR CAST(`text` AS CHAR) LIKE '%$word%')";
+               } else {
+                       unset($words[$key]);
+               }
+       }
+       if ($words) {
+               $sql_search = ' AND (' . implode(' OR ', $words).')';
+       }
+} else if ($_GET['reset_filter']) {
+       unset($_GET);
+}
+if (!isset($_GET['type']) || !isset($_variables[$_GET['type']])) {
+       $_GET['type'] = 'template';
+}
+
+if (isset($_GET['custom'])) {
+       $variable = $_c_variables[$_GET['type']];
+} else {
+       $variable = $_variables[$_GET['type']];
+}
+
+$sql = "SELECT * FROM ".TABLE_PREFIX."language_text WHERE language_code='$_SESSION[lang]' AND `variable`='$variable' $sql_search ORDER BY text";
+$result = mysql_query($sql, $db);
+$num_results = mysql_num_rows($result);
+?>
+
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+       <div class="input-form">
+               <div class="row">
+                       <h3><?php echo _AT('results_found', $num_results); ?></h3>
+               </div>
+
+               <div class="row">
+                       <?php echo _AT('type'); ?><br />
+                       <input type="radio" name="type" value="template" id="tyte" <?php if ($_GET['type'] == 'template') { echo 'checked="checked"'; } ?> /><label for="tyte"><?php echo _AT('template'); ?></label>
+                       <input type="radio" name="type" value="feedback" id="tyfe" <?php if ($_GET['type'] == 'feedback') { echo 'checked="checked"'; } ?> /><label for="tyfe"><?php echo _AT('feedback'); ?></label>
+               </div>
+
+               <div class="row">
+                       <input type="checkbox" name="custom" value="1" id="cus" <?php if (isset($_GET['custom'])) { echo 'checked="checked"'; } ?> /><label for="cus"><?php echo _AT('only_show_edited_terms'); ?></label>
+               </div>
+
+               <div class="row">
+                       <label for="search"><?php echo _AT('search'); ?></label><br />
+                       <input type="text" name="search" id="search" size="40" value="<?php echo htmlspecialchars($_GET['search']); ?>" />
+               </div>
+
+               <div class="row buttons">
+                       <input type="submit" name="filter" value="<?php echo _AT('filter'); ?>" />
+                       <input type="submit" name="reset_filter" value="<?php echo _AT('reset_filter'); ?>" />
+               </div>
+       </div>
+</form>
+
+<form name="form" method="post">
+<div class="input-form">
+       <table cellspacing="0" cellpadding="0">
+       <tr>
+       <td valign="top">
+               <?php if ($num_results): ?>
+                       <select size="<?php echo min(max($num_results,2), 25); ?>" name="terms" id="terms" onchange="javascript:showtext(this);">
+                               <?php
+                                       while ($row = mysql_fetch_assoc($result)): 
+                                               if ($strlen($row['text']) > 30) {
+                                                       $row['text'] = $substr($row['text'], 0, 28) . '...';
+                                               }
+                                       ?>
+                                               <option value="<?php echo $row['term']; ?>"><?php echo htmlspecialchars($row['text']); ?></option>
+                                       <?php endwhile; ?>
+                       </select>
+               <?php else: ?>
+                       <p><?php echo _AT('none_found'); ?></p>
+               <?php endif; ?>
+       </td>
+
+       <td valign="top">
+               <div class="row">
+                       <iframe src="admin/language_term.php" frameborder="0" height="430" width="450" marginheight="0" marginwidth="0" name="tran" id="tran"></iframe>
+               </div>
+       </td>
+       </tr>
+       </table>
+</div>
+</form>
+
+<script language="javascript" type="text/javascript">
+//<!--
+function showtext(obj) {
+       frames['tran'].location.href = "<?php echo AT_BASE_HREF; ?>admin/language_term.php?type=<?php echo $_variables[$_GET['type']].SEP; ?>term=" + obj.value;
+}
+//-->
+</script>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/language_import.php b/admin/language_import.php
new file mode 100644 (file)
index 0000000..fc023a8
--- /dev/null
@@ -0,0 +1,105 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_LANGUAGES);
+
+require(AT_INCLUDE_PATH.'classes/pclzip.lib.php');
+require_once(AT_INCLUDE_PATH.'classes/Language/LanguageEditor.class.php');
+require_once(AT_INCLUDE_PATH.'classes/Language/LanguagesParser.class.php');
+
+/* to avoid timing out on large files */
+@set_time_limit(0);
+
+$_SESSION['done'] = 1;
+
+if (isset($_POST['submit_import'])) {
+       require_once(AT_INCLUDE_PATH.'classes/Language/RemoteLanguageManager.class.php');
+       $remoteLanguageManager =& new RemoteLanguageManager();
+       $remoteLanguageManager->import($_POST['language']);
+
+       header('Location: language_import.php');
+       exit;
+} else if (isset($_POST['submit']) && (!is_uploaded_file($_FILES['file']['tmp_name']) || !$_FILES['file']['size'])) {
+       $msg->addError('LANG_IMPORT_FAILED');
+} else if (isset($_POST['submit']) && !$_FILES['file']['name']) {
+       $msg->addError('IMPORTFILE_EMPTY');
+} else if (isset($_POST['submit']) && is_uploaded_file($_FILES['file']['tmp_name'])) {
+       $languageManager->import($_FILES['file']['tmp_name']);
+
+       header('Location: language_import.php');
+       exit;
+}
+
+?>
+<?php require(AT_INCLUDE_PATH.'header.inc.php'); ?>
+
+<form name="form1" method="post" action="admin/language_import.php" enctype="multipart/form-data" onsubmit="openWindow('<?php echo AT_BASE_HREF; ?>tools/prog.php');">
+<div class="input-form">
+       <div class="row">
+               <p><?php echo _AT('import_lang_howto'); ?></p>
+       </div>
+       
+       <div class="row">
+               <label for="file"><?php echo _AT('import_a_new_lang'); ?></label><br />
+               <input type="file" name="file" id="file" />
+       </div>
+       
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('import'); ?>" />
+       </div>
+</div>
+</form>
+
+
+<form name="form1" method="post" action="admin/language_import.php">
+<div class="input-form">
+       <div class="row">
+               <?php echo _AT('import_remote_language'); ?>
+       </div>
+
+       <div class="row">
+               <?php
+                       require_once(AT_INCLUDE_PATH.'classes/Language/RemoteLanguageManager.class.php');
+                       $remoteLanguageManager =& new RemoteLanguageManager();
+                       if ($remoteLanguageManager->getNumLanguages()) {
+                               $found = false;
+                               foreach ($remoteLanguageManager->getAvailableLanguages() as $codes){
+                                       $language = current($codes);
+                                       if (!$languageManager->exists($language->getCode()) && ($language->getStatus() == AT_LANG_STATUS_PUBLISHED)) {
+                                               if (!$found) {
+                                                       echo '<select name="language">';
+                                                       $found = true;
+                                               }
+                                               echo '<option value="'.$language->getCode().'">'.$language->getEnglishName().' - '.$language->getNativeName().'</option>';
+                                       }
+                               }
+                               if ($found) {
+                                       echo '</select></div>';
+                                       echo '<div class="row buttons"><input type="submit" name="submit_import" value="' . _AT('import') . '" class="button" /></div>';
+                               } else {
+                                       echo _AT('none_found');
+                                       echo '</div>';
+                               }
+                       } else {
+                               echo _AT('cannot_find_remote_languages');
+                               echo '</div>';
+                       }
+               ?>
+</div>
+</form>
+
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/language_term.php b/admin/language_term.php
new file mode 100644 (file)
index 0000000..7c32499
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_LANGUAGES);
+
+if (isset($_POST['submit'])) {
+       $_POST['variable'] = $addslashes($_POST['variable']);
+       $_POST['term'] = $addslashes($_POST['term']);
+       $_POST['text'] = $addslashes($_POST['text']);
+
+       $_POST['variable'] = '_c' . $_POST['variable'];
+
+       $sql = "REPLACE INTO ".TABLE_PREFIX."language_text VALUES ('$_SESSION[lang]', '{$_POST['variable']}', '{$_POST['term']}', '{$_POST['text']}', NOW(), '')";
+       mysql_query($sql, $db);
+       header('Location: '.$_SERVER['PHP_SELF'].'?term='.$_POST['term']);
+       exit;
+} else if (isset($_POST['delete'])) {
+       $_POST['variable'] = $addslashes($_POST['variable']);
+       $_POST['term'] = $addslashes($_POST['term']);
+       $_POST['text'] = $addslashes($_POST['text']);
+
+       $_POST['variable'] = '_c' . $_POST['variable'];
+
+       $sql = "DELETE FROM ".TABLE_PREFIX."language_text WHERE language_code='$_SESSION[lang]' AND `variable`='{$_POST['variable']}' AND term='{$_POST['term']}' LIMIT 1";
+       mysql_query($sql, $db);
+       header('Location: '.$_SERVER['PHP_SELF'].'?term='.$_POST['term']);
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'html/frameset/header.inc.php');
+if (isset($_GET['term'])) {
+       $_GET['term'] = $addslashes($_GET['term']);
+       $sql = "SELECT * FROM ".TABLE_PREFIX."language_text WHERE language_code='$_SESSION[lang]' AND term='$_GET[term]' ORDER BY `variable` DESC";
+       $result = mysql_query($sql, $db);
+       $original_row = mysql_fetch_assoc($result);
+       $custom_row = mysql_fetch_assoc($result);
+}
+?>
+
+<?php if ($original_row): ?>
+       <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+       <input type="hidden" name="term" value="<?php echo $_GET['term']; ?>" />
+       <input type="hidden" name="variable" value="<?php echo $original_row['variable']; ?>" />
+
+       <div class="input-form" style="width: 99%">
+               <div class="row">
+                       <h3><?php echo $original_row['term']; ?></h3>
+                       <?php if ($original_row['context']): ?>
+                               <p><?php echo $original_row['context']; ?></p>
+                       <?php endif; ?>
+
+                       <?php if ($custom_row): ?>
+                               <h4><?php echo _AT('original_term'); ?></h4>
+                               <p><?php echo $original_row['text']; ?></p>
+                               <textarea name="text" rows="8" cols="50"><?php echo htmlspecialchars($custom_row['text']); ?></textarea>
+                       <?php else: ?>
+                               <textarea name="text" rows="8" cols="50"><?php echo htmlspecialchars($original_row['text']); ?></textarea>
+                       <?php endif; ?>
+               </div>
+
+               <div class="row">
+                       <?php 
+                               $sql    = "SELECT * FROM ".TABLE_PREFIX."language_pages WHERE `term`='$_GET[term]' ORDER BY page LIMIT 11";
+                               $result = mysql_query($sql, $db);
+                               if (mysql_num_rows($result) > 10) {
+                                       echo '<em>'._AT('global_more_than_10_pages').'</em>';
+                               } else {
+                                       echo '<ul style="padding: 0px; margin: 0px; list-style: none">';
+                                       while ($page_row = mysql_fetch_assoc($result)) {
+                                               echo '<li>'.$page_row['page'] . '</li>';
+                                       }
+                                       echo '</ul>';
+                               }
+                        ?>
+               </div>
+
+               <div class="buttons row">
+                       <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+                       <?php if ($custom_row): ?>
+                               <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" />
+                       <?php endif; ?>
+               </div>
+       </div>
+       </form>
+<?php else: ?>
+       <p><?php echo _AT('select_term_to_edit'); ?></p>
+<?php endif; ?>
+</body>
+</html>
\ No newline at end of file
diff --git a/admin/language_translate.php b/admin/language_translate.php
new file mode 100644 (file)
index 0000000..a161088
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_LANGUAGES);
+
+if (isset($_POST['svn_submit'])) {
+       $languageManager->liveImport($addslashes($_POST['import_lang']));
+       header('Location: '.$_SERVER['PHP_SELF']);
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+
+$button_state = '';
+if (!defined('AT_DEVEL_TRANSLATE') || !AT_DEVEL_TRANSLATE) {
+       $button_state = 'disabled="disabled"';
+}
+
+?>
+
+<form method="get">
+<div class="input-form">
+       <div class="row">
+               <h3><?php echo _AT('translate'); ?></h3>
+       </div>
+
+       <div class="row">
+               <p><?php echo _AT('translate_lang_howto'); ?></p>
+       </div>
+
+       <div class="row buttons">
+               <input type="button" onclick="javascript:window.open('<?php echo AT_BASE_HREF; ?>admin/translate_atutor.php', 'newWin1', 'toolbar=0, location=0, directories=0, status=0, menubar=0, scrollbars=1, resizable=1, copyhistory=0, width=640, height=480')" value="<?php echo _AT('translate'); ?>" <?php echo $button_state; ?> />
+       </div>
+</div>
+</form>
+
+<?php if (defined('AT_DEVEL_TRANSLATE') && AT_DEVEL_TRANSLATE): ?>
+       <form name="form1" method="post" action="admin/language_translate.php">
+               <div class="input-form">
+                       <div class="row">
+                               Import partial language from the <em>live ATutor language database</em> to your local installation for translating.
+                       </div>
+                       <div class="row">
+                               <?php
+                                       require_once(AT_INCLUDE_PATH.'classes/Language/RemoteLanguageManager.class.php');
+                                       $remoteLanguageManager =& new RemoteLanguageManager();
+                                       $remoteLanguageManager->printDropdown($_SESSION['lang'], 'import_lang', 'import_lang');
+                               ?>
+                       </div>
+
+                       <div class="row buttons">
+                               <input type="submit" name="svn_submit" value="<?php echo _AT('import'); ?>" />
+                       </div>
+               </div>
+       </form>
+<?php endif; ?>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/master_list.php b/admin/master_list.php
new file mode 100644 (file)
index 0000000..e7f96d1
--- /dev/null
@@ -0,0 +1,340 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_USERS);\r
+\r
+if (!defined('AT_MASTER_LIST') || !AT_MASTER_LIST) {\r
+       require(AT_INCLUDE_PATH.'header.inc.php');\r
+       $msg->addInfo('MASTER_LIST_DISABLED');\r
+       $msg->printInfos();\r
+       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+\r
+\r
+if (isset($_POST['submit'])) {\r
+       if ($_FILES['file']['error'] == 1) { \r
+               $errors = array('FILE_MAX_SIZE', ini_get('upload_max_filesize'));\r
+               $msg->addError($errors);\r
+               header('Location: '.$_SERVER['PHP_SELF']);\r
+               exit;\r
+       }\r
+\r
+       if (!$_FILES['file']['name'] || (!is_uploaded_file($_FILES['file']['tmp_name']))) {\r
+               $msg->addError('FILE_NOT_SELECTED');\r
+               header('Location: '.$_SERVER['PHP_SELF']);\r
+               exit;\r
+       }\r
+\r
+       $fp = fopen($_FILES['file']['tmp_name'], 'r');\r
+       if ($fp) {\r
+               $existing_accounts = array();\r
+               $number_of_updates = 0;\r
+\r
+               if ($_POST['override'] > 0) {\r
+                       /* Delete all the un-created accounts. (There is no member to delete or disable). */\r
+                       $sql = "DELETE FROM ".TABLE_PREFIX."master_list WHERE member_id=0";\r
+                       $result = mysql_query($sql, $db);\r
+\r
+                       /* Get all the created accounts. (They will be disabled or deleted if not in the new list). */\r
+                       $sql = "SELECT public_field, member_id FROM ".TABLE_PREFIX."master_list";\r
+                       $result = mysql_query($sql, $db);\r
+                       $num_affected += mysql_affected_rows($db);\r
+                       if ($num_affected > 0) {\r
+                               $number_of_updated += $num_affected;\r
+                       }\r
+                       while ($row = mysql_fetch_assoc($result)) {\r
+                               $existing_accounts[$row['public_field']] = $row['member_id'];\r
+                       }\r
+               }\r
+               $sql = '';\r
+               while (($row = fgetcsv($fp, 1000, ',')) !== FALSE) {\r
+                       if (count($row) != 2) {\r
+                               continue;\r
+                       }\r
+                       if (!$existing_accounts[$row[0]]) {\r
+                               $row[0] = addslashes($row[0]);\r
+                               $row[1] = md5($row[1]); // this may be hashed\r
+\r
+                               $sql = "INSERT INTO ".TABLE_PREFIX."master_list VALUES ('$row[0]', '$row[1]', 0)";\r
+                               mysql_query($sql, $db);\r
+\r
+                               write_to_log(AT_ADMIN_LOG_INSERT, 'master_list', mysql_affected_rows($db), $sql);\r
+                               $num_affected = mysql_affected_rows($db);\r
+                               if ($num_affected > 0) {\r
+                                       $number_of_updated += $num_affected;\r
+                               }\r
+                       }\r
+                       unset($existing_accounts[$row[0]]);\r
+               }\r
+               fclose($fp);\r
+\r
+               if (($_POST['override'] == 1) && $existing_accounts) {\r
+                       // disable missing accounts\r
+                       $existing_accounts = implode(',', $existing_accounts);\r
+\r
+                       $sql    = "UPDATE ".TABLE_PREFIX."members SET status=".AT_STATUS_DISABLED.", creation_date=creation_date, last_login=last_login WHERE member_id IN ($existing_accounts)";\r
+                       $result = mysql_query($sql, $db);\r
+                       \r
+                       write_to_log(AT_ADMIN_LOG_UPDATE, 'members', mysql_affected_rows($db), $sql);\r
+\r
+                       // un-enrol disabled accounts\r
+                       $sql    = "DELETE FROM ".TABLE_PREFIX."course_enrollment WHERE member_id IN ($existing_accounts)";\r
+                       $result = mysql_query($sql, $db);\r
+\r
+                       $num_affected = mysql_affected_rows($db);\r
+                       if ($num_affected > 0) {\r
+                               $number_of_updated += $num_affected;\r
+                       }\r
+                       write_to_log(AT_ADMIN_LOG_DELETE, 'course_enrollment', mysql_affected_rows($db), $sql);\r
+                       \r
+               } else if ($_POST['override'] == 2) {\r
+                       // delete missing accounts\r
+               }\r
+\r
+               if ($number_of_updated > 0) {\r
+                       $msg->addFeedback('MASTER_LIST_UPLOADED');\r
+               } else {\r
+                       $msg->addFeedback('MASTER_LIST_NO_CHANGES');\r
+               }\r
+                       header('Location: '.$_SERVER['PHP_SELF']);\r
+       }\r
+\r
+       exit;\r
+} else if (isset($_GET['edit'], $_GET['id'])) {\r
+       if (substr($_GET['id'], 0, 1) != '-') {\r
+               header('Location: '.AT_BASE_HREF.'admin/edit_user.php?id='.$_GET['id'] . SEP . 'ml=1');\r
+       } else {\r
+               header('Location: '.AT_BASE_HREF.'admin/master_list_edit.php?id='.substr($_GET['id'], 1) . SEP . 'ml=1');\r
+       }\r
+       exit;\r
+} else if (isset($_GET['delete'], $_GET['id'])) {\r
+       if (substr($_GET['id'], 0, 1) != '-') {\r
+               header('Location: '.AT_BASE_HREF.'admin/admin_delete.php?id='.$_GET['id'] . SEP . 'ml=1');\r
+       } else {\r
+               header('Location: '.AT_BASE_HREF.'admin/master_list_delete.php?id='.substr($_GET['id'], 1) . SEP . 'ml=1');\r
+       }\r
+       exit;\r
+} else if (isset($_GET['delete']) || isset($_GET['edit'])) {\r
+       $msg->addError('NO_ITEM_SELECTED');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+\r
+if ($_GET['reset_filter']) {\r
+       unset($_GET);\r
+}\r
+?>\r
+\r
+<form name="importForm" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" enctype="multipart/form-data">\r
+<div class="input-form">\r
+       <div class="row">\r
+               <h3><?php echo _AT('update_list'); ?></h3>\r
+               <label for="file"><?php echo _AT('file'); ?></label><br />\r
+               <input type="file" name="file" size="40" id="file" />\r
+       </div>\r
+       \r
+       <div class="row">\r
+               <?php echo _AT('master_not_in_list'); ?><br />\r
+               <input type="radio" name="override" id="o0" value="0" checked="checked" /><label for="o0"><?php echo _AT('leave_unchanged'); ?></label>\r
+               <input type="radio" name="override" id="o1" value="1" /><label for="o1"><?php echo _AT('disable');     ?></label>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type= "submit" name="submit" value="<?php echo _AT('upload'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php\r
+\r
+if (isset($_GET['status']) && ($_GET['status'] != '')) {\r
+       if ($_GET['status'] == 1) {\r
+               $status = ' M.member_id=0 ';\r
+       } else {\r
+               $status = ' M.member_id>0 ';\r
+       }\r
+       $page_string .= SEP.'status='.$_GET['status'];\r
+} else {\r
+       $status = '1';\r
+}\r
+\r
+if ($_GET['search']) {\r
+       $_GET['search'] = trim($_GET['search']);\r
+       $page_string .= SEP.'search='.urlencode($_GET['search']);\r
+       $search = $addslashes($_GET['search']);\r
+\r
+       $search = explode(',', $search);\r
+\r
+       $sql = '';\r
+       foreach ($search as $term) {\r
+               $term = trim($term);\r
+               $term = str_replace(array('%','_'), array('\%', '\_'), $term);\r
+               if ($term) {\r
+                       if (strpos($term, '-') === FALSE) {\r
+                               $term = '%'.$term.'%';\r
+                               $sql .= "(M.public_field LIKE '$term') OR ";\r
+                       } else {\r
+                               // range search\r
+                               $range = explode('-', $term, 2);\r
+                               $range[0] = trim($range[0]);\r
+                               $range[1] = trim($range[1]);\r
+                               if (is_numeric($range[0]) && is_numeric($range[1])) {\r
+                                       $sql .= "(M.public_field >= $range[0] AND M.public_field <= $range[1]) OR ";\r
+                               } else {\r
+                                       $sql .= "(M.public_field >= '$range[0]' AND M.public_field <= '$range[1]') OR ";\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       $sql = '('.substr($sql, 0, -3).')';\r
+       $search = $sql;\r
+} else {\r
+       $search = '1';\r
+}\r
+\r
+$sql   = "SELECT COUNT(member_id) AS cnt FROM ".TABLE_PREFIX."master_list M WHERE $status AND $search";\r
+\r
+$result = mysql_query($sql, $db);\r
+$row = mysql_fetch_assoc($result);\r
+\r
+$num_results = $row['cnt'];\r
+\r
+$results_per_page = 100;\r
+$num_pages = max(ceil($num_results / $results_per_page), 1);\r
+$page = intval($_GET['p']);\r
+if (!$page) {\r
+       $page = 1;\r
+}\r
+$offset = ($page-1)*$results_per_page;\r
+\r
+$sql   = "SELECT M.*, B.login, B.first_name, B.second_name, B.last_name FROM ".TABLE_PREFIX."master_list M LEFT JOIN ".TABLE_PREFIX."members B USING (member_id) WHERE $status AND $search ORDER BY M.public_field LIMIT $offset, $results_per_page";\r
+$result = mysql_query($sql, $db);\r
+?>\r
+\r
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+       <div class="input-form">\r
+               <div class="row">\r
+                       <h3><?php echo _AT('results_found', $num_results); ?></h3>\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <?php echo _AT('account_status'); ?><br />\r
+                       <input type="radio" name="status" value="1" id="s0" <?php if ($_GET['status'] == 1) { echo 'checked="checked"'; } ?> /><label for="s0"><?php echo _AT('not_created'); ?></label> \r
+\r
+                       <input type="radio" name="status" value="2" id="s1" <?php if ($_GET['status'] == 2) { echo 'checked="checked"'; } ?> /><label for="s1"><?php echo _AT('created'); ?></label> \r
+\r
+                       <input type="radio" name="status" value="" id="s" <?php if ($_GET['status'] == '') { echo 'checked="checked"'; } ?> /><label for="s"><?php echo _AT('all'); ?></label> \r
+               </div>\r
+\r
+               <div class="row">\r
+                       <label for="search"><?php echo _AT('search'); ?> (<?php echo _AT('student_id'); ?>)</label><br />\r
+                       <input type="text" name="search" id="search" size="20" value="<?php echo htmlspecialchars($_GET['search']); ?>" />\r
+               </div>\r
+\r
+               <div class="row buttons">\r
+                       <input type="submit" name="filter" value="<?php echo _AT('filter'); ?>" />\r
+                       <input type="submit" name="reset_filter" value="<?php echo _AT('reset_filter'); ?>" />\r
+               </div>\r
+       </div>\r
+</form>\r
+\r
+<div class="paging">\r
+       <ul>\r
+       <?php for ($i=1; $i<=$num_pages; $i++): ?>\r
+               <li>\r
+                       <?php if ($i == $page) : ?>\r
+                               <a class="current" href="<?php echo $_SERVER['PHP_SELF']; ?>?p=<?php echo $i.$page_string; ?>"><em><?php echo $i; ?></em></a>\r
+                       <?php else: ?>\r
+                               <a href="<?php echo $_SERVER['PHP_SELF']; ?>?p=<?php echo $i.$page_string; ?>"><?php echo $i; ?></a>\r
+                       <?php endif; ?>\r
+               </li>\r
+       <?php endfor; ?>\r
+       </ul>\r
+</div>\r
+\r
+\r
+<form name="form" method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<input type="hidden" name="status" value="<?php echo $_GET['status']; ?>" />\r
+\r
+<table summary="" class="data" rules="cols" style="width: 60%;">\r
+<thead>\r
+<tr>\r
+       <th scope="col">&nbsp;</th>\r
+       <th scope="col"><?php echo _AT('student_id'); ?></th>\r
+       <th scope="col"><?php echo _AT('login_name'); ?></th>\r
+       <th scope="col"><?php echo _AT('first_name'); ?></th>\r
+       <th scope="col"><?php echo _AT('second_name'); ?></th>\r
+       <th scope="col"><?php echo _AT('last_name'); ?></th>\r
+</tr>\r
+</thead>\r
+<?php if ($num_results > 0): ?>\r
+<tfoot>\r
+<tr>\r
+       <td colspan="6"><input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /></td>\r
+</tr>\r
+</tfoot>\r
+<tbody>\r
+       <?php while($row = mysql_fetch_assoc($result)): ?>\r
+               <tr onmousedown="document.form['m<?php echo $row['public_field']; ?>'].checked = true;rowselect(this);" id="r_<?php echo $row['public_field']; ?>">\r
+                       <td><input type="radio" name="id" value="<?php \r
+                               if ($row['member_id']) {\r
+                                       echo $row['member_id'];\r
+                               } else {\r
+                                       echo '-'.$row['public_field'];\r
+                               }\r
+                               ?>" id="m<?php echo $row['public_field']; ?>" /></td>\r
+                       <td><label for="m<?php echo $row['public_field']; ?>"><?php echo $row['public_field']; ?></label></td>\r
+                       <td><?php\r
+                               if ($row['member_id']) {\r
+                                       echo $row['login'];\r
+                               } else {\r
+                                       echo '-';\r
+                               }\r
+                               ?></td>\r
+                       <td><?php\r
+                               if ($row['member_id']) {\r
+                                       echo $row['first_name'];\r
+                               } else {\r
+                                       echo '-';\r
+                               }\r
+                               ?></td>\r
+                       <td><?php\r
+                               if ($row['member_id']) {\r
+                                       echo $row['second_name'];\r
+                               } else {\r
+                                       echo '-';\r
+                               }\r
+                               ?></td>\r
+                       <td><?php\r
+                               if ($row['member_id']) {\r
+                                       echo $row['last_name'];\r
+                               } else {\r
+                                       echo '-';\r
+                               }\r
+                               ?></td>\r
+               </tr>\r
+       <?php endwhile; ?>\r
+</tbody>\r
+<?php else: ?>\r
+       <tr>\r
+               <td colspan="6"><?php echo _AT('none_found'); ?></td>\r
+       </tr>\r
+<?php endif; ?>\r
+</table>\r
+</form>\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/master_list_delete.php b/admin/master_list_delete.php
new file mode 100644 (file)
index 0000000..7900176
--- /dev/null
@@ -0,0 +1,49 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_USERS);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.AT_BASE_HREF.'admin/master_list.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       $_POST['id'] = $addslashes($_POST['id']);\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."master_list WHERE public_field='$_POST[id]'";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       write_to_log(AT_ADMIN_LOG_DELETE, 'master_list', mysql_affected_rows($db), $sql);\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: '.AT_BASE_HREF.'admin/master_list.php');\r
+       exit;\r
+}\r
+require(AT_INCLUDE_PATH.'header.inc.php'); ?>\r
+<?php\r
+$_GET['id'] = $addslashes($_GET['id']);\r
+$sql = "SELECT * FROM ".TABLE_PREFIX."master_list WHERE public_field='$_GET[id]'";\r
+$result = mysql_query($sql, $db);\r
+if (!($row = mysql_fetch_assoc($result))) {\r
+       echo _AT('no_user_found');\r
+} else {\r
+       $hidden_vars['id'] = $_GET['id'];\r
+       $confirm = array('LIST_DELETE', $_GET['id']);\r
+       $msg->addConfirm($confirm, $hidden_vars);\r
+       $msg->printConfirm();\r
+}\r
+?>\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/master_list_edit.php b/admin/master_list_edit.php
new file mode 100644 (file)
index 0000000..04e3d3b
--- /dev/null
@@ -0,0 +1,74 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_USERS);\r
+\r
+$_REQUEST['id'] = $addslashes($_REQUEST['id']);\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.AT_BASE_HREF.'admin/master_list.php');\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       $_POST['public_field'] = trim($_POST['public_field']);\r
+       if ($_POST['public_field'] == '') {\r
+               $msg->addError(array('EMPTY_FIELDS', _AT('student_id')));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               $_POST['public_field'] = $addslashes($_POST['public_field']);\r
+\r
+               $sql = "UPDATE ".TABLE_PREFIX."master_list SET public_field='$_POST[public_field]' WHERE public_field='$_POST[id]'";\r
+               $result = mysql_query($sql, $db);\r
+\r
+               write_to_log(AT_ADMIN_LOG_UPDATE, 'master_list', mysql_affected_rows($db), $sql);\r
+\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+\r
+               header('Location: '.AT_BASE_HREF.'admin/master_list.php');\r
+               exit;\r
+       }\r
+} \r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+\r
+$sql = "SELECT * FROM ".TABLE_PREFIX."master_list WHERE public_field='$_REQUEST[id]'";\r
+$result = mysql_query($sql, $db);\r
+if (!($row = mysql_fetch_assoc($result))) {\r
+       $msg->addError('USER_NOT_FOUND');\r
+       $msg->printErrors();\r
+       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+} else {\r
+       $_POST = $row;\r
+}\r
+?>\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">\r
+<input type="hidden" name="id" value="<?php echo $_REQUEST['id']; ?>" />\r
+<div class="input-form">\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="student_id"><?php echo _AT('student_id'); ?></label><br />\r
+               <input type="text" name="public_field" id="student_id" size="25" value="<?php echo $_POST['public_field']; ?>" />\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/missing_language.php b/admin/missing_language.php
new file mode 100644 (file)
index 0000000..0b662a5
--- /dev/null
@@ -0,0 +1,38 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+//if ($_SESSION['course_id'] > -1) { exit; }\r
+\r
+if (isset($_POST['submit'])) {\r
+       unset($_POST['g']);\r
+       unset($_POST['submit']);\r
+       $langEditor->updateTerms($_POST);\r
+}\r
+\r
+$params = array();\r
+if ($_POST['filter_new']) {\r
+       $params['new'] = true;\r
+}\r
+if ($_POST['filter_update']) {\r
+       $params['update'] = true;\r
+}\r
+$langEditor->setFilter($params);\r
+\r
+\r
+$langEditor->printTerms($_GET['terms']);\r
+\r
+\r
+?>
\ No newline at end of file
diff --git a/admin/modules/add_new.php b/admin/modules/add_new.php
new file mode 100644 (file)
index 0000000..8153cc3
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);
+require(AT_INCLUDE_PATH.'classes/Module/ModuleParser.class.php');
+
+if (isset($_GET['mod'])) {
+       $dir_name = str_replace(array('.','..'), '', $_GET['mod']);
+
+       if (isset($_GET['install'])) {
+               header('Location: '.AT_BASE_HREF.'admin/modules/details.php?mod='.urlencode($dir_name).SEP.'new=1');
+               exit;
+       }
+
+} else if (isset($_GET['install'])) {
+       $msg->addError('NO_ITEM_SELECTED');
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+$module_list = $moduleFactory->getModules(AT_MODULE_STATUS_UNINSTALLED | AT_MODULE_STATUS_MISSING, AT_MODULE_TYPE_EXTRA);
+$keys = array_keys($module_list);
+natsort($keys);
+
+?>
+
+<div class="input-form">
+       <div class="row">
+               <?php echo _AT('install_module_text', realpath('./../../mods')); ?>             
+       </div>
+</div>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get" name="installform">
+<table class="data" summary="" rules="cols" style="width:80%;">
+<thead>
+<tr>
+       <th scope="col">&nbsp;</th>
+       <th scope="col"><?php echo _AT('module_name'); ?></th>
+       <th scope="col"><?php echo _AT('directory_name'); ?></th>
+       <th scope="col"><?php echo _AT('description'); ?></th>
+</tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="4">
+               <input type="submit" name="install"  value="<?php echo _AT('install'); ?>" />
+       </td>
+</tr>
+</tfoot>
+<tbody>
+<?php if (!empty($keys)): ?>
+       <?php foreach($keys as $dir_name) : $module =& $module_list[$dir_name]; ?>
+               <tr onmousedown="document.installform['m_<?php echo $dir_name; ?>'].checked = true; rowselect(this);" id="r_<?php echo $dir_name; ?>">
+                       <td valign="top"><input type="radio" id="m_<?php echo $dir_name; ?>" name="mod" value="<?php echo $dir_name; ?>" /></td>
+                       <td valign="top"><label for="m_<?php echo $row['dir_name']; ?>"><?php echo $module->getName(); ?></label></td>
+                       <td valign="top"><code><?php echo $dir_name; ?>/</code></td>
+                       <td valign="top"><?php echo $module->getDescription($_SESSION['lang']); ?></td>
+               </tr>
+       <?php endforeach; ?>
+<?php else: ?>
+       <tr>
+               <td colspan="4"><?php echo _AT('none_found'); ?></td>
+       </tr>
+<?php endif; ?>
+</tbody>
+</table>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/modules/create.php b/admin/modules/create.php
new file mode 100644 (file)
index 0000000..713c3c5
--- /dev/null
@@ -0,0 +1,138 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);
+
+unset($module_xml);
+
+if (isset($_POST['submit'])) {
+       require('./module.template.php');
+       
+       $maintainers_xml = '';
+       if (isset($_POST['name_1'], $_POST['email_1']) && $_POST['name_1'] && $_POST['email_1']) {
+               $maintainers_xml .= str_replace(array('{NAME}', '{EMAIL}'), array($stripslashes($_POST['name_1']), $stripslashes($_POST['email_1'])), $maintainer_xml);
+       }
+
+       if (isset($_POST['name_2'], $_POST['email_2']) && $_POST['name_2'] && $_POST['email_2']) {
+               $maintainers_xml .= str_replace(array('{NAME}', '{EMAIL}'), array($stripslashes($_POST['name_2']), $stripslashes($_POST['email_2'])), $maintainer_xml);
+       }
+       $maintainers_xml .= "\n";
+       $tokens = array('{NAME}', '{DESCRIPTION}', '{MAINTAINERS}', '{URL}', '{VERSION}', '{USER_PRIVILEGE}', '{DATE}', '{LICENSE}', '{STATE}', '{NOTES}');
+       $replace = array($stripslashes($_POST['name']),
+                                       $stripslashes($_POST['description']),
+                                       $maintainers_xml, 
+                                       $stripslashes($_POST['url']),
+                                       $stripslashes($_POST['version']),
+                                       $stripslashes($_POST['priv']),
+                                       $stripslashes($_POST['date']),
+                                       $stripslashes($_POST['license']),
+                                       $stripslashes($_POST['state']),
+                                       $stripslashes($_POST['notes']));
+
+       $module_xml = str_replace($tokens, $replace, $module_xml);
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if (isset($module_xml)) :  ?>
+       <form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+       <div class="input-form">
+               <div class="input-form">
+                       <div class="row"><pre><?php highlight_string($module_xml); ?></pre></div>
+               </div>
+
+               <div class="row buttons">
+                       <input type="submit" name="submit" value="<?php echo _AT('back'); ?>" />
+               </div>
+       </div>
+       </form>
+<?php else: ?>
+
+[[ this form is used to generate the module.xml file which must be packaged with each module ]]
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<div class="input-form">
+       <h3><?php echo _AT('module_details'); ?></h3>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="name"><?php echo _AT('module_name'); ?></label><br />
+               <input type="text" name="name" id="name" size="40" value="" />
+       </div>
+
+       <div class="row">
+               <label for="desc"><?php echo _AT('description'); ?></label><br />
+               <textarea name="description" id="desc" cols="10" rows="2"></textarea>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('maintainers'); ?>
+               <ol style="margin-top: 0px; margin-bottom: 0px;">
+                       <li style="margin-bottom: 5px;"><label for="name_1"><?php echo _AT('name'); ?></label> <input type="text" name="name_1" id="name_1" size="25" value="" />
+                               <label for="email_1"><?php echo _AT('email'); ?></label> <input type="text" name="email_1" id="email_1" size="35" value="" /></li>
+
+                       <li><label for="name_2"><?php echo _AT('name'); ?></label> <input type="text" name="name_2" id="name_2" size="25" value="" />
+               <label for="email_2"><?php echo _AT('email'); ?></label> <input type="text" name="email_2" id="email_2" size="35" value="" /></li>
+               </ol>
+       </div>
+
+       <div class="row">
+               <label for="url"><?php echo _AT('url'); ?></label><br />
+               <input type="text" name="url" id="url" size="50" value="http://" />
+       </div>
+
+       <div class="row">
+               <label for="license"><?php echo _AT('license'); ?></label><br />
+               <input type="text" name="license" id="license" size="65" value="GPL" />
+       </div>
+
+
+       <h3><?php echo _AT('release_details'); ?></h3>
+
+       <div class="row">
+               <label for="version"><?php echo _AT('version'); ?></label><br />
+               <input type="text" name="version" id="version" size="5" value="" />
+       </div>
+
+       <div class="row">
+               <?php echo _AT('use_custom_privilege'); ?><br />
+               <input type="radio" name="priv" value="false" id="priv_1" checked="checked" /><label for="priv_1"><?php echo _AT('no'); ?></label>, 
+               <input type="radio" name="priv" value="true"  id="priv_2" /><label for="priv_2"><?php echo _AT('yes'); ?></label>
+       </div>
+
+       <div class="row">
+               <label for="date"><?php echo _AT('date'); ?></label><br />
+               <input type="text" name="date" id="date" value="" />
+       </div>
+
+       <div class="row">
+               <?php echo _AT('state'); ?><br />
+                       <input type="radio" name="state" value="stable"       id="state_1" checked="checked" /><label for="state_1"><?php echo _AT('stable'); ?></label>, 
+                       <input type="radio" name="state" value="beta"         id="state_2" /><label for="state_2"><?php echo _AT('beta'); ?></label>,
+                       <input type="radio" name="state" value="experimental" id="state_3" /><label for="state_3"><?php echo _AT('experimental'); ?></label>
+       </div>
+
+       <div class="row">
+               <label for="notes"><?php echo _AT('notes'); ?></label><br />
+               <textarea name="notes" id="notes" cols="10" rows="2"></textarea>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('submit'); ?>" />
+       </div>
+</div>
+</form>
+<?php endif; ?>
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/modules/default_mods.php b/admin/modules/default_mods.php
new file mode 100644 (file)
index 0000000..66b8b40
--- /dev/null
@@ -0,0 +1,256 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: ../courses.php');
+       exit;
+}
+
+if (isset($_POST['up'])) {
+       $up = key($_POST['up']);
+       $_new_modules  = array();
+       if (isset($_POST['main'])) {
+               foreach ($_POST['main'] as $m) {
+                       if ($m == $up) {
+                               $last_m = array_pop($_new_modules);
+                               $_new_modules[] = $m;
+                               $_new_modules[] = $last_m;
+                       } else {
+                               $_new_modules[] = $m;
+                       }
+               }
+
+               $_POST['main'] = $_new_modules;
+       }
+       if (isset($_POST['home'])) {
+               $_new_modules  = array();
+               foreach ($_POST['home'] as $m) {
+                       if ($m == $up) {
+                               $last_m = array_pop($_new_modules);
+                               $_new_modules[] = $m;
+                               $_new_modules[] = $last_m;
+                       } else {
+                               $_new_modules[] = $m;
+                       }
+               }
+               $_POST['home'] = $_new_modules;
+       }
+
+       $_POST['submit'] = TRUE;
+} else if (isset($_POST['down'])) {
+       $_new_modules  = array();
+
+       $down = key($_POST['down']);
+
+       if (isset($_POST['main'])) {
+               foreach ($_POST['main'] as $m) {
+                       if ($m == $down) {
+                               $found = TRUE;
+                               continue;
+                       }
+                       $_new_modules[] = $m;
+                       if ($found) {
+                               $_new_modules[] = $down;
+                               $found = FALSE;
+                       }
+               }
+
+               $_POST['main'] = $_new_modules;
+       }
+
+       if (isset($_POST['home'])) {
+               $_new_modules  = array();
+               foreach ($_POST['home'] as $m) {
+                       if ($m == $down) {
+                               $found = TRUE;
+                               continue;
+                       }
+                       $_new_modules[] = $m;
+                       if ($found) {
+                               $_new_modules[] = $down;
+                               $found = FALSE;
+                       }
+               }
+
+               $_POST['home'] = $_new_modules;
+       }
+
+       $_POST['submit'] = TRUE;
+}
+
+if (isset($_POST['submit'])) {
+       if (isset($_POST['main'])) {
+               $_POST['main'] = array_unique($_POST['main']);
+               $_POST['main'] = array_filter($_POST['main']); // remove empties
+               $main_defaults = implode('|', $_POST['main']);
+
+       } else {
+               $main_defaults = '';
+       }
+
+       if (isset($_POST['home'])) {
+               $_POST['home'] = array_unique($_POST['home']);
+               $_POST['home'] = array_filter($_POST['home']); // remove empties
+               $home_defaults = implode('|', $_POST['home']);
+       } else {
+               $home_defaults = '';
+       }
+
+       if (!($_config_defaults['main_defaults'] == $main_defaults) && (strlen($main_defaults) < 256)) {
+               $sql    = "REPLACE INTO ".TABLE_PREFIX."config VALUES('main_defaults', '$main_defaults')";
+               $result = mysql_query($sql, $db);
+
+               $sql    = "DELETE FROM ".TABLE_PREFIX."config WHERE name='main_defaults_2'";
+       } else if (!($_config_defaults['main_defaults'] == $main_defaults) && (strlen($main_defaults) > 255)) {
+               // we don't have to worry about chopping in the middle since they'll be combined anyway
+               $main_defaults_1 = substr($main_defaults, 0, 255);
+               $main_defaults_2 = substr($main_defaults, 255);
+               $sql    = "REPLACE INTO ".TABLE_PREFIX."config VALUES('main_defaults', '$main_defaults_1')";
+               $result = mysql_query($sql, $db);
+
+               $sql    = "REPLACE INTO ".TABLE_PREFIX."config VALUES('main_defaults_2', '$main_defaults_2')";
+       } else if ($_config_defaults['main_defaults'] == $main_defaults) {
+               $sql    = "DELETE FROM ".TABLE_PREFIX."config WHERE name='main_defaults' OR name='name_defaults_2'";
+       }
+       $result = mysql_query($sql, $db);
+
+
+       if (!($_config_defaults['home_defaults'] == $home_defaults) && (strlen($home_defaults) < 256)) {
+               $sql    = "REPLACE INTO ".TABLE_PREFIX."config VALUES('home_defaults', '$home_defaults')";
+               $result = mysql_query($sql, $db);
+
+               $sql    = "DELETE FROM ".TABLE_PREFIX."config WHERE name='home_defaults_2'";
+
+       } else  if (!($_config_defaults['home_defaults'] == $home_defaults) && (strlen($home_defaults) > 255)) {
+               // we don't have to worry about chopping in the middle since they'll be combined anyway
+               $home_defaults_1 = substr($home_defaults, 0, 255);
+               $home_defaults_2 = substr($home_defaults, 255);
+               $sql    = "REPLACE INTO ".TABLE_PREFIX."config VALUES('home_defaults', '$home_defaults_1')";
+               $result = mysql_query($sql, $db);
+
+               $sql    = "REPLACE INTO ".TABLE_PREFIX."config VALUES('home_defaults_2', '$home_defaults_2')";
+
+       } else if ($_config_defaults['home_defaults'] == $home_defaults) {
+               $sql    = "DELETE FROM ".TABLE_PREFIX."config WHERE name='home_defaults' OR name='home_defaults_2'";
+       }
+       $result = mysql_query($sql, $db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: '.$_SERVER['PHP_SELF']);
+       exit;
+}
+
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$main_defaults = explode('|', $_config['main_defaults']);
+$home_defaults = explode('|', $_config['home_defaults']);
+
+$main_defaults = array_filter($main_defaults); // remove empties
+$home_defaults = array_filter($home_defaults); // remove empties
+?>
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<table class="data static" rules="rows" summary="">
+<thead>
+<tr>
+       <th scope="cols"><?php echo _AT('section'); ?></th>
+       <th><?php echo _AT('location'); ?></th>
+       <th><?php echo _AT('order'); ?></th>
+</tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="3" style="text-align:right;">              
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s"  />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>"  />     
+       </td>
+</tr>
+</tfoot>
+<tbody>
+<?php 
+$module_list =& $moduleFactory->getModules(AT_MODULE_STATUS_ENABLED);
+$keys = array_keys($module_list);
+
+foreach ($keys as $dir_name) {
+       $module =& $module_list[$dir_name]; 
+
+       if ($module->getStudentTools()) {
+               $student_tools[] = $module->getStudentTools();
+       }
+}
+
+$count = 0;
+
+//main mods
+$_current_modules = $main_defaults;
+$num_main    = count($_current_modules);
+//main and home merged
+$_current_modules = array_merge($_current_modules, array_diff($home_defaults, $main_defaults));
+$num_modules = count($_current_modules);
+//all other mods
+$_current_modules = array_merge($_current_modules, array_diff($student_tools, $_current_modules));
+
+
+foreach ($_current_modules as $tool) :
+       $count++; 
+?>
+       <tr>
+               <td><?php 
+               if (isset($_pages[$tool]['title'])) {
+                       echo $_pages[$tool]['title'];
+               } else {
+                       echo _AT($_pages[$tool]['title_var']);
+               } ?></td>
+               <td align="center">
+                       <?php if (in_array($tool, $main_defaults)): ?>
+                               <input type="checkbox" name="main[]" value="<?php echo $tool; ?>" id="m<?php echo $tool; ?>" checked="checked" /><label for="m<?php echo $tool; ?>"><?php echo _AT('main_navigation'); ?></label>
+                       <?php else: ?>
+                               <input type="checkbox" name="main[]" value="<?php echo $tool; ?>" id="m<?php echo $tool; ?>" /><label for="m<?php echo $tool; ?>"><?php echo _AT('main_navigation'); ?></label>
+                       <?php endif; ?>
+
+                       <?php if (in_array($tool, $home_defaults)): ?>
+                               <input type="checkbox" name="home[]" value="<?php echo $tool; ?>" id="h<?php echo $tool; ?>" checked="checked" /><label for="h<?php echo $tool; ?>"><?php echo _AT('home'); ?></label>
+                       <?php else: ?>
+                               <input type="checkbox" name="home[]" value="<?php echo $tool; ?>" id="h<?php echo $tool; ?>" /><label for="h<?php echo $tool; ?>"><?php echo _AT('home'); ?></label>
+                       <?php endif; ?>
+               </td>
+               <td align="right">
+                       <?php if (!in_array($tool, $home_defaults) && !in_array($tool, $main_defaults)): ?>
+                               &nbsp;
+                       <?php else: ?>
+                               <?php if (($count != $num_main+1) && ($count > 1)): ?>
+                                       <input type="submit" name="up[<?php echo $tool; ?>]" value="<?php echo _AT('move_up'); ?>" title="<?php echo _AT('move_up'); ?>" style="background-color: white; border: 1px solid; padding: 0px;" />
+                               <?php else: ?>
+                                       <img src="images/clr.gif" alt="" width="12" />
+                               <?php endif; ?>
+                               <?php if (($count != $num_main) && ($count < $num_modules)): ?>
+                                       <input type="submit" name="down[<?php echo $tool; ?>]" value="<?php echo _AT('move_down'); ?>" title="<?php echo _AT('move_down'); ?>" style="background-color: white; border: 1px solid; padding: 0px;"/>
+                               <?php else: ?>
+                                       <img src="images/clr.gif" alt="" width="12" />
+                               <?php endif; ?>
+                       <?php endif; ?>
+               </td>
+       </tr>
+<?php 
+endforeach; ?>
+</tbody>
+</table>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/modules/default_side.php b/admin/modules/default_side.php
new file mode 100644 (file)
index 0000000..da7f6a0
--- /dev/null
@@ -0,0 +1,100 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$ $
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);
+
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: ../courses.php');
+       exit;
+}
+
+if (isset($_POST['submit'])) {
+
+       $side_menu = '';
+       $_stack_names = array();
+
+       foreach($_stacks as $name=>$file) {
+               $_stack_names[] = $name;
+       }
+
+       $_POST['stack'] = array_unique($_POST['stack']);
+       $_POST['stack'] = array_intersect($_POST['stack'], $_stack_names);
+
+       foreach($_POST['stack'] as $dropdown) {
+               if($dropdown != '') {
+                       $side_menu .= $dropdown . '|';
+               }
+       }
+       $side_menu = substr($side_menu, 0, -1);
+
+       if (!($_config_defaults['side_defaults'] == $side_menu) && (strlen($side_menu) < 256)) {
+               $sql    = "REPLACE INTO ".TABLE_PREFIX."config VALUES('side_defaults', '$side_menu')";
+       } else if ($_config_defaults['side_defaults'] == $side_menu) {
+               $sql    = "DELETE FROM ".TABLE_PREFIX."config WHERE name='side_defaults'";
+       }
+
+       $result = mysql_query($sql, $db);
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location:'. $_SERVER[PHP_SELF]);
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="prefs">
+<div class="input-form" style="width:50%">
+       <div class="row">
+               <p><?php echo _AT('side_menu_text'); ?></p>
+       </div>
+
+       <div class="row">
+               <?php
+                       $num_stack = count($_stacks);   
+
+                       $side_menu = explode('|', $_config['side_defaults']);
+
+                       for ($i=0; $i<$num_stack; $i++) {                               
+                               echo '<select name="stack['.$i.']">';
+                               echo '<option value=""></option>';
+                               foreach ($_stacks as $name=>$info) {
+                                       if (isset($info['title'])) {
+                                               $title = $info['title'];
+                                       } else {
+                                               $title = _AT($info['title_var']);
+                                       }
+                                       echo '<option value="'.$name.'"';
+                                       if (isset($side_menu[$i]) && ($name == $side_menu[$i])) {
+                                               echo ' selected="selected"';
+                                       }
+                                       echo '>'.$title.'</option>';
+                               }
+                               echo '</select>';
+                               echo '<br />'; 
+                       } ?>
+       </div>
+
+       <div class="buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>"  />
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/modules/details.php b/admin/modules/details.php
new file mode 100644 (file)
index 0000000..9ddb023
--- /dev/null
@@ -0,0 +1,186 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);
+
+require(AT_INCLUDE_PATH.'classes/Module/ModuleParser.class.php');
+
+
+if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'admin/modules/add_new.php');
+       exit;
+} else if (isset($_POST['mod']) && isset($_POST['submit_yes'])) {
+       $module =& $moduleFactory->getModule($_POST['mod']);
+       $module->load();
+       $module->install();
+
+       if ($msg->containsErrors()) {
+               header('Location: '.AT_BASE_HREF.'admin/modules/details.php?mod='.$addslashes($_POST['mod']).SEP.'new=1');
+       } else {
+               $msg->addFeedback('MOD_INSTALLED');
+               header('Location: '.AT_BASE_HREF.'admin/modules/index.php');
+       }
+       exit;
+} else if (isset($_GET['submit'])) {
+       $args = '';
+
+       if (isset($_GET['enabled'])  && $_GET['enabled'])  {  $args .= 'enabled=1';      }
+       if (isset($_GET['disabled']) && $_GET['disabled']) {  $args .= SEP.'disabled=1'; }
+       if (isset($_GET['missing'])  && $_GET['missing'])  {  $args .= SEP.'missing=1';  }
+       if (isset($_GET['core'])     && $_GET['core'])     {  $args .= SEP.'core=1';     }
+       if (isset($_GET['standard']) && $_GET['standard']) {  $args .= SEP.'standard=1'; }
+       if (isset($_GET['extra'])    && $_GET['extra'])    {  $args .= SEP.'extra=1';    }
+
+       header('Location: index.php?'. $args);
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+$moduleParser =& new ModuleParser();
+
+$_REQUEST['mod'] = str_replace(array('.','..'), '', $_REQUEST['mod']);
+
+if (!file_exists('../../mods/'.$_GET['mod'].'/module.xml')) {
+?>
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<input type="hidden" name="mod" value="<?php echo $_GET['mod']; ?>" />
+<input type="hidden" name="new" value="<?php echo $_GET['new']; ?>" />
+<div class="input-form">
+       <div class="row">
+               <h3><?php echo $_GET['mod']; ?></h3>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('missing_info'); ?>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('back'); ?>" />
+               <?php if (isset($_GET['new']) && $_GET['new']): ?>
+                       <input type="submit" name="install" value="<?php echo _AT('install'); ?>" />
+               <?php endif; ?>
+       </div>
+
+</div>
+</form>
+<?php
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+$moduleParser->parse(file_get_contents('../../mods/'.$_GET['mod'].'/module.xml'));
+
+$module =& $moduleFactory->getModule($_GET['mod']);
+
+$properties = $module->getProperties(array('maintainers', 'url', 'date', 'license', 'state', 'notes', 'version'));
+?>
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<input type="hidden" name="mod" value="<?php echo $_GET['mod']; ?>" />
+<input type="hidden" name="new" value="<?php echo $_GET['new']; ?>" />
+
+<input type="hidden" name="enabled" value="<?php echo (int) isset($_GET['enabled']); ?>" />
+<input type="hidden" name="disabled" value="<?php echo (int) isset($_GET['disabled']); ?>" />
+<input type="hidden" name="core" value="<?php echo (int) isset($_GET['core']); ?>" />
+<input type="hidden" name="standard" value="<?php echo (int) isset($_GET['standard']); ?>" />
+<input type="hidden" name="extra" value="<?php echo (int) isset($_GET['extra']); ?>" />
+<input type="hidden" name="missing" value="<?php echo (int) isset($_GET['missing']); ?>" />
+
+<div class="input-form">
+       <div class="row">
+               <h3><?php echo $module->getName(); ?></h3>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('description'); ?><br />
+               <?php echo nl2br($module->getDescription($_SESSION['lang'])); ?>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('maintainers'); ?><br />
+                       <ul class="horizontal">
+                               <?php foreach ($properties['maintainers'] as $maintainer): ?>
+                                       <li><?php echo $maintainer['name'] .' &lt;'.$maintainer['email'].'&gt;'; ?></li>
+                               <?php endforeach; ?>
+                       </ul>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('url'); ?><br />
+               <?php echo $properties['url']; ?>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('version'); ?><br />
+               <?php echo $properties['version']; ?>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('date'); ?><br />
+               <?php echo $properties['date']; ?>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('license'); ?><br />
+               <?php echo $properties['license']; ?>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('state'); ?><br />
+               <?php echo $properties['state']; ?>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('notes'); ?><br />
+               <?php echo nl2br($properties['notes']); ?>
+       </div>
+
+       <?php if (is_array($module->_pages)): ?>
+               <div class="row">
+                       <?php if (!isset($_GET['files'])): ?>
+                               <a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES).SEP; ?>files#files"><?php echo _AT('files'); ?></a><br />
+                       <?php else: ?>
+                               <?php $module_pages = array_keys($module->_pages); ?>
+                               <?php natsort($module_pages); ?>
+                               <a name="files"></a><?php echo _AT('files'); ?><br />
+                               <ul style="margin-top: 0px;">
+                                       <?php foreach ($module_pages as $key): ?>
+                                               <?php if (defined($key)) : continue; endif; ?>
+                                               <li><kbd><?php echo $key; ?></kbd></li>
+                                       <?php endforeach; ?>
+                               </ul>
+                       <?php endif; ?>
+               </div>
+       <?php endif; ?>
+
+<?php if (!isset($_REQUEST['new'])): ?>
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('back'); ?>" />
+       </div>
+<?php endif; ?>
+</div>
+</form>
+<?php if (isset($_REQUEST['new'])): ?>
+       <?php
+               $hidden_vars['mod'] = $_REQUEST['mod'];
+               $hidden_vars['new'] = '1';
+               $msg->addConfirm(array('ADD_MODULE', $_REQUEST['mod']), $hidden_vars);
+               $msg->printConfirm();
+       ?>
+<?php endif; ?>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/modules/index.php b/admin/modules/index.php
new file mode 100644 (file)
index 0000000..75c2bb2
--- /dev/null
@@ -0,0 +1,201 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);
+
+$dir_name = str_replace(array('.','..'), '', $_GET['mod_dir']);
+
+$args = '';
+
+if (isset($_GET['enabled'])  && $_GET['enabled'])  {  $args .= 'enabled=1';      }
+if (isset($_GET['disabled']) && $_GET['disabled']) {  $args .= SEP.'disabled=1'; }
+if (isset($_GET['missing'])  && $_GET['missing'])  {  $args .= SEP.'missing=1';  }
+if (isset($_GET['core'])     && $_GET['core'])     {  $args .= SEP.'core=1';     }
+if (isset($_GET['standard']) && $_GET['standard']) {  $args .= SEP.'standard=1'; }
+if (isset($_GET['extra'])    && $_GET['extra'])    {  $args .= SEP.'extra=1';    }
+
+if (isset($_GET['reset_filter'])) {
+       header('Location: '.$_SERVER['PHP_SELF']);
+       exit;
+}
+
+if (isset($_GET['mod_dir'], $_GET['enable'])) {
+       $module =& $moduleFactory->getModule($_GET['mod_dir']);
+       if (!$module->isEnabled() && !$module->isCore() && !$module->isMissing()) {
+               $module->enable();
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       }
+
+       header('Location: '.$_SERVER['PHP_SELF'] . '?' . $args);
+       exit;
+} else if (isset($_GET['mod_dir'], $_GET['disable'])) {
+       $module =& $moduleFactory->getModule($_GET['mod_dir']);
+       if ($module->isCore()) {
+               // core modules cannot be disabled!
+               $msg->addError('DISABLE_CORE_MODULE');
+       } else if ($module->isMissing()) {
+               $msg->addError('DISABLE_MISSING_MODULE');
+       } else if ($module->isEnabled()) {
+               $module->disable();
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       }
+       header('Location: '.$_SERVER['PHP_SELF'] . '?' . $args);
+       exit;
+} else if (isset($_GET['mod_dir'], $_GET['details'])) {
+       header('Location: details.php?mod='.$_GET['mod_dir'] . SEP . $args);
+       exit;
+
+} else if (isset($_GET['disable']) || isset($_GET['enable']) || isset($_GET['details'])) {
+       $msg->addError('NO_ITEM_SELECTED');
+       header('Location: '.$_SERVER['PHP_SELF'] . '?' . $args);
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+$module_status_bits = $module_type_bits = 0;
+
+if (isset($_GET['enabled']))  { $module_status_bits += AT_MODULE_STATUS_ENABLED;  }
+if (isset($_GET['disabled'])) {        $module_status_bits += AT_MODULE_STATUS_DISABLED; }
+if (isset($_GET['missing']))  {        $module_status_bits += AT_MODULE_STATUS_MISSING;  }
+
+if (isset($_GET['core']))     {  $module_type_bits += AT_MODULE_TYPE_CORE;     }
+if (isset($_GET['standard'])) {  $module_type_bits += AT_MODULE_TYPE_STANDARD; }
+if (isset($_GET['extra']))    {  $module_type_bits += AT_MODULE_TYPE_EXTRA;    }
+
+if ($module_status_bits == 0) {
+       $module_status_bits = AT_MODULE_STATUS_DISABLED | AT_MODULE_STATUS_ENABLED | AT_MODULE_STATUS_MISSING;
+       $_GET['enabled'] = $_GET['disabled'] = $_GET['missing'] = 1;
+}
+
+if ($module_type_bits == 0) {
+       $module_type_bits = AT_MODULE_TYPE_STANDARD + AT_MODULE_TYPE_EXTRA;
+       $_GET['standard'] = $_GET['extra'] = 1;
+}
+
+
+$module_list = $moduleFactory->getModules($module_status_bits, $module_type_bits, $sort = TRUE);
+$keys = array_keys($module_list);
+?>
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+       <div class="input-form">
+               <div class="row">
+                       <h3><?php echo _AT('results_found', count($keys)); ?></h3>
+               </div>
+
+               <div class="row">
+                       <?php echo _AT('type'); ?><br />
+                       <input type="checkbox" name="core" value="1" id="t0" <?php if (isset($_GET['core'])) { echo 'checked="checked"'; } ?> /><label for="t0"><?php echo _AT('core'); ?></label>
+
+                       <input type="checkbox" name="standard" value="1" id="t1" <?php if (isset($_GET['standard'])) { echo 'checked="checked"'; } ?> /><label for="t1"><?php echo _AT('standard'); ?></label> 
+
+                       <input type="checkbox" name="extra" value="1" id="t2" <?php if (isset($_GET['extra'])) { echo 'checked="checked"'; } ?> /><label for="t2"><?php echo _AT('extra'); ?></label> 
+               </div>
+
+
+               <div class="row">
+                       <?php echo _AT('status'); ?><br />
+                       <input type="checkbox" name="enabled" value="1" id="s0" <?php if (isset($_GET['enabled'])) { echo 'checked="checked"'; } ?> /><label for="s0"><?php echo _AT('enabled'); ?></label> 
+
+                       <input type="checkbox" name="disabled" value="1" id="s1" <?php if (isset($_GET['disabled'])) { echo 'checked="checked"'; } ?> /><label for="s1"><?php echo _AT('disabled'); ?></label> 
+
+                       <input type="checkbox" name="missing" value="1" id="s2" <?php if (isset($_GET['missing'])) { echo 'checked="checked"'; } ?> /><label for="s2"><?php echo _AT('missing'); ?></label> 
+               </div>
+
+               <div class="row buttons">
+                       <input type="submit" name="filter" value="<?php echo _AT('filter'); ?>" />
+                       <input type="submit" name="reset_filter" value="<?php echo _AT('reset_filter'); ?>" />
+               </div>
+       </div>
+</form>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get" name="form">
+
+<input type="hidden" name="enabled" value="<?php echo (int) isset($_GET['enabled']); ?>" />
+<input type="hidden" name="disabled" value="<?php echo (int) isset($_GET['disabled']); ?>" />
+<input type="hidden" name="core" value="<?php echo (int) isset($_GET['core']); ?>" />
+<input type="hidden" name="standard" value="<?php echo (int) isset($_GET['standard']); ?>" />
+<input type="hidden" name="extra" value="<?php echo (int) isset($_GET['extra']); ?>" />
+<input type="hidden" name="missing" value="<?php echo (int) isset($_GET['missing']); ?>" />
+
+<table class="data" summary="" rules="cols">
+<colgroup>
+               <col />
+               <col class="sort" />
+               <col span="4" />
+<thead>
+<tr>
+       <th scope="col">&nbsp;</th>
+       <th scope="col"><?php echo _AT('module_name'); ?></th>
+       <th scope="col"><?php echo _AT('type'); ?></th>
+       <th scope="col"><?php echo _AT('status'); ?></th>
+       <th scope="col"><?php echo _AT('cron'); ?></th>
+       <th scope="col"><?php echo _AT('directory_name'); ?></th>
+</tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="6">
+               <input type="submit" name="details" value="<?php echo _AT('details'); ?>" />
+               <input type="submit" name="enable"  value="<?php echo _AT('enable'); ?>" />
+               <input type="submit" name="disable" value="<?php echo _AT('disable'); ?>" />
+       </td>
+</tr>
+</tfoot>
+<tbody>
+<?php foreach($keys as $dir_name) : $module =& $module_list[$dir_name]; ?>
+
+       <tr onmousedown="document.form['t_<?php echo $dir_name; ?>'].checked = true; rowselect(this);" id="r_<?php echo $dir_name; ?>">
+               <td valign="top"><input type="radio" id="t_<?php echo $dir_name; ?>" name="mod_dir" value="<?php echo $dir_name; ?>" /></td>
+               <td nowrap="nowrap" valign="top"><label for="t_<?php echo $dir_name; ?>"><?php echo $module->getName(); ?></label></td>
+               <td valign="top"><?php
+                       if ($module->isCore()) {
+                               echo '<strong>'._AT('core').'</strong>';
+                       } else if ($module->isStandard()) {
+                               echo _AT('standard');
+                       } else {
+                               echo _AT('extra');
+                       }
+                       ?></td>
+               <td valign="top"><?php
+                       if ($module->isEnabled()) {
+                               echo _AT('enabled');
+                       } else if ($module->isMissing()) {
+                               echo '<strong>'._AT('missing').'</strong>';
+                       } else {
+                               echo '<em>'._AT('disabled').'</em>';
+                       }
+                       ?></td>
+               <td valign="top" align="center">
+                       <?php if ($module->getCronInterval()): ?>
+                               <?php echo _AT('minutes', $module->getCronInterval()); ?>
+                       <?php else: ?>
+                               -
+                       <?php endif; ?>
+               </td>
+               <td valign="top"><code><?php echo $dir_name; ?>/</code></td>
+       </tr>
+<?php endforeach; ?>
+<?php if (!$keys): ?>
+       <tr>
+               <td colspan="6"><?php echo _AT('none_found'); ?></td>
+       </tr>
+<?php endif; ?>
+</tbody>
+</table>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/modules/module.template.php b/admin/modules/module.template.php
new file mode 100644 (file)
index 0000000..0cd5c18
--- /dev/null
@@ -0,0 +1,24 @@
+<?php\r
+\r
+$module_xml = '<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+       <name>{NAME}</name> \r
+       <description>{DESCRIPTION}</description> \r
+       <maintainers>{MAINTAINERS}      </maintainers> \r
+       <url>{URL}</url> \r
+       <license>{LICENSE}</license> \r
+       <release> \r
+               <version>{VERSION}</version> \r
+               <use_privilege>{USER_PRIVILEGE}</use_privilege> \r
+               <date>{DATE}</date> \r
+               <state>{STATE}</state> \r
+               <notes>{NOTES}</notes> \r
+       </release> \r
+</module>';\r
+\r
+$maintainer_xml = "\n\t\t".'<maintainer> \r
+                       <name>{NAME}</name> \r
+                       <email>{EMAIL}</email> \r
+               </maintainer>';\r
+\r
+?>
\ No newline at end of file
diff --git a/admin/password_user.php b/admin/password_user.php
new file mode 100644 (file)
index 0000000..207d3a6
--- /dev/null
@@ -0,0 +1,145 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id: users.php 5035 2005-06-28 18:02:56Z joel $
+
+$_user_location = 'admin';
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_USERS);
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'admin/users.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       /* password check: password is verified front end by javascript. here is to handle the errors from javascript */
+       if ($_POST['password_error'] <> "")
+       {
+               $pwd_errors = explode(",", $_POST['password_error']);
+
+               foreach ($pwd_errors as $pwd_error)
+               {
+                       if ($pwd_error == "missing_password")
+                               $missing_fields[] = _AT('password');
+                       else
+                               $msg->addError($pwd_error);
+               }
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['id'] = intval($_POST['id']);
+
+               $sql = "UPDATE ".TABLE_PREFIX."members SET password= '$_POST[form_password_hidden]', creation_date=creation_date, last_login=last_login WHERE member_id=$_POST[id]";
+               $result = mysql_query($sql, $db);
+
+               $sql    = "SELECT login, email FROM ".TABLE_PREFIX."members WHERE member_id=$_POST[id]";
+               $result = mysql_query($sql,$db);
+               if ($row = mysql_fetch_assoc($result)) {
+                       $r_login = $row['login'];       
+                       $r_email = $row['email'];
+
+                       $tmp_message  = _AT('password_change_msg')."\n\n";
+                       $tmp_message .= _AT('web_site').' : '.AT_BASE_HREF."\n";
+                       $tmp_message .= _AT('login_name').' : '.$r_login."\n";
+
+                       require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+
+                       $mail = new ATutorMailer;
+
+                       $mail->From     = $_config['contact_email'];
+                       $mail->AddAddress($r_email);
+                       $mail->Subject = $_config['site_name'] . ': ' . _AT('password_changed');
+                       $mail->Body    = $tmp_message;
+
+                       if(!$mail->Send()) {
+                          $msg->printErrors('SENDING_ERROR');
+                          exit;
+                       }
+
+               }
+
+               $msg->addFeedback('PROFILE_UPDATED_ADMIN');
+               header('Location: '.AT_BASE_HREF.'admin/users.php');
+               exit;
+       }
+       $_GET['id'] = $_POST['id'];
+}
+
+
+$onload = 'document.form.password.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$id = intval($_GET['id']);
+
+$sql   = "SELECT login FROM ".TABLE_PREFIX."members WHERE member_id=$id";
+$result = mysql_query($sql, $db);
+
+if (!$row = mysql_fetch_assoc($result)) {
+       $msg->printErrors('USER_NOT_FOUND');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+?>
+<script language="JavaScript" src="sha-1factory.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+function encrypt_password()
+{
+       document.form.password_error.value = "";
+
+       err = verify_password(document.form.password.value, document.form.password2.value);
+       
+       if (err.length > 0)
+       {
+               document.form.password_error.value = err;
+       }
+       else
+       {
+               document.form.form_password_hidden.value = hex_sha1(document.form.password.value);
+               document.form.password.value = "";
+               document.form.password2.value = "";
+       }
+}
+</script>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">
+       <input type="hidden" name="id" value="<?php echo $id; ?>" />
+       <input type="hidden" name="form_password_hidden" value="" />
+       <input type="hidden" name="password_error" value="" />
+
+       <div class="input-form">
+               <div class="row">
+                       <h3><?php echo htmlspecialchars($row['login']); ?></h3>
+               </div>
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="password"><?php echo _AT('password'); ?></label><br />
+                       <input type="password" name="password" id="password" value="" size="30" />
+               </div>
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="password2"><?php echo _AT('confirm_password'); ?></label><br />
+                       <input type="password" name="password2" id="password2" value="" size="30" />
+               </div>
+
+               <div class="row buttons">
+                       <input type="submit" name="submit" value="<?php echo _AT('submit'); ?>" onClick="encrypt_password()" />
+                       <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+               </div>
+       </div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/profile_picture.php b/admin/profile_picture.php
new file mode 100644 (file)
index 0000000..197c42a
--- /dev/null
@@ -0,0 +1,20 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id: profile_picture.php 6850 2007-03-06 19:35:37Z joel $\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_USERS);\r
+\r
+$member_id = intval($_GET['member_id']);\r
+\r
+require(AT_INCLUDE_PATH.'html/profile_picture.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/rss_feeds/add_feed.php b/admin/rss_feeds/add_feed.php
new file mode 100644 (file)
index 0000000..1229913
--- /dev/null
@@ -0,0 +1,136 @@
+<?php  \r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH . 'vitals.inc.php');\r
+\r
+admin_authenticate(AT_ADMIN_PRIV_RSS);\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header("Location: index_admin.php");\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       $missing_fields = array();\r
+\r
+       if (trim($_POST['title']) == '') {\r
+               $missing_fields[] = _AT('title');\r
+       }\r
+       if (trim($_POST['url']) == '') {\r
+               $missing_fields[] = _AT('url');\r
+       }\r
+       if ($missing_fields) {\r
+               $missing_fields = implode(', ', $missing_fields);\r
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               $output = make_cache_file(0);\r
+               if (!isset($output) || empty($output)) {\r
+                       $msg->addError('FEED_NO_CONTENT');\r
+               }\r
+       }\r
+\r
+       if ($msg->containsErrors()) {\r
+               unset($_POST['confirm']);\r
+       }\r
+\r
+} else if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+\r
+} else if (isset($_POST['submit_yes'])) {\r
+       $_POST['url'] = $addslashes($_POST['url']);\r
+\r
+       $sql    = "INSERT INTO ".TABLE_PREFIX."feeds VALUES (NULL, '".$_POST['url']."')";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $feed_id = mysql_insert_id($db);\r
+       \r
+       //copy load file\r
+       copy('../../mods/_standard/rss_feeds/load_file.php', AT_CONTENT_DIR.'feeds/'.$feed_id.'_rss.inc.php');\r
+\r
+       //add language\r
+       $title_file = AT_CONTENT_DIR.'feeds/'.$feed_id.'_rss_title.cache';\r
+       if ($f = @fopen($title_file, 'w')) {\r
+               fwrite ($f, $_POST['title'], strlen($_POST['title']));\r
+               fclose($f);\r
+       }\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: index.php');\r
+       exit;\r
+} \r
+\r
+$onload = 'document.form.title.focus();';\r
+\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+if (!isset($_POST['confirm'])) {\r
+?>\r
+       <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">\r
+               <input type="hidden" name="confirm" value="1" />\r
+\r
+               <div class="input-form" style="max-width: 525px">\r
+                       <div class="row">\r
+                               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php echo _AT('title'); ?></label><br />\r
+                               <input id="title" name="title" type="text" size="60" maxlength="255" value="<?php echo $stripslashes(htmlspecialchars($_POST['title'])); ?>" /><br />\r
+                       </div>\r
+\r
+                       <div class="row">\r
+                               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="url"><?php echo _AT('url'); ?></label><br />\r
+                               <input id="url" name="url" type="text" size="60" maxlength="255" value="<?php echo $stripslashes(htmlspecialchars($_POST['url'])); ?>" /><br />\r
+                       </div>\r
+\r
+                       <div class="row buttons">\r
+                               <input type="submit" name="submit" value=" <?php echo _AT('save'); ?> " accesskey="s" />\r
+                               <input type="submit" name="cancel" value=" <?php echo _AT('cancel'); ?> " />\r
+                       </div>\r
+               </div>\r
+       </form>\r
+<?php \r
+} else { ?>\r
+\r
+       <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+       <input type="hidden" name="new" value="<?php echo $_POST['new']; ?>" />\r
+\r
+       <div class="input-form">\r
+               <div class="row">\r
+                       <h3><?php if (file_exists($title_file)) { \r
+                                       readfile($title_file); \r
+                               } else {\r
+                                       echo $_POST['title'];\r
+                               }?>\r
+                       </h3>\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <?php echo $output; ?>\r
+               </div>\r
+       </div>\r
+       </form>\r
+\r
+       <?php\r
+               $hidden_vars['new'] = '1';\r
+               $hidden_vars['title'] = $_POST['title'];\r
+               $hidden_vars['url'] = $_POST['url'];\r
+\r
+               $msg->addConfirm('ADD_FEED', $hidden_vars);\r
+               $msg->printConfirm();\r
+       ?>\r
+\r
+<?php \r
+}\r
+?>\r
+\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/rss_feeds/delete_feed.php b/admin/rss_feeds/delete_feed.php
new file mode 100644 (file)
index 0000000..b9b004c
--- /dev/null
@@ -0,0 +1,65 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+admin_authenticate(AT_ADMIN_PRIV_RSS);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       $feed_id = intval($_POST['fid']);\r
+\r
+       //delete feed\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."feeds WHERE feed_id=$feed_id";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       //delete feed title from lang\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."language_text WHERE term='".$feed_id."_rss_title'";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       //delete files\r
+       @unlink(AT_CONTENT_DIR.'/feeds/'.$feed_id.'_rss.cache');\r
+       @unlink(AT_CONTENT_DIR.'/feeds/'.$feed_id.'_rss_title.cache');\r
+       @unlink(AT_CONTENT_DIR.'/feeds/'.$feed_id.'_rss.inc.php');\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+\r
+       $feed_id = intval($_GET['fid']);\r
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."feeds WHERE feed_id=".$feed_id;\r
+       $result = mysql_query($sql, $db);\r
+       $row = mysql_fetch_assoc($result);\r
+\r
+       if (!$row) {\r
+               $msg->addError('FEED_NOT_FOUND');\r
+               $msg->printErrors();\r
+       } else {\r
+               $hidden_vars['delete_feed'] = TRUE;\r
+               $hidden_vars['fid'] = $feed_id;\r
+\r
+               $title = file_get_contents(AT_CONTENT_DIR.'/feeds/'.$feed_id.'_rss_title.cache');\r
+               $msg->addConfirm(array('DELETE_FEED', $title), $hidden_vars);\r
+               $msg->printConfirm();\r
+       }\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php'); \r
+?>
\ No newline at end of file
diff --git a/admin/rss_feeds/edit_feed.php b/admin/rss_feeds/edit_feed.php
new file mode 100644 (file)
index 0000000..6c869c3
--- /dev/null
@@ -0,0 +1,100 @@
+<?php  \r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH . 'vitals.inc.php');\r
+\r
+admin_authenticate(AT_ADMIN_PRIV_RSS);\r
+\r
+$feed_id = intval($_GET['fid']);\r
+$title_file = AT_CONTENT_DIR.'feeds/'.$feed_id.'_rss_title.cache';\r
+\r
+if (isset($_GET['submit'])) {\r
+       $missing_fields = array();\r
+       //check both fields are not empty\r
+       if (trim($_POST['title']) == '') {\r
+               $missing_fields[] = _AT('title');\r
+       }\r
+       if (trim($_POST['url']) == '') {\r
+               $missing_fields[] = _AT('url');\r
+       }\r
+       if ($missing_fields) {\r
+               $missing_fields = implode(', ', $missing_fields);\r
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               $_GET['url'] = $addslashes($_GET['url']);\r
+               \r
+               $sql    = "REPLACE INTO ".TABLE_PREFIX."feeds VALUES(".$feed_id.", '".$_GET['url']."')";\r
+               $result = mysql_query($sql, $db);\r
+\r
+               //update language\r
+               if ($f = @fopen($title_file, 'w')) {\r
+                       fwrite($f, $_GET['title'], strlen($_GET['title']));\r
+                       fclose($f);\r
+               }\r
+\r
+               //delete old cache file\r
+               @unlink(AT_CONTENT_DIR.'/feeds/'.$feed_id.'_rss.cache');\r
+\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+               header('Location: index.php');\r
+               exit;\r
+       } \r
+\r
+} else if (isset($_GET['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header("Location:index.php");\r
+       exit;\r
+}\r
+\r
+if ($feed_id != '') {\r
+\r
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."feeds WHERE feed_id=".$feed_id;\r
+       $result = mysql_query($sql, $db);\r
+       $row = mysql_fetch_assoc($result);\r
+       \r
+       if (file_exists($title_file)) {\r
+               $_GET['title'] = file_get_contents($title_file);\r
+       }\r
+       $_GET['url'] = $row['url'];\r
+} \r
+\r
+$onload = 'document.form.title.focus();';\r
+\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+?>\r
+\r
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get" name="form">\r
+       <input type="hidden" name="fid" value="<?php echo $feed_id; ?>" />\r
+       <div class="input-form" style="max-width: 525px">\r
+               <div class="row">\r
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php echo _AT('title'); ?></label><br />\r
+                       <input id="title" name="title" type="text" size="60" maxlength="255" value="<?php echo $stripslashes(htmlspecialchars($_GET['title'])); ?>" /><br />\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="url"><?php echo _AT('url'); ?></label><br />\r
+                       <input id="url" name="url" type="text" size="60" maxlength="255" value="<?php echo $stripslashes(htmlspecialchars($_GET['url'])); ?>" /><br />\r
+               </div>\r
+\r
+               <div class="row buttons">\r
+                       <input type="submit" name="submit" value=" <?php echo _AT('save'); ?> " accesskey="s" />\r
+                       <input type="submit" name="cancel" value=" <?php echo _AT('cancel'); ?> " />\r
+               </div>\r
+       </div>\r
+</form>\r
+\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/rss_feeds/index.php b/admin/rss_feeds/index.php
new file mode 100644 (file)
index 0000000..d5a816d
--- /dev/null
@@ -0,0 +1,82 @@
+<?php  \r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH . 'vitals.inc.php');\r
+\r
+admin_authenticate(AT_ADMIN_PRIV_RSS);\r
+\r
+\r
+if ((isset($_GET['preview']) || isset($_GET['edit']) || isset($_GET['delete'])) && !isset($_GET['fid'])) {\r
+       $msg->addError('NO_ITEM_SELECTED');\r
+} else if (isset($_GET['edit'])) {\r
+       header("Location:edit_feed.php?fid=".intval($_GET['fid']));\r
+       exit;\r
+} else if (isset($_GET['delete'])) {\r
+       header("Location:delete_feed.php?fid=".intval($_GET['fid']));\r
+       exit;\r
+} else if (isset($_GET['preview'])) {\r
+       header("Location:preview.php?fid=".intval($_GET['fid']));\r
+       exit;\r
+}\r
+\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+?>\r
+\r
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get" name="form">\r
+\r
+<table class="data" summary="" rules="cols">\r
+<thead>\r
+<tr>\r
+       <th scope="col">&nbsp;</th>\r
+       <th scope="col"><?php echo _AT('title'); ?></th>\r
+       <th scope="col"><?php echo _AT('url'); ?></th>\r
+</tr>\r
+</thead>\r
+<tfoot>\r
+<tr>\r
+       <td colspan="3">\r
+               <input type="submit" name="preview" value="<?php echo _AT('preview'); ?>" />\r
+               <input type="submit" name="edit"    value="<?php echo _AT('edit'); ?>" />\r
+               <input type="submit" name="delete"  value="<?php echo _AT('delete'); ?>" />\r
+       </td>\r
+</tr>\r
+</tfoot>\r
+<tbody>\r
+<?php \r
+$sql   = "SELECT * FROM ".TABLE_PREFIX."feeds ORDER BY feed_id";\r
+$result = mysql_query($sql, $db);\r
+\r
+if (!($row = mysql_fetch_assoc($result))) { \r
+?>\r
+\r
+       <tr>\r
+               <td colspan="3"><?php echo _AT('none_found'); ?></td>\r
+       </tr>\r
+<?php } else { ?>\r
+       <?php do { \r
+               $title_file = AT_CONTENT_DIR.'feeds/'.$row['feed_id'].'_rss_title.cache'; ?>\r
+               <tr onmousedown="document.form['f_<?php echo $row['feed_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $row['feed_id']; ?>">\r
+                       <td valign="top"><input type="radio" id="f_<?php echo $row['feed_id']; ?>" name="fid" value="<?php echo $row['feed_id']; ?>" /></td>\r
+                       <td><label for="f_<?php echo $row['feed_id']; ?>"><?php if (file_exists($title_file)) { readfile($title_file); } ?></label></td>\r
+                       <td><?php echo $row['url']; ?></td>\r
+               </tr>\r
+       <?php } while ($row = mysql_fetch_assoc($result)); ?>\r
+\r
+<?php } ?>\r
+</tbody>\r
+</table>\r
+</form>\r
+\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/rss_feeds/preview.php b/admin/rss_feeds/preview.php
new file mode 100644 (file)
index 0000000..3a6c46c
--- /dev/null
@@ -0,0 +1,58 @@
+<?php  \r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH . 'vitals.inc.php');\r
+\r
+admin_authenticate(AT_ADMIN_PRIV_RSS);\r
+\r
+if (isset($_POST['back'])) {\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$feed_id    = intval($_GET['fid']);\r
+$cache_file = AT_CONTENT_DIR.'feeds/'.$feed_id.'_rss.cache';\r
+$title_file = AT_CONTENT_DIR.'feeds/'.$feed_id.'_rss_title.cache';\r
+\r
+if (!file_exists($cache_file) || ((time() - filemtime($cache_file)) > 21600) ) {\r
+       make_cache_file($feed_id);\r
+}\r
+?>\r
+\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+\r
+<div class="input-form">\r
+       <div class="row">\r
+               <h3><?php if (file_exists($title_file)) { readfile($title_file); } ?></h3>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <?php if (file_exists($cache_file) && filesize($cache_file) > 0) { \r
+                       readfile($cache_file); \r
+                       echo '<p><br /><small>'._AT('new_window').'</small></p>';\r
+               } else {\r
+                       echo _AT('no_content_avail');\r
+               }?>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="back" value="<?php echo _AT('back'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/themes/delete.php b/admin/themes/delete.php
new file mode 100644 (file)
index 0000000..d6a3bb2
--- /dev/null
@@ -0,0 +1,40 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+$_user_location = 'admin';\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_THEMES);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       require_once(AT_INCLUDE_PATH.'lib/themes.inc.php');\r
+       delete_theme($_POST['tc']);\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+\r
+$hidden_vars['tc'] = $_GET['theme_code'];\r
+\r
+$msg->addConfirm(array('DELETE_THEME', $_GET['theme_code']), $hidden_vars);\r
+$msg->printConfirm();\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/admin/themes/import.php b/admin/themes/import.php
new file mode 100644 (file)
index 0000000..fe4d7f0
--- /dev/null
@@ -0,0 +1,203 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+$_user_location = 'admin';\r
+// 1. define relative path to `include` directory:\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require (AT_INCLUDE_PATH . 'vitals.inc.php');\r
+require (AT_INCLUDE_PATH . 'lib/filemanager.inc.php'); /* for clr_dir() and dirsize() */\r
+require (AT_INCLUDE_PATH . 'classes/pclzip.lib.php');\r
+require (AT_INCLUDE_PATH . 'classes/Themes/ThemeParser.class.php');\r
+admin_authenticate(AT_ADMIN_PRIV_THEMES);\r
+\r
+\r
+if(isset($_POST['import'])) {\r
+       import_theme();\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+/**\r
+* Imports a theme from a URL or Zip file to Atutor\r
+* @access  private\r
+* @author  Shozub Qureshi\r
+*/\r
+function import_theme() {\r
+       global $db;\r
+       global $msg;\r
+       \r
+       if (isset($_POST['url']) && ($_POST['url'] != 'http://') ) {\r
+               if ($content = @file_get_contents($_POST['url'])) {\r
+       \r
+                       // save file to /themes/\r
+                       $filename = pathinfo($_POST['url']);\r
+                       $filename = $filename['basename'];\r
+                       $full_filename = AT_CONTENT_DIR . '/' . $filename;\r
+                       \r
+                       if (!$fp = fopen($full_filename, 'w+b')) {\r
+                               //Cannot open file ($filename)";\r
+                               $errors = array('CANNOT_OPEN_FILE', $filename);\r
+                               $msg->addError($errors);\r
+                               header('Location: index.php');\r
+                               exit;\r
+                       }\r
+               \r
+                       if (fwrite($fp, $content, strlen($content) ) === FALSE) {\r
+                               //"Cannot write to file ($filename)";\r
+                               $errors = array('CANNOT_WRITE_FILE', $filename);\r
+                               $msg->addError($errors);\r
+                               header('Location: index.php');\r
+                               exit;\r
+                       }\r
+                       fclose($fp);\r
+               }       \r
+               $_FILES['file']['name']     = $filename;\r
+               $_FILES['file']['tmp_name'] = $full_filename;\r
+               $_FILES['file']['size']     = strlen($content);\r
+               unset($content);\r
+               $url_parts = pathinfo($_POST['url']);\r
+               $package_base_name_url = $url_parts['basename'];\r
+       }\r
+       $ext = pathinfo($_FILES['file']['name']);\r
+       $ext = $ext['extension'];\r
+       \r
+       //error in the file\r
+       if ($_FILES['file']['error'] == 1) { \r
+               $errors = array('FILE_MAX_SIZE', ini_get('upload_max_filesize'));\r
+               $msg->addError($errors);\r
+               header('Location: index.php');\r
+               exit;\r
+       }\r
+\r
+       //If file has no name or no address or if the extension is not .zip\r
+       if (!$_FILES['file']['name'] \r
+               || (!is_uploaded_file($_FILES['file']['tmp_name']) && !$_POST['url'])) {\r
+\r
+                       $msg->addError('FILE_NOT_SELECTED');\r
+                       header('Location: index.php');\r
+                       exit;\r
+       }\r
+       \r
+       if (($ext != 'zip')) {\r
+               $msg->addError('IMPORT_NOT_PROPER_FORMAT');\r
+               header('Location: index.php');\r
+               exit;\r
+       }\r
+\r
+       //check if file size is ZERO    \r
+       if ($_FILES['file']['size'] == 0) {\r
+               $msg->addError('IMPORTFILE_EMPTY');\r
+               header('Location: index.php');\r
+               exit;\r
+       }\r
+\r
+       // new directory name is the filename minus the extension\r
+       $fldrname    = substr($_FILES['file']['name'], 0, -4);\r
+       $fldrname   = str_replace(' ', '_', $fldrname);\r
+       $import_path = '../../themes/' . $fldrname;\r
+\r
+       //check if Folder by that name already exists\r
+       if (is_dir($import_path)) {\r
+               $i = 1;\r
+               while (is_dir($import_path . '_' . $i)) {\r
+                       $i++;\r
+               }\r
+               $fldrname    = $fldrname . '_' . $i; \r
+               $import_path = $import_path . '_' . $i;\r
+       }\r
+       \r
+       //if folder does not exist previously\r
+       if (!@mkdir($import_path, 0700)) { \r
+               $msg->addError('IMPORTDIR_FAILED');\r
+               header('Location: index.php'); \r
+               exit;\r
+       }\r
+       \r
+       // unzip file and save into directory in themes\r
+       $archive = new PclZip($_FILES['file']['tmp_name']);\r
+\r
+       //extract contents to importpath/foldrname\r
+       if (!$archive->extract($import_path)) {\r
+               $errors = array('IMPORT_ERROR_IN_ZIP', $archive->errorInfo(true));\r
+               clr_dir($import_path);\r
+               $msg->addError($errors);\r
+               header('Location: index.php'); \r
+               exit;\r
+       }\r
+\r
+       $handle = opendir($import_path);\r
+       while ($file = readdir($handle)) { \r
+       if (is_dir($import_path.'/'.$file) && $file != '.' && $file != '..') {\r
+                  $folder = $file;\r
+          }\r
+       }\r
+\r
+       //copy contents from importpath/foldrname to importpath\r
+       copys($import_path.'/'.$folder, $import_path);\r
+\r
+       //delete importpath/foldrname\r
+       clr_dir($import_path.'/'.$folder);\r
+\r
+       $theme_xml = @file_get_contents($import_path . '/theme_info.xml');\r
+\r
+       //Check if XML file exists (if it doesnt send error and clear directory)\r
+       if ($theme_xml == false) {\r
+               /** Next version 1.4.4, require themes.xml\r
+               $msg->addError('MISSING_THEMEXML');\r
+               \r
+               // clean up\r
+               clr_dir($import_path);\r
+               \r
+               header('Location: index.php');\r
+               exit;\r
+               */\r
+               $version = '1.4.x';\r
+               $extra_info = 'unspecified';\r
+       } else {\r
+               //parse information\r
+               $xml_parser =& new ThemeParser();\r
+               $xml_parser->parse($theme_xml);\r
+\r
+               $version      = $xml_parser->theme_rows['version'];\r
+               $extra_info   = $xml_parser->theme_rows['extra_info'];\r
+       }\r
+\r
+       $title        = str_replace('_', ' ', $fldrname);\r
+       $last_updated = date('Y-m-d');\r
+       $status       = '1';\r
+\r
+       //if version number is not compatible with current Atutor version, set theme as disabled\r
+       if ($version != VERSION) {\r
+               $status = '0';\r
+       }\r
+\r
+       //save information in database\r
+       $sql = "INSERT INTO ".TABLE_PREFIX."themes VALUES ('$title', '$version', '$fldrname', '$last_updated', '$extra_info', '$status')";\r
+       $result = mysql_query($sql, $db);       \r
+       \r
+       write_to_log(AT_ADMIN_LOG_INSERT, 'themes', mysql_affected_rows($db), $sql);\r
+\r
+       if (!$result) {\r
+               $msg->addError('IMPORT_FAILED');\r
+               header('Location: index.php');\r
+               exit;\r
+       }\r
+\r
+       if (isset($_POST['url'])) {\r
+               @unlink($full_filename);\r
+       }\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/admin/themes/index.php b/admin/themes/index.php
new file mode 100644 (file)
index 0000000..1e9630a
--- /dev/null
@@ -0,0 +1,160 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+$_user_location = 'admin';\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'lib/themes.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_THEMES);\r
+\r
+$theme   = $addslashes($_GET['theme_dir']);\r
+$version = $addslashes($_GET[$theme.'_version']);\r
+\r
+if (isset($_GET['export'], $_GET['theme_dir'])) {\r
+       export_theme($theme);\r
+} else if (isset($_GET['delete'], $_GET['theme_dir'])) {\r
+       header('Location: delete.php?theme_code='.urlencode($theme));\r
+       exit;\r
+} else if (isset($_GET['default'], $_GET['theme_dir'])) {\r
+       set_theme_as_default($theme);\r
+       $_config['pref_defaults'] = unserialize($_config['pref_defaults']);\r
+       $_config['pref_defaults']['PREF_THEME'] = $theme;\r
+       $_config['pref_defaults'] = serialize($_config['pref_defaults']);\r
+\r
+       $sql    = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('pref_defaults','{$_config['pref_defaults']}')";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       header('Location: '.$_SERVER['PHP_SELF']);\r
+       exit;\r
+} else if (isset($_GET['enable'], $_GET['theme_dir'])) {\r
+       if ($version != VERSION) {\r
+               $str = $theme . ' - version: ' . $version;\r
+               $warnings = array('THEME_VERSION_DIFF', $str);\r
+               $msg->addWarning($warnings);\r
+       }\r
+       enable_theme($theme);\r
+       header('Location: '.$_SERVER['PHP_SELF']);\r
+       exit;\r
+} else if (isset($_GET['disable'], $_GET['theme_dir'])) {\r
+       disable_theme($theme);\r
+       header('Location: '.$_SERVER['PHP_SELF']);\r
+       exit;\r
+} else if (isset($_GET['preview'], $_GET['theme_dir'])) {\r
+       $_SESSION['prefs']['PREF_THEME'] = $_GET['theme_dir'];\r
+       header('Location: '.$_SERVER['PHP_SELF']);\r
+       exit;\r
+} else if (isset($_GET['disable']) || isset($_GET['enable']) || isset($_GET['default']) || isset($_GET['delete']) || isset($_GET['export'])) {\r
+       $msg->addError('NO_ITEM_SELECTED');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$sql    = "SELECT * FROM " . TABLE_PREFIX . "themes ORDER BY title ASC";\r
+$result = mysql_query($sql, $db);\r
+?>\r
+\r
+<?php if (!is_writeable(realpath('./../../themes'))): ?>\r
+       <div class="input-form">\r
+               <div class="row">\r
+                       <?php echo _AT('install_themes_text', realpath('./../../themes')); ?>           \r
+               </div>\r
+       </div>\r
+<?php else: ?>\r
+       <form name="importForm" method="post" action="admin/themes/import.php" enctype="multipart/form-data">\r
+       <div class="input-form" style="width:50%;">\r
+               <div class="row">\r
+                       <h3><?php echo _AT('import_theme'); ?></h3>\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <label for="file"><?php echo _AT('upload_theme_package'); ?></label><br />\r
+                       <input type="file" name="file" size="40" id="file" />\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <label for="url"><?php echo _AT('specify_url_to_theme_package'); ?></label><br />\r
+                       <input type="text" name="url" value="http://" size="40" id="url" />\r
+               </div>\r
+                       \r
+               <div class="row buttons">\r
+                       <input type= "submit" name="import" value="<?php echo _AT('import'); ?>" />\r
+               </div>\r
+       </div>\r
+       </form>\r
+\r
+       <br /><br />\r
+<?php endif; ?>\r
+\r
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get" name="form">\r
+<table class="data" summary="" rules="cols">\r
+<thead>\r
+<tr>\r
+       <th scope="col">&nbsp;</th>\r
+       <th scope="col"><?php echo _AT('title'); ?></th>\r
+       <th scope="col"><?php echo _AT('status'); ?></th>\r
+       <th scope="col"><?php echo _AT('version'); ?></th>\r
+       <th scope="col"><?php echo _AT('directory_name'); ?></th>\r
+       <th scope="col"><?php echo _AT('description'); ?></th>\r
+       <th scope="col"><?php echo _AT('theme_screenshot'); ?></th>\r
+</tr>\r
+</thead>\r
+<tfoot>\r
+<tr>\r
+       <td colspan="7">\r
+               <input type="submit" name="preview"  value="<?php echo _AT('preview'); ?>" />\r
+               <input type="submit" name="enable"  value="<?php echo _AT('enable'); ?>" />\r
+               <input type="submit" name="disable" value="<?php echo _AT('disable'); ?>" />\r
+               <input type="submit" name="default" value="<?php echo _AT('set_default'); ?>" />\r
+               <input type="submit" name="export"  value="<?php echo _AT('export'); ?>" />\r
+               <input type="submit" name="delete"  value="<?php echo _AT('delete'); ?>" />\r
+       </td>\r
+</tr>\r
+</tfoot>\r
+<?php while($row = mysql_fetch_assoc($result)) : ?>\r
+       <tbody>\r
+       <tr onmousedown="document.form['t_<?php echo $row['dir_name']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $row['dir_name']; ?>">\r
+               <td valign="top">\r
+                       <input type="radio" id="t_<?php echo $row['dir_name']; ?>" name="theme_dir" value="<?php echo $row['dir_name']; ?>" />\r
+                       <input type="hidden" name="<?php echo $row['dir_name']; ?>_version" value="<?php echo $row['version']; ?>" />\r
+               </td>\r
+               <td nowrap="nowrap" valign="top"><label for="t_<?php echo $row['dir_name']; ?>"><?php echo AT_print($row['title'], 'themes.title'); ?></label></td>\r
+               <td valign="top"><?php\r
+                       if ($row['status'] == 0) {\r
+                               echo _AT('disabled');\r
+                       } else if ($row['status'] == 1) {\r
+                               echo _AT('enabled');\r
+                       } else if ($row['status'] == 2) {\r
+                               echo '<strong>'._AT('default').'</strong>'; \r
+                       }\r
+                       ?>\r
+               </td>\r
+               <td valign="top"><?php echo $row['version']; ?></td>\r
+               <td valign="top"><code><?php echo $row['dir_name']; ?>/</code></td>\r
+               <td valign="top"><?php echo $row['extra_info']; ?></td>\r
+               <td valign="top"><?php\r
+                       if (file_exists('../../themes/'.$row['dir_name'].'/screenshot.jpg')) { ?>\r
+                                 <img src="<?php echo AT_BASE_HREF; ?>themes/<?php echo $row['dir_name']; ?>/screenshot.jpg" border="1" alt="<?php echo _AT('theme_screenshot'); ?>" />\r
+                       <?php           \r
+                       } else if (file_exists('../../themes/'.$row['dir_name'].'/screenshot.gif')) { ?>\r
+                                <img src="<?php echo AT_BASE_HREF; ?>themes/<?php echo $row['dir_name']; ?>/screenshot.gif" border="1" alt="<?php echo _AT('theme_screenshot'); ?>" />\r
+                       <?php } ?>\r
+               </td>\r
+       </tr>\r
+       </tbody>\r
+<?php endwhile; ?>\r
+</table>\r
+</form>\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/translate.php b/admin/translate.php
new file mode 100644 (file)
index 0000000..77606d3
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+$_REQUEST['u'] = 'admin';
+
+$_user_location = 'admin';
+
+$variables = array('_template', '_msgs');
+// Get the language codes for the languages on the current system
+
+define('AT_INCLUDE_PATH', '../include/');
+?>
+
+<script language="javascript" type="text/javascript">
+function openWindow(page) {
+       newWindow = window.open(page, "progWin", "width=400,height=200,toolbar=no,location=no");
+       newWindow.focus();
+}
+</script>
+
+<br /><form name="form1" method="post" action="admin/import_lang.php" enctype="multipart/form-data" onsubmit="openWindow('tools/prog.php');">
+<input type="hidden" name="import" value="1" />
+<table cellspacing="1" cellpadding="0" border="0" class="bodyline" width="80%" summary="" align="center">
+<tr>
+       <td class="cyan" colspan="2"><?php echo _AT('import_a_new_lang'); ?></td>
+</tr>
+<tr>
+       <td colspan="2"><small><?php echo _AT('import_lang_howto'); ?></small></td>
+</tr>
+<tr>
+       <td align="center" colspan="2"><br /><strong><?php echo _AT('import_a_new_lang'); ?></strong>: <input type="file" name="file" class="formfield" /> | <input type="submit" name="submit" value="<?php echo _AT('import'); ?>" class="button" /><br /><br /></td>
+</tr>
+</table>
+</form>
diff --git a/admin/translate_atutor.php b/admin/translate_atutor.php
new file mode 100644 (file)
index 0000000..8c4b38c
--- /dev/null
@@ -0,0 +1,83 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.               */\r
+/****************************************************************/\r
+\r
+$page = 'translate';\r
+$_user_location = 'public';\r
+$page_title = 'ATutor: LCMS: Translation';\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+if (!$_REQUEST['f']) {\r
+       $_REQUEST['f']  = 'en';\r
+}\r
+\r
+if (!defined('AT_DEVEL_TRANSLATE') || !AT_DEVEL_TRANSLATE) { exit; }\r
+\r
+$_INCLUDE_PATH = AT_INCLUDE_PATH;\r
+$_TABLE_PREFIX = TABLE_PREFIX;\r
+$_TABLE_SUFFIX = '';\r
+\r
+$_SESSION['language'] = $_SESSION['lang'];\r
+\r
+global $db;\r
+global $_user_location;\r
+global $_base_path;\r
+global $addslashes;\r
+?>\r
+\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r
+<html lang="en">\r
+<head>\r
+       <title>ATutor Translator Site</title>\r
+       <link rel="stylesheet" href="<?php echo AT_BASE_HREF; ?>include/style_popup.css" type="text/css" />\r
+       <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />\r
+       <base href="<?php echo AT_BASE_HREF; ?>" />\r
+</head>\r
+\r
+<body>\r
+\r
+<?php\r
+\r
+echo '<div align="right"><a href="javascript:window.close()">' . _AT('close_window') . '</a></div>';\r
+echo '<h3>ATutor Translator Site</h3>';\r
+\r
+$variables = array('_template','_msgs','_module');\r
+\r
+$atutor_test = '<a href="'.$_base_path.'" title="Open ATutor in a new window" target="new">';\r
+\r
+$_SESSION['status'] = 2;\r
+$_USER_ADMIN = $_SESSION['status'];\r
+\r
+$sql = "SELECT english_name, char_set FROM ".TABLE_PREFIX."languages WHERE language_code = '$_SESSION[language]'";\r
+$result = mysql_query($sql, $db);\r
+$row = mysql_fetch_assoc($result);\r
+\r
+?>\r
+<ol>\r
+       <li><br />\r
+       <table border="0" cellspacing="0" cellpadding="2" style="border: 1px solid #cccccc;" >\r
+       <tr>\r
+               <td  bgcolor="#eeeeee" nowrap="nowrap"><h5 class="heading2">Translate</h5></td>\r
+               <td style="font-size:small; border-left: 1px solid #cccccc;">\r
+                       From <strong>English - iso-8859-1</strong> to <strong> <?php echo $row['english_name'] . ' - ' . $row['char_set']; ?> </strong>\r
+               </td>\r
+       </tr>\r
+       </table>\r
+       </li>\r
+       <br />\r
+\r
+       <?php require_once('translator.php'); ?>\r
+\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/admin/translator.php b/admin/translator.php
new file mode 100644 (file)
index 0000000..a1d1589
--- /dev/null
@@ -0,0 +1,602 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+if ( !isset($db) || !defined('AT_INCLUDE_PATH') || !isset($_SESSION['language'])       ) { echo 'xx'; exit; }
+
+if ($_POST['function'] == 'edit_term') {
+       if ($_POST['submit2']) {
+               delete_term($_POST['v'], $_POST['k']);
+       } else {
+               $success_error = update_term($_POST['text'], $_POST['context'], $_POST['v'], $_POST['k']);
+       }
+} else if ($_POST['function'] == 'add_term') {
+       $success_error = add_term($_POST['text'], $_POST['context'], $_POST['v'], $_POST['k']);
+       $_REQUEST['page'] = 'none';
+}
+
+if ($_REQUEST['n']) {
+       $n = ' checked="checked"';
+               }
+if ($_REQUEST['u']) {
+       $u = ' checked="checked"';
+}
+
+if ($_SESSION['language'] != 'en') {
+       echo '<li>Choose the New and Updated filters to display only language that has not been translated, or language that needs to be modified<br />';
+
+       echo '<table border="0" cellspacing="0" cellpadding="2" style="border: 1px solid #cccccc;"><tr><td  bgcolor="#eeeeee" nowrap="nowrap"><h5 class="heading2">Filter</h5></td><td>';
+       echo '<form method="get" action="'.$_SERVER['PHP_SELF'].'">
+               <input type="hidden" name="v" value="'.$_REQUEST['v'].'" />
+               <input type="hidden" name="f" value="'.$_REQUEST['f'].'" /><input type="checkbox" name="n" id="n" value="1" '.$n.' /><label for="n">New Language</label>, <input type="checkbox" name="u" id="u" value="1" '.$u.'/><label for="u">Updated Language</label> <input type="submit" name="filter" value="Apply" class="submit" /></form></td></tr></table><br />';
+       echo '</li>';
+}
+?>
+
+       <!--//display messages and templates, with option to add new language terms/messages//-->
+       <li>Choose Template,  Msgs, or Modules to display a list of language variables. Click on a variable name to display its associated language.
+               <ul>
+               <?php foreach ($variables as $row) { ?>
+                       <li><strong>
+                       <?php echo '<a href="'.$_SERVER['PHP_SELF'].'?v='.$row.SEP.'f='.$_REQUEST['f'].SEP.'n='.$_REQUEST['n'].SEP.'u='.$_REQUEST['u'].'">';
+                       echo ucwords(str_replace('_', '', $row));
+                       echo '</a>';
+                       if ($_SESSION['status'] == $_USER_ADMIN && ($_SESSION['language'] == 'en')) {
+                               echo ' | <a href="'.$_SERVER['PHP_SELF'].'?v='.$row.SEP.'new=1">new</a>';
+                       }
+                       ?>
+                       </strong></li>
+               <?php } ?>
+               </ul>
+               <br />
+       </li>
+
+       <li>
+               <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>"> 
+                       <input type="text" name="search_term" value="<?php echo htmlspecialchars($stripslashes($_REQUEST['search_term'])); ?>" /> <input type="submit" name="search" value="Search Phrase" class="submit" /> 
+               </form>
+       </li>
+</ol>
+<hr />
+
+<?php if (($_REQUEST['new'] == 1) && $_SESSION['status'] == $_USER_ADMIN) { ?>
+<a name="anchor"></a>
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>#anchor">
+       <input type="hidden" name="search_term" value="<?php echo htmlspecialchars($stripslashes($_REQUEST['search_term'])); ?>" />
+       <input type="hidden" name="v" value="<?php echo $_REQUEST['v']; ?>" />
+       <input type="hidden" name="page" value="<?php echo $_REQUEST['page']; ?>" />
+       <input type="hidden" name="function" value="add_term" />
+
+       <table border="0" cellspacing="0" cellpadding="3" width="75%" align="center" class="box">
+       <tr>
+               <th colspan="2" class="box">New</th>
+       </tr>
+       <tr>
+               <td align="right"><b>Variable:</b></td>
+               <td><tt><?php echo $_REQUEST['v'];?></tt></td>
+       </tr>
+       <tr>
+               <td align="right"><b>Term:</b></td>
+               <td><input type="text" name="k" class="input" /></td>
+       </tr>
+       <tr>
+               <td align="right"><b>Context:</b></td>
+               <td><input type="text" name="context" class="input" /></td>
+       </tr>
+       <tr>
+               <td valign="top" align="right" nowrap="nowrap"><b><tt><?php echo $langs[$_SESSION['language']]['name'];?></tt> text:</b></td>
+               <td><textarea cols="45" rows="5" name="text" class="input2"><?php echo $row2['text'];?></textarea></td>
+       </tr>
+       <tr>
+               <td colspan="2" align="center"><input type="submit" name="submit" value="Save ALT-S" class="submit" accesskey="s" /></td>
+       </tr>
+       </table>
+</form>
+<?php
+       }
+       if ($_REQUEST['v'] && $_REQUEST['k']) {
+               $sql    = "SELECT * FROM ".TABLE_PREFIX."language_text WHERE term='$_REQUEST[k]' AND variable='$_REQUEST[v]' AND `language_code`='$_REQUEST[f]'";
+               $result = mysql_query($sql, $db);
+               $row    = mysql_fetch_assoc($result);
+               if ($row == '') {
+                       echo '<p>The source language was not found for that item (try using the English source).</p>';
+                       require (AT_INCLUDE_PATH.'footer.inc.php');
+                       exit;
+               }
+
+               if ($_SESSION['language'] == 'en') {
+                       $row2 = $row;
+               } else {
+                       $sql    = "SELECT text FROM ".TABLE_PREFIX."language_text WHERE term='$_REQUEST[k]' AND variable='$_REQUEST[v]' AND `language_code`='$_SESSION[language]'";
+               }
+
+               $result = mysql_query($sql, $db);
+               $row2   = mysql_fetch_array($result);
+
+function trans_form($page) {
+       global $row0;
+       global $row;
+       global $row2;
+       global $langs;
+       global $success_error;
+       global $db;
+       global $_USER_ADMIN;
+       global $addslashes;
+       global $stripslashes;
+?>
+<br />
+<a name="anchor"></a>
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>#anchor">
+       <input type="hidden" name="v" value="<?php echo $row['variable']; ?>" />
+       <input type="hidden" name="k" value="<?php echo $row['term']; ?>" />
+       <input type="hidden" name="f" value="<?php echo $_REQUEST['f']; ?>" />
+       <input type="hidden" name="search_term" value="<?php echo htmlspecialchars($stripslashes($_REQUEST['search_term'])); ?>" />
+       <input type="hidden" name="page" value="<?php echo $page; ?>" />
+       <input type="hidden" name="function" value="edit_term" />
+
+       <?php ?>
+
+       <table border="0" cellspacing="0" cellpadding="2" width="90%" align="center" class="box">
+       <tr>
+               <th class="box" colspan="2">Edit</th>
+       </tr>
+       <tr>
+               <td align="right"><b>Context:</b></td>
+               <td><?php
+                       if ($_SESSION['language'] == 'en') {
+                               echo '<input type="text" name="context" class="input" value="'.$row['context'].'" size="45" />';
+                       } else {
+                               if ($row['context'] == '') {
+                                       echo '<em>None specified.</em>';
+                               } else {
+                                       echo $row['context'];
+                               }
+                       } ?>&nbsp;</td>
+       </tr>
+       <tr>
+               <td valign="top" align="right" nowrap="nowrap"><b>Pages:</b></td>
+               <td><?php 
+                                       $sql    = "SELECT * FROM ".TABLE_PREFIX."language_pages WHERE `term`='$_REQUEST[k]' ORDER BY page LIMIT 11";
+                                       $result = mysql_query($sql, $db);
+
+                                       if (mysql_num_rows($result) > 10) {
+                                               echo '<em>Global (more than 10 pages)</em>';
+                                       } else {
+                                               while ($page_row = mysql_fetch_array($result)) {
+                                                       echo $page_row['page'] . '<br />';
+                                               }
+                                       }
+
+                                ?>
+               </td>
+       </tr>
+       <tr>
+               <td valign="top" align="right" nowrap="nowrap"><b><tt><?php echo $langs[$_REQUEST['f']]['name'];?></tt> text:</b></td>
+               <td><?php echo nl2br(htmlspecialchars($row['text'])); ?></td>
+       </tr>
+       <tr>
+               <td valign="top" align="right" nowrap="nowrap"><b><tt><?php echo $langs[$_SESSION['language']]['name'];?></tt> text:</b></td>
+               <td><textarea cols="55" rows="8" name="text" class="input2"><?php echo $row2['text'];?></textarea></td>
+       </tr>
+       <tr>
+               <td colspan="2" align="center"><input type="submit" name="submit" value="Save ALT-S" class="submit" accesskey="s" />
+               <?php if ($_SESSION['language'] == 'en' && $_SESSION['status'] == $_USER_ADMIN): ?>
+                                       &nbsp;&nbsp;&nbsp;&nbsp; <input type="submit" name="submit2" value="Delete" onClick="return confirm('Do you really want to delete?');" class="submit" />
+               <?php endif; ?>
+               </td>
+       </tr>
+       </table>
+       </form>
+
+       <?php
+               echo $success_error;
+       }
+}
+       //displaying templates
+       if (!$_REQUEST['search_term'] && ($_REQUEST['v'] == $variables[0])) {
+               echo '<ul>';
+               
+               echo '<li><a href="'.$_SERVER['PHP_SELF'].'?v='.$_REQUEST['v'].SEP.'page=all'.SEP.'f='.$_REQUEST['f'].SEP.'n='.$_REQUEST['n'].SEP.'u='.$_REQUEST['u'].'#anchor1">View All Terms</a>';
+               
+               if ($_REQUEST['page'] == 'all') {
+                       echo '<a name="anchor1"></a>';
+                       display_all_terms($_REQUEST['v'], $_REQUEST['k'], $_REQUEST['f'], $_REQUEST['n'], $_REQUEST['u']);
+               }
+               echo '</li>';
+
+               echo '<li><a href="'.$_SERVER['PHP_SELF'].'?v='.$_REQUEST['v'].SEP.'page=none'.SEP.'f='.$_REQUEST['f'].SEP.'n='.$_REQUEST['n'].SEP.'u='.$_REQUEST['u'].'#anchor1">View Unused Terms</a>';
+
+               if ($_REQUEST['page'] == 'none') {
+                       echo '<a name="anchor1"></a>';
+                       display_unused_terms($_REQUEST['v'], $_REQUEST['k'], $_REQUEST['f'], $_REQUEST['n'], $_REQUEST['u']);
+               }
+               echo '</li>';
+
+               $sql0 = "SELECT DISTINCT page FROM ".TABLE_PREFIX."language_pages ORDER BY page";
+               $result0 = mysql_query($sql0, $db);
+                               
+               while ($row0 = mysql_fetch_assoc($result0)) {
+
+                       if ($_REQUEST['page'] == $row0['page']) {
+                               display_page_terms($_REQUEST['v'], $_REQUEST['k'], $_REQUEST['f'], $_REQUEST['n'], $_REQUEST['u'], $row0['page']);
+                       }
+                       else {
+                               echo '<li><a href="'.$_SERVER['PHP_SELF'].'?v='.$_REQUEST['v'].SEP.'page='.urlencode($row0['page']).SEP.'f='.$_REQUEST['f'].SEP.'n='.$_REQUEST['n'].SEP.'u='.$_REQUEST['u'].'#anchor1">'.$row0['page'].'</a></li>';
+                       }
+               }
+               echo '</ul>';
+       } else if (!$_REQUEST['search_term'] && ($_REQUEST['v'] == $variables[1])){
+               //displaying messages
+               display_all_terms($_REQUEST['v'], $_REQUEST['k'], $_REQUEST['f'], $_REQUEST['n'], $_REQUEST['u']);
+       } else if (!$_REQUEST['search_term'] && ($_REQUEST['v'] == $variables[2])){
+               display_all_terms($_REQUEST['v'], $_REQUEST['k'], $_REQUEST['f'], $_REQUEST['n'], $_REQUEST['u']);
+       } else if ($_REQUEST['search_term']) {
+               display_search_terms($_REQUEST['v'], $_REQUEST['k'], $_REQUEST['f'], $_REQUEST['n'], $_REQUEST['u']);
+       }
+
+
+function delete_term($variable, $term) {
+       global $db;
+
+       $sql = "DELETE FROM ".TABLE_PREFIX."language_text WHERE variable='$variable' AND term='$term'";
+       $result = mysql_query($sql, $db);
+
+       $sql3 = "DELETE FROM ".TABLE_PREFIX."language_pages WHERE term='$term'";
+       $result3 = mysql_query($sql3, $db);
+
+       unset($_REQUEST['k']);
+       echo '<div class="feedback2"">Success: deleted.</div>';
+}
+
+function update_term($text, $context, $variable, $term) {
+       global $addslashes, $db;
+       
+       $term    = $addslashes(trim($term));
+       $text    = $addslashes(trim($text));
+       $context = $addslashes(trim($context));
+
+       if ($_SESSION['language'] == 'en') {
+               $sql    = "UPDATE ".TABLE_PREFIX."language_text SET `text`='$text', revised_date=NOW(), context='$context' WHERE variable='$variable' AND term='$term' AND language_code='en'";
+       }
+       
+       else {
+               $sql    = "REPLACE INTO ".TABLE_PREFIX."language_text VALUES ('$_SESSION[language]', '$variable', '$term', '$text', NOW(), '')";
+
+               $trans = get_html_translation_table(HTML_ENTITIES);
+               $trans = array_flip($trans);
+               $sql = strtr($sql, $trans);
+       }
+
+       $result = mysql_query($sql, $db);
+       
+       if (!$result) {
+               echo mysql_error($db);
+               echo '<div class="error">Error: changes not saved!</div>';
+               $success_error = '<div class="error">Error: changes not saved!</div>';
+               return $success_error;
+       }
+       else {
+               echo '<div class="feedback2"">Success: changes saved.</div>';
+               $success_error = '<div class="feedback2"">Success: changes saved.</div>';
+               return $success_error;
+       }
+}
+
+function add_term($text, $context, $variable, $term) {
+       global $addslashes, $db;
+
+       $term    = $addslashes(trim($term));
+       $text    = $addslashes(trim($text));
+       $context = $addslashes(trim($context));
+
+       $sql    = "INSERT INTO ".TABLE_PREFIX."language_text VALUES ('en', '$variable', '$term', '$text', NOW(), '$context')";
+       $result = mysql_query($sql, $db);
+
+       if (!$result) {
+               echo '<div class="error">Error: that term already exists!</div>';
+               $success_error = '';            
+       } else {
+               echo '<div class="feedback2"">Success: term added.</div>';
+               $success_error = '<div class="feedback2"">Success: term added.</div>';
+               return $success_error;
+       }
+}
+
+function display_page_terms ($variable, $term1, $lang_code, $new, $updated, $page) {
+       global $db;
+       
+       echo '<li><a name="anchor1"></a>';
+       echo '<a href="'.$_SERVER['PHP_SELF'].'?v='.$variable.SEP.'page='.urlencode($page).SEP.'f='.$lang_code.SEP.'n='.$new.SEP.'u='.updated.'#anchor">'.$page.'</a>';
+                       
+       $sql1 = "SELECT term FROM ".TABLE_PREFIX."language_pages WHERE page='$page' ORDER BY term";
+       $result1 = mysql_query($sql1, $db);
+
+       $term_list = array();
+
+       while ($row1 = mysql_fetch_assoc($result1)) {
+       
+               if ($_SESSION['language'] != 'en') {
+                       $sql    = "SELECT term, revised_date+0  AS r_date FROM ".TABLE_PREFIX."language_text WHERE variable='$variable' AND `language_code`='$_SESSION[language]' AND term='$row1[term]' ORDER BY `term`";
+                       $result = mysql_query($sql, $db);
+                                                               
+                       while ($row = mysql_fetch_assoc($result)) {
+                               $t_keys[$row['term']] = $row['r_date'];
+                       }
+               }
+               $term_list[] = $row1['term'];
+       }
+
+       echo '<ul>';
+       
+       foreach ($term_list as $term) {
+
+               if ($_REQUEST['f'] == 'en') {
+                       $sql    = "SELECT *, revised_date+0 AS r_date FROM ".TABLE_PREFIX."language_text WHERE variable='$_REQUEST[v]' AND language_code='en' AND term='$term'";
+               } else {
+                       $sql    = "SELECT * FROM ".TABLE_PREFIX."language_text WHERE variable='$_REQUEST[v]' AND language_code='$_REQUEST[f]' AND term='$term'";
+               }
+                               
+               $result = mysql_query($sql, $db);
+               $row = mysql_fetch_assoc($result);
+
+               if ($_SESSION['language'] != 'en') {
+                       if ($new && $updated) {
+                               if ((!($t_keys[$row['term']] == '')) && (!(($t_keys[$row['term']] < $row['r_date']) && $t_keys[$row['term']]))) {
+                                       continue;
+                               }
+                       } else if ($new) {
+                               if (!($t_keys[$row['term']] == '')) {   
+                                       continue;
+                               }
+                       } else if ($updated) {
+                               if (!(($t_keys[$row['term']] < $row['r_date']) && $t_keys[$row['term']])) {
+                                       continue;
+                               }
+                       }
+               }
+
+               if ($term == $term1) {
+                       trans_form($page);
+                       echo '<li class="selected">';
+               } else {
+                       echo '<li>';
+               }
+               echo '<small>';
+
+               if ($_SESSION['language'] != 'en') {
+                       if ($t_keys[$row['term']] == '') {
+                               echo '<b>*New*</b> ';
+                       } else if ($t_keys[$term] < $row['r_date']) {
+                               echo '<b>*Updated*</b> ';
+                       }
+               }
+
+               if ($term != $term1) {
+                       echo '<a href="'.$_SERVER['PHP_SELF'].'?v='.$variable.SEP.'k='.$term.SEP.'f='.$lang_code.SEP.'n='.$new.SEP.'u='.$updated.SEP.'page='.urlencode($page).'#anchor">';
+                       echo $term;
+                       echo '</a>';
+               } else {
+                       echo $term;
+               }
+               echo '</small>';
+               echo '</li>';
+       }
+       echo '</ul>';
+       echo '</li>';
+}
+
+function display_all_terms ($variable, $term1, $lang_code, $new, $updated) {
+       global $db;
+
+       if ($_SESSION['language'] != 'en') {
+               $sql    = "SELECT term, revised_date+0  AS r_date FROM ".TABLE_PREFIX."language_text WHERE variable='$variable' AND `language_code`='$_SESSION[language]' ORDER BY `term`";
+               $result = mysql_query($sql, $db);
+
+               $t_keys = array();
+               while ($row = mysql_fetch_assoc($result)) {
+                       $t_keys[$row['term']] = $row['r_date'];
+               }
+       }
+
+       if ($lang_code == 'en') {
+               $sql    = "SELECT *, revised_date+0 AS r_date FROM ".TABLE_PREFIX."language_text WHERE variable='$variable' AND language_code='en' ORDER BY term";
+       } else {
+               $sql    = "SELECT * FROM ".TABLE_PREFIX."language_text WHERE variable='$variable' AND language_code='$lang_code' ORDER BY term";
+       }
+       $result = mysql_query($sql, $db);
+
+       echo '<ul>';
+       while ($row = mysql_fetch_assoc($result)) {
+               if ($_SESSION['language'] != 'en') {
+                       if ($new && $updated) {
+                               if ((!($t_keys[$row['term']] == '')) && (!(($t_keys[$row['term']] < $row['r_date']) && $t_keys[$row['term']]))) {
+                                       continue;
+                               }
+                       } else if ($new) {
+                               if (!($t_keys[$row['term']] == '')) {   
+                                       continue;
+                               }
+                       } else if ($updated) {
+                               if (!(($t_keys[$row['term']] < $row['r_date']) && $t_keys[$row['term']])) {
+                                       continue;
+                               }
+                       }
+               }
+
+
+               if ($row['term'] == $term1) {
+                       trans_form('all');
+                       echo '<li class="selected">';
+
+               } else {
+                       echo '<li>';
+               }
+               echo '<small>';
+               if ($_SESSION['language'] != 'en') {
+                       if ($t_keys[$row['term']] == '') {
+                               echo '<b>*New*</b> ';
+                       } else if ($t_keys[$row['term']] < $row['r_date']) {
+                               echo '<b>*Updated*</b> ';
+                       }
+               }
+
+               if ($row['term'] != $term1) {
+                       echo '<a href="'.$_SERVER['PHP_SELF'].'?v='.$variable.SEP.'k='.$row['term'].SEP.'page=all'.SEP.'f='.$lang_code.SEP.'n='.$new.SEP.'u='.$updated.'#anchor">';
+                       echo $row['term'];
+                       echo '</a>';
+               } else {
+                       echo $row['term'];
+               }
+               echo '</small>';
+               echo '</li>';
+       }
+       echo '</ul>';
+}
+
+function display_unused_terms ($variable, $term1, $lang_code, $new, $updated) {
+       global $db;
+
+       if ($_SESSION['language'] != 'en') {
+               $sql    = "SELECT term, revised_date+0  AS r_date FROM ".TABLE_PREFIX."language_text WHERE variable='$variable' AND `language_code`='$_SESSION[language]' ORDER BY `term`";
+               $result = mysql_query($sql, $db);
+
+               $t_keys = array();
+               while ($row = mysql_fetch_assoc($result)) {
+                       $t_keys[$row['term']] = $row['r_date'];
+               }
+       }
+
+       if ($lang_code == 'en') {
+               $sql    = "SELECT lt.*, lt.revised_date+0 AS r_date FROM ".TABLE_PREFIX."language_text lt LEFT JOIN ".TABLE_PREFIX."language_pages lp ON lt.term = lp.term WHERE lp.term IS NULL AND lt.variable='$variable' AND lt.language_code='en' ORDER BY lt.term";
+       } else {
+               $sql    = "SELECT lt.* FROM ".TABLE_PREFIX."language_text lt LEFT JOIN ".TABLE_PREFIX."language_pages lp ON lt.term = NULL WHERE lt.variable='$variable' AND lt.language_code='$lang_code' ORDER BY lt.term";
+       }
+       $result = mysql_query($sql, $db);
+
+       echo '<ul>';
+       while ($row = mysql_fetch_assoc($result)) {
+               if ($_SESSION['language'] != 'en') {
+                       if ($new && $updated) {
+                               if ((!($t_keys[$row['term']] == '')) && (!(($t_keys[$row['term']] < $row['r_date']) && $t_keys[$row['term']]))) {
+                                       continue;
+                               }
+                       } else if ($new) {
+                               if (!($t_keys[$row['term']] == '')) {   
+                                       continue;
+                               }
+                       } else if ($updated) {
+                               if (!(($t_keys[$row['term']] < $row['r_date']) && $t_keys[$row['term']])) {
+                                       continue;
+                               }
+                       }
+               }
+
+
+               if ($row['term'] == $term1) {
+                       trans_form('none');
+                       echo '<li class="selected">';
+
+               } else {
+                       echo '<li>';
+               }
+               echo '<small>';
+               if ($_SESSION['language'] != 'en') {
+                       if ($t_keys[$row['term']] == '') {
+                               echo '<b>*New*</b> ';
+                       } else if ($t_keys[$row['term']] < $row['r_date']) {
+                               echo '<b>*Updated*</b> ';
+                       }
+               }
+
+               if ($row['term'] != $term1) {
+                       echo '<a href="'.$_SERVER['PHP_SELF'].'?v='.$variable.SEP.'k='.urlencode($row['term']).SEP.'page=none'.SEP.'f='.$lang_code.SEP.'n='.$new.SEP.'u='.$updated.'#anchor">';
+                       echo $row['term'];
+                       echo '</a>';
+               } else {
+                       echo $row['term'];
+               }
+               echo '</small>';
+               echo '</li>';
+       }
+       echo '</ul>';
+}
+
+
+function display_search_terms ($variable, $term1, $lang_code, $new, $updated) {
+       global $db, $addslashes, $stripslashes;
+
+       $_REQUEST['search_term'] = $addslashes($_REQUEST['search_term']);
+
+       $sql    = "SELECT term, revised_date+0  AS r_date FROM ".TABLE_PREFIX."language_text WHERE (term LIKE '%$_REQUEST[search_term]%' OR CAST(`text` AS CHAR) LIKE '%$_REQUEST[search_term]%') AND (`language_code`='$_SESSION[language]' OR `language_code`='en') GROUP BY `term` ORDER BY `term`";
+       $result = mysql_query($sql, $db);
+
+       $t_keys = array();
+       while ($row = mysql_fetch_assoc($result)) {
+               $t_keys[$row['term']] = $row['r_date'];
+       }
+
+       $sql    = "SELECT *, revised_date+0 AS r_date FROM ".TABLE_PREFIX."language_text WHERE (term LIKE '%$_REQUEST[search_term]%' OR CAST(`text` AS CHAR) LIKE '%$_REQUEST[search_term]%') AND (language_code='en' OR language_code='$_SESSION[language]') GROUP BY `term` ORDER BY term";
+       $result = mysql_query($sql, $db);
+
+       if (mysql_num_rows($result) == 0) {
+               echo '<ul><li>No results found.</li></ul>';
+       } else {
+               echo '<ul>';
+               while ($row = mysql_fetch_assoc($result)) {
+                       if ($_SESSION['language'] != 'en') {
+                               if ($new && $updated) {
+                                       if ((!($t_keys[$row['term']] == '')) && (!(($t_keys[$row['term']] < $row['r_date']) && $t_keys[$row['term']]))) {
+                                               continue;
+                                       }
+                               } else if ($new) {
+                                       if (!($t_keys[$row['term']] == '')) {   
+                                               continue;
+                                       }
+                               } else if ($updated) {
+                                       if (!(($t_keys[$row['term']] < $row['r_date']) && $t_keys[$row['term']])) {
+                                               continue;
+                                       }
+                               }
+                       }
+
+
+                       if ($row['term'] == $term1) {
+                               trans_form('search');
+                               echo '<li class="selected">';
+
+                       } else {
+                               echo '<li>';
+                       }
+                       echo '<small>';
+                       if ($_SESSION['language'] != 'en') {
+                               if ($t_keys[$row['term']] == '') {
+                                       echo '<b>*New*</b> ';
+                               } else if ($t_keys[$row['term']] < $row['r_date']) {
+                                       echo '<b>*Updated*</b> ';
+                               }
+                       }
+
+                       if ($row['term'] != $term1) {
+                               echo '<a href="'.$_SERVER['PHP_SELF'].'?v='.$row['variable'].SEP.'search=1'.SEP.'search_term='.urlencode($stripslashes($_REQUEST['search_term'])).SEP.'k='.$row['term'].SEP.'f='.$lang_code.SEP.'n='.$new.SEP.'u='.$updated.'#anchor">';
+                               echo $row['term'];
+                               echo '</a>';
+                       } else {
+                               echo $row['term'];
+                       }
+                       echo '</small>';
+                       echo '</li>';
+               }
+               echo '</ul>';
+       }
+}
+?>
\ No newline at end of file
diff --git a/admin/user_enrollment.php b/admin/user_enrollment.php
new file mode 100644 (file)
index 0000000..60b30fe
--- /dev/null
@@ -0,0 +1,210 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+$_user_location = 'admin';
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_ENROLLMENT);
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'admin/users.php');
+       exit;
+} else if (isset($_POST['enrolled_unenroll'])) {
+       $_POST['id'] = intval($_POST['id']);
+
+       if (!is_array($_POST['enrolled'])) {
+               $msg->addError('NO_ITEM_SELECTED');
+       } else {
+               $cids = implode(',', $_POST['enrolled']);
+               $sql = "DELETE FROM ".TABLE_PREFIX."course_enrollment WHERE member_id={$_POST['id']} AND course_id IN ($cids)";
+               mysql_query($sql, $db);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: '.$_SERVER['PHP_SELF'] . '?id='.$_POST['id']);
+               exit;
+       }
+} else if (isset($_POST['pending_remove'])) {
+       $_POST['id'] = intval($_POST['id']);
+
+       if (!is_array($_POST['pending'])) {
+               $msg->addError('NO_ITEM_SELECTED');
+       } else {
+               $cids = implode(',', $_POST['pending']);
+               $sql = "DELETE FROM ".TABLE_PREFIX."course_enrollment WHERE member_id={$_POST['id']} AND course_id IN ($cids)";
+               mysql_query($sql, $db);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: '.$_SERVER['PHP_SELF'] . '?id='.$_POST['id']);
+               exit;
+       }
+} else if (isset($_POST['pending_enroll'])) {
+       $_POST['id'] = intval($_POST['id']);
+
+       if (!is_array($_POST['pending'])) {
+               $msg->addError('NO_ITEM_SELECTED');
+       } else {
+               $cids = implode(',', $_POST['pending']);
+               $sql = "UPDATE ".TABLE_PREFIX."course_enrollment SET approved='y' WHERE member_id={$_POST['id']} AND course_id IN ($cids)";
+               mysql_query($sql, $db);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: '.$_SERVER['PHP_SELF'] . '?id='.$_POST['id']);
+               exit;
+       }
+} else if (isset($_POST['not_enrolled_enroll'])) {
+       $_POST['id'] = intval($_POST['id']);
+
+       if (!is_array($_POST['not_enrolled'])) {
+               $msg->addError('NO_ITEM_SELECTED');
+       } else {
+               foreach ($_POST['not_enrolled'] as $cid) {
+                       $sql = "INSERT INTO ".TABLE_PREFIX."course_enrollment VALUES ({$_POST['id']}, $cid, 'y', 0, '', 0)";
+                       mysql_query($sql, $db);
+               }
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: '.$_SERVER['PHP_SELF'] . '?id='.$_POST['id']);
+               exit;
+       }
+}
+
+$id = intval($_GET['id']);
+
+// add the user's name to the page heading:
+$_pages['admin/user_enrollment.php']['title'] = _AT('enrollment').': '.get_display_name($id);
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$sql   = "SELECT login FROM ".TABLE_PREFIX."members WHERE member_id=$id";
+$result = mysql_query($sql, $db);
+
+if (!$row = mysql_fetch_assoc($result)) {
+       $msg->printErrors('USER_NOT_FOUND');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+$enrollment = array();
+$sql = "SELECT * FROM ".TABLE_PREFIX."course_enrollment WHERE member_id=$id";
+$result = mysql_query($sql, $db);
+while ($row = mysql_fetch_assoc($result)) {
+       $enrollment[$row['course_id']] = $row;
+}
+
+$instruct     = array();
+$enrolled     = array();
+$pending      = array();
+$not_enrolled = array();
+
+foreach ($system_courses as $cid => $course) {
+       if ($course['member_id'] == $id) {
+               $instruct[] = $cid;
+       } else if (isset($enrollment[$cid]) && $enrollment[$cid]['approved'] == 'y') {
+               $enrolled[] = $cid;
+       } else if (isset($enrollment[$cid]) && $enrollment[$cid]['approved'] == 'n') {
+               $pending[] = $cid;
+       } else {
+               $not_enrolled[] = $cid;
+       }
+}
+
+?>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>?id=<?php echo $id; ?>">
+<input type="hidden" name="id" value="<?php echo $id; ?>"/>
+<div class="input-form" style="min-width: 400px; width: 45%; float: left; margin: 5px">
+       <div class="row">
+       <h3><?php echo _AT('instructor'); ?></h3>
+               <?php if ($instruct): ?>
+                       <ul>
+                       <?php foreach ($instruct as $cid): ?>
+                               <li><?php echo $system_courses[$cid]['title']; ?></li>
+                       <?php endforeach; ?>
+                       </ul>
+               <?php else: ?>
+                       <?php echo _AT('none'); ?>
+               <?php endif; ?>
+       </div>
+       <div class="row buttons">
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>"/>
+       </div>
+</div>
+
+<div class="input-form" style="min-width: 400px; width: 45%; float: left; margin: 5px">
+       <div class="row">
+       <h3><?php echo _AT('enrolled'); ?></h3>
+               <?php if ($enrolled): ?>
+                       <ul>
+                       <?php foreach ($enrolled as $cid): ?>
+                               <li><input type="checkbox" name="enrolled[]" value="<?php echo $cid; ?>" id="c<?php echo $cid; ?>"/><label for="c<?php echo $cid; ?>"><?php echo $system_courses[$cid]['title']; ?></label></li>
+                       <?php endforeach; ?>
+                       </ul>
+               <?php else: ?>
+                       <?php echo _AT('none'); ?>
+               <?php endif; ?>
+       </div>
+       <div class="row buttons">
+       <?php if ($enrolled): ?>
+               <input type="submit" name="enrolled_unenroll" value="<?php echo _AT('unenroll'); ?>"/>
+       <?php endif; ?>
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>"/>
+       </div>
+
+</div>
+
+<div class="input-form" style="min-width: 400px; width: 45%; float: left; margin: 5px">
+       <div class="row">
+       <h3><?php echo _AT('pending_enrollment'); ?></h3>
+               <?php if ($pending): ?>
+                       <ul>
+                       <?php foreach ($pending as $cid): ?>
+                               <li><input type="checkbox" name="pending[]" value="<?php echo $cid; ?>" id="c<?php echo $cid; ?>"/><label for="c<?php echo $cid; ?>"><?php echo $system_courses[$cid]['title']; ?></label></li>
+                       <?php endforeach; ?>
+                       </ul>
+               <?php else: ?>
+                       <?php echo _AT('none'); ?>
+               <?php endif; ?>
+       </div>
+       <div class="row buttons">
+       <?php if ($pending): ?>
+               <input type="submit" name="pending_remove" value="<?php echo _AT('remove'); ?>"/>
+               <input type="submit" name="pending_enroll" value="<?php echo _AT('enroll'); ?>"/>
+       <?php endif; ?>
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>"/>
+       </div>  
+</div>
+
+<div class="input-form" style="min-width: 400px; width: 45%; float: left; margin: 5px">
+       <div class="row">
+               <h3><?php echo _AT('not_enrolled');?></h3>
+                       <?php if ($not_enrolled): ?>
+                               <ul>
+                               <?php foreach ($not_enrolled as $cid): ?>
+                                       <li><input type="checkbox" name="not_enrolled[]" value="<?php echo $cid; ?>" id="c<?php echo $cid; ?>"/><label for="c<?php echo $cid; ?>"><?php echo $system_courses[$cid]['title']; ?></label></li>
+                               <?php endforeach; ?>
+                               </ul>
+                       <?php else: ?>
+                               <?php echo _AT('none'); ?>
+                       <?php endif; ?>
+       </div>
+       <div class="row buttons">
+       <?php if ($not_enrolled): ?>
+               <input type="submit" name="not_enrolled_enroll" value="<?php echo _AT('enroll'); ?>"/>
+       <?php endif; ?>
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>"/>
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/admin/user_status.php b/admin/user_status.php
new file mode 100644 (file)
index 0000000..d3c56c9
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+/* linked from admin/users.php                                  */
+/* deletes a user from the system.                              */
+/****************************************************************/
+// $Id: admin_delete.php 6644 2006-11-01 17:24:25Z joel $
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_USERS);
+
+$ids = explode(',', $_REQUEST['ids']);
+$status = intval($_REQUEST['status']);
+
+if (isset($_POST['submit_yes'])) {
+
+       foreach ($ids as $id) {
+               //make sure not instructor of a course
+               $id = intval($id);
+               $sql    = "SELECT course_id FROM ".TABLE_PREFIX."courses WHERE member_id=$id";
+               $result = mysql_query($sql, $db);
+               if (!mysql_fetch_assoc($result)) {
+                       $sql2 = "UPDATE ".TABLE_PREFIX."members SET status=".$status." WHERE member_id=$id";
+                       $result2 = mysql_query($sql2,$db);
+               }
+       }
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: '.AT_BASE_HREF.'admin/users.php');
+       exit;
+
+} else if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'admin/users.php');
+       exit;
+}
+
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+$names = get_login($ids);
+$names_html = '<ul>'.html_get_list($names).'</ul>';
+$status_name = get_status_name($status);
+
+$hidden_vars['ids'] = implode(',', array_keys($names));
+$hidden_vars['status'] = $status;
+
+$confirm = array('EDIT_STATUS', $status_name, $names_html);
+$msg->addConfirm($confirm, $hidden_vars);
+$msg->printConfirm();
+
+require(AT_INCLUDE_PATH.'footer.inc.php'); 
+?>
\ No newline at end of file
diff --git a/admin/users.php b/admin/users.php
new file mode 100644 (file)
index 0000000..e92bfa8
--- /dev/null
@@ -0,0 +1,407 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+admin_authenticate(AT_ADMIN_PRIV_USERS);
+
+if ( (isset($_GET['edit']) || isset($_GET['password']) || isset($_GET['enrollment'])) && (isset($_GET['id']) && count($_GET['id']) > 1) ) {
+       $msg->addError('SELECT_ONE_ITEM');
+} else if (isset($_GET['edit'], $_GET['id'])) {
+       header('Location: edit_user.php?id='.$_GET['id'][0]);
+       exit;
+} else if (isset($_GET['password'], $_GET['id'])) {
+       header('Location: password_user.php?id='.$_GET['id'][0]);
+       exit;
+} else if (isset($_GET['enrollment'], $_GET['id'])) {
+       header('Location: user_enrollment.php?id='.$_GET['id'][0]);
+       exit;
+} else if ( isset($_GET['apply']) && isset($_GET['id']) && $_GET['change_status'] >= -1) {
+       $ids = implode(',', $_GET['id']);
+       $status = intval($_GET['change_status']);
+       if ($status == -1) {
+               header('Location: admin_delete.php?id='.$ids);
+               exit;
+       } else {
+               header('Location: user_status.php?ids='.$ids.'&status='.$status);
+               exit;
+       }
+} else if ( (isset($_GET['apply']) || isset($_GET['apply_all'])) && $_GET['change_status'] < -1) {
+       $msg->addError('NO_ACTION_SELECTED');
+} else if (isset($_GET['apply']) || isset($_GET['edit']) || isset($_GET['delete']) || isset($_GET['password'])) {
+       $msg->addError('NO_ITEM_SELECTED');
+}
+
+if ($_GET['reset_filter']) {
+       unset($_GET);
+}
+
+$page_string = '';
+$orders = array('asc' => 'desc', 'desc' => 'asc');
+$cols   = array('login' => 1, 'public_field' => 1, 'first_name' => 1, 'second_name' => 1, 'last_name' => 1, 'email' => 1, 'status' => 1, 'last_login' => 1);
+
+if (isset($_GET['asc'])) {
+       $order = 'asc';
+       $col   = isset($cols[$_GET['asc']]) ? $_GET['asc'] : 'login';
+} else if (isset($_GET['desc'])) {
+       $order = 'desc';
+       $col   = isset($cols[$_GET['desc']]) ? $_GET['desc'] : 'login';
+} else {
+       // no order set
+       $order = 'asc';
+       $col   = 'login';
+}
+if (isset($_GET['status']) && ($_GET['status'] != '')) {
+       $_GET['status'] = intval($_GET['status']);
+       $status = '=' . intval($_GET['status']);
+       $page_string .= SEP.'status'.$status;
+} else {
+       $status = '<>-1';
+       $_GET['status'] = '';
+}
+
+if (isset($_GET['last_login_days'], $_GET['last_login_have']) && ($_GET['last_login_have'] >= 0) && $_GET['last_login_days']) {
+       $have = intval($_GET['last_login_have']);
+       $days = intval($_GET['last_login_days']);
+       $page_string .= SEP.'last_login_have='.$have;
+       $page_string .= SEP.'last_login_days='.$days;
+
+       if ($have) {
+               $ll =  " >= TO_DAYS(NOW())-$days)";
+       } else {
+               $ll =  " < TO_DAYS(NOW())-$days OR last_login+0=0)";
+       }
+       $last_login_days = '(TO_DAYS(last_login)'.$ll;
+} else {
+       $last_login_days = '1';
+}
+
+if (isset($_GET['include']) && $_GET['include'] == 'one') {
+       $checked_include_one = ' checked="checked"';
+       $page_string .= SEP.'include=one';
+} else {
+       $_GET['include'] = 'all';
+       $checked_include_all = ' checked="checked"';
+       $page_string .= SEP.'include=all';
+}
+
+if ($_GET['search']) {
+       $page_string .= SEP.'search='.urlencode($stripslashes($_GET['search']));
+       $search = $addslashes($_GET['search']);
+       $search = explode(' ', $search);
+
+       if ($_GET['include'] == 'all') {
+               $predicate = 'AND ';
+       } else {
+               $predicate = 'OR ';
+       }
+
+       $sql = '';
+       foreach ($search as $term) {
+               $term = trim($term);
+               $term = str_replace(array('%','_'), array('\%', '\_'), $term);
+               if ($term) {
+                       $term = '%'.$term.'%';
+                       $sql .= "((M.first_name LIKE '$term') OR (M.second_name LIKE '$term') OR (M.last_name LIKE '$term') OR (M.email LIKE '$term') OR (M.login LIKE '$term')) $predicate";
+               }
+       }
+       $sql = '('.substr($sql, 0, -strlen($predicate)).')';
+       $search = $sql;
+} else {
+       $search = '1';
+}
+
+if ($_GET['searchid']) {
+       $_GET['searchid'] = trim($_GET['searchid']);
+       $page_string .= SEP.'searchid='.urlencode($_GET['searchid']);
+       $searchid = $addslashes($_GET['searchid']);
+
+       $searchid = explode(',', $searchid);
+
+       $sql = '';
+       foreach ($searchid as $term) {
+               $term = trim($term);
+               $term = str_replace(array('%','_'), array('\%', '\_'), $term);
+               if ($term) {
+                       if (strpos($term, '-') === FALSE) {
+                               $term = '%'.$term.'%';
+                               $sql .= "(L.public_field LIKE '$term') OR ";
+                       } else {
+                               // range search
+                               $range = explode('-', $term, 2);
+                               $range[0] = trim($range[0]);
+                               $range[1] = trim($range[1]);
+                               if (is_numeric($range[0]) && is_numeric($range[1])) {
+                                       $sql .= "(L.public_field >= $range[0] AND L.public_field <= $range[1]) OR ";
+                               } else {
+                                       $sql .= "(L.public_field >= '$range[0]' AND L.public_field <= '$range[1]') OR ";
+                               }
+                       }
+               }
+       }
+       $sql = '('.substr($sql, 0, -3).')';
+       $searchid = $sql;
+} else {
+       $searchid = '1';
+}
+
+if (defined('AT_MASTER_LIST') && AT_MASTER_LIST) {
+       $sql    = "SELECT COUNT(M.member_id) AS cnt FROM ".TABLE_PREFIX."members M LEFT JOIN ".TABLE_PREFIX."master_list L USING (member_id) WHERE M.status $status AND $search AND $searchid AND $last_login_days";
+} else {
+       $sql    = "SELECT COUNT(member_id) AS cnt FROM ".TABLE_PREFIX."members M WHERE status $status AND $search AND $last_login_days";
+}
+$result = mysql_query($sql, $db);
+$row = mysql_fetch_assoc($result);
+$num_results = $row['cnt'];
+
+$results_per_page = 50;
+$num_pages = max(ceil($num_results / $results_per_page), 1);
+$page = intval($_GET['p']);
+if (!$page) {
+       $page = 1;
+}      
+$count  = (($page-1) * $results_per_page) + 1;
+$offset = ($page-1)*$results_per_page;
+
+if ( isset($_GET['apply_all']) && $_GET['change_status'] >= -1) {
+       $offset = 0;
+       $results_per_page = 999999;
+}
+
+if (defined('AT_MASTER_LIST') && AT_MASTER_LIST) {
+       $sql    = "SELECT M.member_id, M.login, M.first_name, M.second_name, M.last_name, M.email, M.status, M.last_login+0 AS last_login, L.public_field FROM ".TABLE_PREFIX."members M LEFT JOIN ".TABLE_PREFIX."master_list L USING (member_id) WHERE M.status $status AND $search AND $searchid AND $last_login_days ORDER BY $col $order LIMIT $offset, $results_per_page";
+} else {
+       $sql    = "SELECT M.member_id, M.login, M.first_name, M.second_name, M.last_name, M.email, M.status, M.last_login+0 AS last_login FROM ".TABLE_PREFIX."members M WHERE M.status $status AND $search AND $last_login_days ORDER BY $col $order LIMIT $offset, $results_per_page";
+}
+
+$result = mysql_query($sql, $db);
+
+if ( isset($_GET['apply_all']) && $_GET['change_status'] >= -1) {
+       $ids = '';
+       while ($row = mysql_fetch_assoc($result)) {
+               $ids .= $row['member_id'].','; 
+       }
+       $ids = substr($ids,0,-1);
+       $status = intval($_GET['change_status']);
+
+       if ($status==-1) {
+               header('Location: admin_delete.php?id='.$ids);
+               exit;
+       } else {
+               header('Location: user_status.php?ids='.$ids.'&status='.$status);
+               exit;
+       }
+}
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+       <div class="input-form">
+               <div class="row">
+                       <h3><?php echo _AT('results_found', $num_results); ?></h3>
+               </div>
+
+               <div class="row">
+                       <?php echo _AT('account_status'); ?><br />
+                       <input type="radio" name="status" value="0" id="s0" <?php if ($_GET['status'] == 0) { echo 'checked="checked"'; } ?> /><label for="s0"><?php echo _AT('disabled'); ?></label> 
+
+                       <input type="radio" name="status" value="1" id="s1" <?php if ($_GET['status'] == 1) { echo 'checked="checked"'; } ?> /><label for="s1"><?php echo _AT('unconfirmed'); ?></label> 
+
+                       <input type="radio" name="status" value="2" id="s2" <?php if ($_GET['status'] == 2) { echo 'checked="checked"'; } ?> /><label for="s2"><?php echo _AT('student'); ?></label>
+
+                       <input type="radio" name="status" value="3" id="s3" <?php if ($_GET['status'] == 3) { echo 'checked="checked"'; } ?> /><label for="s3"><?php echo _AT('instructor'); ?></label>
+
+                       <input type="radio" name="status" value="" id="s" <?php if ($_GET['status'] === '') { echo 'checked="checked"'; } ?> /><label for="s"><?php echo _AT('all'); ?></label>
+               </div>
+
+               <div class="row">
+                       <label for="search"><?php echo _AT('search'); ?> (<?php echo _AT('login_name').', '._AT('first_name').', '._AT('second_name').', '._AT('last_name') .', '._AT('email'); ?>)</label><br />
+
+                       <input type="text" name="search" id="search" size="40" value="<?php echo htmlspecialchars($_GET['search']); ?>" />
+                       <br/>
+                       <?php echo _AT('search_match'); ?>:
+                       <input type="radio" name="include" value="all" id="match_all" <?php echo $checked_include_all; ?> /><label for="match_all"><?php echo _AT('search_all_words'); ?></label> 
+                       <input type="radio" name="include" value="one" id="match_one" <?php echo $checked_include_one; ?> /><label for="match_one"><?php echo _AT('search_any_word'); ?></label>
+               </div>
+
+               <?php if (defined('AT_MASTER_LIST') && AT_MASTER_LIST): ?>
+                       <div class="row">
+                               <label for="searchid"><?php echo _AT('search'); ?> (<?php echo _AT('student_id'); ?>)</label><br />
+                               <input type="text" name="searchid" id="searchid" size="20" value="<?php echo htmlspecialchars($_GET['searchid']); ?>" />
+                       </div>
+               <?php endif; ?>
+
+               <div class="row">
+                       <label for="last_login_have"><?php echo _AT('last_login'); ?></label><br />                                     
+                       <select name="last_login_have" id="last_login_have">
+                               <option value="-1">- <?php echo _AT('select'); ?> -</option>
+                               <option value="1" <?php if($_GET['last_login_have']=='1') { echo 'selected="selected"';}?>><?php echo _AT('have'); ?></option>
+                               <option value="0" <?php if(isset($_GET['last_login_have']) && $_GET['last_login_have']=='0') { echo 'selected="selected"';}?>><?php echo _AT('have_not'); ?></option>
+                       </select> <?php echo _AT('logged_in_within'); ?>: <input type="text" name="last_login_days" size="3" value="<?php echo htmlspecialchars($_GET['last_login_days']); ?>" /> <?php echo _AT('days'); ?> <br />
+                       
+               </div>
+
+               <div class="row buttons">
+                       <input type="submit" name="filter" value="<?php echo _AT('filter'); ?>" />
+                       <input type="submit" name="reset_filter" value="<?php echo _AT('reset_filter'); ?>" />
+               </div>
+       </div>
+</form>
+
+<?php print_paginator($page, $num_results, $page_string . SEP . $order .'='. $col, $results_per_page); ?>
+
+<form name="form" method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<input type="hidden" name="status" value="<?php echo $_GET['status']; ?>" />
+<input type="hidden" name="search" value="<?php echo htmlspecialchars($_GET['search']); ?>" />
+<input type="hidden" name="include" value="<?php echo htmlspecialchars($_GET['include']); ?>" />
+
+<?php if (defined('AT_MASTER_LIST') && AT_MASTER_LIST) {  $col_counts = 1; } else { $col_counts = 0; } ?>
+<table summary="" class="data" rules="rows">
+<colgroup>
+       <?php if ($col == 'login'): ?>
+               <col />
+               <col class="sort" />
+               <col span="<?php echo 5 + $col_counts; ?>" />
+       <?php elseif($col == 'public_field'): ?>
+               <col span="<?php echo 1 + $col_counts; ?>" />
+               <col class="sort" />
+               <col span="6" />
+       <?php elseif($col == 'first_name'): ?>
+               <col span="<?php echo 2 + $col_counts; ?>" />
+               <col class="sort" />
+               <col span="5" />
+       <?php elseif($col == 'second_name'): ?>
+               <col span="<?php echo 3 + $col_counts; ?>" />
+               <col class="sort" />
+               <col span="4" />
+       <?php elseif($col == 'last_name'): ?>
+               <col span="<?php echo 4 + $col_counts; ?>" />
+               <col class="sort" />
+               <col span="3" />
+       <?php elseif($col == 'email'): ?>
+               <col span="<?php echo 5 + $col_counts; ?>" />
+               <col class="sort" />
+               <col span="2" />
+       <?php elseif($col == 'status'): ?>
+               <col span="<?php echo 6 + $col_counts; ?>" />
+               <col class="sort" />
+               <col />
+       <?php elseif($col == 'last_login'): ?>
+               <col span="<?php echo 7 + $col_counts; ?>" />
+               <col class="sort" />
+       <?php endif; ?>
+</colgroup>
+<thead>
+<tr>
+       <th scope="col" align="left"><input type="checkbox" value="<?php echo _AT('select_all'); ?>" id="all" title="<?php echo _AT('select_all'); ?>" name="selectall" onclick="CheckAll();" /></th>
+
+       <th scope="col"><a href="admin/users.php?<?php echo $orders[$order]; ?>=login<?php echo $page_string; ?>"><?php echo _AT('login_name');      ?></a></th>
+       <?php if (defined('AT_MASTER_LIST') && AT_MASTER_LIST): ?>
+               <th scope="col"><a href="admin/users.php?<?php echo $orders[$order]; ?>=public_field<?php echo $page_string; ?>"><?php echo _AT('student_id'); ?></a></th>
+       <?php endif; ?>
+       <th scope="col"><a href="admin/users.php?<?php echo $orders[$order]; ?>=first_name<?php echo $page_string; ?>"><?php echo _AT('first_name'); ?></a></th>
+       <th scope="col"><a href="admin/users.php?<?php echo $orders[$order]; ?>=second_name<?php echo $page_string; ?>"><?php echo _AT('second_name'); ?></a></th>
+       <th scope="col"><a href="admin/users.php?<?php echo $orders[$order]; ?>=last_name<?php echo $page_string; ?>"><?php echo _AT('last_name');   ?></a></th>
+       <th scope="col"><a href="admin/users.php?<?php echo $orders[$order]; ?>=email<?php echo $page_string; ?>"><?php echo _AT('email');           ?></a></th>
+       <th scope="col"><a href="admin/users.php?<?php echo $orders[$order]; ?>=status<?php echo $page_string; ?>"><?php echo _AT('account_status'); ?></a></th>
+       <th scope="col"><a href="admin/users.php?<?php echo $orders[$order]; ?>=last_login<?php echo $page_string; ?>"><?php echo _AT('last_login'); ?></a></th>
+</tr>
+
+</thead>
+<?php if ($num_results > 0): ?>
+       <tfoot>
+       <tr>
+               <td colspan="<?php echo 8 + $col_counts; ?>">
+                       <input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> 
+                       <input type="submit" name="password" value="<?php echo _AT('password'); ?>" />
+                       <?php if (admin_authenticate(AT_ADMIN_PRIV_ENROLLMENT, true)): ?>
+                               <input type="submit" name="enrollment" value="<?php echo _AT('enrollment'); ?>" />
+                       <?php endif; ?>
+                       <span style="padding:0px 10px">|</span> 
+                       
+                       <select name="change_status">
+                               <option value="-2"><?php echo _AT('more_options'); ?></option>
+                               <optgroup label="<?php echo _AT('status'); ?>">
+                                       <option value="<?php echo AT_STATUS_STUDENT; ?>"><?php echo _AT('student'); ?></option>
+                                       <option value="<?php echo AT_STATUS_INSTRUCTOR; ?>"><?php echo _AT('instructor'); ?></option>   
+                                       <?php if ($_config['email_confirmation']): ?>
+                                               <option value="<?php echo AT_STATUS_UNCONFIRMED; ?>"><?php echo _AT('unconfirmed'); ?></option>
+                                       <?php endif; ?>
+                                       <option value="<?php echo AT_STATUS_DISABLED; ?>"><?php echo _AT('disable'); ?></option>                                
+                               </optgroup>
+                               <option value="-2" disabled="disabled">- - - - - - - - -</option>       
+                               <option value="-1"><?php echo _AT('delete'); ?></option>                                
+                       </select>
+                       <input type="submit" name="apply" value="<?php echo _AT('apply'); ?>" />
+                       <input type="submit" name="apply_all" value="<?php echo _AT('apply_to_all_results'); ?>" />
+               </td>
+       </tr>
+       </tfoot>
+       <tbody>
+               <?php while($row = mysql_fetch_assoc($result)): ?>
+                       <tr onmousedown="document.form['m<?php echo $row['member_id']; ?>'].checked = !document.form['m<?php echo $row['member_id']; ?>'].checked; togglerowhighlight(this, 'm<?php echo $row['member_id']; ?>');" id="rm<?php echo $row['member_id']; ?>">
+                               <td><input type="checkbox" name="id[]" value="<?php echo $row['member_id']; ?>" id="m<?php echo $row['member_id']; ?>" onmouseup="this.checked=!this.checked" /></td>
+                               <td><?php echo $row['login']; ?></td>
+                               <?php if (defined('AT_MASTER_LIST') && AT_MASTER_LIST): ?>
+                                       <td><?php echo $row['public_field']; ?></td>
+                               <?php endif; ?>
+
+                               <td><?php echo AT_print($row['first_name'], 'members.first_name'); ?></td>
+                               <td><?php echo AT_print($row['second_name'], 'members.second_name'); ?></td>
+                               <td><?php echo AT_print($row['last_name'], 'members.last_name'); ?></td>
+                               <td><?php echo AT_print($row['email'], 'members.email'); ?></td>
+                               <td><?php echo get_status_name($row['status']); ?></td>
+                               <td nowrap="nowrap">
+                                       <?php if ($row['last_login'] == 0): ?>
+                                               <?php echo _AT('never'); ?>
+                                       <?php else: ?>
+                                               <?php 
+                                               
+                                               $startend_date_longs_format=_AT('startend_date_longs_format');
+                                               //echo AT_date('%d/%m/%y - %H:%i', $row['last_login'], AT_DATE_MYSQL_TIMESTAMP_14);
+                                               echo AT_date($startend_date_longs_format, $row['last_login'], AT_DATE_MYSQL_TIMESTAMP_14); 
+                                       ?>
+                                       <?php endif; ?>
+                               </td>
+                       </tr>
+               <?php endwhile; ?>
+       </tbody>
+<?php else: ?>
+       <tr>
+               <td colspan="<?php echo 8 + $col_counts; ?>"><?php echo _AT('none_found'); ?></td>
+       </tr>
+<?php endif; ?>
+</table>
+</form>
+<script language="JavaScript" type="text/javascript">
+//<!--
+function CheckAll() {
+       for (var i=0;i<document.form.elements.length;i++)       {
+               var e = document.form.elements[i];
+               if ((e.name == 'id[]') && (e.type=='checkbox')) {
+                       e.checked = document.form.selectall.checked;
+                       togglerowhighlight(document.getElementById("r" + e.id), e.id);
+               }
+       }
+}
+
+function togglerowhighlight(obj, boxid) {
+       if (document.getElementById(boxid).checked) {
+               obj.className = 'selected';
+       } else {
+               obj.className = '';
+       }
+}
+//-->
+</script>
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/assignments/add_assignment.php b/assignments/add_assignment.php
new file mode 100644 (file)
index 0000000..67f267c
--- /dev/null
@@ -0,0 +1,375 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_ASSIGNMENTS);
+
+// initial values for controls
+$id = 0;
+$today = getdate();
+
+// Are we editing an existing assignment or creating a new assignment?
+if (isset ($_GET['id'])){
+       // editing an existing assignment
+       $id = intval($_GET['id']); 
+
+       $sql = "SELECT *, DATE_FORMAT(date_due, '%Y-%m-%d %H:%i:00') AS date_due, DATE_FORMAT(date_cutoff, '%Y-%m-%d %H:%i:00') AS date_cutoff FROM ".TABLE_PREFIX."assignments WHERE course_id=$_SESSION[course_id] AND assignment_id=$id";
+
+       $result = mysql_query($sql,$db);
+       if (!($row = mysql_fetch_assoc($result))) {
+               // should not happen
+               $msg->addFeedback('ASSIGNMENT_NOT_FOUND');
+               header('Location: index_instructor.php');
+               exit;
+       }
+
+       // get values of existing assignment from database
+       $title                  = $row['title'];
+       $assign_to              = $row['assign_to'];
+       $multi_submit   = $row['multi_submit'];
+
+       $array1                 = explode (' ', $row['date_due'], 2);
+       $array_date_due = explode ('-', $array1[0],3);
+       $array_time_due = explode (':', $array1[1]);
+       $dueyear                = $array_date_due[0];
+       $duemonth               = $array_date_due[1];
+       $dueday                 = $array_date_due[2];
+       $duehour                = $array_time_due[0];
+       $dueminute              = $array_time_due[1];
+
+       if ($dueyear == '0000'){
+               $has_due_date = 'false';
+       } else {
+               $has_due_date = 'true';
+       }
+
+       // use date from database
+       $array2 = explode (' ', $row['date_cutoff'], 2);
+       $array_date_cutoff = explode ('-', $array2[0],3);
+       $array_time_cutoff = explode (':', $array2[1]);
+       $cutoffyear             = $array_date_cutoff[0];
+       $cutoffmonth    = $array_date_cutoff[1];
+       $cutoffday              = $array_date_cutoff[2];
+       $cutoffhour             = $array_time_cutoff[0];
+       $cutoffminute   = $array_time_cutoff[1];
+
+       if ($cutoffyear == '0000'){
+               $late_submit    = '0'; // allow late submissions always
+       } else if ($row['date_cutoff'] == $row['date_due']){
+               $late_submit    = '1'; // allow late submissions never
+               // use today's date as default
+               $cutoffday              = $today['mday'];
+               $cutoffmonth    = $today['mon'];
+               $cutoffyear             = $today['year'];
+               $cutoffhour             = $today['hours'];
+               $cutoffminute   = $today['minutes'];
+               // round the minute to the next highest multiple of 5 
+               $cutoffminute = round($cutoffminute / '5' ) * '5' + '5';
+               if ($cutoffminute > '55'){ $cutoffminute = '55'; }
+       } else {
+               $late_submit    = '2'; // allow late submissions until (date)
+       }
+}
+else if (isset($_POST['cancel'])) {
+       // cancel, nothing happened
+       $msg->addFeedback('CANCELLED');
+       header('Location: index_instructor.php');
+       exit;
+}
+else if (isset($_POST['submit'])) {
+       // user has submitted form to update database
+       $id = intval ($_POST['id']);
+
+       if ($_POST['multi_submit'] == 'on'){
+               $multi_submit = '1';
+       }
+
+       // get values from form that was just submitted
+       $title                  = $addslashes($_POST['title']);
+       $assign_to              = intval($_POST['assign_to']);
+       $has_due_date   = $addslashes($_POST['has_due_date']);
+       $late_submit    = intval($_POST['late_submit']);
+
+       $dueday                 = intval($_POST['day_due']);
+       $duemonth               = intval($_POST['month_due']);
+       $dueyear                = intval($_POST['year_due']);
+       $duehour                = intval($_POST['hour_due']);
+       $dueminute              = intval($_POST['min_due']);
+
+       $cutoffday              = intval($_POST['day_cutoff']);
+       $cutoffmonth    = intval($_POST['month_cutoff']);
+       $cutoffyear             = intval($_POST['year_cutoff']);
+       $cutoffhour             = intval($_POST['hour_cutoff']);
+       $cutoffminute   = intval($_POST['min_cutoff']);
+
+       // ensure title is not empty
+       if (trim($title) == '') {
+               $msg->addError(array('EMPTY_FIELDS', _AT('title')));
+       } else {
+               //ensure the title does not exceed db length, 60
+               $title = validate_length($title, 60);
+       }
+
+       // If due date is set and user has selected 'accept late submission until'
+       // then ensure cutoff date is greater or equal to due date.
+       if (($has_due_date == 'true') && ($late_submit == '2')){
+               if ($cutoffyear < $dueyear){
+                       $msg->addError('CUTOFF_DATE_WRONG');
+               } else if ($cutoffyear == $dueyear){
+                       if ($cutoffmonth < $duemonth){
+                               $msg->addError('CUTOFF_DATE_WRONG');
+                       } else if ($cutoffmonth == $duemonth){
+                               if ($cutoffday < $dueday){
+                                       $msg->addError('CUTOFF_DATE_WRONG');
+                               } else if ($cutoffday == $dueday){
+                                       if ($cutoffhour < $duehour){
+                                               $msg->addError('CUTOFF_DATE_WRONG');
+                                       } else if ($cutoffhour == $duehour) {
+                                               if ($cutoffminute < $dueminute){
+                                                       $msg->addError('CUTOFF_DATE_WRONG');
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if (!$msg->containsErrors()) {
+               $multi_submit = 0;
+
+               // create the date strings
+               $date_due = '0';
+               $date_cutoff = '0';
+
+               // note: if due date is NOT set then ignore the late submission date
+               if ($has_due_date == 'true'){
+                       $date_due = $dueyear. '-' .str_pad ($duemonth, 2, "0", STR_PAD_LEFT). '-' .str_pad ($dueday, 2, "0", STR_PAD_LEFT). ' '.str_pad ($duehour, 2, "0", STR_PAD_LEFT). ':' .str_pad ($dueminute, 2, "0", STR_PAD_LEFT) . ':00';
+               }
+
+               if ($late_submit == '1'){ // never accept late submissions
+                       $date_cutoff = $date_due; // cutoff date will be same as due date
+               } else if ($late_submit == '2'){ // accept late submissions until date
+                       $date_cutoff = $cutoffyear. '-' .str_pad ($cutoffmonth, 2, "0", STR_PAD_LEFT). '-' .str_pad ($cutoffday, 2, "0", STR_PAD_LEFT). ' '.str_pad ($cutoffhour, 2, "0", STR_PAD_LEFT). ':' .str_pad ($cutoffminute, 2, "0", STR_PAD_LEFT) . ':00';
+               }
+
+               // Are we creating a new assignment or updating an existing assignment?
+               if ($id == '0'){
+                       // creating a new assignment
+                       $sql = "INSERT INTO ".TABLE_PREFIX."assignments VALUES (NULL, $_SESSION[course_id],
+                               '$title',
+                               '$assign_to',
+                               '$date_due',
+                               '$date_cutoff',
+                               '$multi_submit'
+                               )";
+
+                       $result = mysql_query($sql,$db);
+                       $msg->addFeedback('ASSIGNMENT_ADDED');
+               } else { // updating an existing assignment
+                       $assign_to = 'assign_to';
+
+                       $sql = "UPDATE ".TABLE_PREFIX."assignments SET title='$title', assign_to=$assign_to, date_due='$date_due', date_cutoff='$date_cutoff' WHERE assignment_id='$id' AND course_id=$_SESSION[course_id]";
+
+                       $result = mysql_query($sql,$db);
+                       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               }
+               header('Location: index_instructor.php');
+               exit;
+       }
+} else { // creating a new assignment
+       $title                  = '';
+       $assign_to              = '0';
+       $multi_submit   = '1';
+       $has_due_date   = 'false';
+       $late_submit    = '0'; // 0 == always, 1 == never, 2 = until (date)
+
+       $dueday         = $today['mday'];
+       $duemonth       = $today['mon'];
+       $dueyear        = $today['year'];
+       $duehour        = '12';
+       $dueminute      = '0';
+
+       $cutoffday              = $today['mday'];
+       $cutoffmonth    = $today['mon'];
+       $cutoffyear             = $today['year'];
+       $cutoffhour             = '12';
+       $cutoffminute   = '0';
+}
+
+// ensure the dates are valid
+if ($dueyear == '0'){
+       // use today's date as default
+       $dueday         = $today['mday'];
+       $duemonth       = $today['mon'];
+       $dueyear        = $today['year'];
+       $duehour        = $today['hours'];
+       $dueminute      = $today['minutes'];
+       // round the minute to the next highest multiple of 5 
+       $dueminute = round($dueminute / '5' ) * '5' + '5';
+       if ($dueminute > '55'){ $dueminute = '55'; }
+}
+if ($cutoffyear == '0'){
+       // use today's date as default
+       $cutoffday              = $today['mday'];
+       $cutoffmonth    = $today['mon'];
+       $cutoffyear             = $today['year'];
+       $cutoffhour             = $today['hours'];
+       $cutoffminute   = $today['minutes'];
+       // round the minute to the next highest multiple of 5 
+       $cutoffminute = round($cutoffminute / '5' ) * '5' + '5';
+       if ($cutoffminute > '55'){ $cutoffminute = '55'; }
+}
+
+$onload = 'document.form.title.focus();';
+
+// enable/disable date controls
+if ($has_due_date == 'false'){ 
+       $onload .= ' disable_dates (true, \'_due\');';
+}
+
+if ($late_submit != '2'){
+       $onload .= ' disable_dates (true, \'_cutoff\');';
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="id" value="<?php echo $id ?>" />
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('add_assignment'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php  echo _AT('title'); ?></label><br/>
+               <input type="text" name="title" size="50" id="title" value="<?php echo htmlspecialchars($title); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="assignto"><?php  echo _AT('assign_to'); ?></label><br/>
+
+               <?php // Are we editing an assignment?
+                       if ($id != '0'){
+                               // editing an existing assignment 
+                               if ($assign_to == '0'){ 
+                                       echo _AT('all_students'); 
+                               } else { // name of group goes here
+                                       $sql = "SELECT title FROM ".TABLE_PREFIX."groups_types WHERE type_id=$assign_to AND course_id=$_SESSION[course_id]";
+                                       $result = mysql_query($sql, $db);
+                                       $type_row = mysql_fetch_assoc($result);
+                                       echo $type_row['title'];
+                               }
+                               ?>
+                       <?php } else { // creating a new assignment
+                       ?>
+                               <select name="assign_to" size="5" id="assignto">
+                                       <option value="0" <?php if ($assign_to == '0'){ echo 'selected="selected"'; } ?> label="<?php  echo _AT('all_students'); ?>"><?php  echo _AT('all_students'); ?></option>
+                                       <optgroup label="<?php  echo _AT('specific_groups'); ?>">
+                                               <?php
+                                                       $sql = "SELECT type_id, title FROM ".TABLE_PREFIX."groups_types WHERE course_id={$_SESSION['course_id']} ORDER BY title";
+                                                       $result = mysql_query($sql, $db);
+                                                       while ($type_row = mysql_fetch_assoc($result)) {
+                                                               echo '<option value="'.$type_row['type_id'].'" ';
+                                                               if ($assign_to == $type_row['type_id']) {
+                                                                       echo 'selected="selected"';
+                                                               }
+                                                               echo '>'.$type_row['title'].'</option>';
+                                                       }
+                                               ?>
+                                       </optgroup>
+                               </select>
+                       <?php } ?>
+       </div>  
+
+       <div class="row">
+               <?php  echo _AT('due_date'); ?><br />
+               <input type="radio" name="has_due_date" value="false" id="noduedate" <?php if ($has_due_date == 'false') { echo 'checked="checked"'; } ?> 
+               onfocus="disable_dates (true, '_due');" />
+               <label for="noduedate" title="<?php echo _AT('due_date'). ': '. _AT('none');  ?>"><?php echo _AT('none'); ?></label><br />
+
+               <input type="radio" name="has_due_date" value="true" id="hasduedate" <?php if ($has_due_date == 'true'){echo 'checked="checked"'; } ?> 
+               onfocus="disable_dates (false, '_due');" />
+               <label for="hasduedate"  title="<?php echo _AT('due_date') ?>"><?php  echo _AT('date'); ?></label>
+
+               <?php
+                       $today_day  = $dueday;
+                       $today_mon  = $duemonth;
+                       $today_year = $dueyear;
+                       $today_hour = $duehour;
+                       $today_min  = $dueminute;
+                       
+                       $name = '_due';
+                       require(AT_INCLUDE_PATH.'html/release_date.inc.php');
+               ?>
+       </div>
+
+       <div class="row">
+               <?php  echo _AT('accept_late_submissions'); ?><br />
+               <input type="radio" name="late_submit" value="0" id="always"  <?php if ($late_submit == '0'){echo 'checked="checked"';} ?> 
+               onfocus="disable_dates (true, '_cutoff');" />
+
+               <label for="always" title="<?php echo _AT('accept_late_submissions'). ': '. _AT('always');  ?>"><?php echo _AT('always'); ?></label><br />
+
+               <input type="radio" name="late_submit" value="1" id="never"  <?php if ($late_submit == '1'){echo 'checked="checked"';} ?>
+               onfocus="disable_dates (true, '_cutoff');" />
+
+               <label for="never" title="<?php echo _AT('accept_late_submissions'). ': '. _AT('never');  ?>"><?php  echo _AT('never'); ?></label><br />
+
+               <input type="radio" name="late_submit" value="2" id="until"  <?php if ($late_submit == '2'){echo 'checked="checked"';} ?>
+               onfocus="disable_dates (false, '_cutoff');" />
+
+               <label for="until" title="<?php echo _AT('accept_late_submissions'). ': '. _AT('until');  ?>"><?php  echo _AT('until'); ?></label>
+
+               <?php
+                       $today_day  = $cutoffday;
+                       $today_mon  = $cutoffmonth;
+                       $today_year = $cutoffyear;
+                       $today_hour = $cutoffhour;
+                       $today_min  = $cutoffminute;
+                       
+                       $name = '_cutoff';
+                       require(AT_INCLUDE_PATH.'html/release_date.inc.php');
+               ?>
+       </div>
+       <?php
+       /****
+        * not included in the initial release.
+        *
+       <div class="row">
+               <?php  echo _AT('options'); <br/>
+               <input type="checkbox" name="multi_submit" id="multisubmit" <?php if ($multi_submit == '1'){ echo 'checked="checked"'; }  />
+               <label for="multisubmit"><?php  echo _AT('allow_re_submissions'); </label>
+       </div>
+       ***/
+       ?>
+       
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+
+</form>
+
+<script language="javascript" type="text/javascript">
+function disable_dates (state, name) {
+       document.form['day' + name].disabled=state;
+       document.form['month' + name].disabled=state;
+       document.form['year' + name].disabled=state;
+       document.form['hour' + name].disabled=state;
+       document.form['min' + name].disabled=state;
+}
+</script>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/assignments/delete_assignment.php b/assignments/delete_assignment.php
new file mode 100644 (file)
index 0000000..ce75912
--- /dev/null
@@ -0,0 +1,58 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008                                      */\r
+/* Written by Greg Gay & Joel Kronenberg & Chris Ridpath        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_ASSIGNMENTS);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       Header('Location: index_instructor.php');\r
+       exit;\r
+}\r
+else if (isset($_POST['submit_yes'])) {\r
+       $_POST['assignment_id'] = intval($_POST['assignment_id']);\r
+\r
+       // delete the assignment from the table\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."assignments WHERE course_id=$_SESSION[course_id] AND assignment_id=$_POST[assignment_id]";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       // delete all the files for this assignment\r
+       require(AT_INCLUDE_PATH.'lib/file_storage.inc.php');\r
+       fs_delete_workspace(WORKSPACE_ASSIGNMENT, $_POST['assignment_id']);\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: index_instructor.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$_GET['id'] = intval($_GET['id']); \r
+\r
+$sql = "SELECT title FROM ".TABLE_PREFIX."assignments WHERE course_id=$_SESSION[course_id] AND assignment_id=$_GET[id]";\r
+$result = mysql_query($sql, $db);\r
+\r
+if ($row = mysql_fetch_assoc($result)){\r
+       $hidden_vars['assignment_id'] = $_GET['id'];\r
+       $confirm = array('DELETE_ASSIGNMENT', $row['title']);\r
+       $msg->addConfirm($confirm, $hidden_vars);\r
+       $msg->printConfirm();\r
+}\r
+else {\r
+       $msg->addError('ASSIGNMENT_NOT_FOUND');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/assignments/edit_assignment.php b/assignments/edit_assignment.php
new file mode 100644 (file)
index 0000000..5cf80b0
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+require('add_assignment.php');
+?>
\ No newline at end of file
diff --git a/assignments/index.php b/assignments/index.php
new file mode 100644 (file)
index 0000000..8828b4b
--- /dev/null
@@ -0,0 +1,17 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008                                      */\r
+/* Written by Greg Gay & Joel Kronenberg & Chris Ridpath        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+header('Location: index_instructor.php');\r
+exit;\r
+?>
\ No newline at end of file
diff --git a/assignments/index_instructor.php b/assignments/index_instructor.php
new file mode 100644 (file)
index 0000000..0508930
--- /dev/null
@@ -0,0 +1,134 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008                                      */\r
+/* Written by Greg Gay & Joel Kronenberg & Chris Ridpath        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_ASSIGNMENTS);\r
+\r
+if (isset($_GET['edit'])) {\r
+       $_GET['assignment'] = intval($_GET['assignment']);\r
+       header('Location: edit_assignment.php?id='. $_GET['assignment']);\r
+       exit;\r
+} else if (isset($_GET['delete'])) {\r
+       $_GET['assignment'] = intval($_GET['assignment']);\r
+       header('Location: delete_assignment.php?id='. $_GET['assignment']);\r
+       exit;\r
+} else if (isset($_GET['submissions'])){\r
+       $_GET['assignment'] = intval($_GET['assignment']);\r
+       header('Location: '.AT_BASE_HREF.'file_storage/index.php?ot='.WORKSPACE_ASSIGNMENT.SEP.'oid='.$_GET['assignment']);\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+\r
+// sort order of table\r
+$orders = array('ASC' => 'DESC', 'DESC' => 'ASC');\r
+$cols   = array('title' => 1, 'date' => 1);\r
+$sort = 'title';\r
+$order = 'ASC';\r
+if (isset($_GET['sort'])){\r
+       $sort = isset($cols[$_GET['sort']]) ? $_GET['sort'] : 'title';\r
+}\r
+if (isset($_GET['order'])){\r
+       $order = $addslashes($_GET['order']);\r
+       if (($order != 'ASC') && ($order != 'DESC')){\r
+               $order = 'ASC';\r
+       }\r
+}\r
+$sql = "SELECT * FROM ".TABLE_PREFIX."assignments WHERE course_id=$_SESSION[course_id] ORDER BY $sort $order";\r
+$result = mysql_query($sql, $db);\r
+?>\r
+\r
+<?php $msg->printInfos('ASSIGNMENT_FS_SUBMISSIONS'); ?>\r
+\r
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">\r
+<table class="data" style="width: 90%;" rules="cols">\r
+<colgroup>\r
+       <?php if ($sort == 'title'): ?>\r
+               <col />\r
+               <col class="sort" />\r
+               <col span="5" />\r
+       <?php elseif($sort == 'assign_to'): ?>\r
+               <col span="2" />\r
+               <col class="sort" />\r
+               <col span="4" />\r
+       <?php elseif($sort == 'date_due'): ?>\r
+               <col span="3" />\r
+               <col class="sort" />\r
+               <col span="3" />\r
+       <?php endif; ?>\r
+</colgroup>\r
+<thead>\r
+<tr>\r
+       <th>&nbsp;</th>\r
+       <th scope="col"><a href="assignments/index_instructor.php?sort=title<?php echo SEP; ?>order=<?php echo $orders[$order]; ?>"><?php echo _AT('title'); ?></a></th>\r
+       <th scope="col"><?php echo _AT('assigned_to'); ?></th>\r
+       <th scope="col"><a href="assignments/index_instructor.php?sort=date_due<?php echo SEP; ?>order=<?php echo $orders[$order]; ?>"><?php echo _AT('due_date'); ?></a></th>\r
+</tr>\r
+</thead>\r
+<?php if (($result != 0) && ($row = mysql_fetch_assoc($result))) : ?>\r
+<tfoot>\r
+<tr>\r
+       <td colspan="4">\r
+               <input type="submit" name="submissions" value="<?php echo _AT('submissions'); ?>" /> \r
+               <input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> \r
+               <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" />\r
+                                       \r
+       </td>\r
+</tr>\r
+</tfoot>\r
+<tbody>\r
+       <?php do { ?>\r
+               <tr onmousedown="document.form['a<?php echo $row['assignment_id']; ?>'].checked = true; rowselect(this);" id="a_<?php echo $row['assignment_id']; ?>_0">\r
+               \r
+               <td><input type="radio" id="a<?php echo $row['assignment_id']; ?>" name="assignment" value="<?php echo $row['assignment_id']; ?>" \r
+\r
+               <?php // set first item as checked if nothing selected\r
+               if (isset($_GET['assignment_id'])){\r
+                       if ($_GET['assignment_id'] == $row['assignment_id']){ \r
+                               echo ' checked="checked"'; \r
+                       } \r
+               }\r
+               else {\r
+                       echo ' checked="checked"';\r
+                       $_GET['assignment_id'] = $row['assignment_id'];\r
+               }\r
+               ?>/></td>\r
+\r
+               <td><label for="a<?php echo $row['assignment_id']; ?>"><?php echo $row['title']; ?></label></td>\r
+\r
+               <td><?php if($row['assign_to'] == '0'){echo _AT('all_students'); } else {\r
+                                       $sql = "SELECT title FROM ".TABLE_PREFIX."groups_types WHERE type_id=$row[assign_to] AND course_id=$_SESSION[course_id]";\r
+                                       $type_result = mysql_query($sql, $db);\r
+                                       $type_row = mysql_fetch_assoc($type_result);\r
+                                       echo $type_row['title']; } ?></td>\r
+\r
+               <td><?php  if ($row['date_due'] == '0000-00-00 00:00:00'){\r
+                       echo _AT('none');\r
+               }else {\r
+                       echo AT_Date(_AT('forum_date_format'), $row['date_due'], AT_DATE_MYSQL_DATETIME);\r
+               }?></td>\r
+               </tr>\r
+       <?php } while($row = mysql_fetch_assoc($result)); ?>\r
+</tbody>\r
+<?php else: ?>\r
+       <tr>\r
+               <td colspan="4"><em><?php echo _AT('none_found'); ?></em></td>\r
+       </tr>\r
+<?php endif; ?>\r
+</table>\r
+</form>\r
+\r
+\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/blogs/add_post.php b/blogs/add_post.php
new file mode 100644 (file)
index 0000000..2751103
--- /dev/null
@@ -0,0 +1,98 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+// authenticate ot+oid ....\r
+$owner_type = abs($_REQUEST['ot']);\r
+$owner_id = abs($_REQUEST['oid']);\r
+if (!($owner_status = blogs_authenticate($owner_type, $owner_id)) || !query_bit($owner_status, BLOGS_AUTH_WRITE)) {\r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: '.url_rewrite('blogs/index.php', AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+}\r
+\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.url_rewrite('blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_POST['oid'], AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       $_POST['title'] = $addslashes(trim($_POST['title']));\r
+       $_POST['body']  = $addslashes(trim($_POST['body']));\r
+\r
+       if ($_POST['body'] == '') {\r
+               $msg->addError(array('EMPTY_FIELDS', _AT('body')));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               $_POST['title'] = htmlspecialchars($_POST['title']);\r
+               $_POST['body']  = htmlspecialchars($_POST['body']);\r
+               $_POST['private'] = abs($_POST['private']);\r
+               $sql = "INSERT INTO ".TABLE_PREFIX."blog_posts VALUES (NULL, $_SESSION[member_id], ".BLOGS_GROUP.", $_POST[oid], $_POST[private], NOW(), 0, '$_POST[title]', '$_POST[body]')";\r
+               mysql_query($sql, $db);\r
+\r
+               $msg->addFeedback('POST_ADDED_SUCCESSFULLY');\r
+\r
+               header('Location: '.url_rewrite('blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_POST['oid'], AT_PRETTY_URL_IS_HEADER));\r
+               exit;\r
+       }\r
+}\r
+\r
+// this will also be dynamic as the parent page changes\r
+$_pages['blogs/add_post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['title_var'] = 'add';\r
+$_pages['blogs/add_post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['parent'] = 'blogs/view.php';\r
+\r
+$_pages['blogs/add_post.php']['title_var'] = 'add';\r
+$_pages['blogs/add_post.php']['parent']    = 'blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'];\r
+\r
+$_pages['blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['title'] = blogs_get_blog_name(BLOGS_GROUP, $_REQUEST['oid']);\r
+$_pages['blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['parent']    = 'blogs/index.php';\r
+$_pages['blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['children']  = array('blogs/add_post.php');\r
+\r
+\r
+$onload = 'document.form.title.focus();';\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+?>\r
+\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">\r
+<input type="hidden" name="ot" value="<?php echo BLOGS_GROUP; ?>" />\r
+<input type="hidden" name="oid" value="<?php echo abs($_REQUEST['oid']); ?>" />\r
+<div class="input-form">\r
+       <div class="row">\r
+               <label for="title"><?php echo _AT('title'); ?></label><br />\r
+               <input type="text" name="title" id="title" value="<?php echo htmlspecialchars(stripslashes($_POST['title'])); ?>" size="50" />\r
+       </div>\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="body"><?php echo _AT('body'); ?></label><br />\r
+               <textarea name="body" id="body" cols="40" rows="10"></textarea>\r
+       </div>\r
+\r
+       <div class="row">       \r
+               <a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#jumpcodes" title="<?php echo _AT('jump_codes'); ?>"><img src="images/clr.gif" height="1" width="1" alt="<?php echo _AT('jump_codes'); ?>" border="0" /></a><?php require(AT_INCLUDE_PATH.'html/code_picker.inc.php'); ?>\r
+\r
+               <a name="jumpcodes"></a>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <input type="checkbox" name="private" value="1" id="private" /><label for="private"><?php echo _AT('private'); ?></label>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('post'); ?>" accesskey="s" /> <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" /> \r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/blogs/delete_comment.php b/blogs/delete_comment.php
new file mode 100644 (file)
index 0000000..4f22f3a
--- /dev/null
@@ -0,0 +1,64 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id: delete_comment.php 5999 2006-03-20 20:18:07Z joel $\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+// authenticate ot+oid..\r
+$owner_type = abs($_REQUEST['ot']);\r
+$owner_id = abs($_REQUEST['oid']);\r
+if (!($owner_status = blogs_authenticate($owner_type, $owner_id)) || !query_bit($owner_status, BLOGS_AUTH_WRITE)) {\r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+$id = abs($_REQUEST['id']);\r
+$delete_id = abs($_REQUEST['delete_id']);\r
+\r
+$sql = "SELECT post_id FROM ".TABLE_PREFIX."blog_posts WHERE owner_type=$owner_type AND owner_id=$owner_id AND post_id=$id";\r
+$result = mysql_query($sql, $db);\r
+if (!$row = mysql_fetch_assoc($result)) {\r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.url_rewrite('blogs/post.php?ot='.$owner_type.SEP.'oid='.$owner_id.SEP.'id='.$id, AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."blog_posts_comments WHERE comment_id=$delete_id AND post_id=$id";\r
+       $result = mysql_query($sql, $db);\r
+       if (mysql_affected_rows($db) == 1) {\r
+               $sql = "UPDATE ".TABLE_PREFIX."blog_posts SET num_comments=num_comments-1, date=date WHERE owner_type=$owner_type AND owner_id=$owner_id AND post_id=$id";\r
+               $result = mysql_query($sql, $db);\r
+       }\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: '.url_rewrite('blogs/post.php?ot='.$owner_type.SEP.'oid='.$owner_id.SEP.'id='.$id, AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$hidden_vars = array('id' => $id, 'ot' => $owner_type, 'oid' => $owner_id, 'delete_id' => $delete_id);\r
+$msg->addConfirm(array('DELETE'), $hidden_vars);\r
+$msg->printConfirm();\r
+\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/blogs/delete_post.php b/blogs/delete_post.php
new file mode 100644 (file)
index 0000000..3dd9dc6
--- /dev/null
@@ -0,0 +1,67 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+// authenticate ot+oid ....\r
+$owner_type = abs($_REQUEST['ot']);\r
+$owner_id = abs($_REQUEST['oid']);\r
+if (!($owner_status = blogs_authenticate($owner_type, $owner_id)) || !query_bit($owner_status, BLOGS_AUTH_WRITE)) {\r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       $id = abs($_POST['id']);\r
+       header('Location: post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_POST['oid'].SEP.'id='.$id);\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       $id = abs($_POST['id']);\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."blog_posts WHERE owner_type=".BLOGS_GROUP." AND owner_id=$_REQUEST[oid] AND post_id=$id";\r
+       mysql_query($sql, $db);\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+\r
+       header('Location: view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_POST['oid']);\r
+       exit;\r
+}\r
+\r
+$id = abs($_REQUEST['id']);\r
+$sql = "SELECT title, body FROM ".TABLE_PREFIX."blog_posts WHERE owner_type=".BLOGS_GROUP." AND owner_id=$owner_id AND post_id=$id";\r
+$result = mysql_query($sql, $db);\r
+$post_row = mysql_fetch_assoc($result);\r
+\r
+$_pages['blogs/delete_post.php']['parent']    = 'blogs/post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id'];\r
+\r
+\r
+$_pages['blogs/post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id']]['children'] = array('blogs/edit_post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id'], 'blogs/delete_post.php');\r
+$_pages['blogs/post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id']]['parent'] = 'blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'];\r
+$_pages['blogs/post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id']]['title'] = $post_row['title'];\r
+\r
+\r
+$_pages['blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['title'] = blogs_get_blog_name(BLOGS_GROUP, $_REQUEST['oid']);\r
+$_pages['blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['parent']    = 'blogs/index.php';\r
+$_pages['blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['children']  = array('blogs/add_post.php');\r
+\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$hidden_vars = array('id' => $id, 'ot' => $_REQUEST['ot'], 'oid' => $_REQUEST['oid']);\r
+$msg->addConfirm('DELETE', $hidden_vars);\r
+$msg->printConfirm();\r
+?>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/blogs/edit_post.php b/blogs/edit_post.php
new file mode 100644 (file)
index 0000000..569e128
--- /dev/null
@@ -0,0 +1,106 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+// authenticate ot+oid ....\r
+$owner_type = abs($_REQUEST['ot']);\r
+$owner_id = abs($_REQUEST['oid']);\r
+if (!($owner_status = blogs_authenticate($owner_type, $owner_id)) || !query_bit($owner_status, BLOGS_AUTH_WRITE)) {\r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.url_rewrite('blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_POST['oid'], AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       $_POST['title'] = $addslashes(trim($_POST['title']));\r
+       $_POST['body']  = $addslashes(trim($_POST['body']));\r
+       $id = abs($_POST['id']);\r
+\r
+       if ($_POST['body'] == '') {\r
+               $msg->addError(array('EMPTY_FIELDS', _AT('body')));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               $_POST['title'] = htmlspecialchars($_POST['title']);\r
+               $_POST['body']  = htmlspecialchars($_POST['body']);\r
+               $_POST['private'] = abs($_POST['private']);\r
+               $sql = "UPDATE ".TABLE_PREFIX."blog_posts SET private=$_POST[private], title='$_POST[title]', body='$_POST[body]', date=date WHERE owner_type=".BLOGS_GROUP." AND owner_id=$_REQUEST[oid] AND post_id=$id";\r
+               mysql_query($sql, $db);\r
+\r
+               $msg->addFeedback('POST_ADDED_SUCCESSFULLY');\r
+\r
+               header('Location: '.url_rewrite('blogs/post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_POST['oid'].SEP.'id='.$id, AT_PRETTY_URL_IS_HEADER));\r
+               exit;\r
+       }\r
+}\r
+\r
+$id = abs($_REQUEST['id']);\r
+$sql = "SELECT private, title, body FROM ".TABLE_PREFIX."blog_posts WHERE owner_type=".BLOGS_GROUP." AND owner_id=$_REQUEST[oid] AND post_id=$id";\r
+$result = mysql_query($sql, $db);\r
+$post_row = mysql_fetch_assoc($result);\r
+\r
+$_pages['blogs/edit_post.php']['parent']    = 'blogs/post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id'];\r
+$_pages['blogs/post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id']] = $_pages['blogs/post.php'];\r
+$_pages['blogs/post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id']]['children'] = array('blogs/edit_post.php', 'blogs/delete_post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id']);\r
+\r
+$_pages['blogs/post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id']]['parent'] = 'blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'];\r
+$_pages['blogs/post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id']]['title'] = $post_row['title'];\r
+$_pages['blogs/post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id']]['children'] = array('blogs/edit_post.php', 'blogs/delete_post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id']);\r
+\r
+$_pages['blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['title'] = blogs_get_blog_name(BLOGS_GROUP, $_REQUEST['oid']);\r
+$_pages['blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['parent']    = 'blogs/index.php';\r
+$_pages['blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['children']  = array('blogs/add_post.php');\r
+\r
+\r
+$onload = 'document.form.title.focus();';\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+?>\r
+\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">\r
+<input type="hidden" name="ot" value="<?php echo BLOGS_GROUP; ?>" />\r
+<input type="hidden" name="oid" value="<?php echo abs($_REQUEST['oid']); ?>" />\r
+<input type="hidden" name="id" value="<?php echo $id; ?>" />\r
+<div class="input-form">\r
+       <div class="row">\r
+               <label for="title"><?php echo _AT('title'); ?></label><br />\r
+               <input type="text" name="title" id="title" value="<?php echo $post_row['title']; ?>" size="50" />\r
+       </div>\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="body"><?php echo _AT('body'); ?></label><br />\r
+               <textarea name="body" id="body" cols="40" rows="10"><?php echo $post_row['body']; ?></textarea>\r
+       </div>\r
+\r
+       <div class="row">       \r
+               <a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#jumpcodes" title="<?php echo _AT('jump_codes'); ?>"><img src="images/clr.gif" height="1" width="1" alt="<?php echo _AT('jump_codes'); ?>" border="0" /></a><?php require(AT_INCLUDE_PATH.'html/code_picker.inc.php'); ?>\r
+\r
+               <a name="jumpcodes"></a>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <input type="checkbox" name="private" value="1" id="private" <?php if ($post_row['private']) { echo 'checked="checked"'; } ?> /><label for="private"><?php echo _AT('private'); ?></label>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" /> <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" /> \r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/blogs/index.php b/blogs/index.php
new file mode 100644 (file)
index 0000000..55233e2
--- /dev/null
@@ -0,0 +1,46 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$sql = "SELECT G.group_id, G.title, G.modules FROM ".TABLE_PREFIX."groups G INNER JOIN ".TABLE_PREFIX."groups_types T USING (type_id) WHERE T.course_id=$_SESSION[course_id] ORDER BY G.title";\r
+$result = mysql_query($sql, $db);\r
+\r
+echo '<ol id="tools">';\r
+\r
+$blogs = false;\r
+while ($row = mysql_fetch_assoc($result)) {\r
+       if (strpos($row['modules'], '_standard/blogs') !== FALSE) {\r
+               // retrieve the last posted date/time from this blog\r
+               $sql = "SELECT MAX(date) AS date FROM ".TABLE_PREFIX."blog_posts WHERE owner_type=".BLOGS_GROUP." AND owner_id={$row['group_id']}";\r
+               $date_result = mysql_query($sql, $db);\r
+               if (($date_row = mysql_fetch_assoc($date_result)) && $date_row['date']) {\r
+                       $last_updated = ' - ' . _AT('last_updated', AT_date(_AT('forum_date_format'), $date_row['date'], AT_DATE_MYSQL_DATETIME));\r
+               } else {\r
+                       $last_updated = '';\r
+               }\r
+\r
+               echo '<li class="top-tool"><a href="'.url_rewrite('blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$row['group_id']).'">'.$row['title'].$last_updated.'</a></li>';\r
+               $blogs = true;\r
+       }\r
+}\r
+echo '</ol>';\r
+\r
+if (!$blogs) {\r
+       echo _AT('none_found');\r
+}\r
+?>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/blogs/post.php b/blogs/post.php
new file mode 100644 (file)
index 0000000..6fe89c4
--- /dev/null
@@ -0,0 +1,135 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require_once (AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+// authenticate ot+oid..\r
+$owner_type = abs($_REQUEST['ot']);\r
+$owner_id = abs($_REQUEST['oid']);\r
+if (!($owner_status = blogs_authenticate($owner_type, $owner_id))) {\r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: '.url_rewrite('blogs/index.php'));\r
+       exit;\r
+}\r
+\r
+$id = abs($_REQUEST['id']);\r
+$auth = '';\r
+if (!query_bit($owner_status, BLOGS_AUTH_WRITE)) {\r
+       $auth = 'private=0 AND ';\r
+}\r
+$sql = "SELECT member_id, private, date, title, body FROM ".TABLE_PREFIX."blog_posts WHERE $auth owner_type=".BLOGS_GROUP." AND owner_id=$_REQUEST[oid] AND post_id=$id ORDER BY date DESC";\r
+$result = mysql_query($sql, $db);\r
+\r
+\r
+if (isset($_POST['submit']) && $_SESSION['member_id']) {\r
+       // post a comment\r
+       $_POST['body'] = $addslashes(trim($_POST['body']));\r
+       $_POST['private'] = abs($_POST['private']);\r
+\r
+       if ($_POST['body'] == '') {\r
+               $msg->addError(array('EMPTY_FIELDS', _AT('comments')));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               $sql = "INSERT INTO ".TABLE_PREFIX."blog_posts_comments VALUES (NULL, $id, $_SESSION[member_id], NOW(), $_POST[private], '$_POST[body]')";\r
+               mysql_query($sql, $db);\r
+               if (mysql_affected_rows($db) == 1) {\r
+                       $sql = "UPDATE ".TABLE_PREFIX."blog_posts SET num_comments=num_comments+1, date=date WHERE post_id=$id";\r
+                       mysql_query($sql, $db);\r
+               }\r
+\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+\r
+               header('Location: '.url_rewrite('blogs/post.php?ot='.$owner_type.SEP.'oid='.$owner_id.SEP.'id='.$id, AT_PRETTY_URL_IS_HEADER));\r
+               exit;\r
+       }\r
+}\r
+\r
+if (!$post_row = mysql_fetch_assoc($result)) {\r
+       header('Location: '.url_rewrite('blogs/view.php?ot='.$owner_type.SEP.'oid='.$owner_id));\r
+       exit;\r
+}\r
+\r
+$_pages['blogs/post.php']['title'] = AT_PRINT($post_row['title'], 'blog_posts.title') . ($post_row['private'] ? ' - '._AT('private') : '');\r
+$_pages['blogs/post.php']['parent']    = 'blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'];\r
+if (query_bit($owner_status, BLOGS_AUTH_WRITE)) {\r
+       $_pages['blogs/post.php']['children']  = array('blogs/edit_post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id'], 'blogs/delete_post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id']);\r
+} else {\r
+       $_pages['blogs/post.php']['children']  = array();\r
+}\r
+\r
+$_pages['blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['title'] = blogs_get_blog_name(BLOGS_GROUP, $_REQUEST['oid']);\r
+$_pages['blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['parent']    = 'blogs/index.php';\r
+\r
+if (query_bit($owner_status, BLOGS_AUTH_WRITE)) {\r
+       $_pages['blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['children']  = array('blogs/add_post.php');\r
+} else {\r
+       $_pages['blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['children']  = array();\r
+}\r
+\r
+\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+?>\r
+       <div class="entry">\r
+               <h3 class="date"><?php echo get_display_name($post_row['member_id']); ?> - <?php echo AT_date(_AT('forum_date_format'), $post_row['date'], AT_DATE_MYSQL_DATETIME); ?></h3>\r
+\r
+               <p><?php echo AT_PRINT($post_row['body'], 'blog_posts.body'); ?></p>\r
+       </div>\r
+\r
+<a name="comments"></a><h2><?php echo _AT('comments'); ?></h2>\r
+<?php\r
+       $sql = "SELECT comment_id, member_id, date, comment FROM ".TABLE_PREFIX."blog_posts_comments WHERE post_id=$id ORDER BY date";\r
+       $result = mysql_query($sql, $db);\r
+?>\r
+<?php while ($row = mysql_fetch_assoc($result)): ?>\r
+       <div class="input-form">\r
+               <div class="row">\r
+                       <h4 class="date"><?php echo get_display_name($row['member_id']); ?> - <?php echo AT_date(_AT('forum_date_format'), $row['date'], AT_DATE_MYSQL_DATETIME); ?></h4>\r
+\r
+                       <p><?php echo AT_print($row['comment'], 'blog_posts_comments.comment'); ?></p>\r
+\r
+                       <?php if (query_bit($owner_status, BLOGS_AUTH_WRITE)): ?>\r
+                               <div style="text-align: right; font-size: smaller;">\r
+                                       <a href="blogs/delete_comment.php?ot=<?php echo $owner_type.SEP.'oid='.$owner_id.SEP.'id='.$id.SEP.'delete_id='.$row['comment_id']; ?>"><?php echo _AT('delete'); ?></a>\r
+                               </div>\r
+                       <?php endif; ?>\r
+               </div>\r
+       </div>\r
+\r
+<?php endwhile; ?>\r
+\r
+<?php if ($_SESSION['member_id']): ?>\r
+       <form method="post" action="<?php echo $_SERVER['PHP_SELF'].'?ot='.$owner_type.SEP.'oid='.$owner_id; ?>" name="form">\r
+       <input type="hidden" name="id" value="<?php echo $id; ?>" />\r
+       <div class="input-form">\r
+               <div class="row">\r
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="commentsarea"><?php echo _AT('comments'); ?></label><br />\r
+                       <textarea name="body" id="commentsarea" cols="40" rows="3"></textarea>\r
+               </div>\r
+\r
+               <div class="row">       \r
+                       <a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#jumpcodes" title="<?php echo _AT('jump_codes'); ?>"><img src="images/clr.gif" height="1" width="1" alt="<?php echo _AT('jump_codes'); ?>" border="0" /></a><?php require(AT_INCLUDE_PATH.'html/code_picker.inc.php'); ?>\r
+\r
+                       <a name="jumpcodes"></a>\r
+               </div>\r
+\r
+               <div class="row buttons">\r
+                       <input type="submit" name="submit" value="<?php echo _AT('post'); ?>" accesskey="s" />\r
+               </div>\r
+       </div>\r
+       </form>\r
+<?php endif; ?>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/blogs/view.php b/blogs/view.php
new file mode 100644 (file)
index 0000000..71b42b3
--- /dev/null
@@ -0,0 +1,94 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require_once (AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+$owner_type = intval($_REQUEST['ot']);\r
+$owner_id   = intval($_REQUEST['oid']);\r
+\r
+$owner_arg_prefix = '?ot='.$owner_type.SEP.'oid='.$owner_id. SEP;\r
+if (!($owner_status = blogs_authenticate($owner_type, $owner_id))) {\r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+// these will all by dynamically defined on the view page\r
+$_pages['blogs/view.php']['title'] = blogs_get_blog_name(BLOGS_GROUP, $_REQUEST['oid']);\r
+$_pages['blogs/view.php']['parent']    = 'blogs/index.php';\r
+\r
+if (query_bit($owner_status, BLOGS_AUTH_WRITE)) {\r
+       $_pages['blogs/view.php']['children']  = array('blogs/add_post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']);\r
+} else {\r
+       $_pages['blogs/view.php']['children']  = array();\r
+}\r
+\r
+$_pages['blogs/add_post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['title_var'] = 'add';\r
+\r
+$_pages['blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['title'] = blogs_get_blog_name(BLOGS_GROUP, $_REQUEST['oid']);\r
+$_pages['blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['parent']    = 'blogs/index.php';\r
+if (query_bit($owner_status, BLOGS_AUTH_WRITE)) {\r
+       $_pages['blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['children'] = array('blogs/add_post.php');\r
+} else {\r
+       $_pages['blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid']]['children'] = array();\r
+}\r
+\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$auth = '';\r
+if (!query_bit($owner_status, BLOGS_AUTH_WRITE)) {\r
+       $auth = 'private=0 AND ';\r
+}\r
+\r
+\r
+if (isset($_GET['p'])) {\r
+       $page = abs($_GET['p']);\r
+} else {\r
+       $page = 1;\r
+}\r
+\r
+$num_posts_per_page = 20;\r
+$start = ($page - 1) * $num_posts_per_page;\r
+\r
+$count = 0;\r
+\r
+$sql = "SELECT post_id, member_id, private, num_comments, date, title, body FROM ".TABLE_PREFIX."blog_posts WHERE $auth owner_type=".BLOGS_GROUP." AND owner_id=$_REQUEST[oid] ORDER BY date DESC LIMIT $start, " . ($num_posts_per_page+1);\r
+$result = mysql_query($sql, $db);\r
+?>\r
+<?php if (mysql_num_rows($result)): ?>\r
+       <?php while (($row = mysql_fetch_assoc($result)) && ($count < $num_posts_per_page)): $count++; ?>\r
+               <div class="entry">\r
+                       <h2><a href="<?php echo url_rewrite('blogs/post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$row['post_id']); ?>"><?php echo AT_PRINT($row['title'], 'blog_posts.title'); ?></a>\r
+                       <?php if ($row['private']): ?>\r
+                               - <?php echo _AT('private'); ?>\r
+                       <?php endif; ?></h2>\r
+                       <h3 class="date"><?php echo get_display_name($row['member_id']); ?> - <?php echo AT_date(_AT('forum_date_format'), $row['date'], AT_DATE_MYSQL_DATETIME); ?></h3>\r
+\r
+                       <p><?php echo AT_PRINT($row['body'], 'blog_posts.body'); ?></p>\r
+\r
+                       <p><a href="<?php echo url_rewrite('blogs/post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$row['post_id']); ?>#comments"><?php echo _AT('comments_num', $row['num_comments']); ?></a></p>\r
+                       <hr />\r
+               </div>\r
+       <?php endwhile; ?>\r
+       <?php\r
+               if (mysql_num_rows($result) > $num_posts_per_page) {\r
+\r
+                       echo '<a href="'.url_rewrite('blogs/view.php?ot='.$owner_type.SEP.'oid='.$owner_id.SEP.'p='.(++$page)).'">'._AT('previous_posts').'</a>';\r
+               }\r
+       ?>\r
+<?php else: ?>\r
+       <p><?php echo _AT('none_found'); ?></p>\r
+<?php endif; ?>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/bounce.php b/bounce.php
new file mode 100644 (file)
index 0000000..4e878e4
--- /dev/null
@@ -0,0 +1,481 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                             */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+function apply_category_theme($category_id) {
+       if (defined('AT_ENABLE_CATEGORY_THEMES') && AT_ENABLE_CATEGORY_THEMES) {
+               global $db;
+
+               if ($category_id) {
+                       // apply the theme for this category:
+                       $sql    = "SELECT theme FROM ".TABLE_PREFIX."course_cats WHERE cat_id=$category_id";
+                       $result = mysql_query($sql, $db);
+                       if (($cat_row = mysql_fetch_assoc($result)) && $cat_row['theme']) {
+                               $_SESSION['prefs']['PREF_THEME'] = $cat_row['theme'];
+                       } else {                        
+                               $th = get_default_theme();
+                               $_SESSION['prefs']['PREF_THEME'] = $th['dir_name'];
+                       }
+               } else {                        
+                       $th = get_default_theme();
+                       $_SESSION['prefs']['PREF_THEME'] = $th['dir_name'];
+               }
+       }
+}
+
+function count_login( ) {
+       global $db, $moduleFactory;
+
+       $module =& $moduleFactory->getModule(AT_MODULE_DIR_STANDARD.'/statistics');
+       if (!$module->isEnabled()) {
+               return;
+       }
+       if ($_SESSION['is_guest']) {
+           $sql   = "INSERT INTO ".TABLE_PREFIX."course_stats VALUES ($_SESSION[course_id], NOW(), 1, 0)";
+       } else {
+          $sql    = "INSERT INTO ".TABLE_PREFIX."course_stats VALUES ($_SESSION[course_id], NOW(), 0, 1)";
+       }
+
+    $result = @mysql_query($sql, $db);
+
+    if (!$result) {
+               /* that entry already exists, then update it. */
+               if ($_SESSION['is_guest']) {
+                       $sql   = "UPDATE ".TABLE_PREFIX."course_stats SET guests=guests+1 WHERE course_id=$_SESSION[course_id] AND login_date=NOW()";
+               } else {
+                       $sql   = "UPDATE ".TABLE_PREFIX."course_stats SET members=members+1 WHERE course_id=$_SESSION[course_id] AND login_date=NOW()";
+               }
+               $result = @mysql_query($sql, $db);
+       }
+}
+
+function get_groups($course_id) {
+       global $db;
+
+       $groups = array();
+
+       if (authenticate(AT_PRIV_GROUPS, true)) {
+               $sql = "SELECT G.group_id FROM ".TABLE_PREFIX."groups G INNER JOIN ".TABLE_PREFIX."groups_types T USING (type_id) WHERE T.course_id=$course_id";
+       } else {
+               $sql = "SELECT G.group_id FROM ".TABLE_PREFIX."groups G INNER JOIN (".TABLE_PREFIX."groups_types T, ".TABLE_PREFIX."groups_members M) ON (G.type_id=T.type_id AND  G.group_id=M.group_id) WHERE T.course_id=$course_id AND M.member_id=$_SESSION[member_id]";
+       }
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_assoc($result)) {
+               $groups[$row['group_id']] = $row['group_id'];
+       }
+
+       return $groups;
+}
+
+$_user_location        = 'public';
+define('AT_INCLUDE_PATH', 'include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+$set_to_public = false;
+if ($_SERVER['PHP_SELF'] == $_base_path."acl.php") {
+       //search through the auth table and find password that matches get password
+       $key = $addslashes(key($_GET));
+       $sql = "SELECT * FROM ".TABLE_PREFIX."course_access WHERE password='$key' AND (expiry_date > NOW() OR expiry_date+0 = 0) AND enabled=1";
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)) {
+               $set_to_public = true;
+               $_GET['course'] = $row['course_id'];
+               $_SESSION['member_id'] = 0;
+               $_SESSION['valid_user'] = false;
+               $_SESSION['login'] = 'guest';
+       }
+}
+
+
+if (isset($_GET['admin']) && isset($_SESSION['is_super_admin'])) {
+       $sql = "SELECT login, `privileges`, language FROM ".TABLE_PREFIX."admins WHERE login='$_SESSION[is_super_admin]' AND `privileges`>0";
+       $result = mysql_query($sql, $db);
+
+       if ($row = mysql_fetch_assoc($result)) {
+               $sql = "UPDATE ".TABLE_PREFIX."admins SET last_login=NOW() WHERE login='$_SESSION[is_super_admin]'";
+               mysql_query($sql, $db);
+
+               $_SESSION['login']              = $row['login'];
+               $_SESSION['valid_user'] = true;
+               $_SESSION['course_id']  = -1;
+               $_SESSION['privileges'] = intval($row['privileges']);
+               $_SESSION['lang'] = $row['language'];
+               unset($_SESSION['member_id']);
+               unset($_SESSION['is_super_admin']);
+
+               write_to_log(AT_ADMIN_LOG_UPDATE, 'admins', mysql_affected_rows($db), $sql);
+
+               $msg->addFeedback('LOGIN_SUCCESS');
+
+               header('Location: admin/index.php');
+               exit;
+       }
+}
+
+if (!empty($_REQUEST['pu'])) {
+       //for pretty url iff mod_rewrite is not on
+       if ($_config['apache_mod_rewrite'] > 0){
+               //URL are in pretty format, but not in .htaccess RewriteRule format
+               //http://www.atutor.ca/atutor/mantis/view.php?id=3426
+               $page = url_rewrite($_REQUEST['pu'], AT_PRETTY_URL_NOT_HEADER, true);
+       } else {
+               $page = AT_PRETTY_URL_HANDLER.$_REQUEST['pu'];
+       }
+} elseif (!empty($_REQUEST['p'])) {
+       //For search
+       $page = urldecode($_REQUEST['p']);
+} elseif (($_config['pretty_url'] > 0) && preg_match('/bounce.php\?course=([\d]+)$/', $_SERVER['REQUEST_URI'])==1) {
+       //for browse, and my start page url rewrite.    
+       $page = url_rewrite($_SERVER['REQUEST_URI'], AT_PRETTY_URL_NOT_HEADER, true).'/index.php';      //force overwrite
+} else {
+       //handles jump menu
+       if (isset($_POST['jump']) && abs($_POST['course']) > 0){
+               $_SESSION['course_id'] = abs($_POST['course']);
+       }
+       $page = url_rewrite('index.php');
+}
+
+if (substr($page, 0, 1) == '/') {
+       $page = substr($page, 1);
+}
+
+$_SESSION['enroll']            = AT_ENROLL_NO;
+$_SESSION['s_cid']             = 0;
+$_SESSION['privileges'] = 0;
+$_SESSION['is_admin']   = false;
+
+if ($_SESSION['course_id'] == -1) {
+       unset($_SESSION['valid_user']);
+       unset($_SESSION['is_guest']);
+       unset($_SESSION['login']);
+       unset($_SESSION['is_admin']);
+       unset($_SESSION['course_id']);
+}
+
+if (isset($_GET['course'])) {
+       $course = abs($_GET['course']);
+} else if (isset($_POST['course'])) {
+       $course = abs($_POST['course']);
+} else {
+       $course = 0;
+}
+
+if (($course === 0) && $_SESSION['valid_user']) {
+       $_SESSION['course_id']    = 0;
+       $_SESSION['last_updated'] = time()/60 - ONLINE_UPDATE - 1;
+
+       if (defined('AT_ENABLE_CATEGORY_THEMES') && AT_ENABLE_CATEGORY_THEMES) {
+               $th = get_default_theme();
+               $_SESSION['prefs']['PREF_THEME'] = $th['dir_name'];
+       }
+
+       header('Location: users/index.php');
+       exit;
+} else if (($course === 0) && !$_SESSION['valid_user']) { // guests
+       header('Location: '.AT_BASE_HREF.'login.php');
+       exit;
+} else if ($course == -1) {
+       $_SESSION['course_id']    = 0;
+       $_SESSION['last_updated'] = time()/60 - ONLINE_UPDATE - 1;
+
+       if (defined('AT_ENABLE_CATEGORY_THEMES') && AT_ENABLE_CATEGORY_THEMES) {
+               $th = get_default_theme();
+               $_SESSION['prefs']['PREF_THEME'] = $th['dir_name'];
+       }
+
+       header('Location: users/index.php');
+       exit; 
+}
+
+$sql   = "SELECT member_id, content_packaging, cat_id, access, title, UNIX_TIMESTAMP(release_date) AS u_release_date, UNIX_TIMESTAMP(end_date) AS u_end_date FROM ".TABLE_PREFIX."courses WHERE course_id=$course";
+$result = mysql_query($sql,$db);
+if (!$row = mysql_fetch_assoc($result)) {
+       $msg->addError('ITEM_NOT_FOUND');
+       if ($_SESSION['member_id']) {
+               header('Location: '.AT_BASE_HREF.'users/index.php');
+       } else {
+               header('Location: '.AT_BASE_HREF.'login.php');
+       }
+       exit;
+}
+
+if (!$_SESSION['member_id']) {
+       assign_session_prefs(unserialize(stripslashes($_config['pref_defaults'])));
+}
+
+$owner_id = $row['member_id'];
+$_SESSION['packaging'] = $row['content_packaging'];
+
+$_SESSION['groups'] = array();
+unset($_SESSION['fs_owner_type']);
+unset($_SESSION['fs_owner_id']);
+unset($_SESSION['fs_folder_id']);
+
+//check for acl var
+if ($set_to_public) {
+       $row['access'] = "public";
+}
+
+//debug($row); exit;
+switch ($row['access']){
+       case 'public':
+               apply_category_theme($row['cat_id']);
+
+               if (!$_SESSION['valid_user'] && ($row['u_release_date'] < time()) && (!$row['u_end_date'] || $row['u_end_date'] > time())) {
+                       $_SESSION['course_id']    = $course;
+                       /* guest login */
+                       $_SESSION['login']              = 'guest';
+                       $_SESSION['valid_user'] = false;
+                       $_SESSION['member_id']  = 0;
+                       $_SESSION['is_admin']   = false;
+                       $_SESSION['is_guest']   = true;
+       
+                       /* add guest login to counter: */
+                       count_login();
+               } else if (!$_SESSION['valid_user']) {
+                       if ($row['u_release_date'] > time()) {
+                               $msg->addError(array('COURSE_NOT_RELEASED', AT_Date(_AT('announcement_date_format'), $row['u_release_date'], AT_DATE_UNIX_TIMESTAMP)));
+                       } else {
+                               $msg->addError(array('COURSE_ENDED', AT_Date(_AT('announcement_date_format'), $row['u_end_date'], AT_DATE_UNIX_TIMESTAMP)));
+                       }
+                       header('Location: '.AT_BASE_HREF.'browse.php');
+                       exit;
+
+               } else {
+                       $_SESSION['course_id']    = $course;
+                       /* check if we're an admin here */
+                       if ($owner_id == $_SESSION['member_id']) {
+                               $_SESSION['is_admin'] = true;
+                               $_SESSION['enroll']       = AT_ENROLL_YES;
+                       } else {
+                               $_SESSION['is_admin'] = false;
+                       }
+               }
+
+               /* title wont be needed. comes from the cache. */
+               $_SESSION['course_title'] = $row['title'];
+
+               $sql    = "SELECT * FROM ".TABLE_PREFIX."course_enrollment WHERE member_id=$_SESSION[member_id] AND course_id=$course";
+               $result = mysql_query($sql, $db);
+               if ($row2 = mysql_fetch_assoc($result)) {
+                       /* we have requested or are enrolled in this course */
+                       $_SESSION['enroll'] = AT_ENROLL_YES;
+                       $_SESSION['s_cid']  = $row2['last_cid'];
+                       $_SESSION['privileges'] = $row2['privileges'];
+               }
+
+               if (($row['u_release_date'] > time()) && !($_SESSION['is_admin'] || $_SESSION['privileges'])) {
+                       $msg->addError(array('COURSE_NOT_RELEASED', AT_Date(_AT('announcement_date_format'), $row['u_release_date'], AT_DATE_UNIX_TIMESTAMP)));
+                       header('Location: '.AT_BASE_HREF.'bounce.php?course=0');
+                       exit;
+               } else if ($row['u_release_date'] > time()) {
+                       $msg->addInfo(array('COURSE_RELEASE', AT_Date(_AT('announcement_date_format'), $row['u_release_date'], AT_DATE_UNIX_TIMESTAMP)));
+
+               } else if ($row['u_end_date'] && ($row['u_end_date'] < time()) && !($_SESSION['is_admin'] || $_SESSION['privileges'])) {
+                       $msg->addError(array('COURSE_ENDED', AT_Date(_AT('announcement_date_format'), $row['u_end_date'], AT_DATE_UNIX_TIMESTAMP)));
+                       header('Location: '.AT_BASE_HREF.'bounce.php?course=0');
+                       exit;
+               } else if ($row['u_end_date'] && $row['u_end_date'] < time()) {
+                       $msg->addInfo(array('COURSE_ENDED', AT_Date(_AT('announcement_date_format'), $row['u_end_date'], AT_DATE_UNIX_TIMESTAMP)));
+               }
+
+               /* add member login to counter: */
+               if (!$_SESSION['is_admin']) {
+                       count_login();
+               }
+
+               /* update users_online  */
+               add_user_online();
+
+               $_SESSION['groups'] = get_groups($course);
+
+               if ($_GET['f']) {
+                       header('Location: ./'.$page.'?f='.$addslashes($_GET['f']));
+                       exit;
+               } /* else */
+               header('Location: ./'.$page);
+               exit;
+
+               break;
+
+       case 'protected':
+               if (!$_SESSION['valid_user']) {
+                       header('Location: ./login.php?course='.intval($course));
+                       exit;
+               } /* else */
+               /* we're already logged in */
+               $_SESSION['course_id'] = $course;
+
+               apply_category_theme($row['cat_id']);
+
+               /* check if we're an admin here */
+               if ($owner_id == $_SESSION['member_id']) {
+                       $_SESSION['is_admin'] = true;
+                       $_SESSION['enroll']       = AT_ENROLL_YES;
+               } else {
+                       $_SESSION['is_admin'] = false;
+                       /* add member login to counter: */
+                       count_login();
+               }
+
+               $sql    = "SELECT * FROM ".TABLE_PREFIX."course_enrollment WHERE member_id=$_SESSION[member_id] AND course_id=$course";
+               $result = mysql_query($sql, $db);
+               if ($row2 = mysql_fetch_assoc($result)) {
+                       /* we have requested or are enrolled in this course */
+                       $_SESSION['enroll'] = AT_ENROLL_YES;
+                       $_SESSION['s_cid']  = $row2['last_cid'];
+                       $_SESSION['privileges'] = $row2['privileges'];
+               }
+
+               if (($row['u_release_date'] > time()) && !($_SESSION['is_admin'] || $_SESSION['privileges'])) {
+                       $msg->addError(array('COURSE_NOT_RELEASED', AT_Date(_AT('announcement_date_format'), $row['u_release_date'], AT_DATE_UNIX_TIMESTAMP)));
+                       header('Location: '.AT_BASE_HREF.'bounce.php?course=0');
+                       exit;
+               } else if ($row['u_release_date'] > time()) {
+                       $msg->addInfo(array('COURSE_RELEASE', AT_Date(_AT('announcement_date_format'), $row['u_release_date'], AT_DATE_UNIX_TIMESTAMP)));
+
+               } else if ($row['u_end_date'] && ($row['u_end_date'] < time()) && !($_SESSION['is_admin'] || $_SESSION['privileges'])) {
+                       $msg->addError(array('COURSE_ENDED', AT_Date(_AT('announcement_date_format'), $row['u_end_date'], AT_DATE_UNIX_TIMESTAMP)));
+                       header('Location: '.AT_BASE_HREF.'bounce.php?course=0');
+                       exit;
+               } else if ($row['u_end_date'] && $row['u_end_date'] < time()) {
+                       $msg->addInfo(array('COURSE_ENDED', AT_Date(_AT('announcement_date_format'), $row['u_end_date'], AT_DATE_UNIX_TIMESTAMP)));
+               }
+
+
+               $_SESSION['course_title'] = $row['title'];
+
+               /* update users_online  */
+               add_user_online();
+
+               $_SESSION['groups'] = get_groups($course);
+
+               if ($_GET['f']) {
+                       header('Location: ./'.$page.'?f='.$addslashes($_GET['f']));
+                       exit;
+               } /* else */
+               header('Location: ./'.$addslashes($page));
+               exit;
+
+               break;
+
+       case 'private':
+               if (!$_SESSION['valid_user']) {
+                       /* user not logged in: */
+                       header('Location: ./login.php?course='.intval($course));
+                       exit;
+               } /* else */
+
+               if ($owner_id == $_SESSION['member_id']) {
+                       /* we own this course. so we dont have to enroll or get the groups */
+
+                       $_SESSION['is_admin']  = true;
+                       $_SESSION['course_id'] = $course;
+                       $_SESSION['course_title'] = $row['title'];
+                       $_SESSION['enroll']       = AT_ENROLL_YES;
+
+                       $sql    = "SELECT last_cid FROM ".TABLE_PREFIX."course_enrollment WHERE member_id=$_SESSION[member_id] AND course_id=$course";
+                       $result = mysql_query($sql, $db);
+                       $row2 = mysql_fetch_assoc($result);
+
+                       $_SESSION['s_cid']  = $row2['last_cid'];
+
+                       /* update users_online */
+                       add_user_online();
+
+                       apply_category_theme($row['cat_id']);
+
+                       $_SESSION['groups'] = get_groups($course);
+
+                       if (!empty($_GET['f'])) {
+                               header('Location: ./'.$page.'?f='.$addslashes($_GET['f']));
+                               exit;
+                       } /* else */
+                       if ($row['u_release_date'] > time()) {
+                               $msg->addInfo(array('COURSE_RELEASE', AT_Date(_AT('announcement_date_format'), $row['u_release_date'], AT_DATE_UNIX_TIMESTAMP)));
+                       } else if ($row['u_end_date'] && $row['u_end_date'] < time()) {
+                               $msg->addInfo(array('COURSE_ENDED', AT_Date(_AT('announcement_date_format'), $row['u_end_date'], AT_DATE_UNIX_TIMESTAMP)));
+                       }
+                       header('Location: ./'.$addslashes($page));
+                       exit;
+               }
+
+               /* check if we're enrolled */
+               $sql    = "SELECT * FROM ".TABLE_PREFIX."course_enrollment WHERE member_id=$_SESSION[member_id] AND course_id=$course";
+               $result = mysql_query($sql, $db);
+
+               if (!$row2 = mysql_fetch_assoc($result)) {
+                       /* we have not requested enrollment in this course */
+                       $_SESSION['course_id'] = 0;
+                       header('Location: users/private_enroll.php?course='.intval($course));
+                       exit;
+               } /* else */
+
+               if (($row['u_release_date'] > time()) && !($_SESSION['is_admin'] || $_SESSION['privileges'])) {
+                       $msg->addError(array('COURSE_NOT_RELEASED', AT_Date(_AT('announcement_date_format'), $row['u_release_date'], AT_DATE_UNIX_TIMESTAMP)));
+                       header('Location: '.AT_BASE_HREF.'bounce.php?course=0');
+                       exit;
+               } else if ($row['u_release_date'] > time()) {
+                       $msg->addInfo(array('COURSE_RELEASE', AT_Date(_AT('announcement_date_format'), $row['u_release_date'], AT_DATE_UNIX_TIMESTAMP)));
+
+               } else if ($row['u_end_date'] && ($row['u_end_date'] < time()) && !($_SESSION['is_admin'] || $_SESSION['privileges'])) {
+                       $msg->addError(array('COURSE_ENDED', AT_Date(_AT('announcement_date_format'), $row['u_end_date'], AT_DATE_UNIX_TIMESTAMP)));
+                       header('Location: '.AT_BASE_HREF.'bounce.php?course=0');
+                       exit;
+               } else if ($row['u_end_date'] && $row['u_end_date'] < time()) {
+                       $msg->addInfo(array('COURSE_ENDED', AT_Date(_AT('announcement_date_format'), $row['u_end_date'], AT_DATE_UNIX_TIMESTAMP)));
+               }
+               /* we have requested or are enrolled in this course */
+
+               apply_category_theme($row['cat_id']);
+
+               $_SESSION['enroll'] = AT_ENROLL_YES;
+               $_SESSION['s_cid']  = $row2['last_cid'];
+
+               if ($row2['approved'] == 'n') {
+                       /* we have not been approved to enroll in this course */
+                       $_SESSION['course_id'] = 0;
+                       header('Location: users/private_enroll.php?course='.$course);
+                       exit;
+               } /* else */
+
+               /* enrollment has been approved or student is alumni */
+               if ($row2['approved'] == 'a') {
+                       $_SESSION['enroll'] = AT_ENROLL_ALUMNUS;
+               }
+               /* we're already logged in */
+               $_SESSION['course_id'] = $course;
+
+               /* check if we're an admin here */
+               $_SESSION['privileges'] = $row2['privileges'];
+               $_SESSION['course_title'] = $row['title'];
+
+               /* update users_online                  */
+               add_user_online();
+
+               $_SESSION['groups'] = get_groups($course);
+
+               /* add member login to counter: */
+               count_login();
+
+               if($_GET['f']){
+                       header('Location: '.$page.'?f='.$addslashes($_GET['f']));
+                       exit;
+               } /* else */
+               header('Location: '.$addslashes($page));
+               exit;
+       break;
+} // end switch
+
+?>
\ No newline at end of file
diff --git a/browse.php b/browse.php
new file mode 100644 (file)
index 0000000..5caa478
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+$_user_location = 'public';
+
+define('AT_INCLUDE_PATH', 'include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+require(AT_INCLUDE_PATH.'html/browse.inc.php');
+?>
\ No newline at end of file
diff --git a/calendar.js b/calendar.js
new file mode 100644 (file)
index 0000000..e014099
--- /dev/null
@@ -0,0 +1,1750 @@
+// *****************************************************************************
+//      Simple Calendar Widget - Cross-Browser Javascript pop-up calendar.
+//
+//   Copyright (C) 2005-2007  Anthony Garrett
+//
+//   This library is free software; you can redistribute it and/or
+//   modify it under the terms of the GNU Lesser General Public
+//   License as published by the Free Software Foundation; either
+//   version 2.1 of the License, or (at your option) any later version.
+//
+//   This library 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
+//   Lesser General Public License for more details.
+//
+//   You should have received a copy of the GNU Lesser General Public
+//   License along with this library; if not, it is available at
+//   the GNU web site (http://www.gnu.org/) or by writing to the
+//   Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+//   Boston, MA  02110-1301  USA
+//
+// *****************************************************************************
+//
+// Contact:   Sorry, I can't offer support for this but if you find a problem
+//            (or just want to tell me how useful you find it), please send
+//            me an email at scwfeedback@tarrget.info (Note the two Rs in
+//            tarrget).  I will try to fix problems quickly but this is a
+//            spare time thing for me.
+//
+// Credits:   I wrote this from scratch myself but I couldn't have done it
+//            without the superb "JavaScript The Definitive Guide" by David
+//            Flanagan (Pub. O'Reilly ISBN 0-596-00048-0).  I also recognise
+//            a contribution from my experience with PopCalendar 4.1 by
+//            Liming(Victor) Weng.
+//
+// Link back: Please give me credit and link back to my page.  To ensure that
+//            search engines give my page a higher ranking you can add the
+//            following HTML to any indexed page on your web site:
+//
+//            <A HREF="http://www.tarrget.info/calendar/scw.htm">
+//              Simple Calendar Widget by Anthony Garrett
+//            </A>
+//
+// Features:  Easily customised
+//                  (output date format, colours, language, year range and
+//                   week start day)
+//            Accepts a date as input
+//                  (see comments below for formats).
+//            Cross-browser code tested against;
+//                  Internet Explorer 6.0.28     Mozilla  1.7.1
+//                  Opera             7.52+      Firefox  0.9.1+
+//                  Konqueror         3.4.0      Flock    0.4.9
+//
+// How to add the Calendar to your page:
+//            This script needs to be defined for your page so, immediately
+//            after the BODY tag add the following line;
+//
+//                  <script type='Text/JavaScript' src='scw.js'></script>
+//
+//            Your root directory of the web site should also contain an empty
+//            file called "scwblank.html". See
+//                  http://www.tarrget.info/calendar/IEnightmare.html
+//            for a full explanation.
+//
+// How to use the Calendar once it is defined for your page:
+//
+//            Simply choose an event to trigger the calendar (like an onClick
+//            or an onMouseOver) and an element to work on (for the calendar
+//            to take its initial date from and write its output date to) then
+//            write it like this;
+//
+//                  <<event>>="scwShow(<<element>>,event);"
+//
+//            e.g. onClick="scwShow(scwID('myElement'),event);"
+//            or   onMouseOver="scwShow(this,event);"
+//
+//            NOTE: If you wish to use the calendar with an Anchor tag, do
+//                  not use the syntax:   href="javascript:scwShow(...)"
+//                  Instead you should use the following;
+//
+//                  <a href="#" onclick="scwShow(<<element>>,event);return false;">
+//                      <<your text>>
+//                  </a>
+//
+//            If you are using a text node then specify the text's parent node
+//            in the function call. The date should be the only text under that
+//            node;
+//
+//            e.g.  <p onclick="scwShow(this,event);"><<date>></p>
+//
+//            You can also disable days of the week by adding arguments to the
+//            call to scwShow.  The values should be Sunday = 0 through to
+//            Saturday = 6.  A call to scwShow with Friday and Monday disabled
+//            would look something like this;
+//
+//                  scwShow(<<element>>,event,5,1);
+//
+//            Finally you can use the following technique to run a function
+//            when the calendar closes:
+//
+//                  scwNextAction=<<function>>.runsAfterSCW(this,<<arguments>>);
+//                  scwShow(<<element>>,event <<,optional arguments above>>);
+//
+//            Where <<function>> is a function defined on the calling page
+//            and <<arguments>> is the list of arguments being passed to that
+//            function.
+//
+//      No event? No problem!
+//
+//            Normally the calendar will be triggered by an event but if you wish to
+//            control it in code and the event is not available to you, simply pass
+//            an element as the second parameter;
+//
+//            E.G.  scwShow(<<target element>>,<<source element>>);
+//                  as in: scwShow(this,this);
+//
+//            ------------------------------------------------------------------
+//            Here's an extremely trivial but fully functioning example page
+//            showing two of the ways to trigger the calendar;
+//
+//            <html>
+//                <head><title>Basic Example</title></head>
+//                <body>
+//                    <script type='text/JavaScript' src='scw.js'></script>
+//                    <p onclick='scwShow(this,event);'>06-Dec-2006</p>
+//                    <input onclick='scwShow(this,event);' value='07-Dec-2006' />
+//                    <br/><br/>
+//                    <a href='#' onclick='scwShow(this,event);return false;'>
+//                        08-Dec-2006
+//                    </a>
+//                </body>
+//            </html>
+//
+// *****************************************************************************
+//
+// See http://www.tarrget.info/calendar/scw.htm for a complete version history
+//
+// Version   Date        By               Description
+// =======   ====        ===============  ===========
+//   3.58    2007-04-04  Anthony Garrett  Resolved an error caused when the date
+//                                         range does not include the current year.
+//                                         Thanks to Steve Davis for letting me know.
+//
+//                                        Fixed "Today" selector display which
+//                                         was incorrectly visible when year range
+//                                         ended last year. (Also the result of
+//                                         investigations based on Steve Davis'
+//                                         feedback).
+//
+//   3.59    2007-06-13  Anthony Garrett  Added Verdana to font list of
+//                                         calendar's CSS.  Resolves rendering
+//                                         bug in Safari Beta 3 for Windows.
+//
+//   3.60    2007-07-31  Anthony Garrett  Fixed javascript error that occurred
+//                                         when the target element had no value
+//                                         attribute.  The error had no impact
+//                                         on the behaviour of the script.  Thanks
+//                                         to John Phelps for reporting this bug.
+//
+//   3.70    2007-09-21  Anthony Garrett  Updated the event trapping to make it
+//                                         less intrusive on the page body.
+//                                         NOTE: This requires that a calendar's
+//                                         second parameter should be the calling
+//                                         event (not the calling object as in
+//                                         previous versions).
+//                                         Thanks to Steve Davis for the bug report
+//                                         that led to this change.
+//
+//                                        Fixed a bug that caused undelimited
+//                                         dates to be handled incorrectly. They
+//                                         are now parsed against the full date
+//                                         output format then checked for validity.
+//                                         Thanks to Dan Wood for raising this bug.
+//
+//                                        Replaced the date input sequence user
+//                                         configuration setting with parsing the
+//                                         sequence from the full format. New users
+//                                         are often confused by the sequence and
+//                                         in practice (to allow the calendar's date
+//                                         output to be used for input) the sequence
+//                                         must always match the full format element
+//                                         order.
+//
+//                                        Extended IFRAME backing to all calendar objects
+//                                         in order to improve calendar display over
+//                                         some embedded applets and objects.  Thanks to
+//                                         Stanko Kupcevic for his feedback on this.
+//                                         NOTE: It is not possible to protect any
+//                                         JavaScript object displayed over an
+//                                         embedded DYNAMIC (and, therefore refreshed)
+//                                         object because browsers usually do not
+//                                         directly control the screen handling within
+//                                         the object.  The best advice therefore remains
+//                                         to design pages in such a way that the calendar
+//                                         does not overlap embedded objects.
+//
+//  3.71     2008-12-14  Anthony Garrett  Restored the ability to use an element
+//                                         as the second parameter when opening a
+//                                         calendar while retaining the option
+//                                         of passing an event. Thanks to Thierry Blind
+//                                         and Sergey Snovsky for the feedback.
+//
+// *****************************************************************************
+
+// ************************************
+// Start of Simple Calendar Widget Code
+// ************************************
+
+// This date is used throughout to determine today's date.
+
+    var scwDateNow = new Date(Date.parse(new Date().toDateString()));
+
+//******************************************************************************
+//------------------------------------------------------------------------------
+// Customisation section
+//------------------------------------------------------------------------------
+//******************************************************************************
+
+    // Set the bounds for the calendar here...
+    // If you want the year to roll forward you can use something like this...
+    //      var scwBaseYear = scwDateNow.getFullYear()-5;
+    // alternatively, hard code a date like this...
+    //      var scwBaseYear = 1990;
+
+    var scwBaseYear        = scwDateNow.getFullYear()-10;
+
+    // How many years do want to be valid and to show in the drop-down list?
+
+    var scwDropDownYears   = 20;
+
+    // All language-dependent changes can be made here...
+
+    // If you wish to work in a single language (other than English) then
+    // just replace the English (in the function scwSetLanguage below) with
+    // your own text.
+
+    // Using multiple languages:
+    // In order to keep this script to a resonable size I have not included
+    // languages here.  You can set language fields in a function that you
+    // should call  scwSetLanguage  the script will use your languages.
+    // I have included all the translations that have been sent to me in
+    // such a function on the demonstration page.
+
+    var scwLanguage;
+
+    function scwSetDefaultLanguage()
+        {try
+            {scwSetLanguage();}
+         catch (exception)
+            {// English
+             scwToday               = 'Today:';
+             scwDrag                = 'click here to drag';
+             scwArrMonthNames       = ['Jan','Feb','Mar','Apr','May','Jun',
+                                       'Jul','Aug','Sep','Oct','Nov','Dec'];
+             scwArrWeekInits        = ['S','M','T','W','T','F','S'];
+             scwInvalidDateMsg      = 'The entered date is invalid.\n';
+             scwOutOfRangeMsg       = 'The entered date is out of range.';
+             scwDoesNotExistMsg     = 'The entered date does not exist.';
+             scwInvalidAlert        = ['Invalid date (',') ignored.'];
+             scwDateDisablingError  = ['Error ',' is not a Date object.'];
+             scwRangeDisablingError = ['Error ',
+                                       ' should consist of two elements.'];
+            }
+        };
+
+    // Note:  Always start the scwArrWeekInits array with your string for
+    //        Sunday whatever scwWeekStart (below) is set to.
+
+    // scwWeekStart determines the start of the week in the display
+    // Set it to: 0 (Zero) for Sunday, 1 (One) for Monday etc..
+
+    var scwWeekStart       =    1;
+
+    // The week start day for the display is taken as the week start
+    // for week numbering.  This ensures that only one week number
+    // applies to one line of the calendar table.
+    // [ISO 8601 begins the week with Day 1 = Monday.]
+
+    // If you want to see week numbering on the calendar, set
+    // this to true.  If not, false.
+
+    var scwWeekNumberDisplay    = false;
+
+    // Week numbering rules are generally based on a day in the week
+    // that determines the first week of the year.  ISO 8601 uses
+    // Thursday (day four when Sunday is day zero).  You can alter
+    // the base day here.
+
+    // See http://www.cl.cam.ac.uk/~mgk25/iso-time.html for more information
+
+    var scwWeekNumberBaseDay    = 4;
+
+    // Each of the calendar's alert message types can be disabled
+    // independently here.
+
+    var scwShowInvalidDateMsg       = true,
+        scwShowOutOfRangeMsg        = true,
+        scwShowDoesNotExistMsg      = true,
+        scwShowInvalidAlert         = true,
+        scwShowDateDisablingError   = true,
+        scwShowRangeDisablingError  = true;
+
+    // Set the allowed input date delimiters here...
+    // E.g. To set the rising slash, hyphen, full-stop (aka stop or point),
+    //      comma and space as delimiters use
+    //              var scwArrDelimiters   = ['/','-','.',',',' '];
+
+    var scwArrDelimiters   = ['/','-','.',',',' '];
+
+    // Set the format for the displayed 'Today' date and for the output
+    // date here.
+    //
+    // The format is described using delimiters of your choice (as set
+    // in scwArrDelimiters above) and case insensitive letters D, M and Y.
+    //
+    // NOTE: If no delimiters are input then the date output format is used
+    //       to parse the value.  This allows less flexiblility in the input
+    //       value than using delimiters but an accurately entered date
+    //       remains parsable.
+    //
+    // Definition               Returns
+    // ----------               -------
+    // D            date in the month without zero filling
+    // DD           date in the month left zero filled
+    // M            month number without zero filling
+    // MM           month number left zero filled
+    // MMM          month string from scwArrMonthNames
+    // YY           year number in two digits
+    // YYYY         year number in four digits
+
+    // Displayed "Today" date format
+
+    //var scwDateDisplayFormat = 'dd-mm-yy';     // e.g. 'MMM-DD-YYYY' for the US
+    var scwDateDisplayFormat = 'dd/mmm/yyyy';     // e.g. 'MMM-DD-YYYY' for the US
+
+    // Output date format
+
+    //var scwDateOutputFormat  = 'DD MMM, YYYY'; // e.g. 'MMM-DD-YYYY' for the US
+    //var scwDateOutputFormat  = 'DD-MMM-YYYY'; // e.g. 'MMM-DD-YYYY' for the US
+    var scwDateOutputFormat  = 'YYYY-MM-DD'; // e.g. 'MMM-DD-YYYY' for the US
+
+    // Note: The delimiters used should be in scwArrDelimiters.
+
+    // scwZindex controls how the pop-up calendar interacts with the rest
+    // of the page.  It is usually adequate to leave it as 1 (One) but I
+    // have made it available here to help anyone who needs to alter the
+    // level in order to ensure that the calendar displays correctly in
+    // relation to all other elements on the page.
+
+    var scwZindex          = 1;
+
+    // Personally I like the fact that entering 31-Sep-2005 displays
+    // 1-Oct-2005, however you may want that to be an error.  If so,
+    // set scwBlnStrict = true.  That will cause an error message to
+    // display and the selected month is displayed without a selected
+    // day. Thanks to Brad Allan for his feedback prompting this feature.
+
+    var scwBlnStrict       = false;
+
+    // If you wish to disable any displayed day, e.g. Every Monday,
+    // you can do it by setting the following array.  The array elements
+    // match the displayed cells.
+    //
+    // You could put something like the following in your calling page
+    // to disable all weekend days;
+    //
+    //  for (var i=0;i<scwEnabledDay.length;i++)
+    //      {if (i%7%6==0) scwEnabledDay[i] = false;}
+    //
+    // The above approach will allow you to disable days of the week
+    // for the whole of your page easily.  If you need to set different
+    // disabled days for a number of date input fields on your page
+    // there is an easier way: You can pass additional arguments to
+    // scwShow. The syntax is described at the top of this script in
+    // the section:
+    //    "How to use the Calendar once it is defined for your page:"
+    //
+    // It is possible to use these two approaches in combination.
+
+    var scwEnabledDay      = [true, true, true, true, true, true, true,
+                              true, true, true, true, true, true, true,
+                              true, true, true, true, true, true, true,
+                              true, true, true, true, true, true, true,
+                              true, true, true, true, true, true, true,
+                              true, true, true, true, true, true, true];
+
+    // You can disable any specific date (e.g. 24-Jan-2006 or Today) by
+    // creating an element of the array scwDisabledDates as a date object
+    // with the value you want to disable.  Date ranges can be disabled
+    // by placing an array of two values (Start and End) into an element
+    // of this array.
+
+    var scwDisabledDates   = new Array();
+
+    // e.g. To disable 10-Dec-2005:
+    //          scwDisabledDates[0] = new Date(2005,11,10);
+    //
+    //      or a range from 2004-Dec-25 to 2005-Jan-01:
+    //          scwDisabledDates[1] = [new Date(2004,11,25),new Date(2005,0,1)];
+    //
+    // Remember that Javascript months are Zero-based.
+
+    // The disabling by date and date range does prevent the current day
+    // from being selected.  Disabling days of the week does not so you can set
+    // the scwActiveToday value to false to prevent selection.
+
+    var scwActiveToday = true;
+
+    // Dates that are out of the displayed month are shown at the start
+    // (unless the month starts on the first day of the week) and end of each
+    // month.
+    //
+    // Set scwOutOfMonthDisable to  true  to disable these dates (or  false
+    // to allow their selection).
+    //
+    // Set scwOutOfMonthHide    to  true  to hide    these dates (or  false
+    // to make them visible).
+
+    var scwOutOfMonthDisable = false;
+    var scwOutOfMonthHide    = false;
+
+    // Dates that are out of the specified range can be displayed at the start
+    // of the very first month and end of the very last.  Set
+    // scwOutOfRangeDisable to  true  to disable these dates (or  false  to
+    // allow their selection).
+
+    var scwOutOfRangeDisable = true;
+
+    // If you want a special format for the cell that contains the current day
+    // set this to true.  This sets a thin border around the cell in the colour
+    // set by scwTodayCellBorderColour.
+
+    var scwFormatTodayCell = true;
+    var scwTodayCellBorderColour = 'red';
+
+    // You can allow the calendar to be dragged around the screen by
+    // using the setting scwAllowDrag to true.
+    // I can't say I recommend it because of the danger of the user
+    // forgetting which date field the calendar will update when there
+    // are multiple date fields on a page.
+
+    var scwAllowDrag = false;
+
+    // Closing the calendar by clicking on it (rather than elsewhere on the
+    // main page) can be inconvenient.  The scwClickToHide boolean value
+    // controls this feature.
+
+    var scwClickToHide = false;
+
+    // I have made every effort to isolate the pop-up script from any
+    // CSS defined on the main page but if you have anything set that
+    // affects the pop-up (or you may want to change the way it looks)
+    // then you can address it in the following style sheets.
+
+    document.writeln(
+        '<style type="text/css">'                                       +
+            '.scw           {padding:1px;vertical-align:middle;}'       +
+            'iframe.scw     {position:absolute;z-index:' + scwZindex    +
+                            ';top:0px;left:0px;visibility:hidden;'      +
+                            'width:1px;height:1px;}'                    +
+            'table.scw      {padding:0px;visibility:hidden;'            +
+                            'position:absolute;cursor:default;'         +
+                            'width:200px;top:0px;left:0px;'             +
+                            'z-index:' + (scwZindex+1)                  +
+                            ';text-align:center;}'                      +
+        '</style>'  );
+
+    // This style sheet can be extracted from the script and edited into regular
+    // CSS (by removing all occurrences of + and '). That can be used as the
+    // basis for themes. Classes are described in comments within the style
+    // sheet.
+
+    document.writeln(
+        '<style type="text/css">'                                       +
+            '/* IMPORTANT:  The SCW calendar script requires all '      +
+            '               the classes defined here.'                  +
+            '*/'                                                        +
+            'table.scw      {padding:       1px;'                       +
+                            'vertical-align:middle;'                    +
+                            'border:        ridge 2px;'                 +
+                            'font-size:     10pt;'                      +
+                            'font-family:   ' +
+                                   'Verdana,Arial,Helvetica,Sans-Serif;'+
+                            'font-weight:   bold;}'                     +
+            'td.scwDrag,'                                               +
+            'td.scwHead                 {padding:       0px 0px;'       +
+                                        'text-align:    center;}'       +
+            'td.scwDrag                 {font-size:     8pt;}'          +
+            'select.scwHead             {margin:        3px 1px;'       +
+                                        'text-align:    center;}'       +
+            'input.scwHead              {height:        22px;'          +
+                                        'width:         22px;'          +
+                                        'vertical-align:middle;'        +
+                                        'text-align:    center;'        +
+                                        'margin:        2px 1px;'       +
+                                        'font-weight:   bold;'          +
+                                        'font-size:     10pt;'          +
+                                        'font-family:   fixedSys;}'     +
+            'td.scwWeekNumberHead,'                                     +
+            'td.scwWeek                 {padding:       0px;'           +
+                                        'text-align:    center;'        +
+                                        'font-weight:   bold;}'         +
+            'td.scwFoot,'                                               +
+            'td.scwFootHover,'                                          +
+            'td.scwFoot:hover,'                                         +
+            'td.scwFootDisabled         {padding:       0px;'           +
+                                        'text-align:    center;'        +
+                                        'font-weight:   normal;}'       +
+            'table.scwCells             {text-align:    right;'         +
+                                        'font-size:     8pt;'           +
+                                        'width:         96%;}'          +
+            'td.scwCells,'                  +
+            'td.scwCellsHover,'             +
+            'td.scwCells:hover,'            +
+            'td.scwCellsDisabled,'          +
+            'td.scwCellsExMonth,'           +
+            'td.scwCellsExMonthHover,'      +
+            'td.scwCellsExMonth:hover,'     +
+            'td.scwCellsExMonthDisabled,'   +
+            'td.scwCellsWeekend,'           +
+            'td.scwCellsWeekendHover,'      +
+            'td.scwCellsWeekend:hover,'     +
+            'td.scwCellsWeekendDisabled,'   +
+            'td.scwInputDate,'              +
+            'td.scwInputDateHover,'         +
+            'td.scwInputDate:hover,'        +
+            'td.scwInputDateDisabled,'      +
+            'td.scwWeekNo,'                 +
+            'td.scwWeeks                {padding:           3px;'       +
+                                        'width:             16px;'      +
+                                        'height:            16px;'      +
+                                        'border-width:      1px;'       +
+                                        'border-style:      solid;'     +
+                                        'font-weight:       bold;'      +
+                                        'vertical-align:    middle;}'   +
+            '/* Blend the colours into your page here...    */'         +
+            '/* Calendar background */'                                 +
+            'table.scw                  {background-color:  #CCCCCC;}'  +
+            '/* Drag Handle */'                                         +
+            'td.scwDrag                 {background-color:  #9999CC;'   +
+                                        'color:             #CCCCFF;}'  +
+            '/* Week number heading */'                                 +
+            'td.scwWeekNumberHead       {color:             #6666CC;}'  +
+            '/* Week day headings */'                                   +
+            'td.scwWeek                 {color:             #CCCCCC;}'  +
+            '/* Week numbers */'                                        +
+            'td.scwWeekNo               {background-color:  #776677;'   +
+                                        'color:             #CCCCCC;}'  +
+            '/* Enabled Days */'                                        +
+            '/* Week Day */'                                            +
+            'td.scwCells                {background-color:  #CCCCCC;'   +
+                                        'color:             #000000;}'  +
+            '/* Day matching the input date */'                         +
+            'td.scwInputDate            {background-color:  #CC9999;'   +
+                                        'color:             #FF0000;}'  +
+            '/* Weekend Day */'                                         +
+            'td.scwCellsWeekend         {background-color:  #CCCCCC;'   +
+                                        'color:             #CC6666;}'  +
+            '/* Day outside the current month */'                       +
+            'td.scwCellsExMonth         {background-color:  #CCCCCC;'   +
+                                        'color:             #666666;}'  +
+            '/* Today selector */'                                      +
+            'td.scwFoot                 {background-color:  #6666CC;'   +
+                                        'color:             #FFFFFF;}'  +
+            '/* MouseOver/Hover formatting '                            +
+            '       If you want to "turn off" any of the formatting '   +
+            '       then just set to the same as the standard format'   +
+            '       above.'                                             +
+            ' '                                                         +
+            '       Note: The reason that the following are'            +
+            '       implemented using both a class and a :hover'        +
+            '       pseudoclass is because Opera handles the rendering' +
+            '       involved in the class swap very poorly and IE6 '    +
+            '       (and below) only implements pseudoclasses on the'   +
+            '       anchor tag.'                                        +
+            '*/'                                                        +
+            '/* Active cells */'                                        +
+            'td.scwCells:hover,'                                        +
+            'td.scwCellsHover           {background-color:  #FFFF00;'   +
+                                        'cursor:            pointer;'   +
+                                        'color:             #000000;}'  +
+            '/* Day matching the input date */'                         +
+            'td.scwInputDate:hover,'                                    +
+            'td.scwInputDateHover       {background-color:  #FFFF00;'   +
+                                        'cursor:            pointer;'   +
+                                        'color:             #000000;}'  +
+            '/* Weekend cells */'                                       +
+            'td.scwCellsWeekend:hover,'                                 +
+            'td.scwCellsWeekendHover    {background-color:  #FFFF00;'   +
+                                        'cursor:            pointer;'   +
+                                        'color:             #000000;}'  +
+            '/* Day outside the current month */'                       +
+            'td.scwCellsExMonth:hover,'                                 +
+            'td.scwCellsExMonthHover    {background-color:  #FFFF00;'   +
+                                        'cursor:            pointer;'   +
+                                        'color:             #000000;}'  +
+            '/* Today selector */'                                      +
+            'td.scwFoot:hover,'                                         +
+            'td.scwFootHover            {color:             #FFFF00;'   +
+                                        'cursor:            pointer;'   +
+                                        'font-weight:       bold;}'     +
+            '/* Disabled cells */'                                      +
+            '/* Week Day */'                                            +
+            '/* Day matching the input date */'                         +
+            'td.scwInputDateDisabled    {background-color:  #999999;'   +
+                                        'color:             #000000;}'  +
+            'td.scwCellsDisabled        {background-color:  #999999;'   +
+                                        'color:             #000000;}'  +
+            '/* Weekend Day */'                                         +
+            'td.scwCellsWeekendDisabled {background-color:  #999999;'   +
+                                        'color:             #CC6666;}'  +
+            '/* Day outside the current month */'                       +
+            'td.scwCellsExMonthDisabled {background-color:  #999999;'   +
+                                        'color:             #666666;}'  +
+            'td.scwFootDisabled         {background-color:  #6666CC;'   +
+                                        'color:             #FFFFFF;}'  +
+        '</style>'
+                    );
+
+//******************************************************************************
+//------------------------------------------------------------------------------
+// End of customisation section
+//------------------------------------------------------------------------------
+//******************************************************************************
+
+//  Variables required by both scwShow and scwShowMonth
+
+    var scwTargetEle,
+        scwTriggerEle,
+        scwMonthSum            = 0,
+        scwBlnFullInputDate    = false,
+        scwPassEnabledDay      = new Array(),
+        scwSeedDate            = new Date(),
+        scwParmActiveToday     = true,
+        scwWeekStart           = scwWeekStart%7,
+        scwToday,
+        scwDrag,
+        scwArrMonthNames,
+        scwArrWeekInits,
+        scwInvalidDateMsg,
+        scwOutOfRangeMsg,
+        scwDoesNotExistMsg,
+        scwInvalidAlert,
+        scwDateDisablingError,
+        scwRangeDisablingError;
+
+    // Add a method to format a date into the required pattern
+
+    Date.prototype.scwFormat =
+        function(scwFormat)
+            {var charCount = 0,
+                 codeChar  = '',
+                 result    = '';
+
+             for (var i=0;i<=scwFormat.length;i++)
+                {if (i<scwFormat.length && scwFormat.charAt(i)==codeChar)
+                        {// If we haven't hit the end of the string and
+                         // the format string character is the same as
+                         // the previous one, just clock up one to the
+                         // length of the current element definition
+                         charCount++;
+                        }
+                 else   {switch (codeChar)
+                            {case 'y': case 'Y':
+                                result += (this.getFullYear()%Math.
+                                            pow(10,charCount)).toString().
+                                            scwPadLeft(charCount);
+                                break;
+                             case 'm': case 'M':
+                                // If we find an M, check the number of them to
+                                // determine whether to get the month number or
+                                // the month name.
+                                result += (charCount<3)
+                                            ?(this.getMonth()+1).
+                                                toString().scwPadLeft(charCount)
+                                            :scwArrMonthNames[this.getMonth()];
+                                break;
+                             case 'd': case 'D':
+                                // If we find a D, get the date and format it
+                                result += this.getDate().toString().
+                                            scwPadLeft(charCount);
+                                break;
+                             default:
+                                // Copy any unrecognised characters across
+                                while (charCount-- > 0) {result += codeChar;}
+                            }
+
+                         if (i<scwFormat.length)
+                            {// Store the character we have just worked on
+                             codeChar  = scwFormat.charAt(i);
+                             charCount = 1;
+                            }
+                        }
+                }
+             return result;
+            };
+
+    // Add a method to left pad zeroes
+
+    String.prototype.scwPadLeft =
+        function(padToLength)
+            {var result = '';
+             for (var i=0;i<(padToLength - this.length);i++) {result += '0';}
+             return (result + this);
+            };
+
+    // Set up a closure so that any next function can be triggered
+    // after the calendar has been closed AND that function can take
+    // arguments.
+
+    Function.prototype.runsAfterSCW =
+        function()  {var func = this,
+                         args = new Array(arguments.length);
+
+                     for (var i=0;i<args.length;++i) {args[i] = arguments[i];}
+
+                     return function()
+                        {// concat/join the two argument arrays
+                         for (var i=0;i<arguments.length;++i) {args[args.length] = arguments[i];}
+                         return (args.shift()==scwTriggerEle)?func.apply(this, args):null;
+                        };
+                    };
+
+    // Set up some shortcuts
+
+    function scwID(id)  {return document.getElementById(id);};
+
+    // Use a global variable for the return value from the next action
+    // IE fails to pass the function through if the target element is in
+    // a form and scwNextAction is not defined.
+
+    var scwNextActionReturn, scwNextAction;
+
+// ****************************************************************************
+// Start of Function Library
+//
+//  Exposed functions:
+//
+//      scwShow             Entry point for display of calendar,
+//                              called in main page.
+//      showCal             Legacy name of scwShow:
+//                              Passes only legacy arguments,
+//                              not the optional day disabling arguments.
+//
+//      scwShowMonth        Displays a month on the calendar,
+//                              Called when a month is set or changed.
+//
+//      scwBeginDrag        Controls calendar dragging.
+//
+//      scwCancel           Called when the calendar background is clicked:
+//                              Calls scwStopPropagation and may call scwHide.
+//      scwHide             Hides the calendar, called on various events.
+//      scwStopPropagation  Stops the propagation of an event.
+//
+// ****************************************************************************
+
+    function showCal(scwEle,scwSource) {scwShow(scwEle,scwSource);};
+    function scwShow(scwEle,scwSource)
+        {if (!scwSource) {scwSource = window.event;}
+
+         if (scwSource.tagName) // Second parameter isn't an event it's an element
+            {var scwSourceEle = scwSource;
+
+             if (scwID('scwIE'))  {window.event.cancelBubble = true;}
+             else {scwSourceEle.parentNode.addEventListener('click',scwStopPropagation,false);}
+            }
+         else   // Second parameter is an event
+            {var scwSourceEle = (scwSource.target)
+                                    ?scwSource.target
+                                    :scwSource.srcElement;
+
+             // Stop the click event that opens the calendar from bubbling up to
+             // the document-level event handler that hides it!
+             if (scwSource.stopPropagation) {scwSource.stopPropagation();}
+             else                           {scwSource.cancelBubble = true;}
+            }
+
+         scwTriggerEle = scwSourceEle;
+
+         // Take any parameters that there might be from the third onwards as
+         // day numbers to be disabled 0 = Sunday through to 6 = Saturday.
+
+         scwParmActiveToday = true;
+
+         for (var i=0;i<7;i++)
+            {scwPassEnabledDay[(i+7-scwWeekStart)%7] = true;
+             for (var j=2;j<arguments.length;j++)
+                {if (arguments[j]==i)
+                    {scwPassEnabledDay[(i+7-scwWeekStart)%7] = false;
+                     if (scwDateNow.getDay()==i) {scwParmActiveToday = false;}
+                    }
+                }
+            }
+
+         //   If no value is preset then the seed date is
+         //      Today (when today is in range) OR
+         //      The middle of the date range.
+
+         scwSeedDate = scwDateNow;
+
+         // Find the date and Strip space characters from start and
+         // end of date input.
+
+         var scwDateValue = '';
+
+         if (scwEle.value) {scwDateValue = scwEle.value.replace(/^\s+/,'').replace(/\s+$/,'');}
+         else   {if (typeof scwEle.value == 'undefined')
+                    {var scwChildNodes = scwEle.childNodes;
+                     for (var i=0;i<scwChildNodes.length;i++)
+                        {if (scwChildNodes[i].nodeType == 3)
+                            {scwDateValue = scwChildNodes[i].nodeValue.replace(/^\s+/,'').replace(/\s+$/,'');
+                             if (scwDateValue.length > 0)
+                                {scwTriggerEle.scwTextNode = scwChildNodes[i];
+                                 scwTriggerEle.scwLength   = scwChildNodes[i].nodeValue.length;
+                                 break;
+                                }
+                            }
+                        }
+                    }
+                }
+
+         // Set the language-dependent elements
+
+         scwSetDefaultLanguage();
+
+         scwID('scwDragText').innerHTML = scwDrag;
+
+         scwID('scwMonths').options.length = 0;
+         for (var i=0;i<scwArrMonthNames.length;i++)
+            {scwID('scwMonths').options[i] = new Option(scwArrMonthNames[i],scwArrMonthNames[i]);}
+
+         scwID('scwYears').options.length = 0;
+         for (var i=0;i<scwDropDownYears;i++)
+            {scwID('scwYears').options[i] =  new Option((scwBaseYear+i),(scwBaseYear+i));}
+
+         for (var i=0;i<scwArrWeekInits.length;i++)
+            {scwID('scwWeekInit' + i).innerHTML = scwArrWeekInits[(i+scwWeekStart)%scwArrWeekInits.length];}
+
+         if (scwID('scwFoot'))
+            {scwID('scwFoot').innerHTML = scwToday + ' ' + scwDateNow.scwFormat(scwDateDisplayFormat);}
+
+         if (scwDateValue.length==0)
+            {// If no value is entered and today is within the range,
+             // use today's date, otherwise use the middle of the valid range.
+
+             scwBlnFullInputDate=false;
+
+             if ((new Date(scwBaseYear+scwDropDownYears,0,0))<scwSeedDate ||
+                 (new Date(scwBaseYear,0,1))                 >scwSeedDate
+                )
+                {scwSeedDate = new Date(scwBaseYear + Math.floor(scwDropDownYears / 2), 5, 1);}
+            }
+         else
+            {function scwInputFormat()
+                {var scwArrSeed = new Array(),
+                     scwArrInput = scwDateValue.split(new RegExp('[\\'+scwArrDelimiters.join('\\')+']+','g'));
+
+                 // "Escape" all the user defined date delimiters above -
+                 // several delimiters will need it and it does no harm for
+                 // the others.
+
+                 // Strip any empty array elements (caused by delimiters)
+                 // from the beginning or end of the array. They will
+                 // still appear in the output string if in the output
+                 // format.
+
+                 if (scwArrInput[0]!=null)
+                    {if (scwArrInput[0].length==0)                      {scwArrInput.splice(0,1);}
+                     if (scwArrInput[scwArrInput.length-1].length==0)   {scwArrInput.splice(scwArrInput.length-1,1);}
+                    }
+
+                 scwBlnFullInputDate = false;
+
+                 scwDateOutputFormat = scwDateOutputFormat.toUpperCase();
+
+                 // List all the allowed letters in the date format
+                 var template = ['D','M','Y'];
+
+                 // Prepare the sequence of date input elements
+                 var result = new Array();
+
+                 for (var i=0;i<template.length;i++)
+                    {if (scwDateOutputFormat.search(template[i])>-1)
+                        {result[scwDateOutputFormat.search(template[i])] = template[i];}
+                    }
+
+                 var scwDateSequence = result.join('');
+
+                 // Separate the elements of the date input
+                 switch (scwArrInput.length)
+                    {case 1:
+                        {if (scwDateOutputFormat.indexOf('Y')>-1 &&
+                             scwArrInput[0].length>scwDateOutputFormat.lastIndexOf('Y'))
+                            {scwArrSeed[0] = parseInt(scwArrInput[0].substring(scwDateOutputFormat.indexOf('Y'),
+                                                                               scwDateOutputFormat.lastIndexOf('Y')+1),10);
+                            }
+                         else   {scwArrSeed[0] = 0;}
+
+                         if (scwDateOutputFormat.indexOf('M')>-1 &&
+                             scwArrInput[0].length>scwDateOutputFormat.lastIndexOf('M'))
+                            {scwArrSeed[1] = scwArrInput[0].substring(scwDateOutputFormat.indexOf('M'),
+                                                                      scwDateOutputFormat.lastIndexOf('M')+1);
+                            }
+                         else   {scwArrSeed[1] = '6';}
+
+                         if (scwDateOutputFormat.indexOf('D')>-1 &&
+                             scwArrInput[0].length>scwDateOutputFormat.lastIndexOf('D'))
+                            {scwArrSeed[2] = parseInt(scwArrInput[0].substring(scwDateOutputFormat.indexOf('D'),
+                                                                               scwDateOutputFormat.lastIndexOf('D')+1),10);
+                            }
+                         else   {scwArrSeed[2] = 1;}
+
+                         if (scwArrInput[0].length==scwDateOutputFormat.length) {scwBlnFullInputDate = true;}
+                         break;
+                        }
+                     case 2:
+                        {// Year and Month entry
+                         scwArrSeed[0] =
+                             parseInt(scwArrInput[scwDateSequence.
+                                                    replace(/D/i,'').
+                                                    search(/Y/i)],10);  // Year
+                         scwArrSeed[1] = scwArrInput[scwDateSequence.
+                                                    replace(/D/i,'').
+                                                    search(/M/i)];      // Month
+                         scwArrSeed[2] = 1;                             // Day
+                         break;
+                        }
+                     case 3:
+                        {// Day Month and Year entry
+
+                         scwArrSeed[0] =
+                             parseInt(scwArrInput[scwDateSequence.
+                                                    search(/Y/i)],10);  // Year
+                         scwArrSeed[1] = scwArrInput[scwDateSequence.
+                                                    search(/M/i)];      // Month
+                         scwArrSeed[2] =
+                             parseInt(scwArrInput[scwDateSequence.
+                                                    search(/D/i)],10);  // Day
+
+                         scwBlnFullInputDate = true;
+                         break;
+                        }
+                     default:
+                        {// A stuff-up has led to more than three elements in
+                         // the date.
+                         scwArrSeed[0] = 0;     // Year
+                         scwArrSeed[1] = 0;     // Month
+                         scwArrSeed[2] = 0;     // Day
+                        }
+                    }
+
+                 // These regular expressions validate the input date format
+                 // to the following rules;
+                 //         Day   1-31 (optional zero on single digits)
+                 //         Month 1-12 (optional zero on single digits)
+                 //                     or case insensitive name
+                 //         Year  One, Two or four digits
+
+                 // Months names are as set in the language-dependent
+                 // definitions and delimiters are set just below there
+
+                 var scwExpValDay    = new RegExp('^(0?[1-9]|[1-2][0-9]|3[0-1])$'),
+                     scwExpValMonth  = new RegExp('^(0?[1-9]|1[0-2]|'        +
+                                                  scwArrMonthNames.join('|') +
+                                                  ')$','i'),
+                     scwExpValYear   = new RegExp('^([0-9]{1,2}|[0-9]{4})$');
+
+                 // Apply validation and report failures
+
+                 if (scwExpValYear.exec(scwArrSeed[0])  == null ||
+                     scwExpValMonth.exec(scwArrSeed[1]) == null ||
+                     scwExpValDay.exec(scwArrSeed[2])   == null
+                    )
+                    {if (scwShowInvalidDateMsg)
+                        {alert(scwInvalidDateMsg  +
+                               scwInvalidAlert[0] + scwDateValue +
+                               scwInvalidAlert[1]);}
+                     scwBlnFullInputDate = false;
+                     scwArrSeed[0] = scwBaseYear +
+                                     Math.floor(scwDropDownYears/2); // Year
+                     scwArrSeed[1] = '6';                            // Month
+                     scwArrSeed[2] = 1;                              // Day
+                    }
+
+                 // Return the  Year    in scwArrSeed[0]
+                 //             Month   in scwArrSeed[1]
+                 //             Day     in scwArrSeed[2]
+
+                 return scwArrSeed;
+                };
+
+             // Parse the string into an array using the allowed delimiters
+
+             scwArrSeedDate = scwInputFormat();
+
+             // So now we have the Year, Month and Day in an array.
+
+             //   If the year is one or two digits then the routine assumes a
+             //   year belongs in the 21st Century unless it is less than 50
+             //   in which case it assumes the 20th Century is intended.
+
+             if (scwArrSeedDate[0]<100) {scwArrSeedDate[0] += (scwArrSeedDate[0]>50)?1900:2000;}
+
+             // Check whether the month is in digits or an abbreviation
+
+             if (scwArrSeedDate[1].search(/\d+/)!=0)
+                {month = scwArrMonthNames.join('|').toUpperCase().
+                            search(scwArrSeedDate[1].substr(0,3).
+                                                    toUpperCase());
+                 scwArrSeedDate[1] = Math.floor(month/4)+1;
+                }
+
+             scwSeedDate = new Date(scwArrSeedDate[0],scwArrSeedDate[1]-1,scwArrSeedDate[2]);
+            }
+
+         // Test that we have arrived at a valid date
+
+         if (isNaN(scwSeedDate))
+            {if (scwShowInvalidDateMsg) {alert(scwInvalidDateMsg + scwInvalidAlert[0] + scwDateValue + scwInvalidAlert[1]);}
+             scwSeedDate = new Date(scwBaseYear + Math.floor(scwDropDownYears/2),5,1);
+             scwBlnFullInputDate=false;
+            }
+         else
+            {// Test that the date is within range,
+             // if not then set date to a sensible date in range.
+
+             if ((new Date(scwBaseYear,0,1)) > scwSeedDate)
+                {if (scwBlnStrict && scwShowOutOfRangeMsg) {alert(scwOutOfRangeMsg);}
+                 scwSeedDate = new Date(scwBaseYear,0,1);
+                 scwBlnFullInputDate=false;
+                }
+             else
+                {if ((new Date(scwBaseYear+scwDropDownYears,0,0))<scwSeedDate)
+                    {if (scwBlnStrict && scwShowOutOfRangeMsg) {alert(scwOutOfRangeMsg);}
+                     scwSeedDate = new Date(scwBaseYear + Math.floor(scwDropDownYears)-1,11,1);
+                     scwBlnFullInputDate=false;
+                    }
+                 else
+                    {if (scwBlnStrict && scwBlnFullInputDate &&
+                          (scwSeedDate.getDate()      != scwArrSeedDate[2] ||
+                           (scwSeedDate.getMonth()+1) != scwArrSeedDate[1] ||
+                           scwSeedDate.getFullYear()  != scwArrSeedDate[0]
+                          )
+                        )
+                        {if (scwShowDoesNotExistMsg) alert(scwDoesNotExistMsg);
+                         scwSeedDate = new Date(scwSeedDate.getFullYear(),scwSeedDate.getMonth()-1,1);
+                         scwBlnFullInputDate=false;
+                        }
+                    }
+                }
+            }
+
+         // Test the disabled dates for validity
+         // Give error message if not valid.
+
+         for (var i=0;i<scwDisabledDates.length;i++)
+            {if (!((typeof scwDisabledDates[i] == 'object') && (scwDisabledDates[i].constructor == Date)))
+                {if ((typeof scwDisabledDates[i] == 'object') && (scwDisabledDates[i].constructor == Array))
+                    {var scwPass = true;
+
+                     if (scwDisabledDates[i].length !=2)
+                        {if (scwShowRangeDisablingError)
+                            {alert(scwRangeDisablingError[0] + scwDisabledDates[i] + scwRangeDisablingError[1]);}
+                         scwPass = false;
+                        }
+                     else
+                        {for (var j=0;j<scwDisabledDates[i].length;j++)
+                            {if (!((typeof scwDisabledDates[i][j] == 'object') && (scwDisabledDates[i][j].constructor == Date)))
+                                {if (scwShowRangeDisablingError)
+                                    {alert(  scwDateDisablingError[0] + scwDisabledDates[i][j] + scwDateDisablingError[1]);}
+                                 scwPass = false;
+                                }
+                            }
+                        }
+
+                     if (scwPass && (scwDisabledDates[i][0] > scwDisabledDates[i][1])) {scwDisabledDates[i].reverse();}
+                    }
+                 else
+                    {if (scwShowRangeDisablingError) {alert(scwDateDisablingError[0] + scwDisabledDates[i] + scwDateDisablingError[1]);}}
+                }
+            }
+
+         // Calculate the number of months that the entered (or
+         // defaulted) month is after the start of the allowed
+         // date range.
+
+         scwMonthSum =  12*(scwSeedDate.getFullYear()-scwBaseYear)+scwSeedDate.getMonth();
+
+         scwID('scwYears' ).options.selectedIndex = Math.floor(scwMonthSum/12);
+         scwID('scwMonths').options.selectedIndex = (scwMonthSum%12);
+
+         // Check whether or not dragging is allowed and display drag handle if necessary
+
+         scwID('scwDrag').style.display=(scwAllowDrag)?'':'none';
+
+         // Display the month
+
+         scwShowMonth(0);
+
+         // Position the calendar box
+
+         // The object sniffing for Opera allows for the fact that Opera
+         // is the only major browser that correctly reports the position
+         // of an element in a scrollable DIV.  This is because IE and
+         // Firefox omit the DIV from the offsetParent tree.
+
+         scwTargetEle=scwEle;
+
+         var offsetTop =parseInt(scwEle.offsetTop ,10) + parseInt(scwEle.offsetHeight,10),
+             offsetLeft=parseInt(scwEle.offsetLeft,10);
+
+         if (!window.opera)
+             {while (scwEle.tagName!='BODY' && scwEle.tagName!='HTML')
+                 {offsetTop -=parseInt(scwEle.scrollTop, 10);
+                  offsetLeft-=parseInt(scwEle.scrollLeft,10);
+                  scwEle=scwEle.parentNode;
+                 }
+              scwEle=scwTargetEle;
+             }
+
+         do {scwEle=scwEle.offsetParent;
+             offsetTop +=parseInt(scwEle.offsetTop, 10);
+             offsetLeft+=parseInt(scwEle.offsetLeft,10);
+            }
+         while (scwEle.tagName!='BODY' && scwEle.tagName!='HTML');
+
+         scwID('scw').style.top =offsetTop +'px';
+         scwID('scw').style.left=offsetLeft+'px';
+
+         scwID('scwIframe').style.top=offsetTop +'px';
+         scwID('scwIframe').style.left=offsetLeft+'px';
+         scwID('scwIframe').style.width=(scwID('scw').offsetWidth-(scwID('scwIE')?2:4))+'px';
+         scwID('scwIframe').style.height=(scwID('scw').offsetHeight-(scwID('scwIE')?2:4))+'px';
+         scwID('scwIframe').style.visibility='inherit';
+
+         // Show it on the page
+         scwID('scw').style.visibility='inherit';
+        };
+
+    function scwHide()
+        {scwID('scw').style.visibility='hidden';
+         scwID('scwIframe').style.visibility='hidden';
+         if (typeof scwNextAction!='undefined' && scwNextAction!=null)
+             {scwNextActionReturn = scwNextAction();
+              // Explicit null set to prevent closure causing memory leak
+              scwNextAction = null;
+             }
+        };
+
+    function scwCancel(scwEvt)
+        {if (scwClickToHide) {scwHide();}
+         scwStopPropagation(scwEvt);
+        };
+
+    function scwStopPropagation(scwEvt)
+        {if (scwEvt.stopPropagation)
+                {scwEvt.stopPropagation();}     // Capture phase
+         else   {scwEvt.cancelBubble = true;}   // Bubbling phase
+        };
+
+    function scwBeginDrag(event)
+        {var elementToDrag = scwID('scw');
+
+         var deltaX    = event.clientX,
+             deltaY    = event.clientY,
+             offsetEle = elementToDrag;
+
+         do {deltaX   -= parseInt(offsetEle.offsetLeft,10);
+             deltaY   -= parseInt(offsetEle.offsetTop ,10);
+             offsetEle = offsetEle.offsetParent;
+            }
+         while (offsetEle.tagName!='BODY' &&
+                offsetEle.tagName!='HTML');
+
+         if (document.addEventListener)
+                {document.addEventListener('mousemove',moveHandler,true);        // Capture phase
+                 document.addEventListener('mouseup',  upHandler,  true);        // Capture phase
+                }
+         else   {elementToDrag.attachEvent('onmousemove',moveHandler); // Bubbling phase
+                 elementToDrag.attachEvent('onmouseup',  upHandler);   // Bubbling phase
+                 elementToDrag.setCapture();
+                }
+
+         scwStopPropagation(event);
+
+         function moveHandler(scwEvt)
+            {if (!scwEvt) scwEvt = window.event;
+
+             elementToDrag.style.left = (scwEvt.clientX - deltaX) + 'px';
+             elementToDrag.style.top  = (scwEvt.clientY - deltaY) + 'px';
+
+             scwID('scwIframe').style.left = (scwEvt.clientX - deltaX) + 'px';
+             scwID('scwIframe').style.top  = (scwEvt.clientY - deltaY) + 'px';
+
+             scwStopPropagation(scwEvt);
+            };
+
+         function upHandler(scwEvt)
+            {if (!scwEvt) scwEvt = window.event;
+
+             if (document.removeEventListener)
+                    {document.removeEventListener('mousemove',moveHandler,true);     // Capture phase
+                     document.removeEventListener('mouseup',  upHandler,  true);     // Capture phase
+                    }
+             else   {elementToDrag.detachEvent('onmouseup',  upHandler);   // Bubbling phase
+                     elementToDrag.detachEvent('onmousemove',moveHandler); // Bubbling phase
+                     elementToDrag.releaseCapture();
+                    }
+
+             scwStopPropagation(scwEvt);
+            };
+        };
+
+    function scwShowMonth(scwBias)
+        {// Set the selectable Month and Year
+         // May be called: from the left and right arrows
+         //                  (shift month -1 and +1 respectively)
+         //                from the month selection list
+         //                from the year selection list
+         //                from the showCal routine
+         //                  (which initiates the display).
+
+         var scwShowDate  = new Date(Date.parse(new Date().toDateString())),
+             scwStartDate = new Date();
+
+         // Set the time to the middle of the day so that the handful of
+         // regions that have daylight saving shifts that change the day
+         // of the month (i.e. turn the clock back at midnight or forward
+         // at 23:00) do not mess up the date display in the calendar.
+
+         scwShowDate.setHours(12);
+
+         scwSelYears  = scwID('scwYears');
+         scwSelMonths = scwID('scwMonths');
+
+         if (scwSelYears.options.selectedIndex>-1)
+            {scwMonthSum=12*(scwSelYears.options.selectedIndex)+scwBias;
+             if (scwSelMonths.options.selectedIndex>-1) {scwMonthSum+=scwSelMonths.options.selectedIndex;}
+            }
+         else
+            {if (scwSelMonths.options.selectedIndex>-1) {scwMonthSum+=scwSelMonths.options.selectedIndex;}}
+
+         scwShowDate.setFullYear(scwBaseYear + Math.floor(scwMonthSum/12),(scwMonthSum%12),1);
+
+         // If the Week numbers are displayed, shift the week day names to the right.
+         scwID('scwWeek_').style.display=(scwWeekNumberDisplay)?'':'none';
+
+         // Opera has a bug with setting the selected index.
+         // It requires the following work-around to force SELECTs to display correctly.
+         if (window.opera)
+            {scwID('scwMonths').style.display = 'inherit';
+             scwID('scwYears' ).style.display = 'inherit';
+           }
+
+         // Set the drop down boxes.
+         scwTemp = (12*parseInt((scwShowDate.getFullYear()-scwBaseYear),10)) + parseInt(scwShowDate.getMonth(),10);
+
+         if (scwTemp > -1 && scwTemp < (12*scwDropDownYears))
+            {scwSelYears.options.selectedIndex=Math.floor(scwMonthSum/12);
+             scwSelMonths.options.selectedIndex=(scwMonthSum%12);
+
+             scwCurMonth = scwShowDate.getMonth();
+
+             scwShowDate.setDate((((scwShowDate.
+                                    getDay()-scwWeekStart)<0)?-6:1)+
+                                 scwWeekStart-scwShowDate.getDay());
+
+             // This statement moved by Michael Cerveny to make version 3.55
+             var scwCompareDateValue = new Date(scwShowDate.getFullYear(),
+                                                scwShowDate.getMonth(),
+                                                scwShowDate.getDate()).valueOf();
+
+             scwStartDate = new Date(scwShowDate);
+
+             if (scwID('scwFoot'))
+                {var scwFoot = scwID('scwFoot');
+
+                 function scwFootOutput() {scwSetOutput(scwDateNow);};
+
+                 if (scwDisabledDates.length==0)
+                    {if (scwActiveToday && scwParmActiveToday)
+                        {scwFoot.onclick     = scwFootOutput;
+                         scwFoot.className   = 'scwFoot';
+
+                         if (scwID('scwIE'))
+                            {scwFoot.onmouseover  = scwChangeClass;
+                             scwFoot.onmouseout   = scwChangeClass;
+                            }
+
+                        }
+                     else
+                        {scwFoot.onclick     = null;
+                         scwFoot.className   = 'scwFootDisabled';
+
+                         if (scwID('scwIE'))
+                            {scwFoot.onmouseover  = null;
+                             scwFoot.onmouseout   = null;
+                            }
+
+                         if (document.addEventListener)
+                                {scwFoot.addEventListener('click',scwStopPropagation,false);}
+                         else   {scwFoot.attachEvent('onclick',scwStopPropagation);}
+                        }
+                    }
+                 else
+                    {for (var k=0;k<scwDisabledDates.length;k++)
+                        {if (!scwActiveToday || !scwParmActiveToday ||
+                             ((typeof scwDisabledDates[k] == 'object')                   &&
+                                 (((scwDisabledDates[k].constructor == Date)             &&
+                                   scwDateNow.valueOf() == scwDisabledDates[k].valueOf()
+                                  ) ||
+                                  ((scwDisabledDates[k].constructor == Array)               &&
+                                   scwDateNow.valueOf() >= scwDisabledDates[k][0].valueOf() &&
+                                   scwDateNow.valueOf() <= scwDisabledDates[k][1].valueOf()
+                                  )
+                                 )
+                             )
+                            )
+                            {scwFoot.onclick     = null;
+                             scwFoot.className   = 'scwFootDisabled';
+
+                             if (scwID('scwIE'))
+                                {scwFoot.onmouseover  = null;
+                                 scwFoot.onmouseout   = null;
+                                }
+
+                             if (document.addEventListener)
+                                    {scwFoot.addEventListener('click',scwStopPropagation,false);}
+                             else   {scwFoot.attachEvent('onclick',scwStopPropagation);}
+                             break;
+                            }
+                         else
+                            {scwFoot.onclick=scwFootOutput;
+                             scwFoot.className='scwFoot';
+
+                             if (scwID('scwIE'))
+                                {scwFoot.onmouseover  = scwChangeClass;
+                                 scwFoot.onmouseout   = scwChangeClass;
+                                }
+                            }
+                        }
+                    }
+                }
+
+             function scwSetOutput(scwOutputDate)
+                {if (typeof scwTargetEle.value == 'undefined')
+                      {scwTriggerEle.scwTextNode.replaceData(0,scwTriggerEle.scwLength,scwOutputDate.scwFormat(scwDateOutputFormat));}
+                 else {scwTargetEle.value = scwOutputDate.scwFormat(scwDateOutputFormat);}
+                 scwHide();
+                };
+
+             function scwCellOutput(scwEvt)
+                {var scwEle = scwEventTrigger(scwEvt),
+                     scwOutputDate = new Date(scwStartDate);
+
+                 if (scwEle.nodeType==3) scwEle=scwEle.parentNode;
+
+                 scwOutputDate.setDate(scwStartDate.getDate() + parseInt(scwEle.id.substr(8),10));
+
+                 scwSetOutput(scwOutputDate);
+                };
+
+             function scwChangeClass(scwEvt)
+                {var scwEle = scwEventTrigger(scwEvt);
+
+                 if (scwEle.nodeType==3) {scwEle=scwEle.parentNode;}
+
+                 switch (scwEle.className)
+                    {case 'scwCells':
+                        scwEle.className = 'scwCellsHover';
+                        break;
+                     case 'scwCellsHover':
+                        scwEle.className = 'scwCells';
+                        break;
+                     case 'scwCellsExMonth':
+                        scwEle.className = 'scwCellsExMonthHover';
+                        break;
+                     case 'scwCellsExMonthHover':
+                        scwEle.className = 'scwCellsExMonth';
+                        break;
+                     case 'scwCellsWeekend':
+                        scwEle.className = 'scwCellsWeekendHover';
+                        break;
+                     case 'scwCellsWeekendHover':
+                        scwEle.className = 'scwCellsWeekend';
+                        break;
+                     case 'scwFoot':
+                        scwEle.className = 'scwFootHover';
+                        break;
+                     case 'scwFootHover':
+                        scwEle.className = 'scwFoot';
+                        break;
+                     case 'scwInputDate':
+                        scwEle.className = 'scwInputDateHover';
+                        break;
+                     case 'scwInputDateHover':
+                        scwEle.className = 'scwInputDate';
+                    }
+
+                 return true;
+                }
+
+             function scwEventTrigger(scwEvt)
+                {if (!scwEvt) {scwEvt = event;}
+                 return scwEvt.target||scwEvt.srcElement;
+                };
+
+             function scwWeekNumber(scwInDate)
+                {// The base day in the week of the input date
+                 var scwInDateWeekBase = new Date(scwInDate);
+
+                 scwInDateWeekBase.setDate(scwInDateWeekBase.getDate()
+                                            - scwInDateWeekBase.getDay()
+                                            + scwWeekNumberBaseDay
+                                            + ((scwInDate.getDay()>
+                                                scwWeekNumberBaseDay)?7:0));
+
+                 // The first Base Day in the year
+                 var scwFirstBaseDay = new Date(scwInDateWeekBase.getFullYear(),0,1);
+
+                 scwFirstBaseDay.setDate(scwFirstBaseDay.getDate()
+                                            - scwFirstBaseDay.getDay()
+                                            + scwWeekNumberBaseDay
+                                        );
+
+                 if (scwFirstBaseDay < new Date(scwInDateWeekBase.getFullYear(),0,1))
+                    {scwFirstBaseDay.setDate(scwFirstBaseDay.getDate()+7);}
+
+                 // Start of Week 01
+                 var scwStartWeekOne = new Date(scwFirstBaseDay
+                                                - scwWeekNumberBaseDay
+                                                + scwInDate.getDay());
+
+                 if (scwStartWeekOne > scwFirstBaseDay)
+                    {scwStartWeekOne.setDate(scwStartWeekOne.getDate()-7);}
+
+                 // Subtract the date of the current week from the date of the
+                 // first week of the year to get the number of weeks in
+                 // milliseconds.  Divide by the number of milliseconds
+                 // in a week then round to no decimals in order to remove
+                 // the effect of daylight saving.  Add one to make the first
+                 // week, week 1.  Place a string zero on the front so that
+                 // week numbers are zero filled.
+
+                 var scwWeekNo = '0' + (Math.round((scwInDateWeekBase - scwFirstBaseDay)/604800000,0) + 1);
+
+                 // Return the last two characters in the week number string
+
+                 return scwWeekNo.substring(scwWeekNo.length-2, scwWeekNo.length);
+                };
+
+             // Treewalk to display the dates.
+             // I tried to use getElementsByName but IE refused to cooperate
+             // so I resorted to this method which works for all tested
+             // browsers.
+
+             var scwCells = scwID('scwCells');
+
+             for (i=0;i<scwCells.childNodes.length;i++)
+                {var scwRows = scwCells.childNodes[i];
+                 if (scwRows.nodeType==1 && scwRows.tagName=='TR')
+                    {if (scwWeekNumberDisplay)
+                        {//Calculate the week number using scwShowDate
+                         scwTmpEl = scwRows.childNodes[0];
+                         scwTmpEl.innerHTML = scwWeekNumber(scwShowDate);
+                         scwTmpEl.style.borderColor =
+                             (scwTmpEl.currentStyle)
+                                ?scwTmpEl.currentStyle['backgroundColor']
+                                :(window.getComputedStyle)
+                                    ?document.defaultView.getComputedStyle(scwTmpEl,null).getPropertyValue('background-color')
+                                    :'';
+                         scwTmpEl.style.display='';
+                        }
+                     else
+                        {scwRows.childNodes[0].style.display='none';}
+
+                     for (j=1;j<scwRows.childNodes.length;j++)
+                        {var scwCols = scwRows.childNodes[j];
+                         if (scwCols.nodeType==1 && scwCols.tagName=='TD')
+                            {scwRows.childNodes[j].innerHTML=
+                                scwShowDate.getDate();
+                             var scwCell=scwRows.childNodes[j],
+                                 scwDisabled =
+                                    ((scwOutOfRangeDisable &&
+                                        (scwShowDate <
+                                            (new Date(scwBaseYear,0,1,
+                                                      scwShowDate.getHours()))
+                                         ||
+                                         scwShowDate >
+                                            (new Date(scwBaseYear+
+                                                      scwDropDownYears,0,0,
+                                                      scwShowDate.getHours()))
+                                        )
+                                     ) ||
+                                     (scwOutOfMonthDisable &&
+                                        (scwShowDate <
+                                            (new Date(scwShowDate.getFullYear(),
+                                                      scwCurMonth,1,
+                                                      scwShowDate.getHours()))
+                                         ||
+                                         scwShowDate >
+                                            (new Date(scwShowDate.getFullYear(),
+                                                      scwCurMonth+1,0,
+                                                      scwShowDate.getHours()))
+                                        )
+                                     )
+                                    )?true:false;
+
+                             scwCell.style.visibility =
+                                (scwOutOfMonthHide &&
+                                    (scwShowDate <
+                                        (new Date(scwShowDate.getFullYear(),
+                                                  scwCurMonth,1,
+                                                  scwShowDate.getHours()))
+                                     ||
+                                     scwShowDate >
+                                        (new Date(scwShowDate.getFullYear(),
+                                                  scwCurMonth+1,0,
+                                                  scwShowDate.getHours()))
+                                    )
+                                )?'hidden':'inherit';
+
+                             for (var k=0;k<scwDisabledDates.length;k++)
+                                {if ((typeof scwDisabledDates[k]=='object') &&
+                                     (scwDisabledDates[k].constructor == Date) &&
+                                     scwCompareDateValue == scwDisabledDates[k].valueOf()
+                                    )
+                                    {scwDisabled = true;}
+                                 else
+                                    {if ((typeof scwDisabledDates[k]=='object') &&
+                                         (scwDisabledDates[k].constructor == Array) &&
+                                         scwCompareDateValue >= scwDisabledDates[k][0].valueOf() &&
+                                         scwCompareDateValue <= scwDisabledDates[k][1].valueOf()
+                                        )
+                                        {scwDisabled = true;}
+                                    }
+                                }
+
+                             if (scwDisabled ||
+                                 !scwEnabledDay[j-1+(7*((i*scwCells.childNodes.length)/6))] ||
+                                 !scwPassEnabledDay[(j-1+(7*(i*scwCells.childNodes.length/6)))%7]
+                                )
+                                {scwRows.childNodes[j].onclick = null;
+
+                                 if (scwID('scwIE'))
+                                    {scwRows.childNodes[j].onmouseover  = null;
+                                     scwRows.childNodes[j].onmouseout   = null;
+                                    }
+
+                                 scwCell.className=
+                                    (scwShowDate.getMonth()!=scwCurMonth)
+                                        ?'scwCellsExMonthDisabled'
+                                        :(scwBlnFullInputDate &&
+                                          scwShowDate.toDateString()==
+                                          scwSeedDate.toDateString())
+                                            ?'scwInputDateDisabled'
+                                            :(scwShowDate.getDay()%6==0)
+                                                ?'scwCellsWeekendDisabled'
+                                                :'scwCellsDisabled';
+
+                                 scwCell.style.borderColor =
+                                     (scwFormatTodayCell && scwShowDate.toDateString()==scwDateNow.toDateString())
+                                        ?scwTodayCellBorderColour
+                                        :(scwCell.currentStyle)
+                                            ?scwCell.currentStyle['backgroundColor']
+                                            :(window.getComputedStyle)
+                                                ?document.defaultView.getComputedStyle(scwCell,null).getPropertyValue('background-color')
+                                                :'';
+                                }
+                             else
+                                {scwRows.childNodes[j].onclick=scwCellOutput;
+
+                                 if (scwID('scwIE'))
+                                    {scwRows.childNodes[j].onmouseover  = scwChangeClass;
+                                     scwRows.childNodes[j].onmouseout   = scwChangeClass;
+                                    }
+
+                                 scwCell.className=
+                                     (scwShowDate.getMonth()!=scwCurMonth)
+                                        ?'scwCellsExMonth'
+                                        :(scwBlnFullInputDate &&
+                                          scwShowDate.toDateString()==
+                                          scwSeedDate.toDateString())
+                                            ?'scwInputDate'
+                                            :(scwShowDate.getDay()%6==0)
+                                                ?'scwCellsWeekend'
+                                                :'scwCells';
+
+                                 scwCell.style.borderColor =
+                                     (scwFormatTodayCell && scwShowDate.toDateString() == scwDateNow.toDateString())
+                                        ?scwTodayCellBorderColour
+                                        :(scwCell.currentStyle)
+                                            ?scwCell.currentStyle['backgroundColor']
+                                            :(window.getComputedStyle)
+                                                ?document.defaultView.getComputedStyle(scwCell,null).getPropertyValue('background-color')
+                                                :'';
+                               }
+
+                             scwShowDate.setDate(scwShowDate.getDate()+1);
+                             scwCompareDateValue = new Date(scwShowDate.getFullYear(),scwShowDate.getMonth(),scwShowDate.getDate()).valueOf();
+                            }
+                        }
+                    }
+                }
+            }
+
+         // Opera has a bug with setting the selected index.
+         // It requires the following work-around to force SELECTs to display correctly.
+         // Also Opera's poor dynamic rendering prior to 9.5 requires
+         // the visibility to be reset to prevent garbage in the calendar
+         // when the displayed month is changed.
+
+         if (window.opera)
+            {scwID('scwMonths').style.display = 'inline';
+             scwID('scwYears' ).style.display = 'inline';
+             scwID('scw').style.visibility='hidden';
+             scwID('scw').style.visibility='inherit';
+           }
+        };
+
+// *************************
+//  End of Function Library
+// *************************
+// ***************************
+// Start of Calendar structure
+// ***************************
+
+    document.writeln("<!--[if IE]><div id='scwIE'></div><![endif]-->");
+    document.writeln("<!--[if lt IE 7]><div id='scwIElt7'></div><![endif]-->");
+    document.write(
+     "<iframe class='scw' " + (scwID('scwIElt7')?"src='/scwblank.html '":'') +
+             "id='scwIframe' name='scwIframe' frameborder='0'>" +
+     "</iframe>" +
+     "<table id='scw' class='scw'>" +
+       "<tr class='scw'>" +
+         "<td class='scw'>" +
+           "<table class='scwHead' id='scwHead' width='100%' " +
+                    "cellspacing='0' cellpadding='0'>" +
+            "<tr id='scwDrag' style='display:none;'>" +
+                "<td colspan='4' class='scwDrag' " +
+                    "onmousedown='scwBeginDrag(event);'>" +
+                    "<div id='scwDragText'></div>" +
+                "</td>" +
+            "</tr>" +
+            "<tr class='scwHead' >" +
+                 "<td class='scwHead'>" +
+                    "<input class='scwHead' id='scwHeadLeft' type='button' value='<' " +
+                            "onclick='scwShowMonth(-1);'  /></td>" +
+                 "<td class='scwHead'>" +
+                    "<select id='scwMonths' class='scwHead' " +
+                            "onchange='scwShowMonth(0);'>" +
+                    "</select>" +
+                 "</td>" +
+                 "<td class='scwHead'>" +
+                    "<select id='scwYears' class='scwHead' " +
+                            "onchange='scwShowMonth(0);'>" +
+                    "</select>" +
+                 "</td>" +
+                 "<td class='scwHead'>" +
+                    "<input class='scwHead' id='scwHeadRight' type='button' value='>' " +
+                            "onclick='scwShowMonth(1);' /></td>" +
+                "</tr>" +
+              "</table>" +
+            "</td>" +
+          "</tr>" +
+          "<tr class='scw'>" +
+            "<td class='scw'>" +
+              "<table class='scwCells' align='center'>" +
+                "<thead>" +
+                  "<tr><td class='scwWeekNumberHead' id='scwWeek_' ></td>");
+
+    for (i=0;i<7;i++)
+        {document.write(
+                      "<td class='scwWeek' id='scwWeekInit" + i + "'></td>");
+        }
+
+    document.write("</tr>" +
+                "</thead>" +
+                "<tbody id='scwCells' " +
+                        "onClick='scwStopPropagation(event);'>");
+
+    for (i=0;i<6;i++)
+        {document.write(
+                    "<tr>" +
+                      "<td class='scwWeekNo' id='scwWeek_" + i + "'></td>");
+         for (j=0;j<7;j++)
+            {document.write(
+                        "<td class='scwCells' id='scwCell_" + (j+(i*7)) +
+                        "'></td>");
+            }
+
+         document.write(
+                    "</tr>");
+        }
+
+    document.write(
+                "</tbody>");
+
+    if ((new Date(scwBaseYear + scwDropDownYears, 0, 0)) > scwDateNow &&
+        (new Date(scwBaseYear, 0, 0))                    < scwDateNow)
+        {document.write(
+                  "<tfoot class='scwFoot'>" +
+                    "<tr class='scwFoot'>" +
+                      "<td class='scwFoot' id='scwFoot' colspan='8'>" +
+                      "</td>" +
+                    "</tr>" +
+                  "</tfoot>");
+        }
+
+    document.write(
+              "</table>" +
+            "</td>" +
+          "</tr>" +
+        "</table>");
+
+    if (document.addEventListener)
+            {scwID('scw'         ).addEventListener('click',scwCancel,false);
+             scwID('scwHeadLeft' ).addEventListener('click',scwStopPropagation,false);
+             scwID('scwMonths'   ).addEventListener('click',scwStopPropagation,false);
+             scwID('scwMonths'   ).addEventListener('change',scwStopPropagation,false);
+             scwID('scwYears'    ).addEventListener('click',scwStopPropagation,false);
+             scwID('scwYears'    ).addEventListener('change',scwStopPropagation,false);
+             scwID('scwHeadRight').addEventListener('click',scwStopPropagation,false);
+            }
+    else    {scwID('scw'         ).attachEvent('onclick',scwCancel);
+             scwID('scwHeadLeft' ).attachEvent('onclick',scwStopPropagation);
+             scwID('scwMonths'   ).attachEvent('onclick',scwStopPropagation);
+             scwID('scwMonths'   ).attachEvent('onchange',scwStopPropagation);
+             scwID('scwYears'    ).attachEvent('onclick',scwStopPropagation);
+             scwID('scwYears'    ).attachEvent('onchange',scwStopPropagation);
+             scwID('scwHeadRight').attachEvent('onclick',scwStopPropagation);
+            }
+
+// ***************************
+//  End of Calendar structure
+// ***************************
+// ****************************************
+// Start of document level event definition
+// ****************************************
+
+    if (document.addEventListener)
+            {document.addEventListener('click',scwHide, false);}
+    else    {document.attachEvent('onclick',scwHide);}
+
+// ****************************************
+//  End of document level event definition
+// ****************************************
+// ************************************
+//  End of Simple Calendar Widget Code
+// ************************************
\ No newline at end of file
diff --git a/chat/MachineThatGoesBing.class b/chat/MachineThatGoesBing.class
new file mode 100644 (file)
index 0000000..11a07ee
Binary files /dev/null and b/chat/MachineThatGoesBing.class differ
diff --git a/chat/admin.settings.default b/chat/admin.settings.default
new file mode 100644 (file)
index 0000000..aeb9094
--- /dev/null
@@ -0,0 +1,10 @@
+produceTran=0
+tranFile=
+returnLink=
+adminPass=
+chatName=
+returnL=
+returnT=
+msgLifeSpan=86400
+chatSessionLifeSpan=2700
+chatIDLifeSpan=31104000
diff --git a/chat/atrc.gif b/chat/atrc.gif
new file mode 100644 (file)
index 0000000..9d7bc09
Binary files /dev/null and b/chat/atrc.gif differ
diff --git a/chat/bing.php b/chat/bing.php
new file mode 100644 (file)
index 0000000..a6f03f0
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+
+       require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/chat.inc.php');
+       $chatID  = $_GET['chatID'];
+       $uniqueID= intval($_GET['uniqueID']);
+
+       $myPrefs = getPrefs($_GET['chatID']);
+
+       howManyMessages(&$topMsgNum, &$bottomMsgNum);
+       if ($myPrefs['lastChecked'] < $topMsgNum && $myPrefs['lastRead'] < $topMsgNum) {
+               $myPrefs['lastChecked'] = $topMsgNum;
+               writePrefs($myPrefs, $chatID);
+               print "yes\n";
+       }
+       print "$topMsgNum $myPrefs[lastChecked] $myPrefs[lastRead] \n";
+?>
\ No newline at end of file
diff --git a/chat/bings/.html b/chat/bings/.html
new file mode 100644 (file)
index 0000000..c7fd822
--- /dev/null
@@ -0,0 +1,37 @@
+<html><script language="vbscript">
+               option explicit
+               Dim IntervalID
+               Dim count
+               count = 0
+
+               sub loaded
+
+                   IntervalID = Window.setInterval("askServer",5000)
+               end sub
+
+               sub changedF2
+                   askServer
+               end sub
+
+               sub askServer
+                   Dim objAsp, theFile
+                   set objAsp = CreateObject("Microsoft.XMLHTTP")
+                   objAsp.open "GET", "bing.php?uselessVar=" + CStr(count) + "&chatID=", false
+                   objAsp.send()
+                   theFile = objAsp.responsetext
+                   if InStr(theFile,"yes") > 0 then
+                       Player.URL = "chime.wav"
+                   else
+                   end if
+                   count = count + 1
+                   document.f1.f2.value = CStr(count) + theFile
+                   objAsp = 3
+                   theFile = ""
+               end sub
+
+               </script>
+               <body onLoad="loaded" language="vbscript">
+               <form name=f1><input type=text name=f2 length="200" /></form>
+               <OBJECT ID="Player" height="0" width="0" CLASSID="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6"></OBJECT>
+               </body>
+               </html>
\ No newline at end of file
diff --git a/chat/bings/chime.au b/chat/bings/chime.au
new file mode 100644 (file)
index 0000000..91c63fb
Binary files /dev/null and b/chat/bings/chime.au differ
diff --git a/chat/bings/chime.wav b/chat/bings/chime.wav
new file mode 100644 (file)
index 0000000..9502298
Binary files /dev/null and b/chat/bings/chime.wav differ
diff --git a/chat/bings/taras.html b/chat/bings/taras.html
new file mode 100644 (file)
index 0000000..e510494
--- /dev/null
@@ -0,0 +1,39 @@
+<html><script language="vbscript">
+               option explicit
+               Dim IntervalID
+               Dim count
+               count = 0
+
+               sub loaded
+
+                   IntervalID = Window.setInterval("askServer",5000)
+               end sub
+
+               sub changedF2
+                   askServer
+               end sub
+
+               sub askServer
+                   Dim objAsp, theFile
+                   set objAsp = CreateObject("Microsoft.XMLHTTP")
+                   objAsp.open "GET", "../bing.php?uselessVar=" + CStr(count) + "&chatID=test2", false
+                   objAsp.send()
+                   theFile = objAsp.responsetext
+                   if InStr(theFile,"yes") > 0 then
+                       Player.URL = "/chime.wav"
+                   else
+                   end if
+                   count = count + 1
+                   document.f1.f2.value = CStr(count) + theFile
+                   objAsp = 3
+                   theFile = ""
+               end sub
+
+               </script>
+               <body onLoad="loaded" language="vbscript">
+               
+               <h2>bing on</h2>
+               <form name=f1><input type=text name=f2 length="200" /></form>
+               <OBJECT ID="Player" height="0" width="0" CLASSID="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6"></OBJECT>
+               </body>
+               </html>
diff --git a/chat/bings/taras.php b/chat/bings/taras.php
new file mode 100644 (file)
index 0000000..dfb1161
--- /dev/null
@@ -0,0 +1,37 @@
+<html><script language="vbscript">
+               option explicit
+               Dim IntervalID
+               Dim count
+               count = 0
+
+               sub loaded
+
+                   IntervalID = Window.setInterval("askServer",5000)
+               end sub
+
+               sub changedF2
+                   askServer
+               end sub
+
+               sub askServer
+                   Dim objAsp, theFile
+                   set objAsp = CreateObject("Microsoft.XMLHTTP")
+                   objAsp.open "GET", "../bing.php?uselessVar=" + CStr(count) + "&chatID=<?php echo $_SESSION['login']; ?>", false
+                   objAsp.send()
+                   theFile = objAsp.responsetext
+                   if InStr(theFile,"yes") > 0 then
+                       Player.URL = "chime.wav"
+                   else
+                   end if
+                   count = count + 1
+                   document.f1.f2.value = CStr(count) + theFile
+                   objAsp = 3
+                   theFile = ""
+               end sub
+
+               </script>
+               <body onLoad="loaded" language="vbscript">
+               <form name=f1><input type=text name=f2 length="200" />sss</form>
+               <OBJECT ID="Player" height="0" width="0" CLASSID="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6"></OBJECT>
+               </body>
+               </html>
diff --git a/chat/chat.php b/chat/chat.php
new file mode 100644 (file)
index 0000000..1ceb63f
--- /dev/null
@@ -0,0 +1,83 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+require(AT_INCLUDE_PATH.'lib/chat.inc.php');
+
+$myPrefs = getPrefs($_SESSION['login']);
+writePrefs($myPrefs, $_SESSION['login']);
+?>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
+   "http://www.w3.org/TR/html4/frameset.dtd">
+<html lang="<?php echo $myLang->getCode(); ?>">
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $myLang->getCharacterSet(); ?>">
+       <meta http-equiv="Pragma" content="no-cache">
+       <title>ATutor AChat</title>
+</head>
+
+<?php
+       if ($myPrefs['bingFlag'] > 0 && $myPrefs['refresh'] == 'manual') {
+               //makeBingFile($chatID);
+?>
+       <frameset cols="*,300" frameborder="0">
+               <frame src="display.php?firstLoginFlag=<?php echo $_GET['firstLoginFlag']; ?>" name="display" title="Message Display" frameborder="0">
+               <frameset rows="*,1">
+                       <frame src="options.php" name="options" title="Chat Options" frameborder="0">
+                       <frame src="bings/taras.php" name="bing" title="Hidden Bing Frame" frameborder="0">
+               </frameset>
+  <noframes>
+      <p><?php echo _AT('frame_contains'); ?><br />
+         * <a href="display.php?firstLoginFlag=<?php echo $_GET['firstLoginFlag']; ?>"><?php echo _AT('chat_messages') ?></a>
+         * <a href="options.php"><?php echo _AT('chat_options'); ?></a>
+         * <a href="poster.php"><?php echo _AT('chat_compose_message'); ?></a>
+         </p>
+  </noframes>
+       </frameset>
+<?php
+       } else if ($myPrefs['refresh'] == 'manual') {
+?>
+       <frameset cols="*,300" frameborder="0">
+               <frame src="display.php?firstLoginFlag=<?php echo $_GET['firstLoginFlag']; ?>" name="display" title="Message Display and Poster" frameborder="0">
+               <frame src="options.php" name="options" title="<?php echo _AT('chat_options'); ?>" frameborder="0" />
+       <noframes>
+      <p><?php echo _AT('frame_contains'); ?><br />
+         * <a href="display.php?firstLoginFlag=<?php echo $_GET['firstLoginFlag']; ?>"><?php echo _AT('chat_messages') ?></a>
+         * <a href="options.php"><?php echo _AT('chat_options'); ?></a>
+         * <a href="poster.php"><?php echo _AT('chat_compose_message'); ?></a>
+         </p>
+  </noframes>
+       </frameset>
+<?php
+       } else {
+?>
+       <frameset cols="*,300" frameborder="0">
+               <frameset rows="*,120">
+                       <frame src="display.php?firstLoginFlag=<?php echo $_GET['firstLoginFlag']; ?>" name="display" title="Message Display" frameborder="0" marginwidth="0" marginheight="0">
+                       <frame src="poster.php" name="compose" title="Message Poster" frameborder="0" marginwidth="0" marginheight="0">
+               </frameset>
+               <frame src="options.php" name="options" title="<?php echo _AT('chat_options'); ?>" frameborder="0" marginwidth="0" marginheight="0">
+                       <noframes>
+      <p><?php echo _AT('frame_contains'); ?><br />
+         * <a href="display.php?firstLoginFlag=<?php echo $_GET['firstLoginFlag']; ?>"><?php echo _AT('chat_messages') ?></a>
+         * <a href="options.php"><?php echo _AT('chat_options'); ?></a>
+         * <a href="poster.php"><?php echo _AT('chat_compose_message'); ?></a>
+         </p>
+  </noframes>
+       </frameset>
+<?php
+       }
+?>
+</html>
diff --git a/chat/display.php b/chat/display.php
new file mode 100644 (file)
index 0000000..1a798a2
--- /dev/null
@@ -0,0 +1,130 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+session_write_close();
+//authenticate(USER_CLIENT, USER_ADMIN);
+require(AT_INCLUDE_PATH.'lib/chat.inc.php');
+
+       $myPrefs = getPrefs($_SESSION['login']);
+
+       cleanUp();
+
+       howManyMessages($topMsgNum, $bottomMsgNum);
+
+       if ($_REQUEST['set']) {
+               if (isset($_GET['set'])) {
+                       if ($_GET['set'] == $_POST['message']) {
+                               $tmp_message = $_POST['tempField'];
+                       } else {
+                               $tmp_message = $_POST['message'];
+                       }
+               } else {
+                       $tmp_message = $_POST['message'];
+               }
+               //$message = $_POST['message'];
+               postMessage($_SESSION['login'], $tmp_message, $topMsgNum, $bottomMsgNum);
+       } else if ($_REQUEST['firstLoginFlag'] > 0) {
+        postMessage(_AT('chat_system'), _AT('chat_user_logged_in', $_SESSION['login']), $topMsgNum, $bottomMsgNum);
+    }
+
+require('include/html/chat_header.inc.php');
+       if ($myPrefs['refresh'] != 'manual') {
+?>
+       <script language="javascript" type="text/javascript">
+       <!--
+               setTimeout("reDisplay()", <?php echo $myPrefs['refresh'] * 1000; ?>);
+               function reDisplay() {
+                       window.location.href = "<?php echo $_SERVER[PHP_SELF]; ?>";
+               }
+       //-->
+       </script>
+<?php
+       } /* end if */
+?>
+<a name="messages"></a>
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <th align="left"><?php echo _AT('chat_messages') ?></th>
+</tr>
+</table>
+
+<?php
+       $min = 1;
+       if ($topMsgNum - 10 > 1) {
+               $min = $topMsgNum - 10;
+       }
+       if ($myPrefs['onlyNewFlag'] > 0) {
+               $min = $myPrefs['lastRead'] +1;
+       }
+       if ($min <= $topMsgNum) {
+          echo '<table border="0" cellpadding="2" cellspacing="0" width="98%" class="chat-display" align="center">';
+       } else {
+          echo '<p>'._AT('chat_no_new_messages').'</p>';
+       }
+
+       if ($myPrefs['newestFirstFlag'] > 0) {
+        for ($i = $topMsgNum; $i >= $min; $i--) {
+            showMessage($i, $myPrefs);
+        }
+    } else {
+        for ($i = $min; $i <= $topMsgNum ; $i++) {
+            showMessage($i, $myPrefs);
+        }
+    }
+
+    if ($min <= $topMsgNum) {
+               echo '</table>';
+       }
+
+       echo '<table width="100%" border="0" cellpadding="5" cellspacing="0">';
+       echo '<tr>';
+       echo '<td align="right">';
+    if ($myPrefs['navigationAidFlag'] > 0) {   
+               echo '<a accesskey="m" href="display.php#messages" onfocus="this.className=\'highlight\'" onblur="this.className=\'\'" title="'._AT('chat_jump_to_message').' Alt-m">'._AT('chat_jump_to_message').'</a> | ';
+       }
+
+       echo '<a accesskey="r" href="display.php" target="display" onfocus="this.className=\'highlight\'" onblur="this.className=\'\'" title="'._AT('chat_refresh_message').' Alt-r">'._AT('chat_refresh_message').'</a>';
+       echo '</td></tr>';
+       echo '</table>';
+    
+    echo '<br /><br />';
+    if ($myPrefs['refresh'] == 'manual') {
+               echo '<table width="100%" border="0" cellpadding="5" cellspacing="0">
+           <tr><th align="left">'._AT('chat_compose_message').'</th></tr></table>';
+               echo '<p>';
+
+               echo '<form action="display.php" target="display" name="f1" method="post" onSubmit="return checkForm();">
+                          <input type="hidden" name="set" value="1" />
+                          <label accesskey="c" for="message"><input type="text" maxlength="200" size="50" id="message" name="message" value="" class="input" title="Alt-c" onfocus="this.className=\'input highlight\'" onblur="this.className=\'input\'" /></label>
+                          <input type="submit" name="submit" value="'._AT('send').'" class="button" title="'._AT('send').'" onfocus="this.className=\'submit highlight\'" onblur="this.className=\'submit\'" />';
+
+               echo '</form></p>';
+               echo '<script language="javascript"><!--
+                          function checkForm() {
+                                  if (document.f1.message.value == "" || !document.f1.message.value) return false;
+                                  return true;
+                          }';
+               echo '//--></script>';
+    } else {
+        if ($myPrefs['bingFlag'] > 0 && $topMsgNum > $myPrefs['lastRead']) {
+            echo '<embed src="bings/chime.wav" loop="false" autoplay="true" play="true" hidden="true" width="1" height="1" />';
+        }
+       } 
+
+    $myPrefs['lastRead']       = $topMsgNum;
+    $myPrefs['lastChecked']    = $topMsgNum;
+    writePrefs($myPrefs, $_SESSION['login']);
+       require('include/html/chat_footer.inc.php');
+?>
\ No newline at end of file
diff --git a/chat/filterHistory.php b/chat/filterHistory.php
new file mode 100644 (file)
index 0000000..b03e647
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+//authenticate(USER_CLIENT, USER_ADMIN);
+require(AT_INCLUDE_PATH.'lib/chat.inc.php');
+
+       $myPrefs = getPrefs($_SESSION['username']);
+       writePrefs($myPrefs, $_SESSION['username']);
+
+       cleanUp();
+       $topMsgNum = $bottomMsgNum = 0;
+    howManyMessages($topMsgNum, $bottomMsgNum);
+
+    $filterChatID = $_GET['filterChatID'];
+
+require('include/html/chat_header.inc.php');
+?>
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <td align="right"><a href="chat.php" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''"><?php echo _AT('chat_return'); ?></a></td>
+</tr>
+</table>
+
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <th align="left" class="box"><?php echo _AT('history'); ?></th>
+</tr>
+</table>
+<p><table border="0" cellpadding="2" cellspacing="0" width="90%" class="box2">
+<?php
+    if ($myPrefs['newestFirstFlag'] > 0) {
+        for ($i = $topMsgNum; $i >= 1; $i--) {
+            showMessageFiltered($i, $myPrefs, $filterChatID);
+        }
+    } else {
+        for ($i = 1; $i <= $topMsgNum ; $i++) {
+            showMessageFiltered($i, $myPrefs, $filterChatID);
+        }    
+    }
+?>
+</table></p>
+<br />
+
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <td align="right"><a href="chat.php" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''"><?php echo _AT('chat_return'); ?></a></td>
+</tr>
+</table>
+<?php require('include/html/chat_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/chat/help.php b/chat/help.php
new file mode 100644 (file)
index 0000000..96df783
--- /dev/null
@@ -0,0 +1,76 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+       require(AT_INCLUDE_PATH.'vitals.inc.php');
+       //authenticate(USER_CLIENT, USER_ADMIN);
+require(AT_INCLUDE_PATH.'lib/chat.inc.php');
+       $myPrefs = getPrefs($_SESSION['username']);
+
+
+require('include/html/chat_header.inc.php');
+
+?>
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <th align="left" class="box"><?php echo _AT('chat_help_screen'); ?></th>
+</tr>
+</table>
+
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <td align="right"><a href="chat.php?chatID=<?php echo $_GET['chatID'].SEP.'uniqueID='.$_GET['uniqueID']; ?>" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''"><?php echo _AT('chat_return'); ?></a></td>
+</tr>
+</table>
+<a name="jumps"></a><p>
+           <a href="help.php#display" onFocus="this.className='highlight'" onBlur="this.className=''"><?php echo _AT('chat_help_display_jump'); ?></a><br />
+           <a href="help.php#options" onFocus="this.className='highlight'" onBlur="this.className=''"><?php echo _AT('chat_help_options_jump'); ?></a><br />
+           <a href="help.php#history" onFocus="this.className='highlight'" onBlur="this.className=''"><?php echo _AT('chat_help_history_jump'); ?></a></p>
+<a name="display"></a>
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <th align="left" class="box"><small><?php echo _AT('chat_help_display_frame'); ?></small></th>
+</tr>
+</table>
+<?php echo _AT('chat_help_display_blurb'); ?>
+
+<p><a href="help.php#jumps" onFocus="this.className='highlight'" onBlur="this.className=''"><?php echo _AT('chat_help_jump_top'); ?></a>
+</p><a name="options"></a>
+
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <th align="left" class="box"><small><?php echo _AT('chat_help_options_frame'); ?></small></th>
+</tr>
+</table>
+<?php echo _AT('chat_help_options_blurb'); ?>
+
+<p><a href="help.php#jumps" onFocus="this.className='highlight'" onBlur="this.className=''"><?php echo _AT('chat_help_jump_top'); ?></a></p>
+<a name="history"></a>
+    
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <th align="left" class="box"><small><?php echo _AT('chat_help_history_frame'); ?></small></th>
+</tr>
+</table>
+<?php echo _AT('chat_help_history_blurb'); ?>
+
+<p><br /><a href="help.php#jumps" onFocus="this.className='highlight'" onBlur="this.className=''"><?php echo _AT('chat_help_jump_top'); ?></a></p>
+
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <td align="right"><a href="chat.php?chatID=<?php echo $_GET['chatID'].SEP.'uniqueID='.$_GET['uniqueID']; ?>" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''"><?php echo _AT('chat_return'); ?></a></td>
+</tr>
+</table>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/chat/history.php b/chat/history.php
new file mode 100644 (file)
index 0000000..b5b2524
--- /dev/null
@@ -0,0 +1,128 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+       require(AT_INCLUDE_PATH.'vitals.inc.php');
+       //authenticate(USER_CLIENT, USER_ADMIN);
+require(AT_INCLUDE_PATH.'lib/chat.inc.php');
+
+       $myPrefs = getPrefs($_SESSION['username']);
+       writePrefs($myPrefs, $_SESSION['username']);
+
+       cleanUp();
+       $topMsgNum = $bottomMsgNum = 0;
+    howManyMessages($topMsgNum, $bottomMsgNum);
+
+       $hisTopNum = $_GET['hisTopNum'];
+
+       if ($hisTopNum > $topMsgNum) {
+               $hisTopNum = $topMsgNum;
+       }
+    if (!$hisTopNum) {
+               $hisTopNum = $topMsgNum;
+       }
+
+    $hisBottomNum = getLower20Bound($hisTopNum, $bottomMsgNum);
+
+    if ($hisBottomNum == 0) {
+               $hisBottomNum = 1;
+       }
+    $totalNum = $topMsgNum - $bottomMsgNum + 1;
+
+    $hisTopNumUserPerspective = $hisTopNum - $bottomMsgNum + 1;
+    $hisBottomNumUserPerspective = $hisBottomNum - $bottomMsgNum + 1;
+
+    if ($hisBottomNumUserPerspective < 1) {
+               $hisBottomNumUserPerspective = 1;
+       }
+
+       $prevNumT = $hisBottomNum - 1;
+    $nextNumT = $hisTopNum + 20;
+
+require('include/html/chat_header.inc.php');
+
+
+       if ($hisTopNum < $topMsgNum && $hisBottomNum > $bottomMsgNum) {
+?>
+               <table width="100%" border="0" cellpadding="5" cellspacing="0">
+               <tr>
+                       <td align="right"><a href="history.php?hisTopNum=<?php echo $prevNumT; ?>" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''"><?php echo _AT('previous'); ?></a> | <a href="history.php?hisTopNum=<?php echo $nextNumT; ?>" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''"><?php echo _AT('next'); ?></a> | <a href="chat.php" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''"><?php echo _AT('chat_return'); ?></a></td>
+               </tr>
+               </table>
+<?php
+    } else if ($hisBottomNum > $bottomMsgNum) {
+?>
+               <table width="100%" border="0" cellpadding="5" cellspacing="0">
+               <tr>
+                       <td align="right"><a href="history.php?hisTopNum=<?php echo $prevNumT; ?>" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''"><?php echo _AT('previous'); ?></a> | <a href="chat.php" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''"><?php echo _AT('chat_return'); ?></a></td>
+               </tr>
+               </table>
+<?php
+       } else {
+?>
+               <table width="100%" border="0" cellpadding="5" cellspacing="0">
+               <tr>
+                       <td align="right"><a href="history.php?hisTopNum=<?php echo $nextNumT; ?>" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''"><?php echo _AT('next'); ?></a> | <a href="chat.php" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''"><?php echo _AT('chat_return'); ?></a></td>
+               </tr>
+               </table>
+<?php
+       }
+?>
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <th align="left" class="box"><?php echo _AT('chat_history_messages', $hisBottomNumUserPerspective, $hisTopNumUserPerspective, $totalNum); ?></th>
+</tr>
+</table>
+<?php
+    echo '<p><table border="0" cellpadding="2" cellspacing="0" width="90%" class="box2">';
+
+    if ($myPrefs['newestFirstFlag'] > 0) {
+        for ($i = $hisTopNum; $i >= $hisBottomNum; $i--) {
+            showMessage($i, $myPrefs);
+        }
+    } else {
+        for ($i = $hisBottomNum; $i <= $hisTopNum ; $i++) {
+            showMessage($i, $myPrefs);
+        }
+    }
+    echo '</table></p>';
+
+       if ($hisTopNum < $topMsgNum && $hisBottomNum > $bottomMsgNum) {
+?>
+               <table width="100%" border="0" cellpadding="5" cellspacing="0">
+               <tr>
+                       <td align="right"><a href="history.php?hisTopNum=<?php echo $prevNumT; ?>" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''">Previous</a> | <a href="history.php?hisTopNum=<?php echo $nextNumT; ?>" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''">Next</a> | <a href="chat.php" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''">Return to Chat</a></td>
+               </tr>
+               </table>
+<?php
+
+       } else if ($hisBottomNum > $bottomMsgNum) {
+?>
+               <table width="100%" border="0" cellpadding="5" cellspacing="0">
+               <tr>
+                       <td align="right"><a href="history.php?hisTopNum=<?php echo $prevNumT; ?>" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''">Previous</a> | <a href="chat.php" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''">Return to Chat</a></td>
+               </tr>
+               </table>
+<?php
+    } else {
+?>
+               <table width="100%" border="0" cellpadding="5" cellspacing="0">
+               <tr>
+                       <td align="right"><a href="history.php?hisTopNum=<?php echo $nextNumT; ?>" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''">Next</a> | <a href="chat.php" target="_top" onFocus="this.className='highlight'" onBlur="this.className=''">Return to Chat</a></td>
+               </tr>
+               </table>
+<?php
+    }
+
+       require('include/html/chat_footer.inc.php');
+?>
\ No newline at end of file
diff --git a/chat/include/html/chat_footer.inc.php b/chat/include/html/chat_footer.inc.php
new file mode 100644 (file)
index 0000000..691287b
--- /dev/null
@@ -0,0 +1,2 @@
+</body>
+</html>
\ No newline at end of file
diff --git a/chat/include/html/chat_header.inc.php b/chat/include/html/chat_header.inc.php
new file mode 100644 (file)
index 0000000..ec4c54d
--- /dev/null
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html lang="en">
+<head>
+       <title>ATutor AChat</title>
+       <?php if ($_GET['frame']) { ?>
+               <META HTTP-EQUIV="refresh" content="3;URL=prog.php?frame=1"> 
+       <?php } ?>
+       <link rel="stylesheet" href="<?php echo AT_BASE_HREF.'themes/'.$_SESSION['prefs']['PREF_THEME']; ?>/styles.css" type="text/css" />
+       <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+</head>
+
+<body <?php
+       if ($_SESSION['done']) {
+               echo 'onLoad="parent.window.close();"';
+       }
+?> class="chat">
diff --git a/chat/include/html/login_footer.inc.php b/chat/include/html/login_footer.inc.php
new file mode 100644 (file)
index 0000000..50df04c
--- /dev/null
@@ -0,0 +1,5 @@
+<br /><br />\r
+<small>Developed by Joel Kronenberg at the <?php echo $admin['returnLink']; ?><br />\r
+&copy; Copyright ATRC, 2003</small>\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/chat/include/html/login_header.inc.php b/chat/include/html/login_header.inc.php
new file mode 100644 (file)
index 0000000..488c7aa
--- /dev/null
@@ -0,0 +1,11 @@
+<html>\r
+<head>\r
+       <title>ATRC A-Chat-PHP: Login</title>\r
+       <link rel="stylesheet" href="style.css" />\r
+</head>\r
+<body bgColor="beige" text="black">\r
+<table width="100%" border="0" cellpadding="5" cellspacing="0">\r
+<tr>\r
+       <td align="left" bgColor="#bbccaa"><h3>ATRC A-Chat-<em>PHP</em></h3></td>\r
+</tr>\r
+</table>
\ No newline at end of file
diff --git a/chat/index.php b/chat/index.php
new file mode 100644 (file)
index 0000000..052203a
--- /dev/null
@@ -0,0 +1,134 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+
+$CACHE_DEBUG=0;
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+require(AT_INCLUDE_PATH.'lib/chat.inc.php');
+$admin = getAdminSettings();
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<p align="center"><a href="chat/chat.php?firstLoginFlag=1"><strong> <?php echo _AT('enter_chat');  ?></strong></a></p><br />
+<?php
+
+$orders = array('asc' => 'desc', 'desc' => 'asc');
+$cols   = array('name' => 1, 'date' => 1);
+
+if (isset($_GET['asc'])) {
+       $order = 'asc';
+       $col   = isset($cols[$_GET['asc']]) ? $_GET['asc'] : 'date';
+} else if (isset($_GET['desc'])) {
+       $order = 'desc';
+       $col   = isset($cols[$_GET['desc']]) ? $_GET['desc'] : 'date';
+} else {
+       // no order set
+       $order = 'desc';
+       $col   = 'date';
+}
+
+$tran_files = array();
+if (!@opendir(AT_CONTENT_DIR . 'chat/')){
+       mkdir(AT_CONTENT_DIR . 'chat/', 0777);
+}
+
+if(!file_exists(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings')){
+       @mkdir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'], 0777);
+       @mkdir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/tran/', 0776);
+       @mkdir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/msgs/', 0776);
+       @mkdir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/users/', 0776);
+       @copy('admin.settings.default', AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings');
+       @chmod (AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings', 0777);
+
+}
+       
+if ($dir = @opendir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/tran/')) {
+       while (($file = readdir($dir)) !== false) {
+               if (substr($file, -strlen('.html')) == '.html') {
+                       $la     = stat(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/tran/'.$file);
+
+                       $file = str_replace('.html', '', $file);
+                       $tran_files[$file] = $la['ctime'];
+               }
+       }
+}
+
+if (count($tran_files) == 0) {
+       echo '<p>'._AT('chat_none_found').'</p>';
+} else {?>
+       
+<form name="form" method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+
+       <table class="data" rules="cols" summary="">
+       <colgroup>
+               <?php if ($col == 'name'): ?>
+                       <col class="sort" />
+                       <col span="2" />
+               <?php elseif($col == 'date'): ?>
+                       <col span="2" />
+                       <col class="sort" />
+               <?php endif; ?>
+       </colgroup>
+       <thead>
+       <tr>
+               <th scope="col"><a href="<?php echo url_rewrite('chat/index.php?'.$orders[$order].'=name'); ?>"><?php echo _AT('chat_transcript');?></a></th>
+               <th scope="col"><?php echo _AT('status'); ?></th>
+               <th scope="col"><a href="<?php echo url_rewrite('chat/index.php?'.$orders[$order].'=date'); ?>"><?php echo _AT('date'); ?></a></th> 
+       </tr>
+       </thead>
+       <?php
+
+       if (($col == 'date') && ($order == 'asc')) {
+               asort($tran_files);
+       } else if (($col == 'date') && ($order == 'desc')) {
+               arsort($tran_files);
+       } else if (($col == 'name') && ($order == 'asc')) {
+               ksort($tran_files);
+       } else if (($col == 'name') && ($order == 'desc')) {
+               krsort($tran_files);
+       }
+       reset ($tran_files);
+       ?>
+
+       <tbody>
+       <?php foreach ($tran_files as $file => $date) { ?>
+               <tr onmousedown="document.location='<?php echo AT_BASE_HREF; ?>chat/view_transcript.php?t=<?php echo $file; ?>'">
+                       <td><a href="<?php echo url_rewrite('chat/view_transcript.php?t='.$file); ?>"><?php echo $file; ?></a></td>
+                       <td>
+                               <?php if (($file.'.html' == $admin['tranFile']) && ($admin['produceTran'])) { 
+                                       echo _AT('chat_currently_active');
+                               } else {
+                                       echo _AT('chat_inactive');
+                               }?>
+                       </td>
+       
+                       <td><?php 
+                                               //echo $date;
+                       $startend_date_longs_format=_AT('startend_date_longs_format');
+                       echo AT_date($startend_date_longs_format, $date, AT_DATE_UNIX_TIMESTAMP);
+                       ?></td>
+               </tr>
+       <?php } ?>
+       </tbody>
+
+       </table>
+</form>
+<?php
+}
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/chat/logout.php b/chat/logout.php
new file mode 100644 (file)
index 0000000..f1624cb
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+       require(AT_INCLUDE_PATH.'vitals.inc.php');
+       session_write_close();
+       //authenticate(USER_CLIENT, USER_ADMIN);
+       require(AT_INCLUDE_PATH.'lib/chat.inc.php');
+
+       $myPrefs = getPrefs($_SESSION['login']);
+
+
+       $topMsgNum = $bottomMsgNum = 0;
+    howManyMessages($topMsgNum, $bottomMsgNum);
+       postMessage(_AT('chat_system'),
+                               _AT('chat_logged_out', $_SESSION['login']),
+                               $topMsgNum,
+                               $bottomMsgNum);
+
+       $myPrefs['lastAccessed'] = 0;
+       writePrefs($myPrefs, $_SESSION['login']);
+
+       Header('Location: index.php');
+       exit;
+       //exit;
+require('include/html/chat_header.inc.php');
+?>
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <td align="left"><h4><?php echo $admin['chatName']; ?>: Logout</h4></td>
+</tr>
+</table>
+
+<p>The <?php echo $admin['chatName']; ?> will automatically save an account for you so that the next time you login with your <em>Chat ID</em> and <em>Password</em> your <em>Preference Settings</em> will be reloaded.</p>
+
+<p align="center"><b>Thank you for using the <?php echo $admin['chatName']; ?>.<br />
+<a href="http://www.utoronto.ca/atrc/" target="_new" onFocus="this.className='highlight'" onBlur="this.className=''"><img src="chat/atrc.gif" border="0" /></a></p>
+
+
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr> 
+       <td align="right"><a href="chat/index.php" onFocus="this.className='highlight'" onBlur="this.className=''">Re-enter Chat</a></td>
+</tr>
+</table>
+<?php
+       require('include/html/chat_footer.inc.php');
+?>
diff --git a/chat/options.php b/chat/options.php
new file mode 100644 (file)
index 0000000..4b4c03b
--- /dev/null
@@ -0,0 +1,88 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+session_write_close();
+//authenticate(USER_CLIENT, USER_ADMIN);
+require(AT_INCLUDE_PATH.'lib/chat.inc.php');
+
+$myPrefs = getPrefs($_SESSION['login']);
+
+require('include/html/chat_header.inc.php');
+?>
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <th align="left"><?php echo _AT('chat_options'); ?></th>
+</tr>
+</table>
+
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <td align="right"><a href="prefs.php" target="_top" onfocus="this.className='highlight'" onblur="this.className=''"><?php echo _AT('chat_edit_prefs'); ?></a> | <a href="logout.php" target="_top" accesskey="q" onfocus="this.className='highlight'" onblur="this.className=''"><?php  echo _AT('chat_exit'); ?></a></td></tr></table>
+<br /><br />
+<table width="100%" border="0" cellpadding="5" cellspacing="0"><tr>
+<th
+align="left"><?php echo _AT('chat_list_and_history'); ?></th></tr></table><?php
+       echo '<ul>';
+       if ($dir = opendir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/users/')) {
+               while (($file = readdir($dir)) !== false) {
+                       if (($file == '..') || ($file == '.')) {
+                               continue;
+                       }
+
+                       $chatName       = substr($file, 0, -strlen('.prefs'));
+                       $la                     = getLastAccessed($chatName);
+                       $now            = time();
+
+                       if (($la == 0) || (!$la)) {
+                               $la = 0;
+                       } else if ($now - $la < $admin['chatSessionLifeSpan']) {
+                               $colour = getChatIDColour($chatName, $myPrefs['colours']);
+                               if ($chatName == $_SESSION['login']) {
+                                       echo '<li><a href="filterHistory.php?filterChatID='.$chatName.'" target="_top" onfocus="this.className=\'highlight\'" onblur="this.className=\'\'"><span style="color:'.$colour.'">'.$chatName.'</span></a> ('._AT('chat_you').')</li>';
+                               } else if($chatName != '') {
+                                       echo '<li><a href="filterHistory.php?filterChatID='.$chatName.'" target="_top" onfocus="this.className=\'highlight\'" onblur="this.className=\'\'"><span style="color:'.$colour.'">'.$chatName.'</span></a></li>';
+                               }
+                       } else {
+                resetLastAccessed($chatName);
+                               $topMsgNum = $bottomMsgNum = 0;
+                howManyMessages($topMsgNum, $bottomMsgNum);
+                               postMessage(_AT('chat_system'),
+                                                       _AT('chat_user_logged_out', $chatName),
+                                                       $topMsgNum,
+                                                       $bottomMsgNum);
+                       }
+               }
+       }
+       closedir($dir);
+       echo '</ul>';
+
+       echo '<table width="100%" border="0" cellpadding="5" cellspacing="0">
+           <tr><td align="right"><a href="history.php" target="_top" onfocus="this.className=\'highlight\'" onblur="this.className=\'\'">'._AT('chat_full_history').'</a> | <a href="options.php" target="options" onfocus="this.className=\'highlight\'" onblur="this.className=\'\'">'._AT('chat_refresh_user_list').'</a></td></tr></table>';
+
+    //if ($myPrefs['navigationAidFlag'] > 0) {
+        echo '<br /><br />';
+               echo '<table width="100%" border="0" cellpadding="5" cellspacing="0">
+           <tr><td align="left"><h4>'._AT('chat_quick_keys').'</h4></td></tr></table>';
+
+        echo '<ul><li>'._AT('chat_altc').'</li>
+               <li>'._AT('chat_post').'</li>
+               <li>'._AT('chat_altr').'</li>
+               <li>'._AT('chat_altm').'</li>
+               <li>'._AT('chat_altq').'</li></ul>';
+    //}
+?>
+<?php
+require('include/html/chat_footer.inc.php');
+?>
diff --git a/chat/poster.php b/chat/poster.php
new file mode 100644 (file)
index 0000000..7c84f7a
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+session_write_close();
+//authenticate(USER_CLIENT, USER_ADMIN);
+require(AT_INCLUDE_PATH.'lib/chat.inc.php');
+
+$myPrefs = getPrefs($_GET['chatID']);
+
+require('include/html/chat_header.inc.php');
+
+$now = time();
+?>
+<table width="100%" border="0" cellpadding="5" cellspacing="0" class="input-form">
+<tr>
+       <th align="left"><?php echo _AT('chat_compose_message'); ?></th>
+</tr>
+<tr>
+       <td>
+       <form action="display.php?set=<?php echo $now; ?>" target="display" name="f1" method="post" onsubmit="return checkForm();" />
+               <input type="hidden" name="message" value="<?php echo $now; ?>" /><label accesskey="c" for="tempField"><input type="text" maxlength="200" size="40" name="tempField" id="tempField" value="" class="input" onfocus="this.className='input highlight'" onblur="this.className='input'" /></label><input type="submit" value="<?php echo _AT('send'); ?>" class="button" onfocus="this.className='submit highlight'" onblur="this.className='submit'" />  
+       </form>
+       </td>
+</tr>
+</table>
+<script language="javascript" type="text/javascript"><!--
+       function checkForm() {
+               document.f1.message.value = document.f1.tempField.value;
+        if (document.f1.message.value == "" || !document.f1.message.value) return false;
+               document.f1.tempField.value = "";
+        return true;
+       }
+//--></script>
+<?php require('include/html/chat_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/chat/prefs.php b/chat/prefs.php
new file mode 100644 (file)
index 0000000..b6c8b88
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+       require(AT_INCLUDE_PATH.'vitals.inc.php');
+       //authenticate(USER_CLIENT, USER_ADMIN);
+require(AT_INCLUDE_PATH.'lib/chat.inc.php');
+
+       $myPrefs = getPrefs($_SESSION['login']);
+       if ($_POST['submit'] || $_POST['submit_r']) {
+               getAndWriteFormPrefs($myPrefs);
+
+               if ($_POST['submit']) {
+                       $location = 'prefs2.php?firstLoginFlag='.$addslashes($_POST['firstLoginFlag']);
+               } else {
+                       $location = 'chat.php?firstLoginFlag='.$addslashes($_POST['firstLoginFlag']);
+               }
+               
+               Header('Location: '.$location);
+               exit;
+       }
+       writePrefs($myPrefs, $_SESSION['login']);
+
+
+require('include/html/chat_header.inc.php');
+?>
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <th align="left"><h4><?php echo _AT('chat_prefs_checking'); ?></h4></th>
+</tr>
+</table>
+<br />
+<form action="prefs.php" name="f1" method="post" target="_top">
+       <input type="hidden" name="firstLoginFlag" value="<?php echo $_GET['firstLoginFlag']; ?>" />
+<?php
+    if ($myPrefs['refresh'] == 'manual') {
+       $mCManSelT = 'selected';
+    } else if ($myPrefs['refresh'] > 100) {
+       $mC180SelT = 'selected';
+    } else if ($myPrefs['refresh'] > 30) {
+       $mC60SelT = 'selected';
+    } else if ($myPrefs['refresh'] > 10) {
+       $mC20SelT = 'selected';
+    } else {
+       $mc5SelT = 'selected';
+    }
+
+?>
+<p><b><?php echo _AT('chat_message_checking')  ?></b>
+       <select name="refresh">
+               <option value="5" <?php echo $mc5SelT; ?>><?php echo _AT('chat_auto5_checking');  ?></option>
+               <option value="20" <?php echo $mC20SelT; ?>><?php echo _AT('chat_auto20_checking');  ?></option>
+        <option value="60" <?php echo $mC60SelT; ?>><?php echo _AT('chat_auto60_checking');  ?></option>
+        <option value="180" <?php echo $mC180SelT; ?>><?php echo _AT('chat_auto180_checking');  ?></option>
+        <option value="manual" <?php echo $mCManSelT; ?>><?php echo _AT('chat_manual_checking');  ?></option>
+       </select></p>
+       <p><?php echo _AT('chat_message_check_help');  ?></p>
+
+<?php
+    if ($myPrefs['bingFlag'] > 0) {
+       $bFSelT = 'selected';
+    }
+?>
+
+<p><b><?php echo _AT('chat_message_chime') ?></b>
+       <select name="bingFlag">
+               <option value="0"><?php echo _AT('no'); ?></option>
+               <option value="1" <?php echo $bFSelT; ?>><?php echo _AT('yes'); ?></option>
+       </select></p>
+<p><?php echo _AT('chat_chime_help');  ?></p>
+
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <td align="left"><input type="submit" value="<?php echo _AT('next'); ?>" name="submit" class="submit" onFocus="this.className='submit highlight'" onBlur="this.className='submit'" />
+                     <input type="submit" value="<?php echo _AT('chat_enter'); ?>" name="submit_r" class="submit" onFocus="this.className='submit highlight'" onBlur="this.className='submit'" /></td>
+</tr>
+</table>
+</form>
+<?php require('include/html/chat_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/chat/prefs2.php b/chat/prefs2.php
new file mode 100644 (file)
index 0000000..7963530
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+       require(AT_INCLUDE_PATH.'vitals.inc.php');
+       //authenticate(USER_CLIENT, USER_ADMIN);
+require(AT_INCLUDE_PATH.'lib/chat.inc.php');
+       //not getting session username
+       $myPrefs = getPrefs($_SESSION['login']);
+
+       if ($_POST['submit'] || $_POST['submit_r'] || $_POST['submit_p']) {
+               getAndWriteFormPrefs($myPrefs);
+
+               if ($_POST['submit_p']) {
+                       $location = './prefs.php?firstLoginFlag='.$addslashes($_POST['firstLoginFlag']);
+               } else if ($_POST['submit_r']) {
+                       $location = './chat.php?firstLoginFlag='.$addslashes($_POST['firstLoginFlag']);
+               }
+
+               Header('Location: '.$location);
+               exit;
+       }
+       writePrefs($myPrefs, $_SESSION['username']);
+
+require('include/html/chat_header.inc.php');
+?>
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <th align="left"><h4><?php echo _AT('chat_layout_prefs'); ?></h4></th>
+</tr>
+</table>
+<br />
+<form action="prefs2.php" name="f1" method="post" target="_top">
+       <input type="hidden" name="firstLoginFlag" value="<?php echo $_REQUEST['firstLoginFlag']; ?>" />
+
+<?php
+    if ($myPrefs['newestFirstFlag'] > 0) {
+       $nFFSelT = 'selected';
+    }
+?>
+
+<p><b><?php echo _AT('chat_order_prefs'); ?></b>
+       <select name="newestFirstFlag">
+               <option value="0"><?php echo _AT('chat_oldnew_prefs'); ?></option>
+               <option value="1" <?php echo $nFFSelT;?>><?php echo _AT('chat_newold_prefs'); ?></option>
+       </select></p>
+<p><?php echo _AT('chat_message_order_help') ;?></p>
+
+<?php
+    if ($myPrefs['onlyNewFlag'] > 0) {
+       $oNFSelT = 'selected';
+    }
+?>
+
+<p><b><?php echo _AT('chat_newmsg_prefs'); ?></b>
+       <select name="onlyNewFlag">
+               <option value="0"><?php echo _AT('no'); ?></option>
+        <option value="1" <?php echo $oNFSelT;?>><?php echo _AT('yes'); ?></option>
+       </select></p>
+<p><?php echo _AT('chat_message_new_help') ;?></p>
+
+<table width="100%" border="0" cellpadding="5" cellspacing="0">
+<tr>
+       <td align="left"><input type="submit" value="<?php echo _AT('previous'); ?>" name="submit_p" class="submit" onFocus="this.className='submit highlight'" onBlur="this.className='submit'" /> <input type="submit" value="<?php echo _AT('chat_enter'); ?>" name="submit_r" class="submit" onFocus="this.className='submit highlight'" onBlur="this.className='submit'" /></td>
+</tr>
+</table>
+
+</form>
+<?php require('include/html/chat_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/chat/view_transcript.php b/chat/view_transcript.php
new file mode 100644 (file)
index 0000000..ebdcedd
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+if (isset($_GET['back'])) {
+       header('Location: '.url_rewrite('chat/index.php', AT_PRETTY_URL_IS_HEADER));
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+@readfile(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/tran/'.$_GET['t'].'.html');
+?>
+
+</table>
+<br />
+
+<form method="get" action="chat/view_transcript.php">
+       <input type="submit" value="<?php echo _AT('back'); ?>" name="back" class="button" />
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/confirm.php b/confirm.php
new file mode 100644 (file)
index 0000000..ba117ce
--- /dev/null
@@ -0,0 +1,185 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+$_user_location = 'public';
+
+define('AT_INCLUDE_PATH', 'include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.$_base_href.'login.php');
+       exit;
+}
+
+if (isset($_GET['e'], $_GET['id'], $_GET['m'])) {
+       $id = intval($_GET['id']);
+       $m  = $_GET['m'];
+       $e  = $addslashes($_GET['e']);
+
+       $sql    = "SELECT creation_date FROM ".TABLE_PREFIX."members WHERE member_id=$id";
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)) {
+               $code = substr(md5($_GET['e'] . $row['creation_date'] . $id), 0, 10);
+
+               if ($code == $m) {
+                       $sql = "UPDATE ".TABLE_PREFIX."members SET email='$_GET[e]', last_login=last_login WHERE member_id=$id";
+                       $result = mysql_query($sql, $db);
+
+                       $msg->addFeedback('CONFIRM_GOOD');
+
+                       header('Location: '.$_base_href.'users/index.php');
+                       exit;
+               } else {
+                       $msg->addError('CONFIRM_BAD');
+               }
+       } else {
+               $msg->addError('CONFIRM_BAD');
+       }
+
+} else if (isset($_GET['id'], $_GET['m'])) {
+       $id = intval($_GET['id']);
+       $m  = $_GET['m'];
+
+       $sql    = "SELECT email, creation_date FROM ".TABLE_PREFIX."members WHERE member_id=$id AND status=".AT_STATUS_UNCONFIRMED;
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)) {
+               $code = substr(md5($row['email'] . $row['creation_date'] . $id), 0, 10);
+
+               if ($code == $m) {
+                       if (defined('AUTO_APPROVE_INSTRUCTORS') && AUTO_APPROVE_INSTRUCTORS) {
+                               $sql = "UPDATE ".TABLE_PREFIX."members SET status=".AT_STATUS_INSTRUCTOR.", creation_date=creation_date, last_login=last_login WHERE member_id=$id";
+                       } else {
+                               $sql = "UPDATE ".TABLE_PREFIX."members SET status=".AT_STATUS_STUDENT.", creation_date=creation_date, last_login=last_login WHERE member_id=$id";
+                       }
+                       $result = mysql_query($sql, $db);
+
+                       if (isset($_REQUEST["en_id"]) && $_REQUEST["en_id"] <> "")
+                       {
+                               $msg->addFeedback('CONFIRM_GOOD');
+
+                               $member_id      = $id;
+                               require (AT_INCLUDE_PATH.'html/auto_enroll_courses.inc.php');
+                               unset($_SESSION['valid_user']);
+                               unset($_SESSION['member_id']);
+                               
+                               $table_title="
+                               <div class=\"row\">
+                                       <h3>" . _AT('auto_enrolled_msg'). "<br /></h3>
+                               </div>";
+               
+                               require(AT_INCLUDE_PATH.'header.inc.php');
+                               echo "<div class=\"input-form\">";
+                               require(AT_INCLUDE_PATH.'html/auto_enroll_list_courses.inc.php');
+                               echo '<p style="text-align:center"><a href="'. $_SERVER['PHP_SELF'] . '?auto_login=1&member_id='. $id .'">' . _AT("go_to_my_start_page") . '</a></p>';
+                               echo "</div>";
+                               require(AT_INCLUDE_PATH.'footer.inc.php');
+                               exit;
+                       }
+                       else
+                       {
+                               $msg->addFeedback('CONFIRM_GOOD');
+                               
+                               // enable auto login student into "my start page"
+                               $_REQUEST["auto_login"] = 1;
+                               $_REQUEST["member_id"] = $id;
+                       }
+               } else {
+                       $msg->addError('CONFIRM_BAD');
+               }
+       } else {
+               $msg->addError('CONFIRM_BAD');
+       }
+} else if (isset($_POST['submit'])) {
+       $_POST['email'] = $addslashes($_POST['email']);
+
+       $sql    = "SELECT member_id, email, creation_date, status FROM ".TABLE_PREFIX."members WHERE email='$_POST[email]'";
+       $result = mysql_query($sql, $db);
+
+       if ($row = mysql_fetch_assoc($result)) {
+
+               if ($row['status'] == AT_STATUS_UNCONFIRMED) {
+                       $code = substr(md5($row['email'] . $row['creation_date']. $row['member_id']), 0, 10);
+                       
+                       if ($_POST["en_id"] <> "")
+                               $confirmation_link = $_base_href . 'confirm.php?id='.$row['member_id'].SEP.'m='.$code.'&en_id='.$_POST["en_id"];
+                       else
+                               $confirmation_link = $_base_href . 'confirm.php?id='.$row['member_id'].SEP.'m='.$code;
+
+                       /* send the email confirmation message: */
+                       require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+                       $mail = new ATutorMailer();
+
+                       $mail->From     = $_config['contact_email'];
+                       $mail->AddAddress($row['email']);
+                       $mail->Subject = SITE_NAME . ': ' . _AT('email_confirmation_subject');
+                       $mail->Body    = _AT('email_confirmation_message', $_base_href, $confirmation_link)."\n\n";
+                       $mail->Send();
+
+                       $msg->addFeedback('CONFIRMATION_SENT');
+               } else {
+                       $msg->addFeedback('ACCOUNT_CONFIRMED');
+               }
+
+               header('Location: '.$_base_href.'login.php');
+               exit;
+       } else {
+               $msg->addError('EMAIL_NOT_FOUND');
+       }
+}
+
+if (isset($_REQUEST['auto_login']))
+{
+       
+       $sql = "SELECT M.member_id, M.login, M.preferences, M.language FROM ".TABLE_PREFIX."members M WHERE M.member_id=".$_REQUEST["member_id"];
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)) 
+       {
+               $_SESSION['valid_user'] = true;
+               $_SESSION['member_id']  = $_REQUEST["member_id"];
+               $_SESSION['course_id']  = 0;
+               $_SESSION['login']              = $row[login];
+               assign_session_prefs(unserialize(stripslashes($row['preferences'])));
+               $_SESSION['is_guest']   = 0;
+               $_SESSION['lang']               = $row[lang];
+               session_write_close();
+
+               header('Location: '.AT_BASE_HREF.'bounce.php?course='.$_POST['course']);
+               exit;
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); ?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+
+<div class="input-form" style="max-width: 400px">
+       <div class="row">
+               <p><?php echo _AT('send_confirmation'); ?></p>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="email"><?php echo _AT('email'); ?></label><br />
+               <input type="text" name="email" id="email" size="50" />
+               <input type="hidden" name="en_id" id="en_id" value="<?php echo $_REQUEST['en_id']; ?>" size="50" />
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('send'); ?>" /> 
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/contact_instructor.php b/contact_instructor.php
new file mode 100644 (file)
index 0000000..bece95b
--- /dev/null
@@ -0,0 +1,142 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+$_user_location = 'public';
+
+define('AT_INCLUDE_PATH', 'include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+if (isset($_SESSION['member_id']) && $_SESSION['member_id']) {
+       $to = $_base_href . 'users/browse.php';
+} else {
+       $to = $_base_href . 'browse.php';
+}
+
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: ' . $to);
+       exit;
+}
+
+$row = array();
+
+$id = intval($_REQUEST['id']);
+if (isset($system_courses[$id], $system_courses[$id]['member_id'])) {
+       $sql    = "SELECT M.member_id, M.first_name, M.last_name, M.email FROM ".TABLE_PREFIX."members M WHERE M.member_id={$system_courses[$id][member_id]}";
+       $result = mysql_query($sql, $db);
+       $row = mysql_fetch_assoc($result);
+}
+
+if ($row) {
+       $instructor_name = get_display_name($row['member_id']);
+       $instructor_email = AT_print($row['email'], 'members.email');
+} else {
+       $msg->addError('INST_INFO_NOT_FOUND');
+       header('Location: ' . $to);
+       exit;
+}
+
+if (isset($_POST['submit'])) {
+       $missing_fields = array();
+
+       $to_email = $_POST['email'];
+       $_POST['subject'] = trim($_POST['subject']);
+       $_POST['body']    = trim($_POST['body']);
+
+       if ($_POST['subject'] == '') {
+               $missing_fields[] = _AT('subject');
+       }
+               
+       if ($_POST['body'] == '') {
+               $missing_fields[] = _AT('body');
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       if (!$msg->containsErrors()) {
+
+               require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+
+               if (empty($_POST['from_email'])) {
+                       $_POST['from_email'] = $instructor_email;
+               }
+               if (empty($_POST['from'])) {
+                       $_POST['from'] = '';
+               }
+
+               $mail = new ATutorMailer;
+
+               $mail->From     = $_POST['from_email'];
+               $mail->FromName = $_POST['from'];
+               $mail->AddAddress($instructor_email, $instructor_name);
+               $mail->Subject = stripslashes($addslashes($_POST['subject']));
+               $mail->Body    = stripslashes($addslashes($_POST['body']));
+
+               if(!$mail->Send()) {
+                  $msg->addError('SENDING_ERROR');
+                  header('Location: ' . $to);
+                  exit;
+               }
+               unset($mail);
+               
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: ' . $to);
+               exit;
+       }
+
+}
+
+require (AT_INCLUDE_PATH.'header.inc.php');
+?>
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<input type="hidden" name="id" value="<?php echo $id; ?>" />
+
+<div class="input-form">
+       <div class="row">
+               <?php echo _AT('to'); ?><br />
+               <?php echo $instructor_name; ?>
+       </div>
+
+       <div class="row">
+               <label for="from"><?php echo _AT('from_name'); ?></label><br />
+               <input type="text" class="formfield" name="from" id="from" size="40" value="<?php echo $student_name;?>" />
+       </div>
+
+       <div class="row">
+               <label for="from_email"><?php echo _AT('from_email'); ?></label><br />
+               <input type="text" class="formfield" name="from_email" id="from_email" size="40" value="<?php echo $student_email;?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="subject"><?php echo _AT('subject'); ?></label><br />
+               <input type="text" class="formfield" name="subject" id="subject" size="40" value="<?php echo $_POST['subject']; ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="body"><?php echo _AT('body'); ?></label><br />
+               <textarea class="formfield" cols="55" rows="15" id="body" name="body" wrap="wrap"><?php echo $_POST['body']; ?></textarea>
+       </div>
+
+       <div class="buttons row">
+               <input type="submit" name="submit" class="button" value="<?php echo _AT('send_message'); ?>" accesskey="s" />  
+               <input type="submit" name="cancel" class="button" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/content.php b/content.php
new file mode 100644 (file)
index 0000000..a6080a0
--- /dev/null
@@ -0,0 +1,174 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', 'include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+$cid = $_GET['cid'] = intval($_GET['cid']);
+
+if ($cid == 0) {
+       header('Location: '.$_base_href.'index.php');
+       exit;
+}
+
+/* show the content page */
+$result = $contentManager->getContentPage($cid);
+
+if (!($content_row = mysql_fetch_assoc($result))) {
+       $_pages['content.php']['title_var'] = 'missing_content';
+       $_pages['content.php']['parent']    = 'index.php';
+       $_pages['content.php']['ignore']        = true;
+
+
+       require(AT_INCLUDE_PATH.'header.inc.php');
+
+       $msg->addError('PAGE_NOT_FOUND');
+       $msg->printAll();
+
+       require (AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+} /* else: */
+
+if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+       $course_base_href = 'get.php/';
+} else {
+       $course_base_href = 'content/' . $_SESSION['course_id'] . '/';
+}
+
+/* the "heading navigation": */
+$path  = $contentManager->getContentPath($cid);
+
+if ($content_row['content_path']) {
+       $content_base_href = $content_row['content_path'].'/';
+}
+
+$parent_headings = '';
+$num_in_path = count($path)-1;
+
+/* the page title: */
+$page_title = '';
+$page_title .= $content_row['title'];
+
+$num_in_path = count($path)-1;
+for ($i=0; $i<$num_in_path; $i++) {
+       $content_info = $path[$i];
+       if ($_SESSION['prefs']['PREF_NUMBERING']) {
+               if ($contentManager->_menu_info[$content_info['content_id']]['content_parent_id'] == 0) {
+                       $top_num = $contentManager->_menu_info[$content_info['content_id']]['ordering'];
+                       $parent_headings .= $top_num;
+               } else {
+                       $top_num = $top_num.'.'.$contentManager->_menu_info[$content_info['content_id']]['ordering'];
+                       $parent_headings .= $top_num;
+               }
+               $parent_headings .= ' ';
+       }
+}
+
+if ($_SESSION['prefs']['PREF_NUMBERING']) {
+       if ($top_num != '') {
+               $top_num = $top_num.'.'.$content_row['ordering'];
+               $page_title .= $top_num.' ';
+       } else {
+               $top_num = $content_row['ordering'];
+               $page_title .= $top_num.' ';
+       }
+}
+
+$parent = 0;
+foreach ($path as $page) {
+       if (!$parent) {
+               $_pages['content.php?cid='.$page['content_id']]['title']    = $page['title'];
+               $_pages['content.php?cid='.$page['content_id']]['parent']   = 'index.php';
+       } else {
+               $_pages['content.php?cid='.$page['content_id']]['title']    = $page['title'];
+               $_pages['content.php?cid='.$page['content_id']]['parent']   = 'content.php?cid='.$parent;
+       }
+
+       $_pages['content.php?cid='.$page['content_id']]['ignore'] = true;
+       $parent = $page['content_id'];
+}
+
+$last_page = array_pop($_pages);
+$_pages['content.php'] = $last_page;
+
+reset($path);
+$first_page = current($path);
+
+// use any styles that were part of the imported document
+// $_custom_css = $_base_href.'headstuff.php?cid='.$cid.SEP.'path='.urlEncode($_base_href.$course_base_href.$content_base_href);
+
+if ($content_row['use_customized_head'] && strlen($content_row['head']) > 0)
+{
+       $_custom_head = $content_row['head'];
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+save_last_cid($cid);
+if (isset($top_num) && $top_num != (int) $top_num) {
+       $top_num = substr($top_num, 0, strpos($top_num, '.'));
+}
+
+$shortcuts = array();
+if ((  ($content_row['r_date'] <= $content_row['n_date'])
+               && ((!$content_row['content_parent_id'] && ($_SESSION['packaging'] == 'top'))
+                       || ($_SESSION['packaging'] == 'all'))
+       ) || authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
+
+       $shortcuts[] = array('title' => _AT('export_content'), 'url' => $_base_href . 'tools/ims/ims_export.php?cid='.$cid);
+}
+
+if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
+       $shortcuts[] = array('title' => _AT('edit_this_page'),   'url' => $_base_href . 'editor/edit_content.php?cid='.$cid);
+       $shortcuts[] = array('title' => _AT('add_top_page'),     'url' => $_base_href . 'editor/edit_content.php');
+       if ($contentManager->_menu_info[$cid]['content_parent_id']) {
+               $shortcuts[] = array('title' => _AT('add_sibling_page'), 'url' => $_base_href .
+                       'editor/edit_content.php?pid='.$contentManager->_menu_info[$cid]['content_parent_id']);
+       }
+       $shortcuts[] = array('title' => _AT('add_sub_page'),     'url' => $_base_href . 'editor/edit_content.php?pid='.$cid);
+       $shortcuts[] = array('title' => _AT('delete_this_page'), 'url' => $_base_href . 'editor/delete_content.php?cid='.$cid);
+}
+$savant->assign('shortcuts', $shortcuts);
+
+/* if i'm an admin then let me see content, otherwise only if released */
+$released_status = $contentManager->isReleased($cid);
+if ($released_status === TRUE || authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
+       if ($content_row['text'] == '') {
+               $msg->addInfo('NO_PAGE_CONTENT');
+               $msg->printAll();
+               $savant->assign('body', '');
+       } else {
+               if ($released_status !== TRUE) {
+                       /* show the instructor that this content hasn't been released yet */
+                       $infos = array('NOT_RELEASED', AT_date(_AT('announcement_date_format'), $released_status, AT_DATE_UNIX_TIMESTAMP));
+                       $msg->addInfo($infos);
+                       $msg->printAll();
+                       unset($infos);
+               }
+
+               /* @See: include/lib/output.inc.php */
+               $savant->assign('body', format_content($content_row['text'], $content_row['formatting'], $glossary));
+       }
+} else {
+       $infos = array('NOT_RELEASED', AT_date(_AT('announcement_date_format'), $released_status, AT_DATE_UNIX_TIMESTAMP));
+       $msg->addInfo($infos);
+       $msg->printAll();
+       unset($infos);
+}
+
+$savant->assign('content_info', _AT('page_info', AT_date(_AT('inbox_date_format'), $content_row['last_modified'], AT_DATE_MYSQL_DATETIME), $content_row['revision'], AT_date(_AT('inbox_date_format'), $content_row['release_date'], AT_DATE_MYSQL_DATETIME)));
+
+$savant->display('content.tmpl.php');
+
+require (AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/directory.php b/directory.php
new file mode 100644 (file)
index 0000000..3249cf7
--- /dev/null
@@ -0,0 +1,185 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', 'include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+/* should only be in here if you are enrolled in the course!!!!!! */\r
+if ($_SESSION['enroll'] == '') {\r
+       require(AT_INCLUDE_PATH.'header.inc.php');\r
+       $msg->addInfo('NOT_ENROLLED');\r
+       $msg->printAll();\r
+       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+\r
+if ($_GET['reset_filter']) {\r
+       unset($_GET);\r
+}\r
+\r
+if (isset($_GET['online_status']) && ($_GET['online_status'] != '')) {\r
+       if ($_GET['online_status'] == 1) {\r
+               $on = 'checked="checked"';\r
+       } else if ($_GET['online_status'] == 2) {\r
+               $all = 'checked="checked"';\r
+       } else if ($_GET['online_status'] == 0) {\r
+               $off = 'checked="checked"';\r
+       }\r
+} else {\r
+       $all = 'checked="checked"';\r
+}\r
+\r
+$group = abs($_GET['group']);\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+?>\r
+\r
+<form name="form" action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get">\r
+<div class="input-form">\r
+       <div class="row">\r
+               <?php echo _AT('online_status'); ?><br />\r
+               <input type="radio" name="online_status" id="s1" value="1" <?php echo $on; ?>  /><label for="s1"><?php echo _AT('user_online');  ?></label>\r
+               <input type="radio" name="online_status" id="s0" value="0" <?php echo $off; ?> /><label for="s0"><?php echo _AT('user_offline'); ?></label>\r
+               <input type="radio" name="online_status" id="s2" value="2" <?php echo $all; ?> /><label for="s2"><?php echo _AT('all');          ?></label>\r
+       </div>\r
+\r
+               <div class="row">\r
+\r
+                       <label for="groups"><?php echo _AT('groups'); ?></label><br />\r
+                       <?php\r
+                       $sql_groups = implode(',', $_SESSION['groups']);\r
+                       $sql = "SELECT G.title, G.group_id, T.title AS type_title FROM ".TABLE_PREFIX."groups G INNER JOIN ".TABLE_PREFIX."groups_types T USING (type_id) WHERE T.course_id=$_SESSION[course_id] AND G.group_id IN ($sql_groups) ORDER BY T.title";\r
+                       $result = mysql_query($sql, $db);\r
+                       ?>\r
+                       <select name="group" id="groups">\r
+                               <option value="0" id="g0" ><?php echo _AT('entire_course'); ?></option>\r
+                       <?php while ($row = mysql_fetch_assoc($result)): ?>\r
+                               <option value="<?php echo $row['group_id']; ?>" id="g<?php echo $row['group_id']; ?>" <?php if ($group == $row['group_id']) { echo 'selected="selected"'; } ?> ><?php echo $row['type_title'] . ': ' . $row['title']; ?></option>\r
+                       <?php endwhile; ?>\r
+                       </select>\r
+\r
+               </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('filter'); ?>" />\r
+               <input type="submit" name="reset_filter" value="<?php echo _AT('reset_filter'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php\r
+if ($_GET['order'] == 'asc') {\r
+       $order = 'desc';\r
+} else {\r
+       $order = 'asc';\r
+}\r
+\r
+$group_members = '';\r
+if ($group) {\r
+       $group_members = array();\r
+       $sql = "SELECT member_id FROM ".TABLE_PREFIX."groups_members WHERE group_id=$group";\r
+       $result = mysql_query($sql, $db);\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               $group_members[] = $row['member_id'];\r
+       }\r
+       $group_members = ' AND C.member_id IN (' . implode(',', $group_members) . ')';\r
+}\r
+\r
+/* look through enrolled students list */\r
+$sql_members = "SELECT C.member_id, C.approved, C.privileges, M.login, M.first_name, M.second_name, M.last_name FROM ".TABLE_PREFIX."course_enrollment C, ".TABLE_PREFIX."members M    WHERE C.course_id=$_SESSION[course_id] AND C.member_id=M.member_id AND (C.approved='y' OR C.approved='a')       $group_members ORDER BY M.login $order";\r
+\r
+$result_members = mysql_query($sql_members, $db);\r
+\r
+while ($row_members = mysql_fetch_assoc($result_members)) {\r
+       $all_[$row_members['member_id']] = $row_members;\r
+       $all_[$row_members['member_id']]['online'] = FALSE;\r
+}\r
+\r
+$sql_online = "SELECT member_id FROM ".TABLE_PREFIX."users_online WHERE course_id = $_SESSION[course_id] AND expiry>".time();\r
+$result_online = mysql_query($sql_online, $db);\r
+\r
+while ($row_online = mysql_fetch_assoc($result_online)) {\r
+       if ($all_[$row_online['member_id']] != '') {\r
+               $all_[$row_online['member_id']]['online'] = TRUE;\r
+               $online[$row_online['member_id']] = $all_[$row_online['member_id']];\r
+       }\r
+}\r
+\r
+if ($all) {\r
+       $final = $all_;\r
+} else if ($on) {\r
+       $final = $online;\r
+} else {\r
+       foreach ($all_ as $id=>$attrs) {\r
+               if ($attrs['online'] == FALSE) {\r
+                       $final[$id] = $attrs;\r
+               }\r
+       }\r
+}\r
+\r
+?>\r
+<table class="data" rules="cols" summary="">\r
+<thead>\r
+<tr>\r
+       <th scope="col"><?php echo _AT('login_name'); ?></th>\r
+       <th scope="col"><?php echo _AT('full_name'); ?></th>\r
+       <th scope="col"><?php echo _AT('status'); ?></th>\r
+       <th scope="col"><?php echo _AT('online_status'); ?></th>\r
+</tr>\r
+</thead>\r
+<tbody>\r
+<?php\r
+if ($final) {\r
+       foreach ($final as $user_id=>$attrs) {\r
+               echo '<tr onmousedown="document.location=\''.$_base_href.'profile.php?id='.$user_id.'\'">';\r
+               $type = 'class="user"';\r
+               if ($system_courses[$_SESSION['course_id']]['member_id'] == $user_id) {\r
+                       $type = 'class="user instructor" title="'._AT('instructor').'"';\r
+               }\r
+               echo '<td><a href="profile.php?id='.$user_id.'" '.$type.'>'.AT_print($attrs['login'], 'members.login') . '</a></td>';\r
+\r
+               //echo '<td>'.AT_print($attrs['first_name'] .' '. $attrs['second_name'] .' '. $attrs['last_name'],'members.first_name').'</td>';\r
+               echo '<td>'.AT_print(get_display_name($user_id), 'members.full_name').'</td>';  \r
+               \r
+               if ($attrs['privileges'] != 0) {\r
+                       echo '<td>'._AT('assistant').'</td>';\r
+               } else if ($attrs['approved'] == 'a') {\r
+                       /* if alumni display alumni */\r
+                       echo '<td>'._AT('alumni').'</td>';\r
+               } else if ($attrs['approved'] == 'y') {\r
+                       if ($user_id == $system_courses[$_SESSION['course_id']]['member_id']) {\r
+                               echo '<td>'._AT('instructor').'</td>';\r
+                       } else {\r
+                               echo '<td>'._AT('enrolled').'</td>';\r
+                       }\r
+               } else {\r
+                       echo '<td></td>';\r
+               }\r
+               \r
+               if ($attrs['online'] == TRUE) {\r
+                       echo '<td><strong>'._AT('user_online').'</strong></td>';\r
+               } else {\r
+                       echo '<td>'._AT('user_offline').'</td>';\r
+               }\r
+\r
+               echo '</tr>';\r
+       }       \r
+} else {\r
+       echo '<tr><td colspan="3">' . _AT('none_found') . '</td></tr>';\r
+}\r
+?>\r
+</tbody>\r
+</table>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/add_note.php b/documentation/add_note.php
new file mode 100644 (file)
index 0000000..3f210d7
--- /dev/null
@@ -0,0 +1,105 @@
+<?php\r
+require(dirname(__FILE__) .'/common/vitals.inc.php');\r
+function my_add_null_slashes( $string ) {\r
+    return ( $string );\r
+}\r
+\r
+if ( get_magic_quotes_gpc() == 1 ) {\r
+       $addslashes = 'my_add_null_slashes';\r
+} else {\r
+       $addslashes = 'addslashes';\r
+}\r
+\r
+\r
+if (isset($_POST['submit'])) {\r
+       $_POST['email'] = str_replace('@', ' at ', $_POST['email']);\r
+       $_POST['email'] = str_replace('.', ' dot ', $_POST['email']);\r
+       $_POST['email'] = str_replace('<', '&lt;', $_POST['email']);\r
+\r
+       $_POST['note']  = str_replace('<', '&lt;', $_POST['note']);\r
+\r
+       $_POST['email']   = $addslashes($_POST['email']);\r
+       $_POST['note']    = $addslashes($_POST['note']);\r
+       $_POST['section'] = $addslashes($_POST['section']);\r
+       $_POST['page']    = $addslashes($_POST['page']);\r
+\r
+       // all this stuff has to go into some common vitals type file.\r
+\r
+       $enable_user_notes = false;\r
+\r
+       $config_location = '../include/config.inc.php';\r
+       if (is_file($config_location) && is_readable($config_location)) {\r
+               require($config_location);\r
+               $db = mysql_connect(DB_HOST . ':' . DB_PORT, DB_USER, DB_PASSWORD);\r
+               mysql_select_db(DB_NAME, $db);\r
+\r
+               // check atutor config table to see if handbook notes is enabled.\r
+               $sql    = "SELECT value FROM ".TABLE_PREFIX."config WHERE name='user_notes'";\r
+               $result = @mysql_query($sql, $db);\r
+               if (($row = mysql_fetch_assoc($result)) && $row['value']) {\r
+                       define('AT_HANDBOOK_ENABLE', true);\r
+                       $enable_user_notes = true;\r
+               }\r
+               define('AT_HANDBOOK_DB_TABLE_PREFIX', TABLE_PREFIX);\r
+       }\r
+       if (!defined('AT_HANDBOOK_ENABLE')) {\r
+               // use local config file\r
+               require('./config.inc.php');\r
+       }\r
+\r
+       if (!$db && defined('AT_HANDBOOK_ENABLE') && AT_HANDBOOK_ENABLE) {\r
+               $db = @mysql_connect(AT_HANDBOOK_DB_HOST . ':' . AT_HANDBOOK_DB_PORT, AT_HANDBOOK_DB_USER, AT_HANDBOOK_DB_PASSWORD);\r
+               if (@mysql_select_db(AT_HANDBOOK_DB_DATABASE, $db)) {\r
+                       $enable_user_notes = true;\r
+               }\r
+       }\r
+\r
+       if ($enable_user_notes) {\r
+               // insert into DB\r
+               $sql = "INSERT INTO ".AT_HANDBOOK_DB_TABLE_PREFIX."handbook_notes VALUES (NULL, NOW(), '$_POST[section]', '$_POST[page]', 0, '$_POST[email]', '$_POST[note]')";\r
+               mysql_query($sql, $db);\r
+               header('Location: '.$_POST['section']. '/' . $_POST['page'].'?noted');\r
+               exit;\r
+       }\r
+}\r
+\r
+?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html lang="en">\r
+<head>\r
+       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />\r
+       <title><?php get_text('add_note'); ?></title>\r
+       <link rel="stylesheet" href="common/styles.css" type="text/css" />\r
+<style type="text/css">\r
+div.input-form div.row {\r
+       margin-bottom: 10px;\r
+}\r
+</style>\r
+</head>\r
+<body>\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<input type="hidden" name="section" value="<?php echo $section; ?>" />\r
+<input type="hidden" name="page" value="<?php echo htmlspecialchars($_GET['p']); ?>" />\r
+\r
+<div class="input-form">\r
+       <div class="row">\r
+               <p><?php get_text('add_note_blurb'); ?></p>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <label for="email"><?php get_text('email_name'); ?>:</label><br />\r
+               <input type="text" name="email" value="" id="email" size="40" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <label for="note"><?php get_text('your_note');?>:</label><br />\r
+               <textarea name="note" id="note" cols="50" rows="20"></textarea>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php get_text('add_note'); ?>" />\r
+       </div>\r
+\r
+</form>\r
+\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/documentation/admin/administrators.php b/documentation/admin/administrators.php
new file mode 100644 (file)
index 0000000..dd0a3dd
--- /dev/null
@@ -0,0 +1,23 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Administrators</h2>
+       <p>An ATutor installation can be maintained by multiple administrators, each with their own privileges. The three kinds of administrator accounts are described below.</p>
+
+       <dl>
+               <dt>Super Administrator</dt>
+               <dd>This administrator has no restrictions and has access to all of the administrator options. This is the only administrator type that can create and delete other administrator accounts. There must always be at least one Super Administrator account.</dd>
+
+               <dt>Active Administrator</dt>
+               <dd>An administrator account whose access is limited. This administrator only has privileged access to sections that they were assigned to when their account was created by the Super Administrator.</dd>
+
+               <dt>Inactive Administrator</dt>
+               <dd>An administrator account that has not been assigned any access privileges. As a result, this administrator cannot login.</dd>
+       </dl>
+
+       <h3>Create Administrator Account</h3>
+       <p>To make a new administrator, follow the <em>Create Administrator Account</em> link, enter the login name, password, real name and email and select the appropriate administrative privileges to be assigned to this account.</p>
+
+       <h3>Administrator Activity Log</h3>
+       <p>The <em>Administrator Activity Log</em> lists all actions made to the ATutor database tables. Viewing a log entry will give detailed information about the selected activity. The log can be reset by using the <em>Reset Log</em> feature.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/admin/auto_enroll.php b/documentation/admin/auto_enroll.php
new file mode 100644 (file)
index 0000000..dfd984d
--- /dev/null
@@ -0,0 +1,15 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate: 2006-06-29 11:21:18 -0400 (Thu, 29 Jun 2006) $'; ?>
+
+<h2>Auto-Enroll at Registration</h2>
+       <p>Administrators can use this tool to generate a unique URL for the ATutor registration screen, so that when new users follow the link and register, they are automatically enrolled in a specified number of courses. Once the URL is generated, make it available to perspective students so they can register, enroll, and login in one easy step. When students access the registration form using the link, the selected courses will be listed on the form, and when the registration is complete, those courses will be added to the student's My Start Page, and he or she will be logged in.</p>
+       <p> Click on <strong>Create/Edit Auto Enrollment</strong> to create an auto-enroll URL</p>
+
+       <dl>
+               <dt>Title</dt>
+               <dd>This should be a general reference that encompasses the grouping of courses. For example, if students will be enrolled in introductory Boilogy 101, Botany 101, and Zoology 101, the title might be "First Year Natural Science" .</dd>
+
+               <dt>Courses to Enroll</dt>
+               <dd>Select from the available courses on the system to have them added to the auto-enroll grouping of courses for the title described above. Once all the required courses have been choosen, press the <kdb>Save</kdb> button to generate the link </dd>
+       </dl>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/admin/backups.php b/documentation/admin/backups.php
new file mode 100644 (file)
index 0000000..3bf21f9
--- /dev/null
@@ -0,0 +1,20 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Backups</h2>
+       <p>A course backup includes all available course material as an archive in a format specific to ATutor. Backups are forwards compatible with future versions of ATutor but may not be backwards compatible with previous versions of ATutor. Once a backup is created, it can be downloaded for safe-keeping, imported into another ATutor installation, used as the basis for a newly created course, and available in the originating course's Backup Manager. Instructor can also create their own course backups from within a course.</p>
+
+<h3>Creating Backups</h3>
+       <p>To create a backup, use the <em>Create Backup</em> link in the sub-navigation. The number of backups a single course can keep on the server is defined by the <a href="system_preferences.php">System Preferences</a> <em>Course Backups</em> option.</p>
+
+       <p>Administrators can create backups for any course, while instructors can only create backups of courses they own.</p>
+
+<h3>Restoring Backups</h3>
+
+       <p>Restoring a backup as an administrator is similar to restoring a backup as an instructor, with the added option of being able to select which course the backup should be restored into.</p>
+
+       <p>For details on restoring a backup into a course, see the Backup Manager's <a href="../instructor/creating_restoring.php">Restoring Backups</a> section in the Instructor Documentation.</p>
+
+<h3>Managing Backups</h3>
+       <p>Backups can be downloaded to the administrator's hard-drive for safe-keeping by using the <code>Download</code> button. Backups can also be edited or deleted.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/admin/categories.php b/documentation/admin/categories.php
new file mode 100644 (file)
index 0000000..68dc969
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Course Categories</h2>
+       <p>Categories are used for grouping related courses. This is helpful when viewing courses in the course browser. Courses can be associated with categories when they are created, or at a later time by editing their properties. Course categories can also be associated with Themes if the <a href="system_preferences.php">System Preferences</a> <em>Theme Specific Categories</em> option is enabled.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/configuration.php b/documentation/admin/configuration.php
new file mode 100644 (file)
index 0000000..8a0c97c
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Administrator Home</h2>
+       <p>The Administrator Home page is the first screen after logging in. It displays a linked list of the administrative tools, shows new and pending <a href="instructor_requests.php">Instructor Requests</a>, provides the ability to check for the latest version of ATutor by connecting to the atutor.ca website, and basic installation statistics and information.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/courses.php b/documentation/admin/courses.php
new file mode 100644 (file)
index 0000000..3e75027
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Courses</h2>
+       <p>An administrator can create and manage courses, shared forums, and course categories without having to login as a course instructor.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/admin/create_patches.php b/documentation/admin/create_patches.php
new file mode 100644 (file)
index 0000000..7bb34b8
--- /dev/null
@@ -0,0 +1,42 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate: 2006-06-29 11:25:07 -0400 (Thu, 29 Jun 2006) $'; ?>
+
+<h2>Creating Patches</h2>
+
+<p>If you happen to come across a bug you can fix, or have a new feature you would like added to the ATutor public distribution, you can use Create Patch to put your changes into a form that can be easily added to the ATutor public code. Or, if you have a feature you are adding to one ATutor installation that you would like to have added to another, Create Patch is ideal for reproducing your feature across installations. If you are creating new features that are not going to become part of the ATutor public source code, you can build them into a patch so they can be reapplied from version to version as you upgrade your ATutor system. Creating patches does require knowledge of PHP, and of SQL if you plan on creating a patch that changes the ATutor database. Please refer to the appropriate documentation for information on PHP and SQL. <p>
+
+<dl>
+       <dt>ATutor Patch ID</dt>
+       <dd>The patch id you give to your patch must be different from all patches available for the particular version of ATutor it applies to. It is suggested you prefix your patches with a special identifier that represents the author or the authoring organization. If for example the University of Toronto is creating the patch, a patch ID might look like "uoft_0002."</dd>
+       <dt>ATutor Version to Apply</dt>
+       <dd>This needs to be the exact version number of the ATutor version the patch applies to (e.g 1.6). including any minor version numbers (e.g 1.6.1.2)  The exact version number can be found on the Administrator open screen under "Statistics and Information." In most cases when applying a patch created for an older version of ATutor, the "ATutor version to Apply" will need to be adjusted. Or, this can be adjusted manually in the patch.xml file included with the source code of the patch.
+       </dd>
+       <dt>Description</dt>
+       <dd>This should be a detailed description of what the patch does. Example might include "fixes problem uploading files to filemanager" for a bug fix, or "added a timer function to tests" for an added feature, or "removes registration tab" for a feature adjustment, etc. Include enough detail so those applying the patch understand exactly what it will do..</dd>
+       <dt>SQL Statement</dt>
+       <dd>This optional field can be used to insert SQL commands which modify the ATutor database. It might be used to write an SQL statement to modify and existing table, such as changing a data type, or a field size, or to add or remove an field. It can also be used to insert SQL that generates a new table for a new feature created by a patch, or it can be used to insert data into a table used by a feature created by the patch. Any SQL can be included in this field. Be careful when running SQL, that that SQL is not going to interfere with upgrade SQL. If you are changing table structures and those same tables are being altered during an upgrade, the upgrade may fail.</dd>
+       <dt>Dependant Patches</dt>
+       <dd>It is common for later patches to require changes from earlier patches before they can be installed. If this is the case for the patch you are creating, enter the patch IDs into the Dependant Patch ID field. Click on Add Dependent Patch if additional dependencies are required. Be sure to check the patches on the opening screen of the Patcher to see if the file you are modifying with your patch is  being modified by an update.atutor.ca patch. If they are modifying the same files, you may need to include the ID numbers for those patches in the Dependant Patches for the patch your are creating.</dd>
+       <dt>Files</dt>  
+       <dd>This area is where most ATutor patches are created. Click on <strong>Add File</strong>  to generate a patch block. A patch block can include one of four actions on the file being modified, as described below. As many patch blocks as required can be added to a patch. </dd>
+               <dl>
+       <dt>Add File</dt>
+       <dd>The <strong>Add</strong> action can be used to add a new file to ATutor. This action is often used in conjuction with other patch blocks that alter or delete files, to add a replacement file for one deleted, or to perhaps add a required or include file needed by a modified section in the file being changed. In the <strong>File Name</strong> field enter the file name to be assigned to the file when it is installed. In the <strong>Directory</strong> field enter the <i>relative path</i> from the ATutor root directory in which the modified file is or will exist. Select  from <strong>Upload File</strong> using the Browse button to locate the file in your local computer's file system. Note that the upload file can have any name. It will be renamed to the file name listed in the File Name field when it is installed.</dd>
+       <dt>Alter File</dt>
+       <dd>This option is used when you wish to make changes to a piece of code within an existing source code file. In the <strong>File Name</strong> field enter the name of the file in the ATutor source code that will be altered. In the <strong>Directory</strong> field enter the relative path to the directory in which the to be alter file exists, relative to the ATutor root directory. In the <strong>Code To Replace From</strong> field copy the code from the original file the will be replaced, or appended to, and in the <strong>Code To Replace To</strong> field enter to code that will replace the code above in the <i>From</i> field. Or, if you are adding code instead of replacing code, include the code from the field above so it gets added back if you are only using that code as a way of identifying a location in the file where new code is being added.</dd>
+       <dt>Delete File</dt>
+       <dd>This option will remove files from ATutor. In the <strong>File Name</strong>  field enter the name of the file to be deleted. In the <strong>Directory</strong> field enter the path to the directory in which the to be delete file exists, relative to the root directory of the ATutor installation. </dd>
+       <dt>Overwrite File</dt>
+       <dd>This option is used to replace an existing file in ATutor with a new one. In the <strong>File Name</strong>  field enter the name of the file to be replaced. In the <strong>Directory</strong> field enter the path to the directory in which the to be replaced file exists, relative to the root directory of the ATutor installation. In the <strong>Upload File</strong> field use the Browse button to choose a file from your local computer to replace the specified file. The upload file may be named anything. It will be renamed to the file it is replacing when the patch is installed.</dd>
+       </dl>
+       <dt>Create Patch</dt>
+       <dd>Click on this button to build the patch into a downloadable zip file. This zip file can then be uploaded in the Upload field on the main Patcher screen to apply a patch to a system.</dd>
+       <dt>Save Patch</dt>
+       <dd>Click on this button to save the developing patch to the ATutor database for future reference. Though it is not required, you should save a copy of the patch in this way, so it can be retrieved and edited if necessary. Or, if a patch takes more than a single sitting to build, you can save it, then retrieve it later to continue.</dd>
+       <dt>Cancel</dt>
+       <dd>Press this button to ignore the latest changes to the patch, and return to My Own Patches Screen.</dd>
+
+</dl>
+
+
+
+<?php require('../common/body_footer.inc.php');?>
\ No newline at end of file
diff --git a/documentation/admin/creating_courses.php b/documentation/admin/creating_courses.php
new file mode 100644 (file)
index 0000000..23353bd
--- /dev/null
@@ -0,0 +1,17 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>Creating Courses</h2>\r
+\r
+<p>See <a href="../instructor/creating_courses.php">Creating Courses</a> documentation for Instructors.</p>\r
+\r
+<p>In addition, administrators have access to the following properties:</p>\r
+\r
+       <dl>\r
+               <dt>Course Quota</dt>\r
+               <dd>Defines the maximum size of a course.  That is, the amount of space each course's file manager can have.</dd>\r
+\r
+               <dt>Max File Size</dt>\r
+               <dd>Defines the maximum size allowed for a file being uploaded to a course's file manager.</dd>\r
+       </dl>\r
+<p>Note that Max File Size limitations can not be set higher than that allowed in the PHP settings for the system. The maximum allowable upload size can be increased by editing the values of <kbd>upload_max_filesize</kbd> and <kbd>post_max_size</kbd> in the system's <kbd>php.ini</kbd> configuration file.</p>\r
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/creating_themes.php b/documentation/admin/creating_themes.php
new file mode 100644 (file)
index 0000000..aedc396
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Creating Themes</h2>
+       <p>The process for creating a theme is basically to export an existing theme from ATutor, import it back into ATutor, then modify the files of the copied theme. Details about creating themes can be found in the <kbd><a href="../../themes/themes_readme.txt">themes_readme.txt</a></kbd> file found in the <kbd>/themes</kbd> directory of your ATutor installation. Also see the comments included in the files of the Default ATutor theme for additional details.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/admin/cron_setup.php b/documentation/admin/cron_setup.php
new file mode 100644 (file)
index 0000000..0a47346
--- /dev/null
@@ -0,0 +1,32 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Cron Set-Up</h2>
+
+       <p>ATutor operates best with the help of an automated event scheduler, commonly known as a <em>cron job</em>. The cron interval should be set at between 5-30 minutes, depending on server resources. Setting the cron to 10-15 minutes is recommended.</p>
+
+       <p>The cron is run by requesting a specific ATutor page, and can be initiated by any machine that has an Internet connection and access to the ATutor installation.</p>
+
+       <p>Notice that the URL being used will be unique for each installation and that for security reasons the requested URL includes a secret six-character alpha-numerica authentication key. The cron will not run if the key is incorrect or missing.</p>
+
+       <p>The <em><a href="system_preferences.php">Mail Queue</a></em> feature requires the cron to be set-up and running correctly before it can be enabled.</p>
+
+       <h3>Unix Setup</h3>
+               <ol>
+                       <li>Enter your hosts cron utility, either using an existing web interface or from the shell with the command <code>crontab -e</code>.</li>
+                       <li>To run the cron every 10 minutes enter one of the following lines into the crontab editor:<br />
+                         <code>*/10 * * * * wget -q -O /dev/null http://<em>your-server.com/atutor/</em>admin/cron.php?k=<em>SECRET-KEY</em></code><br />
+                         Or<br />
+                         <code>*/10 * * * * lynx -dump http://<em>your-server.com/atutor/</em>admin/cron.php?k=<em>SECRET-KEY</em> > /dev/null</code>
+                         <p>Replace <em><code>your-server.com/atutor/</code></em> with the full server and path to your ATutor installation.</p>
+                         <p>Replace <em><code>SECRET-KEY</code></em> with the key provided on the Cron Configuration page in your ATutor Administration section.</p>
+                         <p>Replace <code>10</em> with the desired interval.</p>
+                         </li>
+               </ol>
+
+               <p>Note: If your site uses <acronym title="Secure Sockets Layer">SSL</acronym> then replace <em>http</em> with <em>https</em> and you may also need to add <code>--no-check-certificate</code> to <code>wget</code>.</p>
+
+       <h3>Windows et al Setup</h3>
+               <p><a href="http://www.webcron.org">webcron.org</a> offers free web-based cron services and is available in multiple languages.</p>
+
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/default_preferences.php b/documentation/admin/default_preferences.php
new file mode 100644 (file)
index 0000000..dc25793
--- /dev/null
@@ -0,0 +1,7 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Default Preferences</h2>
+
+<p>The default preferences are only applied to newly created accounts at the time of their creation and to guests when accessing public courses. Note that the default theme is set in the <a href="themes.php">Themes</a> area, and default language is set in the <a href="system_preferences.php">System Preferences</a> area.  Also, Auto-Login is not decided by administrators. Members may alter their settings once they have logged in by going to the Preferences area in the main navigation. For more information, see <a href="../general/preferences.php">Preferences</a> in the general help area.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/default_side_menu.php b/documentation/admin/default_side_menu.php
new file mode 100644 (file)
index 0000000..d4b4a07
--- /dev/null
@@ -0,0 +1,7 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Default Side Menu</h2>
+
+       <p>Administrators are able to set the side menu dropdowns for newly created courses by specifying side menu defaults. Instructors can alter these settings after a course is created by going to Properties under the Manage area.  For more information, see <a href="../instructor/side_menu.php">Side Menu</a> in the instructor help area.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/default_student_tools.php b/documentation/admin/default_student_tools.php
new file mode 100644 (file)
index 0000000..bac5995
--- /dev/null
@@ -0,0 +1,7 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Default Student Tools</h2>
+
+       <p>Administrators are able to set the tools that will appear in the main navigation and the home page for newly created courses by specifying student tool defaults. Instructors can alter these settings after a course is created by going to <a href="../instructor/student_tools.php">Student Tools</a> area  under the Manage tab.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/email_users.php b/documentation/admin/email_users.php
new file mode 100644 (file)
index 0000000..bd96b9b
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Email Users</h2>
+       <p>The Email Users feature allows an administrator to send an email to all students, instructors, or both. Unconfirmed and Disabled accounts are not included in the mailing. The email address specified in the <a href="system_preferences.php">System Preferences</a> is used as the reply-to address for the email(s).</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/en/index.php b/documentation/admin/en/index.php
new file mode 100644 (file)
index 0000000..35fa5ae
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg                    */
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: index.php 5866 2005-12-15 16:16:03Z joel $
+
+header('Location: ../index.php'); // no need for english
+exit;
+?>
\ No newline at end of file
diff --git a/documentation/admin/enrollment.php b/documentation/admin/enrollment.php
new file mode 100644 (file)
index 0000000..e2be8c6
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate: 2006-06-29 11:25:07 -0400 (Thu, 29 Jun 2006) $'; ?>
+
+       <h2>Enrollment</h2>
+       <p>The Enrollment list for a particular course determines which of your students have access to the course content and course management tools. Instructors can create, import and export student lists. </p>
+       
+       <p>To administer members of a course, select the <em>Enrollment</em> tab, then select a course and press the <em>Filter</em> button.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/admin/enrollment_privileges.php b/documentation/admin/enrollment_privileges.php
new file mode 100644 (file)
index 0000000..c9f30bf
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate: 2006-06-29 11:25:07 -0400 (Thu, 29 Jun 2006) $'; ?>
+
+<h2>Privileges</h2>
+
+<p>Students who are enrolled in a course can be assigned course administrative privileges. This allows students to perform actions like managing content, creating and marking tests, managing groups, or moderating forums or the chat. This tool is useful for creating teaching assistants, or for creating multiple instructors for a course.  Select the users you wish to give privileges to, and use the <em>Privileges</em> button.  Then choose which tools you want each user to have access to and use the <em>Save</em> button.</p>
+
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/admin/error_logging.php b/documentation/admin/error_logging.php
new file mode 100644 (file)
index 0000000..e92beec
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Error Logging</h2>
+       <p>Error logging is available to administrators as a trouble shooting tool. Should the system be giving error messages, a daily list of these errors are collected and available for review or to be bundled up and sent to the ATutor team for investigation. When using the atutor.ca support forums, attaching any error logs may be helpful in finding solutions to problems on your system.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/admin/feeds.php b/documentation/admin/feeds.php
new file mode 100644 (file)
index 0000000..c25e196
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Syndicated Feeds</h2>
+       <p>Instructors may display syndicated feeds in the side menu of their courses. The choice of feeds available to them is controlled by the administrator. Feeds may be managed by going to the <em>Syndicated Feeds</em> link under the System Preferences tab. </p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/admin/forums.php b/documentation/admin/forums.php
new file mode 100644 (file)
index 0000000..ec45b10
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Forums</h2>
+       <p>This section allows administrators to create regular course-specific forums as well as shared cross-course forums. A shared forum is available to all courses specified to use it, allowing users from different courses to communicate with eachother in one forum. Only administrators can create shared forums, though instructors or privileged users in any of the courses sharing a forum can manage its messages.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/fr/index.php b/documentation/admin/fr/index.php
new file mode 100644 (file)
index 0000000..c71e41f
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg                    */
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: index.php 5866 2005-12-15 16:16:03Z joel $
+
+$parts = pathinfo($_SERVER['PHP_SELF']);
+
+$dir_parts = explode('/', $parts['dirname']);
+$last_dir_name = end($dir_parts);
+
+header('Location: ../index.php?' . $last_dir_name);
+exit;
+?>
\ No newline at end of file
diff --git a/documentation/admin/google_key.php b/documentation/admin/google_key.php
new file mode 100644 (file)
index 0000000..f892c10
--- /dev/null
@@ -0,0 +1,7 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Google Key</h2>
+
+       <p>For the Web Search module to function, an administrator must first create an account and obtain a license key at <a href="http://google.com/apis" target="_new">google.com/apis</a> and enter it on this page. The google web search can then be used by students as an external embedded service within ATutor.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/importing_themes.php b/documentation/admin/importing_themes.php
new file mode 100644 (file)
index 0000000..b92096c
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Importing/Exporting Themes</h2>
+       <p>Themes can be imported into, or exported from, ATutor using the Themes manager in the ATutor administrators' configuration tools. An existing theme can be exported, then imported back into an ATutor installation to create a copy, after which the copy can be modified to create a new theme. Themes can be exported and shared with others. See the <a href="http://www.atutor.ca/atutor/themes/index.php" target="_new">Themes page on atutor.ca</a> for a list of available themes, and for a place to share your themes.</p>
+
+       <p>To import a theme the <kbd>./themes/</kbd> directory must be writable. On Windows machines using multiple user accounts, that directory will have to be shared to provide write access to it. On Unix machines the command <code>chmod a+rw themes</code> should be used to make the directory writable.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/index.php b/documentation/admin/index.php
new file mode 100644 (file)
index 0000000..04121b3
--- /dev/null
@@ -0,0 +1 @@
+<?php require('../index.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/installation.php b/documentation/admin/installation.php
new file mode 100644 (file)
index 0000000..f69f56d
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Installation</h2>
+       <p>This section describes the requirements and important considerations needed for running ATutor. It also details the steps involved in installing and upgrading an installation.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/admin/instructor_requests.php b/documentation/admin/instructor_requests.php
new file mode 100644 (file)
index 0000000..33f3d66
--- /dev/null
@@ -0,0 +1,10 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Instructor Requests</h2>
+       <p>If the <a href="system_preferences.php">System Preferences</a> <em>Allow Instructor Requests</em> option is enabled and the <em>Auto Approve Instructor Requests</em> option is disabled, then pending instructor account requests will be listed on this page.</p>
+
+       <p>Using the <code>Deny</code> or <code>Approve</code> buttons after selecting an entry will remove it from the list and take the appropriate action. An email message will be sent to the account holder notifying them of the change.</p>
+
+       <p>Note that the number of pending Instructor Requests is always listed on the <a href="configuration.php">Administrator Home</a> page.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/introduction.php b/documentation/admin/introduction.php
new file mode 100644 (file)
index 0000000..977b8ee
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Introduction</h2>
+       <p>Welcome to the ATutor Administrator Documentation! This documentation is intended for those who manage ATutor systems. Also see the <a href="../instructor/" target="_top">Instructor Documentation</a> for more about creating and managing courses. </p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/languages.php b/documentation/admin/languages.php
new file mode 100644 (file)
index 0000000..8661a5e
--- /dev/null
@@ -0,0 +1,58 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Languages</h2>
+       <p>ATutor can be displayed in many different languages! Through the Langauge Manager completed languages packs can be selected and imported directly from the atutor.ca website. </p>
+
+<h3>Managing Existing Languages</h3>
+       <p>Installed languages can be edited, deleted or exported as an ATutor language pack for redistribution. When exporting a language, a download prompt will appear asking to download a zip file of the language pack.</p>
+       
+       <p>Editing the language properties allows you to change the following:
+       <ul>
+               <li>Language Code</li>
+               <li>Locale</li>
+               <li>Character Set</li>
+               <li>Direction</li>
+               <li>Left to Right, Right to Left</li>
+               <li>Regular Expression</li>
+               <li>Language name translated</li>
+               <li>Language name in English</li>
+       </ul>
+       </p>
+
+       <p>Note that the default language (as specified in the <a href="system_preferences.php">System Preferences</a> <em>Default Language</em>) cannot be disabled or deleted unless another language has been installed.</p>
+
+
+<h3>Importing Languages</h3>
+       <p>Language packs can be imported either manually by retreiving the package and then importing it into ATutor, or automatically by having ATutor connect to the atutor.ca language repository directly.</p>
+
+       <p>To <em>manually</em> import a new language pack:</p>
+       <ol>
+               <li>Visit <a href="http://atutor.ca/atutor/translate/index.php" target="_new">atutor.ca/atutor/translate/</a> to download one of the available language packs for your version.</li>
+               <li>Use the <code>Browse...</code> button to find the downloaded language pack.</li>
+               <li>Use the <code>Import</code> button to import the language.</li>
+       </ol>
+
+       <p>If your ATutor installation is connected to the Internet and can contact the atutor.ca website, then it will try to retrieve the list remotely. To <em>automatically</em> import a new language pack from within ATutor:</p>
+
+       <ol>
+               <li>Select the language you want to import from the drop down.</li>
+               <li>Use the <code>Import</code> button to import the selected language.</li>
+       </ol>
+
+       <p>If your installation cannot retrieve the language list from atutor.ca, a message indicating so will be presented rather than a drop down list. In this case you will have to use the manual method described above.</p>
+
+
+<h3>Translating ATutor</h3>
+
+       <p>Administrators have the ability to customize an installation's language. In order to translate a language, 
+       <ol>
+               <li>Set the AT_DEVEL_TRANSLATE constant in /include/vitals.inc.php to '1'</li> 
+               <li>Set the session language to the language you wish to translate by using the language selector at the bottom of the screen.</li>
+               <li>Use the <code>Translate</code> button to pop up a translation window.</li>
+       </ol>
+       </p>
+
+       <p>You can contribute to the ATutor community by  exporting a language pack from your ATutor installation, and attaching it to a message in the atutor.ca <a href="http://atutor.ca/forum/4/1.html">Translation Forum</a>. Also see the <a href="http://atutor.ca/atutor/docs/translate.php">Translator Documentation</a> for further details about translating ATutor.</p>
+
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/admin/link-out.gif b/documentation/admin/link-out.gif
new file mode 100644 (file)
index 0000000..ecef094
Binary files /dev/null and b/documentation/admin/link-out.gif differ
diff --git a/documentation/admin/managing_existing_themes.php b/documentation/admin/managing_existing_themes.php
new file mode 100644 (file)
index 0000000..0965c0c
--- /dev/null
@@ -0,0 +1,28 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Managing Existing Themes</h2>
+       <p>All available themes on an ATutor system are listed in the Administrator's Themes section.</p>
+
+       <dl>
+               <dt><code>Preview</code></dt>
+               <dd>Use the Preview button to test the theme to make sure it doesn't break. If a previewed theme breaks, simply log-out and login again to restore the default theme. The Preview button can also be used to preview disabled themes. This feature is available in ATutor 1.5.1+.</dd>
+
+               <dt><code>Enable/Disable</code></dt>
+               <dd>Enabled themes are available to users in their Preferences. Themes can be disabled, helpful if you are modifying a theme. If a student's preferred theme is disabled, the system default theme will be used in its place.</dd>
+
+               <dt><code>Set as Default</code></dt>
+               <dd>If a theme is set as the Default Theme, it will display for students who have not selected a prefered theme, and it will be displayed on public pages, such as the Login screen or Registration screen.</dd>
+
+               <dt><code>Export</code></dt>
+               <dd>Any theme can be exported from an ATutor installation to share with others.  It can also be imported back into an ATutor installation as a copy, available to be modified for creating a new theme.</dd>
+
+               <dt><code>Delete</code></dt>
+               <dd>A theme is removed from the system if the Delete button is used. The Default theme can not be deleted.</dd>
+       </dl>
+
+       <h3>Category Themes</h3>
+       <p>If there are <a href="categories.php">Course Categories</a> defined and the <a href="system_preferences.php">System Preferences</a> <em>Theme Specific Categories</em>  has been enabled, themes can be assigned to categories of courses so they are all displayed with the same look and feel. When defining course categories while Category Themes is enabled, a list of available themes will appear to select from, and assign to each category.</p>
+
+       <p>Note that when Category Themes has been enabled, users will no longer be able to select themes from their personal preference settings.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/master_student_list.php b/documentation/admin/master_student_list.php
new file mode 100644 (file)
index 0000000..5f1b616
--- /dev/null
@@ -0,0 +1,20 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Master Student List</h2>
+       <p>If the <a href="system_preferences.php">System Preferences</a> <em>Authenticate Against A Master Student List</em> option is enabled, this page will allow an administrator to manage that list. If enabled, only new registrations that validate against the master list will be successful. The master list is flexible and can be used to validate any two fields, one of which is publicly viewable to Administrators, while the other is hidden. A common use of this feature would be to authenticate students using a previously assigned Student ID &amp; Birth Date combination. Two extra fields will appear on the Registration screen when master list authentication is enabled.</p>
+
+       <p>Subsequently, when a student registers for an ATutor account on the system, he/she must provide this authenticating information (such as their student ID and Birth Date). Once an account is authenticated and created, the user will then be associated with the appropriate entry in the Master Student List. If <em>Require Email Confirmation Upon Registration</em> is enabled in <a href="system_preferences.php">System Preferences</a>, the user must confirm his/her account using that email before the account is activated.</p>
+
+       <p>Viewing the Master Student List shows Student ID-Username pairs. Student IDs in the Master Student List that are not associated with any student account are considered to not have been created.</p>
+
+<h3>Importing Student IDs</h3>
+       <p>Importing Student IDs into the Master Student List requires a specifically formatted file. This file can be uploaded under the "Upload List" heading.</p>
+
+       <p>The master list must be imported from a plain text file, where each row in the file contains two fields seperated by a single comma. The first field will be used as the Student ID. The second field will be the PIN or Password which will be encrypted by the ATutor system, once the list is uploaded, so that it cannot be viewed and read by anyone. Those two fields together will be used to authenticate students when creating new accounts. The fields may optionally be enclosed by double quotes. Such a file is known as a <acronym title="Comma Separated Values">CSV</acronym> file and can be generated manually using a text editor, or by any spreadsheet application (such as MS Excel).</p>
+
+       <p>In the example below, a student number and a birth date are used to construct a master list:</p>
+       <pre>"12345", "10/07/54"
+"12346", "23/04/76"
+"12347", "30/05/68"</pre>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/modules.php b/documentation/admin/modules.php
new file mode 100644 (file)
index 0000000..32a7f2c
--- /dev/null
@@ -0,0 +1,12 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Modules</h2>
+       <p>Since version 1.5.2, ATutor provides the facility to install, enable, or disable student, instructor, and administrator tools as modules.</p>
+
+       <p>To install a module it must first be extracted into a unique subdirectory within the <kbd>./mods</kbd> directory of your ATutor installation. It will then be listed on the <em>Install Modules</em> page where more details can be retrieved and the module installed.</p>
+
+       <p>After extracting a module, be sure to see the readme file in the module's top directory for any additional installation instructions or requirements. See the ATutor <a href="../developer/modules.html">Module Development Documentation</a> for information about creating ATutor modules, and review the module files in the Hello World demo module (and other modules) as a model that can be duplicated and modified to quickly add new addon features to an ATutor installation. </p>
+
+<p>Visit the <a href="http://www.atutor.ca/atutor/modules.php" target="_new">ATutor Modules Site</a> for a list of add-on modules for ATutor.</p>
+
+<?php require('../common/body_footer.inc.php');?>
\ No newline at end of file
diff --git a/documentation/admin/my_account.php b/documentation/admin/my_account.php
new file mode 100644 (file)
index 0000000..bd9eec1
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>My Account</h2>
+       <p><em>My Account</em> allows the Administrator to change his/her account password, name, or email address.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/new_installation.php b/documentation/admin/new_installation.php
new file mode 100644 (file)
index 0000000..4901b7b
--- /dev/null
@@ -0,0 +1,46 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>New Installation</h2>
+       <p>Please review the <a href="requirements_recommendations.php">requirements</a> section <em>before</em> attempting to install ATutor. The latest version of ATutor can always be found on the <a href="http://atutor.ca/atutor/download.php" target="_new">atutor.ca downloads</a> page.</p>
+
+       <h3>Windows Considerations</h3>
+               <p>To extract the ATutor <kbd>.tar.gz</kbd> archive you will need an application like <a href="http://winzip.com" target="_new">WinZip</a> or <a href="http://rarlabs.com" target="_new">WinRar</a>.</p>
+               
+       <h3>Unix Considerations</h3>
+               <p>To extract the ATutor <kbd>.tar.gz</kbd> archive, use the command <kbd>tar -zxvf ATutor-version_number.tar.gz</kbd>, which will create a directory called <kbd>ATutor</kbd> in your current working directory.</p>
+
+               <p>Extracting the files on a Windows machine and then uploading them via <acronym title="File Transfer Protocol">FTP</acronym> is not recommended, as it may not preserve the case-sensitive file names.</p>
+
+               <p>Installing on a Unix machine requires some knowledge of file and directory permissions. You will be required to create a content directory and set permissions for that directory and for the <kbd>include/config.inc.php</kbd> file, so that the web server can write to them. The installation will not be successful if the permissions are not correctly set on that file and directory.</p>
+
+               <p>Changing Unix file permissions from the shell prompt: <kbd>chmod a+rw filename</kbd> or <kbd>chmod a+rwx directoryname</kbd>.</p>
+               
+               <p>Changing Unix file permissions from an FTP client: Many FTP clients allow you to change a file's permissions. The option may be labled as "Unix Permissions", "CHMOD", or simply as "Properties" or "Attributes" and will display a window with Read, Write, and Execute checkboxes for Owner, Group, and World; checking the appropriate boxes will change that file's permissions. In our case we need the <kbd>include/config.inc.php</kbd> to be Readable and Writeable by World, and the content directory to be Readable, Writeable, and Executable by World.</p>
+
+       <h3>Installation Procedure</h3>
+               <p>Extract the downloaded archive using the method specified for your system (either Windows or Unix). Open a web browser and enter the address to your new ATutor installation, <kbd>http://your_server.com/path_to_atutor/ATutor/</kbd>, then follow the step-by-step instructions:</p>
+
+               <ol>
+                       <li><strong>Terms of Use</strong><br />
+                               The usage of ATutor is restricted by the <acronym title="Recursive acronym for GNU's Not Unix">GNU</acronym> General Public License (GPL). Your agreement with the GPL is required if you wish to use ATutor. See the <a href="http://atutor.ca/services/licensing.php" target="_new">Licensing section</a> for more details.</li>
+
+                       <li><strong>Database</strong><br />
+                               Enter the required details needed to connect to your MySQL database. The optional <em>Table Prefix</em> (e.g. "AT_") allows ATutor to share an existing database with other applications and tables. The ATutor installation script will attempt to create the database specified, if it does not already exist. This requires that your MySQL user account has permission to create databases and permission to create tables. If this step fails, contact your system administrator to have your MySQL account upgraded to allow creation of new databases, or ask your administrator to create the database for you.</li>
+
+                       <li><strong>Accounts &amp; Preferences</strong><br />
+                               The Super Administrator account is used for managing your ATutor installation. The Super Administrator can also create additional Administrators each with their own privileges and roles once ATutor is installed. The personal account can be used to enroll in or create courses.</li>
+
+                       <li><strong>Content Directory</strong><br />
+                               Create a content directory, preferably outside your web server's document directory for added security, and set permissions as described above. On a Unix machine you will need to manually change the permissions on the listed files and directories in this step. No action is usually required on a Windows server, though in some circumstances Windows users may need to adjust the properties of the specified files and directories to make them writable. Copy the path of the created directory into the text box provided. Ensure that there are no shortcuts or symbolic links in the path.</li>
+
+                       <li><strong>Save configuration</strong><br />
+                               Before reaching the final step the <kbd>include/config.inc.php</kbd> file needs to be writable, otherwise an error will appear. Follow the instructions on the screen if the file permissions need to be changed. If the file does not exist in the <kbd>include/</kbd> directory, then you will need to create an empty text file with the filename <kbd>config.inc.php</kbd>.</li>
+
+                       <li><strong>Anonymous Usage Collection</strong><br />
+                               To assist the development team in serving the ATutor community, you can anonymously submit basic system information to the atutor.ca server.</li>
+
+                       <li><strong>Done!</strong><br />
+                               ATutor installation has been successful and you may now log-in with your personal account or the administrator account created in Step 3.</li>
+               </ol>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/pages.inc.php b/documentation/admin/pages.inc.php
new file mode 100644 (file)
index 0000000..6cecf93
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+// the order matters, b/c it what generates the prev/next links
+       $_pages = array();
+       $_pages['introduction.php']                  = 'Introduction';
+       $_pages['installation.php']                  = 'Installation';
+       $_pages['requirements_recommendations.php']  = 'Requirements &amp; Recommendations';
+       $_pages['new_installation.php']              = 'New Installation';
+       $_pages['upgrading.php']                     = 'Upgrading an Installation';
+       $_pages['configuration.php']                 = 'Administrator Home';
+       $_pages['my_account.php']                    = 'My Account';
+       $_pages['system_preferences.php']            = 'System Preferences';
+       $_pages['default_preferences.php']                       = 'Default Preferences';
+       $_pages['languages.php']                     = 'Languages';
+       $_pages['themes.php']                        = 'Themes';
+       $_pages['importing_themes.php']              = 'Importing/Exporting Themes';
+       $_pages['managing_existing_themes.php']          = 'Managing Existing Themes';
+       $_pages['creating_themes.php']               = 'Creating Themes';
+       $_pages['error_logging.php']                 = 'Error Logging';
+       $_pages['feeds.php']                                             = 'Syndicated Feeds';
+       $_pages['google_key.php']                                        = 'Google Key';
+       $_pages['cron_setup.php']                                        = 'Cron Set-up';
+       $_pages['enrollment.php']                    = 'Enrollment';
+       $_pages['enrollment_privileges.php']         = 'Privileges';
+       $_pages['users.php']                         = 'Users';
+       $_pages['instructor_requests.php']           = 'Instructor Requests';
+       $_pages['master_student_list.php']           = 'Master Student List';
+       $_pages['email_users.php']                   = 'Email Users';
+       $_pages['administrators.php']                = 'Administrators';
+       $_pages['courses.php']                       = 'Courses';
+       $_pages['creating_courses.php']              = 'Creating Courses';
+       $_pages['default_student_tools.php']         = 'Default Student Tools';
+       $_pages['default_side_menu.php']                         = 'Default Side Menu';
+       $_pages['backups.php']                       = 'Backups';
+       $_pages['forums.php']                        = 'Forums';
+       $_pages['auto_enroll.php']                        = 'Auto-Enroll at Registration';
+       $_pages['categories.php']                    = 'Course Categories';
+       $_pages['modules.php']                       = 'Modules';
+       $_pages['patcher.php']                       = 'Patcher';
+       $_pages['create_patches.php']                = 'Create Patches';
+       $_pages['troubleshooting.php']               = 'Troubleshooting';
+?>
diff --git a/documentation/admin/patcher.php b/documentation/admin/patcher.php
new file mode 100644 (file)
index 0000000..89c184c
--- /dev/null
@@ -0,0 +1,22 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate: 2008-04-04 11:25:07 -0400 (Fri, 04 April 2008) $'; ?>
+
+<h2>Patcher</h2>
+       <p>The Patcher was introduce in ATutor 1.6 to allow administrators to update their systems with feature adjustments, security fixes, and other ATutor code changes in between ATutor releases. The Patcher is included as a standard module with ATutor 1.6.1+, and installs as an extra module for 1.6.</p>
+<dl>
+       <dt>The Patch List</dt>
+       <dd>On the opening screen of the Patcher will appear a list of patches available for the version of ATutor you are using, along with a description of each patch.  This list is retrieved from update.atutor.ca, as are the patches themselves, so you must be connected to the Internet. Patches are retrieved from update.atutor.ca by ATutor and applied as necessary. </dd>
+       <dt>File Permissions</dt>
+       <dd>In most cases you will be asked to temporarily grant write permission to the files that need to be updated or replaced, then once the patch has been applied, you will be asked to change the permissions back to read only. It is important that you follow the instructions after patches have been applied, otherwise you run the risk of opening a security hole. 
+       </dd>
+       <dt>Types of Patches</dt>
+       <dd>Patches come in various forms. Some patches replace code in a file with new code. Others replace a file with a new file.  Others may do both on multiple files and multiple code changes. Other patches delete files that are no longer required.</dd>
+       <dt>Required and Non-Required Patches</dt>
+       <dd>In most cases you will want to install patches in the order they appear in the patch list, but not all patches are required patches.  Some feature patches can be ignored if you do not need the features they would add or modify on your system. Other patches will have dependencies, requiring the administrator to install earlier patches before installing a later one. You will be prompted to install previous patches if there are dependencies.</dd>
+       <dt>Checks and File Backups</dt>
+       <dd>If you have made changes to a file the Patcher wishes to change,  you will be prompted to continue or not. The patcher compares your local file with the same file in the ATutor code repository, and if they differ the prompt will display. In many cases  the Patcher can apply patches without changing the code you have modified, but if the code to be replaced was modified, the patch will fail, or if the patch replaces a file, your changes will be lost. In all cases the patcher will create a backup of the files that were modified, identified by the filename plus the patch number added as a suffix. Rename the file to its original name to restore that file back to its original state. You can list these files by clicking the view messages button next to the patch listing after the patch is installed. After you have confirmed that the patches were applied and are working properly, it is safe to delete the backup files, though it does not hurt to keep them around. </dd>
+       <dt>Private Patches</dt>
+       <dd>In some cases private patches can be applied by uploading a patch file through the upload form below the patch list.  Private patches are often those used to apply changes that are not being applied to the ATutor default source code, or to apply custom features, or to share patches between users, etc. When uploading a patch, be sure the patch id, defined in the patch.xml file, is unique . </dd>
+</dl>
+
+
+<?php require('../common/body_footer.inc.php');?>
\ No newline at end of file
diff --git a/documentation/admin/requirements_recommendations.php b/documentation/admin/requirements_recommendations.php
new file mode 100644 (file)
index 0000000..fcd6a72
--- /dev/null
@@ -0,0 +1,75 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Requirements &amp; Recommendations</h2>
+       <p>The first step when installing or upgrading ATutor is to check if the minimum requirements are met. The following describes those checks.</p>
+
+       <h3>File Integrity</h3>
+               <p>The Case Sensitivity check verifies that file names were not converted to lower-case during the extraction process. This is not an issue on case-insensitive operating systems like MS Windows, but is an issue on case-sensative ones like Linux.</p>
+
+       <h3>Web Server</h3>
+               <p>The ATutor development and testing processes are done primarily on Apache 1.3 and Apache 2 (using pre-forking), and as such we strongly recommend them for production environments. ATutor has been successfully installed on other web servers, including, Zeus, lighttpd, Abyss, Zazou Mini Web Server, Microsoft IIS, and Jana-Server.</p>
+
+               <p>The web server can be configured with <acronym title="Secure Sockets Layer">SSL</acronym> for added security or to use a non-standard port and ATutor will function without modification.</p>
+
+
+       <h3>PHP</h3>
+               <p>ATutor is written in the <acronym title="Recursive acronym for PHP: Hypertext Preprocessor">PHP</acronym> language. The PHP configuration file contains many configuration settings that can be changed. The following are the minimum requirements needed to install and use ATutor.</p>
+
+               <dl>
+                       <dt>PHP 4.3.0+</dt>
+                       <dd>PHP 4.3.0 or higher is required. Version 5.2.0 or higher is recommended.</dd>
+
+                       <dt><kbd>zlib</kbd></dt>
+                       <dd>Zlib support must be enabled in PHP; It is used for compressing and uncompressing ZIP files.</dd>
+
+                       <dt><kbd>mysql</kbd></dt>
+                       <dd>MySQL support must be enabled in PHP.</dd>
+
+                       <dt><kbd>safe_mode = Off</kbd></dt>
+                       <dd><kbd>safe_mode</kbd> must be disabled in PHP. ATutor cannot function with the restrictions enforced when <kbd>safe_mode</kbd> is enabled.</dd>
+
+                       <dt><kbd>file_uploads = On</kbd></dt>
+                       <dd>File uploads support must be enabled in PHP.</dd>
+
+                       <dt><kbd>upload_max_filesize</kbd> >= 2 MB</dt>
+                       <dd>This option specifies the maximum size of files that can be uploaded to ATutor.</dd>
+
+                       <dt><kbd>post_max_size</kbd> >= 8 MB</dt>
+                       <dd>This value must be larger than the <kbd>upload_max_filesize</kbd>.</dd>
+
+                       <dt><kbd>sessions</kbd></dt>
+                       <dd>Sessions support must be enabled in PHP.</dd>
+
+                       <dt><kbd>session.auto_start = 0</kbd></dt>
+                       <dd><kbd>session.auto_start</kbd> must be disabled in PHP.</dd>
+
+                       <dt><kbd>session.save_path</kbd></dt>
+                       <dd><kbd>session.save_path</kbd> must be set to a real path that can store session data.</dd>
+
+                       <dt><kbd>.</kbd> in <kbd>include_path</kbd></dt>
+                       <dd><kbd>.</kbd> must be in the list of paths in the <kbd>include_path</kbd> option.</dd>
+               </dl>
+
+
+               <p>Additionally, the following <kbd>php.ini</kbd> configuration settings are recommended:</p>
+               <pre>display_errors          = Off
+arg_separator.input     = ";&amp;"
+register_globals        = Off
+magic_quotes_gpc        = Off
+magic_quotes_runtime    = Off
+allow_url_fopen         = On
+allow_url_include       = Off
+register_argc_argv      = Off
+zlib.output_compression = On
+session.use_trans_sid   = 0
+</pre>
+
+       <h3>MySQL</h3>
+               <p>Currently ATutor only supports the MySQL database. MySQL 4.0.2 or higher, or 4.1.10 or higher is required. MySQL 4.0.20 and higher or 4.1.10 and higher is recommended, especially if you are using languages that would benefit from being represented in the <acronym title="UCS Transformation Format, a multibyte character encoding format.">UTF-8</acronym> character set. As ATutor moves towards utilizing UTF-8 throughout, support for older version of MySQL will be removed.</p>
+
+               <p>A database user account with database creation privileges is required if your database does not already exist. That same user will then need table creation privileges for the chosen database. See the MySQL chapter <a href="http://dev.mysql.com/doc/mysql/en/privileges.html" target="_new">How the Privilege System Works</a> for additional information.</p>
+
+       <h3>Web Browser</h3>
+               <p>ATutor makes use of many new HTML features that are only supported in recent web browsers. Though ATutor is designed to function effectively in older browsers we strongly recommend using the latest version of your favorite browser. We recommend <a href="http://getfirefox.com" target="_new">FireFox</a> for either Windows, *nix or Mac OS X.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/styles.css b/documentation/admin/styles.css
new file mode 100644 (file)
index 0000000..b6bae62
--- /dev/null
@@ -0,0 +1,131 @@
+pre {\r
+       font-family: trebuchet ms, Arial, sans-serif;\r
+}\r
+\r
+body{\r
+       background-color: #fafafa;\r
+    font-family: Arial,sans-serif;\r
+       font-size: small;\r
+}\r
+h1,h2,h3,p, table, ul {\r
+    font-family: "Trebuchet MS",Verdana,Arial,sans-serif;\r
+}\r
+h1 {\r
+       border-bottom: 1px dashed #cfcfcf;\r
+       margin-left: -5px;\r
+       padding-left: 15px;\r
+       margin-right: -5px;\r
+       padding-right: 15px;\r
+}\r
+h2{\r
+       color: #666;\r
+       border-bottom: 1px dashed #cfcfcf;\r
+       margin-left: -5px;\r
+       padding-left: 15px;\r
+       margin-right: -5px;\r
+       padding-right: 15px;\r
+}\r
+p{padding-bottom:1em}\r
+\r
+a {\r
+       text-decoration: none;\r
+       border-bottom: 1px solid;\r
+       font-weight: bold;\r
+}\r
+a:hover {\r
+       border-bottom: 0px;\r
+}\r
+td,th {\r
+       font-size: 85%;\r
+}\r
+\r
+kbd {\r
+       padding: 0px 1px 0px 1px;\r
+       border-width: 1px 2px 2px 1px;\r
+       border-style: solid;\r
+       border-color: #edd #baa #baa #eed;\r
+       white-space: pre;\r
+}\r
+\r
+code {\r
+    font-family: "Trebuchet MS",Verdana,Arial,sans-serif;\r
+       background-color: #efefef;\r
+       padding: 0px 4px 0px 4px;\r
+       border-width: 1px 1px 1px 1px;\r
+       border-style: solid;\r
+       border-color: #edd #baa #baa #eed;              \r
+}\r
+\r
+\r
+div#toc {\r
+       color: #f0f0f0;\r
+       padding-bottom: 15px;\r
+}\r
+\r
+div#toc ul {\r
+       list-style: none;\r
+}\r
+div#toc li {\r
+       padding-top: 2px;\r
+       padding-bottom: 0px;\r
+}\r
+\r
+ol {\r
+       margin-top: 0px;\r
+}\r
+\r
+ol li {\r
+       padding-bottom: 3px;\r
+}\r
+\r
+dl {\r
+       margin: 0 10px\r
+}\r
+dl dd { \r
+       padding-top: 0px;\r
+       padding-left: 5px;\r
+       margin-left: 5%;\r
+       border-left: 1px solid #d0d0d0;\r
+       margin-bottom: 10px;\r
+} \r
+\r
+acronym {\r
+       cursor: help;\r
+}\r
+\r
+a[href*="http"] {\r
+       padding-right: 8px;\r
+       background-image: url('link-out.gif');\r
+       background-repeat: no-repeat;\r
+       background-position: right 4px;\r
+       margin-right: 2px;\r
+}\r
+\r
+div#nav-links {\r
+       margin-left: 20px;\r
+       margin-right: 20px;\r
+       margin-bottom: 20px;\r
+}\r
+\r
+div#nav-links a {\r
+       color: black;\r
+       text-decoration: none;\r
+       border-bottom: 1px solid;\r
+}\r
+\r
+pre {\r
+       font-family: Courier, monospace;\r
+       background-color: #EEEEFF;\r
+       padding: 5px;\r
+       margin-left: 20px;\r
+       color:#761596;\r
+    margin-top: 0px;\r
+       width: 50%;\r
+       font-size: smaller;\r
+}\r
+\r
+div.seq {\r
+       font-size: smaller;\r
+       padding: 5px;\r
+       border: 1px dashed #cfcfcf;\r
+}
\ No newline at end of file
diff --git a/documentation/admin/system_preferences.php b/documentation/admin/system_preferences.php
new file mode 100644 (file)
index 0000000..89ef487
--- /dev/null
@@ -0,0 +1,84 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+       <h2>System Preferences</h2>
+               <dl>
+                       <dt>Site Name</dt>
+                       <dd>The name of the course server's website. This name will appear at the top of all the public pages, in the web browser's title bar, and as the <em>From</em> name when sending non-personal emails.</dd>
+
+                       <dt>Home <acronym title="Uniform Resource Locator, a site's address">URL</acronym></dt>
+                       <dd>This will be the web address for the 'Home' link in the public area. Leave empty to remove this link.</dd>
+
+                       <dt>Default Language</dt>
+                       <dd>The default language to use if the client's browser settings cannot be detected. Must be one of the languages already installed. See the <a href="languages.php">Languages</a> section on installing and managing existing languages.</dd>
+
+                       <dt>Contact Email</dt>
+                       <dd>The reply address used for emails sent for instructor requests and other system emails.</dd>
+
+                       <dt>Time Zone</dt>
+                       <dd>Changing ATutor's time zone to one other than that specific by the server requires MySQL 4.1.3+. Additionally, MySQL's time zone tables must be loaded; see <a href="http://dev.mysql.com/doc/refman/4.1/en/time-zone-support.html" target="_new">MySQL Server Time Zone Support</a> for additional details. This option is available in ATutor 1.5.3.3+.</dd>
+
+                       <dt>Maximum File Size</dt>
+                       <dd>Maximum allowable file size in Bytes that can be uploaded to the course's File Manager. This does not override the value set for <kbd>upload_max_filesize</kbd> in <kbd>php.ini</kbd>.</dd>
+
+                       <dt>Maximum Course Size</dt>
+                       <dd>Total maximum allowable course size in Bytes. This is the total amount of space a course's File Manager can use.</dd>
+
+                       <dt>Maximum Course Float</dt>
+                       <dd>How much a course can be over its <em>Maximum Course Size</em> limit while still allowing a file to upload or import. Makes the course limit actually be <em>Max Course Size</em> + <em>Max Course Float</em>. When <em>Max Course Float</em> is reached, no more uploads will be allowed for that course until files are deleted and the course's space usage falls under the Maximum Course Size.</dd>
+
+                       <dt>Display Name Format</dt>
+                       <dd>The Display Name Format option controls how non-administrator users' names appear. This option is available in ATutor 1.5.4+.</dd>
+
+                       <dt>Authenticate Against A Master Student List</dt>
+                       <dd>Whether or not to enable Master Student List authentication. If enabled, only new accounts that validate against the master list will be created. See the <a href="master_student_list.php">Master Student List</a> section for additional details on using this feature.</dd>
+
+                       <dt>Require Email Confirmation Upon Registration</dt>
+                       <dd>If  email confirmation is enabled, before they can login, registrants must confirm their registration by replying to a message sent to the email address they registered with.  </dd>
+
+                       <dt>Allow Instructor Requests</dt>
+                       <dd>If enabled, students will be allowed to request that their account be upgraded to an instructor account. Instructor account requests must be approved by administrators using the <a href="instructor_requests.php">Instructor Requests</a> section. If disabled then the <em>Create Course</em> link used for requesting an instructor account will be removed and only the administrators will be able to create instructor accounts.</dd>
+
+                       <dt>Instructor Request Email Notification</dt>
+                       <dd>If enabled, and if <em>Allow Instructor Requests</em> is enabled, then an email notification message will be sent to the <em>Contact Email</em> each time a new instructor account request is made. This does not affect whether or not instructor requests can be made, only whether or not a notification message is sent out each time.</dd>
+
+                       <dt>Auto Approve Instructor Requests</dt>
+                       <dd>If <em>Allow Instructor Requests</em> is enabled, then existing students requesting instructor accounts will be upgraded automatically, bypassing the approval process. Additionally, any newly created accounts will be created as instructors rather than as students. Useful for setting up a demo version of ATutor. </dd>
+
+                       <dt>Theme Specific Categories</dt>
+                       <dd>Theme specific categories allows for the association between themes and categories. Courses belonging to a specific category will always be presented using that category's associated theme. This option disables the personalised theme preference. Use the <a href="categories.php">Categories</a> section to create and manage course categories, and the <a href="themes.php">Themes</a> section to install and manage themes.</dd>
+
+                       <dt>User Contributed Handbook Notes</dt>
+                       <dd>If enabled will allow anyone viewing the Handbook to contribute notes. User contributed notes must then be approved by an administrator by logging in on the main Handbook page. This option is available in ATutor 1.5.1+.</dd>
+
+                       <dt>Illegal File Extensions</dt>
+                       <dd>A list of all the file types, by extension, that are not allowed to be stored on the server. Any file that is being imported or uploaded with an extension in the specified list will be ignored and not saved. The list must contain only the file extensions seperated by commas without the leading dot.</dd>
+
+                       <dt>Cache Directory</dt>
+                       <dd>Where cached data is stored. On a Windows machine the path should look like <kbd>C:\Windows\temp\</kbd>, while on Unix it should look like <kbd>/tmp/cache/</kbd>. On some Linux/Unix based systems, a shared memory device can also be used <kbd>/dev/shm/</kbd> if it is available.  Leave empty to disable caching.</dd>
+
+                       <dt>Course Backups</dt>
+                       <dd>The maximum number of backups that can be stored per course. The stored backups do not count towards the course's <em>Max Course Size</em>.</dd>
+
+                       <dt>Number of Days to Keep Copied Sent Messages for</dt>
+                       <dd>All sent messages are copied to the sender's <em>Sent Messages</em> area. This option specifies the number of days old a copied message has to be before it is automatically deleted. The recipient's message is not affected.</dd>
+
+                       <dt>Check for ATutor Updates Automatically</dt>
+                       <dd>If enabled, ATutor will check the atutor.ca web site for updates whenever the administrator logs in. This option is available since ATutor 1.5.2.</dd>
+
+                       <dt>Maintain File Storage Version Control</dt>
+                       <dd>If enabled, every file revision in the File Storage area will be saved. If space is a concern, the administrator may wish to disable this feature.</dd>
+
+                       <dt>Enable Mail Queue</dt>
+                       <dd>The administrator may wish to set up a <a href="cron_setup.php">cron job</a> (automated event scheduler) for email. If enabled, and if the cron has been set up, system email will be sent out at a certain time instead of immediately. This can help speed up email capable features where a slower mail server is being used.</dd>
+
+                       <dt>Automatically Install New Language Packs</dt>
+                       <dd>If enabled, and if the <a href="cron_setup.php">cron job</a> (automated event scheduler) has been set up, new language packs published on atutor.ca will be imported automatically This option is available in ATutor 1.5.3.2+.</dd>
+
+                       <dt>Pretty URL</dt>
+                       <dd>If enabled, all the public accessible pages will automatically converts their URLs to "pretty url".  Pretty URL will remove the traditional URL query stirngs, and replace them with slashes (/).  This option is available in ATutor 1.6.1+.</dd>
+
+                       <dt>Course Directory Name</dt>
+                       <dd>If enabled, and only if the Pretty URL is enabled.  The course id in the pretty URL will be replaced by a custom course directory name.  This name can be setup individually and uniquely in the course property.  This option is available in ATutor 1.6.1+.</dd>
+               </dl>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/themes.php b/documentation/admin/themes.php
new file mode 100644 (file)
index 0000000..e2a23b1
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Themes</h2>
+       <p>Themes are used for changing the look and feel of an ATutor installation. Themes can be set as a personal preference or forced to display by default using the <a href="system_preferences.php">System Preferences</a> <em>Theme Specific Categories</em> option.</p>
+
+       <p>ATutor's architecture allows for the separation of presentation elements from code or logic elements. As a result, it is easy for any <acronym title="Extensible Hypertext Markup Language, the web's structured language">XHTML</acronym> and <acronym title="Cascading Style Sheets, the web's presentation layer">CSS</acronym> proficient person to create customized themes and layouts without having to know anything about <acronym title="Recursive acronym for PHP: Hypertext Preprocessor, the language ATutor is written in">PHP</acronym> or the inner workings of ATutor itself.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/troubleshooting.php b/documentation/admin/troubleshooting.php
new file mode 100644 (file)
index 0000000..2ee6a39
--- /dev/null
@@ -0,0 +1,30 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Troubleshooting</h2>
+       <p>A variety of strategies are available for troubleshooting an ATutor installation that may not be functioning properly.</p>
+       <dl>
+               <dt><kbd>AT_DEVEL</kbd></dt>
+               <dd>Near the top of the <kbd>include/vitals.inc.php</kbd> file, set the value of <kbd>AT_DEVEL</kbd> to <kbd>true</kbd>. This will display your session variables at the bottom of the screen. It will also display the variable names associated with all feedback messages, so they are easier to find through the language manager if you wish to modify their language.  The <kbd>debug()</kbd> function will also become available, allowing testers to print out any type of variable in an easily readable format.</dd>
+
+               <dt><kbd>debug(mixed variable [, string title])</kbd></dt>
+               <dd>It is possible to display the value of variables using <kbd>debug()</kbd>. <kbd>variable</kbd> is the PHP variable to output. <kbd>title</kbd> is an optional title that can be printed inside the debugging box to easily identify which variable is being outputted.
+<pre>debug($_SESSION); // print current session variables
+debug($_REQUEST); // print all GET, POST, and COOKIE variables
+</pre>
+
+               </dd>
+               <dt>Error Logging</dt>
+               <dd>View the error log through the <a href="system_preferences.php">System Preferences</a> section. There may be information in the error reports that can help you identify where or how an error occured. The output from the error log can be sent to the ATutor team to aid them in finding a solution to your problem.</dd>
+
+               <dt><kbd>phpinfo()</kbd></dt>
+               <dd>Often, system problems can be fixed by reviewing the phpinfo page. This will show all of the configuration options for your system. Review the <a href="requirements_recommendations.php">Requirement &amp; Recommendations</a> for different values that should be set and displayed in the phpinfo output. Below is the contents of a phpinfo file. Viewing this page in a browser will show the system variables.<br /><br />
+<pre>
+&lt;?php
+phpinfo();
+?&gt;
+</pre>
+</dd>
+<p>Also see the <a href="../developer/guidelines.html">Developer Documentation</a> for details about modifying the source code.</p>
+               </dd>
+       </dl>
+<?php require('../common/body_footer.inc.php');?>
\ No newline at end of file
diff --git a/documentation/admin/upgrading.php b/documentation/admin/upgrading.php
new file mode 100644 (file)
index 0000000..d44efac
--- /dev/null
@@ -0,0 +1,50 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Upgrading an  Existing ATutor Installation</h2>
+       <h3>Considerations Before Upgrading</h3>
+
+       <p>Note that Release Candidates (RC) and nightly build upgrades are not supported using this method and that depending on the size of the old courses, some steps of the upgrade may require considerable time to complete (in particular steps 2 and 6).</p>
+
+       <p>Be sure that <em><a href="http://www.atutor.ca/atutor/translate/" target="_new"">Language Packs</a></em> you have installed on your old version of ATutor are available for the new version, or be prepared to translate the missing language. The old language will be removed during upgrade. If they are not available, you might volunteer to help finish any remaining language that needs to be translated for these languages. See the <a href="http://atutor.ca/atutor/docs/translate.php" target="_new">Translator Documentation</a>  for more details. If you have made custom changes the the language, you may wish to export the customized language using the language manager. 
+       <p>If you have <em><a href="http://atutor.ca/atutor/themes/index.php" target="_new">Custom Themes</a></em> created, export those before upgrading, then import them back into the new version of ATutor after the upgrade is complete (you may need to make a few adjustment after reimporting the custom themes if there have been changes in the ATutor)</p>
+       <p>If you have <em><a href="http://atutor.ca/atutor/modules.php" target="_new">Extra Modules</em></a> installed, be sure the modules are either compatible, or are available for the new version.  Modules must be reinstalled after an upgrade. </p>
+       <p>Also be sure the <a href="requirements_recommendations.php?en">System Requirements</a> are still met.</p>
+
+
+       <p>Before upgrading, rename your old ATutor directory. Download the latest version of ATutor and extract the new version into the same directory that the old one was in. Example: If the old ATutor installation was in <kbd>/htdocs/ATutor</kbd> and renamed to <kbd>/htdocs/ATutor_old</kbd>, then the new ATutor installation should be in <kbd>/htdocs/ATutor</kbd>, such that both the old and new installations are at the same directory level. On Windows you may use WinZip or WinRar, while on Unix use the command <kbd>tar -zxvf ATutor-version_number.tar.gz</kbd>. Once extracted, an <kbd>ATutor</kbd> directory will be created alongside your old ATutor directory. Open a web browser and enter the address to your new installation, <kbd>http://your_server.com/path_to_atutor/ATutor/</kbd>, then follow the step-by-step instructions.</p>
+
+       <h3>Steps for Upgrading ATutor</h3>
+       <p><strong>Important</strong>: It is highly recommended that you backup your old ATutor database before attempting an upgrade.</p>
+
+
+       <p>The following eight steps describe the upgrade process as they are presented by the ATutor installer:</p>
+<ol>
+       <li><strong>Locate Old Version</strong><br />
+       Specify the directory name of the old ATutor installation you wish to upgrade (e.g. ATutor_old). The new and old ATutor directories must be at the same directory level.</li>
+        <li><strong>UTF-8 Conversion (1.6+)</strong><br />
+       If you have not already, you are strongly advised to backup you database before completing this step.
+       If ATutor is being upgraded from a previous version that was not using UTF-8 language packs, options will be provided to convert the database to UTF-8 all-at-once, used for single language ATutor installations, or to convert on a course-by-course basis, used if courses in different languages are present on the system. If the system is already setup with UTF-8, you'll skip this step. NOTE: This step can take a very long time for installations with many courses</li>
+       <li><strong>Database</strong><br />
+       The upgrade will use the old version's settings to connect to the database and then update the old database tables with any changes to bring them up to date with the new version.</li>
+
+       <li><strong>Preferences</strong><br />
+       In some cases, the newer version will introduce new configuration options and preferences that have to be set or confirmed. Review the Preferences and modify them if necessary.</li>
+
+       <li><strong>Directories</strong><br />
+       Create a content directory , preferably outside your web server's document directory for added security, and set permissions to make the content directory writable (<kbd>chmod a+rwx content</kbd>). On a Unix machine you will need to manually change the permissions on the content directory during this step, if you are using a directory other than the one used in the version of ATutor being upgraded. No action is usually required on a Windows server, though in some circumstances Windows users may need to adjust the properties of the specified files and directories to make them writable. Copy the path of the directory into the text box provided. Ensure there are no shortcuts (Windows), or symbolic links (Unix) are contained in the path. The path can be the same as that to the content directory use in the version being upgraded from if the directory is outside the old ATutor installation.</li>
+
+       <li><strong>Save configuration</strong><br />
+       Before reaching the final step the include/config.inc.php file needs to be writable, otherwise an error will appear. Follow the instructions on the screen if the file permissions need to be changed (<kbd>chmod a+rwx include/config.inc.php</kbd>). Once your upgrade is complete and you have confirmed it was successfuly, you should set the configuration file back to read only to secure it (<kbd>chmod a-w include/config.inc.php</kbd>)</li>
+
+       <li><strong>Content Files</strong><br />
+       All the old course content files and chat messages will be copied over to the new installation. Depending on the size of your old installation, this process may take a few seconds to several minutes or more to complete.</li>
+
+       <li><strong>Submit Usage Information</strong><br />
+       To assist the development team in serving the ATutor community, submit some basic information collected about the system you are running. All information is private. Though you are encouraged to list the location of your ATutor installation, you may remain anonymous by choosing not to submit the URL to your ATutor server along with the system information during this step.</li>
+       
+       <li><strong>Done!</strong><br />
+       ATutor upgrade has been successful and you may now log-in with your personal account or your administrator account.</li>
+
+</ol>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/admin/users.php b/documentation/admin/users.php
new file mode 100644 (file)
index 0000000..0ae0ddf
--- /dev/null
@@ -0,0 +1,28 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Users</h2>
+
+       <p>The Users section allows managment of students, instructors, and administrators. Note that administrators are not 
+considered regular users of the system; an administrator account can not normally be used to login to a course. They can however login temporarily as the course instructor, using the View button in the administrator's Courses listing. For the 
+purposes of documentation the term "users" will be reserved for any account type that is <em>not</em> an administrator.</p>    
+
+<p>There are four types of user accounts that can exist in an ATutor installation, as defined by their Status: 
+       <dl>
+               <dt>Disabled</dt>
+               <dd>Only administrators may disable an account. Disabled accounts cannot login to the ATutor installation, and will not appear in a course's Enrollment Manager.</dd>
+               <dt>Unconfirmed</dt>
+               <dd>Unconfirmed accounts are created only when the <a href="system_preferences.php">System Preferences</a> <em>Require Email Confirmation Upon Registration</em> option is enabled.</dd>
+               <dt>Student</dt>
+               <dd>A regular account which can enroll, but not create courses.</dd>
+
+               <dt>Instructor</dt>
+               <dd>A regular account which can enroll as well as create courses.</dd>
+       </dl>
+</p>
+
+<h3>Creating User Accounts</h3>
+
+<p>Administrators can manually add users to the system by using <em>Create User Account</em>. Manually created accounts are automatically confirmed and the account status is set to Student, Instructor, or disabled as choosen in the Account Status field of the user account creation form. </p>
+<p>User accounts can also be created by individuals using the Registration form available through the public pages of ATutor. Instructors can also generate user accounts by importing a course list in the Enrollment Manager.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/approve_note.php b/documentation/approve_note.php
new file mode 100644 (file)
index 0000000..46b833e
--- /dev/null
@@ -0,0 +1,59 @@
+<?php\r
+require(dirname(__FILE__) .'/common/vitals.inc.php');\r
+\r
+if (!isset($_SESSION['handbook_admin']) || !$_SESSION['handbook_admin'] || !isset($_GET['id'])) {\r
+       exit;\r
+}\r
+\r
+function my_add_null_slashes( $string ) {\r
+    return ( $string );\r
+}\r
+\r
+if ( get_magic_quotes_gpc() == 1 ) {\r
+       $addslashes = 'my_add_null_slashes';\r
+} else {\r
+       $addslashes = 'addslashes';\r
+}\r
+\r
+\r
+$_GET['id'] = intval($_GET['id']);\r
+\r
+$config_location = '../include/config.inc.php';\r
+if (is_file($config_location) && is_readable($config_location)) {\r
+       require($config_location);\r
+       $db = mysql_connect(DB_HOST . ':' . DB_PORT, DB_USER, DB_PASSWORD);\r
+       mysql_select_db(DB_NAME, $db);\r
+\r
+       // check atutor config table to see if handbook notes is enabled.\r
+       $sql    = "SELECT value FROM ".TABLE_PREFIX."config WHERE name='user_notes'";\r
+       $result = @mysql_query($sql, $db);\r
+       if (($row = mysql_fetch_assoc($result)) && $row['value']) {\r
+               define('AT_HANDBOOK_ENABLE', true);\r
+               $enable_user_notes = true;\r
+       }\r
+       define('AT_HANDBOOK_DB_TABLE_PREFIX', TABLE_PREFIX);\r
+\r
+       define('AT_HANDBOOK_ENABLE', true);\r
+}\r
+if (!defined('AT_HANDBOOK_ENABLE')) {\r
+       // use local config file\r
+       require('./config.inc.php');\r
+}\r
+\r
+if (!$db && defined('AT_HANDBOOK_ENABLE') && AT_HANDBOOK_ENABLE) {\r
+       $db = @mysql_connect(AT_HANDBOOK_DB_HOST . ':' . AT_HANDBOOK_DB_PORT, AT_HANDBOOK_DB_USER, AT_HANDBOOK_DB_PASSWORD);\r
+       if (@mysql_select_db(AT_HANDBOOK_DB_DATABASE, $db)) {\r
+               $enable_user_notes = true;\r
+       }\r
+}\r
+\r
+if ($enable_user_notes) {\r
+       // insert into DB\r
+       $sql = "UPDATE ".AT_HANDBOOK_DB_TABLE_PREFIX."handbook_notes SET approved=1, date=date WHERE note_id=$_GET[id]";\r
+       mysql_query($sql, $db);\r
+}\r
+\r
+header('Location: index_list.php');\r
+exit;\r
+\r
+?>
\ No newline at end of file
diff --git a/documentation/common/body_footer.inc.php b/documentation/common/body_footer.inc.php
new file mode 100644 (file)
index 0000000..2c63d8d
--- /dev/null
@@ -0,0 +1,86 @@
+<?php if (!defined('AT_HANDBOOK')) { exit; } ?>\r
+<?php\r
+\r
+       // if ATutor config.inc is available, then:\r
+       // read it for DB info and comments_enabling option.\r
+       // else: use local configuration option for DB/comments option\r
+\r
+       $enable_user_notes = false;\r
+\r
+       $config_location = dirname(__FILE__) . '/../../include/config.inc.php';\r
+       if (is_file($config_location) && is_readable($config_location)) {\r
+               require($config_location);\r
+               if (defined('DB_HOST')) {\r
+               \r
+                       $db = @mysql_connect(DB_HOST . ':' . DB_PORT, DB_USER, DB_PASSWORD);\r
+                       @mysql_select_db(DB_NAME, $db);\r
+\r
+                       // check atutor config table to see if handbook notes is enabled.\r
+                       $sql    = "SELECT value FROM ".TABLE_PREFIX."config WHERE name='user_notes'";\r
+                       $result = @mysql_query($sql, $db);\r
+                       if (($row = mysql_fetch_assoc($result)) && $row['value']) {\r
+                               define('AT_HANDBOOK_ENABLE', true);\r
+                               $enable_user_notes = true;\r
+                       } else {\r
+                               define('AT_HANDBOOK_ENABLE', false);\r
+                       }\r
+                       define('AT_HANDBOOK_DB_TABLE_PREFIX', TABLE_PREFIX);\r
+               }\r
+       } \r
+       if (!defined('AT_HANDBOOK_ENABLE')) {\r
+               // use local config file\r
+               require(dirname(__FILE__) . '/../config.inc.php');\r
+       }\r
+\r
+       if (defined('AT_HANDBOOK_ENABLE') && AT_HANDBOOK_ENABLE) {\r
+               if (!$db) {\r
+                       $db = @mysql_connect(AT_HANDBOOK_DB_HOST . ':' . AT_HANDBOOK_DB_PORT, AT_HANDBOOK_DB_USER, AT_HANDBOOK_DB_PASSWORD);\r
+                       @mysql_select_db(AT_HANDBOOK_DB_DATABASE, $db);\r
+               }\r
+               if ($db) {\r
+                       $enable_user_notes = true;\r
+                       $sql = "SELECT note_id, date, email, note FROM ".AT_HANDBOOK_DB_TABLE_PREFIX."handbook_notes WHERE section='$section' AND page='$this_page' AND approved=1 ORDER BY date DESC";\r
+                       $result = mysql_query($sql, $db);\r
+               }\r
+       }\r
+?>\r
+\r
+<?php if ($enable_user_notes): ?>\r
+       <div class="add-note">\r
+               <a href="../add_note.php?<?php echo $section . SEP . 'p='.$this_page; ?>" style="float: right;">+ <?php get_text('add_note'); ?> +</a>\r
+               <h3><?php get_text('user_contributed_notes'); ?></h3>\r
+       </div>\r
+\r
+       <?php if ($result && mysql_num_rows($result) > 0): ?>\r
+               <?php while ($row = mysql_fetch_assoc($result)): ?>\r
+                       <div class="note">\r
+                               <h5><?php echo $row['date']; ?>\r
+                                       <?php if (isset($_SESSION['handbook_admin']) && $_SESSION['handbook_admin']): ?>\r
+                                               <a href="../delete_note.php?<?php echo $section.SEP.'p='.$this_page.SEP.'id='.$row['note_id']; ?>" onclick="return confirm('<?php get_text('are_you_sure_delete_note'); ?>');"><?php get_text('delete'); ?></a>\r
+                                       <?php endif; ?>\r
+                               </h5>\r
+                               <h4><?php echo $row['email'];?></h4>\r
+                               <p><?php echo nl2br($row['note']); ?></p>\r
+                       </div>\r
+               <?php endwhile; ?>\r
+       <?php else: ?>\r
+               <div class="note"><?php get_text('no_notes_on_page'); ?></div>\r
+       <?php endif; ?>\r
+<?php endif; ?>\r
+\r
+<div class="seq">\r
+       <?php if (isset($previous_page)): ?>\r
+               <?php get_text('previous_chapter'); ?>: <a href="<?php echo $rel_path; ?><?php echo $section; ?>/<?php echo $previous_page; ?>?<?php echo $req_lang; ?>" title="<?php echo $_pages[$previous_page]; ?> Alt+,"><?php echo $_pages[$previous_page]; ?></a><br /> \r
+       <?php endif; ?>\r
+\r
+       <?php if (isset($next_page)): ?>\r
+               <?php get_text('next_chapter'); ?>: <a href="<?php echo $rel_path; ?><?php echo $section; ?>/<?php echo $next_page; ?>?<?php echo $req_lang; ?>" title="<?php echo $_pages[$next_page]; ?> Alt+."><?php echo $_pages[$next_page]; ?></a>\r
+       <?php endif; ?>\r
+</div>\r
+\r
+<div class="tag">\r
+       <?php echo htmlspecialchars($lm); ?><br />\r
+       All text is available under the terms of the GNU Free Documentation License. \r
+</div>\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/documentation/common/body_header.inc.php b/documentation/common/body_header.inc.php
new file mode 100644 (file)
index 0000000..d9e1f59
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: body_header.inc.php 6230 2006-05-26 21:35:34Z greg $
+
+require(dirname(__FILE__) . '/vitals.inc.php');
+
+$missing_lang = FALSE;
+if ($req_lang != 'en') {
+       $file_name = basename($_SERVER['PHP_SELF']);
+
+       $lang_file = $req_lang . '/' . $file_name;
+
+       if (file_exists($lang_file)) {
+               header('Location: '.$lang_file.'?r');
+               exit;
+       } else if (!isset($_GET['r'])) {
+               $missing_lang = TRUE;
+               $lang = 'en';
+       }
+}
+
+if (strpos(@ini_get('arg_separator.input'), ';') !== false) {
+       define('SEP', ';');
+} else {
+       define('SEP', '&');
+}
+
+?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html lang="<?php if ($missing_lang) { echo 'en'; } else { echo $req_lang; } ?>">
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+       <title><?php get_text('atutor_documentation'); ?></title>
+       <link rel="stylesheet" href="<?php echo $rel_path; ?>common/styles.css" type="text/css" />
+</head>
+
+<body onload="doparent();">
+<script type="text/javascript">
+// <!--
+function doparent() {
+       if (parent.toc && parent.toc.highlight) parent.toc.highlight('id<?php echo $this_page; ?>');
+}
+// -->
+</script>
+<?php
+require(dirname(__FILE__).'/../'.$section.'/pages.inc.php');
+if (($req_lang != 'en') && (file_exists(dirname(__FILE__).'/../'.$section.'/'.$req_lang.'/pages.inc.php'))) {
+       require(dirname(__FILE__).'/../'.$section.'/'.$req_lang.'/pages.inc.php');
+}
+
+while (current($_pages) !== FALSE) {
+       if (key($_pages) == $this_page) {
+               next($_pages);
+               $next_page = key($_pages);
+               break;
+       }
+       $previous_page = key($_pages);
+       next($_pages);
+}
+?>
+<div class="seq">
+       <?php if (isset($previous_page)): ?>
+               <?php get_text('previous_chapter'); ?>: <a href="<?php echo $rel_path; ?><?php echo $section; ?>/<?php echo $previous_page; ?>?<?php echo $req_lang; ?>" accesskey="," title="<?php echo $_pages[$previous_page]; ?> Alt+,"><?php echo $_pages[$previous_page]; ?></a><br />
+       <?php endif; ?>
+
+       <?php if (isset($next_page)): ?>
+               <?php get_text('next_chapter'); ?>: <a href="<?php echo $rel_path; ?><?php echo $section; ?>/<?php echo $next_page; ?>?<?php echo $req_lang; ?>" accesskey="." title="<?php echo $_pages[$next_page]; ?> Alt+."><?php echo $_pages[$next_page]; ?></a>
+       <?php endif; ?>
+</div>
+
+<?php if ($missing_lang): ?>
+       <div style="margin: 20px auto; border: 1px solid #aaf; padding: 4px; text-align: center; background-color: #eef;">
+               <?php get_text('page_not_translated'); ?>
+       </div>
+<?php endif; ?>
+
+<?php if (isset($_GET['noted'])): ?>
+       <div style="margin: 20px auto; border: 1px solid #aaf; padding: 4px; text-align: center; background-color: #eef;">
+               <?php get_text('note_added'); ?>
+       </div>
+<?php endif; ?>
\ No newline at end of file
diff --git a/documentation/common/folder.gif b/documentation/common/folder.gif
new file mode 100644 (file)
index 0000000..e4802fb
Binary files /dev/null and b/documentation/common/folder.gif differ
diff --git a/documentation/common/fr/text.php b/documentation/common/fr/text.php
new file mode 100644 (file)
index 0000000..5bb8930
--- /dev/null
@@ -0,0 +1,9 @@
+<?php\r
+\r
+$text = array();\r
+$text['next_chapter'] = 'Prochain Chapitre';\r
+$text['previous_chapter'] = 'Chapitre Précédent';\r
+$text['page_not_translated'] = 'Cette section n\'a pas été encore traduite à votre langue demandée.';\r
+$text['doc_user'] = 'User Documentatione';\r
+\r
+?>
\ No newline at end of file
diff --git a/documentation/common/frame_header.php b/documentation/common/frame_header.php
new file mode 100644 (file)
index 0000000..70fe61f
--- /dev/null
@@ -0,0 +1,77 @@
+<?php require(dirname(__FILE__) . '/vitals.inc.php'); ?>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html lang="<?php if ($missing_lang) { echo 'en'; } else { echo $req_lang; } ?>">\r
+<head>\r
+       <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />\r
+       <title><?php get_text('atutor_documentation'); ?></title>\r
+<style type="text/css">\r
+body { font-family: Verdana,Arial,sans-serif; font-size: x-small; margin: 0px; padding: 3px; background: #f4f4f4; color: #afafaf; }\r
+ul, ol { list-style: none; padding-left: 0px; margin-left: -15px; }\r
+li { margin-left: 19pt; padding-top: 2px; }\r
+a { text-decoration: none; }\r
+a:link, a:visited { color: #006699; }\r
+a:hover { color: #66AECC; }\r
+input { border: 0px; padding: 2px 5px 2px 5px; font-size: smaller; }\r
+input[type=submit] { color: #999; background-color: #dfdfdf; padding: 1px; }\r
+input[type=submit]:hover { color: #999; background-color: #eee; padding: 1px; }\r
+form { padding: 0px; margin: 0px; display: inline; }\r
+</style>\r
+<script type="text/javascript">\r
+// <!--\r
+var currentPage;\r
+\r
+function showTocToggle(show, hide) {\r
+       if(document.getElementById) {\r
+               document.writeln('<a href="javascript:toggleToc(false)">' +\r
+               '<span id="showlink" style="display:none;">' + show + '</span>' +\r
+               '<span id="hidelink">' + hide + '</span>'       + '</a>');\r
+       }\r
+}\r
+function toggleToc(override) {\r
+       var showlink=document.getElementById('showlink');\r
+       var hidelink=document.getElementById('hidelink');\r
+\r
+       if (override && (hidelink.style.display == 'none')) {\r
+               top.show();\r
+               hidelink.style.display='';\r
+               showlink.style.display='none';\r
+       } else if (!override && (hidelink.style.display == 'none')) {\r
+               top.show();\r
+               hidelink.style.display='';\r
+               showlink.style.display='none';\r
+       } else if (!override) {\r
+               top.hide(); //('0, *');\r
+               hidelink.style.display='none';\r
+               showlink.style.display='';\r
+       }\r
+}\r
+// -->\r
+</script>\r
+</head>\r
+<body><form method="get" action="search.php" target="toc" onsubmit='toggleToc(true);false;'>\r
+<input type="hidden" name="<?php echo $section; ?>" value="" />\r
+<input type="hidden" name="<?php echo $req_lang; ?>" value="" />\r
+<script type="text/javascript">\r
+// <!--\r
+if (top.name == 'popup') {\r
+       document.write('<a href="javascript:top.close();"><?php get_text('close_popup'); ?></a> | ');\r
+}\r
+// -->\r
+</script>\r
+\r
+<a href="../index/<?php echo $req_lang; ?>" target="_top"><?php get_text('return_to_handbook'); ?></a> | \r
+\r
+<input type="text" name="query" /> <input type="submit" name="search" value="<?php get_text('search'); ?>" /> |  <a href="print.php?<?php echo $section; ?>&amp;<?php echo $req_lang; ?>" target="_top"><?php get_text('print_version'); ?></a>\r
+                       <script type="text/javascript">\r
+                       //<!--\r
+                       document.writeln(' | ');\r
+                       showTocToggle('<?php get_text('show_contents'); ?>' ,'<?php get_text('hide_contents'); ?>');\r
+                       if (top.name == 'popup') {\r
+                               toggleToc(true);\r
+                       }\r
+                       //-->\r
+                       </script>\r
+\r
+</form>\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/documentation/common/frame_toc.php b/documentation/common/frame_toc.php
new file mode 100644 (file)
index 0000000..9ba6168
--- /dev/null
@@ -0,0 +1,214 @@
+<?php
+require(dirname(__FILE__) . '/vitals.inc.php');
+
+/**
+ * handbook toc printer
+ * prints an unordered html list representation of the multidimensional array.
+ * $pages    the array of items to print.
+ * $section  the directory name of the files.
+ */
+function hb_print_toc($pages, $section) {
+       global $_pages, $req_lang;
+       echo '<ul>';
+       foreach ($pages as $page_key => $page_value) {
+               echo '<li>';
+               if (is_array($page_value)) {
+                       echo '<a href="../'.$section.'/'.$page_key.'?'.$req_lang.'" id="id'.$page_key.'" class="tree">'.$_pages[$page_key].'</a>';
+                       hb_print_toc($page_value, $section);
+               } else {
+                       echo '<a href="../'.$section.'/'.$page_value.'?'.$req_lang.'" id="id'.$page_value.'" class="leaf">'.$_pages[$page_value].'</a>';
+               }
+               echo '</li>';
+       }
+       echo '</ul>';
+}
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html lang="<?php if ($missing_lang) { echo 'en'; } else { echo $req_lang; } ?>">
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+       <title><?php get_text('handbook_toc'); ?></title>
+       <base target="body" />
+<style type="text/css">
+body { font-family: Verdana,Arial,sans-serif; font-size: x-small; margin: 0px; padding: 0px; background: #f4f4f4; margin-left: -5px; }
+ul { list-style: none; padding-left: 0px; margin-left: -15px; }
+li { margin-left: 19pt; padding-top: 2px; }
+a { background-repeat: no-repeat; background-position: 0px 1px; padding-left: 12px; text-decoration: none; }
+a.tree { background-image: url('folder.gif'); }
+a.leaf { background-image: url('paper.gif'); }
+a:link, a:visited { color: #006699; }
+a:hover { color: #66AECC; }
+</style>
+<script type="text/javascript">
+// <!--
+function highlight(page) {
+       if (page == false) {
+               if (parent.header.currentPage) {
+                       var toc = parent.toc.document.getElementById(parent.header.currentPage);
+                       toc.style.color = 'blue';
+                       toc.style.fontWeight = 'bold';
+               }
+       } else {
+               if (parent.header.currentPage) {
+                       var toc = parent.toc.document.getElementById(parent.header.currentPage);
+                       toc.style.color = '';
+                       toc.style.fontWeight = '';
+               }
+       
+               var toc = parent.toc.document.getElementById(page);
+               toc.style.color = 'blue';
+               toc.style.fontWeight = 'bold';
+               parent.header.currentPage = page;
+       }
+}
+// -->
+</script>
+</head>
+<body onload="highlight(false);">
+<?php
+require(dirname(__FILE__).'/../'.$section.'/pages.inc.php');
+if (($req_lang != 'en') && (file_exists(dirname(__FILE__).'/../'.$section.'/'.$req_lang.'/pages.inc.php'))) {
+       require(dirname(__FILE__).'/../'.$section.'/'.$req_lang.'/pages.inc.php');
+}
+if ($section == 'admin'){
+       $pages = array(
+                               'introduction.php',
+                               'installation.php' => array(
+                                                                                       'requirements_recommendations.php',
+                                                                                       'new_installation.php',
+                                                                                       'upgrading.php'
+                                                                                       ),
+                               'configuration.php' => array('my_account.php'),
+                               'system_preferences.php' => array(
+                                                                                               'default_preferences.php',
+                                                                                               'languages.php',
+                                                                                               'auto_enroll.php',
+                                                                                               'themes.php' => array(
+                                                                                                                                               'importing_themes.php',
+                                                                                                                                               'managing_existing_themes.php',
+                                                                                                                                               'creating_themes.php'
+                                                                                                                                               ),
+                                                                                               'error_logging.php',
+                                                                                               'feeds.php',
+                                                                                               'google_key.php',
+                                                                                               'cron_setup.php'
+                                                                                               ),
+                               'enrollment.php' => array(
+                                                                       'enrollment_privileges.php',
+                                                                       ),
+                               'users.php' => array(
+                                                                               'instructor_requests.php',
+                                                                               'master_student_list.php',
+                                                                               'email_users.php',
+                                                                               'administrators.php'
+                                                                               ),
+                               'courses.php' => array(
+                                                                               'forums.php',
+                                                                               'creating_courses.php',
+                                                                               'default_student_tools.php',
+                                                                               'default_side_menu.php',
+                                                                               'backups.php',
+                                                                               'categories.php'
+                                                                               ),
+                               'modules.php',
+                               'patcher.php' => array(
+                                                                               'create_patches.php'
+                                                                               ),
+                               'troubleshooting.php',
+                       );
+
+       hb_print_toc($pages, 'admin');
+
+} else if ($section == 'instructor'){
+       $pages = array(
+                       'introduction.php' => array('creating_courses.php'),
+                       'announcements.php',
+                       'assignments.php',
+                       'backups.php' => array(
+                                                                       'creating_restoring.php',
+                                                                       'downloading_uploading.php',
+                                                                       'editing_deleting.php'
+                                                                       ),
+                       'chat.php',
+                       'content.php' => array(
+                                                                       'creating_editing_content.php' => array(
+                                                                                                                                                       'content_edit.php',
+                                                                                                                                                       'content_properties.php',
+                                                                                                                                                       'glossary_terms.php',
+                                                                                                                                                       'content_preview.php',
+                                                                                                                                                       'accessibility.php'
+                                                                                                                                                       ),
+                                                                       'content_packages.php',
+                                                                       'content_usage.php',
+                                                                       'tile_repository.php',
+                                                                       'scorm_packages.php'
+                                                                       ),
+                       'course_email.php',
+                       'enrollment.php' => array(
+                                                                       'enrollment_privileges.php',
+                                                                       'enrollment_alumni.php',
+                                                                       'enrollment_course_list.php'
+                                                                               ),
+                       'file_manager.php' => array(
+                                                                       'managing_files_folders.php',
+                                                                       'extracting_zip_archives.php'
+                                                                       ),
+                       'forums.php' => array(
+                                                                       'managing_threads.php' => array('managing_posts.php')
+                                                                       ),
+                       'faq.php',
+                       'glossary.php',
+                       'groups.php',
+                       'links.php',
+                       'polls.php',
+                       'properties.php' => array('authenticated_access.php', 'delete_course.php'),
+                       'reading_list.php',
+                       'statistics.php',
+                       'student_tools.php' => array('side_menu.php'),
+                       'tests_surveys.php' => array(
+                                                                                       'creating_tests_surveys.php',
+                                                                                       'question_database.php' => array('creating_questions.php'),
+                                                                                       'question_categories.php',
+                                                                                       'edit_delete_tests.php',
+                                                                                       'preview.php',
+                                                                                       'add_questions.php',
+                                                                                       'student_submissions.php',
+                                                                                       'test_statistics.php'
+                                                                                       ),
+                       'feeds.php',
+                       'gradebook.php' => array(
+                                                       'gradebook_add.php',    
+                                                       'gradebook_update.php', 
+                                                       'gradebook_external_marks.php', 
+                                                       'gradebook_edit_marks.php',     
+                                                       'gradebook_scales.php' => array('gradebok_add_scales.php'),     
+                                                       ),
+                       'web_search.php',
+                       );
+       hb_print_toc($pages, 'instructor');
+} else { 
+
+       $pages = array(
+                               'introduction.php',
+                               'login.php',
+                               'register.php',
+                               'browse_courses.php',
+                               'password_reminder.php',
+                               'my_start_page.php' => array(
+                                                                                               'my_courses.php' => array('create_course.php'),
+                                                                                               'profile.php',
+                                                                                               'preferences.php',
+                                                                                               'inbox.php'
+                                                                                               ),
+                               'inside_course.php' => array(
+                                                                                               'export_content.php',
+                                                                                               'packages.php',
+                                                                                               'tile.php',
+                                                                                               'file_storage.php'
+                                                                                               )
+                       );
+       hb_print_toc($pages, 'general');
+} ?>
+
+</body>
+</html>
diff --git a/documentation/common/link-out.gif b/documentation/common/link-out.gif
new file mode 100644 (file)
index 0000000..ecef094
Binary files /dev/null and b/documentation/common/link-out.gif differ
diff --git a/documentation/common/paper.gif b/documentation/common/paper.gif
new file mode 100644 (file)
index 0000000..3e8a06d
Binary files /dev/null and b/documentation/common/paper.gif differ
diff --git a/documentation/common/print.php b/documentation/common/print.php
new file mode 100644 (file)
index 0000000..222e584
--- /dev/null
@@ -0,0 +1,41 @@
+<?php require(dirname(__FILE__) . '/vitals.inc.php'); ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html lang="<?php echo $req_lang; ?>">
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+       <title><?php get_text('doc_title'); ?></title>
+       <link rel="stylesheet" href="styles.css" type="text/css" />
+</head>
+<body>
+<?php
+require('../'.$section.'/pages.inc.php');
+
+echo '<a href="../'.$section.'/index.php?'.$req_lang.'" target="_top">';
+get_text('back_to_chapters');
+echo '</a>';
+
+foreach ($_pages as $file => $title) {
+       if (($req_lang != 'en') && (file_exists('../'.$section.'/'.$req_lang.'/'.$file))) {
+               $string = file_get_contents('../'.$section.'/'.$req_lang.'/'.$file);
+       } else if ($req_lang != 'en') {
+               ?>
+               <div style="margin: 20px auto; border: 1px solid #aaf; padding: 4px; text-align: center; background-color: #eef;">
+                       <?php get_text('page_not_translated'); ?>
+               </div>
+               <?php
+               $string = file_get_contents('../'.$section.'/'.$file);
+       } else {
+               $string = file_Get_contents('../'.$section.'/'.$file);
+       }
+       
+       $patterns = array('#<a href="(?!http)([[:alnum:].?/_-]+)"([^>]*)>([^<]+)</a>#is',
+                                         '#<a href="http://([[:alnum:]./_-]+)"([^>]*)>([^<]+)</a>#i');
+
+       $replacements = array('<strong><u>$3</u></strong>',
+                                                 '<strong><u>$3</u></strong> [$1]');
+
+       echo preg_replace($patterns, $replacements, $string);
+}
+?>
+</body>
+</html>
\ No newline at end of file
diff --git a/documentation/common/search.php b/documentation/common/search.php
new file mode 100644 (file)
index 0000000..01663d8
--- /dev/null
@@ -0,0 +1,95 @@
+<?php require(dirname(__FILE__) . '/vitals.inc.php'); ?>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html lang="<?php if ($missing_lang) { echo 'en'; } else { echo $req_lang; } ?>">\r
+<head>\r
+       <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />\r
+       <title><?php get_text('atutor_documentation'); ?></title>\r
+       <base target="body" />\r
+<style>\r
+body { font-family: Verdana,Arial,sans-serif; font-size: x-small; margin: 0px; padding: 0px; background: #fafafa; margin-left: -5px; }\r
+ul, ol { list-style: none; padding-left: 0px; margin-left: -15px; }\r
+li { margin-left: 19pt; padding-top: 2px; }\r
+a { background-repeat: no-repeat; background-position: 0px 1px; padding-left: 12px; text-decoration: none; }\r
+a.tree { background-image: url('folder.gif'); }\r
+a.leaf { background-image: url('paper.gif'); }\r
+a:link, a:visited { color: #006699; }\r
+a:hover { color: #66AECC; }\r
+</style>\r
+</head>\r
+<body>\r
+<?php\r
+require('../'.$section.'/pages.inc.php');\r
+if (($req_lang != 'en') && (file_exists('../'.$section.'/'.$req_lang.'/pages.inc.php'))) {\r
+       require('../'.$section.'/'.$req_lang.'/pages.inc.php');\r
+}\r
+\r
+echo '<a href="frame_toc.php?'.$section.'" target="_self">';\r
+get_text('back_to_contents');\r
+echo '</a>';\r
+\r
+if ($_GET['query']) {\r
+       $_GET['query'] = str_replace(',', ' ', $_GET['query']);\r
+       $_GET['query'] = str_replace('"', '', $_GET['query']);\r
+\r
+       if (strlen($_GET['query']) > 3) {\r
+               $_GET['query'] = strtolower($_GET['query']);\r
+\r
+               $search_terms = explode(' ', $_GET['query']);\r
+\r
+               $results = array();\r
+               if ($req_lang == 'en') {\r
+                       $files = glob('../'.$section . '/*.php');\r
+               } else {\r
+                       $files = glob('../'.$section . '/'.$req_lang.'/*.php');\r
+               }\r
+               if (is_array($files)) {\r
+                       foreach ($files as $filename) {\r
+                       \r
+                               $count = 0;\r
+                               $filename = basename($filename);\r
+                               \r
+                               if ($req_lang == 'en') {\r
+                                       $contents = strtolower(file_get_contents('../'.$section.'/'.$filename));\r
+                               } else {\r
+                                       $contents = strtolower(file_get_contents('../'.$section. '/'.$req_lang.'/'.$filename));\r
+                               }\r
+\r
+                               foreach ($search_terms as $term) {\r
+                                       $term = trim($term);\r
+                                       if ($term) {\r
+                                               $count += substr_count($contents, $term);\r
+                                       }\r
+                               }\r
+                               if ($count) {\r
+                                       $results[$filename] = $count;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if ($results) {\r
+                       arsort($results);\r
+                       echo '<ol>';\r
+                       foreach ($results as $file => $count) \r
+                       {\r
+                               if (($req_lang != 'en') && (file_exists('../'.$section.'/'.$req_lang.'/'.$file))) \r
+                                       $full_file = '../'.$section.'/'.$req_lang.'/'.$file;\r
+                               else\r
+                                       $full_file = '../'.$section.'/'.$file;\r
+\r
+                               echo '<li><a href="'.$full_file.'?'.$req_lang.'" class="leaf" target="body">'.$_pages[$file].'</a></li>';\r
+                       }\r
+                       echo '</ol>';\r
+               } else {\r
+                       echo '<p style="padding: 8px;">';\r
+                       get_text('no_results_found');\r
+                       echo '</p>';\r
+               }\r
+       } else {\r
+               echo '<p style="padding: 8px;">';\r
+               get_text('search_term_longer_3_chars');\r
+               echo '</p>';\r
+       }\r
+}\r
+?>\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/documentation/common/styles.css b/documentation/common/styles.css
new file mode 100644 (file)
index 0000000..49b48ae
--- /dev/null
@@ -0,0 +1,161 @@
+pre {\r
+       font-family: Verdana, Arial, sans-serif;\r
+}\r
+body{\r
+       background-color: #fafafa;\r
+    font-family: Verdana, Arial,sans-serif;\r
+       font-size: small;\r
+       line-height:150%;\r
+}\r
+h1,h2,h3,p, table, ul {\r
+    font-family: Verdana,Arial,sans-serif;\r
+}\r
+h1 {\r
+       border-bottom: 1px dashed #cfcfcf;\r
+       margin-left: -5px;\r
+       padding-left: 15px;\r
+       margin-right: -5px;\r
+       padding-right: 15px;\r
+}\r
+h2{\r
+       color: #666;\r
+       border-bottom: 1px dashed #cfcfcf;\r
+       margin-left: -5px;\r
+       padding-left: 15px;\r
+       margin-right: -5px;\r
+       padding-right: 15px;\r
+}\r
+a {\r
+       text-decoration: none;\r
+       border-bottom: 1px solid;\r
+       font-weight: bold;\r
+}\r
+a:hover {\r
+       border-bottom: 0px;\r
+}\r
+td,th {\r
+       font-size: 85%;\r
+}\r
+\r
+kbd {\r
+       padding: 0px 1px 0px 1px;\r
+       border-width: 1px 2px 2px 1px;\r
+       border-style: solid;\r
+       border-color: #edd #baa #baa #eed;\r
+       white-space: pre;\r
+}\r
+\r
+code {\r
+    font-family: Verdana,Arial,sans-serif;\r
+       background-color: #efefef;\r
+       padding: 0px 4px 0px 4px;\r
+       border-width: 1px 1px 1px 1px;\r
+       border-style: solid;\r
+       border-color: #edd #baa #baa #eed;              \r
+}\r
+\r
+\r
+div#toc {\r
+       color: #f0f0f0;\r
+       padding-bottom: 15px;\r
+}\r
+\r
+div#toc ul {\r
+       list-style: none;\r
+}\r
+div#toc li {\r
+       padding-top: 2px;\r
+       padding-bottom: 0px;\r
+}\r
+\r
+ol {\r
+       margin-top: 0px;\r
+}\r
+\r
+ol li {\r
+       padding-bottom: 3px;\r
+}\r
+\r
+dl {\r
+       margin: 0 10px\r
+}\r
+dl dd { \r
+       padding-top: 0px;\r
+       padding-left: 5px;\r
+       margin-left: 5%;\r
+       border-left: 1px solid #d0d0d0;\r
+       margin-bottom: 10px;\r
+}\r
+\r
+dd p {\r
+       margin-top: 0px;\r
+       margin-bottom: 0px;\r
+}\r
+dd p:last-child {\r
+       padding-bottom: 0px;\r
+}\r
+acronym {\r
+       cursor: help;\r
+}\r
+a[href*="http"] {\r
+       padding-right: 8px;\r
+       background-image: url('link-out.gif');\r
+       background-repeat: no-repeat;\r
+       background-position: right 4px;\r
+       margin-right: 2px;\r
+}\r
+div#nav-links {\r
+       margin-left: 20px;\r
+       margin-right: 20px;\r
+       margin-bottom: 20px;\r
+}\r
+div#nav-links a {\r
+       color: black;\r
+       text-decoration: none;\r
+       border-bottom: 1px solid;\r
+}\r
+pre {\r
+       font-family: Courier, monospace;\r
+       background-color: #eef;\r
+       padding: 5px;\r
+       margin-left: 20px;\r
+       color:#761596;\r
+    margin-top: 0px;\r
+       width: 50%;\r
+       font-size: smaller;\r
+}\r
+div.seq {\r
+       font-size: smaller;\r
+       padding: 5px;\r
+       border: 1px dashed #cfcfcf;\r
+}\r
+div.tag {\r
+       margin: 10px;\r
+       font-size: smaller;\r
+       padding: 5px;\r
+       line-height: 110%;\r
+       color: #cfcfcf;\r
+}\r
+div.add-note {\r
+       background-color: #f0f0f0;\r
+       padding: 5px;\r
+}\r
+div.add-note h3 {\r
+       margin-top: 0px;\r
+       margin-bottom: 0px;\r
+}\r
+div.note {\r
+       background-color: #fefefe;\r
+       padding: 5px;\r
+       margin-bottom: 5px;\r
+}\r
+div.note h4 {\r
+       margin-top: 0px;\r
+       margin-bottom: 0px;\r
+}\r
+div.note h5 {\r
+       margin-top: 0px;\r
+       margin-bottom: 0px;\r
+       float: right;\r
+       font-weight: normal;\r
+}
\ No newline at end of file
diff --git a/documentation/common/text.php b/documentation/common/text.php
new file mode 100644 (file)
index 0000000..8db0355
--- /dev/null
@@ -0,0 +1,43 @@
+<?php\r
+$text = array();\r
+$text['next_chapter'] = 'Next Chapter';\r
+$text['previous_chapter'] = 'Previous Chapter';\r
+$text['page_not_translated'] = 'This section has not yet been translated to your requested language.';\r
+$text['atutor_documentation'] = 'ATutor Handbook';\r
+$text['handbook_toc'] = 'Handbook TOC';\r
+$text['close_popup'] = 'Close Pop-up';\r
+$text['return_to_handbook'] = 'Return to Handbook';\r
+$text['print_version'] = 'Print Version';\r
+$text['show_contents'] = 'Show Contents';\r
+$text['hide_contents'] = 'Hide Contents';\r
+$text['language']      = 'Language';\r
+$text['search']        = 'Search';\r
+$text['back_to_contents'] = 'Back to Contents';\r
+$text['no_results_found'] = 'No results found.';\r
+$text['search_term_longer_3_chars'] = 'Search term must be longer than 3 characters.';\r
+$text['doc_user'] = 'User Documentation';\r
+$text['doc_admin'] = 'Administrator Documentation';\r
+$text['doc_dev'] = 'Developer Documentation';\r
+$text['doc_instructor'] = 'Instructor Documentation';\r
+$text['doc_mods'] = 'Module Development Documentation';\r
+$text['doc_notes_enabled'] = 'User contributed notes is <em>enabled</em>. <a href="index.php?login">Administrator Login</a>.';\r
+$text['doc_title'] = 'ATutor Handbook';\r
+$text['doc_welcome'] = 'Welcome to the official ATutor Handbook!';\r
+$text['doc_unapproved_notes'] = 'Un-Approved User Contributed Notes';\r
+$text['doc_approved_confirm'] = 'Are you sure you want to approve this note?';\r
+$text['doc_approve'] = 'Approve';\r
+$text['doc_delete'] = 'Delete';\r
+$text['doc_delete_confirm'] = 'Are you sure you want to delete this note?';\r
+$text['doc_no_notes'] = 'There are no un-approved user contributed notes.';\r
+$text['doc_logged_in'] = 'Logged in as notes moderator. <a href="index.php?logout">Log-out</a>.';\r
+$text['user_contributed_notes'] = 'User Contributed Notes';\r
+$text['no_notes_on_page'] = 'There are no user contributed notes for this page.';\r
+$text['delete'] = 'Delete';\r
+$text['are_you_sure_delete_note'] = 'Are you sure you want to delete this note?';\r
+$text['add_note'] = 'Add Note';\r
+$text['add_note_blurb'] = 'If you ask a question, report a bug, or request a feature, your note will not be posted. Notes must be approved by an administrator before they are posted.';\r
+$text['email_name'] = 'Your email address (or name)';\r
+$text['your_note'] = 'Your note';\r
+$text['note_added'] = 'Your note has been saved. It will appear only after it has been approved by an administrator.';\r
+$text['back_to_chapters'] = 'Back to Chapters';\r
+?>
\ No newline at end of file
diff --git a/documentation/common/vitals.inc.php b/documentation/common/vitals.inc.php
new file mode 100644 (file)
index 0000000..f306d3f
--- /dev/null
@@ -0,0 +1,167 @@
+<?php\r
+error_reporting(E_ALL ^ E_NOTICE);\r
+\r
+// Emulate register_globals off. src: http://php.net/manual/en/faq.misc.php#faq.misc.registerglobals\r
+function unregister_GLOBALS() {\r
+   if (!ini_get('register_globals')) { return; }\r
+\r
+   // Might want to change this perhaps to a nicer error\r
+   if (isset($_REQUEST['GLOBALS'])) { die('GLOBALS overwrite attempt detected'); }\r
+\r
+   // Variables that shouldn't be unset\r
+   $noUnset = array('GLOBALS','_GET','_POST','_COOKIE','_REQUEST','_SERVER','_ENV', '_FILES');\r
+   $input = array_merge($_GET,$_POST,$_COOKIE,$_SERVER,$_ENV,$_FILES,isset($_SESSION) && is_array($_SESSION) ? $_SESSION : array());\r
+  \r
+   foreach ($input as $k => $v) {\r
+       if (!in_array($k, $noUnset) && isset($GLOBALS[$k])) { unset($GLOBALS[$k]); }\r
+   }\r
+}\r
+\r
+unregister_GLOBALS();\r
+\r
+function debug($var, $title='') {\r
+\r
+       echo '<pre style="border: 1px black solid; padding: 0px; margin: 10px;">';\r
+       if ($title) {\r
+               echo '<h4>'.$title.'</h4>';\r
+       }\r
+       \r
+       ob_start();\r
+       print_r($var);\r
+       $str = ob_get_contents();\r
+       ob_end_clean();\r
+\r
+       $str = str_replace('<', '&lt;', $str);\r
+\r
+       $str = str_replace('[', '<span style="color: red; font-weight: bold;">[', $str);\r
+       $str = str_replace(']', ']</span>', $str);\r
+       $str = str_replace('=>', '<span style="color: blue; font-weight: bold;">=></span>', $str);\r
+       $str = str_replace('Array', '<span style="color: purple; font-weight: bold;">Array</span>', $str);\r
+       echo $str;\r
+       echo '</pre>';\r
+}\r
+\r
+function get_text($var, $return = FALSE) {\r
+       global $req_lang, $lang, $section;\r
+\r
+       static $req_lang_text, $lang_text;\r
+\r
+       if (!isset($req_lang_text) && ($req_lang != 'en')) {\r
+               $text = array();\r
+               if (file_exists(dirname(__FILE__) . '/'.$req_lang.'/text.php')) {\r
+                       require(dirname(__FILE__) . '/'.$req_lang.'/text.php');\r
+               }\r
+\r
+               $req_lang_text = $text;\r
+       } else if (!isset($lang_text)) {\r
+               $text = array();\r
+               require(dirname(__FILE__) . '/text.php');\r
+               $lang_text = $text;\r
+       }\r
+\r
+       if (isset($req_lang_text[$var])) {\r
+               if ($return) {\r
+                       return $req_lang_text[$var];\r
+               }\r
+               echo $req_lang_text[$var];\r
+       } else if (isset($lang_text[$var])) {\r
+               if ($return) {\r
+                       return $lang_text[$var];\r
+               }\r
+               echo $lang_text[$var];\r
+       } else {\r
+               if ($return) {\r
+                       return $var;\r
+               }\r
+               echo $var;\r
+       }\r
+}\r
+\r
+function get_available_languages($section) {\r
+       global $available_languages;\r
+\r
+       $path = dirname(__FILE__);\r
+       if (is_dir($path)) {\r
+               $files = glob($path . '/??');\r
+               if (is_array($files)) {\r
+                       foreach ($files as $filename) {\r
+                               $filename = basename($filename);\r
+                               $available_languages[$filename] = $filename;\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+define('AT_HANDBOOK', true);\r
+session_name('ATutorID');\r
+session_start();\r
+// $lang is the language we've found to display\r
+// $req_lang is the language we're requesting\r
+\r
+\r
+$_available_sections = array('admin' => 'admin', 'instructor' => 'instructor', 'general' => 'general', 'index' => 'index');\r
+$available_languages = array('en' => 'en', 'fr'=>'fr');\r
+\r
+$parts = pathinfo($_SERVER['PHP_SELF']);\r
+$this_page = $parts['basename'];\r
+\r
+$dir_parts = explode('/', $parts['dirname']);\r
+$last_dir_name = end($dir_parts);\r
+$second_last_dir_name = prev($dir_parts);\r
+\r
+if (isset($_available_sections[$second_last_dir_name])) {\r
+       $lang = $req_lang = $last_dir_name;\r
+       $section = $second_last_dir_name;\r
+       $rel_path = '../../';\r
+       get_available_languages($section);\r
+} else if (isset($_available_sections[$last_dir_name])) {\r
+       $section = $last_dir_name;\r
+       $rel_path = '../';\r
+       get_available_languages($section);\r
+\r
+       foreach ($_GET as $lang_name => $garbage) {\r
+               if (isset($available_languages[$lang_name])) {\r
+                       $lang = $req_lang = $lang_name;\r
+                       break;\r
+               }\r
+       }\r
+       if (!$lang && !$req_lang && isset($_SESSION['lang']) && isset($available_languages[$_SESSION['lang']])) {\r
+               $lang = $req_lang = $_SESSION['lang'];\r
+       } else if (!$lang && !$req_lang) {\r
+               $lang = $req_lang = 'en';\r
+       }\r
+\r
+} else {\r
+       foreach ($_available_sections as $section_name) {\r
+               if (isset($_GET[$section_name])) {\r
+                       $section = $section_name;\r
+                       unset($_GET[$section]);\r
+                       break;\r
+               }\r
+       }\r
+       if ($section) {\r
+               get_available_languages($section);\r
+               foreach ($available_languages as $lang_name) {\r
+                       if (isset($_GET[$lang_name])) {\r
+                               $lang = $req_lang = $lang_name;\r
+                               break;\r
+                       }\r
+               }\r
+               if ((!isset($lang) || !$lang) && isset($_SESSION['lang']) && isset($available_languages[$_SESSION['lang']])) {\r
+                       $lang = $req_lang = $_SESSION['lang'];\r
+               } else if (!$lang) {\r
+                       $lang = $req_lang = 'en';\r
+               }\r
+               $rel_path = '../';\r
+       } else {\r
+               $lang = $req_lang = 'en';\r
+               $section = 'general';\r
+               $rel_path = '../';\r
+               get_available_languages($section);\r
+       }\r
+}\r
+\r
+$lang = htmlspecialchars($lang);\r
+$req_lang = htmlspecialchars($req_lang);\r
+\r
+?>
\ No newline at end of file
diff --git a/documentation/config.inc.php b/documentation/config.inc.php
new file mode 100644 (file)
index 0000000..ad8b3b3
--- /dev/null
@@ -0,0 +1,43 @@
+<?php\r
+/* this is an optional configuration file. */\r
+/* it is used only when the ATutor configuration cannot be found, or if it */\r
+/* can be found but AT_ENABLE_HANDBOOK_NOTES is set to false. */\r
+/* */\r
+/* use the settings found here to enable/disable user notes. */\r
+/* user notes require a valid database connection and a pre-existing */\r
+/* database table. */\r
+/* the structure/schema of the database table is defined at the bottom */\r
+/* of this file. use it to create the table before enabling user notes. */\r
+\r
+define('AT_HANDBOOK_DB_HOST', 'localhost');\r
+\r
+define('AT_HANDBOOK_DB_PORT', '3306');\r
+\r
+define('AT_HANDBOOK_DB_USER', '');\r
+\r
+define('AT_HANDBOOK_DB_PASSWORD', '');\r
+\r
+define('AT_HANDBOOK_DB_DATABASE', 'atutor');\r
+\r
+define('AT_HANDBOOK_DB_TABLE_PREFIX', 'AT_');\r
+\r
+define('AT_HANDBOOK_ADMIN_USERNAME', '');\r
+define('AT_HANDBOOK_ADMIN_PASSWORD', '');\r
+\r
+define('AT_HANDBOOK_ENABLE', true);\r
+\r
+/*\r
+# Note: you will have to add the table prefix!!\r
+\r
+CREATE TABLE `handbook_notes` (\r
+`note_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT ,\r
+`date` DATETIME NOT NULL ,\r
+`section` VARCHAR( 15 ) NOT NULL ,\r
+`page` VARCHAR( 50 ) NOT NULL ,\r
+`approved` TINYINT NOT NULL,\r
+`email` VARCHAR( 50 ) NOT NULL ,\r
+`note` TEXT NOT NULL ,\r
+PRIMARY KEY ( `note_id` )\r
+);\r
+*/\r
+?>
\ No newline at end of file
diff --git a/documentation/delete_note.php b/documentation/delete_note.php
new file mode 100644 (file)
index 0000000..f714464
--- /dev/null
@@ -0,0 +1,64 @@
+<?php\r
+require(dirname(__FILE__) .'/common/vitals.inc.php');\r
+\r
+if (!isset($_SESSION['handbook_admin']) || !$_SESSION['handbook_admin'] || !isset($_GET['id'])) {\r
+       exit;\r
+}\r
+\r
+function my_add_null_slashes( $string ) {\r
+    return ( $string );\r
+}\r
+\r
+if ( get_magic_quotes_gpc() == 1 ) {\r
+       $addslashes = 'my_add_null_slashes';\r
+} else {\r
+       $addslashes = 'addslashes';\r
+}\r
+\r
+\r
+$_GET['id'] = intval($_GET['id']);\r
+$_GET['p'] = $addslashes($_GET['p']);\r
+\r
+$config_location = '../include/config.inc.php';\r
+if (is_file($config_location) && is_readable($config_location)) {\r
+       require($config_location);\r
+       $db = mysql_connect(DB_HOST . ':' . DB_PORT, DB_USER, DB_PASSWORD);\r
+       mysql_select_db(DB_NAME, $db);\r
+\r
+       // check atutor config table to see if handbook notes is enabled.\r
+       $sql    = "SELECT value FROM ".TABLE_PREFIX."config WHERE name='user_notes'";\r
+       $result = @mysql_query($sql, $db);\r
+       if (($row = mysql_fetch_assoc($result)) && $row['value']) {\r
+               define('AT_HANDBOOK_ENABLE', true);\r
+               $enable_user_notes = true;\r
+       }\r
+       define('AT_HANDBOOK_DB_TABLE_PREFIX', TABLE_PREFIX);\r
+\r
+       define('AT_HANDBOOK_ENABLE', true);\r
+}\r
+if (!defined('AT_HANDBOOK_ENABLE')) {\r
+       // use local config file\r
+       require('./config.inc.php');\r
+}\r
+\r
+if (!$db && defined('AT_HANDBOOK_ENABLE') && AT_HANDBOOK_ENABLE) {\r
+       $db = @mysql_connect(AT_HANDBOOK_DB_HOST . ':' . AT_HANDBOOK_DB_PORT, AT_HANDBOOK_DB_USER, AT_HANDBOOK_DB_PASSWORD);\r
+       if (@mysql_select_db(AT_HANDBOOK_DB_DATABASE, $db)) {\r
+               $enable_user_notes = true;\r
+       }\r
+}\r
+\r
+if ($enable_user_notes) {\r
+       // insert into DB\r
+       $sql = "DELETE FROM ".AT_HANDBOOK_DB_TABLE_PREFIX."handbook_notes WHERE note_id=$_GET[id]";\r
+       mysql_query($sql, $db);\r
+}\r
+\r
+if (isset($_GET['p'])) {\r
+       header('Location: '.$section. '/' . $_GET['p']);\r
+} else {\r
+       header('Location: index_list.php');\r
+}\r
+exit;\r
+\r
+?>
\ No newline at end of file
diff --git a/documentation/developer/database.gif b/documentation/developer/database.gif
new file mode 100644 (file)
index 0000000..270dbdc
Binary files /dev/null and b/documentation/developer/database.gif differ
diff --git a/documentation/developer/guidelines.html b/documentation/developer/guidelines.html
new file mode 100644 (file)
index 0000000..a09b810
--- /dev/null
@@ -0,0 +1,1682 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">\r
+<!-- $Id: guidelines.html 3071 2005-01-12 21:53:13Z joel $ -->\r
+\r
+<html>\r
+<head>\r
+       <title>ATutor Developer Documentation</title>\r
+       <meta name="author" content="Joel Kronenberg" />\r
+       <meta name="description" content="ATutor developer documentation and coding guidelines" />\r
+\r
+<style type="text/css">\r
+h1 {\r
+       background-color: #CCCCCC;\r
+       padding-left: 20px;\r
+       padding-right: 20px;\r
+       margin-bottom: 10px;\r
+       text-align: right;\r
+}\r
+\r
+h2 {\r
+       background-color: #DDDDDD;\r
+       padding-left: 10px;\r
+       margin-bottom: 0px;\r
+}\r
+h3 {\r
+       background-color: #EFEFEF;\r
+       padding-left: 20px;\r
+       margin-bottom: 0px;\r
+}\r
+h4  { margin-bottom: 0px; }\r
+p   { margin-top: 0px;    }\r
+dl  { margin-top: 0px;    }\r
+kbd { color: #761596;     }\r
+blockquote { font-style: italic; }\r
+pre.code {\r
+       background-color: #EEEEFF;\r
+       padding: 5px;\r
+       margin-left: 20px;\r
+       color:#761596;\r
+    margin-top: 0px;\r
+}\r
+.top {\r
+       float: right;\r
+       color: green;\r
+       padding-top: 2px;\r
+       padding-right: 5px;\r
+}\r
+\r
+@media print {\r
+       h2 {\r
+               page-break-after: avoid;\r
+               border-bottom: solid 1px black;\r
+       }\r
+       h3 {\r
+               page-break-after: avoid;\r
+               border-bottom: solid 1px black;\r
+               width: 75%;\r
+       }\r
+       .top {\r
+               display: none;\r
+       }\r
+\r
+       pre.code {\r
+               page-break-inside: avoid;\r
+       }\r
+}\r
+</style>\r
+</head>\r
+<body>\r
+<h1><a name="top"></a>ATutor Developer Documentation</h1>\r
+\r
+<h2>Table of Contents</h2>\r
+\r
+<ul>\r
+       <li>0. <a href="#version">Version Considerations</a></li>\r
+       <li>1. <a href="#introduction">Introduction</a></li>\r
+               <ul>\r
+                       <li>1.1 <a href="#introduction-api">API Documentation</a></li>\r
+               </ul>\r
+       <li>2. <a href="#conventions">Conventions Used in This Document</a>\r
+               <ul>\r
+                       <li>2.1 <a href="#typographic-conventions">Typographic Conventions</a></li>\r
+                       <li>2.2 <a href="#links-conventions">Links</a></li>\r
+                       <li>2.3 <a href="#function-definitions">Function Definitions (Prototypes)</a></li>\r
+               </ul></li>\r
+    <li>3. <a href="#setup">Setup</a>\r
+               <ul>\r
+                       <li>3.1 <a href="#php-configuration">PHP Configuration</a></li>\r
+               </ul></li>\r
+    <li>4. <a href="#subversion">Subversion (SVN)</a>\r
+               <ul>\r
+                       <li>4.1 <a href="#svn-install">Installing an SVN Client &amp; Checking-Out</a></li>\r
+                       <li>4.2 <a href="#svn-installing_atutor">Installing ATutor From SVN</a></li>\r
+                       <li>4.3 <a href="#svn-update">Updating ATutor From SVN</a></li>\r
+                       <li>4.4 <a href="#svn-keywords">Keywords</a></li>\r
+\r
+               </ul></li>\r
+    <li>5. <a href="#communication">Communication</a></li>\r
+    <li>6. <a href="#patches">Patches</a></li>\r
+    <li>7. <a href="#editor-tips">Editor Tips</a></li>\r
+    <li>8. <a href="#proposed-features">Proposed Features</a></li>\r
+    <li>9. <a href="#bug-tracking">Bug Tracking</a></li>\r
+    <li>10. <a href="#creating-bundles">Creating Bundles</a></li>\r
+       <li>11. <a href="#writing-portable-code">Writing Portable Code</a></li>\r
+       <li>12. <a href="#coding-style">Coding Style</a>\r
+               <ul>\r
+                       <li>12.1 <a href="#indentation">Indentation</a></li>\r
+                       <li>12.2 <a href="#line-length">Line Length</a></li>\r
+                       <li>12.3 <a href="#whitespace">Using Whitespace</a></li>\r
+                       <li>12.4 <a href="#sql-guidelines">SQL Guidelines</a></li>\r
+                       <li>12.5 <a href="#sql-joins">SQL/99 Joins</a></li>\r
+                       <li>12.6 <a href="#control-flow-constructs">Control Flow Constructs</a></li>\r
+                       <li>12.7 <a href="#commenting">Commenting</a></li>\r
+                       <li>12.8 <a href="#naming-conventions">Naming Conventions</a>\r
+                               <ul>\r
+                                       <li>12.8.1 <a href="#naming-variables">Naming Variables</a></li>\r
+                                       <li>12.8.2 <a href="#naming-functions">Naming Functions</a></li>\r
+                                       <li>12.8.3 <a href="#naming-files">Naming Files</a></li>\r
+                               </ul></li>\r
+               </ul></li>\r
+       <li>13. <a href="#directory-structure">Directory Structure</a>\r
+               <ul>\r
+                       <li>13.1 <a href="#directories">Directories</a></li>\r
+                       <li>13.2 <a href="#files">Files</a></li>\r
+               </ul></li>\r
+       <li>14. <a href="#database-structure">Database Structure</a></li>\r
+       <li>15. <a href="#localisation">Localisation</a>\r
+               <ul>\r
+                       <li>15.1 <a href="#adding-language">Adding &amp; Editing Language</a></li>\r
+               </ul></li>\r
+       <li>16. <a href="#error-feedback-messages">Error and Feedback Messages</a>\r
+               <ul>\r
+                       <li>16.1 <a href="#error-feedback-internals">Internals</a></li>\r
+                       <li>16.2 <a href="#error-feedback-adding">Adding Messages</a></li>\r
+                       <li>16.3 <a href="#error-feedback-printing">Printing Messages</a></li>                  \r
+                       <li>16.4 <a href="#mbstring-support">UTF-8 and Multibyte language</a></li>\r
+               </ul>\r
+       </li>\r
+       <li>17. <a href="#useful-variables">Useful Variables</a>\r
+               <ul>\r
+                       <li>17.1 <a href="#var-db">$db</a></li>\r
+                       <li>17.2 <a href="#var-addslashes">$addslashes</a></li>\r
+                       <li>17.3 <a href="#var-base_href">$_base_href</a></li>\r
+                       <li>17.4 <a href="#var-base_path">$_base_path</a></li>\r
+                       <li>17.5 <a href="#var-user_location">$_user_location</a></li>\r
+                       <li>17.6 <a href="#var-rel_url">$_rel_url</a></li>\r
+                       <li>17.7 <a href="#var-my_uri">$_my_uri</a></li>\r
+                       <li>17.8 <a href="#var-content_manager">$contentManager</a></li>\r
+                       <li>17.9 <a href="#var-section">$_section</a></li>\r
+               </ul></li>\r
+       <li>18. <a href="#useful-functions">Useful Functions</a>\r
+               <ul>\r
+                       <li>18.1 <a href="#fn-authenticate">authenticate()</a></li>\r
+                       <li>18.2 <a href="#fn-at">_AT()</a></li>\r
+                       <li>18.3 <a href="#fn-at_print">AT_print()</a></li>\r
+                       <li>18.4 <a href="#fn-at_date">AT_date()</a></li>\r
+                       <li>18.5 <a href="#fn-addslashes">$addslashes()</a></li>\r
+                       <li>18.6 <a href="#fn-debug">debug()</a></li>\r
+                       <li>18.7 <a href="#fn-get_login">get_login()</a></li>\r
+                       <li>18.8 <a href="#fn-urlencode_feedback">urlencode_feedback()</a></li>\r
+                       <li>18.9 <a href="#fn-url_rewrite">url_rewrite()</a></li>\r
+               </ul></li>\r
+       <li>19. <a href="#useful-constants">Useful Constants</a>\r
+               <ul>\r
+                       <li>19.1 <a href="#const-include_path">AT_INCLUDE_PATH</a></li>\r
+                       <li>19.2 <a href="#const-sep">SEP</a></li>\r
+                       <li>19.3 <a href="#const-devel">AT_DEVEL</a></li>\r
+                       <li>19.4 <a href="#const-table_prefix">TABLE_PREFIX</a></li>\r
+                       <li>19.5 <a href="#const-version">VERSION</a></li>\r
+               </ul></li>\r
+       <li>20. <a href="#install-upgrade-scripts">Install &amp; Upgrade Scripts</a>\r
+               <ul>\r
+                       <li>20.1 <a href="#install-script">Install Script</a></li>\r
+                       <li>20.2 <a href="#upgrade-script">Upgrade Script</a></li>\r
+               </ul></li>\r
+       <li>21. <a href="#accessibility">Accessibility</a></li>\r
+       <li>22. <a href="#validation">Validation</a></li>\r
+       <li>23. <a href="#example">Sample Script</a></li>\r
+       <li>24. <a href="#credits-sources">Credits &amp; Additional Sources</a></li>\r
+</ul>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="version"></a>0. Version Considerations</h2>\r
+       <p>This document is found in ATutor's <kbd>documentation/</kbd> directory and is maintained along with the rest of the code in the code repository. The latest version of this document will always be available in the repository. Versions bundled with ATutor releases are specific to that release. If you are modifying a previous version of ATutor then you should refer to the version of these guidlines as they are available with that specific version.</p>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="introduction"></a>1. Introduction</h2>\r
+       <p>ATutor, as an open source project, encourages PHP developers to develop their own custom features, and potentially contribute those features so they become a permanent part of ATutor. To ensure that  code is easy to  maintain, we urge developers to follow the guidelines outlined below. These rules and recommendations were created to standardize the distributed development process.</p>\r
+\r
+       <p>The latest version of this document can always be found at <a href="http://www.atutor.ca/atutor/docs/">ATutor.ca</a>.</p>\r
+       <h3><a name="introduction-api"></a>1.1 API Documentation</h3>\r
+               <p>Detailed API documentation is distributed throughout the ATutor source code, describing functions and classes, and how they are used in developing features. API documentation can be extracted into a relatively compact form for easy scanning and searching using the <strong>phpDocumentor module</strong>. Download the module from atutor.ca, and install it like any other module, then run the application to extract the API documentation from ATutor.</p>\r
+\r
+               <p><a href="http://www.atutor.ca/atutor/modules/index.php">phpDocumentor Module</p>\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="conventions"></a>2. Conventions Used in This Document</h2>\r
+       <p>This section covers the typographical conventions used in this document.</p>\r
+\r
+       <h3><a name="typographic-conventions"></a>2.1 Typographic Conventions</h3>\r
+       <dl>\r
+               <dt><kbd>Constant width</kbd></dt>\r
+               <dd><p>Used for commands and code examples. Example: Use the <kbd>debug()</kbd> function to view a variable.</p></dd>\r
+\r
+               <dt><kbd>`Constant width surrounded by quotes`</kbd></dt>\r
+               <dd><p>Constant-width font with surrounding quotes is used for filenames and path names. Example: The <kbd>`vitals.php`</kbd> file is important.</p></dd>\r
+\r
+               <dt>Square brackets (<kbd>`[`</kbd> and <kbd>`]`</kbd>)</dt>\r
+               <dd><p>In syntax descriptions, square brackets (<kbd>`[`</kbd> and <kbd>`]`</kbd>) are used to indicate optional words or clauses. Not to be confused with the use of square brackets in <kbd>array</kbd> definitions. For example, in the following statement, <kbd>version</kbd> is optional: <kbd>./bundle.sh [version]</kbd>.</p></dd>\r
+\r
+               <dt>Pipe (<kbd>`|`</kbd>)</dt>\r
+               <dd><p>When a syntax element consists of a number of alternatives, the alternatives are separated by pipes (<kbd>`|`</kbd>).</p></dd>\r
+       </dl>\r
+\r
+       <p>Example code is to be used as examples only and not as tested production code. In most cases its usefulness in the context of the example outweighs its correctness as workable code. In other cases the syntax and style used in the example itself are irrelevant and do not follow the coding guidelines outlined below. For example, <kbd>array</kbd>s may be documented using <kbd>string</kbd> keys without quoting their value, <kbd>$_SESSION[prefs]</kbd>, while in practice it is always best to escape the key with quotes: <kbd>$_SESSION['prefs']</kbd>.</p>\r
+\r
+       <h3><a name="links-conventions"></a>2.2 Links</h3>\r
+               <p>All the links in this document open in the current browser. Links that are not obviously to external sites are supplemented with <em>title</em> text. All other links are assumed to be anchors within this document.</p>\r
+\r
+       <h3><a name="function-definitions"></a>2.3 Function Definitions (Prototypes)</h3>\r
+               <p>The usage of the square brackets (<kbd>`[`</kbd> and <kbd>`]`</kbd>) around parameters imply that they are optional, in which case the function documentation will then state what the default value for that variable is. Please pay close attention to the return types of functions: If a function is described to return <kbd>boolean</kbd> then it will return either <kbd>TRUE</kbd> or <kbd>FALSE</kbd> and <strong>not</strong> an <kbd>integer</kbd> such as 0 or 1. Optional arguments to functions must always be listed as the last parameters in the list.</p>\r
+\r
+               <p><kbd>returned_type <strong>function_name</strong>( param_type $param_name [, opt_param_type $opt_param_name])</kbd></p>\r
+               <dl>\r
+                       <dt><kbd>returned_type</kbd></dt>\r
+                       <dd><p>Type of value this function returns. See <a href="http://www.php.net/manual/en/language.types.php" title="PHP.net - Chapter 6. Types">Types</a> and <a href="http://www.php.net/manual/en/types.comparisons.php" title="PHP.net - Appendix O. PHP type comparison tables">PHP type comparison tables</a>.</p></dd>\r
+\r
+                       <dt><kbd>function_name</kbd></dt>\r
+                       <dd><p>The function name.</p></dd>\r
+\r
+                       <dt><kbd>param_type</kbd> and <kbd>opt_param_type</kbd></dt>\r
+                       <dd><p>The type of the parameter that the function expects. See <a href="http://www.php.net/manual/en/language.types.php" title="PHP.net - Chapter 6. Types">Types</a> and <a href="http://www.php.net/manual/en/types.comparisons.php" title="PHP.net - Appendix O. PHP type comparison tables">PHP type comparison tables</a>.</p></dd>\r
+\r
+                       <dt><kbd>$param_name</kbd> and <kbd>$opt_param_name</kbd></dt>\r
+                       <dd><p>The names of the parameters as they are used in the function. The <kbd>$opt_param_name</kbd> is optional.</p></dd>\r
+               </dl>\r
+       </p>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="setup">3. Setup</a></h2>\r
+       <p>Please review the <a href="http://atutor.ca/atutor/docs/requirements.php" title="ATutor.ca - requirements">ATutor requirements</a> and ensure that your development environment meets the minimum requirements.</p>\r
+\r
+       <ul>\r
+               <li><a href="http://dev.mysql.com/doc/mysql/en/Installing.html">MySQL.com - Installation MySQL</a></li>\r
+               <li><a href="http://www.php.net/manual/en/installation.php">PHP.net - Installing PHP with Apache</a></li>\r
+               <li><a href="http://www.thesitewizard.com/archive/php4install.shtml">How to Install and Configure PHP4 to Run with Apache on Windows</a></li>\r
+       </ul>\r
+\r
+       <h3><a name="php-configuration"></a>3.1 PHP Configuration</h3>\r
+       <p>If you have a dedicated development environment that doesn't share a web server with other production code, then it is best to use the bundled <kbd>php.ini-dist</kbd> configuration file as the default--simply rename it to <kbd>php.ini</kbd>. Listed below are the essential configuration options and their recommended value:</p>\r
+<pre class="code">\r
+safe_mode            = Off\r
+error_reporting      = E_ALL\r
+display_errors       = On\r
+arg_separator.input  = ";&"\r
+register_globals     = Off\r
+magic_quotes_gpc     = Off\r
+magic_quotes_runtime = Off\r
+allow_url_fopen      = On\r
+register_argc_argv   = Off</pre></p>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="subversion"></a>4. Subversion (SVN)</h2>\r
+       <p>We have adopted Subversion (SVN) in place of the aging CVS, allowing us to open up the development repository while still maintaining control over the core project. Additional information can be found on the <a href="http://subversion.tigris.org/project_packages.html">Subversion homepage</a>.</p>\r
+\r
+       <h3><a name="svn-install"></a>4.1 Installing an SVN Client &amp; Checking-Out</h3>\r
+               <p>To obtain a working copy of ATutor, you need to install an SVN client and do a <kbd>checkout</kbd> from our repository of the latest ATutor source code. Checking out the repository creates a copy of it on your local machine with the necessary version control information. The location of the copied files should be web accessible, i.e. a directory under your web server's path. </p>\r
+\r
+               <p>For windows users, we recommend using <a href="http://tortoisesvn.tigris.org/">TortoiseSVN</a>, which is a feature-rich SVN extension for Windows that supports many of the options of other SVN clients (file browser and filters not being one of them). Once TortoiseSVN has been successfully installed and you've rebooted your computer, go to a working directory where you wish to <kbd>checkout</kbd> the ATutor source code. Right-click to pop-up the context menu and select the command "Checkout...". </p>\r
+\r
+               <p>For repository URL, enter <kbd>http://atutorsvn.atrc.utoronto.ca/repos/atutor/trunk</kbd>. If you enter a folder name that does not yet exist, a directory with that name will be created. Press "OK", and the source will be downloaded to your computer.</p>\r
+\r
+               <p>For non-Windows users, download an appropriate SVN package from the <a href="http://subversion.tigris.org/project_packages.html" title="Subversion packages">Subversion homepage</a> and follow the installation instructions. These packages use the command-line client. Checking out the most recent ATutor source code can be done with the following command: <kbd>svn checkout http://atutorsvn.atrc.utoronto.ca/repos/atutor/trunk</kbd>. Unix users also have available a GUI tool called <a href="http://rapidsvn.tigris.org/">RapidSVN</a></p>\r
+               <p>The checkout includes:</p>\r
+               <ul>\r
+                       <li><kbd>bundle.sh</kbd> - Execute this shell script to generate an installable bundle of the ATutor.</li>\r
+                       <li><kbd>docs/</kbd> - The ATutor source code</li>\r
+                       <li><kbd>mods/</kbd> - Extra module source code</li>\r
+               </ul>\r
+               <p>Extra modules can also be checked out into the ATutor <kbd>mods/</kbd> directory, from where they can be easily installed using the ATutor administor's Install Modules tool. See the <a href="modules.html">ATutor Module Documentation</a> for more about creating and modifying modules. From within the <kbd>docs/mods/</kbd> directory of your development version of ATutor, use  <kbd>svn checkout http://atutorsvn.atrc.utoronto.ca/repos/atutor/trunk/mods/[module_name]</kbd>.</p>\r
+       <h3><a name="svn-installing_atutor"></a>4.2 Installing ATutor From SVN</h3>\r
+               <p>Before starting the installation process you should create an empty <kbd>`config.inc.php`</kbd> file in the <kbd>`include/`</kbd> directory: use <kbd>touch config.inc.php</kbd> on UNIX. Browse to the location of your checked out files in a web browser and proceed with the ATutor installation instructions. This will set up the database and user accounts for your ATutor system. The resulting ATutor installation will be your development environment.</p>\r
+\r
+       <h3><a name="svn-update"></a>4.3 Updating ATutor From SVN</h3>\r
+               <p>You should regularly perform updates from the repository to make sure you are working with the developers' latest files. To do this with TortoiseSVN, right click on the working folder and select "Update" from the context menu. For command-line svn clients, use: <kbd>svn update</kbd>.</p>\r
+\r
+               <p>Always review the latest SVN SQL upgrade file to ensure your database structure is up-to-date. The file will contain schema changes of the current pre-released source. Example: If the current working source will be version 1.9, then the upgrade file to keep track of will be named <kbd>atutor_upgrade_<em>x.y.z</em>_to_1.9.sql</kbd>, where <kbd><em>x.y.z</em></kbd> is the version of the currently available stable release.</p>\r
+\r
+       <h3><a name="svn-keywords"></a>4.4 Keywords</h3>\r
+               <p>Until Subversion supports server wide configuration options, the <kbd>svn:keyword="Id"</kbd> option will have to be set on a file-by-file basis via the client. After the keyword property has been set for the given file, add the line <kbd>// $ I d</kbd> (without the spaces) at the top of the file directly below the main comment block to identify the author, date and time of the last <kbd>commit</kbd>.</p>\r
+\r
+               <p>After the file has been added and committed to the repository the keyword will be expanded into <kbd>// $Id: guidelines.html 3071 2005-01-12 21:53:13Z joel $</kbd>. It is helpful to read that line when first opening a file as it lets you know if you were the last person to edit that file and if not, to look out for possible changes.</p>\r
+\r
+               <p>To set <kbd>svn:keyword="Id"</kbd> on a file using TortoiseSVN, right-click on a file, select "Properties" then select the "TortoiseSVN" tab, enter <kbd>svn:keywords</kbd> in the drop-down and <kbd>Id</kbd> in the text box then use the "Set" button.</p>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="communication"></a>5. Communication</h2>\r
+       <p>All communication between developers should occur in the <a href="http://atutor.ca/forum/12/1.html">Development Forum</a>. Please try to keep discussions public including any feature proposals.</p>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="patches"></a>6. Patches</h2>\r
+       <p>As of ATutor 1.6 the Patcher module is available for applying and developing patches to repair bugs, and to add or modify features. Details on creating and applying patches can be found in the ATutor Handbook for version 1.6.1+, or on the ATutor Wiki.</p>\r
+       <p><a href="http://wiki.atutor.ca/display/atutorwiki/Patcher+Module+Documentation">Patcher Documentation</a></p>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="editor-tips"></a>7. Editor Tips</h2>\r
+       <p>We use <a href="http://editplus.com">EditPlus</a>, but you can use whichever editor and settings you feel comfortable with. The most important part when editing is to ensure that tabs meet the coding guidelines on <a href="#indentation">indentation</a>. Unix KDE users might use Kate as their text editor.</p>\r
+\r
+       <p>A few desirable features for a good text editor are listed below:\r
+       <ul>\r
+               <li>Column and row numbering.</li>\r
+               <li>Jump to line number.</li>\r
+               <li>Word wrap toggle.</li>\r
+               <li>Being able to specify soft or hard tabs.</li>\r
+               <li>Syntax highlighting.</li>\r
+               <li>Trim trailing whitespace.</li>\r
+               <li>DOS to UNIX CR/LF conversions. Your editor must be able to save files with UNIX style line breaks. This means the <kbd>\n</kbd> character instead of the </kbd>\r</kbd> (Mac style) or <kbd>\r\n</kbd> (Windows style).</li>\r
+       </ul></p>\r
+\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="proposed-features"></a>8. Proposed Features</h2>\r
+       <p>The <a href="http://atutor.ca/atutor/features.php" title="ATutor.ca - Proposed Features">Proposed Features</a> page lists features which have been requested by the ATutor community. ATutor.ca members can vote on features to establish a priority, while potential developers may then assign themselves to tasks. New feature requests should be posted to the <a href="http://atutor.ca/forum/2/1.html" title="ATutor.ca - Feature Requests Forum">ATutor Feature Requests</a> forum.</p>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="bug-tracking"></a>9. Bug Tracking</h2>\r
+       <p>Please report bugs to the <a href="http://atutor.ca/forum/3/1.html" title="ATutor.ca - Bug Forum">ATutor Bug Reports</a> forum, or directly to the <a href="http://www.atutor.ca/atutor/mantis">Mantis Bug Tracker</a>. Be sure to indicate the code version being used, such as a release candidate, stable release, nightly build, or SVN checkout, etc. Also be sure to describe the details of the system that ATutor is being developed or tested on, such as the operating system, web server and version, PHP version, etc. Browse the <a href="http://www.atutor.ca/development/bugs/">Current Bug Summary</a> for a list of active bug fixing.</p>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="creating-bundles"></a>10. Creating Bundles</h2>\r
+       <p>The file <kbd>`bundle.sh`</kbd> is located in a directory above <kbd>`docs`</kbd> and is used for creating bundles from the working <kbd>`docs`</kbd> directory. The Shell script must be run on UNIX and will retrieve the latest version of the language from the database, disables debugging, creates an empty config.inc.php filr, and lastly create a <kbd>.tar.gz</kbd> file. Note, by default this script will generate a bundle from the atutorsvn source code repository. You may change this path near the top of the file to point to a local version of the ATutor source code, if for instance you have your own customizations you'd like to build into an installable bundle. Usage:\r
+               \r
+               <dl>\r
+                       <dt><kbd>./bundle.sh [version_number]</kbd><dt>\r
+                       <dd><p>Note that you will need execute permissions on the script to use it, and if it isn't in your <kbd>PATH</kbd> then you will have to prefix it with a <kbd>./</kbd>. The optional <kbd>version_number</kbd> argument will be used for suffixing onto the file name.  For example, a version number of <kbd>1.8RC1</kbd> will generate a file named <kbd>ATutor-1.8RC1.tar.gz</kbd>.</p></dd>\r
+               </dl>\r
+       </p>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="writing-portable-code"></a>11. Writing Portable Code</h2>\r
+       <p>When writing your PHP code please try to use functions that exist since (the minimum requirement) PHP version 4.3.0. If you have to use a function that only exists in later versions of PHP, provide an alternative for older versions. To check if the function is available use either <kbd>version_compare(phpversion(), $min_version)</kbd> or <kbd>function_exists($function_name)</kbd>.\r
+\r
+       <p>Code has to work on both Windows and UNIX. You should never use <kbd>exec()</kbd> or <kbd>system()</kbd>. In most cases we prefer to write code that works on both systems as is, without the need for if-statements that check for the operating system, since duplicating the functionality twice (once for each operating system) can be a source of bugs. Review the <a href="#php-configuration">PHP Configuration</a> section for details on how best to set-up your development environment.</p>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="coding-style"></a>12. Coding Style</h2>\r
+       <p>This section should help those who would like to modify or add code. Anyone who wishes to contribute code must adhere to these guidelines or the code may not be accepted. Please try to write code that is easy to read and maintain with appropriate comments as needed. Correctness and efficiency are easier to certify if code is simple to read and understand.</p>\r
+\r
+       <h3><a name="indentation"></a>12.1 Indentation</h3>\r
+               <p>The importance of indentation for code organization cannot be overstated. Although indentation is not mandatory in PHP, it is a powerful visual organization tool that should consistently be applied to code.</p>\r
+               <ul>\r
+                       <li>Indent using 4 spaces for each level.</li>\r
+                       <li>Think carefully about when too many nested levels has been reached. (Usually 4-5 is a good limit).</li>\r
+                       <li>Use <em>Hard tabs</em>, as described below.</li>\r
+               </ul>\r
+\r
+               <p>Internally, we have used hard tabs as we all use the same editor, but we may decide to move to soft tabs in the future. Hard tabs are regular tabs while soft tabs are not really tabs at all; each soft tab is actually represented by a certain number of regular spaces. The benefit of using soft tabs is that they always appear the same, regardless of the editor's tab-spacing. With soft tabs set and enforced, it is easy to maintain consistent indentation and whitespace treatment throughout code. When hard tabs are used, especially if there are multiple developers using different editors, it is easy for mixed levels of indentation to be introduced, confusing the code's layout.</p>\r
+\r
+       <h3><a name="line-length"></a>12.2 Line Length</h3>\r
+               <p>Split the long lines into multiple lines: \r
+<pre class="code">\r
+if (($month = 'jan') || ($month = 'feb') || ($month = 'mar') || ($month = 'apr')) {\r
+    return 1;\r
+}\r
+</pre></p>\r
+\r
+    <p>You can indent the second line to signify the association with the upper. For particularly long lines, you can indent and align every condition:\r
+<pre class="code">\r
+if (($month = 'jan') || \r
+    ($month = 'feb') || \r
+    ($month = 'mar') || \r
+    ($month = 'apr')) {\r
+\r
+    return 1;\r
+}\r
+</pre></p>\r
+\r
+        <p>This methodology works equally well for function parameters:\r
+<pre class="code">\r
+echo format_content($content_row['text'], \r
+                    $content_row['formatting'], \r
+                    $glossary,\r
+                    $indent);\r
+</pre></p>\r
+\r
+       <h3><a name="whitespace"></a>12.3 Using Whitespace</h3>\r
+               <p>Whitespace can be used to provide and reinforce logical structure in the code. For example, it can be effectively used to group assignments and show associations. The following example is poorly formatted and difficult to read:\r
+\r
+<pre class="code">\r
+$password = 'mypassword';\r
+$website_url = 'http://atutor.ca';\r
+$first_name = 'Joel';\r
+$last_name = 'Kronenberg';\r
+</pre></p>\r
+\r
+        <p>But this code block can be improved by using whitespace to logically group related assignments together and align them on the equal sign (<kbd>=</kbd>):\r
+<pre class="code">\r
+$pet_type    = 'mypassword';\r
+$website_url = 'http://atutor.ca';\r
+$first_name  = 'Joel';\r
+$last_name   = 'Kronenberg';\r
+</pre></p>\r
+\r
+       <h3><a name="sql-guidelines"></a>12.4 SQL Guidelines</h3>\r
+               <p>Similar formatting and layout rules applied to PHP can be applied to SQL queries as well. SQL queries, especially in database systems that support complex subqueries, can become convoluted. As with PHP code, whitespace and line breaks should be used in SQL code as needed. Consider the following:\r
+        \r
+<pre class="code">\r
+select employees.first_name, employees.last_name from \r
+               employees where employees.vacation_time > 0 order by employees.last_name";\r
+</pre>        \r
+        </p>\r
+\r
+               <p>This is a simple query, but it is poorly organized. Its organization can be improved in a number of ways, including the following:\r
+        <ul>\r
+            <li>Capitalize SQL keywords.</li>\r
+            <li>Break lines on SQL keywords.</li>\r
+            <li>Use table aliases to keep code clean.</li>\r
+        </ul>\r
+        \r
+<pre class="code">\r
+SELECT   S.first_name, S.last_name \r
+FROM     students S\r
+WHERE    S.email = '' \r
+ORDER BY S.last_name";\r
+</pre></p>\r
+\r
+               <h3><a name="sql-joins"></a>12.5 SQL/99 Joins</h3>\r
+          <p>ANSI SQL/99 features ANSI compliant joins. There are several advantages in using this new syntax, one of which is the separation of the <kbd>JOIN</kbd> condition from the <kbd>WHERE</kbd> clause.\r
+<pre class="code">\r
+SELECT M.email, M.login \r
+FROM   members M, forums_subscriptions S \r
+WHERE  S.member_id=M.member_id \r
+AND     M.email <> ''\r
+</pre>\r
+SQL/99 makes a clear distinction between the fields in the <kbd>JOIN</kbd> condition and the <kbd>WHERE</kbd> clause:\r
+<pre class="code">\r
+SELECT M.email, M.login\r
+FROM   members M\r
+JOIN   forums_subscriptions S USING (member_id)\r
+WHERE  M.email <> ''\r
+</pre></p>\r
+\r
+       <h3><a name="control-flow-constructs"></a>12.6 Control Flow Constructs</h3>\r
+               <p>\r
+                       <ul>\r
+                               <li><em>Always</em> use <kbd>&lt;?php ?></kbd> instead of the short form <kbd>&lt;? ?></kbd>. This implies that you must not use the <kbd>&lt;?=$var;?></kbd> short form either.</li>\r
+                               <li>Always include the optional semicolon in single line PHP blocks: <kbd>&lt;?php echo $something<big>;</big> ?></kbd>\r
+                               <li>Use <kbd>'</kbd> instead of <kbd>"</kbd> if there are no variables or special characters.</li>\r
+                               <li>Use spaces around string concatenating. <kbd>echo 'str' . $value . 'str2';</kbd></li>\r
+                               <li>Parenthesis <kbd>`( )`</kbd> should come right after a function name. <kbd>function()</kbd> not <kbd>function ()</kbd></li>\r
+                               <li>Parenthesis <kbd>`( )`</kbd> should have a space right after a language construct (<kbd>if</kbd>, <kbd>while</kbd>, <kbd>for</kbd>). Examples: <kbd>for (...)</kbd>, <kbd>while (condition)</kbd></li>\r
+                               <li>Avoid using <kbd>continue</kbd> and <kbd>break</kbd> as it makes debugging more difficult.</li>\r
+                   <li>Braces formatting is illustrating below. We use K&R style where the initial brace is placed on the same line as the keyword and the trailing brace inline on its own line with the keyword:\r
+<pre class="code">\r
+if (condition) {\r
+    ...\r
+} else if (condition) {\r
+    ...\r
+} else {\r
+    ...\r
+}\r
+</pre></li>\r
+                               <li>Arrays should be referenced with no spaces. <kbd>$arr['index']</kbd> not <kbd>$arr[ 'index' ]</kbd></li>\r
+                               <li>Avoid using short if-statement construct (<kbd>$var = ($query ? $val1 : $val2)</kbd>) except in very rare cases. It is confusing and has a lot of bug potential.</li>\r
+                       </ul>\r
+               </p>\r
+\r
+       <h3><a name="commenting"></a>12.7 Commenting</h3>\r
+               <p>Avoid using Shell/Perl-style (<kbd>## this is a comment</kbd>) comments entirely. Use C-style comments (<kbd>/* ... */</kbd>) for large comment blocks and C++-style comments (<kbd>// ...</kbd>) for single-line comments only:\r
+<pre class="code">\r
+/* This is a comment block\r
+ * it is used for describing\r
+ * the code below.\r
+ */\r
+...\r
+// this is a single line comment\r
+</pre></p>\r
+       <p>Please, document while your code. See <a href="http://phpdocu.sourceforge.net/howto.php">phpdoc</a>, like <a href="http://java.sun.com/docs/books/jls/first_edition/html/18.doc.html">javadoc</a>, for details how to document functions, classes, methods, and variables. Coding is often hurried, but it will save a lot of time in the end to do this type of documenting! It looks like this:\r
+   <pre class="code">\r
+   /**\r
+   * what the function does in one line.\r
+   * more detailed description on 0-n lines, if needed.\r
+   * @access  [public|static|pseudostatic]\r
+   * @param   [string|int|double|bool|array|object|mixed] $paramName1 desc\r
+   * @param   [string|int|double|bool|array|object|mixed] $paramName2 desc\r
+   *  ...\r
+   * @param   [string|int|double|bool|array|object|mixed] $paramNameN desc\r
+   * @return  datatype  description\r
+   * @throws  <em>not until PHP 5</em>\r
+   * @see     some_function()\r
+   * @todo    description\r
+   * @since   ATutor version, PHP version   (comma separated list)\r
+   * @status  stable|experimental           (if not set then considered stable)\r
+   * @pattern singleton|factory|mvc|observer|facade|...\r
+   * @author  description                   (comma separated list)\r
+   */\r
+   function something() {\r
+   }\r
+   </pre>\r
+   Note that the description should be given as plain text not HTML.  The <kbd>@pattern singleton</kbd> means that the constructor returns a reference to an already existing instance, if there is one.</p>\r
+\r
+       <h3><a name="naming-conventions"></a>12.8 Naming Conventions</h3>\r
+       <ul>\r
+               <li><a name="naming-variables"></a>12.8.1 Naming Variables:\r
+                       <ul>\r
+                               <li>Use capital letters for constants. E.g. <kbd>define('CONSTANT', 1)</kbd> and use the capital form of  <kbd>TRUE</kbd>, <kbd>FALSE</kbd> and <kbd>NULL</kbd></li>\r
+                               <li>Otherwise, use all lower case</li>\r
+                               <li>Use <kbd>_</kbd> to separate words. E.g. <kbd>$green_colour_value</kbd></li>\r
+                               <li>Loop variables can be of the usual variety: <kbd>$i</kbd>, <kbd>$j</kbd>, <kbd>$k</kbd>, etc.</li>\r
+                               <li>Count variables should follow the format $*_count. E.g. <kbd>$bug_count</kbd>, and always initialised to 0</li>\r
+                               <li>Temporary variables should be prefixed with <kbd>temp_</kbd></li>\r
+                               <li><kbd>$sql</kbd>, <kbd>$result</kbd>, and <kbd>$row</kbd> should be used for SQL query, results, and rows respectively</li>\r
+                       </ul>\r
+               </li>\r
+\r
+               <li><a name="naming-functions"></a>12.8.2 Naming Functions:\r
+                       <ul>\r
+                               <li>Use all lower case</li>\r
+                               <li>Use <kbd>_</kbd> to separate words. E.g. <kbd>setup_page_breaks()</kbd></li>\r
+                               <li>Keep functions to 5 words or less</li>\r
+                               <li>Functions that print should be prefixed with <kbd>print_</kbd>.</li>\r
+                               <li>Try to use prefixes to group functions (E.g., <kbd>email_</kbd>, <kbd>news_</kbd>, etc.)</li>\r
+                       </ul>\r
+               </li>\r
+\r
+               <li><a name="naming-files"></a>12.8.3 Naming Files:\r
+                       <ul>\r
+                               <li>Use all lower case</li>\r
+                               <li>Use <kbd>_</kbd> to separate words. E.g. <kbd>view_new_bugs_page.php</kbd></li>\r
+                               <li>Use <kbd>.php</kbd> file extensions (not <kbd>.html</kbd> or <kbd>.php3</kbd>)</li>\r
+                               <li>Filenames must be less than 32 characters in length as this works with older file systems like MacOS</li>\r
+                               <li>Included files should be suffixed by <kbd>.inc.php</kbd></li>\r
+                               <li>Files containing classes should be suffixed by <kbd>.class.php</kbd></li>\r
+                               <li>Exception: Files being included as part of an external library should not be renamed</li>\r
+                       </ul>\r
+               </li>\r
+       </ul>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="directory-structure"></a>13. Directory Structure</h2>\r
+       <p>The following is a short explanation of the important components of the ATutor directory structure.</p>\r
+\r
+       <h3><a name="directories"></a>13.1 Directories</h3>\r
+       <dl>\r
+               <dt><kbd>`admin/`</kbd></dt>\r
+                       <dd>This directory contains files used for the administration area (when a user logs in as an administrator). This includes files for system statistics, instructor requests, management of users, courses, categories and languages, and server configuration.</dd>\r
+\r
+               <dt><kbd>`editor/`</kbd></dt>\r
+                       <dd>This directory contains files used by a course instructor (or privileged user) to edit course content such as the glossary, course content, forums, announcements, and polls.</dd>\r
+\r
+               <dt><a name="directories-include"></a><kbd>`include/`</kbd></dt>\r
+                       <dd>This directory contains files that are required or included into other files.</dd>\r
+\r
+               <dt><kbd>`include/classes/`</kbd></dt>\r
+                       <dd>This directory contains classes, essential to certain ATutor functions, such as the phpMailer, XML, Savant templating, and content management classes.</dd>\r
+\r
+               <dt><kbd>`include/html/`</kbd></dt>\r
+                       <dd>This directory contains files that output HTML, usually displayed on (included into) multiple pages.</dd>\r
+\r
+               <dt><kbd>`include/lib/`</kbd></dt>\r
+                       <dd>This directory contains library files that hold functions and constants used throughout ATutor code.</dd>\r
+\r
+               <dt><kbd>`install/include/`</kbd></dt>\r
+                       <dd>This directory contains files used during the installation process, including each step of the fresh install and upgrade processes.</dd>\r
+\r
+               <dt><kbd>`install/db/`</kbd></dt>\r
+                       <dd>This directory contains the SQL files necessary to set up or upgrade the ATutor database.</dd>\r
+\r
+               <dt><kbd>`jscripts/`</kbd></dt>\r
+                       <dd>This directory contains all JavaScript files.</dd>\r
+\r
+               <dt><kbd>`themes/`</kbd></dt>\r
+                       <dd>This directory contains the different themes installed on an ATutor system, each with its own subdirectory.</dd>\r
+               \r
+               <dt><kbd>`mods/`</kbd></dt>\r
+                       <dd>This directory contains the module installed in an ATutor system.</dd>\r
+\r
+       </dl>\r
+\r
+       <h3><a name="files"></a>13.2 Files</h3>\r
+       <p>The following is a description of some of the important files.</p>\r
+       <dl>\r
+               <dt><kbd>`include/config.inc.php`</kbd></dt>\r
+                       <dd>This file is created during installation and contains specific configuration information for an ATutor system.</dd>\r
+\r
+               <dt><a name="files-vitals"></a><kbd>`include/vitals.inc.php`</kbd></dt>\r
+                       <dd>This file is included by every directly accessible page.  It connects to the database, initiates the user session, includes common libraries and constants, and defines frequently used functions.</dd>\r
+\r
+               <dt><a name="them-readme"></a><kbd>`themes/themes_readme.txt`</kbd></dt>\r
+                       <dd>This file contains detailed information on how to create and install a theme.</dd>\r
+\r
+               <dt><a name="files-header"></a><kbd>`include/header.inc.php`</kbd></dt>\r
+                       <dd>This file outputs the page's header using the correct template and theme.</dd>\r
+\r
+               <dt><a name="files-footer"></a><kbd>`include/html/footer.inc.php`</kbd></dt>\r
+                       <dd>This file outputs the page's footer using the correct template and theme.</dd>\r
+\r
+               <dt><a name="files-output"></a><kbd>`include/lib/output.inc.php`</kbd></dt>\r
+                       <dd>Most output formatting is done in this file, including things such as language, dates, a paginator, and content formatting, among other things .</dd>\r
+       </dl>\r
+\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="database-structure"></a>14. Database Structure</h2>\r
+       <p>A <a href="database.gif">database model diagram</a> (153 KB GIF) created from the ATutor 1.4.1 database schema is available. (somewhat outdated)</p>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="localisation"></a>15. Localisation</h2>\r
+       <p>All language terms and phrases are stored in the ATutor database. See the <a href="#fn-at"><kbd>_AT()</kbd></a> function for details on displaying text. There are three tables that are used for managing languages, their roles are as follows:\r
+               <dl>\r
+                       <dt><kbd>`language_pages`</kbd></dt>\r
+                       <dd>This table is used to cross reference language terms with pages. It allows selecting, via a <kbd>JOIN</kbd>, only the terms needed for a particular page. The <kbd>JOIN</kbd> may be slow at first but once the result is cached, subsequent calls are many times faster such that only the language needed for a particular page is restored from cache.</dd>\r
+\r
+                       <dt><kbd>`language_text`</kbd></dt>\r
+                       <dd>This table holds all of the text for an ATutor installation.</dd>\r
+\r
+                       <dt><kbd>`languages`</kbd></dt>\r
+                       <dd>This table holds the list of all available languages on the system and their attributes.</dd>\r
+\r
+               </dl></p>\r
+\r
+       <h3><a name="adding-language"></a>15.1 Adding &amp; Editing Language</h3>\r
+               <p>Please see the <a href="http://www.atutor.ca/atutor/docs/translate.php">Translator Documentation</a> for more details on translating a language within ATutor.</p>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="error-feedback-messages"></a>16. Error and Feedback Messages</h2>\r
+       <p>All messages are handled using the <kbd>Message</kbd> class. The main purpose of the <kbd>Message</kbd> class is to encapsulate the functionality of tracking \r
+               and managing various message types during a session by providing a nice layer of abstraction between you and the interface to <kbd>$_SESSION</kbd>, where the messages are stored.</p>\r
+\r
+       <p>At the moment six types of messages are supported:\r
+       <dl>\r
+               <dt><kbd>Error</kbd></dt>\r
+               <dd>Messages reflecting negative feedback to the user, indicating issues that need resolving or addressing.</dd>\r
+\r
+               <dt><kbd>Feedback</kbd></dt>\r
+               <dd>Messages reflecting positive feedback, aknowledging a users action was successfull.</dd>\r
+\r
+               <dt><kbd>Warning</kbd></dt>\r
+               <dd>Messages warning the user of a possible action with undesireable effects.</dd>\r
+\r
+               <dt><kbd>Help</kbd></dt>\r
+               <dd>Messages with helpful information about the current page.</dd>\r
+\r
+               <dt><kbd>Info</kbd></dt>\r
+               <dd>Messages with useful information.</dd>\r
+\r
+               <dt><kbd>Confirmation</kbd></dt>\r
+               <dd>Messages requiring a confirmation in order to execute an action.</dd>\r
+\r
+       </dl></p>\r
+\r
+               \r
+       <p>Please note that using the old method of passing messages is not supported anymore.</p>\r
+\r
+       <p>Messages can be passed between pages and can be accessed at any time, without any time restriction other than a session timeout.</p>\r
+\r
+       <h3><a name="error-feedback-internals"></a>16.1 Internals</h3>\r
+               <p>Essentially the internals of the class are divided into two segments, a section responsible for printing graphics via Savant templates and another that manages the storage of Messages.</p>\r
+       \r
+               <p>Tracking messages is accomplished by storing message codes and their optional arguments associatively in <kbd>$_SESSION</kbd>. Printing messages is accomplished via Savant and built in templates which can be found in <kbd>`templates/`</kbd>.</p>\r
+       \r
+               <p>The relational tracking structure is organized in the following manner inside <kbd>$_SESSION</kbd> in no particular order.\r
+                       <ul>\r
+                               <li><kbd>message</kbd>\r
+                                       <ul>\r
+                                               <li><kbd>error</kbd>\r
+                                                       <ul>\r
+                                                               <li><kbd>AT_ERROR_{*}</kbd>\r
+                                                                       <ul>\r
+                                                                               <li><kbd>AT_ERROR_{*}</kbd></li>\r
+                                                                               <li><kbd>[argument_1]</kbd></li>\r
+                                                                               <li><kbd>[argument_2]</kbd></li>\r
+                                                                       </ul>\r
+                                                               </li>\r
+                                                       </ul>\r
+                                               </li>\r
+               \r
+                                               <li><kbd>warning</kbd>\r
+                                                       <ul>\r
+                                                               <li><kbd>AT_WARNING_{*}</kbd>\r
+                                                                       <ul>\r
+                                                                               <li><kbd>AT_WARNING_{*}</kbd></li>\r
+                                                                               <li><kbd>[argument_1]</kbd></li>\r
+                                                                       </ul>\r
+                                                               </li>\r
+                                                       </ul>\r
+                                               </li>\r
+                       \r
+                                               <li><kbd>info</kbd>\r
+                                                       <ul>\r
+                                                               <li><kbd>AT_INFOS_{*}</kbd>\r
+                                                                       <ul>\r
+                                                                               <li><kbd>AT_INFOS_{*}</kbd></li>\r
+                                                                               <li><kbd>[argument_1]</kbd></li>\r
+                                                                       </ul>\r
+                                                               </li>\r
+                                                       </ul>\r
+                                               </li>\r
+\r
+                                               <li><kbd>help</kbd>\r
+                                                       <ul>\r
+                                                               <li><kbd>AT_HELP_{*}</kbd>\r
+                                                                       <ul>\r
+                                                                               <li><kbd>AT_HELP_{*}</kbd></li>\r
+                                                                               <li><kbd>[argument_1</kbd></li>\r
+                                                                       </ul>\r
+                                                               </li>\r
+                                                       </ul>\r
+                                               </li>\r
+\r
+                                               <li><kbd>feedback</kbd>\r
+                                                       <ul>\r
+                                                               <li><kbd>AT_FEEDBACK_{*}</kbd>\r
+                                                                       <ul>\r
+                                                                               <li><kbd>AT_FEEDBACK_{*}</kbd></li>\r
+                                                                               <li><kbd>[argument_1]</kbd></li>\r
+                                                                       </ul>\r
+                                                               </li>\r
+                                                       </ul>\r
+                                               </li>\r
+\r
+                                               <li><kbd>confirm</kbd>\r
+                                                       <ul>\r
+                                                               <li><kbd>AT_CONFIRM_{*}</kbd>\r
+                                                                       <ul>\r
+                                                                               <li><kbd>AT_CONFIRM_{*}</kbd></li>\r
+                                                                               <li><kbd>[argument_1]</kbd></li>\r
+                                                                       </ul>\r
+                                                               </li>\r
+                                                       </ul>\r
+                                               </li>\r
+                                       </ul>\r
+                               </li>\r
+                       </ul>\r
+               </p>\r
+       \r
+       <p>Messages are automaticaaly purged from <kbd>$_SESSION</kbd> following an appropriate print command.</p>\r
+\r
+       <h3><a name="error-feedback-usage"></a>16.2 Adding Messages</h3>\r
+               <kbd>$msg->add{Error|Warning|Info|Feedback|Help}($code);</kbd><br /><br />\r
+\r
+               <p><kbd>$code</kbd> is a <kbs>String</kbd> of a language _msgs code or an array with element 0 being the language _msgs code followed by optional arguments. Refer to the language_text table in the database.</p>\r
+\r
+               <p><strong>Important:</strong> One important thing to note is that <kbd>$code</kbd> must be stripped of the prefix for that type of message. By prefix it is meant <kbd>AT_[code_type]_</kbd>. For example:\r
+\r
+                       <ul>\r
+                               <li><kbd>`AT_ERROR_FORUM_NOT_FOUND`</kbd> should be specified as <kbd>`FORUM_NOT_FOUND`</kbd>, by stripping off the <kbd>`AT_ERROR_`</kbd> prefix.</li>\r
+                               <li><kbd>`AT_WARNING_DELETE_MESSAGE`</kbd> as <kbd>`DELETE_MESSAGE`</kbd> by stripping off <kbd>`AT_WARNING_`</kbd>.</li>\r
+                               <li><kbd>`AT_FEEDBACK_LOGOUT`</kbd> as <kbd>`LOGOUT`</kbd> by stripping off <kbd>`AT_FEEDBACK_`</kbd>.</li>\r
+                               <li><kbd>`AT_INFOS_MSG_SEND_LOGIN`</kbd> as <kbd>`MSG_SEND_LOGIN`</kbd> by stripping off <kbd>`AT_INFOS_`</kbd>.</li>\r
+                               <li><kbd>`AT_HELP_FILE_EXPORTABLE`</kbd> as <kbd>`FILE_EXPORTABLE`</kbd> by stripping off <kbd>`AT_HELP_`</kbd>.</li>\r
+                       </ul>\r
+               </p>\r
+\r
+               <p>There are two ways of adding messages: a single code or a code with an array fo arguments. You can mix-and-match, a combination of both is supported even for the same code. Below is description of the formats:</p>\r
+\r
+               <p>\r
+                       <dt>Adding single code</dt>\r
+                       <dt><kbd>$msg->addHelp('FILE_EXPORTABLE');</kbd></dt>\r
+               <br/>\r
+               <dt><b>OR</b></dt>\r
+               <br/>\r
+               <dt>Adding array with arguments</dt>\r
+               <dt><kbd>$f = array('FILE_EXPORTABLE', 'arg', 'arg2', ...);</kbd></dt>\r
+               <dt><kbd>$msg->addHelp($f);</kbd></dt>\r
+               </p>\r
+\r
+               <p>A nice feature implemented is that you do not have to provide all\r
+               the arguments for a particular code at one time. Subsequent adding of\r
+               the same code will just append the argument. This allows for greater\r
+               manipulative flexibility in your source, without writing redundant code. Also note\r
+               that encoding Feedback codes is no longer necessary for redirection.<p>\r
+\r
+               <p><b>Example 1:</b>\r
+               <dt><kbd>$feedback=array('FORUM_ADDED', 'ac_access_groups');</kbd></dt>\r
+               <dt><kbd>$msg->addFeedback($feedback);</kbd></dt><br/>\r
+\r
+               <dt><kbd>// Before we print lets addr another one to the same code</kbd></dt>\r
+               <dt><kbd>$feedback2=array('FORUM_ADDED', 'about_atutor_help_text');</kbd></dt>\r
+               <dt><kbd>$msg->addFeedback($feedback2);</kbd></dt><br/>\r
+\r
+               <dt><kbd>// No need to url_encode the code</kbd></dt>\r
+               <dt><kbd>$filename = 'archive.zip';</kbd></dt>\r
+               <dt><kbd>$f = array('FILE_UPLOADED_ZIP', $file_name);</kbd></dt>\r
+               <dt><kbd>$msg->addFeedback($f);</kbd></dt>\r
+\r
+               </p>\r
+\r
+<p>Snapshot of a portion of <kbd>$_SESSION</kbd> as a result:</p>\r
+<pre class="code">\r
+       [feedback] => Array\r
+                (\r
+                    [AT_FEEDBACK_FORUM_ADDED] => Array\r
+                        (\r
+                            [0] => AT_FEEDBACK_FORUM_ADDED\r
+                            [1] => ac_access_groups\r
+                            [2] => about_atutor_help_text\r
+                        )\r
+                        \r
+                    [AT_FEEDBACK_FILE_UPLOADED_ZIP] => Array\r
+                        (\r
+                            [0] => AT_FEEDBACK_FILE_UPLOADED_ZIP\r
+                            [1] => archive.zip\r
+                        )\r
+\r
+\r
+                )\r
+       ...\r
+</pre>\r
+\r
+<p>\r
+<dt><kbd>header('Location: file_manager.php');</kbd></dt>\r
+<dt><kbd>exit;</kbd></dt>\r
+</p>\r
+\r
+<h3><a name="error-feedback-printing"></a>16.3 Printing Messages</h3>\r
+<kbd>$msg->print{Errors|Warnings|Infos|Feedbacks|Helps|All}($optional);</kbd><br/><br/>\r
+\r
+<p>Each will dump all the corresponding tracked messages of that type onto\r
+the page at that given line with appropriate graphics defined by its templates file.<p>\r
+\r
+<p><kbd>printAll()</kbd> allows all Messages of all types to be dumped immediately.</p>\r
+\r
+<p>One thing to remember is that once a type of Message is printed\r
+all tracked data relating to that type are gone. There is no need to worry\r
+about purging messages from <kbd>$_SESSION</kbd>. The class manages this.</p>\r
+\r
+<p><b>Notice</b> <kbd>$optional</kbd> as the argument to this function. This allows you\r
+to shortcut the process of adding and printing Message's in one go. For example,\r
+suppose you want to add a Message and print it right away. Thus, you pass as an\r
+argument ANY argument that you would pass when adding a Message of that type. \r
+Essentially, two lines of code are accomplished in one.</p>\r
+<dt>Example:</dt>\r
+<pre class="code">\r
+       $msg->addError('MAX_ATTEMPTS');\r
+       $msg->printErrors();\r
+       \r
+       can also be accomplished as:\r
+       \r
+       $msg->printErrors('MAX_ATTEMPTS');\r
+</pre>\r
+\r
+<h4><a name="Boolean"></a>Printing String inside Feedback style box</h4>\r
+\r
+<kbd>printNoLookup($str);</kbd><br/><br/>\r
+\r
+<p>Print <kbd>$str</kbd> inside a Feedback Message type style box. Performs\r
+no dialog with <kbd>$_SESSION</kbd> or any language mappings in the language_text DB table.\r
+Strictly used in <kbd>/resources/links/index.php</kbd> for compatibility.\r
+</p>\r
+\r
+<h4><a name="Boolean"></a>Checking for existance of specific Message type</h4>\r
+\r
+<kbd>contains{Errors|Warnings|Feedbacks|Helps|Infos}();</kbd><br/><br/>\r
+\r
+<p>Returns true if the type of Message is being tracked and contains\r
+some kind of data. Useful for branching conditions in knowning\r
+when to print a Message or not. Otherwise returns false.</p>\r
+\r
+<h4><a name="Boolean"></a>Manually Deleting a specific Message from storage</h4>\r
+\r
+<kbd>delete{Error|Warning|Feedback|Help|Info}($codcuee);</kbd><br/><br/>\r
+\r
+<p>Will delete anything related to <kbd>$code</kbd> from <kbd>$_SESSION</kbd></p>\r
+<dt>Example:</dt>\r
+<pre class="code">\r
+       $msg->deleteFeedback('CANCELLED');\r
+</pre>\r
+\r
+<h4><a name="Example"></a>Example Code</h4>\r
+       \r
+<pre class="code">\r
+\r
+...\r
+\r
+require_once(AT_INCLUDE_PATH . '/classes/Message/Message.class.php');\r
+\r
+global $savant;\r
+\r
+$msg =& new Message($savant); \r
+\r
+$msg->addError('FORUM_NOT_FOUND');\r
+$msg->addWarning('SAVE_YOUR_WORK');\r
+$msg->addInfo('NO_SEARCH_RESULTS');\r
+$msg->addFeedback('FORUM_ADDED');\r
+\r
+/* State of relevant section of $_SESSION at this point \r
+[message] => Array\r
+        (\r
+            [error] => Array\r
+                (\r
+                    [AT_ERROR_FORUM_NOT_FOUND] => AT_ERROR_FORUM_NOT_FOUND\r
+                )\r
+\r
+            [warning] => Array\r
+                (\r
+                    [AT_WARNING_SAVE_YOUR_WORK] => AT_WARNING_SAVE_YOUR_WORK\r
+                )\r
+\r
+            [info] => Array\r
+                (\r
+                    [AT_INFOS_NO_SEARCH_RESULTS] => AT_INFOS_NO_SEARCH_RESULTS\r
+                )\r
+\r
+            [feedback] => Array\r
+                (\r
+                    [AT_FEEDBACK_FORUM_ADDED] => AT_FEEDBACK_FORUM_ADDED\r
+                )\r
+\r
+        )\r
+*/\r
+\r
+// Now print them\r
+$msg->printErrors();\r
+$msg->printWarnings();\r
+$msg->printInfos();\r
+$msg->printFeedbacks();\r
+\r
+/* State of relevant section of $_SESSION at this point\r
+ [message] => Array\r
+        (\r
+        )\r
+ */\r
+\r
+// Let's add an array of arguments\r
+$feedback=array('FORUM_ADDED', 'ac_access_groups');\r
+$msg->addFeedback($feedback);\r
+\r
+// Before we print lets another another one to the same code\r
+$feedback2=array('FORUM_ADDED', 'about_atutor_help_text');\r
+$msg->addFeedback($feedback2);\r
+\r
+$msg->addHelp('DEMO_HELP2');\r
+\r
+$help=array('DEMO_HELP2', $_my_uri);\r
+$msg->addHelp($help);\r
+\r
+$help2=array('ADD_TEST', $_my_uri);\r
+$msg->addHelp($help2);\r
+\r
+// No need to url_encode the code\r
+$filename = 'archive.zip';\r
+$f = array('FILE_UPLOADED_ZIP', $file_name);\r
+$msg->addFeedback($f);\r
+\r
+/* State of relevant section of $_SESSION at this point. Notice the second addFeddback call above\r
+ * had its arguments appended\r
+\r
+ [message] => Array\r
+        (\r
+            [feedback] => Array\r
+                (\r
+                    [AT_FEEDBACK_FORUM_ADDED] => Array\r
+                        (\r
+                            [0] => AT_FEEDBACK_FORUM_ADDED\r
+                            [1] => ac_access_groups\r
+                            [2] => about_atutor_help_text\r
+                        )\r
+                        \r
+                    [AT_FEEDBACK_FILE_UPLOADED_ZIP] => Array\r
+                        (\r
+                            [0] => AT_FEEDBACK_FILE_UPLOADED_ZIP\r
+                            [1] => archive.zip\r
+                        )\r
+\r
+                )\r
+\r
+            [help] => Array\r
+                (\r
+                    [AT_HELP_DEMO_HELP2] => Array\r
+                        (\r
+                            [0] => AT_HELP_DEMO_HELP2\r
+                            [1] => /~Jay/docs/index.php?\r
+                        )\r
+\r
+                    [AT_HELP_ADD_TEST] => Array\r
+                        (\r
+                            [0] => AT_HELP_ADD_TEST\r
+                            [1] => /~Jay/docs/index.php?\r
+                        )\r
+\r
+                )\r
+\r
+        }\r
+*/\r
+\r
+$msg->printAll();\r
+\r
+/* State of relevant section of $_SESSION at this point\r
+ [message] => Array\r
+        (\r
+        )\r
+ */\r
\r
+ ...\r
+</pre>\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="mbstring-support"></a>16.4 UTF-8 and Multibyte language</h2>\r
+       <p>As of ATutor 1.6, string parsing is done with multibtyle string functions, either the <kbd>mbstring</kbd> function in PHP itself, or the multibyte string functions in the UTF-8 library included with ATutor. By default ATutor will attempt to use the PHP <kbd>mbstring</kbd> functions, and will fall back on the ATutor library if this fails. In order to support both methods of string processing, a set of custom string parsing functions have been created. The only time the ATutor functions will be used is when the mbstring check during the installation or upgrade process has been disabled. The functions mirror the standard string parsing function in PHP, but with the <kbd>$</kbd> prepended. So, where ever you would normally use a PHP function like <kbd>substr() </kbd>, instead use <kbd>$substr()</kbd>. These functions are located in the vital.inc.php\r
+<pre class="code">\r
+ if (extension_loaded('mbstring')){\r
+        $strtolower = 'mb_strtolower';\r
+        $strtoupper = 'mb_strtoupper';\r
+        $substr = 'mb_substr';\r
+        $strpos = 'mb_strpos';\r
+        $strrpos = 'mb_strrpos';\r
+        $strlen = 'mb_strlen';\r
+ } else {\r
+        $strtolower = 'utf8_stringtolower';\r
+        $strtoupper = 'utf8_stringtoupper';\r
+        $substr = 'utf8_substr';\r
+        $strpos = 'utf8_strpos';\r
+        $strrpos = 'utf8_strrpos';\r
+        $strlen = 'utf8_strlen';\r
+ }\r
+\r
+</pre>\r
+\r
+\r
+       <h3>String functions </h3>\r
+               <p><ul>\r
+                       <li><kbd>string <strong>$strtolower</strong>(string $str)</kbd> -- UTF-8 aware strtolower function.  Make a string lowercase </li>\r
+                       <li><kbd>string <strong>$strtoupper</strong>(string $str)</kbd> -- UTF-8 aware strtolower function.  Make a string uppercase </li>\r
+                       <li><kbd>int <strong>$strpos</strong>(string $haystack  , string $needle  )</kbd> -- UTF-8 aware strpos function.  Find position of first occurrence of string in a string </li>\r
+                       <li><kbd>int <strong>$strrpos</strong>(string $haystack , string $needle  )</kbd> -- UTF-8 aware strrpos function.  Find position of last occurrence of a string in a string </li>\r
+                       <li><kbd>int <strong>$strlen</strong>(string $str)</kbd> -- UTF-8 aware strlen function.  Get string length </li>\r
+               </ul></p>\r
+\r
+               <h4>Description</h4>\r
+                       <p>Starting from 1.6, the above string functions will replace the original string functions when dealing with strings in order to adapt the utf-8 environment.</p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/vitals.inc.php`</kbd></p>\r
+               \r
+               <h4>Example 1</h4>\r
+               <p>To alter a text to lowercase:\r
+               <pre class="code">\r
+               $str = 'Αρχαίο Πνεύμα';\r
+               echo $strtolower($str);\r
+               </pre></p>\r
+\r
+               <h4>Example 2</h4>\r
+               <p>To alter a text to uppercase:\r
+               <pre class="code">\r
+               $str = 'Αρχαίο Πνεύμα';\r
+               echo $strtoupper($str);\r
+               </pre></p>\r
+\r
+               <h4>Example 3</h4>\r
+               <p>To find the middle character of a string:\r
+               <pre class="code">\r
+               $str = 'Αρχαίο Πνεύμα';\r
+               $mid = $strlen;\r
+               echo $strpos($mid, $str);\r
+               </pre></p>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="useful-variables"></a>17. Useful Variables</h2>\r
+       <p>Most of the variables documented here are required for most pages to function correctly. <kbd>constant</kbd> variables, although not explicitly declared as constants, should be considered as such, and not altered.</p>\r
+\r
+       <h3><a name="var-db"></a>17.1 $db</h3>\r
+               <h4>Description</h4>\r
+                       <p><kbd>constant resource $db</kbd></p>\r
+\r
+                       <p><kbd>$db</kbd> is the main database handler. Use it to connect to the ATutor database.</p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/vitals.inc.php`</kbd></p>\r
+\r
+       <h3><a name="var-addslashes"></a>17.2 $addslashes</h3>\r
+               <p>See <a href="#fn-addslashes"><kbd>$addslashes()</kbd></a>.</p>\r
+\r
+       <h3><a name="var-base_href"></a>17.3 $_base_href</h3>\r
+               <h4>Description</h4>\r
+               <p><kbd>constant string $_base_href</kbd></p>\r
+               <p>The full URL to ATutor's base installation. Supports both regular and SSL protocols. Example: <kbd>http://myserver.org/files/ATutor/</kbd>.</p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/lib/constants.inc.php`</kbd></p>\r
+\r
+       <h3><a name="var-base_path"></a>17.4 $_base_path</h3>\r
+               <h4>Description</h4>\r
+               <p><kbd>constant string $_base_path</kbd></p>\r
+               <p>The full absolute path to ATutor's base installation. Example: <kbd>/files/ATutor/</kbd>.</p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/lib/constants.inc.php`</kbd></p>\r
+\r
+       <h3><a name="var-user_location"></a>17.5 $_user_location</h3>\r
+               <h4>Description</h4>\r
+               <p><kbd>constant $_user_location</kbd></p>\r
+               <p><kbd>$_user_location</kbd> can be one of five values: <kbd>`public`</kbd>, <kbd>`admin`</kbd>, <kbd>`users`</kbd>, <kbd>`prog`</kbd> or <em>empty</em>. This variable must be set <em>before</em> requiring <kbd>`vitals.inc.php`</kbd>, and specifies what kind of general user authentication the page declaring it needs.</p>\r
+\r
+               <p><kbd>`public`</kbd> pages can be viewed by any user, signed-in as a member or not. <kbd>`admin`</kbd> pages (those in the <kbd>`admin/`</kbd> directory) can only be viewed by the administrator. <kbd>`users`</kbd> pages (those in the <kbd>`users/`</kbd> directory) can only be viewed by logged in members. If <kbd>$_user_location</kbd> is empty, it is assumed the page can only be accessed when a user is signed-in and viewing a course. <kbd>`prog`</kbd> is reserved for the pop-up window displaying the progress bar.</p>\r
+\r
+               <p>This variable was added as a way of specifying which template to use (public, admin, or member). Its role as a way of authenticating is not thoroughly established.</p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><em>Declared on every page that is directly accessible.</em></p>\r
+\r
+\r
+       <h3><a name="var-rel_url"></a>17.6 $_rel_url</h3>\r
+               <h4>Description</h4>\r
+               <p><kbd>constant string $_rel_url</kbd></p>\r
+               <p>The absolute path and file name relative to ATutor's base installation. If ATutor was installed in <kbd>http://myserver.org/files/ATutor/</kbd>, the <kbd>$_rel_url</kbd> of the Site-Map page, for example, would evaluate to <kbd>/tools/sitemap/index.php</kbd>.</p>\r
+\r
+               <p>This URL will always be the same for a given page, regardless of the location or path of an installation. This variable was added as a way of standardising the <kbd>`page`</kbd> value in the <kbd>`lang_base_pages`</kbd> table.</p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/lib/constants.inc.php`</kbd></p>\r
+\r
+       <h3><a name="var-my_uri"></a>17.7 $_my_uri</h3>\r
+               <h4>Description</h4>\r
+               <p><kbd>constant string $_my_uri</kbd></p>\r
+               <p>The full path and file name to the current page in a format that is ready to accept additional URL arguments. The argument separator will be defined as <kbd><a href="#const-sep">SEP</a></kbd>.  For example, if the current URL is <kbd>http://myserver.org/index.php?cid=806;disable=PREF_MENU;menu_jump=2</kbd>, then <kbd>$_my_uri</kbd> would be <kbd>/index.php?cid=806;</kbd>.</p>\r
+\r
+               <p>So, <kbd>$_my_uri</kbd> is the URL to the current page without the temporary switch arguments. The following URL arguments are removed:\r
+\r
+               <kbd>enable</kbd>, <kbd>disable</kbd>, <kbd>expand</kbd>, <kbd>menu_jump</kbd>, <kbd>g</kbd>, <kbd>collapse</kbd>, <kbd>f</kbd>, <kbd>e</kbd>, <kbd>save</kbd>, and <kbd>lang</kbd>.</p>\r
+               \r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/lib/vitals.inc.php`</kbd></p>\r
+\r
+       <h3><a name="var-content_manager"></a>17.8 $contentManager</h3>\r
+               <h4>Description</h4>\r
+               <p><kbd>constant ContentManager $contentManager</kbd></p>\r
+               <p>The <kbd>$contentManager</kbd> object provides access to methods for operating on content. All access to the <kbd>`content`</kbd> table should be done through this object.</p>\r
+\r
+               <h4>Locations</h4>\r
+                       <p><kbd>`include/vitals.inc.php`</kbd><br />\r
+                       <kbd>`include/classes/ContentManager.class.php`</kbd></p>\r
+\r
+       <h3><a name="var-section"></a>17.9 $_section</h3>\r
+               <p><strong>Deprecated in ATutor 1.5</strong></p>\r
+               <h4>Description</h4>\r
+               <p><kbd>array $_section</kbd></p>\r
+\r
+               <p>This variable is a two-dimensional <kbd>array</kbd> used to display a page's breadcrumbs. The first index identifies the page starting from <kbd>0</kbd> such that <kbd>$_section[0]</kbd> defines the first page in the hierarchy, <kbd>$_section[1]</kbd> the second, and so on. The second index is used to assign that page's properties, defined as follows: index <kbd>0</kbd> is the page title, and index <kbd>1</kbd> is the URL. This variable must be defined <em>before</em> the <kbd>`header.inc.php</kbd> file is required.</p>\r
+               \r
+               <p>The URL for the last page (i.e.. the current page) is optional.</p>\r
+\r
+               <h4>Example 1</h4>\r
+                       <p>To assign the path to the site-map:\r
+<pre class="code">\r
+// the Site-Map is a sub-page of the Tools page, hence we define the path:\r
+\r
+$_section[0][0] = _AT('tools');              // the Tools' page title\r
+$_section[0][1] = 'tools/';                  // the Tools' page URL\r
+$_section[1][0] = _AT('sitemap');            // the Site-Map's page title\r
+$_section[1][1] = 'tools/sitemap/index.php'; // the Site-Map's page URL\r
+</pre></p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><em>Declared on every page that is directly accessible.</em></p>\r
+\r
+               \r
+<a href="#top" class="top">top</a>\r
+<h2><a name="useful-functions"></a>18. Useful Functions</h2>\r
+       <p>The functions listed below provide vital functionality for ATutor pages. Developers will most likely end up using most, if not all, of the functions below. Please review the <a href="#function-definitions">Function Definitions (Prototypes)</a> section for an explanation of the syntax being used. Additional javadoc comments can be found with each function's definition.</p>\r
+\r
+       <h3><a name="fn-authenticate"></a>18.1 authenticate()</h3>\r
+               <p><kbd>authenticate()</kbd> -- Authenticates the current user against a specified privilege.</p>\r
+\r
+               <h4>Description</h4>\r
+                       <p><kbd>mixed <strong>authenticate</strong>( integer $privilege [, boolean $check]</em> )</kbd></p>\r
+\r
+                       <p>Authenticates the current user against <kbd>$privilege</kbd>. If <kbd>$check</kbd> is <kbd>AT_PRIV_RETURN</kbd> then the function will return the status of the authentication with <kbd>TRUE</kbd> meaning the user has been successfully authenticated or <kbd>FALSE</kbd> otherwise. With <kbd>$check</kbd> set to <kbd>FALSE</kbd> (default), the function will call <kbd>exit</kbd> to abort the script if the user cannot be authenticated and return <kbd>TRUE</kbd> otherwise.</p>\r
+\r
+                       <p>The instructor user will always return <kbd>TRUE</kbd>.</p>\r
+\r
+                       <p><kbd>$privilege</kbd> is set to one of the constants defined in <kbd>`include/lib/constants.inc.php`</kbd>.</p>\r
+\r
+                       <p>Please use only <kbd>AT_PRIV_RETURN</kbd> or <kbd>FALSE</kbd> as possible values for <kbd>$check</kbd> as additional options may be added and the value of the constant changed.</p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/vitals.inc.php`</kbd></p>\r
+\r
+               <h4>Example 1</h4>\r
+                       <p>To authenticate an entire page using the announcements management privilege:\r
+<pre class="code">\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require (AT_INCLUDE_PATH . 'vitals.inc.php');\r
+/**\r
+/* exit if the user cannot be authenticated\r
+ * otherwise continue loading the page.\r
+ */\r
+authenticate(AT_PRIV_ANNOUNCEMENTS);\r
+</pre></p>\r
+               <h4>Example 2</h4>\r
+                       <p>To authenticate a block of code using the forums management privilege:\r
+<pre class="code">\r
+if (authenticate(AT_PRIV_FORUMS, AT_PRIV_RETURN)) {\r
+    // ... this user has been authenticated\r
+}\r
+</pre></p>\r
+\r
+       <h3><a name="fn-at"></a>18.2 _AT()</h3>\r
+               <p><kbd>_AT()</kbd> -- Returns translated terms.</p>\r
+\r
+               <h4>Description</h4>\r
+                       <p><kbd>string <strong>_AT</strong>( string $term [, string $argument1 [, string $argument2 ...]] )</kbd></p>\r
+                       \r
+                       <p>This function returns a translated version of <kbd>$term</kbd> based on the user's current language preference as defined in <kbd>$_SESSION[lang]</kbd>. If <kbd>$term</kbd> cannot be found in the language database, it will return <kbd>`[ $term ]`</kbd> to signify that it was not found.</p>\r
+\r
+                       <p>Terms may require supplements in the form of additional arguments (see example 2). A term may require zero or more arguments. If a <kbd>term</kbd> requires arguments, then they must all be provided; no argument can be left out.</p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/lib/output.inc.php`</kbd></p>\r
+\r
+               <h4>Example 1</h4>\r
+                       <p>Printing a single term:\r
+<pre class="code">\r
+/* echo a translated version of the 'tools' string.\r
+ * i.e. 'Tools' in English, 'Outils' in French, etc..\r
+ */\r
+ $_SESSION['lang'] = 'en';\r
+echo '&lt;h2>' . _AT('tools') . '&lt;/h2>';\r
+\r
+ $_SESSION['lang'] = 'fr';\r
+echo '&lt;h2>' . _AT('tools') . '&lt;/h2>';\r
+</pre></p>\r
+\r
+                       <p>Result:\r
+<pre class="code">&lt;h2>Tools&lt;/h2>\r
+&lt;h2>Outils&lt;/h2>\r
+</pre></p>\r
+\r
+               <h4>Example 2</h4>\r
+                       <p>Printing a phrase with arguments:\r
+<pre class="code">\r
+$username = 'Jon';\r
+echo _AT('welcome_message', $username);\r
+</pre></p>\r
+                       <p>Result:\r
+<pre class="code">Hello, Jon. Welcome back.</pre></p>\r
+\r
+\r
+       <h3><a name="fn-at_print"></a>18.3 AT_print()</h3>\r
+               <p><kbd>AT_print()</kbd> -- Transforms and formats user data for printing.</p>\r
+\r
+               <h4>Description</h4>\r
+                       <p><kbd>string <strong>AT_print</strong>( string $input, string $field_name [, boolean $runtime_html] )</kbd></p>\r
+\r
+                       <p>This function returns a transformed version of <kbd>$input</kbd> based on the rules specified by <kbd>$field_name</kbd>. <kbd>$input</kbd> is assumed to originate from the database, but it may be generalised in the future.</p>\r
+\r
+                       <p><kbd>$field_name</kbd> is the unique name of the <kbd>$input</kbd> field in the form of <kbd><em>table_name</em>.<em>field_name</em></kbd>. The formatting options for the given field are defined in <kbd>`include/lib/constants.inc.php`</kbd>. If <kbd>$field_name</kbd> is not a valid option as defined in the constants file then the function will return <kbd>$input</kbd> unchanged.</p>\r
+\r
+                       <p>The boolean <kbd>$runtime_html</kbd> is used by fields which have an optional HTML formatting field. <kbd>$runtime_html</kbd> should be the associated HTML formatting field for that data. If set to <kbd>FALSE</kbd> then HTML elements will be escaped from <kbd>$input</kbd> and new line characters converted to <kbd>&lt;br /></kbd>s.</p>\r
+\r
+                       <p>No data from the database should be printed without passing it through this function first.</p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/lib/output.inc.php`</kbd></p>\r
+\r
+               <h4>Example 1</h4>\r
+               <p>Printing a field where HTML is not allowed:\r
+<pre class="code">\r
+$username = 'my_name&lt;b>_is';\r
+$value    = AT_print($username, 'members.login'); // escape the '&lt;b>' tag\r
+echo $value</pre></p>\r
+\r
+               <p>Result:\r
+<pre class="code">my_name&lt;b>_is</pre></p>\r
+\r
+\r
+       <h3><a name="fn-at_date"></a>18.4 AT_date()</h3>\r
+               <p><kbd>AT_date()</kbd> -- Returns a localised version of a date.</p>\r
+\r
+               <h4>Description</h4>\r
+                       <p><kbd>string <strong>AT_date</strong>( [string $format [, integer $timestamp [, integer $format_type]]] )</kbd></p>\r
+\r
+                       <p>This function returns the <kbd>string</kbd> representation of the given <kbd>$timestamp</kbd> as transformed by <kbd>$format</kbd>. Uses the same options as PHP's <kbd><a href="http://www.php.net/date" title="PHP.net - date()">date()</a></kbd> function, but requires a <kbd>%</kbd> in front of each argument. If <kbd>$timestamp</kbd> is not specified, then the current time will be used.</p>\r
+\r
+                       <p><kbd>$format_type</kbd> specifies the type of time stamp being provided. Available types are defined in <kbd>`include/lib/constants.inc.php`</kbd>. Possible options are:\r
+                               <dl>\r
+                                       <dt><kbd>AT_DATE_MYSQL_DATETIME</kbd></dt>\r
+                                       <dd>The default. Format <kbd>YYYY-MM-DD HH:MM:SS</kbd>.</dd>\r
+\r
+                                       <dt><kbd>AT_DATE_MYSQL_TIMESTAMP_14</kbd></dt>\r
+                                       <dd>Format <kbd>YYYYMMDDHHMMSS</kbd>.</dd>\r
+\r
+                                       <dt><kbd>AT_DATE_UNIX_TIMESTAMP</kbd></dt>\r
+                                       <dd>A regular UNIX time stamp; seconds since epoch.</dd>\r
+\r
+                                       <dt><kbd>AT_DATE_INDEX_VALUE</kbd></dt>\r
+                                       <dd>A special case specifying that only the single value of <kbd>$format</kbd> should be returned. The index into a specified date <kbd>array</kbd>. Only available for the following date options: <kbd>%D</kbd>, <kbd>%l</kbd>, <kbd>%F</kbd>, <kbd>%M</kbd>.</dd>\r
+                               </dl>\r
+                       </p>\r
+\r
+                       <p>The following arguments are language dependent:\r
+                               <dl>\r
+                                       <dt><kbd>%D</kbd></dt>\r
+                                       <dd>A three-letter textual representation of a day, Mon through Sun</dd>\r
+\r
+                                       <dt><kbd>%F</kbd></dt>\r
+                                       <dd>A full textual representation of a month, January through December</dd>\r
+\r
+                                       <dt><kbd>%l</kbd> (lowercase 'L')</kbd></dt>\r
+                                       <dd>A full textual representation of the day of the week, Monday through Sunday</dd>\r
+\r
+                                       <dt><kbd>%M</kbd></dt>\r
+                                       <dd>A three-letter textual representation of a month, Jan through Dec</dd>\r
+                               </dl></p>\r
+       \r
+                       <p>The following arguments are <em>not yet</em> supported to be language dependent, but may be in the future:\r
+                               <dl>\r
+                                       <dt><kbd>%S</kbd></dt>\r
+                                       <dd>English ordinal suffix for the day of the month, 2 characters st, nd, rd or th. Works well with <kbd>%j</kbd></dd>\r
+\r
+                                       <dt><kbd>%a</kbd></dt>\r
+                                       <dd>Lowercase Ante meridiem and Post meridiem am or pm</dd>\r
+\r
+                                       <dt><kbd>%A</kbd></dt>\r
+                                       <dd>Uppercase Ante meridiem and Post meridiem AM or PM</dd>\r
+                               </dl></p>\r
+\r
+                       <p>In most (soon to be all) cases, <kbd>$format</kbd> will be specified using a call to <kbd>_AT()</kbd> to retrieve the correct date format for that language. See Example 2 below.</p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/lib/output.inc.php`</kbd></p>\r
+\r
+               <h4>Example 1</h4>\r
+                       <p>Returning a specified date using a UNIX time stamp:\r
+<pre class="code">\r
+$time = mktime(0, 0, 0, 7, 14, 2004);\r
+echo AT_Date('%l %F %j, %Y', $time, AT_DATE_UNIX_TIMESTAMP);\r
+</pre></p>\r
+\r
+                       <p>Result:\r
+<pre class="code">Wednesday July 14, 2004</pre></p>\r
+\r
+               <h4>Example 2</h4>\r
+                       <p>Returning a specified date using a UNIX time stamp that is also language dependent:\r
+<pre class="code">\r
+$time = mktime(0, 0, 0, 7, 14, 2004);\r
+\r
+$_SESSION['lang'] = 'en';\r
+echo AT_Date(_AT('announcement_date_format'), $time, AT_DATE_UNIX_TIMESTAMP);\r
+\r
+echo '&lt;br />';\r
+$_SESSION['lang'] = 'fr';\r
+echo AT_Date(_AT('announcement_date_format'), $time, AT_DATE_UNIX_TIMESTAMP);\r
+</pre></p>\r
+\r
+                       <p>Result:\r
+<pre class="code">Wednesday July 14, 2004\r
+mercredi, 14 juillet 2004</pre></p>\r
+\r
+               <h4>Example 3</h4>\r
+               <p>Returning a single month name:\r
+<pre class="code">\r
+$_SESSION['lang'] = 'fr';\r
+The second month in French is: &lt;?php echo AT_date('%F', 2, AT_DATE_INDEX_VALUE) ?>\r
+</pre></p>\r
+\r
+               <p>Result:\r
+<pre class="code">\r
+The second month in French is: f憝rier\r
+</pre></p>\r
+\r
+       <h3><a name="fn-addslashes"></a>18.5 $addslashes()</h3>\r
+               <p><kbd>$addslashes()</kbd> -- Quotes a string with slashes.</p>\r
+\r
+               <h4>Description</h4>\r
+                       <p><kbd>string <strong>$addslashes</strong>( string $str )</kbd></p>\r
+\r
+                       <p>If <kbd>get_magic_quotes_gpc</kbd> is disabled, then this variable function maps onto <kbd><a href="http://www.php.net/addslashes" title="PHP.net - addslashes()">addslashes()</a></kbd>, otherwise it maps onto <kbd>my_add_null_slashes()</kbd> which simply returns the input <kbd>$str</kbd> unchanged.</p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/vitals.inc.php`</kbd></p>\r
+\r
+               <h4>Example 1</h4>\r
+                       <p>With <kbd>magic_quotes_gpc</kbd> enabled:\r
+<pre class="code">\r
+$str = "What's going on?";\r
+\r
+// prints magic_quotes_gpc: 1\r
+echo 'magic_quotes_gpc: ' . get_magic_quotes_gpc();\r
+\r
+// maps to my_add_null_slashes(). prints What\'s going on? [correct]\r
+echo $addslashes($str);\r
+\r
+// prints What\\\'s going on? [wrong]\r
+echo addslashes($str);\r
+</pre></p>\r
+\r
+               <h4>Example 2</h4>\r
+                       <p>With <kbd>magic_quotes_gpc</kbd> disabled:\r
+<pre class="code">\r
+$str = "What's going on?";\r
+\r
+// prints magic_quotes_gpc: 0\r
+echo 'magic_quotes_gpc: ' . get_magic_quotes_gpc();\r
+\r
+// maps to addslashes(). prints What\'s going on? [correct]\r
+echo $addslashes($str);\r
+\r
+// prints What\'s going on? [correct]\r
+echo addslashes($str);\r
+</pre></p>\r
+\r
+\r
+       <h3><a name="fn-debug"></a>18.6 debug()</h3>\r
+               <p><kbd>debug()</kbd> -- Outputs a variable.</p>\r
+\r
+               <h4>Description</h4>\r
+                       <p><kbd>void <strong>debug</strong>( mixed $var [, string $title] )</kbd></p>\r
+\r
+                       <p>This function is used for printing variables for debugging. <kbd>$var</kbd> can be of any type. The output is nicely formatted and easy to read. <kbd>debug()</kbd> will not output anything if the constant <kbd><a href="#const-devel">AT_DEVEL</a></kbd> evaluates to <kbd>FALSE</kbd>.</p>\r
+\r
+                       <p><kbd>$title</kbd> is available to label the debugging box for distinguishing it from other debugging boxes on the same page.</p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/vitals.inc.php`</kbd></p>\r
+\r
+               <h4>Example 1</h4>\r
+               <p>Viewing the contents of an <kbd>array</kbd>:\r
+<pre class="code">\r
+$my_array = array('apple' => 'green', 4 => 'something');\r
+debug($my_array, 'my_array');\r
+</pre></p>\r
+\r
+               <p>Result:\r
+<pre class="code">\r
+    <b>my_array</b>\r
+Array\r
+(\r
+    [apple] => green\r
+    [4] => something\r
+)\r
+</pre></p>\r
+\r
+       <h3><a name="fn-get_login"></a>18.7 get_login()</h3>\r
+               <p><kbd>get_login()</kbd> -- Returns the login name of a member.</p>\r
+\r
+               <h4>Description</h4>\r
+                       <p><kbd>string <strong>get_login</strong>( integer $id )</kbd></p>\r
+\r
+                       <p>Returns the login name of the member whose ID is <kbd>$id</kbd>. There is no error handling.</p>\r
+               \r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/vitals.inc.php`</kbd></p>\r
+\r
+\r
+       <h3><a name="fn-urlencode_feedback"></a>18.8 urlencode_feedback()</h3>\r
+               <p><kbd>urlencode_feedback()</kbd> -- Encodes a feedback code.</p>\r
+\r
+               <h4>Description</h4>\r
+                       <p><kbd>mixed <strong>urlencode_feedback</strong>( mixed $f )</kbd></p>\r
+\r
+                       <p>This function returns a URL safe encoding of a feedback code. Its purpose is to encode the feedback into the URL so that the page being redirected to will then output the feedback. <kbd>$f</kbd> may be an <kbd>array</kbd> of feedback codes, where additionally, each feedback code may be an array consisting of supplementary arguments. If <kbd>$f</kbd> is an <kbd>array</kbd> then the return value will be its <kbd>string</kbd> representation, otherwise the function will return <kbd>$f</kbd> unchanged.</p>\r
+\r
+                       <p>The way feedback is implemented may change in the future, so it is best to use this function even if the feedback code is not an <kbd>array</kbd>.</p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/vitals.inc.php`</kbd></p>\r
+               \r
+               <h4>Example 1</h4>\r
+               <p>To encode a feedback array:\r
+<pre class="code">\r
+$f[] = array(AT_FEEDBACK_FILE_UPLOADED_ZIP, $file_name);\r
+\r
+header('Location: file_manager.php?f='.urlencode_feedback($f));\r
+exit;\r
+</pre></p>\r
+\r
+       <h3><a name="fn-url_rewrite"></a>18.9 url_rewrite()</h3>\r
+               <p><kbd>url_rewrite()</kbd> -- Change an url to a pretty url.</p>\r
+\r
+               <h4>Description</h4>\r
+                       <p><kbd>string <strong>url_rewrite</strong>( string $url, boolean $is_rewriting_header, boolean $force)</kbd></p>\r
+\r
+                       <dt><kbd>$url</kbd></dt>\r
+                       <dd><p>the Url should be a relative link to the file.</p></dd>\r
+\r
+                       <dt><kbd>$is_rewriting_header</kbd></dt>\r
+                       <dd><p>Determine if url_rewrite is rewriting a header (location: ..) path or not.  Available values are AT_PRETTY_URL_IS_HEADER, AT_PRETTY_URL_NOT_HEADER(default).  Use AT_PRETTY_URL_IS_HEADER if url_rewrite is being called inside header(Location:...)</p></dd>\r
+\r
+                       <dt><kbd>$force</kbd></dt>\r
+                       <dd><p>Apply url_rewrite forcefully if it is true, default value is false.</p></dd>\r
+\r
+                       <p>This function returns a pretty URL from the given parameter. Its purpose is to change the URLs to a "prettier" format in order to extend user friendliness in the system, and to create indexes for Google search.  This function will authenticate itself towards the current pages.  In our definition, admins, login, registration pages should not have pretty url applied.  However, if one want to use url_rewrite on these pages, please set <kbd>$force</kbd> to TRUE, this will force it to change the urls to pretty urls.  Please note that the admin's system preference will still overwrite the force effect.  <kbd>$url</kbd> may be an <kbd>string</kbd> of URL, '?' and the seprators in the URL query will be replaced by slashes.  Please note that the PHP_SELF variable might break some of the form action/header redirect because the Pretty URI is a virtual path.  To address this problem, set $is_rewriting_header to AT_PRETTY_URL_IS_HEADER, as demonstrated in example 3.  </p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/vitals.inc.php`</kbd></p>\r
+               \r
+               <h4>Example 1</h4>\r
+               <p>To change an URL:\r
+<pre class="code">\r
+$url = 'forum/view.php?fid=3&pid=4';\r
+echo url_rewrite($url);                //output go.php/1/forum/view.php/fid/3/pid/4\r
+</pre></p>\r
+\r
+               <h4>Example 2</h4>\r
+               <p>To change an URL for mods:\r
+<pre class="code">\r
+$url = 'mods/hello_world/index.php';\r
+echo url_rewrite($url, true);          //output go.php/1/mods/hello_world/index.php\r
+</pre></p>\r
+\r
+               <h4>Example 3</h4>\r
+               <p>To change an URL for header redirection:\r
+<pre class="code">\r
+header('Location: '. url_rewrite('forum/index.php', AT_PRETTY_URL_IS_HEADER)); \r
+</pre></p>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="useful-constants"></a>19. Useful Constants</h2>\r
+       <p>These constants are part of the vital functionality of ATutor.</p>\r
+\r
+       <h3><a name="const-include_path"></a>19.1 AT_INCLUDE_PATH</h3>\r
+       <h4>Description</h4>\r
+               <p>The <kbd>AT_INCLUDE_PATH</kbd> must be defined <em>before</em> you <kbd>require</kbd> or <kbd>include</kbd> any files. The constant defines the relative path to the <kbd>`include/`</kbd> directory. For security reasons <em>no</em> file should ever be called-in without using this constant<em>!</em></p>\r
+\r
+               <h4>Example 1</h4>\r
+               <p>Requiring the vitals file from the tools page:\r
+                               <pre class="code">define('AT_INCLUDE_PATH', '../include/');\r
+require (AT_INCLUDE_PATH . 'vitals.inc.php');</pre></p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><em>Declared on every page that is directly accessible.</em></p>\r
+\r
+       <h3><a name="const-sep"></a>19.2 SEP</h3>\r
+       <h4>Description</h4>\r
+               <p>For XHTML compliance, we have created this constant to use when applying variables to URL arguments. The constant is one of the values defined by PHP's <kbd>arg_separator.input</kbd>, with a preference for the semi-colon (<kbd>`;`</kbd>), if available, over the ampersand (<kbd>`&amp;`</kbd>).</p>\r
+\r
+               <h4>Example 1</h4>\r
+               <p>Printing a dynamic link:\r
+<pre class="code">\r
+$arg1 = 'one';\r
+$arg2 = 'two';\r
+\r
+echo "SEP is ".SEP."\n";\r
+echo '&lt;a href="index.php?arg1=' . $arg1 . SEP . 'arg2=' . $arg2 . '">link&lt;/a>';</pre></p>\r
+               \r
+               <p>Result:\r
+<pre class="code">\r
+SEP is ;\r
+&lt;a href="index.php?arg1=one;arg2=two">link&lt;/a>\r
+</pre></p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/lib/constants.inc.php`</kbd></p>\r
+\r
+\r
+       <h3><a name="const-devel"></a>19.3 AT_DEVEL</h3>\r
+       <h4>Description</h4>\r
+               <p>Enables or disables usage of the <a href="#fn-debug">debug()</a> function.</p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/vitals.inc.php`</kbd></p>\r
+\r
+\r
+       <h3><a name="const-table_prefix"></a>19.4 TABLE_PREFIX</h3>\r
+       <h4>Description</h4>\r
+               <p>The <kbd>TABLE_PREFIX</kbd> constant holds the prefix to the ATutor database tables. It is needed when creating SQL queries.</p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/config.inc.php`</kbd></p>\r
+\r
+\r
+       <h3><a name="const-version"></a>19.5 VERSION</h3>\r
+               <h4>Description</h4>\r
+               <p>The version number of this ATutor installation.</p>\r
+\r
+               <h4>Location</h4>\r
+                       <p><kbd>`include/lib/constants.inc.php`</kbd></p>\r
+\r
+\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="install-upgrade-scripts"></a>20. Install &amp; Upgrade Scripts</h2>\r
+       <p>Installing or upgrading ATutor is done with the scripts found in the <kbd>`install/`</kbd> directory. Two files in particular control the installation or upgrading flow and are appropriately named <kbd>`install.php`</kbd> and <kbd>`upgrade.php`</kbd>. For actual documentation on installing or upgrading please see <a href="http://atutor.ca/atutor/docs/installation.php">ATutor's official documentation</a>.</p>\r
+\r
+       <p>The <kbd>`install/`</kbd> directory contains two other subdirectories that are used during the installation or upgrade process. The <kbd>`install/db/`</kbd> directory contains database schema files and are clearly labeled. The <kbd>`install/include/`</kbd> directory contains scripts that are common to both processes and labeled according to their order in either process.</p>\r
+\r
+       <h3><a name="install-script">20.1 Install Script</h3>\r
+               <p>The <kbd>`install.php`</kbd> script requires each step as it's needed as the <kbd>$step</kbd> counter variable is incremented. To add or edit a step, edit the <kbd>`install.php`</kbd> file.</p>\r
+\r
+       <h3><a name="upgrade-script">20.2 Upgrade Script</h3>\r
+               <p>The <kbd>`upgrade.php`</kbd> script works exactly the same as the install script does, but requires different files (step prefixed with a 'u'). To upgrade the database schema an SQL file named <kbd>`atutor_upgrade_<em>from</em>_to_<em>to</em>.sql`</kbd> must be created, where <kbd><em>from</em></kbd> is the exact version of the previous ATutor version, and <kbd><em>to</em></kbd> is the next stable version.</p>\r
+\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="accessibility"></a>21. Accessibility</h2>\r
+       <p>Part of ATutor's philosophy is to be "designed with accessibility and adaptability in mind", we advise you to consider carefully the practices outlined on the following sites:</p>\r
+       <ul>\r
+               <li><a href="http://www.w3.org/WAI/References/QuickTips/#QuickTips">WAI Quick Tips</a></li>\r
+               <li><a href="http://websavvy-access.org/standards/index.php">Web-Savvy & Standards Compliance</a></li>\r
+               <li><a href="http://atutor.ca/atutor/docs/atutor_access.php">ATutor's specific accessibility features</a></li>\r
+       </ul>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="validation"></a>22. Validation</h2>\r
+       <p>Please use the <a href="http://validator.w3.org/">W3C Markup Validation Service</a>, a free service, to check your pages for XHTML conformance, W3C Recommendations and other standards.</p>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="example"></a>23. Sample Script</h2>\r
+<p>The following is sample code that shows the general flow of an ATutor script. The example shows how you may use some of the variables and functions available to you. Some scripts may not need all the variables and functions used below.\r
+<pre class="code" id="code">&lt;?php\r
+// 0. insert the SVN keywords\r
+// <a href="#svn-keywords">$Id</a>: guidelines.html 1275 2004-07-28 16:02:49Z joel $\r
+\r
+// 1. define relative path to `include` directory:\r
+define('<a href="#const-include_path">AT_INCLUDE_PATH</a>', '../<a href="#directories-include">include/</a>');\r
+\r
+// 2. require the `vitals` file before any others:\r
+require (<a href="#const-include_path">AT_INCLUDE_PATH</a> . '<a href="#files-vitals">vitals.inc.php</a>');\r
+\r
+// 3. authenticate this user:\r
+<a href="#fn-authenticate">authenticate</a>(AT_PRIV_SPECIAL_PRIV);\r
+\r
+// 4. define the breadcrumbs path:\r
+<a href="#var-section">$_section[0][0]</a> =  <a href="#fn-at">_AT</a>('tools');\r
+<a href="#var-section">$_section[0][1]</a> = 'tools/';\r
+<a href="#var-section">$_section[1][0]</a> =  <a href="#fn-at">_AT</a>('my_page');\r
+<a href="#var-section">$_section[1][1]</a> =  'tools/page.php;\r
+\r
+// 5. handle any post request:\r
+if (isset($_POST['submit'])) {\r
+  // 5.1 check for errors:\r
+  if ($_POST['some_field'] == '') {\r
+      <a href="#error-feedback-messages">$msg->addError</a>('SOME_ERROR_CODE');\r
+  }\r
+\r
+  if (!<a href="#error-feedback-messages">$msg->containsErrors()</a>) {\r
+      //5.2 complete the desired action here. (example: insert into DB)\r
+\r
+      //5.3 set the feedback message and add it to the URL:\r
+      <a href="#error-feedback-messages">$msg->addFeedback</a>('MESSAGE');\r
+      $url = <a href="#var-base_href">$_base_href</a> . 'tools/index.php?arg1=yes';\r
+\r
+      //5.4 redirect after successful operation:\r
+      header('Location: ' . $url);\r
+      exit;\r
+  }\r
+}\r
+\r
+// 6. start the page display by calling the header\r
+require (<a href="#const-include_path">AT_INCLUDE_PATH</a> . '<a href="#files-header">header.inc.php</a>');\r
+\r
+// 7. display any feedback or error messages that my occur:\r
+require (<a href="#const-include_path">AT_INCLUDE_PATH</a> . 'html/<a href="#files-feedback">feedback.inc.php</a>');\r
+\r
+/*\r
+ * 8. display the page contents here.\r
+ */\r
+\r
+// 9. finish the page by calling the footer\r
+require (<a href="#const-include_path">AT_INCLUDE_PATH</a> . '<a href="#files-footer">footer.inc.php</a>');\r
+?></pre></p>\r
+\r
+<a href="#top" class="top">top</a>\r
+<h2><a name="credits-sources"></a>24. Credits &amp; Additional Sources</h2>\r
+       <ul>\r
+               <li><a href="http://atutor.ca">ATutor.ca</a></li>\r
+               <li><a href="http://atutor.ca/forum/12/1.html">ATutor Developer Support Forum</a></li>\r
+               <li>Documentation\r
+                       <ul>\r
+                               <li><a href="http://atutor.ca/atutor/docs/translate.php">ATutor Translator Documentation</a></li>\r
+                               <li><a href="http://php.net/manual/en">PHP Manual</a></li>\r
+                               <li><a href="http://svnbook.red-bean.com/svnbook/">Version Control with Subversion</a></li>\r
+                               <li><a href="http://mysql.com/doc">MySQL Documentation</a></li>\r
+                               <li><a href="http://www.zend.com/zend/week/index.php">PHP Weekly Summaries</a></li>\r
+                               <li><a href="http://alltasks.net/code/php_coding_standard.html">PHP Coding Standard</a> by Todd Hoff and Fredrik Kristiansen</li>\r
+                               <li><a href="http://www.blueshoes.org/en/developer/coding_guidelines/">Blueshoes.org - Coding Guidelines for BlueShoes Developers</a> by Andrej Arn</li>\r
+                               <li><a href="http://www.blueshoes.org/en/developer/syntax_exam/">Blueshoes.org - PHP Syntax Exam</a></li>\r
+                               <li><a href="http://www.blueshoes.org/en/developer/php_cheat_sheet/">Blueshoes.org - PHP Cheat Sheet</a></li>\r
+                               <li><a href="http://www.htmlhelp.com/reference/css/">HTMLhelp.com - Cascading Style Sheets</a> by John Pozadzides and Liam Quinn</li>\r
+                               <li><a href="http://httpd.apache.org/docs/">Apache HTTP Server Documentation</a></li>\r
+                               <li><a href="http://www.w3.org/TR/WAI-WEBCONTENT/checkpoint-list.html">W3C's Web Content Accessibility Guidelines</a></li>\r
+                       </ul>\r
+               </li>\r
+               <li>Tools\r
+                       <ul>\r
+                               <li><a href="http://www.phpmyadmin.net">phpMyAdmin</a></li>\r
+                               <li><a href="http://editplus.com">EditPlus</a></li>\r
+                               <li><a href="http://tortoisesvn.tigris.org/">TortoiseSVN</a></li>\r
+                       </ul>\r
+               </li>\r
+       </ul>\r
+\r
+</body>\r
+</html>\r
diff --git a/documentation/developer/modules.html b/documentation/developer/modules.html
new file mode 100644 (file)
index 0000000..2734a62
--- /dev/null
@@ -0,0 +1,791 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html lang="en">
+<head>
+       <title>ATutor Module Documentation</title>
+       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+       <meta name="author" content="Joel Kronenberg/Greg Gay" />
+       <meta name="description" content="ATutor module developer documentation" />
+<style type="text/css">
+
+h1 {
+       background-color: #CCCCCC;
+       padding-left: 20px;
+       padding-right: 20px;
+       margin-bottom: 10px;
+       text-align: right;
+}
+
+h2 {
+       background-color: #DDDDDD;
+       padding-left: 10px;
+       margin-bottom: 0px;
+}
+h3 {
+       background-color: #EFEFEF;
+       padding-left: 20px;
+       margin-bottom: 0px;
+}
+h4  { margin-bottom: 0px; }
+p   { margin-top: 0px;    }
+dl  { margin-top: 0px;    }
+kbd {
+       padding: 0px 1px 0px 1px;
+       border-width: 1px 2px 2px 1px;
+       border-style: solid;
+       border-color: #edd #baa #baa #eed;
+       white-space: pre;
+}
+kbd em {
+       font-weight: bold;
+       background-color: #efefef;
+}
+blockquote { font-style: italic; }
+pre.code {
+       background-color: #EEEEFF;
+       padding: 5px;
+       margin-left: 20px;
+       color:#761596;
+    margin-top: 0px;
+}
+.top {
+       float: right;
+       color: green;
+       padding-top: 2px;
+       padding-right: 5px;
+}
+pre {
+       background-color: #EEEEFF;
+       font-family: Courier, monospace;
+       border-left: 1px solid #761596;
+       padding: 0px 0px 0px 10px;
+       color: #333;
+        margin: 0px 0px 10px 20px;
+       font-size: 88%;
+       line-height: 1.2em;
+}
+@media print {
+       h2 {
+               page-break-after: avoid;
+               border-bottom: solid 1px black;
+       }
+       h3 {
+               page-break-after: avoid;
+               border-bottom: solid 1px black;
+               width: 75%;
+       }
+       .top {
+               display: none;
+       }
+
+       pre.code {
+               page-break-inside: avoid;
+       }
+}
+}
+acronym {
+       cursor: help;
+}
+</style>
+
+</style>
+</head>
+<body><h1>Module Development Documentation</h1>
+<ul>
+<li><a href="#intro">Introduction</a></li>
+<li><a href="#structure">Structure</a></li>
+       <ul>
+       <li><a href="#dirname">Directory Name</a></li>
+       <li><a href="#files">Files</a>
+       <ul>
+       <li><a href="#module.xml">module.xml</a></li>
+       <li><a href="#module.php">module.php</a></li>
+       <li><a href="#module.sql">module.sql</a></li>
+       </ul></li>
+       </ul>
+<li><a href="#installation">Installation</a></li>
+       <ul>
+       <li><a href="#module_install">module_install.php</a></li>
+       <li><a href="#privs">Specifying Privileges</a></li>
+       <li><a href="#data_dir">Creating a Data Directory</a></li>
+       <li><a href="#execute">Executing an SQL FILE</a></li>
+       <li><a href="#errors">Generating Error Messages</a></li>
+
+       </ul>
+
+<li><a href="#auth">Authentication &amp; Privileges</a></li>
+<li><a href="#localisation">Localisation</a></li>
+<li><a href="#config">Configuration Options</a></li>
+<li><a href="#styles">Custom Style Sheets</a></li>
+<li><a href="#sidemenu">Side Menu Boxes</a></li>
+<li><a href="#tools">Student Tools</a></li>
+<li><a href="#groups">Group Tools</a></li>
+<li><a href="#navigation">Navigation &amp; Hierarchy</a></li>
+<li><a href="#delete">Course Deletion</a></li>
+<li><a href="#backup">Backing-Up and Restoring</a></li>
+<ul>
+<li><a href="#directories">Directories</a></li>
+<li><a href="#database">Database Tables</a></li>
+</ul>
+<li><a href="#cron">Running Cron/Scheduling</a></li>
+</ul>
+
+<a name="intro"></a>
+<h2>Introduction</h2>
+       <p>ATutor 1.5.2 introduced the concept of modules, providing developers with a framework to implement additional functionality in a coherent and loosely coupled way.</p>
+
+       <p>The framework defines methods for assigning privileges, backing-up and restoring content, deleting course specific content, and adding side menu blocks,  student tools, course management and administrative tools, as well as public tools and other types of added functionality . </p>
+
+       <p>The intent is to allow for the development and distribution of modules independent of the ongoing development and release of ATutor. The module structure does allow for the creation of modules that run software that is not distributed under the <acronym title="GNU Not Unix">GNU</acronym> General Public License, but distributed separately under their own, perhaps commercial licenses.</p>
+
+       <p>The <em>Hello World</em> example module is included with each ATutor distribution for developers who want to investigate how modules work. The module is found in the <kbd>mods/hello_world</kbd> directory. A copy of the Hello World module works well as a starting point for creating a new module, since it implements (in a simple way) just about all the features found in modules. Also see the files from <a href="http://www.atutor.ca/atutor/modules.php">other modules</a> that operate like you expect your module to operate.</p>
+
+<a name="structure"></a>
+<h2>Structure</h2>
+       <p>Modules are stored under ATutor's <kbd>mods</kbd> directory. <em>Core</em> modules are stored in the <kbd>mods/_core</kbd> subdirectory and are made available with every release of ATutor. These modules cannot be disabled by the administrator as they are vital to ATutor's functionality. <em>Standard</em> modules are stored in the <kbd>mods/_standard</kbd> subdirectory and are also made available with every release of ATutor. Standard modules can be disabled by the administrator. <em>Extra</em> modules are stored in the <kbd>mods</kbd> directory and are installed and distributed independently of ATutor. Although the process of developing modules is the same for each type of module, only <em>extra</em> modules can be distributed separately, while <em>core</em> and <em>standard</em> modules are added to the ATutor code repository (i.e. <acronym title="Subversion">SVN</acronym> trunk).</p>
+
+       <p>Whenever a module identifier is needed within code, it should appear in lowercase with spaces converted to underscores.</p>
+
+       <p>The module name, and hence the directory and function names (see below for additional details), must be unique across all possible modules. A module should not be made available if an existing module is already being distributed under that same name. It is up to the module developer to ensure that their module name is unique.</p>
+       <a name="dirname"></a>
+       <h3>Directory Name</h3>
+               <p>The name given to the directory must be chosen carefully. The name is used to namespace the module's function by prefixing required functions with that directory name. For example, a module named <em>Example Maker</em> should be placed in a directory named <kbd>example_maker</kbd> and the delete function would be named <kbd><em>example_maker</em>_delete()</kbd>.</p>
+       <a name="files"></a>
+       <h3>Files</h3>
+               <p>The following files should exist under the module's top level directory: <kbd>mods/<em>module_name</em></kbd>.</p>
+
+               <dl>
+                       <dt><kbd>module.php</kbd></dt>
+                       <dd>This is the main module file which gets included whenever a page is loaded. <em>Required</em>.</dd>
+
+                       <dt><kbd>module.xml</kbd></dt>
+                       <dd>This file is used only for identifying the module for distribution and is only used when viewing a module's details. <em>Required</em>.</dd>
+
+                       <dt><kbd>module_install.php</kbd></dt>
+                       <dd>This file is used when installing the module. <em>Required</em>.</dd>
+
+                       <dt><kbd>module_backup.php</kbd></dt>
+                       <dd>This file is used when backing-up and restoring course content. <em>Optional</em>.</dd>
+
+                       <dt><kbd>module_delete.php</kbd></dt>
+                       <dd>This file is used when deleting course specific content. <em>Optional</em>.</dd>
+
+
+                       <dt><kbd>module_cron.php</kbd></dt>
+                       <dd>This file is used to run module related commands at specified intervals. <em>Optional</em>.</dd>
+
+                       <dt><kbd>module.sql</kbd></dt>
+                       <dd>This file is used to add tables and/or modify data in the ATutor database. Also used to insert language into the <kbd>language_text</kbd> table. <em>Optional</em>.</dd>
+               </dl>
+<a name="module.xml"></a>
+       <h3>The <kbd>module.xml</kbd> File</h3>
+               <p>The <kbd>module.xml</kbd> file is used for displaying information about the module before it is installed and is useful when distributing the module.</p>
+<pre>
+&lt;?xml version="1.0" encoding="ISO-8859-1"?> 
+&lt;module version="0.1"> 
+    &lt;name lang="en">Example Maker&lt;/name> 
+    &lt;description lang="en">This is an example module that makes examples.&lt;/description> 
+    &lt;maintainers>
+        &lt;maintainer> 
+            &lt;name>ATutor Team&lt;/name> 
+            &lt;email>info@atutor.ca&lt;/email> 
+        &lt;/maintainer>
+        &lt;maintainer> 
+            &lt;name>John Doe&lt;/name> 
+            &lt;email>jd@example.com&lt;/email> 
+        &lt;/maintainer>
+    &lt;/maintainers> 
+    &lt;url>http://www.example.com&lt;/url> 
+    &lt;license>BSD&lt;/license> 
+    &lt;release> 
+        &lt;version>0.2&lt;/version> 
+        &lt;date>2005-08-22&lt;/date> 
+        &lt;state>stable&lt;/state> 
+        &lt;notes>Fixes several bugs in previous version.&lt;/notes> 
+    &lt;/release> 
+&lt;/module>
+</pre>
+
+<a name="module.php"></a>
+       <h3>The <kbd>module.php</kbd> File</h3>
+<p>The <kbd>module.php</kbd> file is typically used to set permissions, and to link module components into the ATutor navigation elements, as tool icons, navigation tabs, sub navigation menus, or side menu blocks, as administrator, course management, and student tools. It is also used to link tools to  My Start Page, or to various public pages that appear where a user is browsing the system without being logged in. The <kbd>module.php</kbd> file can also be used to run module specific functionality. It runs everytime a module screen is viewed, loading whatever settings it may contain, or running any scripts that may be required by the module.</p>
+<pre>
+&lt;?php
+/*******
+ * doesn't allow this file to be loaded with a browser.
+ */
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+/******
+ * this file must only be included within a Module obj
+ */
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }
+
+/*******
+ * assign the instructor and admin privileges to the constants.
+ */
+define('AT_PRIV_EXAMPLE_MAKER',       $this->getPrivilege());
+define('AT_ADMIN_PRIV_EXAMPLE_MAKER', $this->getAdminPrivilege());
+
+/*******
+ * create a side menu box/stack.
+ */
+$this->_stacks['example_maker'] = array('title_var'=>'example_maker', 'file'=>'mods/example_maker/side_menu.inc.php');
+// ** possible alternative: **
+// $this->addStack('example_maker', array('title_var' => 'example_maker', 'file' => './side_menu.inc.php');
+
+/*******
+ * if this module is to be made available to students on the Home or Main Navigation.
+ */
+$_student_tool = 'mods/example_maker/index.php';
+// ** possible alternative: **
+// $this->addTool('./index.php');
+
+/*******
+ * add the admin pages when needed.
+ */
+if (admin_authenticate(AT_ADMIN_PRIV_EXAMPLE_MAKER, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {
+       $this->_pages[AT_NAV_ADMIN] = array('mods/example_maker/index_admin.php');
+       $this->_pages['mods/example_maker/index_admin.php']['title_var'] = 'example_maker';
+       $this->_pages['mods/example_maker/index_admin.php']['parent']    = AT_NAV_ADMIN;
+}
+
+/*******
+ * instructor Manage section:
+ */
+$this->_pages['mods/example_maker/index_instructor.php']['title_var'] = 'example_maker';
+$this->_pages['mods/example_maker/index_instructor.php']['parent']   = 'tools/index.php';
+// ** possible alternative: **
+// $this->pages['./index_instructor.php']['title_var'] = 'example_maker';
+// $this->pages['./index_instructor.php']['parent']    = 'tools/index.php';
+
+/*******
+ * student page.
+ */
+$this->_pages['mods/example_maker/index.php']['title_var'] = 'example_maker';
+$this->_pages['mods/example_maker/index.php']['img']       = 'mods/example_maker/example_maker.jpg';
+
+
+/* public pages */
+$this->_pages[AT_NAV_PUBLIC] = array('mods/example_maker/index_public.php');
+$this->_pages['mods/example_maker/index_public.php']['title_var'] = 'example_maker';
+$this->_pages['mods/example_maker/index_public.php']['parent'] = 'login.php';
+$this->_pages['login.php']['children'] = array('mods/example_maker/index_public.php');
+
+/* my start page pages */
+$this->_pages[AT_NAV_START]  = array('mods/example_maker/index_mystart.php');
+$this->_pages['mods/example_maker/index_mystart.php']['title_var'] = 'example_maker';
+$this->_pages['mods/example_maker/index_mystart.php']['parent'] = 'users/index.php';
+$this->_pages['users/index.php']['children'] = array('mods/example_maker/index_mystart.php');
+?>
+</pre>
+<a name="module.sql"></a>
+       <h3>The <kbd>module.sql</kbd> File</h3>
+<p>A very simple <kbd>module.sql</kbd> file such as the following, creates a table for the module, and inserts it's language into the ATutor <kbd>language_text</kbd> table. Module language can then be managed from the ATutor Language Manager. The <kbd>module.sql</kbd> file can contain any number of SQL statements used to add tables or insert data into the ATutor database. </p>
+
+<pre>
+# sql file for example maker module
+
+CREATE TABLE example_maker (
+   `course_id` mediumint(8) unsigned NOT NULL,
+   `value` VARCHAR( 30 ) NOT NULL ,
+   PRIMARY KEY ( `course_id` )
+);
+
+INSERT INTO `language_text` VALUES ('en', '_module','example_maker','Example Maker',NOW(),'');
+INSERT INTO `language_text` VALUES ('en', '_module','AT_ERROR_GOES_HERE','Example Maker Error Message',NOW(),'');
+
+</pre>
+<a name="installation"></a>
+<h2>Installation</h2>
+       <p>The <kbd>module_install.php</kbd> script gets executed during the installation process, using the administrator's Install Module feature. If the script's execution results in <kbd>$msg->containsErrors()</kbd> evaluating to <kbd>TRUE</kbd>, then the errors are displayed and the user is prompted to correct them. The process is then repeated until errors are no longer being generated and the module is installed successfully. Ultimately, it is up to the module to determine the logical steps involved in its installation. For example, it might be better to create the data directories before trying to create any database tables since creating the directory may require several attempts. Typically the flow we describe here should be suitable in most cases.</p>
+
+       <p>Theoretically, the install script's execution is wide-open and does not have to adhere to the process outlined below or make use of any special privileges, provided it generates errors as appropriate.</p>
+
+<pre># pseudo-code for installing a module:
+while (there are errors)
+    print the error message
+
+    # inside module_install.php:
+    define the privileges used
+
+    if (create database tables is unsuccessful) then
+        generate an error message
+
+    if (there are no errors AND there is an SQL file) then
+        execute the SQL file
+end while
+
+add the module to the system using the defined privileges
+</pre>
+
+<a name="module_install"></a>
+       <h3>The <kbd>module_install.php</kbd> File</h3>
+<p>The <kbd>module_install.php</kbd> file is typically used to run any installation related files, such as an sql file that sets up a database table, or installs the language for the module. The following is an example module_install.php file</p>
+<pre>
+&lt;?php
+/*******
+ * the line below safe-guards this file from being accessed directly from
+ * a web browser. It will only execute if required from within an ATutor script,
+ * in our case the Module::install() method.
+ */
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+/*******
+ * Note: the many options for these variables are used to decrease confusion.
+ *       TRUE | FALSE | 1 will be the convention.
+ *
+ * $_course_privilege
+ *     specifies the type of instructor privilege this module uses.
+ *     set to empty | FALSE | 0   to disable any privileges.
+ *     set to 1 | AT_PRIV_ADMIN   to use the instructor only privilege.
+ *     set to TRUE | 'new'        to create a privilege specifically for this module:
+ *                                will make this module available as a student privilege.
+ *
+ * $_admin_privilege
+ *    specifies the type of ATutor administrator privilege this module uses.
+ *    set to FALSE | AT_ADMIN_PRIV_ADMIN   to use the super administrator only privilege.
+ *    set to TRUE | 'new'                  to create a privilege specifically for this module:
+ *                                         will make this module available as an administrator privilege.
+ *
+ *
+ * $_cron_interval
+ *    if non-zero specifies in minutes how often the module's cron job should be run.
+ *    set to 0 or not set to disable.
+ */
+$_course_privilege = TRUE; // possible values: FALSE | AT_PRIV_ADMIN | TRUE
+$_admin_privilege  = TRUE; // possible values: FALSE | TRUE
+$_cron_interval    = 35; // run every 30 minutes
+
+
+/********
+ * the following code is used for creating a module-specific directory.
+ * it generates appropriate error messages to aid in its creation.
+ */
+$directory = AT_CONTENT_DIR .'example_maker';
+
+// check if the directory is writeable
+if (!is_dir($directory) && !@mkdir($directory)) {
+       $msg->addError(array('MODULE_INSTALL', '&lt;li>'.$directory.' does not exist. Please create it.&lt;/li>'));
+} else if (!is_writable($directory) && @chmod($directory, 0666)) {
+       $msg->addError(array('MODULE_INSTALL', '&lt;li>'.$directory.' is not writeable. On Unix issue the command &lt;kbd>chmod a+rw&lt;/kbd>.&lt;/li>'));
+}
+
+
+/******
+ * the following code checks if there are any errors (generated previously)
+ * then uses the SqlUtility to run any database queries it needs, ie. to create
+ * its own tables.
+ */
+if (!$msg->containsErrors() && file_exists(dirname(__FILE__) . '/module.sql')) {
+       // deal with the SQL file:
+       require(AT_INCLUDE_PATH . 'classes/sqlutility.class.php');
+       $sqlUtility =& new SqlUtility();
+
+       /*
+        * the SQL file could be stored anywhere, and named anything, "module.sql" is simply
+        * a convention we're using.
+        */
+       $sqlUtility->queryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX);
+}
+
+?>
+</pre>
+
+
+<a name="privs"></a>
+       <h3>Specifying Privileges</h3>
+               <p>Privileges control who has access to the course management and administrative sections.</p>
+               
+               <p>See the Authentication &amp; Privileges section for additional details using the privileges.</p>
+
+               <dl>
+                       <dt><kbd>$_course_privilege</kbd></dt>
+                       <dd><p>This variable controls access to a course's management section and can take one of the following values:</p>
+                               <ul>
+                                       <li><kbd>TRUE</kbd>: To use a custom assignable privilege level. If a custom privilege is created, the module will appear as an option when assigning privileges to enrolled students.</li>
+                                       <li><kbd>AT_PRIV_ADMIN</kbd>: To use the instructor privilege. Only the instructor will be given access to the module's management section.</li>
+                                       <li><kbd>FALSE</kbd>: To disable the privilege if there is no management section for the module.</li>
+                               </ul>
+                       </dd>
+
+                       <dt><kbd>$_admin_privilege</kbd></dt>
+                       <dd><p>This variable can take one of the following values:</p>
+                               <ul>
+                                       <li><kbd>TRUE</kbd>: To use a custom assignable privilege level. If a custom privilege is created then the module will appear as an option when assigning privileges to administrators</li>
+                                       <li><kbd>AT_ADMIN_PRIV_ADMIN</kbd>: To use the super administrator privilege. Only the super administrator will be given access to the module's administration section.</li>
+                               </ul>
+                       </dd>
+               </dl>
+
+               <p>Note that creating a privilege is not in itself enough to make the module appear in the Manage section! The hierarchy and navigation path to the management page must be set correctly. See the Navigation &amp; Hierarchy section for additional details.</p>
+<a name="data_dir"></a>
+       <h3>Creating a Data Directory</h3>
+               <p>It is best to keep the directory within the <kbd>AT_CONTENT_DIR</kbd> directory as it should already allow the creation of files and directories by the web server. It is then up to the module to create individual course directories as needed.</p>
+<pre>
+$directory = AT_CONTENT_DIR .'example_maker';
+
+// check if the directory is writable
+if (!is_dir($directory) && !@mkdir($directory)) {
+    $msg->addError(array('MODULE_INSTALL', '&lt;li>'
+                         .$directory
+                         .' does not exist. Please create it.&lt;/li>'));
+} else if (!is_writable($directory) && @chmod($directory, 0666)) {
+    $msg->addError(array('MODULE_INSTALL', '&lt;li>'
+                         . $directory
+                         .' is not writable.&lt;/li>'));
+} // else: it was created successfully.
+</pre>
+<a name="execute"></a>
+       <h3>Executing an <acronym title="Structured Query Language">SQL</acronym> File</h3>
+               <p>If the module requires its own database tables or custom language, then it will have to create them itself. The <acronym title="Structured Query Language">SQL</acronym> can either be executed inline using <acronym title="PHP Hypertext Processor">PHP</acronym> database execution directly, or using the <kbd>SQLUtility</kbd> class to execute an external <acronym title="Structured Query Language">SQL</acronym> file. Also see <a href="#module.sql">module.sql</a> for more about creating an SQL file.</p>
+<pre>
+if (!$msg->containsErrors() && file_exists(dirname(__FILE__) . '/module.sql')) {
+    // deal with the SQL file:
+    require(AT_INCLUDE_PATH . 'classes/sqlutility.class.php');
+    $sqlUtility =& new SqlUtility();
+    $sqlUtility->queryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX);
+}
+</pre>
+<a name="errors"></a>
+       <h3>Generating Errors Messages</h3>
+               <p>It is up to the module to generate and check for any errors that occur during the installation. An error message can be generated using <kbd>$msg->addError(array('MODULE_INSTALL', '&lt;li>your error msg goes here&lt;/li>'));</kbd>. Note that the text supplied to the error message is not translated in this case. If the language should be localised, then the appropriate language vairable should replace the text. Something like <kbd>$msg->addError(array('MODULE_INSTALL', 'AT_ERROR_GOES_HERE'));</kbd> . The corresponding SQL INSERT statement should then be found in the <a href="#module.sql">module.sql </a>file, so the language gets added to the <kbd>language_text</kbd> table in ATutor. </p>
+
+               <p>To check if any errors have been generated, use <kbd>$msg->containsErrors()</kbd> which evaluates to <kbd>TRUE</kbd> if a previous error has been generated.</p>
+               
+               <p>See the <a href="guidelines.html#error-feedback-messages">Error and Feedback </a>section of the Developer Documentation for more details about displaying messages.</p>
+<a name="auth"></a>
+<h2>Authentication &amp; Privileges</h2>
+       <p>See the <em>Installation: Specifying Privileges</em> section on creating privileges during the installation process.</p>
+
+       <p>Authentication uses constants for the privilege levels. The privileges should be declared in the <kbd>module.php</kbd> file using the <kbd>$this->getPrivilege()</kbd> and <kbd>$this->getAdminPrivilege()</kbd> methods, respectively.</p>
+
+<pre>
+define('AT_PRIV_FORUMS',       $this->getPrivilege()      );
+define('AT_ADMIN_PRIV_FORUMS', $this->getAdminPrivilege() );
+</pre>
+
+       <p>Once declared, a page can then authenticate against those privileges using either the <kbd>authentication()</kbd> or the <kbd>admin_authenticate()</kbd> functions.</p>
+
+<pre>
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+// authenticate the administrator forums section:
+admin_authenticate(AT_ADMIN_PRIV_FORUMS);
+</pre>
+<a name="localisation"></a>
+<h2>Localisation</h2>
+       <p>Although a module can be created with all hard-coded language, we recommended you use ATutor's localisation functions. All of ATutor's language is stored in the database, which is then retrieved using the <kbd>_AT()</kbd> function for simple terms and the <kbd>$msg</kbd> object for feedback and error messages.</p>
+
+       <p>Additional details on localising ATutor can be found on the <a href="http://atutor.ca/atutor/docs/translate.php">Thing You Should Know Before Translating</a> and in the <a href="guidelines.html#fn-at">ATutor Developer Documentation</a>.</p>
+
+       <p>Module-specific language should be inserted into the <kbd>language_text</kbd> table during the installation process. The fields in the table are as follows:</p>
+                                         
+       <dl>
+               <dt><kbd>language_code</kbd></dt>
+               <dd>The ISO-639-1 language code plus locale.</dd>
+
+               <dt><kbd>variable</kbd></dt>
+               <dd>Set to <kbd>_module</kbd> for modules.</dd>
+
+               <dt><kbd>term</kbd></dt>
+               <dd>The variable used for retrieving the language.</dd>
+
+               <dt><kbd>text</kbd></dt>
+               <dd>The language text.</dd>
+
+               <dt><kbd>revised_date</kbd></dt>
+               <dd>Set to <kbd>NOW()</kbd> for modules.</dd>
+
+               <dt><kbd>context</kbd></dt>
+               <dd>Short description of the language text.</dd>
+       </dl>
+
+<p>Each language item should have a corresponding SQL INSERT line in the module.sql file, that gets inserted into the ATutor <kbd>language_text</kbd> table during installation. Do not include a prefix (e.g. "AT_") on the <kbd>language_text</kbd> table name. The installer will detect the right prefix, and automatically prepend it to tables names. Also see the section <a href="#module.sql">module.sql</a> for information about creating a file to install the module's language.</p>
+<pre>
+# Insert module specific language:
+INSERT INTO `language_text` VALUES ('en',
+                                    '_module',
+                                    'example_maker',
+                                    'Example Maker',
+                                     NOW(),
+                                    'the module title');
+</pre>
+<p>(Introduced in ATutor 1.5.4) On occassion it may be necessary to modify existing ATutor language to accommodate module functionality that alters the way ATutor itself functions by default. For example, when the payments module is installed the message displayed when a student enrolls in a course that requires a payment, needs to include mention of how to make a payment. In the SQL statement below, the second value (i.e. "variable" in the language_text table) is prefixed with "_c" for custom language. Possible custom language variables are _c_msgs, _c_template, and _c_module.</p>
+
+<pre>
+# Insert custom language:
+INSERT INTO `language_text` VALUES ('en', 
+                                       '_c_msgs',
+                                       'AT_INFOS_EC_PAYMENTS_TURNED_OFF','
+                                       Your request has been made. You will be notifed when your request has been approved. If course fees are pending, they will be listed under the <a href="mods/ecomm/index_mystart.php">Payments</a> tab above, where they can be paid.',
+                                       NOW(),'');
+</pre>
+
+<a name="config"></a>
+<h2>Configuration Options</h2>
+<p>Module configuration options can be stored in the ATutor <kbd>config</kbd> table, and retrieved using a <kbd>$_config[]</kbd> array variable. All module configuration key/value pairs are automatically loaded from the table into global memory while ATutor is running, and can be accessed from any of the module scripts (or from anywhere is ATutor for that matter). The value for a particular configuration option is retrieved by entering its key into the array. To retrieve a URL for the Example Maker module for example,  you might use <kbd>$_config['example_maker']</kbd>. </p>
+<p>In the following example of an <kbd>index_admin.php</kbd> file, the form below accepts a URL to an external application used by the Example Maker module (though it could be any value). In this case imagine a third party application has been installed, and the URL to the application is being stored as a configuration option for the example_maker module. When the form is submitted, <kbd>$_POST['uri']</kbd> is inserted into the config table as the value for the <kbd>example_maker</kbd> key. The following is an example module administrator script used to add/edit a config option for the example_maker module.</p>
+
+<h3>The <kbd>index_admin.php</kbd> File</h3>
+<pre>
+
+&lt;?php
+// make sure user is allowed to see this page (admins only)
+
+admin_authenticate(AT_ADMIN_PRIV_EXAMPLE_MAKER);
+       
+if (isset($_POST['submit'])) {
+       // trim whitespace from the value submitted
+       $_POST['uri'] = trim($_POST['uri']);
+
+       // display an error message if the value is empty
+       if (!$_POST['uri']){
+               $msg->addError('EXAMPLE_MAKER_ADD_EMPTY');
+       }
+       
+       // if no errors, insert the key "example_maker" and value "$_POST['uri']" into the config table 
+       if (!$msg->containsErrors()) {
+               $_POST['uri'] = $addslashes($_POST['uri']);
+               $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('example_maker', '$_POST[uri]')";
+               mysql_query($sql, $db);
+               $msg->addFeedback('EXAMPLE_MAKER_URL_SAVED');
+
+               header('Location: '.$_SERVER['PHP_SELF']);
+               exit;
+       }
+}
+
+require (AT_INCLUDE_PATH.'header.inc.php');
+
+/*******
+ *  First check to see if there is a value for the example_maker key $_config['example_maker']
+ *  If there isn't a value then a missing value message is displayed
+ *  The form below that has a single field for submitting a value, in this case a URL
+ *  If the value exists in the config table, then display it in the text field using  $_config['example_maker']
+ */
+       
+?>
+
+&lt;?php if ($_config['example_maker']): ?>
+       &lt;div class="input-form">
+               &lt;div class="row">
+                       &lt;p>&lt;?php echo _AT('example_maker_text'); ?>&lt;/p>
+               &lt;/div>
+       &lt;/div>
+&lt;?php else: ?>
+       &lt;div class="input-form">
+               &lt;div class="row">
+                       &lt;p>&lt;?php echo _AT('example_maker_missing_url');  ?>&lt;/p>
+               &lt;/div>
+       &lt;/div>
+&lt;?php endif; ?>
+
+&lt;form action="&lt;?php  $_SERVER['PHP_SELF']; ?>" method="post">
+       &lt;div class="input-form">
+               &lt;div class="row">
+                       &lt;p>&lt;label for="uri">&lt;?php echo _AT('example_maker_url'); ?>&lt;/label>&lt;/p>
+       
+                       &lt;input type="text" name="uri" value="&lt;?php echo $_config['example_maker']; ?>" id="uri" size="60" style="min-width: 65%;" />
+               &lt;/div>
+               &lt;div class="row buttons">
+                       &lt;input type="submit" name="submit" value="&lt;?php echo _AT('save'); ?>"  />
+               &lt;/div>
+       &lt;/div>
+&lt;/form>
+</pre>
+
+<a name="styles"></a>
+<h2>Custom Style Sheets</h2>
+       <p>A custom style sheet can be linked into pages by setting <kbd>$_custom_css</kbd> to be the absolute path to the style sheet. This variable must be set on every page that requires that style sheet.</p>
+
+<pre>
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+// using a custom style sheet:
+$_custom_css = $_base_path . 'mods/example_maker/module.css';
+</pre>
+
+<a name="sidemenu"></a>
+<h2>Side Menu Boxes</h2>
+       <p>Side menu boxes generally appear in a column at the side of a course (though this layout can be altered by a theme). A module may implement one or more side menu boxes.</p>
+
+       <p>Side menus are specified using the <kbd>$_module_stacks</kbd> array in <kbd>module.php</kbd>. <kbd>$_module_stacks</kbd> have the attributes <kbd>title_var</kbd> (or <kbd>title</kbd>) and <kbd>file</kbd>. The <kbd>title_var</kbd> value is the language key used for that box; the title will be generated by executing <kbd>_AT($title_var)</kbd>. If <kbd>title</kbd> is set instead, a hard-coded title will be used. The <kbd>file</kbd> attribute specifies the absolute path to the side menu's include file.</p>
+
+       <p>The key to the <kbd>$_module_stacks</kbd> should be the name of the module.</p>
+
+<pre>
+$_module_stacks['example_maker'] = array('title_var' => 'example_maker', 
+                                         'file' => dirname(__FILE__).'\side_menu.inc.php');
+</pre>
+
+       <p>Creating a side menu box involves using the <kbd>$savant</kbd> template object and assigning the output of the box to the <kbd>dropdown_contents</kbd> variable.</p>
+
+<pre>
+&lt;?php global $savant;
+
+$box_content = 'This is my side menu box';
+
+$savant->assign('dropdown_contents', $box_content);
+
+$savant->assign('title', _AT('example_maker'));
+$savant->display('include/box.tmpl.php');
+?>
+</pre>
+
+<a name="tools"></a>
+<h2>Student Tools</h2>
+       <p>Student tools are pages linked from the home page or the main navigation of courses. A module can only implement one student tool. An instructor controls which student tools are available to a course using the <em>Student Tools</em> section found under <em>Manage</em>.</p>
+
+       <p>The tool main page must be specified using the <kbd>$_student_tool</kbd> variable in the <kbd>module.php</kbd> file. The value of that variable must be the relative path to the file from the ATutor base directory (not the module directory). Example: <kbd>$_student_tool = 'mods/example_maker/index.php';</kbd>.</p>
+
+       <p>For the tool to correctly appear its Navigation &amp; Hierarchy must be defined correctly. If the tool is to have an instructor management section then the <em>parent</em> must be specified as being <kbd>tools/index.php</kbd> and the module must have a non-zero privilege level.</p>
+
+<a name="groups"></a>
+<h2>Group Tools</h2>
+       <p>Group tools are student tools that can also be group specific. A module can only implement one group tool. An instructor controls which group tools are available to a each group during the group creation process. Only group tools that are made available to students via the home page or main navigation are available for selection.</p>
+
+       <p>The group tool main page must be specified using the <kbd>$_group_tool</kbd> variable in the <kbd>module.php</kbd> file. The value of that variable must be the relative path to the file from the ATutor base directory (not the module directory). Example: <kbd>$_group_tool = 'mods/example_maker/index.php';</kbd>.</p>
+
+<a name="navigation"></a>
+<h2>Navigation &amp; Hierarchy</h2>
+       <p><em>Every</em> page in ATutor must have an entry in the global <kbd>$_pages</kbd> array where the key to the array is the relative path to the file from ATutor's base directory. Module pages are specified using the <kbd>$_module_pages</kbd> array, which are then merged into the <kbd>$_pages</kbd> array when the <kbd>module.php</kbd> file is loaded. The array supports the following attributes:</p>
+
+       <dl>
+               <dt><kbd>title_var</kbd></dt>
+               <dd>The language variable to be used with <kbd>_AT()</kbd>.</dd>
+
+               <dt><kbd>title</kbd></dt>
+               <dd>The hard-coded version of the language title. If set, overrides the usage of <kbd>_AT(title_var)</kbd>. This version is not language independent.</dd>
+
+               <dt><kbd>parent</kbd></dt>
+               <dd>The relative ATutor path to the parent page. Omit for Student Tools.</dd>
+
+               <dt><kbd>img</kbd></dt>
+               <dd>The relative ATutor path to the icon to use. Only for Student Tools.</dd>
+
+               <dt><kbd>children</kbd></dt>
+               <dd>An array whose values are relative ATutor paths to sub pages.</dd>
+
+               <dt><kbd>guide</kbd></dt>
+               <dd>The the section of the handbook that the module page should link to. Not used for modules at this time.</dd>
+       </dl>
+
+       <p>For pages to appear in the instructor Manage section, their <kbd>parent</kbd> field must be set to <kbd>tools/index.php</kbd>.</p>
+
+<pre>
+$path = 'mods/example_maker/';
+
+// the student tool:
+$_module_pages[$path.'index.php']['title_var'] = 'example_maker';
+$_module_pages[$path.'index.php']['img']       = $path.'icon.gif';
+$_module_pages[$path.'index.php']['children']  = array($path.'sub.php', $path.'more.php');
+
+    $_module_pages[$path.'sub.php']['title_var'] = 'sub_page';
+    $_module_pages[$path.'sub.php']['parent']    = $path.'index.php';
+
+    $_module_pages[$path.'more.php']['title_var'] = 'more_page';
+    $_module_pages[$path.'more.php']['parent']    = $path.'index.php';
+
+// the instructor page:
+$_module_pages[$path . 'inst_index.php']['title_var'] = 'example_maker';
+$_module_pages[$path . 'inst_index.php']['parent']    = 'tools/index.php';
+</pre>
+<a name="delete"></a>
+<h2>Course Deletion</h2>
+       <p>When a course is being deleted, or when a back-up is being restored by overriding (i.e. deleting) existing content, a module has to ensure that the content for that course is also deleted. If the module maintains course data directories, then those directories have to either be emptied or deleted. If the module uses database tables for course content, then it has to delete the appropriate entries for that course.</p>
+
+       <p>The function used to delete the course content for that module must be stored in the <kbd>module_delete.php</kbd> file and named <kbd><em>module_name</em>_delete()</kbd>. The delete function takes a single argument which is the ID of the course to delete.</p>
+
+<pre>
+&lt;?php
+function example_maker_delete($course) {
+    global $db;
+
+    // delete directory
+    $path = AT_CONTENT_DIR . 'example_maker/' . $course . '/';
+    clr_dir($path);
+
+    // delete from database
+    $sql = "DELETE 
+            FROM ".TABLE_PREFIX."example_content 
+            WHERE course_id=$course";
+    mysql_query($sql, $db);
+}
+?>
+</pre>
+<a name="backup"></a>
+<h2>Backing-Up and Restoring</h2>
+       <p>It is possible for a module to include its content when a course backup is being created or restored. Backups support database tables with foreign-key constraints as well as course specific directories.</p>
+<a name="directories"></a>
+       <h3>Directories</h3>
+               <p>A module can backup as many directories as it requires, all specified using the <kbd>$dirs</kbd> array variable.</p>
+
+               <p>The example below uses the special <kbd>?</kbd> token as the place holder for the course ID. When the course is backed-up, the question mark will be replaced with the correct course ID. The key to the array is the unique name of the directory to be used inside the backup archive file. The same information to create the backup is also used to restore it, so no additional details are required.</p>
+<pre>
+$dirs = array();
+$dirs['example_maker/'] = AT_CONTENT_DIR . 'example_maker/?/';
+</pre>
+
+<a name="database"></a>
+       <h3>Database Tables</h3>
+               <p>There are two parts to backing-up and restoring a module's database tables. First, the <acronym title="Structured Query Language">SQL</acronym> queries must be specified using the <kbd>$sql</kbd> array variable and then the restore functions must convert the rows so that they can be inserted into the database tables.</p>
+
+               <p>The example below uses the special <kbd>?</kbd> token as the place holder for the course ID. When the course is backed-up the question-mark will be replaced with the correct course ID. The key to the array is the unique name of the <acronym title="Comma Separated Values">CSV</acronym> file to save in the backup archive, without the extension. The <acronym title="Structured Query Language">SQL</acronym> query itself must only select the fields that will be backed up. If there are foreign key constraints to preserve then the key will have to be retrieved as well so that it can be used when restoring the tables.</p>
+
+<pre>
+$sql = array();
+$sql['example']  = 'SELECT title FROM '.TABLE_PREFIX.'example WHERE course_id=?';
+</pre>
+
+               <p>For each key in the <kbd>$sql</kbd> array there must be a function with the same name, but suffixed with <kbd>_convert</kbd>. The <kbd><em>tbl_name</em>_convert()</kbd> function must return the newly transformed row with respect to the version of ATutor that was used to generate the <acronym title="Comma Separated Values">CSV</acronym> file. The function accepts the following arguments:</p>
+
+               <dl>
+                       <dt><kbd>$row</kbd></dt>
+                       <dd>An array which represents a single row in the <acronym title="Comma Separated Values">CSV</acronym> file.</dd>
+
+                       <dt><kbd>$course_id</kbd></dt>
+                       <dd>The course ID which this content should be associated with.</dd>
+                       
+                       <dt><kbd>$table_id_map</kbd></dt>
+                       <dd>An associative array representing previously restored tables and their new keys. Used to preserve foreign key constraints.</dd>
+
+                       <dt><kbd>$version</kbd></dt>
+                       <dd>The version of ATutor that was used to generate this file.</dd>
+               </dl>
+
+<pre>
+function example_convert($row, $course_id, $table_id_map, $version) {
+    $new_row = array();
+    $new_row[0]  = 0; // auto-increment field
+    $new_row[1]  = $course_id;
+    $new_row[2]  = $row[1]; // the title
+    if (version_compare($version, '1.5.2', '&lt;')) {
+        // this field did not exist prior to 1.5.2
+        $new_row[3] = '';
+    } else {
+        $new_row[3] = $row[2];
+    }
+
+    return $new_row;
+}
+</pre>
+<a name="cron"></a>
+       <h2>Running Cron/Scheduling</h2>
+<p>The <kbd>module_cron.php</kbd> file can be used to run module related functions at specified intervals. The following example doesn't do much of anything..., but you get the idea.  If cron has been enabled in ATutor, all the module_cron.php files from each module are run at the interval specified when the Cron is setup. See the Cron Setup sections in the Administrator Handbook, and in ATutor in the Administrator's System Preferences.</p>
+
+<pre>
+&lt;?php
+/*******
+ * this function named [module_name]_cron is run by the global cron script at the module's specified
+ * interval.
+ */
+
+function hello_world_cron() {
+       global $db;
+       debug('yay i am running!');
+}
+
+?>
+</pre>
+</body>
+</html>
\ No newline at end of file
diff --git a/documentation/developer/styles.css b/documentation/developer/styles.css
new file mode 100644 (file)
index 0000000..146dd46
--- /dev/null
@@ -0,0 +1,137 @@
+pre {\r
+       font-family: trebuchet ms, Arial, sans-serif;\r
+}\r
+\r
+body{\r
+       background-color: #FFF;\r
+    font-family: "Trebuchet MS",Verdana,Arial,sans-serif;\r
+}\r
+h1,h2,h3,p, table, ul {\r
+       margin: 0 10px\r
+}\r
+h1 {\r
+       color: #FFF;\r
+       border-bottom: 1px dashed #FFF;\r
+       margin-left: -5px;\r
+       padding-left: 15px;\r
+       margin-right: -5px;\r
+       padding-right: 15px;\r
+}\r
+h2{color: #FFF;\r
+       border-bottom: 1px dashed #FFF;\r
+       margin-left: -5px;\r
+       padding-left: 15px;\r
+       margin-right: -5px;\r
+       padding-right: 15px;\r
+}\r
+h3{color: #f0f0f0}\r
+p{padding-bottom:1em}\r
+h2{padding-top: 0.3em}\r
+\r
+/* for the curves */\r
+div.nifty { margin: 10px 2%; background: #9BD1FA; }\r
+b.rtop, b.rbottom{display:block;background: #FFF}\r
+b.rtop b, b.rbottom b{display:block;height: 1px; overflow: hidden; background: #9BD1FA}\r
+b.r1{margin: 0 5px}\r
+b.r2{margin: 0 3px}\r
+b.r3{margin: 0 2px}\r
+b.rtop b.r4, b.rbottom b.r4{margin: 0 1px;height: 2px}\r
+\r
+\r
+a {\r
+       text-decoration: none;\r
+       border-bottom: 1px solid white;\r
+       color: white;\r
+       font-weight: bold;\r
+}\r
+a:hover {\r
+       border-bottom: 0px;\r
+}\r
+td,th {\r
+       font-size: 85%;\r
+}\r
+\r
+kbd {\r
+       padding: 0px 1px 0px 1px;\r
+       border-width: 1px 2px 2px 1px;\r
+       border-style: solid;\r
+       border-color: #edd #baa #baa #eed;\r
+       white-space: pre;\r
+}\r
+\r
+code {\r
+    font-family: "Trebuchet MS",Verdana,Arial,sans-serif;\r
+       background-color: #efefef;\r
+       padding: 0px 4px 0px 4px;\r
+       border-width: 1px 1px 1px 1px;\r
+       border-style: solid;\r
+       border-color: #edd #baa #baa #eed;              \r
+}\r
+\r
+\r
+div#toc {\r
+       color: #f0f0f0;\r
+       padding-bottom: 15px;\r
+}\r
+\r
+div#toc ul {\r
+       list-style: none;\r
+}\r
+div#toc li {\r
+       padding-top: 2px;\r
+       padding-bottom: 0px;\r
+}\r
+\r
+ol {\r
+       margin-top: 0px;\r
+}\r
+\r
+ol li {\r
+       padding-bottom: 3px;\r
+}\r
+\r
+dl {\r
+       margin: 0 10px\r
+}\r
+dl dd { \r
+       padding-top: 0px;\r
+       padding-left: 5px;\r
+       margin-left: 5%;\r
+       border-left: 1px solid #f0f0f0;\r
+       margin-bottom: 10px;\r
+} \r
+\r
+acronym {\r
+       cursor: help;\r
+}\r
+\r
+a[href*="http"] {\r
+       padding-right: 8px;\r
+       background-image: url('link-out.gif');\r
+       background-repeat: no-repeat;\r
+       background-position: right 4px;\r
+       margin-right: 2px;\r
+}\r
+\r
+div#nav-links {\r
+       margin-left: 20px;\r
+       margin-right: 20px;\r
+       margin-bottom: 20px;\r
+}\r
+\r
+div#nav-links a {\r
+       color: black;\r
+       text-decoration: none;\r
+       border-bottom: 1px solid;\r
+}\r
+\r
+pre {\r
+       font-family: Courier, monospace;\r
+       background-color: #EEEEFF;\r
+       padding: 5px;\r
+       margin-left: 20px;\r
+       color:#761596;\r
+    margin-top: 0px;\r
+       width: 50%;\r
+       font-size: smaller;\r
+}
\ No newline at end of file
diff --git a/documentation/general/browse_courses.php b/documentation/general/browse_courses.php
new file mode 100644 (file)
index 0000000..7b8c7a4
--- /dev/null
@@ -0,0 +1,9 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>Browse Courses</h2>\r
+\r
+<p>The Browse Courses page lists all  courses presently available on the ATutor system.</p>  \r
+\r
+<p>If a course is Public, it may be accessed without logging in first. Protected and Private courses require that you be logged in. Private courses are available only to those who have been approved and enrolled in the course.</p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/general/create_course.php b/documentation/general/create_course.php
new file mode 100644 (file)
index 0000000..1f5e87f
--- /dev/null
@@ -0,0 +1,7 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>Create Course</h2>\r
+\r
+<p>Only Instructors may create courses,  though if enabled,  students can request instructor accounts by selecting the Create Course link. View the <a href="../instructor/creating_courses.php">Instructor Documentation</a> on creating courses.</p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/general/en/index.php b/documentation/general/en/index.php
new file mode 100644 (file)
index 0000000..35fa5ae
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg                    */
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: index.php 5866 2005-12-15 16:16:03Z joel $
+
+header('Location: ../index.php'); // no need for english
+exit;
+?>
\ No newline at end of file
diff --git a/documentation/general/export_content.php b/documentation/general/export_content.php
new file mode 100644 (file)
index 0000000..4cba322
--- /dev/null
@@ -0,0 +1,9 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>Export Content</h2>\r
+\r
+<p>The Export Content feature creates a "Content Package" that can be downloaded and viewed offline in the viewer included with each package. If  this feature is turned on for a course, it may be accessed through a Student Tool icon on the home page, and/or a link in the main navigation. Choose which section you wish to download as a content package the use the <code>Export</code> button. <em>Export Content</em> is also linked from top level content pages or all content pages (depending on what the instructor has set) in the Shortcuts box.  Using this link will package the current page and all of its sub pages into a single "zip" file, and prompt the user to download the file.</p>\r
+\r
+<p>The downloaded file can be unpacked with a common archiving application (e.g. WinZip, PKZip, Unzip). Unzip the file into an empty directory then open the <kbd>index.html</kbd> file into a Web browser. </p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>\r
diff --git a/documentation/general/file_storage.php b/documentation/general/file_storage.php
new file mode 100644 (file)
index 0000000..3f4c2bc
--- /dev/null
@@ -0,0 +1,28 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>File Storage</h2>\r
+\r
+<p>Students, assistants, and instructors can access a personal file management tool using the <em>File Storage</em> area, if enabled for a course. Workspaces can be selected for storing files,  their presence depending on one's access rights:\r
+       <ul>\r
+               <li><em>Course Files</em> - The default workspace. Managed by the instructor, or assistants with file storage privileges, course resource files are made available for download by course members.</li>\r
+               <li><em>My Files</em> - Private files only the user can access and manage.</li>\r
+               <li><em>Groups</em> - Shared files managed by group members, and accessible to instructors and assistants with group privileges.</li>\r
+               <li><em>Assignments</em> - Students can submit assignments from these workspaces, and instructors or assistants with assignment privileges can manage submissions from the File Storage utiilty. To submit an assignment, upload a file to <em>MyFiles</em>, or to a group workspace, then select the file you wish to hand in and press  the <em>Handin</em> button to view a list is assignments. Choose the assignment for which you are hinding in the file, then press <em>Submit</em></li>\r
+\r
+       </ul>\r
+\r
+To move between workspaces, select them from the dropdown menu and use the <code>    Go!            </code>  button. To view a file in the File Storage area, download and open it locally on your own computer.\r
+</p>\r
+<h3>Create Folders and Adding Files</h3>\r
+<p>To organize files, folders can be created using the <em>Create Folder</em> feature at the top right of the file area. To upload a new file, with an optional description of its contents, use the <em>New File</em> feature at the top left. The file will be uploaded to the currently opened directory.</p>\r
+\r
+<h3>Managing Files</h3>\r
+<p>It is also possible to <code>Download</code> files to your hard drive, <code>Hand In</code> a file for an assignment, <code>Edit</code> file details and rename folders,  <code>Move</code> files around within a workspace, as well as <code>Delete</code> files and folders. Depending on the type of workspace, the buttons that appear will vary.</p>\r
+\r
+<h3>File Revisions</h3>\r
+\r
+<p>If enabled, file revisions can be kept, so a history of the document or file is available. Uploading a file of the same name as one that exists, will create a second version of the file, and so on. With each revision comments can be added, to summarize the changes from authors, and to perhaps collect feedback from reviewers.</p>\r
+\r
+\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/general/fr/index.php b/documentation/general/fr/index.php
new file mode 100644 (file)
index 0000000..c71e41f
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg                    */
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: index.php 5866 2005-12-15 16:16:03Z joel $
+
+$parts = pathinfo($_SERVER['PHP_SELF']);
+
+$dir_parts = explode('/', $parts['dirname']);
+$last_dir_name = end($dir_parts);
+
+header('Location: ../index.php?' . $last_dir_name);
+exit;
+?>
\ No newline at end of file
diff --git a/documentation/general/inbox.php b/documentation/general/inbox.php
new file mode 100644 (file)
index 0000000..9b14d94
--- /dev/null
@@ -0,0 +1,10 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>Inbox</h2>\r
+<p>The Inbox is used for privately messaging other users in your courses. Inbox messages appear in a table, with new messages flagged. Selecting a message will display its contents at the top of the screen.</p>\r
+\r
+<p>In the sub-navigation there is a link to send a message. Choose the recipient, enter a subject and a message, and use the <code>Send</code> button. </p>\r
+\r
+<p>Note: use the <em>Inbox Notification</em> <a href="preferences.php">preference</a> to receive emails when a new Inbox message is received.</p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/general/index.php b/documentation/general/index.php
new file mode 100644 (file)
index 0000000..04121b3
--- /dev/null
@@ -0,0 +1 @@
+<?php require('../index.php'); ?>
\ No newline at end of file
diff --git a/documentation/general/inside_course.php b/documentation/general/inside_course.php
new file mode 100644 (file)
index 0000000..bd092c8
--- /dev/null
@@ -0,0 +1,9 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>Course Features</h2>\r
+\r
+<p>After a student has entered into a course, he/she is presented with the course Home page. The Home page may contain a course banner, links to Student Tool, and course announcements. </p>\r
+\r
+<p>A few of the course features are explained here, as they may be a little tricky for new users. Other features are fairly straight forward and should be intuitive to use. Look for the handbook link while using a tool, to open its help page directly.</p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/general/introduction.php b/documentation/general/introduction.php
new file mode 100644 (file)
index 0000000..243f1f5
--- /dev/null
@@ -0,0 +1,7 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>Introduction</h2>\r
+<p>Welcome to the ATutor General User documentation. The information found here is applicable to both instructors and students. Also see the the <a href="../instructor">Instructor Documentation</a> for details of other tools that might be used to author content while in a group environment. </p>\r
+\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/general/login.php b/documentation/general/login.php
new file mode 100644 (file)
index 0000000..a92dcb2
--- /dev/null
@@ -0,0 +1,7 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>Login</h2>\r
+\r
+<p>A user may login to the system with the Login Name or Email address, and the Password entered during <a href="register.php">registration</a>. Logging in gives users access to Protected courses, lets them enroll, and lets them participate in courses.</p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>\r
diff --git a/documentation/general/my_courses.php b/documentation/general/my_courses.php
new file mode 100644 (file)
index 0000000..539d707
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>My Courses</h2>\r
+<p>Courses that the user is in enrolled in, or courses that are pending enrollment, are listed on the <em>My Courses</em> page.</p>\r
+\r
+<p>To enroll into a public or protected course, follow the <em>Browse Courses</em> link and locate it, then enter the course and use the <em>Enroll Me</em> link located beside the course title. If the course is private, enrollment must be requested first. Admission into the course will be allowed once the instructor has approved the request.</p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/general/my_start_page.php b/documentation/general/my_start_page.php
new file mode 100644 (file)
index 0000000..40251bb
--- /dev/null
@@ -0,0 +1,7 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>My Start Page</h2>\r
+\r
+<p><em>My Start Page</em> is a personal area displayed after logging in. The My Courses section lists the courses that the user either teaches, or is enrolled in. From here one can also create a new course, or browse through courses. There is also a <a href="profile.php">Profile</a> section for editing personal details (including changing a password or an email address), and a <a href="preferences.php">Preferences</a> section for editing some system preferences such as the way information is displayed and the preferred theme. </p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/general/packages.php b/documentation/general/packages.php
new file mode 100644 (file)
index 0000000..511add8
--- /dev/null
@@ -0,0 +1,7 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>Packages</h2>\r
+\r
+<p>If instructors have included SCORM compliant Sharable Content Objects (SCOs), they will be avilable for viewing using the <em>Packages</em> tool. Note that the SCORM Run Time Environment (RTE) requires the Java JRE 1.5 to function properly, as well as LiveConnect, which is enabled by default in the JRE 1.5. Download an install with <a href="http://java.sun.com/javase/downloads/index.jsp" target="new">latest Java JRE</a> from the SUN site, if you need to upgrade your browser's java support.</p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/general/pages.inc.php b/documentation/general/pages.inc.php
new file mode 100644 (file)
index 0000000..22c4061
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+       $_pages = array();
+    $_pages['introduction.php']                                = 'Introduction';
+    $_pages['login.php']                                       = 'Login';
+    $_pages['register.php']                                    = 'Register';
+    $_pages['browse_courses.php']                      = 'Browse Courses';
+    $_pages['password_reminder.php']           = 'Forgot Your Password';
+    $_pages['my_start_page.php']                       = 'My Start Page';
+    $_pages['my_courses.php']                          = 'My Courses';
+    $_pages['create_course.php']                       = 'Create Courses';
+    $_pages['profile.php']                                     = 'Profile';
+    $_pages['preferences.php']                         = 'Preferences';
+    $_pages['inbox.php']                                       = 'Inbox';
+       $_pages['inside_course.php']                    = 'Inside a Course';
+       $_pages['export_content.php']                   = 'Export Content';
+       $_pages['packages.php']                                 = 'Packages';
+       $_pages['tile.php']                                             = 'TILE Repository Search';
+       $_pages['file_storage.php']                             = 'File Storage';
+
+?>
\ No newline at end of file
diff --git a/documentation/general/password_reminder.php b/documentation/general/password_reminder.php
new file mode 100644 (file)
index 0000000..97ac220
--- /dev/null
@@ -0,0 +1,7 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>Forgot Your Password</h2>\r
+\r
+<p>If you have forgotten your password, use the <em>Forgot your password?</em> link on the Login screen. The form will email the login name to you, along with a link you must follow to change your password.</p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/general/preferences.php b/documentation/general/preferences.php
new file mode 100644 (file)
index 0000000..5acb47f
--- /dev/null
@@ -0,0 +1,30 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>Preferences</h2>\r
+<p>The following preferences allow a user to control how some features function, and how information is displayed.</p>\r
+\r
+<dl>\r
+    <dt>Theme</dt>\r
+    <dd>Themes are used for changing the look and feel.</dd>\r
+\r
+    <dt>Inbox Notification</dt>\r
+    <dd>If enabled, an email notification message will be sent each time an Inbox message is received.</dd>\r
+\r
+    <dt>Topic Numbering</dt>\r
+    <dd>If enabled, content topics will be numbered.</dd>\r
+\r
+    <dt>Direct Jump</dt>\r
+    <dd>If enabled, using the Jump feature will redirect to the selected course and load the same section that was being viewed in the previous course (instead of the usual course Home page).</dd>\r
+\r
+    <dt>Auto-Login</dt>\r
+    <dd>If enabled, users are automatically logged in when they open ATutor. You should only enable this if you are accessing ATutor from a private computer, otherwise others will be able to login with your account information.</dd>\r
+\r
+    <dt>Form Focus On Page Load</dt>\r
+    <dd>If enabled, the cursor will be placed at the first field of the form when a page loads.</dd>\r
+\r
+       <dt>Content Editor</dt>\r
+       <dd>This preference controls how content is entered. Choose between <em>Plain Text</em> for entering content text that will escape any HTML markup and will be formatted as entered; <em>HTML</em> for entering HTML content manually; and <em>HTML - Visual Editor</em> for entering HTML content using the visual (also known as a <acronym title="What You See Is What You Get">WYSIWYG</acronym>) editor which represents the content as it will be displayed. It is also possible to change the editor manually for each item.</dd>\r
+</dl>\r
+\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/general/profile.php b/documentation/general/profile.php
new file mode 100644 (file)
index 0000000..a879e2d
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>Profile</h2>\r
+<p>This section allows a user to change elements of his/her personal profile.</p>\r
+\r
+<p>Although the login name cannot be altered, password, email address, and other personal information may be edited. There is also an option to keep the email address hidden.</p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/general/register.php b/documentation/general/register.php
new file mode 100644 (file)
index 0000000..60ca2e3
--- /dev/null
@@ -0,0 +1,9 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>Register</h2>\r
+\r
+<p>In order for a user to login to the ATutor system, a unique system account needs to be created.  Use the <em>Register</em> link in the main navigation to access the registration form. If email-confirmation has been enabled by the system administrator, a message will be sent to the email address entered, containing a link that must be followed to confirm the new account. Once this has been done, the login name or email address, and the password entered during registration can now be used on the <a href="login.php">Login</a> screen.</p>\r
+\r
+<p>Note that if a system administrator has specified users to be checked against a Master List of allowed Student IDs and PINs (for example), this information must also be entered during registration.</p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/general/tile.php b/documentation/general/tile.php
new file mode 100644 (file)
index 0000000..f4b1416
--- /dev/null
@@ -0,0 +1,9 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>TILE Repository Search</h2>\r
+\r
+<p>External content packages can be downloaded from the TILE repository by entering a search term and using the <code>Search</code> button.  Use the <em>Preview</em> link next to a search result to open the TILE content browser, or use <em>Download</em> to retrieve the content package from the TILE repository. Once downloaded, the file can be unpacked with a common archiving application (e.g. WinZip, PKZip, Unzip). Unzip the file into an empty directory and browse the package's content. </p>\r
+\r
+<p>Visit the <a href="http://www.inclusivelearning.ca/" target="new">TILE web site</a> for more information about using the repository.</p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/index.php b/documentation/index.php
new file mode 100644 (file)
index 0000000..ee704c8
--- /dev/null
@@ -0,0 +1,112 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: menu_pages.php 4799 2005-06-06 13:19:09Z heidi $
+
+
+$parts = pathinfo($_SERVER['PHP_SELF']);
+if (substr($parts['dirname'], -5) == 'admin') {
+       $section = 'admin';
+} else if (substr($parts['dirname'], -10) == 'instructor') {
+       $section = 'instructor';
+} else if (substr($parts['dirname'], -7) == 'general') {
+       $section = 'general';
+} else {
+       header('Location: index/index.php');
+       exit;
+}
+
+if ( get_magic_quotes_gpc() == 1 ) {
+       $addslashes = 'my_add_null_slashes';
+} else {
+       $addslashes = 'addslashes';
+}
+
+$req_lang = 'en';
+if (!empty($_GET)) {
+       $req_lang = key($_GET);
+}
+
+$path = '../common/';
+?>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+<html lang="en">
+       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+       <title>ATutor Handbook</title>
+<script type="text/javascript">
+
+var i = 0;
+
+function show2() {
+       var fs = document.getElementById('frameset1');
+       if (fs) {
+               i += 5;
+               if (i > 28) {
+                       i = 28;
+               }
+               fs.cols = i + '%, *';
+       }
+       if (i < 28) {
+               window.setTimeout('show2()', 1);
+       }
+       return true;
+}
+function show() {
+       i = 0;
+       window.setTimeout('show2()', 1);
+       return true;
+}
+
+function hide2() {
+       var fs = document.getElementById('frameset1');
+       if (fs) {
+               i -= 5;
+               if (i < 0) {
+                       i =0;
+               }
+               fs.cols = i + '%, *';
+       }
+       if (i > 0) {
+               window.setTimeout('hide2()', 1);
+       }
+       return false;
+}
+
+function hide() {
+       i= 28;
+       window.setTimeout('hide2()', 1);
+       return false;
+}
+</script>
+
+<?php 
+if (isset($_GET['p'])) {
+       $body = html_entities($_GET['p']);
+} else {
+       $body = 'introduction.php';
+} 
+?>
+</head>
+<frameset rows="24,*">
+       <frame src="<?php echo $path; ?>frame_header.php?<?php echo $section; ?>&amp;<?php echo $req_lang; ?>" frameborder="0" name="header" title="header" scrolling="no" noresize="noresize">
+       <frameset cols="22%, *" id="frameset1">
+               <frame frameborder="0" scrolling="auto" marginwidth="0" marginheight="0" src="<?php echo $path; ?>frame_toc.php?<?php echo $section; ?>&amp;<?php echo $req_lang; ?>" name="toc" id="toc" title="Table of Contents">
+               <frame frameborder="0" src="<?php echo $body.'?'.$req_lang; ?>" name="body" title="Content">
+       </frameset>
+
+       <noframes>
+               <h1>Administrator Documentation</h1>
+               <p><a href="frame_toc.html">Table of Contents</a></p>
+        </noframes>
+</frameset>
+
+</html>
diff --git a/documentation/index/en/index.php b/documentation/index/en/index.php
new file mode 100644 (file)
index 0000000..35fa5ae
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg                    */
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: index.php 5866 2005-12-15 16:16:03Z joel $
+
+header('Location: ../index.php'); // no need for english
+exit;
+?>
\ No newline at end of file
diff --git a/documentation/index/fr/index.php b/documentation/index/fr/index.php
new file mode 100644 (file)
index 0000000..c71e41f
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg                    */
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: index.php 5866 2005-12-15 16:16:03Z joel $
+
+$parts = pathinfo($_SERVER['PHP_SELF']);
+
+$dir_parts = explode('/', $parts['dirname']);
+$last_dir_name = end($dir_parts);
+
+header('Location: ../index.php?' . $last_dir_name);
+exit;
+?>
\ No newline at end of file
diff --git a/documentation/index/index.php b/documentation/index/index.php
new file mode 100644 (file)
index 0000000..b7ef5b4
--- /dev/null
@@ -0,0 +1,163 @@
+<?php\r
+require(dirname(__FILE__) .'/../common/vitals.inc.php');\r
+\r
+// using 401 authentication\r
+if (isset($_GET['login'])) {\r
+       if (!isset($_SERVER['PHP_AUTH_USER'])) {\r
+               header('WWW-Authenticate: Basic realm="Administrator Login"');\r
+               header('HTTP/1.0 401 Unauthorized');\r
+               echo 'Wrong username/password combination.';\r
+               exit;\r
+       } else {\r
+               $_POST['username'] = $_SERVER['PHP_AUTH_USER'];\r
+               $_POST['password'] = $_SERVER['PHP_AUTH_PW'];\r
+               $_POST['submit']   = true;\r
+       }\r
+       unset($_SERVER['PHP_AUTH_USER']);\r
+       unset($_SERVER['PHP_AUTH_PW']);\r
+}\r
+\r
+$config_location = '../../include/config.inc.php';\r
+if (is_file($config_location) && is_readable($config_location)) {\r
+       require($config_location);\r
+       $db = mysql_connect(DB_HOST . ':' . DB_PORT, DB_USER, DB_PASSWORD);\r
+       mysql_select_db(DB_NAME, $db);\r
+\r
+       // check atutor config table to see if handbook notes is enabled.\r
+       $sql    = "SELECT value FROM ".TABLE_PREFIX."config WHERE name='user_notes'";\r
+       $result = @mysql_query($sql, $db);\r
+       if (($row = mysql_fetch_assoc($result)) && $row['value']) {\r
+               define('AT_HANDBOOK_ENABLE', true);\r
+               $enable_user_notes = true;\r
+       }\r
+       define('AT_HANDBOOK_DB_TABLE_PREFIX', TABLE_PREFIX);\r
+\r
+       if (isset($_POST['submit'])) {\r
+               // try to validate $_POST\r
+               // authenticate against the ATutor database if a connection can be made\r
+               $_POST['username'] = addslashes($_POST['username']);\r
+               $_POST['password'] = addslashes($_POST['password']);\r
+                       \r
+               if (!$db) {\r
+                       $db = @mysql_connect(AT_HANDBOOK_DB_HOST . ':' . AT_HANDBOOK_DB_PORT, AT_HANDBOOK_DB_USER, AT_HANDBOOK_DB_PASSWORD);\r
+                       if (@mysql_select_db(AT_HANDBOOK_DB_DATABASE, $db)) {\r
+                               $enable_user_notes = true;\r
+                       }\r
+               }\r
+                       \r
+               // check if it's an admin login.\r
+               $sql = "SELECT login, `privileges` FROM ".TABLE_PREFIX."admins WHERE login='$_POST[username]' AND PASSWORD(password)=PASSWORD('$_POST[password]') AND `privileges`>0";\r
+               $result = mysql_query($sql, $db);\r
+               if ($row = mysql_fetch_assoc($result)) {\r
+                       $_SESSION['handbook_admin'] = true;\r
+                       header('Location: '.$_SERVER['PHP_SELF']);\r
+                       exit;\r
+               }\r
+       } else if (isset($_GET['logout'])) {\r
+               header('WWW-Authenticate: Basic realm="Administrator Login"');\r
+               header('HTTP/1.0 401 Unauthorized');\r
+\r
+               unset($_SERVER['PHP_AUTH_USER']);\r
+               unset($_SERVER['PHP_AUTH_PW']);\r
+               unset($_SESSION['handbook_admin']);\r
+               session_write_close();\r
+               header('Location: '.$_SERVER['PHP_SELF']);\r
+               exit;\r
+       }\r
+}\r
+\r
+if (!defined('AT_HANDBOOK_ENABLE')) {\r
+       // use local config file\r
+       require('../config.inc.php');\r
+\r
+       if (isset($_POST['submit'])) {\r
+               // try to validate $_POST\r
+               if (($_POST['username'] == AT_HANDBOOK_ADMIN_USERNAME) && ($_POST['password'] == AT_HANDBOOK_ADMIN_PASSWORD)) {\r
+                       $_SESSION['handbook_admin'] = true;\r
+                       header('Location: '.$_SERVER['PHP_SELF']);\r
+                       exit;\r
+               }\r
+       } else if (key($_GET) == 'logout') {\r
+               header('WWW-Authenticate: Basic realm="Administrator Login"');\r
+               header('HTTP/1.0 401 Unauthorized');\r
+\r
+               unset($_SERVER['PHP_AUTH_USER']);\r
+               unset($_SERVER['PHP_AUTH_PW']);\r
+               unset($_SESSION['handbook_admin']);\r
+               session_write_close();\r
+               header('Location: '.$_SERVER['PHP_SELF']);\r
+               exit;\r
+       }\r
+}\r
+\r
+if (!$db && defined('AT_HANDBOOK_ENABLE') && AT_HANDBOOK_ENABLE) {\r
+       $db = @mysql_connect(AT_HANDBOOK_DB_HOST . ':' . AT_HANDBOOK_DB_PORT, AT_HANDBOOK_DB_USER, AT_HANDBOOK_DB_PASSWORD);\r
+       @mysql_select_db(AT_HANDBOOK_DB_DATABASE, $db);\r
+       $enable_user_notes = true;\r
+}\r
+?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html lang="<?php if ($req_lang) { echo $req_lang; } else { echo 'dp'; } ?>">\r
+<head>\r
+       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />\r
+       <title><?php get_text('doc_title'); ?></title>\r
+       <link rel="stylesheet" href="../common/styles.css" type="text/css" />\r
+</head>\r
+<body>\r
+<?php if ($missing_lang): ?>\r
+       <div style="margin: 20px auto; border: 1px solid #aaf; padding: 4px; text-align: center; background-color: #eef;">\r
+               <?php get_text('page_not_translated'); ?>\r
+       </div>\r
+<?php endif; ?>\r
+\r
+<h1><?php get_text('doc_title'); ?></h1>\r
+<p><?php get_text('doc_welcome'); ?></p>\r
+\r
+       <ol>\r
+               <li><a href="../general/<?php echo $req_lang; ?>"><?php get_text('doc_user'); ?></a></li>\r
+               <li><a href="../admin/<?php echo $req_lang; ?>"><?php get_text('doc_admin'); ?></a></li>\r
+               <li><a href="../instructor/<?php echo $req_lang; ?>"><?php get_text('doc_instructor'); ?></a></li>\r
+               <li><a href="../developer/guidelines.html"><?php get_text('doc_dev'); ?></a></li>\r
+               <li><a href="../developer/modules.html"><?php get_text('doc_mods'); ?></a></li>\r
+       </ol>\r
+\r
+       <ol>\r
+               <li><a href="http://www.atutor.ca" target="new">atutor.ca</a></li>\r
+               <li><a href="http://www.atutor.ca/forums/" target="new">atutor.ca/forums/</a></li>\r
+               <li><a href="http://www.atutor.ca/atutor/docs/index.php" target="new">atutor.ca/atutor/docs/</a></li>\r
+       </ol>\r
+\r
+<?php if ($enable_user_notes && (!isset($_SESSION['handbook_admin']) || (isset($_SESSION['handbook_admin']) && !$_SESSION['handbook_admin']))): ?>\r
+       <div style="text-align: right;">\r
+               <p><?php get_text('doc_notes_enabled');  ?></p>\r
+       </div>\r
+<?php elseif ($enable_user_notes): ?>\r
+\r
+       <p><?php get_text('doc_logged_in'); ?></p>\r
+\r
+       <?php\r
+               $sql = "SELECT note_id, date, section, page, email, note FROM ".AT_HANDBOOK_DB_TABLE_PREFIX."handbook_notes WHERE approved=0 ORDER BY date DESC";\r
+               $result = mysql_query($sql, $db);\r
+       ?>\r
+       <div class="add-note">\r
+               <h3><?php get_text('doc_unapproved_notes'); ?></h3>\r
+       </div>\r
+\r
+       <?php if ($result && (mysql_num_rows($result) > 0)): ?>\r
+               <?php while ($row = mysql_fetch_assoc($result)): ?>\r
+                       <div class="note">\r
+                               <h5><?php echo $row['date']; ?>\r
+                                       <a href="../approve_note.php?id=<?php echo $row['note_id']; ?>" onclick="return confirm('<?php echo get_text('doc_approved_confirm'); ?>');"><?php  get_text('doc_approve'); ?></a> | \r
+                                       <a href="../delete_note.php?id=<?php echo $row['note_id']; ?>" onclick="return confirm('<?php echo get_text('doc_delete_confirm'); ?>');"><?php get_text('doc_delete'); ?></a>\r
+                               </h5>\r
+                               <h4><?php echo $row['email'];?></h4>\r
+                               <p><?php echo nl2br($row['note']); ?></p>\r
+                       </div>\r
+               <?php endwhile; ?>\r
+       <?php else: ?>\r
+               <div class="note"><?php get_text('doc_no_notes'); ?></div>\r
+       <?php endif; ?>\r
+\r
+<?php endif; ?>\r
+\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/documentation/index_list.php b/documentation/index_list.php
new file mode 100644 (file)
index 0000000..37c544d
--- /dev/null
@@ -0,0 +1,4 @@
+<?php\r
+header('Location: index/index.php?'.$_GET['lang']);\r
+exit;\r
+?>
\ No newline at end of file
diff --git a/documentation/instructor/accessibility.php b/documentation/instructor/accessibility.php
new file mode 100644 (file)
index 0000000..e55442e
--- /dev/null
@@ -0,0 +1,30 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Accessibility</h2>
+       <p>The Accessibility tab performs an analysis of the content for accessibility problems. Recommendations are given and you are given the option to implement or reverse corrections.</p>
+
+       <p>After opening the Accessibility tab, review the report, and notice the number of <em>known</em> and <em>potential</em> problems</p>
+
+       <p>Correct the known problems by reviewing the report, then returning to the Content tab to modify the HTML. Return to the Accessibility tab again when the known problems are corrected to see a <em>Conditional Pass</em>. Select from the choices available in the potential problems listed, then press <code>Make Decisions</code> to update the report. When all known problems are corrected, and decisions have been made on all potential problems, a <em>Full Pass</em> will be displayed, after which you can be sure the content will be accessible to all your students.</p>
+
+<h2>Content Editor Accessiblity</h2>
+<p>The Content Editor includes a number of added features to help make it accessible to assistive technology users, The accesskeys listed below allow navigation through the editor by keyboard. In addition to the Accessibility tab, the visual editor includes its own accessibility checker, as well as prompts while authoring, that prevent making accessibility mistakes.</p>
+<h3>Content Editor AccessKeys</h3>
+<ul>
+<li>[Alt-n] Content Tab</li>
+<li> [Alt-p] Properties Tab</li>
+<li> [Alt-g] Glossary Tab</li>
+<li>[Alt-r] Preview Tab</li>
+<li>[Alt-a] Accessibility Tab</li>
+<li> [Alt-s] Save</li>
+</ul>
+
+<h3>Visual Editor AccessKeys</h3>
+<ul>
+<li>[Alt-q] jump to button bar</li>
+<li>[Alt-z] jump to content area of editor/li>
+<li>[Alt-x] jump to element path (bottom)/li>
+</ul>
+
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/add_questions.php b/documentation/instructor/add_questions.php
new file mode 100644 (file)
index 0000000..9d00585
--- /dev/null
@@ -0,0 +1,9 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>Test Questions</h2>\r
+\r
+<p>To manage the questions in a test, choose the test from the Test/Surveys Manager and then use the <code>Questions</code> button. Questions in the <a href="question_database.php">Question Database</a> can be added to your test by using the <em>Add Questions</em> link. Check the questions and/or categories of questions to be added to the test and use the <code>Add to Test/Survey</code> button. After confirming this action, the added questions will appear in the Question Manager.  Beside each question is a box in which to enter a weight or mark for that question.  If this is for a survey, leave the weight box empty.  Note that Likert questions do not get marked and therefore do not require a weight. Reorder questions by changing the numbers in the Order column.</p>\r
+\r
+<p>It is also possible to <em>Edit</em> or <em>Remove</em> questions by using the links beside each question. Editing a question will alter it in the Question Database, and thus affect all tests and surveys using that question.  Removing the question only removes it from the test and will not delete the question from the Question Database.</p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/announcements.php b/documentation/instructor/announcements.php
new file mode 100644 (file)
index 0000000..0c6b7d6
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Announcements</h2>
+       <p>Announcements added through the Manage section will appear on the course Home page, sorted by date in descending order.</p>
+
+       <p>If the Syndicate Announcements options is enabled in course <a href="properties.php">Properties</a>, it is possible to subscribe to the feed using a <acronym title="Rich Site Summary">RSS</acronym> reader.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/assignments.php b/documentation/instructor/assignments.php
new file mode 100644 (file)
index 0000000..7cf7ffd
--- /dev/null
@@ -0,0 +1,14 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Assignments</h2>
+       <p>The assignment manager works alongside the <a href="../general/file_storage.php">File Storage</a> area by letting instructors create virtual assignment drop-boxes within it. A student can submit files to the assignment workspace, and the instructor can view and download the submissions through the assignment manager or the file storage area directly.</p>
+
+<h3>Add &amp; Manage Assignments</h3>
+       <p>To add a new assignment submission area, follow the <em>Add Assignment</em> link and specify the assignment title, who to assign it to (everyone or a specific <a href="groups.php">Group</a> Type), the due date if there is one, and how to handle late submissions. Be sure to <strong>enable File Storage</strong> for groups assignments are assigned to. Using the <code>Save</code> button will create a special folder named with the assignment title within the Assignment Submissions area of the File Storage area. Within each assignment folder, additional folders will be created for each student or group (depending on the "Assign to" setting). These folders are read-only and cannot be changed.</p>
+
+       <p>It is possible to <code>Edit</code> an assignment's properties after it has been created, though not the "Assign to" element.  Also note that if you <code>Delete</code> an assignment,   all of its submissions will be deleted. Therefore, it is advised that the instructor first download the submissions to her/his harddrive for safe keeping before deleting an assignment entry.</p>
+
+<h3>Downloading Submissions</h3>
+       <p>Only instructors and assistants with Assignment privileges may access assignment folders. Students and groups will not be able to access any submitted files. To download submitted assignments, select an assignment and use the <code>Submissions</code> button. This will redirect to the <a href="../general/file_storage.php">File Storage</a> area where an instructor can download submissions. Alternatively, this area can be accessed directly by going to the File Storage area, and selecting the name of the assignment from the <code>Workspace</code> dropdown.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/authenticated_access.php b/documentation/instructor/authenticated_access.php
new file mode 100644 (file)
index 0000000..c9058ea
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate: 2006-06-29 11:25:07 -0400 (Thu, 29 Jun 2006) $'; ?>
+
+<h2>Authenticated Access</h2>
+       <p>Since version 1.5.4, instructors may enable this feature to generate a unique <acronym title="Uniform Resource Identifier">URI</acronym> that may be distributed to authenticate guest access to the protected or private course.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/backups.php b/documentation/instructor/backups.php
new file mode 100644 (file)
index 0000000..37d0394
--- /dev/null
@@ -0,0 +1,10 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Backups</h2>
+       <p>ATutor offers the facility to create backups of your course and restore the contents of those backups at any time. This is  useful for duplicating a course or saving the entire course content for safe keeping in the case of accidental loss.</p>
+
+       <p>The Backups utility is found under the <em>Manage</em> section and is available to Instructors and System Administrators.</p>
+
+       <p>Each course can store only a finite number of backups (default 5). That limit can be altered by the Administrator using the System Preferences option.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/chat.php b/documentation/instructor/chat.php
new file mode 100644 (file)
index 0000000..53c85b5
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Chat</h2>
+       <p>The chat section is used for managing chat transcripts. An active transcript will record all of the chat messages as they are posted. There can be only one active transcript at a time.</p>
+
+       <p>A transcript is started by using the <em>Start Transcript</em> link. A unique name must be given to a new transcript when it is started.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/content.html b/documentation/instructor/content.html
new file mode 100644 (file)
index 0000000..fb017cf
--- /dev/null
@@ -0,0 +1,140 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html lang="en">\r
+<head>\r
+       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />\r
+       <title>ATutor 1.5 Instructor Documentation</title>\r
+       <link rel="stylesheet" href="../styles.css" type="text/css" />\r
+</head>\r
+<body>\r
+\r
+\r
+<div class="nifty"><b class="rtop"><b class="r1"></b><b class="r2"></b><b class="r3"></b><b class="r4"></b></b>\r
+       <h1>2. Content</h1>\r
+       <p>In order to add and manage content for a course, you must first be logged in as an instructor. By selecting a course, you can manage your content from the Manage tab, or by the Content Navigation tree.</p>\r
+\r
+       <h3>Table of Contents</h3>\r
+       <div id="toc">\r
+               <ul>\r
+                       <li>2.1 <a href="#2.1">Creating and Editing Content</a></li>\r
+                       <li>2.2 <a href="#2.2">Content Packages</a></li>\r
+               </ul>\r
+       </div>\r
+\r
+<b class="rbottom"><b class="r4"></b><b class="r3"></b><b class="r2"></b><b class="r1"></b></b></div>\r
+\r
+\r
+<div class="nifty"><b class="rtop"><b class="r1"></b><b class="r2"></b><b class="r3"></b><b class="r4"></b></b>\r
+       <a name="2.1"></a><h2>2.1 Creating and Editing Content</h2>\r
+\r
+       <p>Once you have selected a course, you can create or edit course content by selecting the <i>Manage</i> tab, then selecting the <i>Content</i> option.</p>\r
+\r
+       <p>You should now see a table of all the content in your current course. If you have no content, this list will be empty. If you already have content in your course, you can select an item and click the <code>Edit</code> button to begin editing. If you want to create new content, select the <i>Create Content</i> link along the top.</p>\r
+\r
+       <p>Whether editing or creating new content, the interface is the same for both actions.</p>\r
+       \r
+       <a name="2.1.1"></a><h3>2.1.1 Content</h3>\r
+       <p>Content can be created in either 'plain text' or 'HTML' modes. Plain text mode is useful for quickly writing up text content. Conversely, HTML mode allows for extra features like text formatting and layout, but is a little more complex to use.</p>\r
+\r
+       <dl>\r
+               <dt>Formatting: Plain Text</dt>\r
+               <dd>If using plain text mode, just type the content in the Body window. Note that any extra spaces between characters will be removed (i.e. two or more spaces), but any blank lines will be saved with the text.</dd>\r
+\r
+               <dt>Formatting: HTML</dt>\r
+               <dd>If using HTML mode, you can type HTML tags in the Body window along with your text. If you are unfamiliar with HTML, you can use the visual editor by clicking the <code>Switch to visual editor</code> button.</dd>\r
+\r
+               <dt>File Manager</dt>\r
+               <dd>\r
+                       <p>The File Manager is a tool that allows you to upload files from your local system to be used in your course.</p>\r
+                       \r
+                       <p><code>Create Folder</code> creates a folder on the ATutor system so you can better organize your uploaded files. You can create folders and/or move files into that folder at any time you like.</p>\r
+\r
+                       <p><code>Browse...</code> opens a local file browser window so you can select the file you want to upload.</p>\r
+\r
+                       <p><code>Upload</code> will upload the specified file to the ATutor system. You can specify a file by either typing the path and filename in the <kbd>text field</kbd> or by using the <code>Browse</code> button.</p>\r
+\r
+                       <p><em>Create a New File</em> link will display a new interface where you can quickly create a new text or HTML file. If using Text mode, any blank lines will be saved with the file. If using HTML, you should be familiar with using HTML tags as no visual editor is provided. Clicking <code>Save</code> will save a new file with your specified information (filename and content) into the ATutor system and bring you back to the File Manager. <code>Cancel</code> will discard the file and bring you back to the File Manager browser.</p>\r
+\r
+                       <p><code>Rename</code> button renames a single, selected file.</p>\r
+\r
+                       <p><code>Delete</code> and <code>Move</code> buttons deletes or moves the selected files and folders (and its contents) from the ATutor system. You can select multiple files and folders for deletion or moving.</p>\r
+\r
+                       <p><code>Insert</code> appears under the <em>Action</em> column for files that can be inserted into the content. Clicking the <code>Insert</code> button will add appropriate HTML code into the body of the content. If you are formatting in <em>plain text</em> you will need to switch to <em>HTML</em> formatting in order for it to display properly.</p>\r
+               </dd>\r
+\r
+               <dt>Terms</dt>\r
+               <dd><p>In either plain text, or HTML formatting modes, you can insert <em>terms</em> which are used to tell the ATutor system the words you want to define in the glossary.</p>\r
+               \r
+               <p>Clicking the <em>Add Term</em> link will add <kbd>[?][/?]</kbd> into your content, and any text you put after <kbd>[?]</kbd> and before <kbd>[/?]</kbd> will specify the term you want to define. Alternatively, you can manually type <kbd>[?][/?]</kbd> into your text without having to click the <em>Add Term</em>.</p>\r
+\r
+               <p>Once you have specified the terms you would like to define, you can go to the <em>Glossary Terms</em> tab to write the definitions. Once done, the terms and their definitions will appear in the glossary and in the content.</p>\r
+\r
+               <dt>Code</dt>\r
+               <dd><p>In either plain text, or HTML formatting modes, you can insert <em>code</em> which is useful for differentiating blocks of text (like math equations, program code, or quotations)from the rest of the text content.</p>\r
+               \r
+               <p>Clicking the <em>Add Code</em> link will add <kbd>[code][/code]</kbd> into your content, and whatever text you put after <kbd>[code]</kbd> and before <kbd>[/code]</kbd> will specify the text you want to differentiate. Alternatively, you can manually type <kbd>[code][/code]</kbd> into your text without having to click the <em>Add Code</em> link.</p>\r
+               </dd>\r
+\r
+               <dt>Colours</dt>\r
+               <dd>Like <em>code</em> and <em>terms</em> you can add colour to your text content in the same way. You can either click the appropriate colour icon to insert colour tags into the content. Valid colour options are blue, red, green, orange, purple, and gray. You can also type the colour codes manually by using the following tags: <kbd>[blue][/blue]</kbd>, <kbd>[red][/red]</kbd>, <kbd>[green][/green]</kbd>, <kbd>[orange][/orange]</kbd>, <kbd>[purple][/purple]</kbd>, and <kbd>[gray][/gray]</kbd></dd>.\r
+\r
+               <dt>Upload from File</dt>\r
+               <dd>Instead of typing your content, you can upload it from a text or HTML file on your local file system. Once uploaded, the content of that file will be displayed in the <em>Body</em> window. Keep in mind that uploading in this manner will replace any content in the <em>Body</em> window.</dd>\r
+\r
+               <dt>Save and Close</dt>\r
+               <dd>At any point of editing or creating content, you can chose to <kbd>Save</kbd> your content, or <kbd>Cancel</kbd> your changes. \r
+               </dd>\r
+       </dl>\r
+\r
+       <a name="2.1.2"></a><h3>2.1.2 Properties</h3>\r
+       <p>In the properties tab, you can specify a Release Date, keywords for easier searching, and specify related topics.</p>\r
+\r
+       <dl>\r
+               <dt>Release Date</dt>\r
+               <dd>The release date is the date in which the content will be visible to the course. You can schedule a release in the future by specifying a later date. Also, if you specify a release date that has past, it will be released immediately.</dd>\r
+\r
+               <dt>Keywords</dt>\r
+               <dd>Words in the Keywords are given greater emphasis during searching. Therefore they will be placed higher in a list of search results than if there were no keywords. Keywords are also used to as Learning Object Metadata.</dd>\r
+\r
+               <dt>Related Topics</dt>\r
+               <dd><p>For each piece of content you have in the course, you can specify what other content in the course is related. Moving content up the related topics list places that content closer to the top of the Content Navigation window. The opposite is true if you move content down the Related Topics list.</p>\r
+               <p>You can also make content a child of another piece of content. In this case, the child content will appear as sub-content on the Content Navigation window. All sub-content children and their parent will appear in the Related Topics window.</p>\r
+               </dd>\r
+       </dl>\r
+\r
+       <a name="2.1.3"></a><h3>2.1.3 Glossary Terms</h3>\r
+       <p>If you specified Terms in the Content tab, you have the opportunity to define those terms here. For each term specified in the <em>Content</em> tab, there is a Definition window where you provide your explanation. If there are no glossary terms listed, you can add glossary terms by going to the Content tab and adding Term tags.</p>\r
+       \r
+       <p>In order to set a Related Term, you must have at least two defined terms in the glossary.</p>\r
+               \r
+       <a name="2.1.4"></a><h3>2.1.4 Preview</h3>\r
+       <p>Under the Preview tab, you can see how your content will appear to a user, including Terms, Code, and Colors you added to the content.</p>\r
+               \r
+       <a name="2.1.5"></a><h3>2.1.5 Accessibility</h3>\r
+       <p></p>\r
+<b class="rbottom"><b class="r4"></b><b class="r3"></b><b class="r2"></b><b class="r1"></b></b></div>\r
+\r
+<div class="nifty"><b class="rtop"><b class="r1"></b><b class="r2"></b><b class="r3"></b><b class="r4"></b></b>\r
+       <a name="2.2"></a><h2>2.2 Content Packages</h2>\r
+       <p>ATutor provides importing and exporting course content using IMS 1.1.3/SCORM 1.2 content package specification. This allows ATutor content to be viewed offline, and transferred to other systems.</p>\r
+\r
+       <a name="2.2.1"></a><h3>2.2.1 Exporting Content</h3>\r
+       <p>An entire course or a single chapter can be exported as an IMS 1.1.3/SCORM 1.2 content package. Exported packages are archived into a single file using ZIP compression. All content is exported including the terms and glossary, colours, and code.</p>\r
+       \r
+       <p>To export content, select the scope by choosing an option from the <em>What to export</em> menu. Then, clicking <kbd>Export</kbd> will generate a download through your browser. Optionally, you can choose to export the content directly to TILE if you have a TILE authoring account.</p>\r
+       \r
+       <a name="2.2.2"></a><h3>2.2.2 Viewing Exported Content</h3>\r
+       <p>To view a content package exported from ATutor, you will either need a IMS 1.1.3/SCORM 1.2 viewer, or a web browser. To view the content in a web browser, first extract the contents of the ZIP file and then open the file <kbd>index.html</kbd> in the browser.</p>\r
+\r
+       <a name="2.2.3"></a><h3>2.2.3 Importing Content</h3>\r
+       <p>To import a content package into ATutor, it must conform to IMS 1.1.3/SCORM 1.2 content package specifications.</p>\r
+\r
+       <p>Before importing, you must specify where in the course structure the new content is to be placed by using the <em>Import into</em> menu.</p>\r
+       \r
+       <p>Select the content package to upload by supplying the file from your local filesystem by typing in the path into the textfield or by using the <kbd>Browse</kbd> button. You can also import a content package over the Web by providing an URL.</p>\r
+\r
+       <p>Clicking <kbd>Import</kbd> will upload the content into the course and at the hierarchy location specified.</p>\r
+       \r
+<b class="rbottom"><b class="r4"></b><b class="r3"></b><b class="r2"></b><b class="r1"></b></b></div>\r
+\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/documentation/instructor/content.php b/documentation/instructor/content.php
new file mode 100644 (file)
index 0000000..a0520a6
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Content</h2>
+       <p>Content in ATutor can be managed in many ways and can be imported and created from many different sources. Content can be entered manually, created from HTML files, standards compliant content packages, or from a learning objects content repository. Content that already exists in ATutor can also be exported into any of the mentioned formats. Only instructors, and assistants who are given content <a href="enrollment_privileges.php">privileges</a>, can manage course content.</p>
+
+       <p>Existing content pages can be managed using the <em>Shortcuts</em> links available when viewing a content page, or through the Content section under the Manage tab.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/content_edit.php b/documentation/instructor/content_edit.php
new file mode 100644 (file)
index 0000000..06cc129
--- /dev/null
@@ -0,0 +1,66 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Entering Content</h2>
+       <p>Content can be created in either 'plain text' or 'HTML' mode. Plain text mode is useful for quickly writing up text content. HTML mode allows for extra features like text formatting and layout, but is a little more complex to use.</p>
+
+       <dl>
+               <dt>Title</dt>
+               <dd><p>The main heading that will appear at the top of the page when viewed.</p></dd>           
+
+               <dt>Customized Head</dt>
+               <dd><p>HTML that normally appears in the <kbd>head</kbd> area of a Web page can be entered here. This can include things like links to stylesheets, or the actual stylesheet markup, or you may insert links to scripts, or the scripts themselves. Additional metadata can also be entered here. HTML content created in an external editor will have its head information displayed here when Pasting from a file (see below) after which you can upload the additional files like stylesheets or scripts, and adjust the links to point to the files in the course File Manager. Note that when importing eXe content, the stylesheet supplied with its content is replaced to avoid conflicts between eXe styles and ATutor styles.  </p></dd>
+
+               <dt>Formatting: Plain Text</dt>
+               <dd><p>If using plain text mode, just type the content in the Body window. Note that any extra spaces between characters will be removed (i.e. two or more spaces), but any blank lines will be saved with the text.</p></dd>
+
+               <dt>Formatting: HTML</dt>
+               <dd><p>If using HTML mode, you can type HTML tags in the Body window along with your text. If you are unfamiliar with HTML, you can use the visual editor by clicking the <code>Switch to visual editor</code> button.</p></dd>
+
+               <dt>File Manager</dt>
+               <dd>
+                       <p>The File Manager is a tool that allows you to upload files from your local system to be used in your course. The popup File Manager can be open alongside the Content Editor by selecting <kbd>Open File Manager</kbd>.</p>
+                       
+                       <p>See the <a href="file_manager.php">File Manager</a> section for details.</p>
+               </dd>
+
+               <dt>Terms</dt>
+               <dd>
+                       <p>In either plain text or HTML formatting mode, you can insert <em>terms</em> to tell the ATutor system which words you wish to mark as glossary terms.</p>
+                       
+                       <p>Using the <em>Add Term</em> link will add <kbd>[?][/?]</kbd> into your content, and any text you put after <kbd>[?]</kbd> and before <kbd>[/?]</kbd> will specify the term you want to define. Alternatively, you can manually type <kbd>[?][/?]</kbd> into your text without having to use the <em>Add Term</em> link.</p>
+
+                       <p>Once you have specified the terms you would like to define, you can go to the <em>Glossary Terms</em> tab to write the definitions. Once this is done, the terms and their definitions will appear in the glossary and in the content.</p>
+               </dd>
+
+               <dt>Code</dt>
+               <dd>
+                       <p>In either plain text or HTML formatting mode, you can insert <em>code</em> which is useful for differentiating blocks of text (like math equations, program code, or quotations) from the rest of the text content.</p>
+                       
+                       <p>Using the <em>Add Code</em> link will add <kbd>[code][/code]</kbd> into your content, and any text you put after <kbd>[code]</kbd> and before <kbd>[/code]</kbd> will specify the text you want to differentiate. Alternatively, you can manually type <kbd>[code][/code]</kbd> into your text without having to use the <em>Add Code</em> link.</p>
+               </dd>
+
+               <dt>Previous/Next</dt>
+               <dd><p>Links can be generated by inserting the <kbd>[pid]</kbd> and the <kbd>[nid]</kbd> codes in your ATutor content.  When the page is displayed these codes get converted to the URL/Link for the previous or next pages in the sequence of content pages. For example <kdb><xmp><a href="[pid]">previous</a> <a href="[nid]">Next</a></xmp></kdb></p>
+
+               <p>Or, pasted the [pid] and [nid] tags into the Link URL field in the visual editor.</p>
+               </dd>
+
+               <dt>Colours</dt>
+               <dd><p>Like <em>code</em> and <em>terms</em>, colour may be added to text content in the same way. Use the appropriate colour icon to insert colour tags into the content. Valid colour options are blue, red, green, orange, purple, and gray. Also, colour codes can be typed in manually by using the following tags: <kbd>[blue][/blue]</kbd>, <kbd>[red][/red]</kbd>, <kbd>[green][/green]</kbd>, <kbd>[orange][/orange]</kbd>, <kbd>[purple][/purple]</kbd>, and <kbd>[gray][/gray]</kbd>.</p></dd>
+
+               <dt>LaTeX</dt>
+               <dd><p>Use <kbd>[tex][/tex]</kbd> to embed LaTeX equations into your content.</p></dd>
+
+               <dt>Multimedia</dt>
+               <dd><p>Use <kbd>[media][/media]</kbd> to embed multimedia into your content. Supported formats currently include: mpeg, mov, wmv, swf, mp3, wav, ogg, mid, and YouTube hosted videos. The media tag can take two parameters to define the width and height of the play when it displays <kbd>[media|640|480]http://www.youtube.com/watch?v=bxcZ-dFffHA[/media]</kbd>. If the parameters are not defined, the player size will default to 425x350</p></dd>
+
+               <dt>Paste from File</dt>
+               <dd><p>Rather than typing out content, it can be uploaded from a text or HTML file on your local file system. Once uploaded, the content of that file will be displayed in the <em>Body</em> window. Keep in mind that uploading in this manner will replace any existing content in the <em>Body</em> window.</p></dd>
+
+               <dt>Save and Close</dt>
+               <dd><p>While editing or creating content, it is wise to frequently <kbd>Save</kbd> your content.  When you are finished, use <kbd>Close</kbd> to close the content editor.  Note that this does not save your content first so any unsaved content will be lost.</p></dd>
+
+
+       </dl>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/content_packages.php b/documentation/instructor/content_packages.php
new file mode 100644 (file)
index 0000000..161d3a2
--- /dev/null
@@ -0,0 +1,24 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Import/Export Content</h2>
+
+       <p>ATutor provides importing and exporting of course content using IMS 1.1.3 or SCORM 1.2 content package specifications. Exported content can be viewed offline, and transferred to other systems. If enabled, students can also export content for offline viewing. See course <a href="properties.php">Properties</a> to learn how to enable content exporting for students.</p>
+
+<h3>Exporting Content</h3>
+       <p>An entire course, a chapter, or a single page of content can be exported as an IMS 1.1.3 or SCORM 1.2 content package. Exported packages are archived into a single file using ZIP compression. All content is exported including the terms and glossary, colours, and code.</p>
+       
+       <p>To export content, select the scope by choosing an option from the <em>What to export</em> menu. Then, using <kbd>Export</kbd> will generate a download through your browser. Optionally, you can choose to export the content directly to the <a href="tile_repository.php">TILE content repository</a> if you have a TILE authoring account.</p>
+       
+<h3>Viewing Exported Content</h3>
+       <p>To view a content package offline that has been exported from ATutor, you will need a IMS 1.1.3 or SCORM 1.2 viewer, or a web browser, and an application to unzip the package. To view the content in a web browser, first extract the contents of the ZIP file into an empty folder on your computer, and then open the file <kbd>index.html</kbd> in your browser.</p>
+
+<h3>Importing Content</h3>
+       <p>To import a content package into ATutor, it must conform to IMS 1.1.3 or SCORM 1.2 content package specifications. </p>
+
+       <p>Before importing, specify where in the course structure the new content is to be placed by using the <em>Import into</em> menu.</p>
+       
+       <p>Select the content package to upload by choosing the file from your local file system, either by typing the path into the <em>Upload a Content Package</em> text field, or by using the <kbd>Browse</kbd> button. You can also import a content package over the Web by entering the URL of the package.</p>
+
+       <p>Using <kbd>Import</kbd> will upload the content into the course at the specified location on the Internet.</p>
+       
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/content_preview.php b/documentation/instructor/content_preview.php
new file mode 100644 (file)
index 0000000..d4bf891
--- /dev/null
@@ -0,0 +1,7 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Previewing Content</h2>
+       <p>The Preview tab displays the content page as it looks with the formatting given.  This is how the content page will appear to a user, with custom HTML, Glossary Terms, Code, and colours.</p>
+               
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/content_properties.php b/documentation/instructor/content_properties.php
new file mode 100644 (file)
index 0000000..3694077
--- /dev/null
@@ -0,0 +1,21 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Properties</h2>
+       <p>In the properties tab, you can move the content page, select a Release Date, enter keywords for easier searching, and specify its related topics.</p>
+
+       <dl>
+               <dt>Move</dt>
+               <dd>In the left column of the Properties screen in the Content Editor choose the 'up arrow' to move the current content <em>Before</em> another item. Choose the 'down arrow' to move the content <em>After</em> that item. Choose the 'plus sign' to make the current content a <em>Child of</em>, or sub-topic, for that item. </dd>
+
+               <dt>Release Date</dt>
+               <dd>The release date specifies when the content page will be visible to students. Content can be scheduled for release by specifying date in the future. Specifying a release date that has past will release the content immediately. The release date of a page affects all of its sub-pages as well, such that a sub-page is released only when the most distant release date of all its parent pages has passed. By default, the Release Date is set as the current date and time.</dd>
+               
+               <dt>Keywords</dt>
+               <dd>Words entered into the Keywords area are given greater emphasis during searching. Therefore they will be placed higher in a list of search results than if there were no keywords. Keywords are also used as Learning Object Metadata when a content package is generated.</dd>
+               
+               <dt>Related Topics</dt>
+               <dd><p>For each content page in the course, it is possible to specify other content pages as being related. Related topics can appear in the side menu, allowing students to quickly jump to a topic. Related topics are cross-refrenced meaning the content page chosen to be related will also be related to the current page.</p>
+               </dd>
+       </dl>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/content_usage.php b/documentation/instructor/content_usage.php
new file mode 100644 (file)
index 0000000..a9ccc60
--- /dev/null
@@ -0,0 +1,9 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Content Usage</h2>
+       <p>Instructors can view <em>Content Usage</em> statistics, or <em>Student Specific Usage</em> data. Content Usage will list the overall number of <em>Visits</em> to each content page, the number of <em>Unique Visits</em>, the <em>Average Duration</em> of each visit, the <em>Total Duration</em> of all visits to each page, as well as the <em>Details</em> of all visits to each page. If enabled, students can also view their own content usage using <em>My Tracker</em>.</p>
+       
+       <p>Use the Reset link to empty the Content Usage data.</p>
+
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/course_email.php b/documentation/instructor/course_email.php
new file mode 100644 (file)
index 0000000..f7c94cd
--- /dev/null
@@ -0,0 +1,13 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Course Email</h2>
+       <p>Using the <em>Course Email</em> option, you can send an email to all assistants (students with privileges), enrolled, un-enrolled, and /or alumni students in your current course. A copy of the email is also sent to your registered email address.</p>
+       <p>The following tags can be added to course emails to customize the message to the recipients. They are replaced with their personal information.</p>
+<ul>
+<li><strong>{AT_FNAME}</strong> Replaced with recipient's first name in the body or subject line.</li>
+<li><strong>{AT_LNAME}</strong> Replaced with recipient's last name in the body or subject line.</li>
+<li><strong>{AT_EMAIL}</strong> Replaced with recipient's email in the body.</li>
+<li><strong>{AT_USER}</strong>  Replaced with recipient's login name in the body.</li>
+</ul>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/creating_courses.php b/documentation/instructor/creating_courses.php
new file mode 100644 (file)
index 0000000..7c50814
--- /dev/null
@@ -0,0 +1,38 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>Creating Courses</h2>\r
+\r
+<p>After logging in, use the <em>Create Course</em> link from My Start Page. Properties set here can be modified through Manage > <a href="properties.php">Properties</a></p>\r
+\r
+<p>Some course properties include:</p>\r
+\r
+       <dl>\r
+               <dt>Description</dt>\r
+               <dd>Enter a meaningful but brief paragraph describing the course, to be displayed under the course name in <em>Browse Courses</em>.</dd>\r
+\r
+               <dt>Export Content</dt>\r
+               <dd>Choose the availability of the "Export Content" link on course content pages.</dd>\r
+\r
+               <dt>Syndicate Announcements</dt>\r
+               <dd>Enable this setting if you wish to make an RSS feed of the course announcements available for display on another website.</dd>\r
+\r
+               <dt>Access</dt>\r
+               <dd>Determines who can have access to the course content - any user, only logged in users, or logged in and enrolled users.</dd>\r
+\r
+               <dt>Release Date</dt>\r
+               <dd>An optional date from when the course can be accessed by non-privileged students.</dd>\r
+\r
+               <dt>End Date</dt>\r
+               <dd>An optional date from when the course can no longer be accessed by non-privileged students.</dd>\r
+\r
+               <dt>Banner</dt>\r
+               <dd>HTML that forms a custom banner or splash screen for the course home page. Appears above the course announcements, if there are any.</dd>\r
+\r
+               <dt>Initial Content</dt>\r
+               <dd>Initialise the course content to be either empty, basic place-holder content, or a restored backup from other courses you own.</dd>\r
+       </dl>\r
+\r
+<p>Enter the necessary information and use the <code>Save</code> button to proceed into the newly created course. </p>\r
+\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/creating_editing_content.php b/documentation/instructor/creating_editing_content.php
new file mode 100644 (file)
index 0000000..4a451ff
--- /dev/null
@@ -0,0 +1,7 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Creating and Editing Content</h2>
+
+       <p>Using the Tabs in the Content Manager, content can be created, its location, keywords, and date properties set, and glossary terms defined.  It can also be previewed and have its accessibility checked. While creating content, save often. Unsaved information is indicated by a red bullet in the corresponding Content Manager tab. When content editing is complete, choose the <kbd>Close after saving</kbd> option, then press <code>Save</code>.</p>
+       
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/creating_questions.php b/documentation/instructor/creating_questions.php
new file mode 100644 (file)
index 0000000..41a4aa9
--- /dev/null
@@ -0,0 +1,32 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Creating Test Questions</h2>
+       <p>Test questions are created in the <a href="question_database.php">Question Database</a>. Options differ depending on the type of question being created. All questions are saved to the Question Database where they can then be added to Tests or Surveys. The following questions are supported:</p>
+       
+       <dl>
+               <dt>Likert</dt>
+               <dd>Likert questions require the respondent to specify their choice based on the scale provided. Keep in mind that Likert questions are not assigned a point value, so if they are included in a randomized test with other questions that do have a point value, they must be included as required question, otherwise test statistics will not be accurate. </dd>
+
+               <dt>Matching (Graphical)</dt>
+               <dd>Matching questions require the respondent to match value pairs. The graphical version creates coloured lines when pairs are created and allows for drag-and-drop interaction.</dd>
+
+               <dt>Matching (Simple)</dt>
+               <dd>Matching questions require the respondent to match value paris. The simple version does not create coloured lines and does not support drag-and-drop interaction.</dd>
+
+               <dt>Multiple Answer</dt>
+               <dd>Multiple answer questions require the respondent to answer a question by selecting two or more correct answers.</dd>
+
+               <dt>Multiple Choice</dt>
+               <dd>Multiple choice questions require the respondent to answer a question by selecting only one correct answer.</dd>
+
+               <dt>Open Ended</dt>
+               <dd>Open ended questions require the respondent to enter text in the specified text area.</dd>
+
+               <dt>Ordering</dt>
+               <dd>Ordering questions require the respondent to correctly assign given items in a particular logical order or rank.</dd>
+
+               <dt>True or False</dt>
+               <dd>True or false questions require the respondent to specify whether or not a given statement is true or false.</dd>
+       </dl>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/creating_restoring.php b/documentation/instructor/creating_restoring.php
new file mode 100644 (file)
index 0000000..f4775cc
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Creating &amp; Restoring Backups</h2>
+       <p>To create a backup of the current course, use the <em>Create</em> link found on the Backups page. All created backups are stored securely on the ATutor server. The space required for the backups does not affect the course's size quota. Once a backup is created, it will be listed on the main Backups page where it can be managed.</p>
+
+       <p>Backups can be restored by selecting a backup and using the <kbd>Restore</kbd> button. The restoration process will present details on what is stored in the backup and allow instructors to select which course material they wish to restore.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/creating_tests_surveys.php b/documentation/instructor/creating_tests_surveys.php
new file mode 100644 (file)
index 0000000..633ea13
--- /dev/null
@@ -0,0 +1,63 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Creating/Editing Tests &amp; Surveys</h2>
+       <p>To begin creating a test, use the <em>Create Test/Survey</em> link. Filling out the information on the Create Test/Survey page will address all the administrative options for a test. Actual questions are added to the test in a separate step.</p>
+
+       <p>Test properties include:</p>
+
+       <dl>
+               <dt>Title (Mandatory field)</dt>
+               <dd>Test title </dd>
+       
+               <dt>Description</dt>
+               <dd>Test description </dd>
+       
+               <dt>Attempts Allowed</dt>
+               <dd>Tests used for evaluation could be set to 1 attempt, while self=tests may be set to Unlimited attempts </dd>
+       
+               <dt>Link from My Courses</dt>
+               <dd>Will display a link to the test on the My Courses page, in the course listing. Students will be made aware that the current test is available before they enter the course. This may be useful for creating a pretest to determine students' level of knowledge before taking a course.</dd>
+       
+               <dt>Anonymous</dt>
+               <dd>Set this to No in most cases, or set it to Yes if you are creating a survey or poll.</dd>
+               <dd><strong>Note: </strong>Please be aware that the instructor can not modify the anonymous option when submissions have been made on a test.</dd>
+
+               <dt>Allow Guest</dt>
+               <dd>Set this if you wish to allow users who are not logged into a course to take the test. In Release Results, set to "Once quiz has been submitted" to allow guest users to see the results of the test after they have completed it. Also see <a href="authenticated_access.php">Authenticated Access</a> for information about guest access to protected and private courses.</dd>
+               
+               <dt>Display</dt>
+               <dd>Controls how test questions are displayed: Either all on one page, or one at a time.</dd>
+
+               <dt>Pass Score</dt>
+               <dd>Define the pass score by points or percentage or no pass score. If the pass score/percentage is define, the pass/fail feedback is displayed on student's test result page and instructor can filter by passed/failed students in test submission statistics page. </dd>
+
+               <dt>Pass feedback</dt>
+               <dd>Displayed in test result page for passed student.</dd>
+
+               <dt>Fail feedback</dt>
+               <dd>Displayed in test result page for failed student.</dd>
+
+               <dt>Release Results</dt>
+               <dd>Defines the availability of test results to students, either once the test has been submitted, once submitted and completely marked, or not at all. In the latter case, the Release Results property can later be changed to <em>Once quiz has been submitted</em> to make results available to students once all submissions have been marked.</dd>
+
+               <dt>Randomized Questions</dt>
+               <dd>Will display the number of questions specified, chosen randomly from the pool of available questions for that test. It is important that either all questions be assigned the same point value, or that those questions with different point values from the others be included as required questions, otherwise tests' "out scores" will differ from student to student. If including Likert questions in a randomized test, they must be included as required questions.</dd>
+       
+               <dt>Start &amp; End Dates</dt>
+               <dd>Define the window of time in which the test will be available to students.  It is possible to define the start date to be in the future, meaning the test will not be available until that date is reached.</dd>
+       
+               <dt>Assign to Groups</dt>
+               <dd>Specifies the groups (Created in the <a href="groups.php">Group Manager</a>) permitted to take this test. By default, tests are available to Everyone in the course if no group is selected.. </dd>
+
+               <dt>Instructions</dt>
+               <dd>Notes that will appear at the top of the test, which might include instructions for taking the test, or include other information relevant to the test.</dd>
+
+               <dd>Specifies the groups (created using the <a href="groups.php">Group Manager</a>) permitted to take this test. By default, tests are available to Everyone in the course.</dd>
+
+       </dl>
+       
+       <p><strong>Surveys</strong> are created in the same way as regular tests, with the exception that no marks are assigned to questions and no results are released, and in some cases it might be preferable to treat submissions as <em>Anonymous</em>.  This can be done by choosing Yes from the <em>Anonymous</em> property setting.</p>
+
+       <p>Once the initial properties have been saved, the test or survey will be listed in the Test/Survey Manager.  From here, one can <em>Edit</em> the test properties,  add <em>Questions</em> to a test, <em>Preview</em> the test questions, view the <em>Submissions</em> received so far, view the test <em>Statistics</em>, or <em>Delete</em> the test.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/delete_course.php b/documentation/instructor/delete_course.php
new file mode 100644 (file)
index 0000000..6923832
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Delete Course</h2>
+       <p>An instructor can delete a course using the <a href="properties.php">Properties</a> manager. Once a course has been deleted from the system, it can not be restored (unless there is a <a href="backups.php">backup</a>). There will be prompts to confirm the action before actual deletion occurs.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/downloading_uploading.php b/documentation/instructor/downloading_uploading.php
new file mode 100644 (file)
index 0000000..f5e5ff4
--- /dev/null
@@ -0,0 +1,10 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Downloading &amp; Uploading Backups</h2>
+       <p>Backups can be downloaded and stored locally by selecting from the list of backups created and using the <kbd>Download</kbd> button. Locally stored backups can be uploaded back into the original course, into a new course, or into another installation of ATutor.</p>
+
+       <p>The backup file itself is a compressed archive in a format specific to ATutor. Backups cannot be used by any other system other than ATutor (see <a href="content_packages.php">Import/Export Content</a> for information about reuseable content). Extracting the backup archive to view and change its contents is strongly discouraged as it may currupt the backup, making it impossible to restore.</p>
+
+       <p>Backups are forwards compatible, but not backwards compatible with older versions of ATutor. That is, backups can be used with all future versions of ATutor, but cannot be used with versions of ATutor older than the version originally used in the backup's creation.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/edit_delete_tests.php b/documentation/instructor/edit_delete_tests.php
new file mode 100644 (file)
index 0000000..055bbbe
--- /dev/null
@@ -0,0 +1,9 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Editing &amp; Deleting Tests</h2>
+
+<p>In the Test/Survey Manager, choose the test who's properties you wish to change and use the <code>Edit</code> button.  This will display a screen like the one for <a href="creating_tests_surveys.php">Creating Tests &amp; Surveys</a>, where the test's properties can be altered and saved.</p>
+
+<p>To delete a Test or Survey, choose it from the Test/Survey Manager and use the <code>Delete</code> button.  Aftering confirming the delete action, the test will be removed.  Note that the questions within the test will not be deleted as they are stored in the <a href="question_database.php">Question Database</a>. </p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/editing_deleting.php b/documentation/instructor/editing_deleting.php
new file mode 100644 (file)
index 0000000..b324f8f
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Editing &amp; Deleting Backups</h2>
+       <p>Selecting a backup and using the <kbd>Delete</kbd> button will delete that backup.</p>
+
+       <p>Use the <kbd>Edit</kbd> button to edit the description of a selected backup. This will not change the backup's contents.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/en/index.php b/documentation/instructor/en/index.php
new file mode 100644 (file)
index 0000000..35fa5ae
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg                    */
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: index.php 5866 2005-12-15 16:16:03Z joel $
+
+header('Location: ../index.php'); // no need for english
+exit;
+?>
\ No newline at end of file
diff --git a/documentation/instructor/enrollment.php b/documentation/instructor/enrollment.php
new file mode 100644 (file)
index 0000000..810f0f3
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+       <h2>Enrollment</h2>
+       <p>The Enrollment list for a particular course determines which of your students have access to the course content and course management tools. Instructors can create, import and export student lists. </p>
+       
+       <p>To administer members of a course, log in as the instructor and select the <em>Enrollment</em> option from the <em>Manage</em> screen.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/enrollment_alumni.php b/documentation/instructor/enrollment_alumni.php
new file mode 100644 (file)
index 0000000..d9806cc
--- /dev/null
@@ -0,0 +1,7 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Alumni</h2>
+
+<p>Instructors can mark students who have completed the course as alumni. Alumni have access to all course content with the exception of tests and surveys. They can particpate in activities to help new students master the content of the course, such as contributing to the forums. Select students from the <em>Enrolled</em> list,  then use <code>Mark Alumni</code> to add the students to the <em>Alumni</em> list.  Re-enrolling or removing alumni can be done from the Alumni tab.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/enrollment_course_list.php b/documentation/instructor/enrollment_course_list.php
new file mode 100644 (file)
index 0000000..3ca47e5
--- /dev/null
@@ -0,0 +1,20 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Course Lists</h2>
+<p>It is possible to enter or import a course enrollment list into your ATutor course. Those on the list can be added to the <code>Enrolled</code> list immediately, or added to the <code>Not Enrolled</code> list and later moved to the Enrolled list when the time comes to give students access to the course. When users are added or moved to the Enrolled list, they are sent an email with instructions on how to access the course.</p>
+
+<h3>Creating a Course List</h3>
+<p>You have the option of manually generating the student list by selecting the <em>Create Course List</em> option. This option is useful if there is only a small number of users to be added to the course. With many students, the <em>Import</em> feature may be a more efficient option.</p>
+
+<h3>Creating a Course Enrollment List for Import</h3>
+<p>To import a class list from your local system into ATutor, create a plain text file with the format <kbd>"firstname", "lastname", "email"</kbd>, with one student per line. This file can be generated from a spreadsheet application, a database, or created manually in a plain text editor.</p>
+
+<h3>Importing Course Enrollment Lists</h3>
+<p>To import a course list (in the file format mentioned above), use the <em>Import Course List</em> link. Choose the course list file on your system by using the <kbd>Browse</kbd> button, and then use the <kbd>Import Course List</kbd> button.</p>
+
+<p>When importing an enrollment list, ATutor will automatically generate login names for each new user based on their first and last names. There is an option to choose a format for this - either separating the username with an underscore or a period. (i.e. J_Smith, or J.Smith).</p>
+
+<h3>Exporting Course Enrollment Lists</h3>
+<p>A course enrollment list can easily be exported from ATutor and is useful for creating a backup or for importing the list into other courses. Choose which subsets of users to export (enrolled students, not enrolled students, and alumni) and use <kbd>Export</kbd> to download the list. The exported list is in the same comma-separated format as that described in <em>Creating a Course Enrollment List for Import</em> above.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/enrollment_privileges.php b/documentation/instructor/enrollment_privileges.php
new file mode 100644 (file)
index 0000000..3ba81a3
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Privileges</h2>
+
+<p>Students who are enrolled in a course can be assigned course administrative privileges. This allows your students to perform actions like managing content, creating and marking tests, managing groups, or moderating forums or the chat. This tool is useful for creating teaching assistants, or for creating multiple instructors for a course.  Select the users you wish to give privileges to, and use the <em>Privileges</em> button.  Then choose which tools you want each student to have access to and use the <em>Save</em> button.</p>
+
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/extracting_zip_archives.php b/documentation/instructor/extracting_zip_archives.php
new file mode 100644 (file)
index 0000000..464f8c5
--- /dev/null
@@ -0,0 +1,9 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Extracting Zip Archives</h2>
+       <p>After uploading a ZIP file to the File Manager, select the <em>Extract Archive</em> icon next to the file name. This will display the contents of the zip file and suggest a directory name in which to unzip the archive. Use the <code>Extract</code> button in the ZIP file viewer to unzip the file into the specified directory.</p>
+
+       <p><strong>Illegal file types</strong> will not be extracted, and file names containing illegal characters will be renamed. The viewer will show illegal file types <span style="text-decoration: line-through;">crossed out</span>, and files with illegal characters pointing ( => ) to the renamed file that will be extracted.</p>
+
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/faq.php b/documentation/instructor/faq.php
new file mode 100644 (file)
index 0000000..e8999e5
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Frequently Asked Questions (FAQs)</h2>
+       <p>If an instructor would like to compile a list of frequently asked questions (and answers) for course members, they may do so by going to the FAQ section of the Manage area. Topics must first be created, and then questions can be created and associated with a particular topic. </p>
+
+       <p>Since version 1.5.2., the FAQ is a <a href="student_tools.php">Student Tool</a> and can therefore be enabled or disabled, and linked from the main menu or from the home page.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/feeds.php b/documentation/instructor/feeds.php
new file mode 100644 (file)
index 0000000..fefd93e
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Syndicated Feeds</h2>
+       <p>Since version 1.5.2, System Administrators are able to add syndicated news feeds to the system, making them available to instructors to use in their courses. When available, instructors can display the news feeds in the side menu of their courses by using the <a href="side_menu.php">Side Menu</a> editor of Student Tools, under Manage section, and selecting a feed from the dropdowns.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/file_manager.php b/documentation/instructor/file_manager.php
new file mode 100644 (file)
index 0000000..ee5389a
--- /dev/null
@@ -0,0 +1,28 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>File Manager</h2>
+       <p>ATutor has a file system used for storing course content resource files, and it is managed with the <em>File Manager</em>. The File Manager allows instructors to include files associated with course content into content pages. The File Manager also allows you to create, edit, move, and delete files. The File Manager should not be confuse with the <a href="..//general/file_storage.php">File Storage</a> area.</p>
+
+       <p>The File Manager can be found in the <em>Manage</em> area, linked from the Content Editor so it can be opened while authoring content pages, or linked throughout the Test Question authoring screens so files can be managed while assembling tests.</p>
+
+
+<h3>Creating Folders</h3>
+       <p>Using the <code>Create Folder</code> button creates a folder for better organizing uploaded files. It is possible to create folders and move files into folders at any time.</p>
+
+<h3>Uploading Files</h3>
+       <p>Uploading files using the <em>File Manager</em> is one way of adding content to your course. After uploading a file, it can be added to a course by using the popup File Manager linked form the <a href="content.php">Content Editor</a> and the <code>Insert</code> button that appears next to each file. This will either create a link to a file, or insert an image into a content page.</p>
+       
+       <p><code>Browse...</code> opens a local file browser window in which to choose the file for upload.</p>
+
+       <p><code>Upload</code> will upload the specified file to the ATutor system. Specify a file by either typing the path and filename in the <kbd>text field</kbd> or by using the <code>Browse...</code> button.</p>
+
+<h3>Creating New Files</h3>
+       <p>The <em>Create a New File</em> area allows for quick creation of a new text or HTML file. If using Text mode, any blank lines will be saved with the file. If using HTML mode, HTML tags will be permitted. Selecting <code>Save</code> will save a new file with the entered information (filename and content) into the ATutor system and return to the File Manager. <code>Cancel</code> will discard the file and return to the File Manager.</p>
+
+<h3>Editing Files</h3>
+       <p>Text or HTML files created using the File Manager, or uploaded from another source, can be edited by selecting the Edit icon next to the file name listed in the File Manager.</p>
+
+<h3>Previewing Files</h3>
+       <p>Use the link on the filename in the File Manager to preview that file. Files that can be viewed online, such as images, text, or html files, will open in a preview window. Files that can not be displayed online, or require a plugin, will prompt you with a download confirmation message. </p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/forums.php b/documentation/instructor/forums.php
new file mode 100644 (file)
index 0000000..2fee3e9
--- /dev/null
@@ -0,0 +1,19 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Forums</h2>
+       <p>A Forum is an area that allows course members to communicate in a structured manner through messages. The forums can be enabled or disabled and linked from the main navigation, the course home page, or displayed as a menu module.  These preferences can be specified in the <a href="student_tools.php">Student Tools</a> section of the Manage area.</p>
+
+       <p>Course instructors and students with forum privileges can manage and mediate the forums by deleting, locking, and sticking threads and messages.</p>
+
+<h3>Creating Forums</h3>
+       <p>To create a new forum, use the <em>Create Forum</em> link in the Forums section of the Manage area and enter a title and optional description. New forums will be accessible to all course students, instructors, and alumni. Forums can also be created for access by <a href="groups.php">Groups</a> only.</p>
+
+<h3>Editing &amp; Deleting Forums</h3>
+       <p>To edit an existing forum, select the forum in the Forums manager and use the <em>Edit</em> button.  Make the necessary changes and then use <em>Save</em> to return to the Forum Manager, or <em>Cancel</em> to return to the Forum Manager without saving any changes.</p>
+
+       <p>To delete an existing forum, select the forum in the Forums manager and use the <em>Delete</em> button. The forum and all threads and messages within it will be deleted.</p>
+
+<h3>Shared Forums</h3>
+       <p>Shared forums are special forums where members of different courses can engage in discussions with one another. The instructors, and students with forum privileges, of each participating course can manage and moderate the shared forum. Shared forums can only be created by an administrator.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/fr/index.php b/documentation/instructor/fr/index.php
new file mode 100644 (file)
index 0000000..c71e41f
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg                    */
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: index.php 5866 2005-12-15 16:16:03Z joel $
+
+$parts = pathinfo($_SERVER['PHP_SELF']);
+
+$dir_parts = explode('/', $parts['dirname']);
+$last_dir_name = end($dir_parts);
+
+header('Location: ../index.php?' . $last_dir_name);
+exit;
+?>
\ No newline at end of file
diff --git a/documentation/instructor/glossary.php b/documentation/instructor/glossary.php
new file mode 100644 (file)
index 0000000..7501fe5
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Glossary</h2>
+       <p>The Glossary lists all course terms, their definitions and related terms. Terms can be added to the glossary by using the <em>Add Glossary Term</em> link in the Glossary Manager, or by adding terms directly into content while it is being created using the <a href="content.php">Content Editor</a>.</p>
+
+       <p>The Glossary is a <a href="student_tools.php">Student Tool</a> and can therefore be enabled or disabled, linked from the main menu, linked from the home page, or displayed as a module in the side menu.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/glossary_terms.php b/documentation/instructor/glossary_terms.php
new file mode 100644 (file)
index 0000000..feee3bb
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Glossary Terms</h2>
+<p>If <em>Terms</em> were specified in the Content tab, they may be defined under the Glossary tab. Enter the definition or explanation for each term specified in the Content. See the Terms section in <a href="content_edit.php">Entering Content</a> for details on how to add glossary terms to your content. </p> 
+       
+<p>It is also possible to relate terms to one another within the glossary by specifying a related term.  This will add a link to the related term beside the glossary item.</p>
+               
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/gradebook.php b/documentation/instructor/gradebook.php
new file mode 100644 (file)
index 0000000..df07f09
--- /dev/null
@@ -0,0 +1,20 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id: 8.4.managing_forums.php 5080 2005-07-06 15:06:11Z heidi $\r
+\r
+require('../common/body_header.inc.php'); ?>\r
+\r
+<h3>Gradebook</h3>\r
+<p>The Gradebook can be used to manage students' marks from ATutor generated tests, from ATutor assignments, or from external tests and assignments. Multiple Tests can be combined into a single Gradebook entry. Custom scales can be defined and used across courses. Gradebook data can be exported for reporting and data analysis.</p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>\r
diff --git a/documentation/instructor/gradebook_add.php b/documentation/instructor/gradebook_add.php
new file mode 100644 (file)
index 0000000..fac4af9
--- /dev/null
@@ -0,0 +1,28 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id: 8.4.managing_forums.php 5080 2005-07-06 15:06:11Z heidi $\r
+\r
+require('../common/body_header.inc.php'); ?>\r
+\r
+<h3>Add ATutor Test/Assignment to Gradebook</h3>\r
+\r
+<dl>\r
+       <dt>Add ATutor Assignment</dt>\r
+       <dd>Assignments that have been created using the ATutor Assignment Manager can be added to the gradebook. Select the <strong>Title</strong> of the assignment from those available, then select the scale to be used. Once an assignment has been added to the gradebook, marks are entered as <strong>External Marks</strong>. Marks may be entered either as a percentage mark or a scale mark. If percentage is used, the gradebook will attempt to convert those percentage marks to a scale mark</dd>\r
+\r
+       <dt>Add ATutor Test</dt>\r
+       <dd>Tests that are created using the ATutor Test & Survey Manager can be added to the gradebook if the test's <strong>Attempts Allowed</strong> property has been set to 1 attempt.   Select the test <strong>Title</strong> from those available, then select the Grade Scale to be used for the test. Additional scales can be created by using the Grade Scales tool. Note that Surveys will not be available to add to the Gradebook. Surveys are technically  tests in the Test & Survey Manager that do not have any "weight" or mark assigned to questions.</dd>\r
+</dl>\r
+\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>\r
diff --git a/documentation/instructor/gradebook_edit_marks.php b/documentation/instructor/gradebook_edit_marks.php
new file mode 100644 (file)
index 0000000..cea0e76
--- /dev/null
@@ -0,0 +1,20 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id: 8.4.managing_forums.php 5080 2005-07-06 15:06:11Z heidi $\r
+\r
+require('../common/body_header.inc.php'); ?>\r
+\r
+<h3>Edit Marks</h3>\r
+<p>Use the Search feature to narrow the data displayed in the table below. The table below can be printed as a report, or the data displayed in it can be exported as a CSV file to be reimported into a spreadsheet or database for archiving or for additional analysis. External marks displayed in the table can be edited directly from within the table by choosing the appropriate <strong>edit</strong> link, editing either marks for a single student, or editing marks for a single test. To edit marks from ATutor based tests, use the <strong>Test & Surveys Manager</strong>. When editing ATutor based marks, be sure to run <a href="gradebook_update.php"><strong>Update ATutor Marks</strong></a> to have the changes take affect in the Gradebook..</p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>\r
diff --git a/documentation/instructor/gradebook_external_marks.php b/documentation/instructor/gradebook_external_marks.php
new file mode 100644 (file)
index 0000000..15ed9f8
--- /dev/null
@@ -0,0 +1,28 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id: 8.4.managing_forums.php 5080 2005-07-06 15:06:11Z heidi $\r
+\r
+require('../common/body_header.inc.php'); ?>\r
+\r
+<h3>External Marks</h3>\r
+\r
+<dl>\r
+       <dt>Export</dt>\r
+       <dd>The Export tool is used to export a course list in a CSV form into which marks can be entered manually, then reimported back into the Gradebook. It can also be used to export marks from the Gradebook to import those marks back into another application such as a spreadsheet, or another database.</dd>\r
+\r
+       <dt>Import</dt>\r
+       <dd>Marks from an external assignment or test can be imported in a Comma Separated Values (CSV) file in the form <em>"firstname", "lastname", "email", "grade"</em> with one student per line. The mark can either be a scale mark such <em>"A"</em> or <em>"Pass"</em>, or a percentage mark such as <em>78%</em>. Select the test or assignment previously defined through <a href="gradebook_add.php"><strong>Add Tests/Assignment</strong></a> The first line of the imported file should contain the field names <em>"First Name, Last Name, Email, Grade" </em> If it is not included the first line will be removed when the marks are imported.</dd>\r
+</dl>\r
+\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>\r
diff --git a/documentation/instructor/gradebook_scales.php b/documentation/instructor/gradebook_scales.php
new file mode 100644 (file)
index 0000000..2b32c31
--- /dev/null
@@ -0,0 +1,20 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id: 8.4.managing_forums.php 5080 2005-07-06 15:06:11Z heidi $\r
+\r
+require('../common/body_header.inc.php'); ?>\r
+\r
+<h3>Gradebook Scales</h3>\r
+<p>ATutor includes a number of predefined, commonly used grade scales, used to convert number grades into some other form, such as a letter grade, or a Pass/Fail grade.  In the Grade Scales submenu choose Add Grade Scale to create your own custom scale(s). You may choose to populate the Grade Scale form with an existing scale, then edit the scale to create a new one. Or, you may create a brand new scale. Once created, new scales become available to you in any of the course you own.</p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>\r
diff --git a/documentation/instructor/gradebook_update.php b/documentation/instructor/gradebook_update.php
new file mode 100644 (file)
index 0000000..1a79820
--- /dev/null
@@ -0,0 +1,29 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id: 8.4.managing_forums.php 5080 2005-07-06 15:06:11Z heidi $\r
+\r
+require('../common/body_header.inc.php'); ?>\r
+\r
+<h3>Update ATutor Marks</h3>\r
+\r
+\r
+<dl>\r
+       <dt>Update ATutor Marks</dt>\r
+       <dd>Marks are imported from ATutor tests, rather than displaying them live from the Test & Surveys Manager. Therefore, when marks are updated in the Test & Surveys Manager, the Gradebook needs to be updated to reimport the modified marks. You may choose to update all ATutor tests at once, or choose only to update a single test at a time. Or, you may choose to update only marks for a single student, on all test or a single test.</dd>\r
+\r
+       <dt>Combine ATutor Tests</dt>\r
+       <dd>Different ATutor generated tests can be combined into a single gradebook entry, if for instance you needed to combine marks from a term test, and marks from a make up test for students who happened to miss the term test. As many tests as required can be combined into a single parent test listed in the <strong>Combine Into</strong>  menu. Select the test to be combined from the <strong>Combined From</strong> select menu, then press the <strong>Combine</strong> button to import the marks from that test.  Be sure to run <strong>Update ATutor Marks</strong> on the <strong>Combined Into</strong> test at least once before combining marks from other tests. When combining marks from multiple tests, should you encounter a conflict such as a mark that already exists for a particular student, you will be given the option to overwrite the old mark with the new one, use the old mark, use the higher mark, or use the lower mark. </dd>\r
+</dl>\r
+\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>\r
diff --git a/documentation/instructor/groups.php b/documentation/instructor/groups.php
new file mode 100644 (file)
index 0000000..e54c338
--- /dev/null
@@ -0,0 +1,25 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Groups</h2>
+       <p>The group area allows an instructor or assistant with Group privileges to create and manage groups of enrolled students within various projects. This may be useful for assigning group-specific tests or assignments, brainstorming, collaborative projects, online discussions and case studies, peer editing or responses, and so on.</p>
+
+       <p>There are two ways to create groups: manually or by using automated tools to generate the groups. To facilitate the creation of multiple sets of groups, groups are collected together by type. An example of a group type may be "Tutorials" or "Project A". This feature lets students belong to different groups across multiple projects.</p>
+       
+       <h3>Create multiple groups automatically</h3>
+               <p>Creating groups automatically allows an instructor to specify the number of groups to create, or the number of students per group, and populate groups accordingly. </p>
+               
+               <p>Enter the group type, group prefix (such as "Tutorial" - the groups will then be named "Tutorial 1", "Tutorial 2",...), and a default description that will be applied to each group. To determine the number of groups that will be created, enter the number of students per group, or the number of groups. Groups will automatically be created accordingly. Check the box beside "Fill groups randomly upon creation" to populate groups evenly at random. Uncheck this box to create the groups, but populate them manually at a later time. Finally, choose which tools will be made avialable to this groups (File Storage, Forum, Blog, Links, etc.) then use the <code>Create</code> button.</p>
+
+
+       <h3>Create a single group manually</h3>
+               <p>It is also possible to create groups manually, one by one. This is a good way of creating groups if you have particular needs in terms of which students work together, and a relatively small class. This method is also good for adding groups to existing projects or types of groups. For example, if groups were created and populated automatically, and then several new students enroll, it's possible to manually add the new students to a new group within an existing project or type. A single group might be created to which students who missed a quiz could be assigned, so they could take a makeup test. A single group might be created with the blog tool enabled, so all students in the class can post to the same blog.</p>
+
+               <p>Enter the type of project, title, and description. Also choose which tools will be made avialable to this groups (File Storage, Forums, Blog, etc.) and use the <code>Create</code> button.</p>
+
+       <h3>Managing Groups</h3>
+
+       <p>From the groups page, it is possible to <code>Edit</code> a group's title, description and tools, or <code>Delete</code> a group entirely.</p>
+
+       <p>To manage the members of a group, select the group and use the <code>Members</code> button. The group members screen displays the course list. All unassigned students can automatically be added to the group by using the <code>Assign Unassigned</code> button, or picked manually and saved using the drop down menus, and then the using <code>Save</code> button.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/index.php b/documentation/instructor/index.php
new file mode 100644 (file)
index 0000000..08e884b
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: index.php 5866 2005-12-15 16:16:03Z joel $
+
+
+require('../index.php');
+?>
\ No newline at end of file
diff --git a/documentation/instructor/introduction.php b/documentation/instructor/introduction.php
new file mode 100644 (file)
index 0000000..7fa0b5d
--- /dev/null
@@ -0,0 +1,9 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Introduction</h2>
+       <p>Welcome to the ATutor Instructor Documentation!</p>
+
+       <p>Most of the course management tools are found in the <em>Manage</em> section and are available to instructors and students with assigned privileges (assistants).</p>
+
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/links.php b/documentation/instructor/links.php
new file mode 100644 (file)
index 0000000..6e2563c
--- /dev/null
@@ -0,0 +1,14 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Links</h2>
+
+       <p>Links to external websites can be added to the course Links area, allowing course members to visit course related information elsewhere on the Web. Both students and instructors can add links by using <em>Suggest Link</em>. Student-submitted links must be approved by the instructor in the Links Manager. Instructors can also add links by using <em>Add Link</em> in the Links Manager.</p>
+
+       <p>The Links section is a <a href="student_tools.php">Student Tool</a> and can therefore be enabled or disabled, linked from the main menu or linked from the home page, and assigned as student privilege.</p>
+
+       <p>The Links section can be selected for <a href="groups.php">Groups</a>. Groups members can add links, without them having to be approved by the Instructor, and either keep them private to the group, and only its members, or make them public, so others not in the group can browse through them.</p>
+
+<h3>Link Categories</h3>
+       <p>It is necessary to create at least one category before adding any links. Use <em>Create Category</em> in the Links Manager to create categories for organising course links. To edit or delete existing categories use the <em>Categories</em> link in the Links Manager. Note that categories that have links associated with them may not be deleted until those links are removed from the category.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/managing_files_folders.php b/documentation/instructor/managing_files_folders.php
new file mode 100644 (file)
index 0000000..e75443e
--- /dev/null
@@ -0,0 +1,13 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Managing Files &amp; Folders</h2>
+
+       <p>It is possible to <em>Rename</em>, <em>Delete</em>, and <em>Move</em> files and folders within the File Manager. Choose a file (or files if mass-deleting or moving to one location) from the File Manager list, then use the appropriate button for the action.</p>
+
+       <p>Renaming a file will change the name of the file.</p>
+
+       <p>Deleting a file deletes all selected files and folders from the ATutor system.  If a folder is being deleted, the files within it will also be deleted. Once the deletion is confirmed, the files can not be undeleted.</p>
+
+       <p>To Move files to a different location, choose a new location from the File Manager tree and use the <code>Move</code> button.  Once the move is confirmed, all selected files will be found in the new directory.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/managing_posts.php b/documentation/instructor/managing_posts.php
new file mode 100644 (file)
index 0000000..92c56be
--- /dev/null
@@ -0,0 +1,29 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id: 8.4.managing_forums.php 5080 2005-07-06 15:06:11Z heidi $\r
+\r
+require('../common/body_header.inc.php'); ?>\r
+\r
+<h3>8.4.1 Managing Posts</h3>\r
+<p>The course instructor and assistants with forum privileges can edit and delete posts. Access to these tools are available when viewing a thread message.</p>\r
+\r
+<dl>\r
+       <dt>Edit</dt>\r
+       <dd>Use the <em>Edit</em> link to edit the title and the body of a post.</dd>\r
+\r
+       <dt>Delete</dt>\r
+       <dd>Use the <em>Delete</em> link to delete a post. Deleting the first post from a thread will delete the entire thread including all replies. A confirmation will be asked prior to each deletion.</dd>\r
+</dl>\r
+\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>\r
diff --git a/documentation/instructor/managing_threads.php b/documentation/instructor/managing_threads.php
new file mode 100644 (file)
index 0000000..3023cbb
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: 8.4.managing_forums.php 5080 2005-07-06 15:06:11Z heidi $
+
+require('../common/body_header.inc.php'); ?>
+
+<h2>8.4 Managing Threads</h2>
+
+<p>As an instructor, it is wise to become familiar with the forum management tools. To access these tools, browse a forum while logged in as an instructor or as an assistant with forum management privileges.</p>
+
+<p>For each thread in a forum, the following actions are available:</p>
+<dl>
+       <dt>Stick Thread</dt>
+       <dd><p>Use the exclamation point icon next to a thread to stick it.  This keeps the specified thread at the top of the forum's thread list and is useful for keeping important information visible to forum users. </p>
+       <p>To unstick a thread, just use the <em>Sticky Thread</em> icon again.</p>
+       <p>Some possible uses of a sticky thread include: course dates, forum rules, contact information, or important course material.</p>
+       </dd>
+
+       <dt>Lock Thread</dt>
+       <dd><p>Use the <em>Lock</em> icon next to the thread title to lock a thread. There are two options for locking a thread - lock posting and reading, and lock posting only. Lock <em>posting and reading</em> closes the thread so that no one can read the contents or post replies. But note that the title of the thread will remain listed in the forum. Lock <em>posting only</em> will let users read the entire thread but not post any replies to it. </p>
+
+       <p>To change the lock preferences or unlock a thread, use the <em>Unlock Thread</em> icon.</p>
+       </dd>
+
+       <dt>Move Thread</dt>
+       <dd>To move a thread, use the <em>Move Thread</em> icon next to the thread title. This will move all posts within the thread to the target forum.</dd>
+
+       <dt>Delete Thread</dt>
+       <dd>To delete a thread, use the <em>Delete Thread</em> icon next to the thread title. This will delete all posts within the thread and cannot be undeleted.</dd>
+</dl>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/pages.inc.php b/documentation/instructor/pages.inc.php
new file mode 100644 (file)
index 0000000..0fe188d
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+       $_pages = array();
+    $_pages['introduction.php']                  = 'Introduction';
+    $_pages['creating_courses.php']                             = 'Creating Courses';
+    $_pages['announcements.php']                 = 'Announcements';
+       $_pages['assignments.php']                                       = 'Assignments';
+    $_pages['backups.php']                       = 'Backups';
+    $_pages['creating_restoring.php']            = 'Creating &amp; Restoring Backups';
+    $_pages['downloading_uploading.php']         = 'Downloading &amp; Uploading Backups';
+    $_pages['editing_deleting.php']              = 'Editing &amp; Deleting Backups';
+    $_pages['chat.php']                          = 'Chat';
+    $_pages['content.php']                       = 'Content';
+    $_pages['creating_editing_content.php']      = 'Creating &amp; Editing Content';
+    $_pages['content_edit.php']                  = 'Edit Content';
+    $_pages['content_properties.php']            = 'Content Properties';
+    $_pages['glossary_terms.php']                = 'Glossary Terms';
+    $_pages['content_preview.php']               = 'Preview';
+    $_pages['accessibility.php']                                = 'Accessibility';
+    $_pages['content_packages.php']              = 'Import/Export Content';
+    $_pages['content_usage.php']                 = 'Content Usage';
+    $_pages['tile_repository.php']               = 'TILE Repository';
+    $_pages['scorm_packages.php']                = 'SCORM Packages';
+    $_pages['course_email.php']                  = 'Course Email';
+    $_pages['enrollment.php']                    = 'Enrollment';
+    $_pages['enrollment_privileges.php']                = 'Privileges';
+    $_pages['enrollment_alumni.php']             = 'Alumni';
+    $_pages['enrollment_course_list.php']        = 'Course Lists';
+    $_pages['file_manager.php']                  = 'File Manager';
+    $_pages['managing_files_folders.php']        = 'Managing Files &amp; Folders';
+    $_pages['extracting_zip_archives.php']       = 'Extracting Zip Archives';
+    $_pages['forums.php']                        = 'Forums';
+    $_pages['managing_threads.php']              = 'Managing Forum Threads';
+    $_pages['managing_posts.php']                               = 'Managing Forum Posts';
+    $_pages['glossary.php']                      = 'Glossary';
+       $_pages['groups.php']                                            = 'Groups';
+    $_pages['links.php']                         = 'Links';
+    $_pages['polls.php']                         = 'Polls';
+    $_pages['properties.php']                    = 'Course Properties';
+    $_pages['authenticated_access.php']          = 'Authenticated Access';
+    $_pages['delete_course.php']                 = 'Delete Course';
+    $_pages['reading_list.php']                                         = 'Reading List';
+    $_pages['statistics.php']                    = 'Statistics';
+    $_pages['student_tools.php']                 = 'Student Tools';
+    $_pages['side_menu.php']                     = 'Side Menu';
+    $_pages['tests_surveys.php']                 = 'Tests &amp; Surveys';
+    $_pages['creating_tests_surveys.php']        = 'Creating Tests &amp; Surveys';
+    $_pages['question_database.php']             = 'Question Database';
+    $_pages['creating_questions.php']                   = 'Creating Questions';
+    $_pages['question_categories.php']           = 'Question Categories';
+    $_pages['edit_delete_tests.php']                    = 'Editing &amp; Deleting Tests';
+    $_pages['preview.php']                                              = 'Previewing Tests';
+       $_pages['add_questions.php']                             = 'Test Questions';
+       $_pages['student_submissions.php']                       = 'Test Submissions';
+    $_pages['test_statistics.php']                              = 'Test Statistics';
+    $_pages['faq.php']                                                  = 'Frequently Asked Questions';
+    $_pages['feeds.php']                                                = 'Syndicated Feeds';
+    $_pages['web_search.php']                                   = 'Web Search';
+    $_pages['gradebook.php']                                    = 'Gradebook';
+    $_pages['gradebook_add.php']                                        = 'Add to Gradebook';
+    $_pages['gradebook_update.php']                                     = 'Update Grades';
+    $_pages['gradebook_external_marks.php']                                     = 'External Marks';
+    $_pages['gradebook_edit_marks.php']                                         = 'Edit Marks';
+    $_pages['gradebook_scales.php']                                     = 'Grade Scales';
+    $_pages['gradebook_add_scales.php']                                         = 'Add Grade Scale';
+
+?>
\ No newline at end of file
diff --git a/documentation/instructor/polls.php b/documentation/instructor/polls.php
new file mode 100644 (file)
index 0000000..dfe6831
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Polls</h2>
+       <p>Polls are useful for quickly gathering course member opinions. Instructors and students with poll privileges can post a question with up to seven choices for answers. Unlike <a href="tests_surveys.php">Tests and Surveys</a>, Polls are not graded. Because Polls is a <a href="student_tools.php">Student Tool</a>, it can be enabled, disabled, and positioned according to the Student Tools preferences. </p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/preview.php b/documentation/instructor/preview.php
new file mode 100644 (file)
index 0000000..d8151de
--- /dev/null
@@ -0,0 +1,7 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>Previewing Tests</h2>\r
+\r
+<p>To preview the questions of a test or survey, choose the test from the Tests/Survey Manager and use the <code>Preview</code> button. The screen displayed shows what the student will see when he/she takes a test.  Though the exception is previewing <strong>randomized tests</strong>, which displays all of the questions assigned to that test rather than showing a random number of them (what the student will see). </p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>\r
diff --git a/documentation/instructor/properties.php b/documentation/instructor/properties.php
new file mode 100644 (file)
index 0000000..a707c65
--- /dev/null
@@ -0,0 +1,45 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Properties</h2>
+       <p>The Properties Manager allows instructors to adjust the visual, functional, and technical details of a course. Properties set during installation can be changed with the Properties Manager. The Properties Manager is also where you <a href="delete_course.php">delete a course</a>. Additional properties are managed by the ATutor system administrator, including upload file size limitations and space limitations for a course. Contact an ATutor administrator if these properties need to be changed.</p>
+
+<dl>
+    <dt>Title</dt>
+    <dd>The course name.</dd>
+
+    <dt>Primary Language</dt>
+    <dd>If a user has not yet chosen a preferred language, ATutor will display in the language selected here.</dd>
+
+    <dt>Description</dt>
+    <dd>An short text description of the course, to display in the Browse Course listing for the course.</dd>
+
+    <dt>Course Directory</dt>
+    <dd>If the ATutor administrator has enabled the "Pretty URL" feature, instructors will see a field to enter a name for the course directory, which gets added to a url while in a course. The course directory may contain numbers, letters, underscores, or dashes. No spaces are allowed. If no course directory is defined, the course ID is used in its place. The Pretty URL feature is enabled to turn conventional URL variables an there values (e.g course=21&user=13) into something more readable (e.g. course/21/user/13)</dd>
+
+
+    <dt>Export Content</dt>
+    <dd>If enabled, students can export course materials as content packages that can be viewed offline. If set to be <code>available  only for top level pages</code>, exporting a top level page also exports all its sub-pages. </dd>
+
+    <dt>Syndicated Announcements</dt>
+    <dd>If enabled, the course's announcements become available as an RSS feed.</dd>
+
+    <dt>Access</dt>
+    <dd>Whether students need to login, and/or enroll, to gain access to a course .</dd>
+
+    <dt>Release Date</dt>
+    <dd>The date the course can be accessed by students.</dd>
+
+    <dt>Banner</dt>
+    <dd>HTML formatted content that appears at the top of the course home page. Create splash screen, or a customized course front page. It is also possible to create a file called banner.txt, and place it in the top directory of a course file manager, that contains HTML to modify the top header area.</dd>
+
+    <dt>Copyright Notice</dt>
+    <dd>Appears in addition to the ATutor copyright notice, to signify the copyright of the content being displayed. Use <code>& copy;</code> (without the space) to create a copyright symbol</dd>
+
+    <dt>Icon</dt>
+    <dd>An 80 pixel by 80 pixel icon displayed with the course listing in MyCourses.</dd>
+
+
+</dl>
+
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/question_categories.php b/documentation/instructor/question_categories.php
new file mode 100644 (file)
index 0000000..36f2419
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Question Categories</h2>
+       <p>Question categories are useful for organizing questions by topic, but also to make it easier to add questions into tests.  When adding questions, it is possible to simply check the box beside the category name which will add all of the questions within it, instead of having to check each question separately. Use the <em>Create Category</em> link to create a category.  It will then appear in the Question Categories manager where it can be Edited and Deleted.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/question_database.php b/documentation/instructor/question_database.php
new file mode 100644 (file)
index 0000000..3e85afd
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Question Database</h2>
+       <p>The <em>Question Database</em> is where course test and survey questions are stored. Questions are created separately so that they may be reused in different tests and surveys.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/reading_list.php b/documentation/instructor/reading_list.php
new file mode 100644 (file)
index 0000000..8e745fa
--- /dev/null
@@ -0,0 +1,12 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Reading List</h2>
+       <p>The reading list area allows instructors and assistants with Reading List privileges to list course resources and schedule when they should be read. </p>
+       
+       <h3>Managing Reading List</h3>
+       <p>A new reading list entry can be added by selecting book, URL, handout, AV, or file from the "Type of Reading" dropdown at the top and using the <code>Create</code> button. If a resource of that type does not already exist, the instructor is prompted to add one. After this is complete, or if resources of that type do exist, the add reading list entry page is displayed. Choose the name of the resource from the dropdown, or follow the <em>Create New</em> link to add a new one. Specify if it is required or optional reading, and add a comment if necessary. It is also possible to specify a "read by" date by entering the start and end reading dates. Use the <code>Save</code> button to create the entry.</p>
+       
+       <h3>Managing Resources</h3>
+       <p>To manage resources, follow the <em>Resources</em> link. Create a new resource by selecting its type from the dropdown at the top and using the <code>Create</code> button. Enter the title, author, year, publisher, ISBN, and comment and use the <code>Save</code> button. To <code>Edit</code> or <code>Delete</code> an entry, choose it from the list and use the appropriate button. </p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/scorm_packages.php b/documentation/instructor/scorm_packages.php
new file mode 100644 (file)
index 0000000..6d76e3d
--- /dev/null
@@ -0,0 +1,24 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>SCORM Packages</h2>
+       <p>The Packages tool, when enabled, allows instructors to include SCORM 1.2 Sharable Content Objects (SCOs) as part of their courses. SCOs remain separated from the course content as complete learning units. SCOs should not be confused with content packages which are loaded into ATutor using the Import/Export tool in the Content Manager.</p>
+       <p><strong>Note:</strong> The ATutor SCORM Run-Time Environment (RTE) that plays SCOs requires users to have Java 1.5 (i.e. JRE 1.5) installed on their computer.</p>
+
+       <p>Use the <em>Packages</em> link from the Manage area to access the following:</p>
+
+       <dl>
+               <dt>Import Package</dt>
+               <dd><p>Upload a SCO from your computer, or enter the URL to a SCO located on the Web to import it into your course.</p></dd>
+
+               <dt>Delete Package</dt>
+               <dd><p>Removes a SCO from a course, and deletes all associated files.</p></dd>
+
+               <dt>Package Setting</dt>
+               <dd>
+                       <p><code>Credit Mode</code> sets the package to credit or no credit.</p>
+
+                       <p><code>Lesson Mode</code> is set to <code>browse</code> if the package is to be available for evaluation, or set to <code>normal</code> as a lesson..</p>
+               </dd>
+       </dl>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/side_menu.php b/documentation/instructor/side_menu.php
new file mode 100644 (file)
index 0000000..21c2def
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Side Menu</h2>
+       <p>Some of the student tools can be accessed through the side menu. Which side menu boxes, and the order in which they will appear, can be controlled by selecting the tool name from the dropdowns, and arrange them in order of preference. Those more likely to be used can be placed at the top of the menu. To remove a menu box, choose the blank option from the selection menus in the side menu editor</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/statistics.php b/documentation/instructor/statistics.php
new file mode 100644 (file)
index 0000000..85238c1
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Statistics</h2>
+       <p>The statistics page displays the number of Members (registered users) and Guests (unregistered users) who have logged into the course. Use the <a href="properties.php">Properties</a> manager to control guest access to the course.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/student_submissions.php b/documentation/instructor/student_submissions.php
new file mode 100644 (file)
index 0000000..e18ef80
--- /dev/null
@@ -0,0 +1,10 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Test Submissions</h2>
+       <p>To view the submissions of a test, choose a test from the Test/Survey Manager and use the <code>Submissions</code> button.  The list of student submissions will be listed, and can be filtered to show all, marked or unmarked tests.</p>
+       
+       <p>Unmarked tests are those requiring instructor input, or those with open-ended questions. Multiple-choice and true-false questions are automatically marked by the Atutor system and Likert questions do not require marking.</p>
+       
+       <p>To view and/or mark test submissions, choose a submission from the list and use the <kbd>View &amp; Mark Test</kbd> button. The test will be displayed with a box beside each question for entering or editing the mark.  Multiple-choice and true-false answers show a red "X" icon beside an answer if the student answered incorrectly, or a green checkmark if he/she was right.  If an answer is incorrect, the correct answer will be shown with a green checkmark after it in brackets. Use <code>Save</code> to enter the marks into the system and return to the submission manager.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/student_tools.php b/documentation/instructor/student_tools.php
new file mode 100644 (file)
index 0000000..d083f0a
--- /dev/null
@@ -0,0 +1,20 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Student Tools</h2>
+       <p>Student Tools is a collection of course features that may be useful for various types of learning activities. Tools include: Forums, Glossary, Site-map, Links, Polls, TILE Repository Search, Tests &amp; Surveys, My Tracker, Export Content, Chat, Directory, Inbox, and Packages. Instructors can decide where these tools will be accessed from - the <em>Main Navigation</em>, and/or <em>Course Home</em>.</p>
+
+       <dl>
+       <dt>Main Navigation</dt>
+       <dd>In the default Atutor theme, the Main Navigation appears as tabs below the title of the course. Student Tools specified to appear here will each have their own tab. Note that other themes may choose to display the Main Navigation differently. </dd>
+
+       <dt>Course Home</dt>
+       <dd>Course Home is the first page viewed when a student enters a course. Student Tools that are selected to appear on the Home page will be displayed with an icon and a label above the course announcements.</dd>
+       </dl>
+
+       <p>If neither <em>Main Navigation</em> or <em>Course Home</em> options are selected, then that Student Tool be "turned off", or not accessible to students. An instructor might choose to turn on Student Tools as they are needed, for example turning on the Tests &amp; Surveys tool when a test is available, or turning on the Chat when an online meeting is going to take place.</p>
+
+       <p>Using the arrows in the <em>Order</em> column will change the ordering of the student tool as it appears in the <em>Main Navigation</em> and on the <em>Course Home</em> page.</p>
+
+       <p>It is also possible to install the <a href="http://www.atutor.ca/atutor/modules/index.php">Student Tools Module</a>, and use it as a place to locate links to the various ATutor tools, leaving the course home page as a splash screen, or as a place to display course announcments. </p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/test_statistics.php b/documentation/instructor/test_statistics.php
new file mode 100644 (file)
index 0000000..dc7f6a9
--- /dev/null
@@ -0,0 +1,9 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>\r
+\r
+<h2>Test Statistics</h2>\r
+\r
+<p>To view a test's statistics, choose the test from the Test/Survey Manager and use the <code>Statistics</code> button.  There are two sets of statistics available for tests.  The first is <em>Question Statistics</em> which shows each question of the test and the number/percentage of students who chose each of the answers. <em>Submission Statistics</em> shows each submission's overall mark and marks given for each test question.  The overall test average is also calculated.</p>\r
+\r
+<p><em>Submission Statistics</em> shows each submission's overall mark and marks given for each test question.  The overall test average is also calculated. The statistics data can be filtered by test's date of taken, all or passed or failed students. The filtered data can be downloaded as CSV file.</p>\r
+\r
+<?php require('../common/body_footer.inc.php'); ?>\r
diff --git a/documentation/instructor/tests_surveys.php b/documentation/instructor/tests_surveys.php
new file mode 100644 (file)
index 0000000..b6924a0
--- /dev/null
@@ -0,0 +1,6 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Tests and Surveys</h2>
+       <p>The instructor, and assistants with test privileges, can create tests and surveys to be administered to enrolled students. There are a variety of options for defining tests like setting the release date, and using randomized questions or group-specific tests. Once a test or survey has been created, add questions to the Question Database, and then add these questions to the new test. </p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/instructor/tile_repository.php b/documentation/instructor/tile_repository.php
new file mode 100644 (file)
index 0000000..c0d1445
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>TILE Repository</h2>
+       <p>Content created in ATutor can be exported to <em>The Inclusive Learning Exchange</em> (TILE) using the <em>Export</em> tool on the Import/Export Content screen. Content can also be imported from the TILE repository by entering a search term into the <em>TILE Repository Search</em>, then using <em>Import</em> next to a listing in the search results.  Use the <em>Preview</em> link next to a search result to open the TILE content browser, or use <em>Download</em> to retrieve the content package from TILE repository. Once downloaded, the retrieved package can be imported into ATutor using the Import/Export Content import tool. </p>
+       
+       <p>Visit the <a href="http://www.inclusivelearning.ca/" target="new">TILE web site</a> for more information about using the repository, and to set up an account on the system.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
\ No newline at end of file
diff --git a/documentation/instructor/web_search.php b/documentation/instructor/web_search.php
new file mode 100644 (file)
index 0000000..688f39f
--- /dev/null
@@ -0,0 +1,8 @@
+<?php require('../common/body_header.inc.php'); $lm = '$LastChangedDate$'; ?>
+
+<h2>Web Search</h2>
+       <p>Since version 1.5.2, course members can use Google to search the web from within an ATutor course.</p>
+
+       <p>The Web Search is a <a href="student_tools.php">Student Tool</a> and can therefore be enabled or disabled, linked from the main menu, linked from the home page, or displayed as a side menu box.</p>
+
+<?php require('../common/body_footer.inc.php'); ?>
diff --git a/documentation/link-out.gif b/documentation/link-out.gif
new file mode 100644 (file)
index 0000000..ecef094
Binary files /dev/null and b/documentation/link-out.gif differ
diff --git a/documentation/styles.css b/documentation/styles.css
new file mode 100644 (file)
index 0000000..3322dcf
--- /dev/null
@@ -0,0 +1,137 @@
+pre {\r
+       font-family: Arial, sans-serif;\r
+}\r
+\r
+body{\r
+       background-color: #FFF;\r
+    font-family: Verdana,Arial,sans-serif;\r
+}\r
+h1,h2,h3,p, table, ul {\r
+       margin: 0 10px\r
+}\r
+h1 {\r
+       color: #FFF;\r
+       border-bottom: 1px dashed #FFF;\r
+       margin-left: -5px;\r
+       padding-left: 15px;\r
+       margin-right: -5px;\r
+       padding-right: 15px;\r
+}\r
+h2{color: #FFF;\r
+       border-bottom: 1px dashed #FFF;\r
+       margin-left: -5px;\r
+       padding-left: 15px;\r
+       margin-right: -5px;\r
+       padding-right: 15px;\r
+}\r
+h3{color: #f0f0f0}\r
+p{padding-bottom:1em}\r
+h2{padding-top: 0.3em}\r
+\r
+/* for the curves */\r
+div.nifty { margin: 10px 2%; background: #9BD1FA; }\r
+b.rtop, b.rbottom{display:block;background: #FFF}\r
+b.rtop b, b.rbottom b{display:block;height: 1px; overflow: hidden; background: #9BD1FA}\r
+b.r1{margin: 0 5px}\r
+b.r2{margin: 0 3px}\r
+b.r3{margin: 0 2px}\r
+b.rtop b.r4, b.rbottom b.r4{margin: 0 1px;height: 2px}\r
+\r
+\r
+a {\r
+       text-decoration: none;\r
+       border-bottom: 1px solid white;\r
+       color: white;\r
+       font-weight: bold;\r
+}\r
+a:hover {\r
+       border-bottom: 0px;\r
+}\r
+td,th {\r
+       font-size: 85%;\r
+}\r
+\r
+kbd {\r
+       padding: 0px 1px 0px 1px;\r
+       border-width: 1px 2px 2px 1px;\r
+       border-style: solid;\r
+       border-color: #edd #baa #baa #eed;\r
+       white-space: pre;\r
+}\r
+\r
+code {\r
+    font-family: Verdana,Arial,sans-serif;\r
+       background-color: #efefef;\r
+       padding: 0px 4px 0px 4px;\r
+       border-width: 1px 1px 1px 1px;\r
+       border-style: solid;\r
+       border-color: #edd #baa #baa #eed;              \r
+}\r
+\r
+\r
+div#toc {\r
+       color: #f0f0f0;\r
+       padding-bottom: 15px;\r
+}\r
+\r
+div#toc ul {\r
+       list-style: none;\r
+}\r
+div#toc li {\r
+       padding-top: 2px;\r
+       padding-bottom: 0px;\r
+}\r
+\r
+ol {\r
+       margin-top: 0px;\r
+}\r
+\r
+ol li {\r
+       padding-bottom: 3px;\r
+}\r
+\r
+dl {\r
+       margin: 0 10px\r
+}\r
+dl dd { \r
+       padding-top: 0px;\r
+       padding-left: 5px;\r
+       margin-left: 5%;\r
+       border-left: 1px solid #f0f0f0;\r
+       margin-bottom: 10px;\r
+} \r
+\r
+acronym {\r
+       cursor: help;\r
+}\r
+\r
+a[href*="http"] {\r
+       padding-right: 8px;\r
+       background-image: url('link-out.gif');\r
+       background-repeat: no-repeat;\r
+       background-position: right 4px;\r
+       margin-right: 2px;\r
+}\r
+\r
+div#nav-links {\r
+       margin-left: 20px;\r
+       margin-right: 20px;\r
+       margin-bottom: 20px;\r
+}\r
+\r
+div#nav-links a {\r
+       color: black;\r
+       text-decoration: none;\r
+       border-bottom: 1px solid;\r
+}\r
+\r
+pre {\r
+       font-family: Courier, monospace;\r
+       background-color: #EEEEFF;\r
+       padding: 5px;\r
+       margin-left: 20px;\r
+       color:#761596;\r
+    margin-top: 0px;\r
+       width: 50%;\r
+       font-size: smaller;\r
+}
\ No newline at end of file
diff --git a/editor/add_content.php b/editor/add_content.php
new file mode 100644 (file)
index 0000000..d5790d2
--- /dev/null
@@ -0,0 +1,17 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+require('./edit_content.php');\r
+\r
+?>
\ No newline at end of file
diff --git a/editor/add_forum.php b/editor/add_forum.php
new file mode 100644 (file)
index 0000000..28a29af
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_FORUMS);
+
+if ($_POST['cancel']) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'tools/forums/index.php');
+       exit;
+}
+
+if ($_POST['add_forum'] && (authenticate(AT_PRIV_FORUMS, AT_PRIV_RETURN))) {
+       if ($_POST['title'] == '') {
+               $msg->addError(array('EMPTY_FIELDS', _AT('title')));
+       } else {
+               $_POST['title'] = validate_length($_POST['title'], 60);
+       }
+
+       if (!$msg->containsErrors()) {
+               require(AT_INCLUDE_PATH.'lib/forums.inc.php');
+               add_forum($_POST);
+               
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: '.AT_BASE_HREF.'tools/forums/index.php');
+               exit;
+       }
+}
+
+$onload = 'document.form.title.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="add_forum" value="true">
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('create_forum'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php echo _AT('title'); ?></label><br />
+               <input type="text" name="title" size="40" id="title" />
+       </div>
+       <div class="row">
+               <label for="body"><?php echo _AT('description'); ?></label><br />
+               <textarea name="body" cols="45" rows="2" id="body" wrap="wrap"></textarea>
+       </div>
+       <div class="row">
+               <label for="edit"><?php echo _AT('allow_editing'); ?></label><br />
+               <input type="text" name="edit" size="3" id="edit" value="<?php echo intval($row['mins_to_edit']); ?>" /> <?php echo _AT('in_minutes'); ?>
+       </div>
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" /> 
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/editor/add_news.php b/editor/add_news.php
new file mode 100644 (file)
index 0000000..34b0ec0
--- /dev/null
@@ -0,0 +1,148 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/tinymce.inc.php');
+
+authenticate(AT_PRIV_ANNOUNCEMENTS);
+
+if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+       $content_base_href = 'get.php/';
+} else {
+       $content_base_href = 'content/' . $_SESSION['course_id'] . '/';
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'tools/news/index.php');
+       exit;
+} 
+
+if ((!$_POST['setvisual'] && $_POST['settext']) || !$_GET['setvisual']){
+       $onload = 'document.form.title.focus();';
+}
+
+if (isset($_POST['add_news'])&& isset($_POST['submit'])) {
+       $_POST['formatting'] = intval($_POST['formatting']);
+       $_POST['title'] = trim($_POST['title']);
+       $_POST['body_text'] = trim($_POST['body_text']);
+       
+       $missing_fields = array();
+
+       if (!$_POST['body_text']) {
+               $missing_fields[] = _AT('body');
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       if (!$msg->containsErrors() && (!isset($_POST['setvisual']) || isset($_POST['submit']))) {
+
+               $_POST['formatting']  = intval($_POST['formatting']);
+               $_POST['title']  = $addslashes($_POST['title']);
+               $_POST['body_text']  = $addslashes($_POST['body_text']);
+
+               //The following checks if title length exceed 100, defined by DB structure
+               $_POST['title'] = validate_length($_POST['title'], 100);
+
+               $sql    = "INSERT INTO ".TABLE_PREFIX."news VALUES (NULL, $_SESSION[course_id], $_SESSION[member_id], NOW(), $_POST[formatting], '$_POST[title]', '$_POST[body_text]')";
+               mysql_query($sql, $db);
+       
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+
+               /* update announcement RSS: */
+               if (file_exists(AT_CONTENT_DIR . 'feeds/' . $_SESSION['course_id'] . '/RSS1.0.xml')) {
+                       @unlink(AT_CONTENT_DIR . 'feeds/' . $_SESSION['course_id'] . '/RSS1.0.xml');
+               }
+               if (file_exists(AT_CONTENT_DIR . 'feeds/' . $_SESSION['course_id'] . '/RSS2.0.xml')) {
+                       @unlink(AT_CONTENT_DIR . 'feeds/' . $_SESSION['course_id'] . '/RSS2.0.xml');
+               }
+
+               header('Location: '.AT_BASE_HREF.'tools/news/index.php');
+               exit;
+       }
+}
+
+if (!isset($_REQUEST['setvisual']) && !isset($_REQUEST['settext'])) {
+       if ($_SESSION['prefs']['PREF_CONTENT_EDITOR'] == 1) {
+               $_POST['formatting'] = 1;
+               $_REQUEST['settext'] = 0;
+               $_REQUEST['setvisual'] = 0;
+
+       } else if ($_SESSION['prefs']['PREF_CONTENT_EDITOR'] == 2) {
+               $_POST['formatting'] = 1;
+               $_POST['settext'] = 0;
+               $_POST['setvisual'] = 1;
+
+       } else { // else if == 0
+               $_POST['formatting'] = 0;
+               $_REQUEST['settext'] = 0;
+               $_REQUEST['setvisual'] = 0;
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if (($_POST['setvisual'] && !$_POST['settext']) || $_GET['setvisual']) {
+       load_editor();
+}
+$msg->printErrors();
+
+?>
+       <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+       <input type="hidden" name="add_news" value="true" />
+
+       <div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('add_announcement'); ?></legend>
+               <div class="row">
+                       <label for="title"><?php echo _AT('title'); ?></label><br />
+                       <input type="text" name="title" size="40" id="title" value="<?php echo $_POST['title']; ?>" />
+               </div>
+
+               <div class="row">
+                       <?php echo _AT('formatting'); ?><br />
+                       <input type="radio" name="formatting" value="0" id="text" <?php if ($_POST['formatting'] == 0) { echo 'checked="checked"'; } ?> onclick="javascript: document.form.setvisual.disabled=true;" <?php if ($_POST['setvisual'] && !$_POST['settext']) { echo 'disabled="disabled"'; } ?> />
+
+                       <label for="text"><?php echo _AT('plain_text'); ?></label>
+                       <input type="radio" name="formatting" value="1" id="html" <?php if ($_POST['formatting'] == 1 || $_POST['setvisual']) { echo 'checked="checked"'; } ?> onclick="javascript: document.form.setvisual.disabled=false;"/>
+
+                       <label for="html"><?php echo _AT('html'); ?></label>
+                       <?php   //Button for enabling/disabling visual editor
+                               if (($_POST['setvisual'] && !$_POST['settext']) || $_GET['setvisual']){
+                                       echo '<input type="hidden" name="setvisual" value="'.$_POST['setvisual'].'" />';
+                                       echo '<input type="submit" name="settext" value="'._AT('switch_text').'" />';
+                               } else {
+                                       echo '<input type="submit" name="setvisual" value="'._AT('switch_visual').'"  ';
+                                       if ($_POST['formatting']==0) { echo 'disabled="disabled"'; }
+                                       echo '/>';
+                               }
+                       ?>
+               </div>
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="body_text"><?php echo _AT('body'); ?></label><br />
+                       <textarea name="body_text" cols="55" rows="15" id="body_text"><?php echo $_POST['body_text']; ?></textarea>
+               </div>
+               
+               <div class="row buttons">
+                       <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+                       <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?> " />
+               </div>
+       </fieldset>
+       </div>
+       </form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/editor/delete_content.php b/editor/delete_content.php
new file mode 100644 (file)
index 0000000..2a9053f
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+if (isset($_POST['submit_yes'])) {
+
+       $_POST['cid'] = intval($_POST['cid']);
+
+       $result = $contentManager->deleteContent($_POST['cid']);
+
+       unset($_SESSION['s_cid']);
+       unset($_SESSION['from_cid']);
+               
+       $msg->addFeedback('CONTENT_DELETED');
+       header('Location: '.AT_BASE_HREF.'tools/content/index.php');
+       exit;
+} else if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'tools/content/index.php');
+       exit;
+}
+
+$_GET['cid'] = intval($_REQUEST['cid']);
+
+$path  = $contentManager->getContentPath($cid);
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if ($_GET['cid'] == 0) {
+       $msg->printErrors('ID_ZERO');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+$children = $contentManager->getContent($_GET['cid']);
+
+$hidden_vars['cid'] = $_GET['cid'];
+
+if (is_array($children) && (count($children)>0) ) {
+       $msg->addConfirm('SUB_CONTENT_DELETE', $hidden_vars);
+       $msg->addConfirm('GLOSSARY_REMAINS', $hidden_vars);
+} else {
+       $msg->addConfirm('GLOSSARY_REMAINS', $hidden_vars);
+}
+       
+$sql = "SELECT * from ".TABLE_PREFIX."content WHERE content_id = '$hidden_vars[cid]'";
+$result = mysql_query($sql, $db);
+while ($row = mysql_fetch_assoc($result)){
+       $title = $row['title'];
+}
+
+$msg->addConfirm(array('DELETE', $title),  $hidden_vars);
+$msg->printConfirm();
+       
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/editor/delete_forum.php b/editor/delete_forum.php
new file mode 100644 (file)
index 0000000..102cc5f
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_FORUMS);
+
+require (AT_INCLUDE_PATH.'lib/forums.inc.php');
+
+if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'tools/forums/index.php');
+       exit;
+} else if (isset($_POST['submit_yes'])) {
+       $_POST['fid'] = intval($_POST['fid']);
+
+       // check if this forum is shared:
+       // (if this forum is shared, then we do not want to delete it.)
+       if (!is_shared_forum($_POST['fid']) && valid_forum_user($_POST['fid'])) {
+               delete_forum($_POST['fid']);
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       } else {
+               $msg->addError('FORUM_NO_DEL_SHARE');
+       }
+       
+       header('Location: '.AT_BASE_HREF.'tools/forums/index.php');
+       exit;
+}
+
+$_section[0][0] = _AT('discussions');
+$_section[0][1] = 'discussions/';
+$_section[1][0] = _AT('forums');
+$_section[1][1] = 'forum/list.php';
+$_section[2][0] = _AT('delete_forum');
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+
+$_GET['fid'] = intval($_GET['fid']); 
+
+$row = get_forum($_GET['fid'], $_SESSION['course_id']);
+
+if (!is_array($row)) {
+       $msg->addError('FORUM_NOT_ADDED');
+} else { ?>
+       <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
+       <input type="hidden" name="delete_forum" value="true">
+       <input type="hidden" name="fid" value="<?php echo $_GET['fid']; ?>">
+               
+       <?php
+       $hidden_vars['delete_forum'] = TRUE;
+       $hidden_vars['fid'] = $_GET['fid'];
+                       
+       $confirm = array('DELETE_FORUM', AT_print($row['title'], 'forums.title'));
+       $msg->addConfirm($confirm, $hidden_vars);
+       $msg->printConfirm();
+}
+
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/editor/delete_news.php b/editor/delete_news.php
new file mode 100644 (file)
index 0000000..b0b7832
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_ANNOUNCEMENTS);
+
+if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'tools/news/index.php');
+       exit;
+} else if (isset($_POST['submit_yes'])) {
+       $_POST['form_news_id'] = intval($_POST['form_news_id']);
+
+       $sql = "DELETE FROM ".TABLE_PREFIX."news WHERE news_id=$_POST[form_news_id] AND course_id=$_SESSION[course_id]";
+       $result = mysql_query($sql, $db);
+       
+       /* update announcement RSS: */
+       if (file_exists(AT_CONTENT_DIR . 'feeds/' . $_SESSION['course_id'] . '/RSS1.0.xml')) {
+               @unlink(AT_CONTENT_DIR . 'feeds/' . $_SESSION['course_id'] . '/RSS1.0.xml');
+       }
+       if (file_exists(AT_CONTENT_DIR . 'feeds/' . $_SESSION['course_id'] . '/RSS2.0.xml')) {
+               @unlink(AT_CONTENT_DIR . 'feeds/' . $_SESSION['course_id'] . '/RSS2.0.xml');
+       }
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: '.AT_BASE_HREF.'tools/news/index.php');
+       exit;
+}
+
+$_section[0][0] = _AT('delete_announcement');
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+       $_GET['aid'] = intval($_GET['aid']); 
+
+       $sql = "SELECT * FROM ".TABLE_PREFIX."news WHERE news_id=$_GET[aid] AND course_id=$_SESSION[course_id]";
+
+       $result = mysql_query($sql,$db);
+       if (mysql_num_rows($result) == 0) {
+               $msg->printErrors('ITEM_NOT_FOUND');
+       } else {
+               $row = mysql_fetch_assoc($result);
+
+               $hidden_vars['delete_news']  = TRUE;
+               $hidden_vars['form_news_id'] = $row['news_id'];
+               
+               $confirm = array('DELETE_NEWS', AT_print($row['title'], 'news.title'));
+               $msg->addConfirm($confirm, $hidden_vars);
+               
+               $msg->printConfirm();
+       }
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+
+?>
\ No newline at end of file
diff --git a/editor/edit_content.php b/editor/edit_content.php
new file mode 100644 (file)
index 0000000..c0337bd
--- /dev/null
@@ -0,0 +1,313 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+
+$get_related_glossary = true;
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/tinymce.inc.php');
+
+$cid = intval($_REQUEST['cid']);
+
+if ($_POST) {
+       $do_check = TRUE;
+} else {
+       $do_check = FALSE;
+}
+
+require(AT_INCLUDE_PATH.'lib/editor_tab_functions.inc.php');
+
+       
+
+if ($_POST['close'] || $_GET['close']) {
+       if ($_GET['close']) {
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       } else {
+               $msg->addFeedback('CLOSED');
+               if ($cid == 0) {
+                       header('Location: '.AT_BASE_HREF.'tools/content/index.php');
+                       exit;
+               }
+       }
+       
+       if ($_REQUEST['cid'] == 0) {
+               header('Location: '.$_base_path.'content.php?cid='.intval($_REQUEST['new_pid']));
+               exit;
+       }
+       header('Location: '.$_base_path.url_rewrite('content.php?cid='.intval($_REQUEST['cid'])));
+       exit;
+}
+       
+$tabs = get_tabs();    
+$num_tabs = count($tabs);
+for ($i=0; $i < $num_tabs; $i++) {
+       if (isset($_POST['button_'.$i]) && ($_POST['button_'.$i] != -1)) { 
+               $current_tab = $i;
+               $_POST['current_tab'] = $i;
+               break;
+       }
+}
+
+if (isset($_POST['submit_file'])) {
+       paste_from_file();
+} else if (isset($_POST['submit']) && ($_POST['submit'] != 'submit1')) {
+       /* we're saving. redirects if successful. */
+       save_changes(true);
+}
+if (isset($_GET['tab'])) {
+       $current_tab = intval($_GET['tab']);
+}
+
+if (!isset($current_tab) && isset($_POST['button_1']) && ($_POST['button_1'] == -1) && !isset($_POST['submit'])) {
+       $current_tab = 1;
+} else if (!isset($current_tab) && (($_POST['desc_submit'] != '') || ($_POST['reverse'] != ''))) {
+       $current_tab = 4;  /* after clicking 'make decisions' on accessibility tab */
+} else if (!isset($current_tab)) {
+       $current_tab = 0;
+}
+
+if ($cid) {
+       $_section[0][0] = _AT('edit_content');
+} else {
+       $_section[0][0] = _AT('add_content');
+}
+
+if ($cid) {
+       $result = $contentManager->getContentPage($cid);
+
+       if (!($content_row = @mysql_fetch_assoc($result))) {
+               require(AT_INCLUDE_PATH.'header.inc.php');
+               $msg->printErrors('PAGE_NOT_FOUND');
+               require (AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+
+       $path   = $contentManager->getContentPath($cid);
+
+       if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+               $course_base_href = 'get.php/';
+       } else {
+               $course_base_href = 'content/' . $_SESSION['course_id'] . '/';
+       }
+
+       if ($content_row['content_path']) {
+               $content_base_href .= $content_row['content_path'].'/';
+       }
+} else {
+       if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+               $content_base_href = 'get.php/';
+       } else {
+               $content_base_href = 'content/' . $_SESSION['course_id'] . '/';
+       }
+}
+
+if ($current_tab == 4) {
+       /* kludge for issue #1626: */
+       /* fixes the base href for the AChecker tab. */
+       $course_base_href = '';
+       $content_base_href = '';
+}
+
+if ($current_tab == 0) {
+       if (!isset($_REQUEST['setvisual']) && !isset($_REQUEST['settext'])) {
+               if ($_SESSION['prefs']['PREF_CONTENT_EDITOR'] == 1) {
+                       $_POST['formatting'] = 1;
+                       $_REQUEST['settext'] = 0;
+                       $_REQUEST['setvisual'] = 0;
+
+               } else if ($_SESSION['prefs']['PREF_CONTENT_EDITOR'] == 2) {
+                       $_POST['formatting'] = 1;
+                       $_POST['settext'] = 0;
+                       $_POST['setvisual'] = 1;
+
+               } else { // else if == 0
+                       $_POST['formatting'] = 0;
+                       $_REQUEST['settext'] = 0;
+                       $_REQUEST['setvisual'] = 0;
+               }
+       }
+       if ((!$_POST['setvisual'] && $_POST['settext']) || !$_GET['setvisual']){
+               $onload = ' document.form.ctitle.focus();';
+       }
+}
+
+// initialize buttons, texts, radio buttons for editor
+if ($current_tab == 0) 
+{
+       $onload="on_load()";
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if ($current_tab == 0) 
+{
+       load_editor(false, "none");
+}
+
+$cid = intval($_REQUEST['cid']);
+$pid = intval($_REQUEST['pid']);
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>?cid=<?php echo $cid; ?>" method="post" name="form" enctype="multipart/form-data">
+<?php
+
+       if ($cid) {
+               //$content_row = sql_quote($content_row);
+               if (isset($_POST['current_tab'])) {
+                       //$changes_made = check_for_changes($content_row);
+               } else {
+                       $changes_made = array();
+
+                       $_POST['formatting'] = $content_row['formatting'];
+                       $_POST['head'] = $content_row['head'];
+                       $_POST['use_customized_head'] = $content_row['use_customized_head'];
+                       $_POST['title']      = $content_row['title'];
+                       $_POST['body_text']  = $content_row['text'];
+                       $_POST['keywords']   = $content_row['keywords'];
+
+                       $_POST['day']   = substr($content_row['release_date'], 8, 2);
+                       $_POST['month'] = substr($content_row['release_date'], 5, 2);
+                       $_POST['year']  = substr($content_row['release_date'], 0, 4);
+                       $_POST['hour']  = substr($content_row['release_date'], 11, 2);
+                       $_POST['minute']= substr($content_row['release_date'], 14, 2);
+
+                       $_POST['ordering'] = $_POST['new_ordering'] = $content_row['ordering'];
+                       $_POST['related'] = $contentManager->getRelatedContent($cid);
+
+                       $_POST['pid'] = $pid = $_POST['new_pid'] = $content_row['content_parent_id'];
+
+                       $_POST['related_term'] = $glossary_ids_related;
+               }
+       } else {
+               $cid = 0;
+               if (!isset($_POST['current_tab'])) {
+                       $_POST['day']  = date('d');
+                       $_POST['month']  = date('m');
+                       $_POST['year'] = date('Y');
+                       $_POST['hour'] = date('H');
+                       $_POST['minute']  = 0;
+
+                       if (isset($_GET['pid'])) {
+                               $pid = intval($_GET['pid']);
+                               $_POST['pid'] = 0;
+                               $_POST['new_pid'] = $pid;
+                               $_POST['ordering'] = count($contentManager->getContent(0))+1;
+                               $_POST['new_ordering'] = count($contentManager->getContent($pid))+1;
+                       } else {
+                               $_POST['pid'] = $_POST['new_pid'] = 0;
+                               $_POST['ordering'] = $_POST['new_ordering'] = count($contentManager->getContent($pid))+1;
+                       }
+                       $pid = 0;
+               }
+               //$changes_made = check_for_changes($content_row);
+       }
+
+
+       echo '<input type="hidden" name="cid" value="'.$cid.'" />';
+       echo '<input type="hidden" name="title" value="'.htmlspecialchars($stripslashes($_POST['title'])).'" />';
+       if ($current_tab != 0) {
+               echo '<input type="hidden" name="body_text" value="'.htmlspecialchars($stripslashes($_POST['body_text'])).'" />';
+               echo '<input type="hidden" name="head" value="'.htmlspecialchars($stripslashes($_POST['head'])).'" />';
+               echo '<input type="hidden" name="use_customized_head" value="'.$_POST['use_customized_head'].'" />';
+               echo '<input type="hidden" name="displayhead" value="'.$_POST['displayhead'].'" />';
+               echo '<input type="hidden" name="setvisual" value="'.$_POST['setvisual'].'" />';
+               echo '<input type="hidden" name="settext" value="'.$_POST['settext'].'" />';            
+               echo '<input type="hidden" name="formatting" value="'.$_POST['formatting'].'" />';
+       }
+       if ($current_tab != 1) {
+               echo '<input type="hidden" name="new_ordering" value="'.$_POST['new_ordering'].'" />';
+               echo '<input type="hidden" name="new_pid" value="'.$_POST['new_pid'].'" />';
+       }
+
+       echo '<input type="hidden" name="ordering" value="'.$_POST['ordering'].'" />';
+       echo  '<input type="hidden" name="pid" value="'.$pid.'" />';
+
+       echo '<input type="hidden" name="day" value="'.$_POST['day'].'" />';
+       echo '<input type="hidden" name="month" value="'.$_POST['month'].'" />';
+       echo '<input type="hidden" name="year" value="'.$_POST['year'].'" />';
+       echo '<input type="hidden" name="hour" value="'.$_POST['hour'].'" />';
+       echo '<input type="hidden" name="minute" value="'.$_POST['minute'].'" />';
+
+       echo '<input type="hidden" name="current_tab" value="'.$current_tab.'" />';
+
+       if (is_array($_POST['related']) && ($current_tab != 1)) {
+               foreach($_POST['related'] as $r_id) {
+                       echo '<input type="hidden" name="related[]" value="'.$r_id.'" />';
+               }
+       }
+
+       echo '<input type="hidden" name="keywords" value="'.htmlspecialchars(stripslashes($_POST['keywords'])).'" />';
+
+       /* get glossary terms */
+       $matches = find_terms(stripslashes($_POST['body_text']));
+       $num_terms = count($matches[0]);
+       $matches = $matches[0];
+       $word = str_replace(array('[?]', '[/?]'), '', $matches);
+
+       if (is_array($word)) {
+               /* update $_POST['glossary_defs'] with any new/changed terms */
+               for($i=0; $i<$num_terms; $i++) {
+                       $word[$i] = urlencode($word[$i]);
+                       if (!isset($_POST['glossary_defs'][$word[$i]])) {
+                               $_POST['glossary_defs'][$word[$i]] = $glossary[$word[$i]];
+                       }
+               }
+       }
+
+       if (is_array($_POST['glossary_defs']) && ($current_tab != 2)) {
+               foreach($_POST['glossary_defs'] as $w => $d) {
+                       /* this term still exists in the content */
+                       if (!in_array($w, $word)) {
+                               unset($_POST['glossary_defs'][$w]);
+                               continue;
+                       }
+                       echo '<input type="hidden" name="glossary_defs['.$w.']" value="'.htmlspecialchars(stripslashes($d)).'" />';
+               }
+               if (isset($_POST['related_term'])) {
+                       foreach($_POST['related_term'] as $w => $d) {
+                               echo '<input type="hidden" name="related_term['.$w.']" value="'.$d.'" />';
+                       }
+               }
+       }
+
+       if ($do_check) {
+               $changes_made = check_for_changes($content_row);
+       }
+
+?>
+<div align="center">
+       <?php output_tabs($current_tab, $changes_made); ?>
+</div>
+<div class="input-form" style="width: 95%">
+
+       <?php if ($changes_made): ?>
+               <div class="unsaved">
+                       <span style="color:red;"><?php echo _AT('save_changes_unsaved'); ?></span> 
+                               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" title="<?php echo _AT('save_changes'); ?> alt-s" accesskey="s" style="border: 1px solid red;" /> 
+                               <input type="submit" name="close" class="button green" value="<?php echo _AT('close'); ?>" />  <input type="checkbox" id="close" name="save_n_close" value="1" <?php if ($_SESSION['save_n_close']) { echo 'checked="checked"'; } ?> />
+                               <label for="close"><?php echo _AT('close_after_saving'); ?></label>
+               </div>
+
+       <?php else: ?>
+               <div class="saved">
+                       <?php //if ($cid) { echo _AT('save_changes_saved'); } ?> <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" title="<?php echo _AT('save_changes'); ?> alt-s" accesskey="s" /> <input type="submit" name="close" value="<?php echo _AT('close'); ?>" /> <input type="checkbox" style="border:0px;" id="close" name="save_n_close" value="1" <?php if ($_SESSION['save_n_close']) { echo 'checked="checked"'; } ?> /><label for="close"><?php echo _AT('close_after_saving'); ?></label>
+               </div>
+       <?php endif; ?>
+
+       <?php include(AT_INCLUDE_PATH.'html/editor_tabs/'.$tabs[$current_tab][1]); ?>
+
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/editor/edit_forum.php b/editor/edit_forum.php
new file mode 100644 (file)
index 0000000..5fe7287
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_FORUMS);
+
+require (AT_INCLUDE_PATH.'lib/forums.inc.php');
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'tools/forums/index.php');
+       exit;
+} else if (isset($_POST['edit_forum'])) {
+       $_POST['fid'] = intval($_POST['fid']);
+
+       if ($_POST['title'] == '') {
+               $msg->addError(array('EMPTY_FIELDS', _AT('title')));
+       } else {
+               $_POST['title'] = validate_length($_POST['title'], 60);
+       }
+
+       if (!$msg->containsErrors()) {
+               if (!is_shared_forum($_POST['fid'])) {
+                       edit_forum($_POST);
+                       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               } else {
+                       $msg->addError('FORUM_NO_EDIT_SHARE');
+               }
+               
+               header('Location: '.AT_BASE_HREF.'tools/forums/index.php');
+               exit;
+       }
+}
+
+$onload = 'document.form.title.focus();';
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$fid = intval($_REQUEST['fid']);
+
+if (!isset($_POST['submit'])) {
+       $row = get_forum($fid, $_SESSION['course_id']);
+       if (!is_array($row)) {
+               $msg->addError('FORUM_NOT_FOUND');
+               $msg->printALL();
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+} else {
+       $row['description'] = $_POST['body'];
+       $row['mins_to_edit'] = $_POST['edit'];
+}
+
+$msg->printErrors();
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="edit_forum" value="true">
+<input type="hidden" name="fid" value="<?php echo $fid; ?>">
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('edit_forum'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php echo _AT('title'); ?></label><br />
+               <input type="text" name="title" size="50" id="title" value="<?php echo htmlspecialchars(stripslashes($row['title'])); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="body"><?php echo _AT('description'); ?></label><br />
+               <textarea name="body" cols="45" rows="2" id="body" wrap="wrap"><?php echo $row['description']; ?></textarea>
+       </div>
+
+       <div class="row">
+               <label for="edit"><?php echo _AT('allow_editing'); ?></label><br />
+               <input type="text" name="edit" size="3" id="edit" value="<?php echo intval($row['mins_to_edit']); ?>" /> <?php echo _AT('in_minutes'); ?>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" /> 
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/editor/edit_news.php b/editor/edit_news.php
new file mode 100644 (file)
index 0000000..97208f1
--- /dev/null
@@ -0,0 +1,156 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/tinymce.inc.php');
+
+authenticate(AT_PRIV_ANNOUNCEMENTS);
+
+if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+       $content_base_href = 'get.php/';
+} else {
+       $content_base_href = 'content/' . $_SESSION['course_id'] . '/';
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'tools/news/index.php');
+       exit;
+} else if ($_POST['edit_news']) {
+       $_POST['title'] = trim($_POST['title']);
+       $_POST['body_text']  = trim($_POST['body_text']);
+       $_POST['aid']   = intval($_POST['aid']);
+       $_POST['formatting']    = intval($_POST['formatting']);
+
+       if (($_POST['title'] == '') && ($_POST['body_text'] == '')) {
+               $msg->addErros('ANN_BOTH_EMPTY');
+       }
+
+       if (!$msg->containsErrors() && isset($_POST['submit'])) {
+               $_POST['title']  = $addslashes($_POST['title']);
+               $_POST['body_text']  = $addslashes($_POST['body_text']);
+               //Check if the title has exceeded the DB length, 100
+               $_POST['title'] = validate_length($_POST['title'], 100);
+
+               $sql = "UPDATE ".TABLE_PREFIX."news SET title='$_POST[title]', body='$_POST[body_text]', formatting=$_POST[formatting], date=date WHERE news_id=$_POST[aid] AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql,$db);
+
+               /* update announcement RSS: */
+               if (file_exists(AT_CONTENT_DIR . 'feeds/' . $_SESSION['course_id'] . '/RSS1.0.xml')) {
+                       @unlink(AT_CONTENT_DIR . 'feeds/' . $_SESSION['course_id'] . '/RSS1.0.xml');
+               }
+               if (file_exists(AT_CONTENT_DIR . 'feeds/' . $_SESSION['course_id'] . '/RSS2.0.xml')) {
+                       @unlink(AT_CONTENT_DIR . 'feeds/' . $_SESSION['course_id'] . '/RSS2.0.xml');
+               }
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: '.AT_BASE_HREF.'tools/news/index.php');
+               exit;
+       }
+}
+
+if (!isset($_REQUEST['setvisual']) && !isset($_REQUEST['settext'])) {
+       if ($_SESSION['prefs']['PREF_CONTENT_EDITOR'] == 1) {
+               $_POST['formatting'] = 1;
+               $_REQUEST['settext'] = 0;
+               $_REQUEST['setvisual'] = 0;
+
+       } else if ($_SESSION['prefs']['PREF_CONTENT_EDITOR'] == 2) {
+               $_POST['formatting'] = 1;
+               $_POST['settext'] = 0;
+               $_POST['setvisual'] = 1;
+
+       } else { // else if == 0
+               $_POST['formatting'] = 0;
+               $_REQUEST['settext'] = 0;
+               $_REQUEST['setvisual'] = 0;
+       }
+}
+
+if ((!$_POST['setvisual'] && $_POST['settext']) || !$_GET['setvisual']){
+       $onload = 'document.form.title.focus();';
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if (($_POST['setvisual'] && !$_POST['settext']) || $_GET['setvisual']) {
+       load_editor();
+}
+
+if (isset($_GET['aid'])) {
+       $aid = intval($_GET['aid']);
+} else {
+       $aid = intval($_POST['aid']);
+}
+
+if ($aid == 0) {
+       $msg->printErrors('ITEM_NOT_FOUND');
+       require (AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+$sql = "SELECT * FROM ".TABLE_PREFIX."news WHERE news_id=$aid AND course_id=$_SESSION[course_id]";
+$result = mysql_query($sql,$db);
+if (!($row = mysql_fetch_array($result))) {
+       $msg->printErrors('ITEM_NOT_FOUND');
+       require (AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+$_POST['formatting'] = intval($row['formatting']);
+
+?>
+
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="edit_news" value="true">
+<input type="hidden" name="aid" value="<?php echo $row['news_id']; ?>">
+
+<div class="input-form">
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php echo _AT('title'); ?></label><br />
+               <input type="text" name="title" id="title" value="<?php echo htmlspecialchars(stripslashes($row['title'])); ?>" size="40">
+       </div>
+
+       <div class="row">
+               <?php echo _AT('formatting'); ?><br />
+               <input type="radio" name="formatting" value="0" id="text" <?php if ($_POST['formatting'] === 0) { echo 'checked="checked"'; } ?> onclick="javascript: document.form.setvisual.disabled=true;" <?php if ($_POST['setvisual'] && !$_POST['settext']) { echo 'disabled="disabled"'; } ?> /><label for="text"><?php echo _AT('plain_text'); ?></label>,
+
+               <input type="radio" name="formatting" value="1" id="html" <?php if ($_POST['formatting'] == 1 || $_POST['setvisual']) { echo 'checked="checked"'; } ?> onclick="javascript: document.form.setvisual.disabled=false;"  /> <label for="html"><?php echo _AT('html'); ?></label>
+               <?php
+                       if (($_POST['setvisual'] && !$_POST['settext']) || $_GET['setvisual']){
+                               echo '<input type="hidden" name="setvisual" value="'.$_POST['setvisual'].'" />';
+                               echo '<input type="submit" name="settext"   value="'._AT('switch_text').'" />';
+                       } else {
+                               echo '<input type="submit" name="setvisual" value="'._AT('switch_visual').'" ';
+                               if ($_POST['formatting']==0) { echo 'disabled="disabled"'; }
+                               echo '/>';
+                       } 
+               ?>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="body_text"><?php echo _AT('body'); ?></label><br />
+               <textarea name="body_text" cols="55" rows="15" id="body_text" wrap="wrap"><?php echo $row['body']; ?></textarea>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?> " />
+       </div>
+
+
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/editor/edit_post.php b/editor/edit_post.php
new file mode 100644 (file)
index 0000000..66a480b
--- /dev/null
@@ -0,0 +1,149 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+require(AT_INCLUDE_PATH.'lib/forums.inc.php');
+
+$fid = intval($_REQUEST['fid']);
+
+if (isset($_GET['pid'])) {
+       $pid = intval($_GET['pid']);
+} else {
+       $pid = intval($_POST['pid']);
+}
+if (!$pid || !$fid || !valid_forum_user($fid)) {
+       $msg->addError('ITEM_NOT_FOUND');
+       header('Location: ../forum/list.php');
+       exit;
+}
+
+$sql = "SELECT *, UNIX_TIMESTAMP(date) AS udate FROM ".TABLE_PREFIX."forums_threads WHERE post_id=$pid";
+$result = mysql_query($sql,$db);
+if (!($post_row = mysql_fetch_assoc($result))) {
+       $msg->addError('ITEM_NOT_FOUND');
+       header('Location: '.url_rewrite('forum/list.php', AT_PRETTY_URL_IS_HEADER));
+       exit;
+}
+
+$forum_info = get_forum($fid, $_SESSION['course_id']);
+
+$expiry = $post_row['udate'] + $forum_info['mins_to_edit'] * 60;
+
+// check if we're either a) an assistant or, b) own this post and within the time allowed:
+if (!(     authenticate(AT_PRIV_FORUMS, AT_PRIV_RETURN) 
+               || ($post_row['member_id'] == $_SESSION['member_id'] && ($expiry > time() || isset($_POST['edit_post']) ) )
+         ) 
+   ) {
+       $msg->addError('POST_EDIT_EXPIRE');
+       header('Location: '.url_rewrite('/forum/list.php', AT_PRETTY_URL_IS_HEADER));
+       exit;
+}
+
+if ($_POST['cancel']) {
+       $msg->addFeedback('CANCELLED');
+       Header('Location: '.url_rewrite('/forum/view.php?fid='.$_POST['fid'].SEP.'pid='.$_POST['pid'], AT_PRETTY_URL_IS_HEADER));
+       exit;
+}
+
+if ($_POST['edit_post']) {
+       $missing_fields = array();
+
+       $_POST['subject']       = str_replace('<', '&lt;', trim($_POST['subject']));
+       $_POST['body']          = str_replace('<', '&lt;', trim($_POST['body']));
+       $_POST['pid']           = intval($_POST['pid']);
+
+       $_POST['subject']  = $addslashes($_POST['subject']);
+       //If subject > 100,then chop subject
+       $_POST['subject'] = validate_length($_POST['subject'], 100);
+
+       $_POST['body']  = $addslashes($_POST['body']);
+
+       if ($_POST['subject'] == '')  {
+               $missing_fields[] = _AT('subject');
+       }
+
+       if ($_POST['body'] == '') {
+               $missing_fields[] = _AT('body');
+       }
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+       if (!$msg->containsErrors()) {
+               $sql = "UPDATE ".TABLE_PREFIX."forums_threads SET subject='$_POST[subject]', body='$_POST[body]', last_comment=last_comment, date=date WHERE post_id=$_POST[pid]";
+               $result = mysql_query($sql,$db);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               if ($_POST['ppid'] == 0) {
+                       $_POST['ppid'] = $_POST['pid'];
+               }
+               header('Location: '.url_rewrite('forum/view.php?fid='.$_POST['fid'].SEP.'pid='.$_POST['ppid'], AT_PRETTY_URL_IS_HEADER));
+               exit;
+       }
+}
+
+$_pages['forum/index.php?fid='.$fid]['title']    = $forum_info['title'];
+$_pages['forum/index.php?fid='.$fid]['parent']   = 'forum/list.php';
+$_pages['forum/index.php?fid='.$fid]['children'] = array('forum/new_thread.php?fid='.$fid);
+
+$_pages['forum/new_thread.php?fid='.$fid]['title_var'] = 'new_thread';
+$_pages['forum/new_thread.php?fid='.$fid]['parent']    = 'forum/index.php?fid='.$fid;
+
+$_pages['forum/view.php']['title']  = $post_row['subject'];
+$_pages['forum/view.php']['parent'] = 'forum/index.php?fid='.$fid;
+
+$_pages['editor/edit_post.php']['title_var'] = 'edit_post';
+$_pages['editor/edit_post.php']['parent']    = 'forum/index.php?fid='.$fid;
+$_pages['editor/edit_post.php']['children']  = array();
+
+
+$onload = 'document.form.subject.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="edit_post" value="true" />
+<input type="hidden" name="pid" value="<?php echo $pid; ?>" />
+<input type="hidden" name="ppid" value="<?php echo $post_row['parent_id']; ?>" />
+<input type="hidden" name="fid" value="<?php echo $post_row['forum_id']; ?>" />
+
+<div class="input-form">
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="subject"><?php echo _AT('subject'); ?></label><br />
+               <input type="text" maxlength="45" name="subject" size="36" value="<?php echo stripslashes(htmlspecialchars($post_row['subject'])); ?>" id="subject" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="body"><?php echo _AT('body'); ?></label>
+               <textarea cols="65" name="body" rows="10" id="body"><?php echo $post_row['body']; ?></textarea>
+       </div>
+       
+       <div class="row">
+               <small class="spacer"><br />&middot; <?php echo _AT('forum_links'); ?><br />
+               &middot; <?php echo _AT('forum_email_links'); ?><br />
+               &middot; <?php echo _AT('forum_html_disabled'); ?></small>
+       </div>
+
+       <div class="row buttons">
+               <input name="submit" type="submit" value="  <?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value=" <?php echo _AT('cancel'); ?> " />
+       </div>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/editor/index.php b/editor/index.php
new file mode 100644 (file)
index 0000000..aa03357
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+$_section[0][0] = 'Blank Page';
+
+require (AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+blank page
+<?php
+require (AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/editor/view_item.php b/editor/view_item.php
new file mode 100644 (file)
index 0000000..5ed4f7b
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+       define('AT_INCLUDE_PATH', '../include/');
+       require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+       $url = urldecode($_GET['url']);
+
+       @readfile($_GET['url']);
+
+?>
\ No newline at end of file
diff --git a/enroll.php b/enroll.php
new file mode 100644 (file)
index 0000000..76da267
--- /dev/null
@@ -0,0 +1,163 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                             */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', 'include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+$course = intval($_GET['course']);
+if ($course == 0) {
+       $course = intval($_POST['form_course_id']);
+}
+
+if ($course == 0) {
+       exit;
+}
+
+$sql   = "SELECT access, member_id FROM ".TABLE_PREFIX."courses WHERE course_id=$course";
+$result = mysql_query($sql, $db);
+$course_info = mysql_fetch_array($result);
+
+if ($_POST['submit']) {
+       $_SESSION['enroll'] = AT_ENROLL_YES;
+       $_POST['form_course_id'] = intval($_POST['form_course_id']);
+
+       if ($course_info[0] == 'private') {
+               $sql    = "INSERT INTO ".TABLE_PREFIX."course_enrollment VALUES ($_SESSION[member_id], $_POST[form_course_id], 'n', 0, '"._AT('student')."', 0)";
+               $result = mysql_query($sql, $db);
+
+               // send the email thing. if needed
+
+               $sql    = "SELECT notify, member_id FROM ".TABLE_PREFIX."courses WHERE course_id=$_POST[form_course_id] AND notify=1";
+               $result = mysql_query($sql, $db);
+               if ($row = mysql_fetch_array($result)) {
+                       // notify is enabled. get the email
+                       $sql    = "SELECT email, first_name, last_name FROM ".TABLE_PREFIX."members WHERE member_id=$row[member_id]";
+                       $result = mysql_query($sql, $db);
+                       $row    = mysql_fetch_assoc($result);
+
+                       $to_email = $row['email'];
+
+                       $tmp_message  = $row['first_name'].' '.$row['last_name'].",\n\n";
+                       $tmp_message .= _AT('enrol_msg', $system_courses[$_POST['form_course_id']]['title']);
+                       $tmp_message .= _AT('enrol_login');
+                       if ($to_email != '') {
+
+                               require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+
+                               $mail = new ATutorMailer;
+
+                               $mail->From     = $_config['contact_email'];
+                               $mail->AddAddress($to_email);
+                               $mail->Subject = _AT('course_enrolment');
+                               $mail->Body    = $tmp_message;
+
+                               if(!$mail->Send()) {
+                                       //echo 'There was an error sending the message';
+                                  $msg->printErrors('SENDING_ERROR');
+                                  exit;
+                               }
+                               unset($mail);
+                       }
+               }
+       } else {
+               // public or protected
+               $sql    = "INSERT INTO ".TABLE_PREFIX."course_enrollment VALUES ($_SESSION[member_id], $_POST[form_course_id], 'y', 0, '"._AT('student')."', 0)";
+               $result = mysql_query($sql, $db);
+       }
+}
+
+if ($_SESSION['valid_user']) {
+
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."course_enrollment WHERE member_id=$_SESSION[member_id] AND course_id=$course";
+       $result = mysql_query($sql, $db);
+       $row    = mysql_fetch_array($result);
+
+       if (($course_info[0] == 'public') || ($course_info[0] == 'protected')) {
+               if ($row != '') {
+               
+                       $feedback = array('NOW_ENROLLED', $system_courses[$course]['title']);
+                       $msg->addFeedback($feedback);
+                       header("Location:index.php");
+               } else if ($course_info[1] != $_SESSION['member_id']) {
+
+                       require(AT_INCLUDE_PATH.'header.inc.php'); ?>
+
+                       <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+                       <input type="hidden" name="form_course_id" value="<?php echo $course; ?>">
+                       <div class="input-form">
+                               <div class="row">
+                                       <p><?php  echo _AT('use_enrol_button'); ?></p>
+                               </div>
+
+                               <div class="row buttons">
+                                       <input type="submit" name="submit" value="<?php echo _AT('enroll_me'); ?>" />
+                               </div>
+                       </div>
+                       </form>
+<?php
+               } else {
+                       // we own this course!
+                       $msg->printErrors('ALREADY_OWNED');
+               }
+       } else { // private
+
+               require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+               if ((!$_POST['submit']) && ($row == '')) {
+
+                       $msg->printInfos('PRIVATE_ENROL'); ?>
+
+                       <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+                       <input type="hidden" name="form_course_id" value="<?php echo $course; ?>">
+                       <input type="submit" name="submit" class="button" value="<?php echo _AT('request_enrollment'); ?>">
+                       </form>
+<?php
+
+               } else if ($_POST['submit']) {
+                       $msg->printFeedbacks('APPROVAL_PENDING');
+               } else if ($course_info[1] != $_SESSION['member_id'] ){
+                        // request has already been made
+                        $msg->printErrors('ALREADY_ENROLED');
+               } else {
+                       $msg->printErrors('ALREADY_OWNED');
+               }
+       }
+
+} else {
+       require(AT_INCLUDE_PATH.'header.inc.php'); 
+       $msg->printErrors('LOGIN_ENROL');       
+       ?>
+       <div class="input-form">
+               <div class="row">
+                       <h3><?php echo _AT('login'); ?></h3>
+                       <p><a href="login.php?course=<?php echo $_SESSION[course_id]; ?>"><?php echo _AT('login_into_atutor'); ?></a></p>
+               </div>
+       </div>
+
+       <form action="registration.php" method="get">
+       <div class="input-form">
+               <div class="row">
+                       <h3><?php echo _AT('new_user');?></h3>
+                       <p><?php echo _AT('registration_text'); ?></p>
+               </div>
+               <div class="row buttons">
+                       <input type="submit" name="register" value="<?php echo _AT('register'); ?>" class="button" />
+               </div>
+       </div>
+       </form>
+
+<?php
+}
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?> 
\ No newline at end of file
diff --git a/exestyles.css b/exestyles.css
new file mode 100644 (file)
index 0000000..1b033f6
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+===========================================================================
+eXe
+Copyright 2007. eXelearning.
+style sheet for default theme
+see: http://exelearning.org/Creating_a_new_Style for more info on how
+to modify this style for your needs.
+===========================================================================
+*/
+
+#content-text {
+   margin: 10px 20px 10px 20px;
+   padding: 10px;
+   color:#4d4d4d;
+   background: #E0DFD8;
+   border:thin solid grey;
+}
+
+
+a {
+ color: #FF6600;
+}
+
+a:hover {
+ color: #B34700;
+}
+
+/* --- Styles for the node/page titles --- */
+
+p#nodeTitle { 
+   color: #4d4d4d;
+   font-size: 32px;
+   letter-spacing: -1px;
+   text-align:left;
+   padding-right: 30px;
+}
+
+div#nodeDecoration {
+   padding: 2px;
+   border-bottom:0px;
+   text-align:right;
+}
+
+
+/* --- iDevice Styles -- */
+
+
+.emphasis0 {
+    padding-bottom: 20px;
+}
+
+
+.emphasis1 {
+   background-color: #FFF;
+   border-bottom: 1px solid #9d9d9d;
+   background-image:url(top_left_corner.gif); /* The left curve */
+   background-position:top left;
+   background-repeat:no-repeat;
+   margin-bottom: 30px;
+   text-align:left;
+}
+
+
+.iDevice p, .iDevice div.block {
+   padding-left: 0px;
+   line-height: 115% 
+   text-align:left;
+}
+
+
+.iDevice li {
+       list-style-position: outside;
+}
+
+.iDeviceTitle {
+   color: #568D14;
+   font-size: 24px;
+   font-weight:bold;
+   letter-spacing:-1px;
+   background: #FFF; 
+   padding-bottom: 0px;
+   padding-right: 10px;
+   margin-bottom: 0px;
+   background-image:url(top_right_corner.gif);
+   background-position:top right;
+   background-repeat:no-repeat;
+   top: 0;
+} 
+
+.emphasis0 .iDeviceTitle {
+   color: #568D14;
+   font-size: 24px;
+   font-weight:bold;
+   letter-spacing:-1px;
+   vertical-align: top;
+   background: transparent; 
+   padding-bottom: 4px;
+   padding-right: 10px;
+   margin-bottom: 0px;
+   background-image:none;
+   background-position:top right;
+   background-repeat:no-repeat;
+ }
+
+.iDevice_icon {
+   margin-top: 0px;
+   margin-left: 10px;
+   padding-right: 10px;
+   top: 0;
+}
+
+.iDevice_inner {
+   color:#4d4d4d;
+   background-color:#f2f2ef;
+   padding: 10px;
+   margin: 10px;
+   margin-top: 12px;
+   padding-top: 10px;
+   background-image:none;
+}
+
+.emphasis0 .iDevice_inner {
+   color:#4d4d4d;
+   background-color:transparent;
+   padding: 10px;
+   margin: 10px;
+   margin-top: 12px;
+   padding-top: 10px;
+}
+
+/* styles for iDevices with Feedback and form buttons */
+
+input.feedbackbutton {
+       background: #DBE992;
+}
+
+p.reading_feedback {
+   border: 1px dashed #ADADAD;
+   background-color: #FFF;
+}
+
+
+/* styles for image with text iDevice */
+
+.image_text { 
+       border: 1px solid #9D9D9D;
+       background: transparent;
+       padding: 4px;
+        margin: 0px 20px 4px 4px;
+}
+
+/* override definition on "fieldset#shortcuts" in themes style.css */
+
+fieldset#shortcuts {
+       float: right;
+       background-color: #FEFDEF;
+       border: 1pt solid #B8AE9C;
+       margin: 0pt 20pt 5pt 5pt;
+       padding-right: 10pt;
+       padding-bottom: 5pt;
+       padding-left: 10pt;
+}
+
diff --git a/export.php b/export.php
new file mode 100644 (file)
index 0000000..8979cc9
--- /dev/null
@@ -0,0 +1,95 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', './include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       header('Location: '.$_base_href.'tools/ims/ims_export.php?cid=' . intval($_POST['cid']));\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+if (!isset($_main_menu)) {\r
+       $_main_menu = $contentManager->getContent();\r
+}\r
+\r
+function print_menu_sections(&$menu, $parent_content_id = 0, $depth = 0, $ordering = '') {\r
+       $my_children = $menu[$parent_content_id];\r
+       $cid = $_GET['cid'];\r
+\r
+       if (!is_array($my_children)) {\r
+               return;\r
+       }\r
+       foreach ($my_children as $children) {\r
+               echo '<option value="'.$children['content_id'].'"';\r
+               if ($cid == $children['content_id']) {\r
+                       echo ' selected="selected"';\r
+               }\r
+               echo '>';\r
+               echo str_pad('', $depth, '-') . ' ';\r
+               if ($parent_content_id == 0) {\r
+                       $new_ordering = $children['ordering'];\r
+                       echo $children['ordering'];\r
+               } else {\r
+                       $new_ordering = $ordering.'.'.$children['ordering'];\r
+                       echo $ordering . '.'. $children['ordering'];\r
+               }\r
+               echo ' '.$children['title'].'</option>';\r
+\r
+               print_menu_sections($menu, $children['content_id'], $depth+1, $new_ordering);\r
+       }\r
+}\r
+\r
+       if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && ($_SESSION['packaging'] == 'none')) {\r
+               echo '<p>'._AT('content_packaging_disabled').'</p>';\r
+               require (AT_INCLUDE_PATH.'footer.inc.php'); \r
+               exit;\r
+       } else if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && ($_SESSION['packaging'] == 'top')) {\r
+               $_main_menu = array($_main_menu[0]);\r
+       }\r
+?>\r
+\r
+\r
+<form method="post" action="<?php $_SERVER['PHP_SELF']?>">\r
+<div class="input-form">\r
+       <div class="row">\r
+               <h3><?php echo _AT('export_content'); ?></h3>\r
+               <p><?php echo _AT('export_content_info'); ?></p>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <label for="select_cid"><?php echo _AT('export_content_package_what'); ?></label><br />\r
+               <select name="cid" id="select_cid">\r
+                       <option value="0"><?php echo _AT('export_entire_course_or_chap'); ?></option>\r
+                       <option>--------------------------</option>\r
+                       <?php\r
+                               print_menu_sections($_main_menu);\r
+                       ?>\r
+               </select>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('export'); ?>" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/faq/add_question.php b/faq/add_question.php
new file mode 100644 (file)
index 0000000..ee1b71c
--- /dev/null
@@ -0,0 +1,111 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_FAQ);
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index_instructor.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $_POST['question'] = trim($_POST['question']);
+       $_POST['answer'] = trim($_POST['answer']);
+
+       $missing_fields = array();
+       
+       if (!$_POST['question']) {
+               $missing_fields[] = _AT('question');
+       }
+
+       if (!$_POST['answer']) {
+               $missing_fields[] = _AT('answer');
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+
+       if (!$msg->containsErrors()) {
+               $_POST['question'] = $addslashes($_POST['question']);
+               $_POST['answer']   = $addslashes($_POST['answer']);
+               $_POST['topic_id'] = intval($_POST['topic_id']);
+               //These will truncate the content of the length to 240 as defined in the db.
+               $_POST['question'] = validate_length($_POST['question'], 250);
+               $_POST['answer'] = validate_length($_POST['answer'], 250);
+
+               // check that this topic_id belongs to this course:
+               $sql    = "SELECT topic_id FROM ".TABLE_PREFIX."faq_topics WHERE topic_id=$_POST[topic_id] AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $db);
+               if ($row = mysql_fetch_assoc($result)) {
+                       $sql    = "INSERT INTO ".TABLE_PREFIX."faq_entries VALUES (NULL, $_POST[topic_id], NOW(), 1, '$_POST[question]', '$_POST[answer]')";
+                       $result = mysql_query($sql,$db);
+               }
+               
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: index_instructor.php');
+               exit;
+       }
+}
+
+$onload = 'document.form.topic.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+       $sql    = "SELECT name, topic_id FROM ".TABLE_PREFIX."faq_topics WHERE course_id=$_SESSION[course_id] ORDER BY name";
+       $result = mysql_query($sql, $db);
+       $num_topics = mysql_num_rows($result);
+       if (!$num_topics) {
+               $msg->printErrors('NO_FAQ_TOPICS');
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('add_question'); ?></legend>
+       <div class="row">
+
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="topic"><?php  echo _AT('topic'); ?></label><br />
+               <select name="topic_id" id="topic">
+                       <?php while ($row = mysql_fetch_assoc($result)): ?>
+                               <option value="<?php echo $row['topic_id']; ?>"<?php if (isset($_POST['topic_id']) && ($row['topic_id'] == $_POST['topic_id'])) { echo ' selected="selected"'; } ?>><?php echo htmlspecialchars($row['name']); ?></option>
+                       <?php endwhile; ?>
+               </select>
+       </div>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="question"><?php  echo _AT('question'); ?></label><br />
+               <input type="text" name="question" size="50" id="question" value="<?php if (isset($_POST['question'])) echo $stripslashes($_POST['question']);  ?>" />
+
+       </div>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="answer"><?php  echo _AT('answer'); ?></label><br />
+               <textarea name="answer" cols="45" rows="3" id="answer" style="width:90%;"><?php if (isset ($_POST['answer'])) echo $stripslashes($_POST['answer']);  ?></textarea>
+       </div>
+
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/faq/add_topic.php b/faq/add_topic.php
new file mode 100644 (file)
index 0000000..1931251
--- /dev/null
@@ -0,0 +1,65 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_FAQ);
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index_instructor.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       if (trim($_POST['name']) == '') {
+               $msg->addError('NAME_EMPTY');
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['name'] = $addslashes($_POST['name']);
+               //This will truncate the content of the length to 240 as defined in the db.
+               $_POST['name'] = validate_length($_POST['name'], 250);
+
+               $sql    = "INSERT INTO ".TABLE_PREFIX."faq_topics VALUES (NULL, $_SESSION[course_id], '$_POST[name]')";
+               $result = mysql_query($sql,$db);
+               
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: index_instructor.php');
+               exit;
+       }
+}
+
+$onload = 'document.form.name.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('add_topic'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="name"><?php  echo _AT('name'); ?></label><br />
+               <input type="text" name="name" size="50" id="name" value="<?php if (isset($_POST['name'])) echo $stripslashes($_POST['name']);  ?>" />
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/faq/delete_question.php b/faq/delete_question.php
new file mode 100644 (file)
index 0000000..e4d655d
--- /dev/null
@@ -0,0 +1,61 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+authenticate(AT_PRIV_FAQ);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       Header('Location: index_instructor.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       $_POST['id'] = intval($_POST['id']);\r
+       $_POST['topic_id'] = intval($_POST['topic_id']);\r
+\r
+       // check that this topic_id belongs to this course:\r
+       $sql    = "SELECT topic_id FROM ".TABLE_PREFIX."faq_topics WHERE topic_id=$_POST[topic_id] AND course_id=$_SESSION[course_id]";\r
+       $result = mysql_query($sql, $db);\r
+       if ($row = mysql_fetch_assoc($result)) {\r
+               $sql = "DELETE FROM ".TABLE_PREFIX."faq_entries WHERE entry_id=$_POST[id] AND topic_id=$_POST[topic_id]";\r
+               $result = mysql_query($sql, $db);\r
+       }\r
+\r
+       $msg->addFeedback('QUESTION_DELETED');\r
+       header('Location: index_instructor.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+\r
+$_GET['id'] = intval($_GET['id']); \r
+\r
+$sql = "SELECT question, topic_id FROM ".TABLE_PREFIX."faq_entries WHERE entry_id=$_GET[id]";\r
+\r
+$result = mysql_query($sql,$db);\r
+if ($row = mysql_fetch_assoc($result)) {\r
+       $hidden_vars['topic_id'] = $row['topic_id'];\r
+       $hidden_vars['id'] = $_GET['id'];\r
+\r
+       $confirm = array('DELETE_FAQ_QUESTION', $row['question']);\r
+       $msg->addConfirm($confirm, $hidden_vars);\r
+       $msg->printConfirm();\r
+} else {\r
+       $msg->addError('ITEM_NOT_FOUND');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+\r
+?>
\ No newline at end of file
diff --git a/faq/delete_topic.php b/faq/delete_topic.php
new file mode 100644 (file)
index 0000000..a9c5499
--- /dev/null
@@ -0,0 +1,58 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+authenticate(AT_PRIV_FAQ);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       Header('Location: index_instructor.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       $_POST['id'] = intval($_POST['id']);\r
+\r
+       // check that this topic_id belongs to this course:\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."faq_topics WHERE topic_id=$_POST[id] AND course_id=$_SESSION[course_id]";\r
+       $result = mysql_query($sql, $db);\r
+       if (mysql_affected_rows($db) == 1) {\r
+               $sql = "DELETE FROM ".TABLE_PREFIX."faq_entries WHERE topic_id=$_POST[topic_id]";\r
+               $result = mysql_query($sql, $db);\r
+       }\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: index_instructor.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+\r
+$_GET['id'] = intval($_GET['id']); \r
+\r
+$sql = "SELECT name, topic_id FROM ".TABLE_PREFIX."faq_topics WHERE topic_id=$_GET[id]";\r
+\r
+$result = mysql_query($sql,$db);\r
+if ($row = mysql_fetch_assoc($result)) {\r
+       $hidden_vars['id'] = $_GET['id'];\r
+\r
+       $confirm = array('DELETE_FAQ_TOPIC', $row['name']);\r
+       $msg->addConfirm($confirm, $hidden_vars);\r
+       $msg->printConfirm();\r
+} else {\r
+       $msg->addError('ITEM_NOT_FOUND');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/faq/edit_question.php b/faq/edit_question.php
new file mode 100644 (file)
index 0000000..82f1a4c
--- /dev/null
@@ -0,0 +1,133 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_FAQ);
+
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index_instructor.php');
+       exit;
+} 
+
+if (isset($_GET['id'])) {
+       $id = intval($_GET['id']);
+} else {
+       $id = intval($_POST['id']);
+}
+
+if (isset($_POST['submit'])) {
+       $_POST['question'] = trim($_POST['question']);
+       $_POST['answer'] = trim($_POST['answer']);
+
+       $missing_fields = array();
+       
+       if (!$_POST['question']) {
+               $missing_fields[] = _AT('question');
+       }
+
+       if (!$_POST['answer']) {
+               $missing_fields[] = _AT('answer');
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['question'] = $addslashes($_POST['question']);
+               $_POST['answer'] = $addslashes($_POST['answer']);
+               $_POST['topic_id'] = intval($_POST['topic_id']);
+               //These will truncate the content of the length to 240 as defined in the db.
+               $_POST['question'] = validate_length($_POST['question'], 250);
+               $_POST['answer'] = validate_length($_POST['answer'], 250);
+
+               $sql = "UPDATE ".TABLE_PREFIX."faq_entries SET question='$_POST[question]', answer='$_POST[answer]', topic_id=$_POST[topic_id] WHERE entry_id=$id";
+               $result = mysql_query($sql,$db);
+
+               $msg->addFeedback('QUESTION_UPDATED');
+               header('Location: index_instructor.php');
+               exit;
+       }
+}
+$onload = 'document.form.topic.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if ($id == 0) {
+       $msg->printErrors('ITEM_NOT_FOUND');
+       require (AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+$sql = "SELECT * FROM ".TABLE_PREFIX."faq_entries WHERE entry_id=$id";
+$result = mysql_query($sql,$db);
+if (!($row = mysql_fetch_assoc($result))) {
+       $msg->printErrors('ITEM_NOT_FOUND');
+       require (AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+
+$sql   = "SELECT name, topic_id FROM ".TABLE_PREFIX."faq_topics WHERE course_id=$_SESSION[course_id] ORDER BY name";
+$result = mysql_query($sql, $db);
+$num_topics = mysql_num_rows($result);
+if (!$num_topics) {
+       $msg->printErrorS('NO_FAQ_TOPICS');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="id" value="<?php echo $row['entry_id']; ?>" />
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('create_new_file'); ?></legend>
+       <div class="row">
+               <?php
+                       $sql    = "SELECT name, topic_id FROM ".TABLE_PREFIX."faq_topics WHERE course_id=$_SESSION[course_id] ORDER BY name";
+                       $result = mysql_query($sql, $db);
+               ?>
+
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="topic"><?php  echo _AT('topic'); ?></label><br />
+               <select name="topic_id" id="topic">
+                       <?php while ($topic_row = mysql_fetch_assoc($result)): ?>
+                               <option value="<?php echo $topic_row['topic_id']; ?>"<?php if ($topic_row['topic_id'] == $row['topic_id']) { echo ' selected="selected"'; } ?>><?php echo htmlspecialchars($topic_row['name']); ?></option>
+                       <?php endwhile; ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="question"><?php echo _AT('question'); ?>:</label><br />
+               <input type="text" name="question" size="50" id="question" value="<?php if (isset ($_POST['question'])) { echo $stripslashes($_POST['question']); } else { echo $row['question']; } ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="answer"><?php  echo _AT('answer'); ?></label><br />
+               <textarea name="answer" cols="45" rows="3" id="answer" style="width:90%;"><?php if (isset ($_POST['answer'])) { echo $stripslashes($_POST['answer']); } else { echo $row['answer']; } ?></textarea>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?> " />
+       </div>
+       </fieldset>
+</div>
+</form>
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/faq/edit_topic.php b/faq/edit_topic.php
new file mode 100644 (file)
index 0000000..4020881
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_FAQ);
+
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index_instructor.php');
+       exit;
+} 
+
+if (isset($_GET['id'])) {
+       $id = intval($_GET['id']);
+} else {
+       $id = intval($_POST['id']);
+}
+
+if (isset($_POST['submit'])) {
+       if (trim($_POST['name']) == '') {
+               $msg->addError('NAME_EMPTY');
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['name'] = $addslashes($_POST['name']);
+               //This will truncate the content of the length to 240 as defined in the db.
+               $_POST['name'] = validate_length($_POST['name'], 250);
+
+               $sql    = "UPDATE ".TABLE_PREFIX."faq_topics SET name='$_POST[name]' WHERE topic_id=$id AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql,$db);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: index_instructor.php');
+               exit;
+       }
+}
+$onload = 'document.form.name.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if ($id == 0) {
+       $msg->printErrors('ITEM_NOT_FOUND');
+       require (AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+$sql   = "SELECT name FROM ".TABLE_PREFIX."faq_topics WHERE course_id=$_SESSION[course_id] AND topic_id=$id ORDER BY name";
+$result = mysql_query($sql, $db);
+if (!$row = mysql_fetch_assoc($result)) {
+       $msg->printErrorS('ITEM_NOT_FOUND');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+} else if (!isset($_POST['name'])) {
+       $_POST['name'] = $row['name'];
+}
+
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="id" value="<?php echo $id; ?>" />
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('edit'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="name"><?php  echo _AT('name'); ?></label><br />
+               <input type="text" name="name" size="50" id="name" value="<?php if (isset($_POST['name'])) echo $stripslashes($_POST['name']);  ?>" />
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?> " />
+       </div>
+       </fieldset>
+</div>
+</form>
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/faq/icon.gif b/faq/icon.gif
new file mode 100644 (file)
index 0000000..56ae823
Binary files /dev/null and b/faq/icon.gif differ
diff --git a/faq/index.php b/faq/index.php
new file mode 100644 (file)
index 0000000..54fef06
--- /dev/null
@@ -0,0 +1,52 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$counter = 1;\r
+$sql    = "SELECT name, topic_id FROM ".TABLE_PREFIX."faq_topics WHERE course_id=$_SESSION[course_id] ORDER BY name";\r
+$result  = mysql_query($sql, $db);\r
+?>\r
+\r
+<?php if ($row = mysql_fetch_assoc($result)) : ?>\r
+       <ul style="list-style: none;">\r
+               <?php do { ?>\r
+                       <li style="font-weight: bold; margin-bottom: 10px;">\r
+                               <?php echo $row['name']; ?>\r
+                               <?php \r
+                                       $entry_sql = "SELECT * FROM ".TABLE_PREFIX."faq_entries WHERE topic_id=$row[topic_id] ORDER BY question";\r
+                                       $entry_result = mysql_query($entry_sql, $db);\r
+                               if ($entry_row = mysql_fetch_assoc($entry_result)) {?>\r
+                               <ol start="<?php echo $counter; ?>">\r
+\r
+                                       <?php do { ?>\r
+                                               <li style="font-weight: normal">\r
+                                                       <h3><?php echo $entry_row['question']; ?></h3>\r
+                                                       <p><?php echo $entry_row['answer'];?></p>\r
+                                               </li>\r
+                                               <?php $counter++; ?>\r
+                                       <?php } while ($entry_row = mysql_fetch_assoc($entry_result)) ?>\r
+                               </ol>\r
+                               <?php } else { ?>\r
+                                       <p style="padding-left: 20px; padding-top:3px; font-weight:normal;"><?php echo _AT('no_questions');  ?></p>\r
+                               <?php } ?>\r
+                       </li>\r
+               <?php } while($row = mysql_fetch_assoc($result)); ?>\r
+       </ul>\r
+<?php else: ?>\r
+       <?php echo _AT('none_found'); ?>\r
+<?php endif; ?>\r
+\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/faq/index_instructor.php b/faq/index_instructor.php
new file mode 100644 (file)
index 0000000..a919d44
--- /dev/null
@@ -0,0 +1,94 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_FAQ);\r
+\r
+if (isset($_GET['edit'], $_GET['item'])) {\r
+       $item = intval($_GET['item']);\r
+       if (substr($_GET['item'], -1) == 'q') {\r
+               header('Location: edit_question.php?id=' . $item);\r
+       } else {\r
+               header('Location: edit_topic.php?id=' . $item);\r
+       }\r
+       exit;\r
+} else if (isset($_GET['delete'], $_GET['item'])) {\r
+       $item = intval($_GET['item']);\r
+\r
+       if (substr($_GET['item'], -1) == 'q') {\r
+               header('Location: delete_question.php?id=' . $item);\r
+       } else {\r
+               header('Location: delete_topic.php?id=' . $item);\r
+       }\r
+       exit;\r
+} else if (!empty($_GET)) {\r
+       $msg->addError('NO_ITEM_SELECTED');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+\r
+$counter = 1;\r
+$sql    = "SELECT name, topic_id FROM ".TABLE_PREFIX."faq_topics WHERE course_id=$_SESSION[course_id] ORDER BY name";\r
+$result  = mysql_query($sql, $db);\r
+?>\r
+\r
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">\r
+<table class="data" style="width: 60%;">\r
+<thead>\r
+<tr>\r
+       <th>&nbsp;</th>\r
+       <th style="width: 100%;"><?php echo _AT('name'); ?></th>\r
+</tr>\r
+</thead>\r
+<tfoot>\r
+<tr>\r
+       <td colspan="2"><input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> \r
+                                   <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /></td>\r
+</tr>\r
+</tfoot>\r
+<?php if ($row = mysql_fetch_assoc($result)) : ?>\r
+<tbody>\r
+               <?php do { ?>\r
+                       <tr onmousedown="document.form['t<?php echo $row['topic_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $row['topic_id']; ?>_0">\r
+                               <th style="border-top:1pt solid #e0e0e0;"><input type="radio" name="item" id="t<?php echo $row['topic_id']; ?>" value="<?php echo $row['topic_id']; ?>" /></th>\r
+                               <th style="border-top:1pt solid #e0e0e0;"><?php echo $row['name']; ?></th>\r
+                       </tr>\r
+                       <?php \r
+                               $entry_sql = "SELECT * FROM ".TABLE_PREFIX."faq_entries WHERE topic_id=$row[topic_id] ORDER BY question";\r
+                               $entry_result = mysql_query($entry_sql, $db);\r
+                       ?>\r
+\r
+                       <?php if ($entry_row = mysql_fetch_assoc($entry_result)) : do { ?>\r
+                               <tr onmousedown="document.form['q<?php echo $entry_row['entry_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $row['topic_id']; ?>_<?php echo $entry_row['entry_id']; ?>">\r
+                                       <td><input type="radio" name="item" id="q<?php echo $entry_row['entry_id']; ?>" value="<?php echo $entry_row['entry_id']; ?>q" /></td>\r
+                                       <td><?php echo $entry_row['question']; ?></td>\r
+                               </tr>\r
+                       <?php } while ($entry_row = mysql_fetch_assoc($entry_result)); else: ?>\r
+                               <tr>\r
+                                       <td>&nbsp;</td>\r
+                                       <td><?php echo _AT('no_questions'); ?></td>\r
+                               </tr>\r
+                       <?php endif; ?>\r
+               <?php } while($row = mysql_fetch_assoc($result)); ?>\r
+</tbody>\r
+<?php else: ?>\r
+       <tr>\r
+               <td colspan="2"><em><?php echo _AT('none_found'); ?></em></td>\r
+       </tr>\r
+<?php endif; ?>\r
+</table>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php');  ?>
\ No newline at end of file
diff --git a/favicon.ico b/favicon.ico
new file mode 100644 (file)
index 0000000..4bdadd7
Binary files /dev/null and b/favicon.ico differ
diff --git a/file_storage/assignment.php b/file_storage/assignment.php
new file mode 100644 (file)
index 0000000..e4fece4
--- /dev/null
@@ -0,0 +1,151 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'lib/file_storage.inc.php');\r
+\r
+$owner_type = abs($_REQUEST['ot']);\r
+$owner_id   = abs($_REQUEST['oid']);\r
+$owner_arg_prefix = '?ot='.$owner_type.SEP.'oid='.$owner_id. SEP;\r
+if (!($owner_status = fs_authenticate($owner_type, $owner_id)) || !query_bit($owner_status, WORKSPACE_AUTH_WRITE)) { \r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: '.url_rewrite('file_storage/index.php', AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+}\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.abs($_POST['folder'], AT_PRETTY_URL_IS_HEADER)));\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       $_POST['assignment'] = abs($_POST['assignment']);\r
+       $assignment_row    = fs_get_assignment($_POST['assignment']);\r
+\r
+       if (!$assignment_row) {\r
+               $msg->addError('ACCESS_DENIED');\r
+               header('Location: '.url_rewrite('file_storage/index.php', AT_PRETTY_URL_IS_HEADER));\r
+               exit;\r
+       }\r
+\r
+       if (!$assignment_row['assign_to']) {\r
+               if (!$_SESSION['enroll']) {\r
+                       $msg->addError('ACCESS_DENIED');\r
+                       header('Location: '.url_rewrite('file_storage/index.php', AT_PRETTY_URL_IS_HEADER));\r
+                       exit;\r
+               }\r
+\r
+       } else {\r
+               $sql = "SELECT group_id FROM ".TABLE_PREFIX."groups WHERE group_id=$owner_id AND type_id=$assignment_row[assign_to]";\r
+               $result = mysql_query($sql, $db);\r
+               if (!$row = mysql_fetch_assoc($result)) {\r
+                       $msg->addError('ACCESS_DENIED');\r
+                       header('Location: '.url_rewrite('file_storage/index.php', AT_PRETTY_URL_IS_HEADER));\r
+                       exit;\r
+               }\r
+       }\r
+\r
+       if ($assignment_row['u_date_cutoff'] && ($assignment_row['u_date_cutoff'] < time())) {\r
+               $msg->addError('ASSIGNMENT_CUTOFF');\r
+               header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.$_POST['folder'], AT_PRETTY_URL_IS_HEADER));\r
+               exit;\r
+       }\r
+\r
+       foreach ($_POST['files'] as $file) {\r
+               $file = abs($file);\r
+               fs_copy_file($file, $owner_type, $owner_id, WORKSPACE_ASSIGNMENT, $_POST['assignment'], $owner_id);\r
+       }\r
+\r
+       $msg->addFeedback('ASSIGNMENT_HANDED_IN');\r
+       header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.$_POST['folder'], AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+}\r
+\r
+// get all the assignments assigned to $owner_id (which is either a student ID or a group type ID)\r
+if ($owner_type == WORKSPACE_GROUP) {\r
+       // get all the assignments assigned to this group type\r
+\r
+       $sql = "SELECT type_id FROM ".TABLE_PREFIX."groups WHERE group_id=$owner_id LIMIT 1";\r
+       $result = mysql_query($sql, $db);\r
+       $row = mysql_fetch_assoc($result);\r
+\r
+       $sql = "SELECT assignment_id, title, date_due, date_cutoff FROM ".TABLE_PREFIX."assignments WHERE assign_to=$row[type_id] AND course_id=$_SESSION[course_id] AND (date_cutoff=0 OR UNIX_TIMESTAMP(date_cutoff) > ".time().") ORDER BY title";\r
+\r
+} else if ($owner_type == WORKSPACE_PERSONAL) {\r
+       // get all the assignments assigned to students\r
+\r
+       $sql = "SELECT assignment_id, title, date_due FROM ".TABLE_PREFIX."assignments WHERE assign_to=0 AND course_id=$_SESSION[course_id] AND (date_cutoff=0 OR UNIX_TIMESTAMP(date_cutoff) > ".time().") ORDER BY title";\r
+} else {\r
+       exit('wrong workspace');\r
+}\r
+\r
+$assignments = array();\r
+$result = mysql_query($sql, $db);\r
+while ($row = mysql_fetch_assoc($result)) {\r
+       $assignments[] = $row;\r
+}\r
+\r
+if (!$assignments) {\r
+       $msg->addError('NO_ASSIGNMENTS_FOUND');\r
+       header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.$_GET['folder'], AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+?>\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF'].$owner_arg_prefix; ?>">\r
+<input type="hidden" name="folder" value="<?php echo abs($_GET['folder']); ?>" />\r
+<?php foreach ($_GET['files'] as $key => $file): ?>\r
+       <?php $_GET['files'][$key] = $file = abs($file); ?>\r
+       <input type="hidden" name="files[]" value="<?php echo $file; ?>" />\r
+<?php endforeach; ?>\r
+\r
+<div class="input-form">\r
+       \r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="name"><?php echo _AT('assignment'); ?></label<br />\r
+               <select name="assignment" size="<?php echo min(5, count($assignments)); ?>">\r
+                       <?php foreach ($assignments as $assignment): ?>\r
+                               <?php if ($assignment['date_due'] != '0000-00-00 00:00:00'): ?>\r
+                                       <option value="<?php echo $assignment['assignment_id']; ?>"><?php echo $assignment['title']; ?> - <?php echo _AT('due') . ': ' . AT_date(_AT('filemanager_date_format'), $assignment['date_due'], AT_DATE_MYSQL_DATETIME); ?></option>\r
+                               <?php else: ?>\r
+                                       <option value="<?php echo $assignment['assignment_id']; ?>"><?php echo $assignment['title']; ?> - <?php echo _AT('no_due_date'); ?></option>\r
+                               <?php endif; ?>\r
+                       <?php endforeach; ?>\r
+               </select>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <?php echo _AT('files'); ?>\r
+               <ul style="list-style: none; margin: 0px; padding: 0px 10px;">\r
+                       <?php\r
+                               $file_list = implode(',', $_GET['files']);\r
+                               $sql = "SELECT file_name FROM ".TABLE_PREFIX."files WHERE file_id IN ($file_list) AND owner_type=$owner_type AND owner_id=$owner_id ORDER BY file_name";\r
+                               $result = mysql_query($sql, $db);\r
+                       ?>\r
+                       <?php while ($row = mysql_fetch_assoc($result)): ?>\r
+                               <li><img src="images/file_types/<?php echo fs_get_file_type_icon($row['file_name']); ?>.gif" height="16" width="16" alt="" title="" /> <?php echo $row['file_name']; ?></li>\r
+                       <?php endwhile; ?>\r
+               </ul>\r
+       </div>\r
+\r
+       <div class="buttons row">\r
+               <input type="submit" name="submit" value="<?php echo _AT('submit'); ?>" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/file_storage/comments.php b/file_storage/comments.php
new file mode 100644 (file)
index 0000000..1446fbf
--- /dev/null
@@ -0,0 +1,196 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'lib/file_storage.inc.php');\r
+\r
+$owner_type = abs($_REQUEST['ot']);\r
+$owner_id   = abs($_REQUEST['oid']);\r
+$owner_arg_prefix = '?ot='.$owner_type.SEP.'oid='.$owner_id. SEP;\r
+if (!fs_authenticate($owner_type, $owner_id)) { \r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: '.url_rewrite('file_storage/index.php', AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+}\r
+\r
+if (isset($_GET['done'])) {\r
+       header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.abs($_GET['folder']), AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+} else if (isset($_GET['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.abs($_GET['folder']), AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+} else if (isset($_POST['edit_cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.url_rewrite('file_storage/comments.php'.$owner_arg_prefix.'id='.$_GET['id'], AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+} else if (isset($_POST['edit_submit'])) {\r
+       $_POST['comment'] = trim($_POST['comment']);\r
+       $_POST['comment_id'] = abs($_POST['comment_id']);\r
+\r
+       if (!$_POST['edit_comment']) {\r
+               $msg->addError(array('EMPTY_FIELDS', _AT('comments')));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               $_POST['edit_comment'] = $addslashes($_POST['edit_comment']);\r
+\r
+               $sql = "UPDATE ".TABLE_PREFIX."files_comments SET comment='$_POST[edit_comment]', date=date WHERE member_id=$_SESSION[member_id] AND comment_id=$_POST[comment_id]";\r
+               mysql_query($sql, $db);\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+               header('Location: '.url_rewrite('file_storage/comments.php'.$owner_arg_prefix.'id='.$_GET['id'], AT_PRETTY_URL_IS_HEADER));\r
+               exit;\r
+       }\r
+} else if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.$_POST['folder'], AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       $_POST['comment'] = trim($_POST['comment']);\r
+       $_POST['id'] = abs($_POST['id']);\r
+\r
+       if (!$_POST['comment']) {\r
+               $msg->addError(array('EMPTY_FIELDS', _AT('comments')));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               $_POST['comment'] = $addslashes($_POST['comment']);\r
+\r
+               $sql = "INSERT INTO ".TABLE_PREFIX."files_comments VALUES (NULL, $_POST[id], $_SESSION[member_id], NOW(), '$_POST[comment]')";\r
+               if (mysql_query($sql, $db)) {\r
+                       $sql = "UPDATE ".TABLE_PREFIX."files SET num_comments=num_comments+1, date=date WHERE file_id=$_POST[id]";\r
+                       mysql_query($sql, $db);\r
+               }\r
+\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+               header('Location: '.url_rewrite('file_storage/comments.php'.$owner_arg_prefix.'id='.$_POST['id'], AT_PRETTY_URL_IS_HEADER));\r
+               exit;\r
+       }\r
+       $_GET['id'] = $_POST['id'];\r
+}\r
+\r
+if (isset($_GET['comment_id'])) {\r
+       $onload = 'document.form.edit_comment.focus();';\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$id = abs($_GET['id']);\r
+\r
+$files = fs_get_revisions($id, $owner_type, $owner_id);\r
+if (!$files) {\r
+       $msg->printErrors('FILE_NOT_FOUND');\r
+       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+?>\r
+\r
+<?php if ($_config['fs_versioning']): ?>\r
+       <form method="get" action="<?php echo 'file_storage/comments.php'\r
+       //@harris echo $_SERVER['PHP_SELF']; ?>">\r
+       <input type="hidden" name="ot" value="<?php echo $owner_type; ?>" />\r
+       <input type="hidden" name="oid" value="<?php echo $owner_id; ?>" />\r
+       <div class="input-form" style="width: 50%">\r
+               <div class="row">\r
+                       <select name="id" size="<?php echo min(count($files), 5);?>">\r
+                               <?php foreach ($files as $file): ?>\r
+                                       <?php\r
+                                               $selected = '';\r
+                                               if ($file['file_id'] == $id) {\r
+                                                       $current_file = $file;\r
+                                                       $selected = ' selected="selected"';\r
+                                               }\r
+                                       ?>\r
+                                       <option value="<?php echo $file['file_id'];?>" <?php echo $selected; ?>><?php echo _AT('revision'); ?> <?php echo $file['num_revisions']; ?>. <?php echo $file['file_name']; ?> - <?php echo $file['num_comments']; ?> <?php echo _AT('comments'); ?></option>\r
+                               <?php endforeach; ?>\r
+                       </select>\r
+               </div>\r
+               <div class="row buttons">\r
+                       <input type="submit" name="comments" value="<?php echo _AT('comments'); ?>" />\r
+                       <input type="submit" name="done" value="<?php echo _AT('done'); ?>" />\r
+               </div>\r
+       </div>\r
+       <input type="hidden" name="folder" value="<?php echo $current_file['folder_id']; ?>" />\r
+       </form>\r
+<?php else: ?>\r
+       <?php $current_file = current($files); ?>\r
+<?php endif; ?>\r
+\r
+<div class="input-form">\r
+       <div class="row">\r
+               <h3><?php echo $current_file['file_name']; ?> <small> - <?php echo _AT('revision'); ?> <?php echo $current_file['num_revisions']; ?></small></h3>\r
+               <span style="font-size: small"><?php echo get_display_name($current_file['member_id']); ?> - <?php echo AT_date(_AT('filemanager_date_format'), $current_file['date'], AT_DATE_MYSQL_DATETIME); ?></span>\r
+               <p><?php echo nl2br(htmlspecialchars($current_file['description'])); ?></p>\r
+       </div>\r
+</div>\r
+\r
+<?php\r
+$_GET['comment_id'] = isset($_GET['comment_id']) ? intval($_GET['comment_id']) : 0;\r
+       $sql = "SELECT * FROM ".TABLE_PREFIX."files_comments WHERE file_id=$id ORDER BY date ASC";\r
+       $result = mysql_query($sql, $db);\r
+if ($row = mysql_fetch_assoc($result)): ?>\r
+       <?php do { ?>\r
+               <div class="input-form">\r
+                       <?php if (($row['member_id'] == $_SESSION['member_id']) && ($row['comment_id'] == $_GET['comment_id'])): ?>\r
+                               <form method="post" action="file_storage/comments.php<?php echo $owner_arg_prefix.'id='.$id;?>" name="form">\r
+                               <input type="hidden" name="comment_id" value="<?php echo $row['comment_id']; ?>" />\r
+                               <div class="row">\r
+                                       <a name="c<?php echo $row['comment_id']; ?>"></a><h4><?php echo get_display_name($row['member_id']); ?> - <?php echo $row['date']; ?></h4>\r
+                                       <textarea rows="4" cols="40" name="edit_comment"><?php echo htmlspecialchars($row['comment']); ?></textarea>\r
+                               </div>\r
+                               <div class="row buttons">\r
+                                       <input type="submit" name="edit_submit" value="<?php echo _AT('save'); ?>" />\r
+                                       <input type="submit" name="edit_cancel" value="<?php echo _AT('cancel'); ?>" />\r
+                               </div>\r
+                               </form>\r
+                                               \r
+                       <?php else: ?>\r
+                               <div class="row">\r
+                                       <h4><?php echo get_display_name($row['member_id']); ?> - <?php echo AT_date(_AT('filemanager_date_format'), $row['date'], AT_DATE_MYSQL_DATETIME); ?></h4>\r
+                                       <p><?php echo nl2br(htmlspecialchars($row['comment'])); ?></p>\r
+                                               <?php if ($row['member_id'] == $_SESSION['member_id']): ?>\r
+                                                       <div style="text-align:right; font-size: smaller">\r
+                                                               <a href="<?php echo url_rewrite('file_storage/comments.php'.$owner_arg_prefix.'id='.$id.SEP.'comment_id='.$row['comment_id'].'#c'.$row['comment_id']); ?>"><?php echo _AT('edit'); ?></a> | <a href="file_storage/delete_comment.php<?php echo $owner_arg_prefix . 'file_id='.$id.SEP; ?>id=<?php echo $row['comment_id']; ?>"><?php echo _AT('delete'); ?></a>\r
+                                                       </div>\r
+                                               <?php endif; ?>\r
+                               </div>\r
+                       <?php endif; ?>\r
+               </div>\r
+       <?php } while ($row = mysql_fetch_assoc($result)); ?>\r
+<?php elseif(0): ?>\r
+       <div class="input-form">\r
+               <div class="row">\r
+                       <p><?php echo _AT('none_found'); ?></p>\r
+               </div>\r
+       </div>\r
+<?php endif; ?>\r
+\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF'].$owner_arg_prefix; ?>id=<?php echo $id; ?>">\r
+<input type="hidden" name="id" value="<?php echo $id; ?>" />\r
+<input type="hidden" name="folder" value="<?php echo $current_file['folder_id']; ?>" />\r
+<div class="input-form">\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="comment"><?php echo _AT('comment'); ?></label><br />\r
+               <textarea cols="40" rows="4" id="comment" name="comment"></textarea>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('post'); ?>" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/file_storage/delete_comment.php b/file_storage/delete_comment.php
new file mode 100644 (file)
index 0000000..9d95b44
--- /dev/null
@@ -0,0 +1,62 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'lib/file_storage.inc.php');\r
+\r
+$owner_type = abs($_REQUEST['ot']);\r
+$owner_id   = abs($_REQUEST['oid']);\r
+$owner_arg_prefix = '?ot='.$owner_type.SEP.'oid='.$owner_id. SEP;\r
+if (!($owner_status = fs_authenticate($owner_type, $owner_id)) || !query_bit($owner_status, WORKSPACE_AUTH_WRITE)) { \r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: '.url_rewrite('file_storage/index.php', AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+}\r
+\r
+$_pages['file_storage/delete_comment.php']['parent'] = 'file_storage/comments.php' . $owner_arg_prefix.'id='.$_GET['file_id'];\r
+$_pages['file_storage/comments.php' . $owner_arg_prefix.'id='.$_GET['file_id']]['title_var'] = 'comments';\r
+$_pages['file_storage/comments.php' . $owner_arg_prefix.'id='.$_GET['file_id']]['parent']    = 'file_storage/index.php';\r
+\r
+$id = abs($_REQUEST['id']);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.url_rewrite('file_storage/comments.php'.$owner_arg_prefix.'id='.$_POST['file_id'], AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       $_POST['file_id'] = abs($_POST['file_id']);\r
+       $_POST['id'] = abs($_POST['id']);\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."files_comments WHERE file_id=$_POST[file_id] AND comment_id=$_POST[id] AND member_id=$_SESSION[member_id]";\r
+       $result = mysql_query($sql, $db);\r
+       if (mysql_affected_rows($db) == 1) {\r
+               $sql = "UPDATE ".TABLE_PREFIX."files SET num_comments=num_comments-1, date=date WHERE owner_type=$owner_type AND owner_id=$owner_id AND file_id=$_POST[file_id]";\r
+               $result = mysql_query($sql, $db);\r
+       }\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: '.url_rewrite('file_storage/comments.php'.$owner_arg_prefix.'id='.$_POST['file_id'], AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$hidden_vars = array('id' => $id, 'ot' => $owner_type, 'oid' => $owner_id, 'file_id' => $_GET['file_id']);\r
+$msg->addConfirm(array('DELETE'), $hidden_vars);\r
+$msg->printConfirm();\r
+\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/file_storage/delete_revision.php b/file_storage/delete_revision.php
new file mode 100644 (file)
index 0000000..786e7ed
--- /dev/null
@@ -0,0 +1,91 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'lib/file_storage.inc.php');\r
+\r
+$owner_type = abs($_REQUEST['ot']);\r
+$owner_id   = abs($_REQUEST['oid']);\r
+$owner_arg_prefix = '?ot='.$owner_type.SEP.'oid='.$owner_id. SEP;\r
+if (!($owner_status = fs_authenticate($owner_type, $owner_id)) || !query_bit($owner_status, WORKSPACE_AUTH_WRITE)) { \r
+       exit('NOT AUTHENTICATED');\r
+}\r
+\r
+$id = abs($_REQUEST['id']);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $path = fs_get_revisions($id, $owner_type, $owner_id);\r
+       reset($path);\r
+       $first = current($path);\r
+\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.url_rewrite('file_storage/revisions.php'.$owner_arg_prefix.'id='.$first['file_id'], AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       $path = fs_get_revisions($id, $owner_type, $owner_id);\r
+\r
+       // set the new parent //\r
+       $sql = "SELECT parent_file_id, owner_type, owner_id, folder_id FROM ".TABLE_PREFIX."files WHERE file_id=$id AND owner_type=$owner_type AND owner_id=$owner_id";\r
+       $result = mysql_query($sql, $db);\r
+       $row = mysql_fetch_assoc($result);\r
+\r
+       $sql = "UPDATE ".TABLE_PREFIX."files SET parent_file_id=$row[parent_file_id], date=date WHERE parent_file_id=$id AND owner_type=$owner_type AND owner_id=$owner_id";\r
+       mysql_query($sql, $db);\r
+\r
+       $sql = "UPDATE ".TABLE_PREFIX."files SET num_revisions=num_revisions-1, date=date WHERE file_id>$id AND owner_type=$row[owner_type] AND owner_id=$row[owner_id] AND folder_id=$row[folder_id]";\r
+       mysql_query($sql, $db);\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."files WHERE file_id=$id AND owner_type=$owner_type AND owner_id=$owner_id";\r
+       mysql_query($sql, $db);\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."files_comments WHERE file_id=$id";\r
+       mysql_query($sql, $db);\r
+\r
+       $file = fs_get_file_path($id);\r
+       if (file_exists($file . $id)) {\r
+               @unlink($file . $id);\r
+       }\r
+\r
+       $back_id = FALSE;\r
+       foreach($path as $file) {\r
+               if ($file['file_id'] != $id) {\r
+                       $back_id = $file['file_id'];\r
+                       break;\r
+               }\r
+       }\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       if ($back_id) {\r
+               header('Location: '.url_rewrite('file_storage/revisions.php'.$owner_arg_prefix.'id='.$back_id, AT_PRETTY_URL_IS_HEADER));\r
+       } else {\r
+               header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix, AT_PRETTY_URL_IS_HEADER));\r
+       }\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$sql = "SELECT file_id, file_name, owner_type, owner_id, date, member_id FROM ".TABLE_PREFIX."files WHERE file_id=$id AND owner_type=$owner_type AND owner_id=$owner_id";\r
+$result = mysql_query($sql, $db);\r
+if (!$row = mysql_fetch_assoc($result)) {\r
+       $msg->printErrors('FILE_NOT_EXIST');\r
+} else {\r
+       $hidden_vars = array('id' => $id, 'ot' => $owner_type, 'oid' => $owner_id);\r
+       $msg->addConfirm(array('FILE_DELETE', '<li>'.$row['date'].' - '. $row['file_name'].' - '.get_display_name($row['member_id']).'</li>'), $hidden_vars);\r
+       $msg->printConfirm();\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/file_storage/edit.php b/file_storage/edit.php
new file mode 100644 (file)
index 0000000..46914f8
--- /dev/null
@@ -0,0 +1,221 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'lib/file_storage.inc.php');\r
+\r
+$owner_type = abs($_REQUEST['ot']);\r
+$owner_id   = abs($_REQUEST['oid']);\r
+$owner_arg_prefix = '?ot='.$owner_type.SEP.'oid='.$owner_id. SEP;\r
+if (!($owner_status = fs_authenticate($owner_type, $owner_id)) || !query_bit($owner_status, WORKSPACE_AUTH_WRITE)) { \r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: '.url_rewrite('file_storage/index.php', AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+}\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.abs($_POST['folder']), AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       $_POST['id'] = abs($_POST['id']);\r
+\r
+\r
+       if (!$_POST['name']) {\r
+               $msg->addError('MISSING_FILENAME');\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               $_POST['name'] = $addslashes($_POST['name']);\r
+               $_POST['comment'] = $addslashes(trim($_POST['comment']));\r
+               $_POST['description'] = $addslashes(trim($_POST['description']));\r
+               $_POST['body'] = $stripslashes($_POST['body']); // saved to disk not db so no need to escape.\r
+               $original_file = fs_get_file_path($_POST['id']);\r
+               $folder = abs($_POST['folder']);\r
+\r
+               if (!$_POST['edit'] || (file_get_contents($original_file . $_POST['id']) == $_POST['body'])) {\r
+                       // file is not editable ,or it is editable but no changes made.\r
+                       // only add the comment (if any) and the file name\r
+\r
+                       $num_comments = 0;\r
+                       \r
+                       if ($_POST['comment']){\r
+                               $sql = "INSERT INTO ".TABLE_PREFIX."files_comments VALUES (NULL, $_POST[id], $_SESSION[member_id], NOW(), '{$_POST['comment']}')";\r
+                               mysql_query($sql, $db);\r
+\r
+                               $num_comments = 1;\r
+                       }\r
+\r
+                       $sql = "UPDATE ".TABLE_PREFIX."files SET file_name='$_POST[name]', description='$_POST[description]', num_comments=num_comments+$num_comments, date=date WHERE file_id=$_POST[id] AND owner_type=$owner_type AND owner_id=$owner_id";\r
+                       mysql_query($sql, $db);\r
+               } else {\r
+                       // this file is editable, and has changed\r
+\r
+                       $size = strlen($_POST['body']);\r
+\r
+                       if ($_POST['comment']) {\r
+                               $num_comments = 1;\r
+                       } else {\r
+                               $num_comments = 0;\r
+                       }\r
+                       $sql = "SELECT * FROM ".TABLE_PREFIX."files WHERE file_id=$_POST[id] AND owner_type=$owner_type AND owner_id=$owner_id";\r
+                       $result = mysql_query($sql, $db);\r
+                       $row = mysql_fetch_assoc($result);\r
+\r
+                       if ($_config['fs_versioning']) {\r
+                               $sql = "INSERT INTO ".TABLE_PREFIX."files VALUES (NULL, {$row['owner_type']}, {$row['owner_id']}, $_SESSION[member_id], {$row['folder_id']}, 0, NOW(), $num_comments, {$row['num_revisions']}+1, '{$_POST['name']}', $size, '$_POST[description]')";\r
+                               $result = mysql_query($sql, $db);\r
+\r
+                               $file_id = mysql_insert_id($db);\r
+\r
+                               $file_path = fs_get_file_path($file_id);\r
+                               if ($fp = fopen($file_path . $file_id, 'wb')) {\r
+                                       ftruncate($fp, 0);\r
+                                       fwrite($fp, $_POST['body'], $size);\r
+                                       fclose($fp);\r
+\r
+                                       $sql = "UPDATE ".TABLE_PREFIX."files SET parent_file_id=$file_id, date=date WHERE file_id=$_POST[id] AND owner_type=$owner_type AND owner_id=$owner_id";\r
+                                       $result = mysql_query($sql, $db);\r
+\r
+                                       if ($_POST['comment']){\r
+                                               $sql = "INSERT INTO ".TABLE_PREFIX."files_comments VALUES (NULL, $file_id, $_SESSION[member_id], NOW(), '{$_POST['comment']}')";\r
+                                               mysql_query($sql, $db);\r
+                                       }\r
+                               }\r
+                       } else {\r
+                               $file_path = fs_get_file_path($_POST['id']);\r
+                               if ($fp = fopen($file_path . $_POST['id'], 'wb')) {\r
+                                       ftruncate($fp, 0);\r
+                                       fwrite($fp, $_POST['body'], $size);\r
+                                       fclose($fp);\r
+                               }\r
+                       }\r
+               }\r
+               $msg->addFeedback('FILE_EDITED_SUCCESSFULLY');\r
+               header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.$folder, AT_PRETTY_URL_IS_HEADER));\r
+               exit;\r
+       }\r
+\r
+       $_GET['id'] = $_POST['id'];\r
+}\r
+\r
+$onload = 'document.form.name.focus();';\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+if (($_POST['setvisual'] && !$_POST['settext']) || $_GET['setvisual']) {\r
+       require(AT_INCLUDE_PATH.'lib/tinymce.inc.php');\r
+\r
+       load_editor('body');\r
+}\r
+\r
+$id = abs($_REQUEST['id']);\r
+\r
+$sql = "SELECT file_name, folder_id, description FROM ".TABLE_PREFIX."files WHERE file_id=$id AND owner_type=$owner_type AND owner_id=$owner_id";\r
+$result = mysql_query($sql, $db);\r
+if (!$row = mysql_fetch_assoc($result)) {\r
+       $msg->printErrors('FILE_NOT_EXIST');\r
+       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+if (isset($_POST['description'])) {\r
+       $row['description'] = $stripslashes($_POST['description']);\r
+       $row['file_name']   = $stripslashes($_POST['name']);\r
+       $row['comment']     = $stripslashes($_POST['comment']);\r
+       $_POST['body']      = $stripslashes($_POST['body']);\r
+}\r
+$ext = fs_get_file_extension($row['file_name']);\r
+$file_path = fs_get_file_path($id);\r
+?>\r
+\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF'] . $owner_arg_prefix; ?>" name="form">\r
+<input type="hidden" name="id" value="<?php echo $id; ?>" />\r
+<input type="hidden" name="folder" value="<?php echo $row['folder_id']; ?>" />\r
+<div class="input-form">\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="name"><?php echo _AT('file_name'); ?></label><br />\r
+               <input type="text" name="name" id="name" value="<?php echo htmlspecialchars($row['file_name']); ?>" size="40" maxlength="70" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <label for="description"><?php echo _AT('description'); ?></label><br />\r
+               <textarea name="description" id="description" cols="30" rows="2"><?php echo htmlspecialchars($row['description']); ?></textarea>\r
+       </div>\r
+\r
+       <?php if (in_array($ext, $editable_file_types)): ?>\r
+               <input type="hidden" name="edit" value="1" />\r
+               <div class="row">\r
+                       <label for="comment"><?php echo _AT('revision_comment'); ?></label><br />\r
+                       <textarea name="comment" id="comment" cols="30" rows="2"><?php echo htmlspecialchars($row['comment']); ?></textarea>\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <?php\r
+                               if (($_POST['setvisual'] && !$_POST['settext']) || $_GET['setvisual']){\r
+                                       echo '<input type="hidden" name="setvisual" value="'.$_POST['setvisual'].'" />';\r
+                                       echo '<input type="submit" name="settext" value="'._AT('switch_text').'" />';\r
+                               } else {\r
+                                       echo '<input type="submit" name="setvisual" value="'._AT('switch_visual').'" />';\r
+                               }\r
+                       ?>\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <label for="body"><?php echo _AT('contents'); ?></label><br />\r
+                       <textarea name="body" id="body" cols="30" rows="20"><?php\r
+                               if (isset($_POST['body'])) {\r
+                                       echo $_POST['body'];\r
+                               } else {\r
+                                       echo htmlspecialchars(file_get_contents($file_path . $id));\r
+                               }\r
+                               ?></textarea>\r
+               </div>\r
+       <?php else: ?>\r
+               <div class="row">\r
+                       <label for="comment"><?php echo _AT('revision_comment'); ?></label><br />\r
+                       <textarea name="comment" id="comment" cols="30" rows="2"></textarea>\r
+               </div>\r
+               <div class="row">\r
+                       <?php echo _AT('contents'); ?><br />\r
+                       <?php echo _AT('not_editable'); ?>\r
+                       <br />\r
+                       <?php if (in_array($ext, array('gif', 'jpg','jpeg'))): ?>\r
+                               <img src="file_storage/index.php<?php echo $owner_arg_prefix; ?>download=1<?php echo SEP; ?>files<?php echo urlencode('[]').'='.$id; ?>" alt="" title="" />\r
+\r
+                       <?php elseif ($ext == 'swf'): ?>\r
+                               <object type="application/x-shockwave-flash" data="file_storage/index.php<?php echo $owner_arg_prefix; ?>download=1<?php echo SEP; ?>files<?php echo urlencode('[]').'='.$id; ?>" width="550" height="400"><param name="movie" value="file_storage/index.php<?php echo $owner_arg_prefix; ?>download=1<?php echo SEP; ?>files<?php echo urlencode('[]').'='.$id; ?>" /></object>\r
+\r
+                       <?php elseif ($ext == 'mov'): ?>\r
+                               <object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" width="550" height="400" codebase="http://www.apple.com/qtactivex/qtplugin.cab"><param name="src" value="file_storage/index.php<?php echo $owner_arg_prefix; ?>download=1<?php echo SEP; ?>files<?php echo urlencode('[]').'='.$id; ?>" /><param name="autoplay" value="true" /><param name="controller" value="true" /><embed src="file_storage/index.php<?php echo $owner_arg_prefix; ?>download=1<?php echo SEP; ?>files<?php echo urlencode('[]').'='.$id; ?>" width="550" height="400" controller="true" pluginspage="http://www.apple.com/quicktime/download/"></embed></object>\r
+\r
+                       <?php elseif ($ext == 'mp3'): ?>\r
+                               <object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" width="200" height="15" codebase="http://www.apple.com/qtactivex/qtplugin.cab"><param name="src" value="file_storage/index.php<?php echo $owner_arg_prefix; ?>download=1<?php echo SEP; ?>files<?php echo urlencode('[]').'='.$id; ?>" /><param name="autoplay" value="false" /><embed src="file_storage/index.php<?php echo $owner_arg_prefix; ?>download=1<?php echo SEP; ?>files<?php echo urlencode('[]').'='.$id; ?>" width="200" height="15" autoplay="false" pluginspage="http://www.apple.com/quicktime/download/"></embed></object>\r
+\r
+                       <?php elseif (in_array($ext, array('wav', 'au'))): ?>\r
+                               <embed SRC="file_storage/index.php<?php echo $owner_arg_prefix; ?>download=1<?php echo SEP; ?>files<?php echo urlencode('[]').'='.$id; ?>" autostart="false" width="145" height="60"><noembed><bgsound src="file_storage/index.php<?php echo $owner_arg_prefix; ?>download=1<?php echo SEP; ?>files<?php echo urlencode('[]').'='.$id; ?>"></noembed></embed>\r
+\r
+                       <?php endif; ?>\r
+               </div>\r
+\r
+               <input type="hidden" name="edit" value="0" />\r
+       <?php endif; ?>\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/file_storage/edit_folder.php b/file_storage/edit_folder.php
new file mode 100644 (file)
index 0000000..18ef910
--- /dev/null
@@ -0,0 +1,86 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'lib/file_storage.inc.php');\r
+\r
+$owner_type = abs($_REQUEST['ot']);\r
+$owner_id   = abs($_REQUEST['oid']);\r
+$owner_arg_prefix = '?ot='.$owner_type.SEP.'oid='.$owner_id. SEP;\r
+if (!($owner_status = fs_authenticate($owner_type, $owner_id)) || !query_bit($owner_status, WORKSPACE_AUTH_WRITE)) {\r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: '.url_rewrite('file_storage/index.php', AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+}\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.abs($_POST['parent_folder']), AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       $_POST['id'] = abs($_POST['id']);\r
+\r
+       if (!$_POST['name']) {\r
+               $msg->addError(array('EMPTY_FIELDS', _AT('name')));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               $_POST['name'] = $addslashes($_POST['name']);\r
+               $folder = abs($_POST['folder']);\r
+               $parent_folder = abs($_POST['parent_folder']);\r
+\r
+               $sql = "UPDATE ".TABLE_PREFIX."folders SET title='$_POST[name]' WHERE owner_type=$owner_type AND owner_id=$owner_id AND folder_id=$_POST[id] AND parent_folder_id=$parent_folder";\r
+               mysql_query($sql, $db);\r
+\r
+               $msg->addFeedback('FOLDER_EDITED_SUCCESSFULLY');\r
+               header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.$parent_folder, AT_PRETTY_URL_IS_HEADER));\r
+               exit;\r
+       }\r
+\r
+       $_GET['id'] = $_POST['id'];\r
+}\r
+       \r
+$onload = 'document.form.name.focus();';\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$id = abs($_GET['id']);\r
+\r
+$sql = "SELECT title, parent_folder_id FROM ".TABLE_PREFIX."folders WHERE folder_id=$id";\r
+$result = mysql_query($sql, $db);\r
+if (!$row = mysql_fetch_assoc($result)) {\r
+       $msg->printErrors('FOLDER_NOT_EXIST');\r
+       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+?>\r
+\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF'].$owner_arg_prefix; ?>" name="form">\r
+<input type="hidden" name="id" value="<?php echo $id; ?>" />\r
+<input type="hidden" name="parent_folder" value="<?php echo $row['parent_folder_id']; ?>" />\r
+<div class="input-form">\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="name"><?php echo _AT('name'); ?></label><br />\r
+               <input type="text" name="name" id="name" value="<?php echo htmlspecialchars($row['title']); ?>" size="40" maxlength="70" />\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/file_storage/index.php b/file_storage/index.php
new file mode 100644 (file)
index 0000000..ff649fd
--- /dev/null
@@ -0,0 +1,705 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/filemanager.inc.php'); // for get_human_size()
+require(AT_INCLUDE_PATH.'lib/file_storage.inc.php');
+
+// check folders and files id
+if (isset($_GET['folders'])){
+       if (is_array($_GET['folders'])){
+               foreach($_GET['folders'] as $k=>$v){
+                       $_GET['folders'][$k] = abs($_GET['folders'][$k]);
+               }
+       } else {
+               $_GET['folders']= abs($_GET['folders']);
+       } 
+}
+if (isset($_GET['files'])){
+       if (is_array($_GET['files'])){
+               foreach($_GET['files'] as $k=>$v){
+                       $_GET['files'][$k] = abs($_GET['files'][$k]);
+               }
+       } else {
+               $_GET['files']= abs($_GET['files']);
+       } 
+}
+
+if (isset($_GET['submit_workspace'])) {
+       unset($_GET['folder']);
+
+       $owner_type = abs($_GET['ot']);
+
+       if ($owner_type == WORKSPACE_GROUP) {
+
+               $parts = explode('_', $_GET['ot'], 2);
+               if (isset($parts[1]) && $parts[1] && isset($_SESSION['groups'][$parts[1]])) {
+                       $owner_id = $parts[1];
+               } else {
+                       $owner_type = WORKSPACE_COURSE;
+                       unset($owner_id);
+               }
+       } else if ($owner_type == WORKSPACE_ASSIGNMENT) {
+               $parts = explode('_', $_GET['ot'], 2);
+               if (isset($parts[1]) && $parts[1]) {
+                       $owner_id = $parts[1];
+               } else {
+                       $owner_type = WORKSPACE_ASSIGNMENT;
+                       unset($owner_id);
+               }
+       } else {
+               unset($owner_id);
+       }
+       $_REQUEST['folder'] = 0;
+} else if (isset($_REQUEST['ot'], $_REQUEST['oid'])) {
+       $owner_type = abs($_REQUEST['ot']);
+       $owner_id   = abs($_REQUEST['oid']);
+} else if (isset($_SESSION['fs_owner_type'], $_SESSION['fs_owner_id'], $_SESSION['fs_folder_id'])) {
+       $owner_type = abs($_SESSION['fs_owner_type']);
+       $owner_id   = abs($_SESSION['fs_owner_id']);
+} else {
+       $owner_type = WORKSPACE_COURSE;
+}
+
+if (isset($_REQUEST['folder'])) {
+       $folder_id = abs($_REQUEST['folder']);
+} else if (isset($_SESSION['fs_folder_id'])) {
+       $folder_id = abs($_SESSION['fs_folder_id']);
+} else {
+       $folder_id = 0;
+}
+
+// init the owner_id if not currently set
+if (!isset($owner_id)) {
+       if ($owner_type == WORKSPACE_COURSE) {
+               $owner_id = $_SESSION['course_id'];
+       } else if ($owner_type == WORKSPACE_PERSONAL) {
+               $owner_id = $_SESSION['member_id'];
+       } else if ($owner_type == WORKSPACE_GROUP) {
+               $owner_id = $group_id;
+       }
+}
+
+$owner_arg_prefix = '?ot='.$owner_type.SEP.'oid='.$owner_id. SEP;
+if (!($owner_status = fs_authenticate($owner_type, $owner_id))) {
+       $msg->addError('ACCESS_DENIED');
+       header('Location: '.url_rewrite('file_storage/index.php', AT_PRETTY_URL_IS_HEADER));
+       exit;
+}
+$_SESSION['fs_owner_type'] = $owner_type;
+$_SESSION['fs_owner_id']   = $owner_id;
+$_SESSION['fs_folder_id']  = $folder_id;
+
+if (isset($_GET['submit_workspace'])) {
+       header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix, AT_PRETTY_URL_IS_HEADER));
+       exit;
+}
+
+// action - Submit Assignment
+if (isset($_GET['assignment']) && (isset($_GET['files']) || isset($_GET['folders']))) {
+       if (isset($_GET['folders'])) {
+               $msg->addError('HAND_IN_FOLDER');
+       } else if (!isset($_GET['files'])) {
+               $msg->addError('NO_ITEM_SELECTED');
+       } else {
+               header('Location: '.AT_BASE_HREF.'file_storage/assignment.php?'.$_SERVER['QUERY_STRING']);
+               exit;
+       }
+}
+// action - View Revisions
+else if (isset($_GET['revisions'], $_GET['files'])) {
+       if (is_array($_GET['files']) && (count($_GET['files']) == 1) && empty($_GET['folders'])) {
+               $file_id = current($_GET['files']);
+               header('Location: '.url_rewrite('file_storage/revisions.php'.$owner_arg_prefix.'id='.$file_id, AT_PRETTY_URL_IS_HEADER));
+               exit;
+       }
+}
+// action - View Comments
+else if (isset($_GET['comments'], $_GET['files'])) {
+       if (is_array($_GET['files']) && (count($_GET['files']) == 1) && empty($_GET['folders'])) {
+               $file_id = current($_GET['files']);
+               header('Location: '.url_rewrite('comments.php'.$owner_arg_prefix.'id='.$file_id, AT_PRETTY_URL_IS_HEADER));
+               exit;
+       }
+}
+// action - Edit File/Folder
+else if (query_bit($owner_status, WORKSPACE_AUTH_WRITE) && isset($_GET['edit']) && (isset($_GET['folders']) || isset($_GET['files']))) {
+       if (is_array($_GET['files']) && (count($_GET['files']) == 1) && empty($_GET['folders'])) {
+               $file_id = current($_GET['files']);
+               header('Location: '.AT_BASE_HREF.'file_storage/edit.php'.$owner_arg_prefix.'id='.$file_id);
+               exit;
+       } else if (is_array($_GET['folders']) && (count($_GET['folders']) == 1) && empty($_GET['files'])) {
+               $folder_id = current($_GET['folders']);
+               header('Location: '.AT_BASE_HREF.'file_storage/edit_folder.php'.$owner_arg_prefix.'id='.$folder_id);
+               exit;
+       }
+}
+// action - Move Files/Folders
+else if (query_bit($owner_status, WORKSPACE_AUTH_WRITE) && isset($_GET['move']) && (isset($_GET['folders']) || isset($_GET['files']))) {
+       header('Location: '.AT_BASE_HREF.'file_storage/move.php'.$owner_arg_prefix.$_SERVER['QUERY_STRING']);
+       exit;
+}
+// action - Download Files/Folders
+else if (isset($_GET['download']) && (isset($_GET['folders']) || isset($_GET['files']))) {
+       if (is_array($_GET['files']) && (count($_GET['files']) == 1) && empty($_GET['folders'])) {
+               $file_id = current($_GET['files']);
+               $sql = "SELECT file_name, file_size FROM ".TABLE_PREFIX."files WHERE file_id=$file_id AND owner_type=$owner_type AND owner_id=$owner_id";
+               $result = mysql_query($sql, $db);
+               if ($row = mysql_fetch_assoc($result)) {
+                       $ext = fs_get_file_extension($row['file_name']);
+
+                       if (isset($mime[$ext]) && $mime[$ext][0]) {
+                               $file_mime = $mime[$ext][0];
+                       } else {
+                               $file_mime = 'application/octet-stream';
+                       }
+                       $file_path = fs_get_file_path($file_id) . $file_id;
+
+                       ob_end_clean();
+                       header("Content-Encoding: none");
+                       header('Content-Type: ' . $file_mime);
+                       header('Content-transfer-encoding: binary'); 
+                       header('Content-Disposition: attachment; filename="'.htmlspecialchars($row['file_name']).'"');
+                       header('Expires: 0');
+                       header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+                       header('Pragma: public');
+                       header('Content-Length: '.$row['file_size']);
+
+                       // see the note in get.php about the use of x-Sendfile
+                       header('x-Sendfile: '.$file_path);
+                       header('x-Sendfile: ', TRUE); // if we get here then it didn't work
+
+                       @readfile($file_path);
+                       exit;
+               }
+       } else {
+               // zip multiple files and folders
+               require(AT_INCLUDE_PATH . 'classes/zipfile.class.php');
+               $zipfile =& new zipfile();
+
+               $zip_file_name = fs_get_workspace($owner_type, $owner_id); // want the name of the workspace
+               $zip_file_name = str_replace(" ","_",$zip_file_name );
+
+               if (is_array($_GET['files'])) {
+                       foreach ($_GET['files'] as $file_id) {
+                               $file_path = fs_get_file_path($file_id) . $file_id;
+                               
+
+                               $sql = "SELECT file_name, UNIX_TIMESTAMP(date) AS date FROM ".TABLE_PREFIX."files WHERE file_id=$file_id AND owner_type=$owner_type AND owner_id=$owner_id";
+                               $result = mysql_query($sql, $db);
+                               if (($row = mysql_fetch_assoc($result)) && file_exists($file_path)) {
+                                       $zipfile->add_file(file_get_contents($file_path), $row['file_name'], $row['date']);
+                               }
+                       }
+               }
+               if (is_array($_GET['folders'])) {
+                       foreach($_GET['folders'] as $folder_id) {
+                               fs_download_folder($folder_id, $zipfile, $owner_type, $owner_id);
+                               $row['title'] = str_replace(" ","_",$row['title']  );
+                               $zipfile->create_dir($row['title']);
+                       }
+
+                       if (count($_GET['folders']) == 1) {
+                               // zip just one folder, use that folder's title as the zip file name
+                               $row = fs_get_folder_by_id($_GET['folders'][0], $owner_type, $owner_id);
+                               if ($row) {
+                                       $zip_file_name = $row['title'];
+                                       $zip_file_name = str_replace(" ","_",$zip_file_name );
+                               }
+                       }
+               }
+               $zipfile->close();
+               $zipfile->send_file($zip_file_name);
+       }
+       exit;
+
+}
+// action - Delete Files/Folders (pre-confirmation)
+else if (query_bit($owner_status, WORKSPACE_AUTH_WRITE) && isset($_GET['delete']) && (isset($_GET['folders']) || isset($_GET['files']))) {
+       $hidden_vars = array();
+       $hidden_vars['folder'] = $folder_id;
+       $hidden_vars['ot']     = $owner_type;
+       $hidden_vars['oid']     = $owner_id;
+       if (isset($_GET['files'])) {
+               $file_list_to_print = '';
+               $files = implode(',', $_GET['files']);
+               $hidden_vars['files'] = $files;
+               $sql = "SELECT file_name FROM ".TABLE_PREFIX."files WHERE file_id IN ($files) AND owner_type=$owner_type AND owner_id=$owner_id ORDER BY file_name";
+               $result = mysql_query($sql, $db);
+               while ($row = mysql_fetch_assoc($result)) {
+                       $file_list_to_print .= '<li style="list-style: none; margin: 0px; padding: 0px 10px;"><img src="images/file_types/'.fs_get_file_type_icon($row['file_name']).'.gif" height="16" width="16" alt="" title="" /> '.htmlspecialchars($row['file_name']).'</li>';
+               }
+               $msg->addConfirm(array('FILE_DELETE', $file_list_to_print), $hidden_vars);
+       }
+               
+       if (isset($_GET['folders'])) {
+               $dir_list_to_print = '';
+               $folders = implode(',', $_GET['folders']);
+               $hidden_vars['folders'] = $folders;
+               $rows = fs_get_folder_by_id($_GET['folders'], $owner_type, $owner_id);
+               foreach ($rows as $row) {
+                       $dir_list_to_print .= '<li style="list-style: none; margin: 0px; padding: 0px 10px;"><img src="images/folder.gif" height="18" width="20" alt="" title="" /> '.htmlspecialchars($row['title']).'</li>';
+               }
+               $msg->addConfirm(array('DIR_DELETE', $dir_list_to_print), $hidden_vars);
+       }
+
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->printConfirm();
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+
+}
+// action - Confirm Delete Files/Folders
+else if (query_bit($owner_status, WORKSPACE_AUTH_WRITE) && isset($_POST['submit_yes'])) {
+
+       // handle the delete
+       if (isset($_POST['files'])) {
+               $files = explode(',', $_POST['files']);
+       }
+       if (isset($_POST['folders'])) {
+               $folders = explode(',', $_POST['folders']);
+       }
+       if (isset($files)) {
+               foreach ($files as $file) {
+                       fs_delete_file($file, $owner_type, $owner_id);
+               }
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       }
+
+       if (isset($folders)) {
+               foreach ($folders as $folder) {
+                       fs_delete_folder($folder, $owner_type, $owner_id);
+               }
+               $msg->addFeedback('DIR_DELETED');
+       }
+
+       header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.abs($_POST['folder']), AT_PRETTY_URL_IS_HEADER));
+       exit;
+}
+// action - Cancel Delete
+else if (query_bit($owner_status, WORKSPACE_AUTH_WRITE) && isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.abs($_POST['folder']), AT_PRETTY_URL_IS_HEADER));
+       exit;
+
+// action - Create Folder
+} else if (query_bit($owner_status, WORKSPACE_AUTH_WRITE) && isset($_POST['create_folder'])) {
+       // create a new folder
+       $_POST['new_folder_name'] = trim($_POST['new_folder_name']);
+
+       if (!$_POST['new_folder_name']) {
+               $msg->addError(array('EMPTY_FIELDS', _AT('name')));
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['new_folder_name'] = $addslashes($_POST['new_folder_name']);
+
+               $parent_folder_id = abs($_POST['folder']);
+
+               $sql = "INSERT INTO ".TABLE_PREFIX."folders VALUES (NULL, $parent_folder_id, $owner_type, $owner_id, '$_POST[new_folder_name]')";
+               $result = mysql_query($sql, $db);
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.$parent_folder_id, AT_PRETTY_URL_IS_HEADER));
+               exit;
+       }
+}
+// action - Upload
+else if (query_bit($owner_status, WORKSPACE_AUTH_WRITE) && isset($_POST['upload'])) {
+       // handle the file upload
+       $_POST['comments'] = trim($_POST['comments']);
+
+       $parent_folder_id = abs($_POST['folder']);
+
+       if ($_FILES['file']['error'] == UPLOAD_ERR_INI_SIZE) {
+               $msg->addError(array('FILE_TOO_BIG', get_human_size(megabytes_to_bytes(substr(ini_get('upload_max_filesize'), 0, -1)))));
+
+       } else if (!isset($_FILES['file']['name']) || ($_FILES['file']['error'] == UPLOAD_ERR_NO_FILE) || ($_FILES['file']['size'] == 0)) {
+               $msg->addError('FILE_NOT_SELECTED');
+
+       } else if ($_FILES['file']['error'] || !is_uploaded_file($_FILES['file']['tmp_name'])) {
+               $msg->addError('FILE_NOT_SAVED');
+       }
+
+       // check that we own this folder
+       if ($parent_folder_id) {
+               $sql = "SELECT folder_id FROM ".TABLE_PREFIX."folders WHERE folder_id=$parent_folder_id AND owner_type=$owner_type AND owner_id=$owner_id";
+               $result = mysql_query($sql, $db);
+               if (!$row = mysql_fetch_assoc($result)) {
+                       $msg->addError('ACCESS_DENIED');
+                       header('Location: '.AT_BASE_HREF.'file_storage/index.php');
+                       exit;
+               }
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['description'] = $addslashes(trim($_POST['description']));
+               $_FILES['file']['name'] = addslashes($_FILES['file']['name']);
+
+               if ($_POST['comments']) {
+                       $num_comments = 1;
+               } else {
+                       $num_comments = 0;
+               }
+
+               $sql = "INSERT INTO ".TABLE_PREFIX."files VALUES (NULL, $owner_type, $owner_id, $_SESSION[member_id], $parent_folder_id, 0, NOW(), $num_comments, 0, '{$_FILES['file']['name']}', {$_FILES['file']['size']}, '$_POST[description]')";
+               $result = mysql_query($sql, $db);
+
+               if ($result && ($file_id = mysql_insert_id($db))) {
+                       $path = fs_get_file_path($file_id);
+                       move_uploaded_file($_FILES['file']['tmp_name'], $path . $file_id);
+
+                       // check if this file name already exists
+                       $sql = "SELECT file_id, num_revisions FROM ".TABLE_PREFIX."files WHERE owner_type=$owner_type AND owner_id=$owner_id AND folder_id=$parent_folder_id AND file_id<>$file_id AND file_name='{$_FILES['file']['name']}' AND parent_file_id=0 ORDER BY file_id DESC LIMIT 1";
+                       $result = mysql_query($sql, $db);
+                       if ($row = mysql_fetch_assoc($result)) {
+                               if ($_config['fs_versioning']) {
+                                       $sql = "UPDATE ".TABLE_PREFIX."files SET parent_file_id=$file_id, date=date WHERE file_id=$row[file_id]";
+                                       $result = mysql_query($sql, $db);
+
+                                       $sql = "UPDATE ".TABLE_PREFIX."files SET num_revisions=$row[num_revisions]+1, date=date WHERE file_id=$file_id";
+                                       $result = mysql_query($sql, $db);
+                               } else {
+                                       fs_delete_file($row['file_id'], $owner_type, $owner_id);
+                               }
+                       }
+
+                       $msg->addFeedback('FILE_UPLOADED');
+               } else {
+                       $msg->addError('FILE_NOT_SAVED');
+               }
+       }
+       header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.$parent_folder_id, AT_PRETTY_URL_IS_HEADER));
+       exit;
+} else if ((isset($_GET['delete']) || isset($_GET['download']) || isset($_GET['move']) || isset($_GET['edit']) || isset($_GET['assignment'])) && !isset($_GET['files']) && !isset($_GET['folders'])) {
+       $msg->addError('NO_ITEM_SELECTED');
+}
+
+if (query_bit($owner_status, WORKSPACE_AUTH_WRITE)) {
+       $onload = 'hideform(\'upload\'); hideform(\'c_folder\');';
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$orders = array('asc' => 'desc', 'desc' => 'asc');
+$cols   = array('file_name' => 1, 'file_size' => 1, 'date' => 1);
+
+if (isset($_GET['asc'])) {
+       $order = 'asc';
+       $col   = isset($cols[$_GET['asc']]) ? $_GET['asc'] : 'file_name';
+} else if (isset($_GET['desc'])) {
+       $order = 'desc';
+       $col   = isset($cols[$_GET['desc']]) ? $_GET['desc'] : 'file_name';
+} else {
+       // no order set
+       $order = 'asc';
+       $col   = 'file_name';
+}
+
+$folder_path = fs_get_folder_path($folder_id, $owner_type, $owner_id);
+
+$folders = fs_get_folder_by_pid($folder_id, $owner_type, $owner_id);
+
+$files = array();
+$sql = "SELECT * FROM ".TABLE_PREFIX."files WHERE folder_id=$folder_id AND owner_type=$owner_type AND owner_id=$owner_id AND parent_file_id=0 ORDER BY $col $order";
+$result = mysql_query($sql, $db);
+
+while ($row = mysql_fetch_assoc($result)) {
+       $files[] = $row;
+}
+
+?>
+
+<?php if (query_bit($owner_status, WORKSPACE_AUTH_WRITE)): ?>
+       <form method="post" action="<?php echo 'file_storage/index.php'.$owner_arg_prefix; ?>" enctype="multipart/form-data" name="form0">
+       <input type="hidden" name="folder" value="<?php echo $folder_id; ?>" />
+       <div style="float:right;">
+               <div style="margin: 0px auto; width: 90%;">     
+                       <div class="input-form" style="width: 23em; float: right;">
+                               <div class="row">
+                                       <h3><a href="file_storage/index.php" onclick="javascript:toggleform('c_folder'); return false;" style="font-family: Helevetica, Arial, sans-serif;" onmouseover="this.style.cursor='pointer'"><?php echo _AT('create_folder'); ?></a></h3>
+                               </div>
+                               <div  id="c_folder">
+                                       <div class="row">
+                                               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="fname"><?php echo _AT('name'); ?></label><br />
+                                               <input type="text" id="fname" name="new_folder_name" size="20" />
+                                       </div>
+                                       <div class="row buttons">
+                                               <input type="submit" name="create_folder" value="<?php echo _AT('create'); ?>" />
+                                       </div>
+                               </div>
+                       </div>
+       
+       
+                       <div class="input-form" style="float: left; width: 23em;">
+                               <div class="row">
+                                       <h3><a href="file_storage/index.php" onclick="javascript:toggleform('upload'); return false;" style="font-family: Helevetica, Arial, sans-serif;" onmouseover="this.style.cursor='pointer'"><?php echo _AT('new_file'); ?></a></h3>
+                               </div>
+                               <div id="upload">
+                                       <div class="row">
+                                               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="file"><?php echo _AT('upload_file'); ?></label><br />
+                                               <input type="file" name="file" id="file" />
+                                               <br /><?php echo _AT('or'); ?> <a href="file_storage/new.php<?php echo $owner_arg_prefix; ?>folder=<?php echo $folder_id; ?>"><?php echo _AT('file_manager_new'); ?></a>
+                                       </div>
+                                       <div class="row">
+                                               <label for="description"><?php echo _AT('description'); ?></label><br />
+                                               <textarea name="description" id="description" rows="1" cols="20"></textarea>
+                                       </div>
+                                       <div class="row buttons">
+                                               <input type="submit" name="upload" value="<?php echo _AT('upload'); ?>" />
+                                       </div>
+                               </div>
+                       </div>
+       
+               </div>
+       </div>
+       </form>
+
+<?php endif; ?>
+
+<?php
+if ($_SESSION['groups']) {
+       $file_storage_groups = array();
+       $groups_list = implode(',',$_SESSION['groups']);
+       $sql = "SELECT G.type_id, G.title, G.group_id FROM ".TABLE_PREFIX."file_storage_groups FS INNER JOIN ".TABLE_PREFIX."groups G USING (group_id) WHERE FS.group_id IN ($groups_list) ORDER BY G.type_id, G.title";
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_assoc($result)) {
+               $file_storage_groups[] = $row;
+       }
+}
+
+if (authenticate(AT_PRIV_ASSIGNMENTS, AT_PRIV_RETURN)) {
+       $file_storage_assignments = array();
+       $sql = "SELECT * FROM ".TABLE_PREFIX."assignments WHERE course_id=$_SESSION[course_id] ORDER BY title";
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_assoc($result)) {
+               $file_storage_assignments[] = $row;
+       }
+}
+?>
+
+<form method="get" action="file_storage/index.php" name="form">
+<input type="hidden" name="folder" value="<?php echo $folder_id; ?>" />
+<input type="hidden" name="oid" value="<?php echo $owner_id; ?>" />
+<table class="data">
+<colgroup>
+       <?php if ($col == 'file_name'): ?>
+               <col />
+               <col class="sort" />
+               <col span="5" />
+       <?php elseif($col == 'file_size'): ?>
+               <col span="5" />
+               <col class="sort" />
+               <col />
+       <?php elseif($col == 'date'): ?>
+               <col span="6" />
+               <col class="sort" />
+       <?php endif; ?>
+</colgroup>
+<thead>
+<tr>
+       <td colspan="7">
+               <?php echo _AT('workspace'); ?> 
+               <select name="ot" id="ot">
+                       <option value="1" <?php if ($owner_type == WORKSPACE_COURSE) { echo 'selected="selected"'; } ?>><?php echo _AT('course_files'); ?></option>
+                       <?php if ($_SESSION['member_id'] && $_SESSION['enroll']): ?>
+                               <option value="2" <?php if ($owner_type == WORKSPACE_PERSONAL) { echo 'selected="selected"'; } ?>><?php echo _AT('my_files'); ?></option>
+                       <?php endif; ?>
+                       <?php if ($file_storage_groups): ?>
+                               <optgroup label="<?php echo _AT('groups'); ?>">
+                                       <?php foreach ($file_storage_groups as $group): ?>
+                                               <option value="<?php echo WORKSPACE_GROUP; ?>_<?php echo $group['group_id']; ?>" <?php if ($owner_type == WORKSPACE_GROUP && $owner_id == $group['group_id']) { echo 'selected="selected"'; } ?>><?php echo $group['title']; ?></option>
+                                       <?php endforeach; ?>
+                               </optgroup>
+                       <?php endif; ?>
+                       <?php if (authenticate(AT_PRIV_ASSIGNMENTS, AT_PRIV_RETURN) && count($file_storage_assignments) != 0) : ?>
+                               <optgroup label="<?php echo _AT('assignments'); ?>">
+                                       <?php foreach ($file_storage_assignments as $assignment): ?>
+                                               <option value="<?php echo WORKSPACE_ASSIGNMENT; ?>_<?php echo $assignment['assignment_id']; ?>" <?php if ($owner_type == WORKSPACE_ASSIGNMENT && $owner_id == $assignment['assignment_id']) { echo 'selected="selected"'; } ?>><?php echo $assignment['title']; ?></option>
+                                       <?php endforeach; ?>
+                               </optgroup>
+                       <?php endif; ?>
+               </select>
+               <input type="submit" name="submit_workspace" value="<?php echo _AT('go'); ?>" class="button" />
+
+               <br />
+               <?php echo _AT('current_path'); ?>
+                       <a href="<?php 
+                       echo url_rewrite($_SERVER['PHP_SELF'].$owner_arg_prefix.'folder=0'); ?>"><?php echo _AT('home'); ?></a>
+               <?php foreach ($folder_path as $folder_info): ?>
+                       <?php if ($folder_info['folder_id'] == $folder_id): ?>
+                               » <?php echo htmlspecialchars($folder_info['title']); ?>
+                               <?php $parent_folder_id = $folder_info['parent_folder_id']; ?>
+                       <?php else: ?>
+                               » <a href="<?php echo url_rewrite($_SERVER['PHP_SELF'].$owner_arg_prefix.'folder='.$folder_info['folder_id']); ?>"><?php echo htmlspecialchars($folder_info['title']); ?></a>
+                       <?php endif; ?>
+               <?php endforeach; ?>
+       </td>
+</tr>
+<tr>
+
+       <th align="left" width="10"><input type="checkbox" value="<?php echo _AT('select_all'); ?>" id="all" title="<?php echo _AT('select_all'); ?>" name="selectall" onclick="CheckAll();" /></th>
+       <th scope="col"><a href="<?php echo url_rewrite($_SERVER['PHP_SELF'] . $owner_arg_prefix . 'folder='.$folder_id.SEP.$orders[$order].'=file_name'); ?>"><?php echo _AT('file');      ?></a></th>
+       <th scope="col"><?php echo _AT('author');    ?></th>
+       <th scope="col"><?php if ($_config['fs_versioning']): ?><?php echo _AT('revisions'); ?><?php endif; ?></th>
+       <th scope="col"><?php echo _AT('comments');  ?></th>
+       <th scope="col"><a href="<?php echo url_rewrite($_SERVER['PHP_SELF'] . $owner_arg_prefix . 'folder='.$folder_id.SEP.$orders[$order].'=file_size'); ?>"><?php echo _AT('size'); ?></a></th>
+       <th scope="col"><a href="<?php echo url_rewrite($_SERVER['PHP_SELF'] . $owner_arg_prefix . 'folder='.$folder_id.SEP.$orders[$order].'=date'); ?>"><?php echo _AT('date'); ?></a></th>
+</tr>
+
+</thead>
+<tfoot>
+<tr>
+       <td colspan="7">
+               <input type="submit" name="download" value="<?php echo _AT('download'); ?>" />
+               <?php if (query_bit($owner_status, WORKSPACE_AUTH_WRITE)): ?>
+                       <?php if (($owner_type != WORKSPACE_COURSE) && !(($owner_type == WORKSPACE_PERSONAL) && ($_SESSION['is_admin'] || authenticate(AT_PRIV_GROUPS,true))) ): ?>
+                               <input type="submit" name="assignment" value="<?php echo _AT('hand_in'); ?>" />
+                       <?php endif; ?>
+                       <input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" />
+                       <input type="submit" name="move" value="<?php echo _AT('move'); ?>" />
+                       <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" />
+               <?php endif; ?>
+       </td>
+</tr>
+</tfoot>
+<tbody>
+<?php if ($folder_id): ?>
+       <tr>
+               <td colspan="7"><a href="<?php echo url_rewrite($_SERVER['PHP_SELF'].$owner_arg_prefix.'folder='.intval($folder_path[count($folder_path)-1]['parent_folder_id'])); ?>"><img src="images/arrowicon.gif" border="0" height="" width="" alt="" /> <?php echo _AT('back'); ?></a></td>
+       </tr>
+<?php endif; ?>
+<?php if ($folders || $files): ?>
+       <?php foreach ($folders as $folder_info): ?>
+               <tr onmousedown="document.form['f<?php echo $folder_info['folder_id']; ?>'].checked = !document.form['f<?php echo $folder_info['folder_id']; ?>'].checked; rowselectbox(this, document.form['f<?php echo $folder_info['folder_id']; ?>'].checked, 'checkbuttons(false)');" id="r_<?php echo $folder_info['folder_id']; ?>_1">
+                       <td width="10"><input type="checkbox" name="folders[]" value="<?php echo $folder_info['folder_id']; ?>" id="f<?php echo $folder_info['folder_id']; ?>" onmouseup="this.checked=!this.checked" /></td>
+                       <td><img src="images/folder.gif" height="18" width="20" alt="" /> <a href="<?php echo url_rewrite($_SERVER['PHP_SELF'].$owner_arg_prefix.'folder='.
+                       $folder_info['folder_id']); ?>"><?php echo htmlspecialchars($folder_info['title']); ?></a></td>
+                       <td>&nbsp;</td>
+                       <td>&nbsp;</td>
+                       <td>&nbsp;</td>
+                       <td>&nbsp;</td>
+                       <td>&nbsp;</td>
+               </tr>
+       <?php endforeach; ?>
+       <?php foreach ($files as $file_info): ?>
+               <tr onmousedown="document.form['r<?php echo $file_info['file_id']; ?>'].checked = !document.form['r<?php echo $file_info['file_id']; ?>'].checked; rowselectbox(this, document.form['r<?php echo $file_info['file_id']; ?>'].checked, 'checkbuttons(false)');" id="r_<?php echo $file_info['file_id']; ?>_0">
+                       <td valign="top" width="10"><input type="checkbox" name="files[]" value="<?php echo $file_info['file_id']; ?>" id="r<?php echo $file_info['file_id']; ?>" onmouseup="this.checked=!this.checked" /></td>
+                       <td valign="top">
+                               <img src="images/file_types/<?php echo fs_get_file_type_icon($file_info['file_name']); ?>.gif" height="16" width="16" alt="" title="" /> <?php echo htmlspecialchars($file_info['file_name']); ?>
+                               <?php if ($file_info['description']): ?>
+                                       <p class="fm-desc"><?php echo htmlspecialchars($file_info['description']); ?></p>
+                               <?php endif; ?>
+                       </td>
+                       <td valign="top"><?php echo get_display_name($file_info['member_id']); ?></td>
+                       <td valign="top">
+                               <?php if ($_config['fs_versioning']): ?>
+                                       <?php if ($file_info['num_revisions']): 
+                                               if ($file_info['num_revisions'] == 1) {
+                                                       $lang_var = 'fs_revision';
+                                               } else {
+                                                       $lang_var = 'fs_revisions';
+                                               }
+                                               ?>
+                                               
+                                               <a href="<?php echo url_rewrite('file_storage/revisions.php'.$owner_arg_prefix.'id='.$file_info['file_id']); ?>"><?php echo _AT($lang_var, $file_info['num_revisions']); ?></a>
+                                       <?php else: ?>
+                                               -
+                                       <?php endif; ?>
+                               <?php endif; ?>
+                       </td>
+                       <td valign="top">
+                       <?php 
+                       if ($file_info['num_comments'] == 1) {
+                               $lang_var = 'fs_comment';
+                       } else {
+                               $lang_var = 'fs_comments';
+                       }
+                       ?>
+                       <a href="<?php echo url_rewrite('file_storage/comments.php'.$owner_arg_prefix.'id='.$file_info['file_id']); ?>"><?php echo _AT($lang_var, $file_info['num_comments']); ?></a></td>
+                       <td align="right" valign="top"><?php echo get_human_size($file_info['file_size']); ?></td>
+                       <td align="right" valign="top"><?php echo AT_date(_AT('filemanager_date_format'), $file_info['date'], AT_DATE_MYSQL_DATETIME); ?></td>
+               </tr>
+       <?php endforeach; ?>
+<?php else: ?>
+       <tr>
+               <td colspan="7"><?php echo _AT('none_found'); ?></td>
+       </tr>
+<?php endif; ?>
+</tbody>
+</table>
+</form>
+
+<script type="text/javascript">
+// <!--
+function checkbuttons(state) {
+       document.form.selectall.checked = state;
+
+       var num_files_checked = 0;
+       var num_folders_checked = 0;
+       for (var i=0;i<document.form.elements.length;i++) {
+               var e = document.form.elements[i];
+               if ((e.name == 'folders[]') && (e.type=='checkbox') && e.checked) {
+                       num_folders_checked++;
+               } else if ((e.name == 'files[]') && (e.type=='checkbox') && e.checked) {
+                       num_files_checked++;
+               }
+       }
+       if (num_files_checked + num_folders_checked > 1) {
+               if (document.form.edit)
+                       document.form.edit.disabled = true;
+       } else {
+               if (document.form.edit)
+                       document.form.edit.disabled = false;
+       }
+}
+function CheckAll() {
+       var state = document.form.selectall.checked;
+       for (var i=0;i<document.form.elements.length;i++)       {
+               var e = document.form.elements[i];
+               if ((e.name == 'folders[]') && (e.type=='checkbox')) {
+                       e.checked = state;
+                       rowselectbox(document.getElementById('r_' + e.value + '_1'), state, 'checkbuttons(' + state + ')');
+               } else if ((e.name == 'files[]') && (e.type=='checkbox')) {
+                       e.checked = state;
+                       rowselectbox(document.getElementById('r_' + e.value + '_0'), state, 'checkbuttons(' + state + ')');
+               }
+       }
+}
+
+function hideform(id) {
+       document.getElementById(id).style.display='none';
+}
+
+function toggleform(id) {
+       if (document.getElementById(id).style.display == "none") {
+               //show
+               document.getElementById(id).style.display='';   
+
+               if (id == "c_folder") {
+                       document.form0.new_folder_name.focus();
+               } else if (id == "upload") {
+                       document.form0.file.focus();
+               }
+
+       } else {
+               //hide
+               document.getElementById(id).style.display='none';
+       }
+}
+
+// -->
+</script>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/file_storage/move.php b/file_storage/move.php
new file mode 100644 (file)
index 0000000..541b23b
--- /dev/null
@@ -0,0 +1,129 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'lib/file_storage.inc.php');\r
+\r
+$owner_type = abs($_REQUEST['ot']);\r
+$owner_id   = abs($_REQUEST['oid']);\r
+$owner_arg_prefix = '?ot='.$owner_type.SEP.'oid='.$owner_id. SEP;\r
+if (!($owner_status = fs_authenticate($owner_type, $owner_id)) || !query_bit($owner_status, WORKSPACE_AUTH_WRITE)) { \r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: '.url_rewrite('file_storage/index.php', AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+}\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.abs($_POST['folder']), AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       $_POST['new_folder'] = abs($_POST['new_folder']);\r
+\r
+       if ($_POST['folder'] == $_POST['new_folder']) {\r
+               // src = dest\r
+               $msg->addFeedback('CANCELLED');\r
+               header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.$_POST['new_folder'], AT_PRETTY_URL_IS_HEADER));\r
+               exit;\r
+       }\r
+\r
+       if (isset($_POST['files'])) {\r
+               foreach ($_POST['files'] as $file) {\r
+                       $file = abs($file);\r
+                       // check if this file name already exists\r
+                       $sql = "SELECT file_name FROM ".TABLE_PREFIX."files WHERE file_id=$file";\r
+                       $result = mysql_query($sql, $db);\r
+                       $row = mysql_fetch_assoc($result);\r
+\r
+                       $sql = "SELECT file_id FROM ".TABLE_PREFIX."files WHERE folder_id={$_POST['new_folder']} AND file_id<>$file AND file_name='{$row['file_name']}' AND parent_file_id=0 AND owner_type=$owner_type AND owner_id=$owner_id ORDER BY file_id DESC LIMIT 1";\r
+                       $result = mysql_query($sql, $db);\r
+                       if ($row = mysql_fetch_assoc($result)) {\r
+                               fs_delete_file($row['file_id'], $owner_type, $owner_id);\r
+                       }\r
+\r
+                       $sql = "UPDATE ".TABLE_PREFIX."files SET folder_id={$_POST['new_folder']}, date=date WHERE file_id=$file AND owner_type=$owner_type AND owner_id=$owner_id";\r
+                       mysql_query($sql, $db);\r
+               }\r
+               $msg->addFeedback('FILES_MOVED');\r
+       }\r
+\r
+       if (isset($_POST['folders'])) {\r
+               foreach ($_POST['folders'] as $folder) {\r
+                       $file = abs($file);\r
+                       $sql = "UPDATE ".TABLE_PREFIX."folders SET parent_folder_id={$_POST['new_folder']} WHERE folder_id=$folder AND owner_type=$owner_type AND owner_id=$owner_id";\r
+                       mysql_query($sql, $db);\r
+               }\r
+               $msg->addFeedback('DIRS_MOVED');\r
+       }\r
+       header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.$_POST['new_folder'], AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$folder_id = abs($_GET['folder']);\r
+\r
+// can't use fs_get_folders() because we want all folders, not just at one level\r
+$folders = array();\r
+$sql = "SELECT folder_id, parent_folder_id, title FROM ".TABLE_PREFIX."folders WHERE owner_type=$owner_type AND owner_id=$owner_id ORDER BY parent_folder_id, title";\r
+$result = mysql_query($sql, $db);\r
+while ($row = mysql_fetch_assoc($result)) {\r
+       $folders[$row['parent_folder_id']][$row['folder_id']] = $row;\r
+}\r
+\r
+?>\r
+\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<?php if ($_GET['files']): foreach ($_GET['files'] as $tmpfile): ?>\r
+       <input type="hidden" name="files[]" value="<?php echo $tmpfile; ?>" />\r
+<?php endforeach; endif; ?>\r
+\r
+<?php if ($_GET['folders']): foreach ($_GET['folders'] as $tmpfolder): ?>\r
+       <input type="hidden" name="folders[]" value="<?php echo $tmpfolder; ?>" />\r
+<?php endforeach; endif; ?>\r
+\r
+<input type="hidden" name="folder" value="<?php echo $folder_id; ?>" />\r
+<input type="hidden" name="ot" value="<?php echo $owner_type; ?>" />\r
+<input type="hidden" name="oid" value="<?php echo $owner_id; ?>" />\r
+<div class="input-form">\r
+       <div class="row">\r
+               <p><?php echo _AT('select_directory'); ?></p>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <ul>\r
+                       <li class="folders"><input type="radio" name="new_folder" value="0" id="fhome" <?php\r
+                               if ($folder_id == 0) {\r
+                                       echo ' checked="checked"';\r
+                               }\r
+                       ?>/><label for="fhome"><?php echo fs_get_workspace($owner_type, $owner_id); ?></label>\r
+                       <?php \r
+                               if ($folder_id == $current_folder_id) {\r
+                                       echo ' '._AT('current_location');\r
+                               }\r
+                       ?>\r
+                       <?php fs_print_folders($folder_id, 0, $folders); ?>\r
+                       </li>\r
+               </ul>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('move'); ?>" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/file_storage/new.php b/file_storage/new.php
new file mode 100644 (file)
index 0000000..03277e6
--- /dev/null
@@ -0,0 +1,159 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/file_storage.inc.php');
+
+$owner_type = abs($_REQUEST['ot']);
+$owner_id   = abs($_REQUEST['oid']);
+$owner_arg_prefix = '?ot='.$owner_type.SEP.'oid='.$owner_id. SEP;
+if (!($owner_status = fs_authenticate($owner_type, $owner_id)) || !query_bit($owner_status, WORKSPACE_AUTH_WRITE)) { 
+       $msg->addError('ACCESS_DENIED');
+       header('Location: index.php');
+       exit;
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php'.$owner_arg_prefix.'folder='.abs($_POST['folder']));
+       exit;
+} else if (isset($_POST['submit'])) {
+       $_POST['comments'] = trim($_POST['comments']);
+       $_POST['name'] = trim($_POST['name']);
+
+       $parent_folder_id = abs($_POST['folder']);
+
+       // check that we own this folder
+       if ($parent_folder_id) {
+               $sql = "SELECT folder_id FROM ".TABLE_PREFIX."folders WHERE folder_id=$parent_folder_id AND owner_type=$owner_type AND owner_id=$owner_id";
+               $result = mysql_query($sql, $db);
+               if (!$row = mysql_fetch_assoc($result)) {
+                       $msg->addError('ACCESS_DENIED');
+                       header('Location: index.php');
+                       exit;
+               }
+       }
+
+       if (!$_POST['name']) {
+               $msg->addError(array('EMPTY_FIELDS', _AT('file_name')));
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['description'] = $addslashes(trim($_POST['description']));
+               $_POST['comment'] = $addslashes(trim($_POST['comment']));
+               $_POST['name'] = $addslashes($_POST['name']);
+               $_POST['body'] = $stripslashes($_POST['body']); // file gets saved to disk not db, so no need to escape.
+
+               if ($_POST['comment']) {
+                       $num_comments = 1;
+               } else {
+                       $num_comments = 0;
+               }
+
+               $size = strlen($_POST['body']);
+               $sql = "INSERT INTO ".TABLE_PREFIX."files VALUES (NULL, $owner_type, $owner_id, $_SESSION[member_id], $parent_folder_id, 0, NOW(), $num_comments, 0, '$_POST[name]',$size, '$_POST[description]')";
+               $result = mysql_query($sql, $db);
+
+               if ($result && ($file_id = mysql_insert_id($db))) {
+                       $file_path = fs_get_file_path($file_id) . $file_id;
+                       $fp = fopen($file_path, 'wb');
+                       fwrite($fp, $_POST['body'], $size);
+                       fclose($fp);
+
+                       // check if this file name already exists
+                       $sql = "SELECT file_id, num_revisions FROM ".TABLE_PREFIX."files WHERE owner_type=$owner_type AND owner_id=$owner_id AND folder_id=$parent_folder_id AND file_id<>$file_id AND file_name='$_POST[name]' AND parent_file_id=0 ORDER BY file_id DESC LIMIT 1";
+                       $result = mysql_query($sql, $db);
+                       if ($row = mysql_fetch_assoc($result)) {
+                               if ($_config['fs_versioning']) {
+                                       $sql = "UPDATE ".TABLE_PREFIX."files SET parent_file_id=$file_id, date=date WHERE file_id=$row[file_id]";
+                                       $result = mysql_query($sql, $db);
+
+                                       $sql = "UPDATE ".TABLE_PREFIX."files SET num_revisions=$row[num_revisions]+1, date=date WHERE file_id=$file_id";
+                                       $result = mysql_query($sql, $db);
+                               } else {
+                                       fs_delete_file($row['file_id'], $owner_type, $owner_id);
+                               }
+                       }
+
+                       if ($_POST['comment']){
+                               $sql = "INSERT INTO ".TABLE_PREFIX."files_comments VALUES (NULL, $file_id, $_SESSION[member_id], NOW(), '{$_POST['comment']}')";
+                               mysql_query($sql, $db);
+                       }
+
+                       $msg->addFeedback(array('FILE_SAVED', $_POST['name']));
+                       header('Location: index.php'.$owner_arg_prefix.'folder='.$parent_folder_id);
+                       exit;
+               }
+       }
+}
+
+$onload = 'document.form.name.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if (($_POST['setvisual'] && !$_POST['settext']) || $_GET['setvisual']) {
+       require(AT_INCLUDE_PATH.'lib/tinymce.inc.php');
+
+       load_editor('body');
+}
+if (isset($_POST['description'])) {
+       $_POST['description'] = $stripslashes($_POST['description']);
+       $_POST['name']        = $stripslashes($_POST['name']);
+       $_POST['comment']     = $stripslashes($_POST['comment']);
+       $_POST['body']        = $stripslashes($_POST['body']);
+}
+?>
+<form action="<?php echo $_SERVER['PHP_SELF'] . $owner_arg_prefix; ?>" method="post" name="form">
+<input type="hidden" name="folder" value="<?php echo abs($_REQUEST['folder']); ?>" />
+<div class="input-form">
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="name"><?php echo _AT('file_name'); ?></label><br />
+               <input type="text" name="name" id="name" value="<?php echo htmlspecialchars($_POST['name']); ?>" size="40" maxlength="70" />
+       </div>
+
+       <div class="row">
+               <label for="description"><?php echo _AT('description'); ?></label><br />
+               <textarea name="description" id="description" cols="30" rows="2"><?php echo htmlspecialchars($_POST['description']); ?></textarea>
+       </div>
+
+       <div class="row">
+               <label for="comment"><?php echo _AT('revision_comment'); ?></label><br />
+               <textarea name="comment" id="comment" cols="30" rows="2"><?php echo htmlspecialchars($_POST['comment']); ?></textarea>
+       </div>
+
+       <div class="row">
+               <?php
+                       if (($_POST['setvisual'] && !$_POST['settext']) || $_GET['setvisual']){
+                               echo '<input type="hidden" name="setvisual" value="'.$_POST['setvisual'].'" />';
+                               echo '<input type="submit" name="settext" value="'._AT('switch_text').'" />';
+                       } else {
+                               echo '<input type="submit" name="setvisual" value="'._AT('switch_visual').'" />';
+                       }
+               ?>
+       </div>
+
+       <div class="row">
+               <label for="body"><?php echo _AT('contents');  ?></label><br />
+               <textarea name="body" id="body" rows="25" cols="30"><?php echo htmlspecialchars($_POST['body']); ?></textarea>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>"  />             
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/file_storage/revisions.php b/file_storage/revisions.php
new file mode 100644 (file)
index 0000000..bab52da
--- /dev/null
@@ -0,0 +1,142 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'lib/filemanager.inc.php'); // for get_human_size()\r
+require(AT_INCLUDE_PATH.'lib/file_storage.inc.php');\r
+\r
+$owner_type = abs($_REQUEST['ot']);\r
+$owner_id   = abs($_REQUEST['oid']);\r
+$owner_arg_prefix = '?ot='.$owner_type.SEP.'oid='.$owner_id. SEP;\r
+if (!($owner_status = fs_authenticate($owner_type, $owner_id))) {\r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: '.url_rewrite('file_storage/index.php', AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+}\r
+\r
+if (isset($_GET['download'], $_GET['revision'])) {\r
+       header('Location: '.AT_BASE_HREF.'file_storage/index.php'.$owner_arg_prefix.'download=1'.SEP.'files'.urlencode('[]').'='.$_GET['revision']);\r
+       exit;\r
+} else if (query_bit($owner_status, WORKSPACE_AUTH_WRITE) && isset($_GET['delete'], $_GET['revision'])) {\r
+       header('Location: '.AT_BASE_HREF.'file_storage/delete_revision.php'.$owner_arg_prefix.'id='.$_GET['revision']);\r
+       exit;\r
+} else if (isset($_GET['cancel'])) {\r
+       header('Location: '.url_rewrite('file_storage/index.php'.$owner_arg_prefix.'folder='.$_GET['folder'], AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+} else if (isset($_GET['comments'])) {\r
+       header('Location: '.url_rewrite('file_storage/comments.php'.$owner_arg_prefix.'id='.$_GET['revision'], AT_PRETTY_URL_IS_HEADER));\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$id = abs($_GET['id']);\r
+\r
+$orders = array('asc' => 'desc', 'desc' => 'asc');\r
+$cols   = array('num_revisions' => 1, 'file_name' => 1, 'date' => 1, 'num_comments' => 1, 'file_size' => 1);\r
+\r
+if (isset($_GET['asc'])) {\r
+       $order = 'asc';\r
+       $col   = isset($cols[$_GET['asc']]) ? $_GET['asc'] : 'num_revisions';\r
+} else if (isset($_GET['desc'])) {\r
+       $order = 'desc';\r
+       $col   = isset($cols[$_GET['desc']]) ? $_GET['desc'] : 'num_revisions';\r
+} else {\r
+       // no order set\r
+       $order = 'desc';\r
+       $col   = 'num_revisions';\r
+}\r
+\r
+$files = fs_get_revisions($id, $owner_type, $owner_id, $col, $order);\r
+$current_file = current($files);\r
+\r
+\r
+usort($files, 'fs_revisions_sort_compare');\r
+\r
+?>\r
+\r
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">\r
+<input type="hidden" name="folder" value="<?php echo $current_file['folder_id']; ?>" />\r
+<input type="hidden" name="ot" value="<?php echo $owner_type; ?>" />\r
+<input type="hidden" name="oid" value="<?php echo $owner_id; ?>" />\r
+<table class="data">\r
+<colgroup>\r
+       <?php if ($col == 'num_revisions'): ?>\r
+               <col />\r
+               <col class="sort" />\r
+               <col span="5" />\r
+       <?php elseif($col == 'file_name'): ?>\r
+               <col span="2" />\r
+               <col class="sort" />\r
+               <col span="4" />\r
+       <?php elseif($col == 'date'): ?>\r
+               <col span="3" />\r
+               <col class="sort" />\r
+               <col span="3" />\r
+       <?php elseif($col == 'num_comments'): ?>\r
+               <col span="4" />\r
+               <col class="sort" />\r
+               <col span="2" />\r
+       <?php elseif($col == 'file_size'): ?>\r
+               <col span="6" />\r
+               <col class="sort" />\r
+       <?php endif; ?>\r
+</colgroup>\r
+<thead>\r
+<tr>\r
+       <th>&nbsp;</th>\r
+       <th><a href="<?php echo $_SERVER['PHP_SELF'] . $owner_arg_prefix . 'id='.$id.SEP.$orders[$order]; ?>=num_revisions"><?php echo _AT('revision');  ?></a></th>\r
+       <th><a href="<?php echo $_SERVER['PHP_SELF'] . $owner_arg_prefix . 'id='.$id.SEP.$orders[$order]; ?>=file_name"><?php echo _AT('file_name'); ?></a></th>\r
+       <th><a href="<?php echo $_SERVER['PHP_SELF'] . $owner_arg_prefix . 'id='.$id.SEP.$orders[$order]; ?>=date"><?php echo _AT('date');      ?></a></th>\r
+       <th><?php echo _AT('author');    ?></th>\r
+       <th><a href="<?php echo $_SERVER['PHP_SELF'] . $owner_arg_prefix . 'id='.$id.SEP.$orders[$order]; ?>=num_comments"><?php echo _AT('comments');  ?></a></th>\r
+       <th><a href="<?php echo $_SERVER['PHP_SELF'] . $owner_arg_prefix . 'id='.$id.SEP.$orders[$order]; ?>=file_size"><?php echo _AT('size');      ?></a></th>\r
+</tr>\r
+\r
+</thead>\r
+<tfoot>\r
+<tr>\r
+       <td colspan="7">\r
+               <input type="submit" name="download" value="<?php echo _AT('download'); ?>" />\r
+               <?php if (query_bit($owner_status, WORKSPACE_AUTH_WRITE)): ?>\r
+                       <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" />\r
+               <?php endif; ?>\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+       </td>\r
+</tr>\r
+</tfoot>\r
+<tbody>\r
+<?php foreach ($files as $file): ?>\r
+       <tr onmousedown="document.form['r<?php echo $file['file_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $file['file_id']; ?>_0">\r
+               <td valign="top"><input type="radio" name="revision" value="<?php echo $file['file_id']; ?>" id="r<?php echo $file['file_id']; ?>" /></td>\r
+               <td valign="top"><?php echo $file['num_revisions']; ?></td>\r
+               <td valign="top">\r
+                               <?php echo $file['file_name']; ?>\r
+                               <?php if ($file['comments']): ?>\r
+                                       <p><?php echo nl2br($file['comments']); ?></p>\r
+                               <?php endif; ?>\r
+               </td>\r
+               <td valign="top"><?php echo AT_date(_AT('filemanager_date_format'), $file['date'], AT_DATE_MYSQL_DATETIME); ?></td>\r
+               <td valign="top"><?php echo get_display_name($file['member_id']); ?></td>\r
+               <td valign="top"><a href="<?php echo url_rewrite('file_storage/comments.php'.$owner_arg_prefix.'id='.$file['file_id']); ?>"><?php echo $file['num_comments']; ?></a></td>\r
+               <td valign="top"><?php echo get_human_size($file['file_size']); ?></td>\r
+       </tr>\r
+<?php endforeach; ?>\r
+</tbody>\r
+</table>\r
+</form>\r
+\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/forum/delete_thread.php b/forum/delete_thread.php
new file mode 100644 (file)
index 0000000..4fdeab6
--- /dev/null
@@ -0,0 +1,138 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/forums.inc.php');
+
+authenticate(AT_PRIV_FORUMS);
+
+$pid  = intval($_REQUEST['pid']);
+$ppid = intval($_REQUEST['ppid']);
+$fid  = intval($_REQUEST['fid']);
+
+if (!valid_forum_user($fid)) {
+       $msg->addError('FORUM_NOT_FOUND');
+       header('Location: list.php');
+       exit;
+}
+
+if (isset($_POST['submit_no'])) {
+       
+       $msg->addFeedback('CANCELLED'); 
+       if ($_POST['nest']) {
+               header('Location: view.php?fid='.$_POST['fid'].SEP.'pid='. ($_POST['ppid'] ? $_POST['ppid'] : $_POST['pid']));
+               exit;
+       } else {
+               header('Location: index.php?fid='.$_POST['fid']);
+               exit;
+       }
+
+       exit;
+
+} else if (isset($_POST['submit_yes'])) {
+       // check if they have access
+       if (!valid_forum_user($fid)) {
+               $msg->addError('FORUM_NOT_FOUND');
+               header('Location: list.php');
+               exit;
+       }
+
+       if ($ppid == 0) {   /* If deleting an entire post */
+               /* First get number of comments from specific post */
+               $sql    = "SELECT * FROM ".TABLE_PREFIX."forums_threads WHERE post_id=$pid AND forum_id=$fid";
+               $result = mysql_query($sql, $db);
+               if (!($row = mysql_fetch_assoc($result))) {
+                       $msg->addError('FORUM_NOT_FOUND');
+                       header('Location: list.php');
+                       exit;
+
+               } // else:
+
+               /* Decrement count for number of posts and topics*/
+               $sql    = "UPDATE ".TABLE_PREFIX."forums SET num_posts=num_posts-1-".$row['num_comments'].", num_topics=num_topics-1, last_post=last_post WHERE forum_id=$fid";
+               $result = mysql_query($sql, $db);
+
+               $sql    = "DELETE FROM ".TABLE_PREFIX."forums_threads WHERE (parent_id=$pid OR post_id=$pid) AND forum_id=$fid";
+               $result = mysql_query($sql, $db);
+
+               $sql    = "DELETE FROM ".TABLE_PREFIX."forums_accessed WHERE post_id=$pid";
+               $result = mysql_query($sql, $db);
+
+       } else {   /* Just deleting a single thread */
+               $sql    = "DELETE FROM ".TABLE_PREFIX."forums_threads WHERE post_id=$pid AND forum_id=$fid";
+               $result = mysql_query($sql, $db);
+               if (mysql_affected_rows($db) == 0) {
+                       $msg->addError('FORUM_NOT_FOUND');
+                       header('Location: list.php');
+                       exit;
+               }
+
+           /* Decrement count of comments in forums_threads table*/
+               $sql    = "UPDATE ".TABLE_PREFIX."forums_threads SET num_comments=num_comments-1, last_comment=last_comment, date=date WHERE post_id=$ppid";
+               $result = mysql_query($sql, $db);
+
+               /* Decrement count of posts in forums table */
+               $sql    = "UPDATE ".TABLE_PREFIX."forums SET num_posts=num_posts-1, last_post=last_post WHERE forum_id=$fid";
+               $result = mysql_query($sql, $db);
+
+       }
+
+       if ($ppid) {
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: view.php?fid='.$fid.SEP.'pid='.$ppid);
+               exit;
+       } else {
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: index.php?fid='.$fid);
+               exit;
+       }
+}
+
+$_pages['forum/index.php?fid='.$fid]['title']    = get_forum_name($fid);
+$_pages['forum/index.php?fid='.$fid]['parent']   = 'forum/list.php';
+$_pages['forum/index.php?fid='.$fid]['children'] = array('forum/new_thread.php?fid='.$fid);
+
+$_pages['forum/new_thread.php?fid='.$fid]['title_var'] = 'new_thread';
+$_pages['forum/new_thread.php?fid='.$fid]['parent']    = 'forum/index.php?fid='.$fid;
+
+$_pages['forum/view.php']['title']  = $post_row['subject'];
+$_pages['forum/view.php']['parent'] = 'forum/index.php?fid='.$fid;
+
+$_pages['forum/delete_thread.php']['title_var'] = 'delete_post';
+$_pages['forum/delete_thread.php']['parent']    = 'forum/index.php?fid='.$fid;
+$_pages['forum/delete_thread.php']['children']  = array();
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+
+$sql = "SELECT * from ".TABLE_PREFIX."forums_threads WHERE post_id = '$pid'";
+$result = mysql_query($sql, $db);
+while ($row = mysql_fetch_assoc($result)){
+       $title = $row['subject'];
+}
+
+$hidden_vars['fid']  = $_GET['fid'];
+$hidden_vars['pid']  = $_GET['pid'];
+$hidden_vars['ppid'] = $_GET['ppid'];
+$hidden_vars['nest'] = $_GET['nest'];
+
+$msg->addConfirm(array('DELETE', $title),$hidden_vars);
+if (($ppid=='') || ($ppid =='0')) {
+       $ppid = '0';
+}
+
+$msg->printConfirm();
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/forum/index.php b/forum/index.php
new file mode 100644 (file)
index 0000000..fcb2613
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+$fid = intval($_GET['fid']);
+
+if (!isset($_GET['fid']) || !$fid) {
+       header('Location: list.php');
+       exit;
+}
+require(AT_INCLUDE_PATH.'lib/forums.inc.php');
+
+if (!valid_forum_user($fid)) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->addError('FORUM_DENIED');
+       $msg->printErrors();
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+}
+
+$_pages['forum/index.php']['title']    = get_forum_name($fid);
+$_pages['forum/index.php']['parent']   = 'forum/list.php';
+$_pages['forum/index.php']['children'] = array('forum/new_thread.php?fid='.$fid);
+
+$_pages['forum/new_thread.php?fid='.$fid]['title_var'] = 'new_thread';
+$_pages['forum/new_thread.php?fid='.$fid]['parent']    = 'forum/index.php';
+
+/* the last accessed field */
+$last_accessed = array();
+if ($_SESSION['valid_user'] && $_SESSION['enroll']) {
+       $sql    = "SELECT post_id, last_accessed + 0 AS last_accessed, subscribe FROM ".TABLE_PREFIX."forums_accessed WHERE member_id=$_SESSION[member_id]";
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_assoc($result)) {
+               $post_id = $row['post_id'];
+               unset($row['post_id']);
+               $last_accessed[$post_id] = $row;
+       }
+}
+
+require(AT_INCLUDE_PATH . 'header.inc.php');
+
+require(AT_INCLUDE_PATH . 'html/forum.inc.php');
+
+require(AT_INCLUDE_PATH . 'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/forum/list.php b/forum/list.php
new file mode 100644 (file)
index 0000000..734f990
--- /dev/null
@@ -0,0 +1,94 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+require(AT_INCLUDE_PATH.'lib/forums.inc.php');
+require (AT_INCLUDE_PATH.'header.inc.php');
+?>
+<table class="data static" summary="" rules="rows">
+<thead>
+<tr>
+       <th scope="col"><?php echo _AT('forum');        ?></th>
+       <th scope="col"><?php echo _AT('num_threads'); ?></th>
+       <th scope="col"><?php echo _AT('num_posts');    ?></th>
+       <th scope="col"><?php echo _AT('last_post');    ?></th>
+</tr>
+</thead>
+<?php
+$shared  = array();
+$general = array();
+$all_forums = get_forums($_SESSION['course_id']);
+//output course forums
+$num_shared    = count($all_forums['shared']);
+$num_nonshared = count($all_forums['nonshared']);
+$num_groups = count($all_forums['group']);
+
+if ($num_shared || $num_nonshared || $num_groups) {
+       foreach ($all_forums as $shared => $forums) {
+               if (($num_shared && $num_nonshared) || ($num_nonshared && $num_groups)) {
+                       if ($num_nonshared && ($shared == 'nonshared')) {
+                               echo '<tbody><tr>';
+                               echo '<th colspan="4">' . _AT('course_forums') . '</th>';
+                               echo '</tr>';
+                       } else if ($num_shared && ($shared == 'shared')) {
+                               echo '</tbody><tbody><tr>';
+                               echo '<th colspan="4">' . _AT('shared_forums') . '</th>';
+                               echo '</tr>';
+                       } else if ($num_groups && ($shared == 'group')) {
+                               echo '</tbody><tbody><tr>';
+                               echo '<th colspan="4">' . _AT('group_forums') . '</th>';
+                               echo '</tr>';
+                       }
+               }
+
+               foreach ($forums as $row) : ?>
+                       <tr>
+                               <td><a href="<?php echo url_rewrite('forum/index.php?fid='.$row['forum_id']); ?>"><?php echo $row['title']; ?></a> <?php
+
+                                       if ($_SESSION['enroll']) {
+                                               $sql    = "SELECT 1 AS constant FROM ".TABLE_PREFIX."forums_subscriptions WHERE forum_id=$row[forum_id] AND member_id=$_SESSION[member_id]";
+                                               $result1 = mysql_query($sql, $db);
+                                               echo ' [ ';
+                                               if ($row1 = mysql_fetch_row($result1)) {
+                                                       echo '<a href="forum/subscribe_forum.php?fid='.$row['forum_id'].SEP.'us=1">'._AT('unsubscribe1').'</a>';
+                                               } else {
+                                                       echo '<a href="forum/subscribe_forum.php?fid='.$row['forum_id'].'">'._AT('subscribe1').'</a>';
+                                               }
+                                               echo ' ]';
+                                       } ?>
+                                       <p><?php echo $row['description']; ?></p>
+                               </td>
+                               <td align="center" valign="top"><?php echo $row['num_topics']; ?></td>
+                               <td align="center" valign="top"><?php echo $row['num_posts']; ?></td>
+                               <td align="right" valign="top"><?php
+
+                                       if ($row['last_post'] == '0000-00-00 00:00:00') {
+                                               echo '<em>'._AT('na').'</em>';
+                                       } else {
+                                               echo $row['last_post'];
+                                       } ?>
+                               </td>
+                       </tr><?php
+               endforeach;
+       }
+       echo '</tbody>';
+} else {
+       echo '<tr><td class="row1" colspan="4"><em>'._AT('no_forums').'</em></td></tr>';
+}
+echo '</table>';
+
+require (AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/forum/lock_thread.php b/forum/lock_thread.php
new file mode 100644 (file)
index 0000000..d07f76c
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+$fid  = intval($_REQUEST['fid']);
+if ($fid == 0) {
+       $fid  = intval($_GET['fid']);
+}
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_FORUMS);
+
+$_pages['forum/index.php?fid='.$fid]['title']    = get_forum_name($fid);
+$_pages['forum/index.php?fid='.$fid]['parent']   = 'forum/list.php';
+$_pages['forum/index.php?fid='.$fid]['children'] = array('forum/new_thread.php?fid='.$fid);
+
+$_pages['forum/new_thread.php?fid='.$fid]['title_var'] = 'new_thread';
+$_pages['forum/new_thread.php?fid='.$fid]['parent']    = 'forum/index.php?fid='.$fid;
+
+$_pages['forum/view.php']['title']  = $post_row['subject'];
+$_pages['forum/view.php']['parent'] = 'forum/index.php?fid='.$fid;
+
+$_pages['forum/lock_thread.php']['title_var'] = 'lock_thread';
+$_pages['forum/lock_thread.php']['parent']    = 'forum/index.php?fid='.$fid;
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'forum/index.php?fid='.$fid);
+       exit;
+} else if (isset($_POST['submit'])) {
+       $_POST['lock'] = intval($_POST['lock']);
+       $_POST['pid']  = intval($_POST['pid']);
+       $_POST['fid']  = intval($_POST['fid']);
+
+       $sql    = "UPDATE ".TABLE_PREFIX."forums_threads SET locked=$_POST[lock], last_comment=last_comment, date=date WHERE post_id=$_POST[pid]";
+       $result = mysql_query($sql, $db);
+
+       if($_POST['lock'] == '1' || $_POST['lock'] == '2'){
+               $msg->addFeedback('THREAD_LOCKED');
+               header('Location: '.AT_BASE_HREF.'forum/index.php?fid='.$fid);
+               exit;
+       } else {
+               $msg->addFeedback('THREAD_UNLOCKED');
+               header('Location: '.AT_BASE_HREF.'forum/index.php?fid='.$fid);
+               exit;
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$pid  = intval($_GET['pid']);
+$fid  = intval($_GET['fid']);
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
+<input type="hidden" name="pid" value="<?php echo $pid?>">
+<input type="hidden" name="fid" value="<?php echo $fid?>">
+
+<div class="input-form" style="width: 40%;">
+
+<?php if ($_GET['unlock']): ?>
+       <div class="row">
+               <input type="radio" name="lock" value="0" id="un"><label for="un"><?php echo _AT('unlock_thread'); ?></label>
+       </div>
+
+<?php endif; ?>
+       <div class="row">
+               <input type="radio" name="lock" value="1" id="rw" <?php
+               if (($_GET['unlock'] == '') || ($_GET['unlock'] == 1)) {
+                       echo ' checked="checked"';
+               }
+               ?>><label for="rw"><?php echo _AT('lock_no_read');  ?></label><br />
+               <input type="radio" name="lock" value="2" id="w" <?php
+               if ($_GET['unlock'] == 2) {
+                       echo ' checked="checked"';
+               }
+               ?>><label for="w"><?php echo _AT('lock_no_post');  ?></label>
+       </div>
+
+       <div class="row buttons">
+               <input name="submit" type="submit" value="<?php echo _AT('lock_submit');  ?>" />
+               <input name="cancel" type="submit" value="<?php echo _AT('cancel');  ?>" />
+       </div>
+</div>
+
+</form>
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/forum/move_thread.php b/forum/move_thread.php
new file mode 100644 (file)
index 0000000..f33f1e0
--- /dev/null
@@ -0,0 +1,108 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/forums.inc.php');
+
+authenticate(AT_PRIV_FORUMS);
+
+$_REQUEST['pid']  = intval($_REQUEST['pid']);
+$_REQUEST['ppid'] = intval($_REQUEST['ppid']);
+$_REQUEST['fid']  = intval($_REQUEST['fid']);
+
+if (!valid_forum_user($_REQUEST['fid'])) {
+       $msg->addError('FORUM_NOT_FOUND');
+       header('Location: list.php');
+       exit;
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED'); 
+       header('Location: index.php?fid='.$_REQUEST['fid']);
+       exit;
+
+} else if (isset($_POST['submit'])) {
+       // check if they have access
+       if (!valid_forum_user($_REQUEST['fid']) || !valid_forum_user($_REQUEST['new_fid'])) {
+               $msg->addError('FORUM_NOT_FOUND');
+               header('Location: list.php');
+               exit;
+       }
+
+       if ($_REQUEST['fid'] == $_REQUEST['new_fid']) {
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: index.php?fid='.$_REQUEST['fid']);
+               exit;
+       }
+
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."forums_threads WHERE post_id=$_REQUEST[pid] AND forum_id=$_REQUEST[fid]";
+       $result = mysql_query($sql, $db);
+       if (!($row = mysql_fetch_assoc($result))) {
+               $msg->addError('FORUM_NOT_FOUND');
+               header('Location: list.php');
+               exit;
+       } // else:
+
+       /* Decrement count for number of posts and topics*/
+       $sql    = "UPDATE ".TABLE_PREFIX."forums SET num_posts=num_posts-1-".$row['num_comments'].", num_topics=num_topics-1, last_post=last_post WHERE forum_id=$_REQUEST[fid]";
+       $result = mysql_query($sql, $db);
+
+       $sql    = "UPDATE ".TABLE_PREFIX."forums SET num_posts=num_posts+1+".$row['num_comments'].", num_topics=num_topics+1, last_post=last_post WHERE forum_id=$_REQUEST[new_fid]";
+       $result = mysql_query($sql, $db);
+
+       $sql    = "UPDATE ".TABLE_PREFIX."forums_threads SET forum_id=$_REQUEST[new_fid], last_comment=last_comment, date=date WHERE (parent_id=$_REQUEST[pid] OR post_id=$_REQUEST[pid]) AND forum_id=$_REQUEST[fid]";
+       $result = mysql_query($sql, $db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: index.php?fid='.$_REQUEST['fid']);
+       exit;
+}
+
+$_pages['forum/index.php?fid='.$_REQUEST['fid']]['title']    = get_forum_name($_REQUEST['fid']);
+$_pages['forum/index.php?fid='.$_REQUEST['fid']]['parent']   = 'forum/list.php';
+$_pages['forum/index.php?fid='.$_REQUEST['fid']]['children'] = array('forum/move_thread.php');
+
+$_pages['forum/move_thread.php']['title_var'] = 'move_thread';
+$_pages['forum/move_thread.php']['parent']    = 'forum/index.php?fid='.$_REQUEST['fid'];
+$_pages['forum/move_thread.php']['children']  = array();
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<input type="hidden" name="fid" value="<?php echo $_REQUEST['fid']; ?>" />
+<input type="hidden" name="pid" value="<?php echo $_REQUEST['pid']; ?>" />
+<input type="hidden" name="ppid" value="<?php echo $_REQUEST['ppid']; ?>" />
+
+<div class="input-form">
+       <div class="row">
+               <?php echo _AT('move_thread_to');
+               $all_forums = get_forums($_SESSION['course_id']);
+               ?>
+               <ul style="list-style: none">
+               <?php foreach($all_forums['nonshared'] as $row): ?>
+                       <li>
+                               <input type="radio" name="new_fid" value="<?php echo $row['forum_id']; ?>" id="f<?php echo $row['forum_id']; ?>" <?php if ($row['forum_id'] == $_REQUEST['fid']) { echo 'checked="checked"'; } ?> /><label for="f<?php echo $row['forum_id']; ?>"><?php echo $row['title']; ?></label>
+                       </li>
+               <?php endforeach; ?>
+               </ul>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('move'); ?>" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/forum/new_thread.php b/forum/new_thread.php
new file mode 100644 (file)
index 0000000..2ff8047
--- /dev/null
@@ -0,0 +1,196 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/forums.inc.php');
+
+$fid = intval($_REQUEST['fid']);
+$_POST['parent_id'] = intval($_REQUEST['parent_id']);
+
+$_pages['forum/index.php?fid='.$fid]['title']    = get_forum_name($fid);
+$_pages['forum/index.php?fid='.$fid]['parent']   = 'forum/list.php';
+$_pages['forum/index.php?fid='.$fid]['children'] = array('forum/new_thread.php');
+
+$_pages['forum/new_thread.php']['title_var'] = 'new_thread';
+$_pages['forum/new_thread.php']['parent']    = 'forum/index.php?fid='.$fid;
+
+if (!valid_forum_user($fid) || !$_SESSION['enroll']) {
+       $msg->addError('FORUM_DENIED');
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.url_rewrite('forum/index.php?fid='.$fid, AT_PRETTY_URL_IS_HEADER));
+       exit;
+} else if (isset($_POST['submit'])) {
+       $missing_fields = array();
+
+       if ($_POST['subject'] == '')  {
+               $missing_fields[] = _AT('subject');
+       } else {
+               //60 was set by db
+               $_POST['subject'] = validate_length($_POST['subject'], 60);
+       }
+
+       if ($_POST['body'] == '') {
+               $missing_fields[] = _AT('body');
+       }
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+       if (!$msg->containsErrors()) {
+               if ($_POST['replytext'] != '') {
+                       $_POST['body'] .= "\n\n".'[reply][b]'._AT('in_reply_to').': [/b]'."\n";
+                       if ($strlen($_POST['replytext']) > 200) {
+                               $_POST['body'] .= $substr($_POST['replytext'], 0, 200).'...';
+                       } else {
+                               $_POST['body'] .= $_POST['replytext'];
+                       }
+                       $num_open_replies = substr_count($_POST['body'], '[reply]');
+                       $num_close_replies = substr_count($_POST['body'], '[/reply]');
+                       $num_replies_add = $num_open_replies - $num_close_replies - 1;
+                       for ($i=0; $i < $num_replies_add; $i++) {
+                               $_POST['body'] .= '[/reply]';
+                       }
+
+                       $_POST['body'] .= "\n".'[op]forum/view.php?fid='.$_POST['fid'].SEP.'pid='.$_POST['parent_id'].SEP.'page='.$_POST['page'].'#'.$_POST['reply'];
+                       $_POST['body'] .= '[/op][/reply]';
+               }
+
+               /* use this value instead of NOW(), because we want the parent post to have the exact */
+               /* same date. and not a second off if that may happen */
+               $now = date('Y-m-d H:i:s');
+
+               $sql_subject = $addslashes($_POST['subject']);
+               $sql_body    = $addslashes($_POST['body']);
+
+               $sql = "INSERT INTO ".TABLE_PREFIX."forums_threads VALUES (NULL, $_POST[parent_id], $_SESSION[member_id], $_POST[fid], '$now', 0, '$sql_subject', '$sql_body', '$now', 0, 0)";
+               $result = mysql_query($sql, $db);
+               $this_id = mysql_insert_id($db);
+
+               /* Increment count for posts in forums table in database */
+               $sql = "UPDATE ".TABLE_PREFIX."forums SET num_posts=num_posts+1, last_post='$now' WHERE forum_id=$_POST[fid]";
+               $result  = mysql_query($sql, $db);
+
+               // If there are subscribers to this forum, send them an email notification
+               $subscriber_email_list = array(); // list of subscribers array('email', 'full_name')
+               $subscriber_list       = '';
+               $enrolled = array();
+               //get list of student enrolled in this course
+               // This needs to be replaced with a tool to clean forum subscriptions when unenrolling
+               $sql = "SELECT member_id from ".TABLE_PREFIX."course_enrollment WHERE course_id = '$_SESSION[course_id]' AND approved = 'y'";
+               $result1 = mysql_query($sql, $db);
+               while($row = mysql_fetch_assoc($result1)){
+                       $enrolled[] = $row['member_id'];
+               }
+               //get a list of users subscribed to this forum
+               $sql = "SELECT member_id FROM ".TABLE_PREFIX."forums_subscriptions WHERE forum_id=$fid";
+               $result = mysql_query($sql, $db);
+               while($row = mysql_fetch_assoc($result)){
+                       $subscriber_list .= $row['member_id'] . ',';
+               }
+               if ($_POST['parent_id']) {
+                       $sql = "SELECT member_id FROM ".TABLE_PREFIX."forums_accessed WHERE post_id=$_POST[parent_id] AND subscribe=1";
+                       $result = mysql_query($sql, $db);
+                       while($row = mysql_fetch_assoc($result)){
+                               if(in_array($row['member_id'], $enrolled)){
+                                       $subscriber_list .= $row['member_id'] . ',';
+                               }
+                       }
+               }
+               $subscriber_list = $substr($subscriber_list, 0, -1);
+
+               if ($subscriber_list != '') {
+                       $sql = "SELECT first_name, second_name, last_name, email, member_id FROM ".TABLE_PREFIX."members WHERE member_id IN ($subscriber_list)";
+                       $result = mysql_query($sql, $db);
+                       while ($row = mysql_fetch_assoc($result)) {
+                               $subscriber_email_list[] = array('email'=> $row['email'], 'full_name' => $row['first_name'] . ' '. $row['second_name'] . ' ' . $row['last_name'], 'member_id'=>$row['member_id']);
+                       }
+               }
+               $sql = "UPDATE ".TABLE_PREFIX."forums_threads SET num_comments=num_comments+1, last_comment='$now', date=date WHERE post_id=$_POST[parent_id]";
+               $result = mysql_query($sql, $db);
+
+               if ($subscriber_email_list) {
+                       require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+
+                       if ($_POST['parent_name'] == ''){
+                               $_POST['parent_name'] = $_POST['subject'];
+                       }
+                       $_POST['parent_name'] = urldecode($_POST['parent_name']);
+                       foreach ($subscriber_email_list as $subscriber){
+                               $mail = new ATutorMailer;
+                               $mail->AddAddress($subscriber['email'], get_display_name($subscriber['member_id']));
+                               $body = _AT('forum_new_submsg', $_SESSION['course_title'],  get_forum_name($_POST['fid']), $_POST['parent_name'],  AT_BASE_HREF.'bounce.php?course='.$_SESSION['course_id']);
+                               $body .= "\n----------------------------------------------\n";
+                               $body .= _AT('posted_by').": ".get_display_name($_SESSION['member_id'])."\n";
+                               $body .= $_POST['body']."\n";
+                               $mail->FromName = $_config['site_name'];
+                               $mail->From     = $_config['contact_email'];
+                               $mail->Subject = _AT('thread_notify1');
+                               $mail->Body    = $body;
+
+                               if(!$mail->Send()) {
+                                       $msg->addError('SENDING_ERROR');
+                               }
+
+                               unset($mail);
+                       }
+               }
+               if ($_REQUEST['subscribe']) {
+                       if($_POST['parent_id'] != 0){
+                               $this_id = $_POST['parent_id'];
+                               $subject = $_POST['parent_name'];
+                       } else {
+                               $subject = $_POST['subject'];
+                       }
+                       $sql    = "REPLACE INTO ".TABLE_PREFIX."forums_accessed VALUES ($this_id, $_SESSION[member_id], NOW(), 1)";
+                       $result = mysql_query($sql, $db);
+
+                       $msg->addFeedback(array('THREAD_SUBSCRIBED', $subject));
+               } else if ($_POST['parent_id'] == 0) {
+                       // not subscribe and it's a new thread, mark read:
+
+                       $sql    = "REPLACE INTO ".TABLE_PREFIX."forums_accessed VALUES ($this_id, $_SESSION[member_id], NOW(), 0)";
+                       $result = mysql_query($sql, $db);
+               }
+
+               if ($_POST['parent_id'] == 0) {
+                       $sql = "UPDATE ".TABLE_PREFIX."forums SET num_topics=num_topics+1, last_post='$now' WHERE forum_id=$_POST[fid]";
+                       $result  = mysql_query($sql, $db);
+                       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+                       $_POST['parent_id'] = $this_id;
+               }
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: '.url_rewrite('forum/view.php?fid='.$fid.SEP.'pid='.$_POST['parent_id'].SEP.'page='.$_POST['page'], AT_PRETTY_URL_IS_HEADER));
+               exit;
+       }
+}
+
+$onload = 'document.form.subject.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+       
+$parent_id = 0;
+$new_thread = TRUE;
+require(AT_INCLUDE_PATH.'html/new_thread.inc.php');
+require(AT_INCLUDE_PATH.'footer.inc.php');
+
+?>
\ No newline at end of file
diff --git a/forum/stick.php b/forum/stick.php
new file mode 100644 (file)
index 0000000..c8881c6
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_FORUMS);
+
+$pid = intval($_GET['pid']);
+
+/* ABS(sticky-1) : if 1 then 0, if 0 then 1 */
+$sql   = "UPDATE ".TABLE_PREFIX."forums_threads SET sticky=ABS(sticky-1), last_comment=last_comment, date=date WHERE post_id=$pid";
+$result = mysql_query($sql, $db);
+
+$msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+
+header('Location: '.AT_BASE_HREF.'forum/index.php?fid='.intval($_GET['fid']));
+exit;
+
+?>
\ No newline at end of file
diff --git a/forum/subscribe.php b/forum/subscribe.php
new file mode 100644 (file)
index 0000000..ffb923e
--- /dev/null
@@ -0,0 +1,82 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/forums.inc.php');
+
+$_section[0][0] = _AT('discussions');
+$_section[0][1] = 'discussions/';
+
+$pid = intval($_GET['pid']);
+$fid = intval($_GET['fid']);
+
+// check if they have access
+if (!valid_forum_user($fid) || !$_SESSION['enroll']) {
+       $msg->addError('FORUM_NOT_FOUND');
+       header('Location: list.php');
+       exit;
+}
+
+$sql = "SELECT subject FROM ".TABLE_PREFIX."forums_threads WHERE post_id=$pid AND forum_id=$fid";
+$result = mysql_query($sql, $db);
+if (!($row = mysql_fetch_assoc($result))) {
+       $msg->addError('FORUM_NOT_FOUND');
+       header('Location: list.php');
+       exit;
+} // else:
+$thread_name = $row['subject'];
+
+/**
+ * Protect against url injection
+ * Maintain consistency in data by not allowing any subscription to a reply thread, only top level id's (0).
+ */
+ $sql = "SELECT parent_id FROM " . TABLE_PREFIX."forums_threads WHERE post_id=$pid AND forum_id=$fid";
+ $result = mysql_query($sql, $db);
+ if ($row = mysql_fetch_assoc($result)) {
+       if ($row['parent_id'] > 0) { // not allowed, only top level
+               $msg->addError('FORUM_NO_SUBSCRIBE');
+               header('Location: view.php?fid='.$fid.SEP.'pid='.$row['parent_id']); // take us back to where we were
+               exit;
+       }
+ }
+if ($_GET['us']) {
+       // unsubscribe:
+       $sql    = "UPDATE ".TABLE_PREFIX."forums_accessed SET subscribe=0 WHERE post_id=$pid AND member_id=$_SESSION[member_id]";
+       $result = mysql_query($sql, $db);
+} else {
+       // subscribe:
+       $sql    = "REPLACE INTO ".TABLE_PREFIX."forums_accessed VALUES ($pid, $_SESSION[member_id], NOW(), 1)";
+       $result = mysql_query($sql, $db);
+}
+
+
+if($_REQUEST['t']){
+       $this_pid = 'index.php?fid='.$fid;
+} else{
+       $this_pid = 'view.php?fid='.$fid.SEP.'pid='.$pid;
+}
+
+if ($_GET['us'] == '1') {
+       $msg->addFeedback(array('THREAD_UNSUBSCRIBED', $thread_name));
+       header('Location: '.AT_BASE_HREF.'forum/'.$this_pid);
+       exit;
+}
+
+/* else: */
+       $msg->addFeedback(array('THREAD_SUBSCRIBED', $thread_name ));
+       header('Location: '.AT_BASE_HREF.'forum/'.$this_pid);
+       exit;
+
+?>
\ No newline at end of file
diff --git a/forum/subscribe_forum.php b/forum/subscribe_forum.php
new file mode 100644 (file)
index 0000000..6ac5445
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id: index.php 2526 2004-11-25 18:54:16Z greg$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/forums.inc.php');
+
+$fid = intval($_REQUEST['fid']);
+
+// check if they have access
+if (!valid_forum_user($fid) || !$_SESSION['enroll']) {
+       $msg->addError('FORUM_NOT_FOUND');
+       header('Location: list.php');
+       exit;
+}
+
+$sql = "SELECT title FROM ".TABLE_PREFIX."forums WHERE forum_id=$fid";
+$result = mysql_query($sql, $db);
+if ($row = mysql_fetch_assoc($result)) {
+       $forum_title = $row['title'];
+} else {
+       $msg->addError('FORUM_NOT_FOUND');
+       header('Location: list.php');
+       exit;
+}
+
+if (isset($_GET['us'])) {
+       $sql = "DELETE from ".TABLE_PREFIX."forums_subscriptions WHERE forum_id = $fid AND member_id = $_SESSION[member_id]";
+       $result = mysql_query($sql, $db);
+       $msg->addFeedback(array(FORUM_UNSUBSCRIBED, $forum_title));
+
+} else {
+       $sql = "INSERT into ".TABLE_PREFIX."forums_subscriptions VALUES($fid, '$_SESSION[member_id]')";
+       mysql_query($sql, $db);
+
+       $msg->addFeedback(array(FORUM_SUBSCRIBED,$forum_title));
+}
+
+header('Location: list.php');
+exit;
+?>
\ No newline at end of file
diff --git a/forum/view.php b/forum/view.php
new file mode 100644 (file)
index 0000000..c7121ff
--- /dev/null
@@ -0,0 +1,185 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+$fid = intval($_GET['fid']);
+
+if (!isset($_GET['fid']) || !$fid) {
+       header('Location: list.php');
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'lib/forums.inc.php'); // for print_entry et al
+
+if (!valid_forum_user($fid)) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->printErrors('FORUM_DENIED');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+$forum_info = get_forum($fid);
+
+$_pages[url_rewrite('forum/index.php?fid='.$fid)]['title']    = get_forum_name($fid);
+$_pages[url_rewrite('forum/index.php?fid='.$fid)]['parent']   = 'forum/list.php';
+$_pages[url_rewrite('forum/index.php?fid='.$fid)]['children'] = array(url_rewrite('forum/new_thread.php?fid='.$fid));
+
+$_pages[url_rewrite('forum/new_thread.php?fid='.$fid)]['title_var'] = 'new_thread';
+$_pages[url_rewrite('forum/new_thread.php?fid='.$fid)]['parent']    = url_rewrite('forum/index.php?fid='.$fid);
+
+$_pages['forum/view.php']['parent'] = url_rewrite('forum/index.php?fid='.$fid);
+
+
+if ($_REQUEST['reply']) {
+       $onload = 'document.form.subject.focus();';
+}
+
+$pid = intval($_GET['pid']);
+
+$num_per_page = 10;
+if (!$_GET['page']) {
+       $page = 1;
+} else {
+       $page = (intval($_GET['page'])>0)?(intval($_GET['page'])):1;
+}
+$start = ($page-1)*$num_per_page;
+       
+/* get the first thread first */
+$sql   = "SELECT *, DATE_FORMAT(date, '%Y-%m-%d %H-%i:%s') AS date, UNIX_TIMESTAMP(date) AS udate FROM ".TABLE_PREFIX."forums_threads WHERE post_id=$pid AND forum_id=$fid";
+$result        = mysql_query($sql, $db);
+
+if (!($post_row = mysql_fetch_array($result))) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $_pages['forum/view.php']['title']  = _AT('no_post');
+
+       echo _AT('no_post');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+$_pages['forum/view.php']['title']  = $post_row['subject'];
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+       <a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#post" style="border: 0px;"><img src="<?php echo $_base_path; ?>images/clr.gif" height="1" width="1" border="0" alt="<?php echo _AT('reply'); ?>" /></a>
+<?php
+       /**
+       * Jacek M.
+       * Protect data consistency
+       * Make sure the pid we are inserting is actually a thread post_id, otherwise we get dangling pointers
+       * in the case of injection
+       */
+
+       if ($_SESSION['valid_user']) {
+               $sql2 = "INSERT INTO ".TABLE_PREFIX."forums_accessed VALUES ($pid, $_SESSION[member_id], NOW(), 0)";
+               $result2 = mysql_query($sql2, $db);
+               if (!$result2) {
+                       $sql2 = "UPDATE ".TABLE_PREFIX."forums_accessed SET last_accessed=NOW() WHERE post_id=$pid AND member_id=$_SESSION[member_id]";
+                       $result2 = mysql_query($sql2, $db);
+               }
+       }
+       
+       $num_threads = $post_row['num_comments']+1;
+       $num_pages = ceil($num_threads/$num_per_page);
+       $locked = $post_row['locked'];
+       if ($locked == 1) {
+               echo '<p><strong>'._AT('lock_no_read1').'</strong></p>';
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+
+       $parent_name = $post_row['subject'];
+
+       echo '<div class="forum-paginator">';
+       echo _AT('page').': ';
+       for ($i=1; $i<=$num_pages; $i++) {
+               if ($i == $page) {
+                       echo '<span class="forum-paginator-active">'.$i.'</span>';
+               } else {
+                       echo '<a href="'.url_rewrite($_SERVER['PHP_SELF'].'?fid='.$fid.SEP.'pid='.$pid.SEP.'page='.$i).'">'.$i.'</a>';
+               }
+
+               if ($i<$num_pages){
+                       echo ' <span class="spacer">|</span> ';
+               }
+       }
+       echo '</div>';
+       echo '<ul id="forum-thread">';
+
+       if ($page == 1) {
+               print_entry($post_row);
+               $subject   = $post_row['subject'];
+               if ($_GET['reply'] == $post_row['post_id']) {
+                       $saved_post = $post_row;
+               }
+               $num_per_page--;
+       } else {
+               $start--;
+       }
+       $sql    = "SELECT *, DATE_FORMAT(date, '%Y-%m-%d %H-%i:%s') AS date, UNIX_TIMESTAMP(date) AS udate FROM ".TABLE_PREFIX."forums_threads WHERE parent_id=$pid AND forum_id=$fid ORDER BY date ASC LIMIT $start, $num_per_page";
+       $result = mysql_query($sql, $db);
+
+       while ($row = mysql_fetch_assoc($result)) {
+               print_entry($row);
+               $subject = $row['subject'];
+               if ($_GET['reply'] == $row['post_id']) {
+                       $saved_post = $row;
+               }
+       }
+       echo '</ul>';
+       
+       echo '<div  class="forum-paginator">';
+       echo _AT('page').': ';
+       for ($i=1; $i<=$num_pages; $i++) {
+               if ($i == $page) {
+                       echo '<span class="forum-paginator-active">'.$i.'</span>';
+               } else {
+                       echo '<a href="'.url_rewrite($_SERVER['PHP_SELF'].'?fid='.$fid.SEP.'pid='.$pid.SEP.'page='.$i).'">'.$i.'</a>';
+               }
+
+               if ($i<$num_pages){
+                       echo ' <span class="spacer">|</span> ';
+               }
+       }
+       echo '</div>';
+
+       $parent_id = $pid;
+       $body      = '';
+       if (substr($subject,0,3) != 'Re:') {
+               $subject = 'Re: '.$subject;
+       }
+       
+       if ($_SESSION['valid_user'] && $_SESSION['enroll'] && !$locked) {
+               $sql    = "SELECT subscribe FROM ".TABLE_PREFIX."forums_accessed WHERE post_id=$_GET[pid] AND member_id=$_SESSION[member_id]";
+               $result = mysql_query($sql, $db);
+               $row = mysql_fetch_assoc($result);
+               if ($row['subscribe']) {
+                       echo '<p><a href="forum/subscribe.php?fid='.$fid.SEP.'pid='.$_GET['pid'].SEP.'us=1">'._AT('unsubscribe').'</a></p>';
+                       $subscribed = true;
+               } else {
+                       echo '<p><a href="forum/subscribe.php?fid='.$fid.SEP.'pid='.$_GET['pid'].'">'._AT('subscribe').'</a></p>';
+               }
+       }
+       if ($_SESSION['valid_user'] && !$_SESSION['enroll']) {
+               echo '<p><strong>'._AT('enroll_to_post').'</strong></p>';
+       } else if ($locked == 0) {
+               require(AT_INCLUDE_PATH.'html/new_thread.inc.php');
+       } else {
+               echo '<p><strong>'._AT('lock_no_post1').'</strong></p>';
+       }
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/get.php b/get.php
new file mode 100644 (file)
index 0000000..bec4360
--- /dev/null
+++ b/get.php
@@ -0,0 +1,132 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', 'include/');
+@ob_end_clean();
+header("Content-Encoding: none");
+if (isset($_GET['test'])) {
+       header('HTTP/1.1 200 OK', TRUE);
+       header('ATutor-Get: OK');
+       exit;
+}
+$in_get = TRUE;
+
+require(AT_INCLUDE_PATH . 'vitals.inc.php');
+require(AT_INCLUDE_PATH . 'lib/mime.inc.php');
+
+$force_download = false;
+
+//get path to file
+if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+       if ((version_compare(phpversion(), '5.2.0', '<') > 0) && !empty($_SERVER['ORIG_PATH_INFO'])){
+               //http://www.atutor.ca/atutor/mantis/view.php?id=3436
+               $current_file = $_SERVER['ORIG_PATH_INFO'];
+       } else if (!empty($_SERVER['PATH_INFO'])) {
+        $current_file = $_SERVER['PATH_INFO'];
+       } else if (!empty($_SERVER['REQUEST_URI'])) {
+               $current_file = $_SERVER['REQUEST_URI'];
+    } else if (!empty($_SERVER['PHP_SELF'])) {
+               if (!empty($_SERVER['QUERY_STRING'])) {
+            $current_file = $_SERVER['PHP_SELF'] . '?' . $_SERVER['QUERY_STRING'];
+        } else {
+               $current_file = $_SERVER['PHP_SELF'];
+               }
+    } else if (!empty($_SERVER['SCRIPT_NAME'])) {
+               if (!empty($_SERVER['QUERY_STRING'])) {
+            $current_file = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING'];
+        } else {
+               $current_file = $_SERVER['SCRIPT_NAME'];
+               }
+    } else if (!empty($_SERVER['URL'])) {
+        if (!empty($_SERVER['QUERY_STRING'])) {
+            $current_file = $_SERVER['URL'] . '?' . $_SERVER['QUERY_STRING'];
+        }
+        $current_file = $_SERVER['URL'];
+       }
+
+       if (($pos = strpos($current_file, '/get.php')) !== FALSE) {
+               $current_file = substr($current_file, $pos + strlen('/get.php'));
+       }
+       if (substr($current_file, 0, 2) == '/@') {
+               $force_download = true;
+               $current_file = substr($current_file, 2);
+       }
+
+} else {
+       $current_file = $_GET['f'];
+
+       if (substr($current_file, 0, 2) == '/@') {
+               $force_download = true;
+               $current_file = substr($current_file, 2);
+       }
+}
+
+$file_name = pathinfo($current_file);
+$file_name = $file_name['basename'];
+
+if (substr($file_name, 0, 4) == 'b64:') {
+       $base64_file_name = substr($file_name, 4);
+       $file_name = base64_decode($base64_file_name);
+       $current_file = '/'.$file_name;
+}
+
+
+$file = AT_CONTENT_DIR . $_SESSION['course_id'] . $current_file;
+
+//send header mime type
+$pathinfo = pathinfo($file);
+$ext = $pathinfo['extension'];
+if ($ext == '') {
+       $ext = 'application/octet-stream';
+} else {
+       $ext = $mime[$ext][0];
+}
+
+//check that this file is within the content directory & exists
+
+// NOTE!! for some reason realpath() is not returning FALSE when the file doesn't exist!
+$real = realpath($file);
+
+if (file_exists($real) && (substr($real, 0, strlen(AT_CONTENT_DIR)) == AT_CONTENT_DIR)) {
+       if ($force_download) {
+               header('Content-Type: application/force-download');
+               header('Content-transfer-encoding: binary'); 
+               header('Content-Disposition: attachment; filename="'.$pathinfo['basename'].'"');
+       } else {
+               header('Content-Disposition: filename="'.$pathinfo['basename'].'"');
+       }
+       
+       /**
+        * although we can check if mod_xsendfile is installed in apache2
+        * we can't actually check if it's enabled. also, we can't check if
+        * it's enabled and installed in lighty, so instead we send the 
+        * header anyway, if it works then the line after it will not
+        * execute. if it doesn't work, then the line after it will replace
+        * it so that the full server path is not exposed.
+        *
+        * x-sendfile is supported in apache2 and lighttpd 1.5+ (previously
+        * named x-send-file in lighttpd 1.4)
+        */
+       header('x-Sendfile: '.$real);
+       header('x-Sendfile: ', TRUE); // if we get here then it didn't work
+
+       header('Content-Type: '.$ext);
+
+       @readfile($real);
+       exit;
+} else {
+       header('HTTP/1.1 404 Not Found', TRUE);
+       exit;
+}
+
+?>
\ No newline at end of file
diff --git a/get_acheck.php b/get_acheck.php
new file mode 100644 (file)
index 0000000..5a911a7
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+/* this file simply gets the AT_CONTENT_DIR/CID.html file that was generated
+ * by the AChecker page of the content editor.
+ * there is no authentication on this page. either the file exists (in which
+ * case it is then quickly deleted after), or it doesn't.
+ */
+
+$_user_location        = 'public';
+
+define('AT_INCLUDE_PATH', 'include/');
+require(AT_INCLUDE_PATH . '/vitals.inc.php');
+
+//get path to file
+$args = substr($_SERVER['PHP_SELF'], strlen($_SERVER['SCRIPT_NAME']));
+$file = AT_CONTENT_DIR . $args;
+
+//check that this file is within the content directory & exists
+
+$real = realpath($file);
+
+if (substr($real, 0, strlen(AT_CONTENT_DIR)) == AT_CONTENT_DIR) {
+       header('Content-Type: text/html');
+       echo file_get_contents($real);
+       exit;
+} else {
+       header('HTTP/1.1 404 Not Found');
+       exit;
+}
+
+
+?>
\ No newline at end of file
diff --git a/get_course_icon.php b/get_course_icon.php
new file mode 100644 (file)
index 0000000..3f3a279
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: get_profile_img.php 6979 2007-06-20 17:35:02Z greg$
+define('AT_INCLUDE_PATH', 'include/');
+@ob_end_clean();
+header("Content-Encoding: none");
+
+$_user_location        = 'public';
+
+require(AT_INCLUDE_PATH . 'vitals.inc.php');
+
+
+require(AT_INCLUDE_PATH . 'lib/mime.inc.php');
+
+$id = intval($_GET['id']);
+$sql="SELECT icon from ".TABLE_PREFIX."courses WHERE course_id='$id'";
+$result = mysql_query($sql, $db);
+while($row=mysql_fetch_assoc($result)){
+       $filename = $row['icon'];
+}
+
+$file = AT_CONTENT_DIR .$id.'/custom_icons/'.$filename;
+
+$extensions = array('gif', 'jpg', 'png');
+$pathinfo = pathinfo($file);
+$ext = strtolower($pathinfo['extension']);
+if ($ext == '') {
+       $ext = 'application/octet-stream';
+} else {
+       $ext = $mime[$ext][0];
+}
+
+$real = realpath($file);
+
+if (file_exists($real) && (substr($real, 0, strlen(AT_CONTENT_DIR)) == AT_CONTENT_DIR)) {
+
+       header('Content-Disposition: filename="'.$size.$id.'.'.$pathinfo['extension'].'"');
+       
+       /**
+        * although we can check if mod_xsendfile is installed in apache2
+        * we can't actually check if it's enabled. also, we can't check if
+        * it's enabled and installed in lighty, so instead we send the 
+        * header anyway, if it works then the line after it will not
+        * execute. if it doesn't work, then the line after it will replace
+        * it so that the full server path is not exposed.
+        *
+        * x-sendfile is supported in apache2 and lighttpd 1.5+ (previously
+        * named x-send-file in lighttpd 1.4)
+        */
+       header('x-Sendfile: '.$real);
+       header('x-Sendfile: ', TRUE); // if we get here then it didn't work
+
+       header('Content-Type: '.$ext);
+
+       @readfile($real);
+       exit;
+} else {
+       header('HTTP/1.1 404 Not Found', TRUE);
+       exit;
+}
+
+?>
\ No newline at end of file
diff --git a/get_noid.php b/get_noid.php
new file mode 100644 (file)
index 0000000..483c3bc
--- /dev/null
@@ -0,0 +1,134 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: get.php 6974 2007-06-15 18:44:37Z joel $
+define('AT_INCLUDE_PATH', 'include/');
+@ob_end_clean();
+header("Content-Encoding: none");
+if (isset($_GET['test'])) {
+       header('HTTP/1.1 200 OK', TRUE);
+       header('ATutor-Get: OK');
+       exit;
+}
+$in_get = TRUE;
+
+require(AT_INCLUDE_PATH . 'vitals.inc.php');
+require(AT_INCLUDE_PATH . 'lib/mime.inc.php');
+
+$force_download = false;
+
+//get path to file
+if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+       if (!empty($_SERVER['PATH_INFO'])) {
+        $current_file = $_SERVER['PATH_INFO'];
+       } else if (!empty($_SERVER['REQUEST_URI'])) {
+               $current_file = $_SERVER['REQUEST_URI'];
+    } else if (!empty($_SERVER['PHP_SELF'])) {
+               if (!empty($_SERVER['QUERY_STRING'])) {
+            $current_file = $_SERVER['PHP_SELF'] . '?' . $_SERVER['QUERY_STRING'];
+        } else {
+               $current_file = $_SERVER['PHP_SELF'];
+               }
+    } else if (!empty($_SERVER['SCRIPT_NAME'])) {
+               if (!empty($_SERVER['QUERY_STRING'])) {
+            $current_file = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING'];
+        } else {
+               $current_file = $_SERVER['SCRIPT_NAME'];
+               }
+    } else if (!empty($_SERVER['URL'])) {
+        if (!empty($_SERVER['QUERY_STRING'])) {
+            $current_file = $_SERVER['URL'] . '?' . $_SERVER['QUERY_STRING'];
+        }
+        $current_file = $_SERVER['URL'];
+       }
+
+       if ($pos = strpos($current_file, '/get.php/') !== FALSE) {
+               $current_file = substr($current_file, $pos + strlen('/get.php/'));
+       }
+       
+       if (substr($current_file, 0, 2) == '/@') {
+               $force_download = true;
+               $current_file = substr($current_file, 2);
+       }
+} else {
+       $current_file = $_GET['f'];
+
+       if (substr($current_file, 0, 2) == '/@') {
+               $force_download = true;
+               $current_file = substr($current_file, 2);
+       }
+}
+
+$file_name = pathinfo($current_file);
+$file_name = $file_name['basename'];
+
+if (substr($file_name, 0, 4) == 'b64:') {
+       $base64_file_name = substr($file_name, 4);
+       $file_name = base64_decode($base64_file_name);
+       $current_file = '/'.$file_name;
+}
+
+if (is_numeric(substr($current_file, 1, 1)) == true) {
+    $course_num = substr($current_file, 1, 1);
+    $current_file = substr($current_file, 2);
+    $file = AT_CONTENT_DIR . $course_num . $current_file;
+} else {
+    $file = AT_CONTENT_DIR . $_SESSION['course_id'] . $current_file;
+}
+
+//send header mime type
+$pathinfo = pathinfo($file);
+$ext = $pathinfo['extension'];
+if ($ext == '') {
+       $ext = 'application/octet-stream';
+} else {
+       $ext = $mime[$ext][0];
+}
+
+//check that this file is within the content directory & exists
+
+// NOTE!! for some reason realpath() is not returning FALSE when the file doesn't exist!
+$real = realpath($file);
+
+if (file_exists($real) && (substr($real, 0, strlen(AT_CONTENT_DIR)) == AT_CONTENT_DIR)) {
+       if ($force_download) {
+               header('Content-Type: application/force-download');
+               header('Content-transfer-encoding: binary'); 
+               header('Content-Disposition: attachment; filename="'.$pathinfo['basename'].'"');
+       } else {
+               header('Content-Disposition: filename="'.$pathinfo['basename'].'"');
+       }
+       
+       /**
+        * although we can check if mod_xsendfile is installed in apache2
+        * we can't actually check if it's enabled. also, we can't check if
+        * it's enabled and installed in lighty, so instead we send the 
+        * header anyway, if it works then the line after it will not
+        * execute. if it doesn't work, then the line after it will replace
+        * it so that the full server path is not exposed.
+        *
+        * x-sendfile is supported in apache2 and lighttpd 1.5+ (previously
+        * named x-send-file in lighttpd 1.4)
+        */
+       header('x-Sendfile: '.$real);
+       header('x-Sendfile: ', TRUE); // if we get here then it didn't work
+
+       header('Content-Type: '.$ext);
+
+       @readfile($real);
+       exit;
+} else {
+       header('HTTP/1.1 404 Not Found', TRUE);
+       exit;
+}
+
+?>
\ No newline at end of file
diff --git a/get_profile_img.php b/get_profile_img.php
new file mode 100644 (file)
index 0000000..0c59f5c
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', 'include/');
+@ob_end_clean();
+header("Content-Encoding: none");
+
+$_user_location        = 'public';
+
+require(AT_INCLUDE_PATH . 'vitals.inc.php');
+require(AT_INCLUDE_PATH . 'lib/mime.inc.php');
+
+$id = intval($_GET['id']);
+if (isset($_GET['size']) && $_GET['size'] == 'o') {
+       $size = 'originals'; //t (thumbnail) or o (original)
+} else {
+       $size = 'thumbs';
+}
+
+$file = AT_CONTENT_DIR . 'profile_pictures/' . $size .'/'. $id .'.';
+
+$extensions = array('gif', 'jpg', 'png');
+
+foreach ($extensions as $extension) {
+       if (file_exists($file.$extension)) {
+               $file .= $extension;
+       }
+}
+
+$pathinfo = pathinfo($file);
+$ext = $pathinfo['extension'];
+if ($ext == '') {
+       $ext = 'application/octet-stream';
+} else {
+       $ext = $mime[$ext][0];
+}
+
+$real = realpath($file);
+
+if (file_exists($real) && (substr($real, 0, strlen(AT_CONTENT_DIR)) == AT_CONTENT_DIR)) {
+
+       header('Content-Disposition: filename="'.$size.$id.'.'.$pathinfo['extension'].'"');
+       
+       /**
+        * although we can check if mod_xsendfile is installed in apache2
+        * we can't actually check if it's enabled. also, we can't check if
+        * it's enabled and installed in lighty, so instead we send the 
+        * header anyway, if it works then the line after it will not
+        * execute. if it doesn't work, then the line after it will replace
+        * it so that the full server path is not exposed.
+        *
+        * x-sendfile is supported in apache2 and lighttpd 1.5+ (previously
+        * named x-send-file in lighttpd 1.4)
+        */
+       header('x-Sendfile: '.$real);
+       header('x-Sendfile: ', TRUE); // if we get here then it didn't work
+
+       header('Content-Type: '.$ext);
+
+       @readfile($real);
+       exit;
+} else {
+       header('HTTP/1.1 404 Not Found', TRUE);
+       exit;
+}
+
+?>
\ No newline at end of file
diff --git a/get_rss.php b/get_rss.php
new file mode 100644 (file)
index 0000000..1b6e25a
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: get_acheck.php 2291 2004-11-16 19:35:41Z joel $
+
+/* call it:
+ * ATUTOR_PATH/get_rss.php?COURSE_ID-VERSION
+
+       COURSE_ID: integer value of the course (non-zero)
+       VERSION: [1|2] version of RSS
+*/
+
+/* assumption: if the rss files exist, then they're supposed to exist and are public.
+ * if the rss file does not exist: check if this course has it enabled, and create it if needed.
+ * that way rss is only ever created if it's ever called. if it's enabled and never viewed, then there's no need
+ * to generate the files.
+ */
+
+$_user_location        = 'public';
+
+define('AT_INCLUDE_PATH', 'include/');
+require(AT_INCLUDE_PATH . '/vitals.inc.php');
+
+if (isset($_SERVER['QUERY_STRING'])) {
+       $parts   = explode('-', $_SERVER['QUERY_STRING'], 2);
+       $course  = intval($parts[0]);
+       $version = intval($parts[1]);
+} else {
+       header('HTTP/1.1 404 Not Found');
+       exit;
+}
+
+if (file_exists(AT_CONTENT_DIR . 'feeds/' . $course . '/RSS' . $version . '.0.xml')) {
+       header('Content-Type: text/xml');
+       header('Content-Length: ' . filesize(AT_CONTENT_DIR . 'feeds/' . $course . '/RSS'.$version.'.0.xml'));
+       echo file_get_contents(AT_CONTENT_DIR . 'feeds/' . $course . '/RSS'.$version.'.0.xml');
+       exit;
+} // else: (rss does not exist)
+if ($system_courses[$course]['rss'] && (($version == 1) || ($version == 2))) {
+       // only RSS1 and 2 for now.
+
+       require(AT_INCLUDE_PATH . 'classes/feedcreator.class.php');
+
+       if (!is_dir(AT_CONTENT_DIR.'feeds/')){
+               @mkdir(AT_CONTENT_DIR. 'feeds/', 0700);
+       }
+       if (!is_dir(AT_CONTENT_DIR . 'feeds/' . $course)){
+               @mkdir(AT_CONTENT_DIR . 'feeds/' . $course . '/', 0700);
+       }
+
+       $rss = new UniversalFeedCreator();
+       $rss->useCached();
+       $rss->title          = $system_courses[$course]['title'];
+       $rss->description    = $system_courses[$course]['description'];
+       $rss->link           = AT_BASE_HREF;
+       $rss->syndicationURL = AT_BASE_HREF;
+       
+       $image = new FeedImage();
+       $image->title = 'ATutor Logo';
+       $image->url   = AT_BASE_HREF . 'images/at-logo.v.3.gif';
+       $image->link  = AT_BASE_HREF;
+       $rss->image   = $image;
+
+       $sql = "SELECT A.*, M.login from ".TABLE_PREFIX."news A, ".TABLE_PREFIX."members M WHERE A.course_id = ".$course." AND A.member_id=M.member_id ORDER BY A.date DESC LIMIT 5";
+
+       $res = mysql_query($sql, $db);
+
+       while ($data = mysql_fetch_assoc($res)) {
+               $item = new FeedItem();
+               
+               $item->title          = $data['title'];
+               $item->link           = AT_BASE_HREF . 'index.php';
+               $item->description    = $data['body'];
+               $item->date           = strtotime($data['date']);
+               $item->source         = AT_BASE_HREF;
+               $item->author         = $data['login'];
+
+               $rss->addItem($item);
+       }
+
+       header('Content-Type: text/xml');
+       $rss->saveFeed('RSS'.$version.'.0', AT_CONTENT_DIR . 'feeds/' . $course . '/RSS' . $version . '.0.xml', false);
+
+       echo file_get_contents(AT_CONTENT_DIR . 'feeds/' . $course . '/RSS'.$version.'.0.xml');
+
+       exit;
+} // else: this course didn't enable rss
+
+header('HTTP/1.1 404 Not Found');
+exit;
+
+
+?>
\ No newline at end of file
diff --git a/glossary/index.php b/glossary/index.php
new file mode 100644 (file)
index 0000000..373e801
--- /dev/null
@@ -0,0 +1,146 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+require (AT_INCLUDE_PATH.'header.inc.php');
+
+$sql   = "SELECT word_id, related_word_id FROM ".TABLE_PREFIX."glossary WHERE related_word_id>0 AND course_id=$_SESSION[course_id] ORDER BY related_word_id";
+$result = mysql_query($sql, $db);
+while ($row = mysql_fetch_array($result)) {
+       $glossary_related[$row['related_word_id']][] = $row['word_id'];                 
+}
+
+$_GET['w'] = stripslashes($_GET['w']);
+
+if ($_GET['w']) {
+       $sql = "SELECT * FROM ".TABLE_PREFIX."glossary WHERE course_id=$_SESSION[course_id] AND word='".addslashes(urldecode($_GET['w']))."'";          
+} else {
+       $sql = "SELECT * FROM ".TABLE_PREFIX."glossary WHERE course_id=$_SESSION[course_id] ORDER BY word";                     
+}
+
+$result= mysql_query($sql, $db);
+
+if(mysql_num_rows($result) > 0){               
+
+       $gloss_results = array();
+       while ($row = mysql_fetch_assoc($result)) {
+               $gloss_results[] = $row;
+       }
+       $num_results = count($gloss_results);
+       $results_per_page = 25;
+       $num_pages = ceil($num_results / $results_per_page);
+       $page = intval($_GET['p']);
+       if (!$page) {
+               $page = 1;
+       }
+       
+       $count = (($page-1) * $results_per_page) + 1;
+       $gloss_results = array_slice($gloss_results, ($page-1)*$results_per_page, $results_per_page);
+
+       if($num_pages > 1):
+       ?>
+       <div class="paging">
+               <ul>
+               <?php for ($i=1; $i<=$num_pages; $i++): ?>
+                       <li>
+                               <?php if ($i == $page) : ?>
+                                       <a class="current" href="<?php echo url_rewrite('glossary/index.php?p='.$i.'#list'); ?>"><em><?php echo $i; ?></em></a>
+                               <?php else: ?>
+                                       <a href="<?php echo url_rewrite('glossary/index.php?p='.$i.'#list'); ?>"><?php echo $i; ?></a>
+                               <?php endif; ?>
+                       </li>
+               <?php endfor; ?>
+               </ul>
+       </div>
+       <?php endif; ?>
+
+<a name="list"></a>
+
+<?php
+       $current_letter = '';
+       foreach ($gloss_results as $item):
+               $item['word'] = AT_print($item['word'], 'glossary.word');
+
+               if ($current_letter != $strtoupper($substr($item['word'], 0, 1))):
+                       if ($current_letter != '') {                            
+                               echo '</dl>';
+                       } 
+                       $current_letter = $strtoupper($substr($item['word'], 0, 1)); ?>
+                       <h3 style="padding-bottom:5px;"><a name="<?php echo $current_letter; ?>"></a><?php echo $current_letter; ?></h3>
+                       <dl style="margin:0px;">
+               <?php endif; ?>
+
+                       <dt>
+                       <?php if ($_GET['w']): ?>
+                               <a name="term"></a>
+                       <?php else: ?>
+                               <a name="<?php echo urlencode($item['word']); ?>"></a>
+                       <?php endif; ?>
+                       <strong><?php echo stripslashes($item['word']); ?>
+
+                       <?php if (($item['related_word_id'] != 0) || (is_array($glossary_related[urlencode($item['word_id'])]) )):
+                               echo ' ('._AT('see').': ';
+
+                               $output = false;
+
+                               if ($item['related_word_id'] != 0) {
+                                       echo '<a href="'.$_SERVER['PHP_SELF'].'?w='.addslashes(urlencode($glossary_ids[$item['related_word_id']])).'#term">'.urldecode($glossary_ids[$item['related_word_id']]).'</a>';
+                                       $output = true;
+                               }
+
+                               if (is_array($glossary_related[urlencode($item['word_id'])]) ) {
+                                       $my_related = $glossary_related[$item['word_id']];
+
+                                       $num_related = count($my_related);
+                                       for ($i=0; $i<$num_related; $i++) {
+                                               if ($glossary_ids[$my_related[$i]] == $glossary_ids[$item['related_word_id']]) {
+                                                       continue;
+                                               }
+                                               if ($output) {
+                                                       echo ', ';
+                                               }
+
+                                               echo '<a href="'.$_SERVER['PHP_SELF'].'?w='.urlencode($glossary_ids[$my_related[$i]]).'#term">'.urldecode($glossary_ids[$my_related[$i]]).'</a>';
+
+                                               $output = true;
+                                       }
+                               }
+                               echo ')';
+               endif; ?>
+               </strong></dt>
+
+               <dd><?php echo AT_print($item['definition'], 'glossary.definition'); ?><br /><br /></dd>
+
+
+       <?php endforeach; ?>
+
+       </dl>
+
+<?php
+       if ($_GET['w']) {
+               echo '<br /><br /><a href="glossary/index.php">'._AT('view_all').'</a>';
+
+               if ($_GET['g_cid']) {
+                       $path   = $contentManager->getContentPath(intval($_GET['g_cid']));
+                       echo ' | '._AT('back_to').' <a href="'.url_rewrite('content.php?cid='.intval($_GET['g_cid'])).'">'.$path[0]['title'].'</a>';
+               }
+       }
+       
+} else {
+       echo '<p>'._AT('no_glossary_items').'</p>';
+}
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/go.php b/go.php
new file mode 100644 (file)
index 0000000..884d9f8
--- /dev/null
+++ b/go.php
@@ -0,0 +1,96 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                             */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id: redirect.php 7208 2008-01-09 16:07:24Z harris $
+
+define('AT_INCLUDE_PATH', 'include/');
+define('AT_REDIRECT_LOADED', true);
+
+$_user_location        = 'public';  //like browse, and registration, doesn't need username/passwords to get into
+
+require_once(AT_INCLUDE_PATH . 'classes/UrlRewrite/UrlParser.class.php');
+include_once(AT_INCLUDE_PATH.'config.inc.php');
+require_once(AT_INCLUDE_PATH.'lib/constants.inc.php');
+require_once(AT_INCLUDE_PATH.'lib/mysql_connect.inc.php');
+//require_once(AT_INCLUDE_PATH.'vitals.inc.php');
+
+//mimic config variables, vitals.inc.php 135-140
+/* get config variables. if they're not in the db then it uses the installation default value in constants.inc.php */
+$sql    = "SELECT * FROM ".TABLE_PREFIX."config";
+$result = mysql_query($sql, $db);
+while ($row = mysql_fetch_assoc($result)) { 
+       $_config[$row['name']] = $row['value'];
+}
+
+//Handles path_info in diff versions of PHP 
+if(isset($_SERVER['ORIG_PATH_INFO']) && $_SERVER['ORIG_PATH_INFO']!=''){
+       $pathinfo = $_SERVER['ORIG_PATH_INFO']; 
+} else {
+       $pathinfo = $_SERVER['PATH_INFO'];      
+}
+$url_parser = new UrlParser($pathinfo);
+$path_array =  $url_parser->getPathArray();
+$_pretty_url_course_id = $path_array[0];
+$obj = $path_array[1];
+
+if (!$obj->isEmpty()){
+       /* 
+        * Addresses the issue for relative uri 
+        * @refer to constants.inc.php $_rel_link
+        */
+       $_rel_url = $obj->redirect();
+       $var_query = $obj->parsePrettyQuery();
+       save2Get($var_query);   //remake all the _GET and _REQUEST variables so that the vitals can use it
+
+       $_user_location = '';   //reset user_location so that the vital file in each page would validate
+       $pretty_current_page = $obj->getPage();
+       //If page not found, forward back to index.php
+       if (!@include($obj->getPage())){
+               header('Location: index.php');
+               exit;
+       } 
+} elseif ($_pretty_url_course_id==0) {
+       //TODO: $_SESSION[course_id] seems to be resetted to 0, causing vitals.inc.php line 273 to redirect incorrectly.
+       //              Need to find out where exactly the course_id is being resetted. 
+       return;
+//     header('location: '.AT_BASE_HREF.'bounce.php?course=0');
+//     exit;
+} elseif ($_pretty_url_course_id != ''){
+       header('location: '.AT_BASE_HREF.'bounce.php?course='.$_pretty_url_course_id);
+       exit;
+}
+
+
+/**
+ * This function will reconstruct all the $_GET variables.
+ * @param      array   consist of all the pathinfo variables in querystring format
+ */
+function save2Get($var_query){
+       if (empty($var_query) || !is_array($var_query))
+               return;
+       foreach($var_query as $k=>$v){
+               if ($k=='page_to_load'){
+                       continue;
+               }
+
+               //If mod_rewrite is on, the page# will be shown as <page#>.html.
+               //in this case, parse the page number out.
+               if ($k=='page'){
+                       if (preg_match('/(.*)\.html$/', $v, $matches)==1){
+                               $v = $matches[1];
+                       }
+               }
+               $_GET[$k] = $v;
+               $_REQUEST[$k] = $v;
+       }
+}
+?>
\ No newline at end of file
diff --git a/google_search/admin/module_prefs.php b/google_search/admin/module_prefs.php
new file mode 100644 (file)
index 0000000..10cf5ec
--- /dev/null
@@ -0,0 +1,127 @@
+<?php\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_ADMIN);\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$key = $_config['gsearch'];\r
+$googleType = $_config['gtype'];\r
+\r
+//For AJAX validation.  If valid key, save it.\r
+if (isset($_GET['keyIsValidated'])){\r
+       $_GET['key'] = trim($_GET['key']);\r
+       $_GET['gtype'] = trim($_GET['gtype']);\r
+       if ($_GET['keyIsValidated']=='true'){\r
+               $key = $addslashes($_GET['key']);\r
+               $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES('gsearch','$key')";\r
+               $result = mysql_query($sql, $db);\r
+               $msg->addFeedback('GOOGLE_KEY_SAVED');\r
+       } elseif ($_GET['keyIsValidated']=='false'){\r
+               //If invalid, remove whatever key that's in the system\r
+               $msg->addError('GOOGLE_KEY_INVALID');\r
+               $key = htmlspecialchars($stripslashes($_GET['key']));\r
+               $sql = "DELETE FROM ".TABLE_PREFIX."config WHERE name='gsearch'";\r
+               $result = mysql_query($sql, $db);\r
+               $key = '';\r
+       }\r
+       //Manually print it out\r
+       $msg->printAll();\r
+}\r
+\r
+if (isset($_POST['submit'])) {\r
+       require('../../mods/_standard/google_search/SOAP_Google.php');\r
+       $_POST['key'] = trim($_POST['key']);\r
+       $_POST['gtype'] = trim($_POST['gtype']);\r
+\r
+       if ($_POST['key']) {\r
+               //Default google search type to soap\r
+               if (!isset($_POST['gtype'])){\r
+                       $_POST['gtype'] = GOOGLE_TYPE_SOAP;\r
+               }\r
+               if ($_POST['gtype']==GOOGLE_TYPE_SOAP){\r
+                       //test key\r
+                       $google = new SOAP_Google($_POST['key']);\r
+                       $search_array = array();\r
+                       $search_array['filter'] = true; \r
+                       $search_array['query'] = 'testing';\r
+                       $search_array['maxResults'] = 1;\r
+                       $search_array['lr'] = "lang_en";\r
+\r
+                       $result = $google->search($search_array);\r
+\r
+                       if (isset($result['faultstring'])) {\r
+                               //If it is invalid, remove whatever keys that are in the system.\r
+                               $msg->addError('GOOGLE_KEY_INVALID');\r
+                               $key = htmlspecialchars($stripslashes($_POST['key']));\r
+                               $sql = "DELETE FROM ".TABLE_PREFIX."config WHERE name='gsearch'";\r
+                               $result = mysql_query($sql, $db);\r
+                               $key = '';\r
+                       } else {\r
+                               $key = $addslashes($_POST['key']);\r
+                               $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES('gsearch','$key')";\r
+                               $result = mysql_query($sql, $db);\r
+                               $msg->addFeedback('GOOGLE_KEY_SAVED');\r
+                       }\r
+               } elseif ($_POST['gtype']==GOOGLE_TYPE_AJAX){                   \r
+                       $key = $addslashes($_POST['key']);\r
+                       $gtype = $addslashes($_POST['gtype']);\r
+                       //Test the key by the script site.\r
+                       ?>              \r
+                          <script src="http://www.google.com/uds/api?file=uds.js&amp;v=1.0&key=<?php echo $key?>" type="text/javascript"></script>\r
+                      <script type="text/javascript">\r
+                                       location.href="<?php echo $_SERVER['SCRIPT_NAME'].'?'.'key='.$key.'&gtype='.$gtype.'&keyIsValidated='?>" + UDS_KeyVerified;\r
+                               </script>\r
+               <?php\r
+               }\r
+       } else {\r
+               $sql = "DELETE FROM ".TABLE_PREFIX."config WHERE name='gsearch'";\r
+               $result = mysql_query($sql, $db);\r
+               $msg->addFeedback('GOOGLE_KEY_SAVED');\r
+               $key = '';\r
+       }\r
+\r
+       //Set Google interface's type.\r
+       $googleType = $addslashes($_POST['gtype']);\r
+       $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES('gtype','$googleType')";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       //Manually print it out\r
+       $msg->printAll();\r
+}\r
+\r
+?>\r
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">\r
+       <div class="input-form" style="max-width: 525px">\r
+               <div class="row">\r
+                       <?php echo _AT("google_search_type_txt"); ?><br/>\r
+                       <?php\r
+                               if ($googleType==GOOGLE_TYPE_SOAP){\r
+                                       $type1=' checked="checked"'; \r
+                               } elseif ($googleType==GOOGLE_TYPE_AJAX){\r
+                                       $type2=' checked="checked"'; \r
+                               }\r
+                       ?>\r
+                       <input type="radio" name="gtype" id="googleTypeSoap" value="<?php echo GOOGLE_TYPE_SOAP?>" <?php echo $type1 ?>/>\r
+                       <label for="googleTypeSoap"><?php echo _AT("google_search_soap"); ?></label><br/>\r
+\r
+                       <input type="radio" name="gtype" id="googleTypeAjax" value="<?php echo GOOGLE_TYPE_AJAX?>" <?php echo $type2 ?>/>\r
+                       <label for="googleTypeAjax"><?php echo _AT("google_search_ajax"); ?></label><br/>\r
+               </div>\r
+               \r
+               <div class="row">\r
+                       <?php echo _AT('google_search_attn'); ?><br/><br/>\r
+                       <?php echo _AT('google_key_txt'); ?>\r
+               </div>\r
+               <div class="row">\r
+                       <input type="text" name="key" size="80" value="<?php echo $key; ?>" style="min-width: 90%;" />\r
+               </div>\r
+\r
+               <div class="row buttons">\r
+                       <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />\r
+               </div>\r
+       </div>\r
+\r
+</form>\r
+\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/google_search/google.gif b/google_search/google.gif
new file mode 100644 (file)
index 0000000..845b9f9
Binary files /dev/null and b/google_search/google.gif differ
diff --git a/google_search/gsearch.php b/google_search/gsearch.php
new file mode 100644 (file)
index 0000000..bc80d31
--- /dev/null
@@ -0,0 +1,317 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008                                      */\r
+/* Written by Harris Wong                                                                      */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id: gsearch.php 1 2007-08-31 12:15:41Z harris $\r
+?>\r
+<script src="http://www.google.com/uds/api?file=uds.js<?php echo "&amp;"; ?>hl=<?php echo $_SESSION['lang']; ?><?php echo "&amp;"; ?>v=1.0<?php echo "&amp;"; ?>key=<?php echo $search_key; ?>" type="text/javascript"></script>\r
+<script type="text/javascript">\r
+       /* This can only be run after importing the google uds.  \r
+        * Ref:         google ajax api.\r
+        * @url         http://code.google.com/apis/ajaxsearch/documentation/reference.html\r
+        */\r
+       //<![CDATA[\r
+       var gsearch;  \r
+       function OnLoad() {\r
+         gsearch = new RawSearchControl();             //instantiate google search object.\r
+         /* The following is for the side menu search.  */\r
+         var q = "<?php echo $side_menu_q; ?>";\r
+         if (q != ""){\r
+                 gsearch.instantSearch(q);\r
+         }\r
+       }\r
+\r
+       /**\r
+        * The RawSearchControl demonstrates how to use Searcher Objects\r
+        * outside of the standard GSearchControl. This includes calling\r
+        * searcher .execute() methods, reacting to search completions,\r
+        * and if you had previously disabled html generation, how to generate\r
+        * an html representation of the result.\r
+        */     \r
+       function RawSearchControl() {\r
+         // latch on to key portions of the document\r
+         this.searcherform = document.getElementById("searcher");\r
+         this.results = document.getElementById("results");\r
+         this.searchform = document.getElementById("searchform");\r
+         this.selector = "";\r
+         this.query = "";\r
+         this.currentSearchType = "";\r
+\r
+         // create map of searchers as well as note the active searcher\r
+         this.searchers = new Array();\r
+         // create and wire up an instance of GwebSearch and one of\r
+         // GlocalSearch. Note that we register to handle search completion notifications\r
+         // when searches complete, they are called in the context of this instance\r
+         // of RawSearchControl and they are passed the searcher that just completed\r
+         for (var i=0; i<7; i++){\r
+                       var searcher = new GwebSearch();\r
+                       switch(i){\r
+                               case 0: \r
+                                       searcher = new GwebSearch();\r
+                                       break;\r
+                               case 1:\r
+                                       searcher = new GlocalSearch();\r
+                                       searcher.setCenterPoint("98074");\r
+                                       break;\r
+                               case 2:\r
+                                       searcher = new GimageSearch();\r
+                                       break;\r
+                               case 3:\r
+                                       searcher = new GvideoSearch();\r
+                                       break;\r
+                               case 4:\r
+                                       searcher = new GnewsSearch();\r
+                                       break;\r
+                               case 5:\r
+                                       searcher = new GblogSearch();\r
+                                       break;\r
+                               case 6:\r
+                                       searcher = new GbookSearch();\r
+                                       break;\r
+                       }\r
+                 searcher.setNoHtmlGeneration();\r
+                 searcher.setSearchCompleteCallback(this,\r
+                                                                                        RawSearchControl.prototype.searchComplete,\r
+                                                                                        [searcher]\r
+                                                                                        );\r
+                 searcher.setResultSetSize(GSearch.LARGE_RESULTSET);\r
+                 searcher.setLinkTarget("temp_new_search");\r
+                 this.searchers[i] = searcher;\r
+         }\r
+\r
+         // now, create a search form and wire up a submit and clear handler\r
+         this.searchForm = new GSearchForm(false, this.searchform);\r
+         this.searchForm.setOnSubmitCallback(this,\r
+                                                                                 RawSearchControl.prototype.onSubmit);\r
+       }\r
+\r
+       /**\r
+        * figure out which searcher is active by looking at the radio\r
+        * button array\r
+        */\r
+       RawSearchControl.prototype.computeActiveSearcher = function() {\r
+               if (this.currentSearchType=="" ){\r
+                         this.activeSearcher = 0;\r
+               } else {\r
+                         this.activeSearcher = this.currentSearchType;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Inject the query into the form, and triggers a instant search\r
+        * @param       The query\r
+        */\r
+        RawSearchControl.prototype.instantSearch = function(q){\r
+                this.searchForm.input.value = q;\r
+                this.onSubmit(this.searchForm);\r
+        }\r
+\r
+       /**\r
+         * figure out which link is being selected, then change that style.\r
+         * reset all other styles.\r
+         * @param      searcherTypeIndex       is the integer that maps onto the searcherType string\r
+         */\r
+       RawSearchControl.prototype.activate = function (searcherTypeIndex){\r
+               for (var i=0; i<this.searchers.length; i++){\r
+                       var gsearcher = this.searchers[i];                                              \r
+                       searcherType = this.getSearcherTypeString(i)[0];        \r
+                       this.selector = document.getElementById(searcherType + "Selector");\r
+                       if (i==searcherTypeIndex){\r
+                               //Run this query, activate the menu bar.\r
+                               this.currentSearchType = searcherTypeIndex;\r
+                               cssSetClass(this.selector, "active");\r
+                               this.computeActiveSearcher();\r
+                               var q = this.searchForm.input.value;\r
+                               if (q) {\r
+                                       gsearcher.execute(q);\r
+                               }\r
+                       } else {\r
+                               cssSetClass(this.selector, "");\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+        * This functiion will retrieve the string of the searcher type by the given index\r
+        */\r
+        RawSearchControl.prototype.getSearcherTypeString = function(searcherTypeIndex){\r
+                       var s;\r
+                       switch(searcherTypeIndex){\r
+                               case 1:\r
+                                       s = new Array("local", "http://www.google.ca/maps?");\r
+                                       break;\r
+                               case 2:\r
+                                       s = new Array("image", "http://www.google.ca/images?");\r
+                                       break;\r
+                               case 3:\r
+                                       s = new Array("video", "http://video.google.ca/videosearch?");\r
+                                       break;\r
+                               case 4:\r
+                                       s = new Array("news", "http://www.google.ca/news?");\r
+                                       break;\r
+                               case 5:\r
+                                       s = new Array("blog", "http://www.google.ca/blogsearch?");\r
+                                       break;\r
+                               case 6:\r
+                                       s = new Array("book", "http://www.google.ca/books?");\r
+                                       break;\r
+                               case 0:\r
+                               default:\r
+                                       s = new Array("web", "http://www.google.ca/search?");\r
+                                       break;\r
+                       }\r
+                       return s;\r
+        }\r
+\r
+       /**\r
+        * onSubmit - called when the search form is "submitted" meaning that\r
+        * someone pressed the search button or hit enter. The form is passed\r
+        * as an argument\r
+        */\r
+       RawSearchControl.prototype.onSubmit = function(form) {\r
+         this.computeActiveSearcher();\r
+         if (form.input.value) {\r
+               // if there is an expression in the form, call the active searcher's\r
+               // .execute method\r
+               this.query = form.input.value;\r
+               this.searchers[this.activeSearcher].execute(form.input.value);\r
+         }\r
+         // always indicate that we handled the submit event\r
+         return false;\r
+       }\r
+\r
+       /**\r
+        * onClear - called when someone clicks on the clear button (the little x)\r
+        */\r
+       RawSearchControl.prototype.onClear = function(form) {\r
+         this.clearResults();\r
+       }\r
+\r
+       /**\r
+        * searchComplete - called when a search completed. Note the searcher\r
+        * that is completing is passes as an arg because thats what we arranged\r
+        * when we called setSearchCompleteCallback\r
+        */\r
+       RawSearchControl.prototype.searchComplete = function(searcher) {\r
+         // always clear old from the page\r
+         this.clearResults();\r
+\r
+         // if the searcher has results then process them\r
+         if (searcher.results && searcher.results.length > 0) {\r
+               // now manually generate the html that we disabled\r
+               // initially and display it\r
+               var div = createDiv("", "");\r
+               this.results.appendChild(div);\r
+               for (var i=0; i<searcher.results.length; i++) {\r
+                 var result = searcher.results[i];\r
+                 searcher.createResultHtml(result);\r
+                 if (result.html) {\r
+                       div = result.html.cloneNode(true);\r
+                 } else {\r
+                       div = createDiv("** failure to create html **");\r
+                 }\r
+                 this.results.appendChild(div);\r
+               }\r
+               div = createDiv("");\r
+               a_elem = createAnchor("More results >>", this.generateMoreResultsURL());\r
+               div.appendChild(a_elem);\r
+               this.results.appendChild(div);\r
+         } else {\r
+               var div = createDiv("No results for: " + this.searchForm.input.value, "");\r
+               this.results.appendChild(div);\r
+         }\r
+       }\r
+\r
+       /**\r
+        * This function returns the appropriate link for the "More results" at the bottom of a search.\r
+        * The "More results" should correspond to the category the search was performed in.(ie. maps, video, images...)\r
+        * @return      the URL described above.\r
+        */\r
+       RawSearchControl.prototype.generateMoreResultsURL = function(){\r
+               var s = "";\r
+               var link = this.getSearcherTypeString(this.activeSearcher)[1];\r
+               return (link + "hl=<?php echo $_SESSION['lang']?>&q=" + this.searchForm.input.value);\r
+       }\r
+\r
+       /**\r
+        * clearResults - clear out any old search results\r
+        */\r
+       RawSearchControl.prototype.clearResults = function() {\r
+         removeChildren(this.results);\r
+       }\r
+\r
+       /**\r
+        * Static DOM Helper Functions\r
+        */\r
+       function removeChildren(parent) {\r
+         while (parent.firstChild) {\r
+               parent.removeChild(parent.firstChild);\r
+         }\r
+       }\r
+       function createDiv(opt_text, opt_className) {\r
+         var el = document.createElement("div");\r
+         if (opt_text) {\r
+               el.innerHTML = opt_text;\r
+         }\r
+         if (opt_className) { el.className = opt_className; }\r
+         return el;\r
+       }\r
+       function createAnchor(a_text, a_href, a_className){\r
+         var el = document.createElement("a");\r
+         if(a_text){\r
+                 el.innerHTML = a_text;\r
+                 el.href = a_href;\r
+                 el.target = "temp_google_search";\r
+         }\r
+         if (a_className){ a.className = a_className;}\r
+         return el;\r
+       }\r
+\r
+       /**\r
+         * CSS helper\r
+         */\r
+       function cssSetClass(el, className) {\r
+               el.className = className;\r
+       }\r
+\r
+       // register to be called at OnLoad when the page loads\r
+       GSearch.setOnLoadCallback(OnLoad);\r
+       //]]>\r
+</script>\r
+\r
+<form id="searcher" method="get" action="">\r
+  <table border='0'>\r
+       <tr><td colspan="2">\r
+       <div class="selector">\r
+       <ul id="navlist">\r
+               <li><a id="webSelector" class="active" href="javascript:gsearch.activate(0);"><?php echo _AT('google_search'); ?></a></li>\r
+               <li><a id="localSelector" href="javascript:gsearch.activate(1);"><?php echo _AT('google_search_local'); ?></a></li>\r
+               <li><a id="imageSelector" href="javascript:gsearch.activate(2);"><?php echo _AT('google_search_images'); ?></a></li>\r
+               <li><a id="videoSelector" href="javascript:gsearch.activate(3);"><?php echo _AT('google_search_videos'); ?></a></li>\r
+               <li><a id="newsSelector" href="javascript:gsearch.activate(4);"><?php echo _AT('google_search_news'); ?></a></li>\r
+               <li><a id="blogSelector" href="javascript:gsearch.activate(5);"><?php echo _AT('blogs'); ?></a></li>\r
+               <li><a id="bookSelector" href="javascript:gsearch.activate(6);"><?php echo _AT('google_search_books'); ?></a></li>\r
+       </ul></div></td>\r
+       </tr>\r
+       <tr>\r
+       <td class="search-form">\r
+         <div id="searchform">Loading</div>\r
+       </td>\r
+       <!-- For clearing the results\r
+       <td>\r
+         <input name="clearResult" value="clear" type="button" class="button" onclick="gsearch.clearResults();"/>\r
+       </td>\r
+       -->\r
+       </tr>\r
+  </table>\r
+</form>\r
+<div id="results"></div>\r
diff --git a/google_search/index.php b/google_search/index.php
new file mode 100644 (file)
index 0000000..20fdce4
--- /dev/null
@@ -0,0 +1,109 @@
+<?php\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'../mods/_standard/google_search/SOAP_Google.php');\r
+$_custom_css = $_base_path . 'mods/_standard/google_search/module.css'; // use a custom stylesheet\r
+$search_key = $_config['gsearch'];\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+?>\r
+\r
+<?php \r
+/* \r
+ * Check which type of google search this is, and perform the corresponding action\r
+ * Note:       If the key was invalid, it doesn't matter what search type the admin has chosen.\r
+ *                     It should simply just forward the query to the Google site.\r
+ */\r
+if (!$_config['gsearch'] || $_config['gtype']==GOOGLE_TYPE_SOAP){ ?>\r
+       <?php\r
+       //Search post - SOAP\r
+       if (isset($_GET['submit'])){\r
+               $google = new SOAP_Google($search_key);\r
+               $search_array = array();\r
+               $search_array['filter'] = true; \r
+               $search_array['query'] = stripslashes($_GET['q']);\r
+               $search_array['maxResults'] = 10;\r
+               $search_array['lr'] = "lang_en";\r
+\r
+               $result = $google->search($search_array);\r
+\r
+               if (isset($result['faultstring'])) {\r
+                       $msg->printErrorS('GOOGLE_QUERY_FAILED');\r
+               } else if ($result) {\r
+                       echo '<h3>Search Results</h3>';\r
+                       if (is_array($result['resultElements'])) {\r
+                               echo '<ol>';\r
+\r
+                               foreach ($result['resultElements'] as $r) {\r
+                                       echo '<li><a href="' . $r['URL'] . '">' . ($r['title'] ? $r['title'] : '<em>'._AT('no_title').'</em>' ) . '</a>';\r
+                                       echo '<br />';\r
+                                       echo '<small>'.($r['snippet'] ? $r['snippet'] : '<em>'._AT('no_content_avail').'</em>' ) .'<br /><i>'.$r['URL'].'</i></small>';\r
+                                       echo '</li>';\r
+                               }\r
+\r
+                               if (count($result['resultElements']) == 10) {\r
+                                       $search_array['start'] = 10;    \r
+                                       $result2 = $google->search($search_array);\r
+\r
+                                       if (false !== $result2) {               \r
+                                               foreach ($result2['resultElements'] as $r) {\r
+                                                       echo '<li><a href="' . $r['URL'] . '">' . ($r['title'] ? $r['title'] : '<em>'._AT('no_title').'</em>' ) . '</a>';\r
+                                                       echo '<br />';\r
+                                                       echo '<small>'.($r['snippet'] ? $r['snippet'] : '<em>'._AT('no_content_avail').'</em>' ) .'<br /><i>'.$r['URL'].'</i></small>';\r
+                                                       echo '</li>';\r
+                                               }\r
+                                       } \r
+                               }\r
+                               echo '</ol>';\r
+\r
+                               if (count($result2['resultElements']) == 10) {\r
+                                       echo '<p><i>'._AT('top_20').'</i></p>';\r
+                               }\r
+                       } else {\r
+                               echo '<p>'._AT('none_found').'</p>';\r
+                       }\r
+               } \r
+       }\r
+       ?>\r
+       <?php if ($_config['gsearch']): ?>\r
+               <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get">\r
+       <?php else: ?>\r
+               <form action="http://www.google.com/search" method="get" target="_new">\r
+               <input type="hidden" name="hl" value="<?php echo $_SESSION['lang']; ?>" />\r
+       <?php endif; ?>\r
+\r
+       <div class="input-form" style="max-width: 525px">\r
+               <div class="row">\r
+                       <?php echo _AT('google_search_txt'); ?>\r
+                       <?php if (!$_config['gsearch']): ?>\r
+                               <br /><br />\r
+                               <p><?php echo _AT('google_new_window'); ?></p>\r
+                       <?php endif; ?>\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="keywords"><?php echo _AT('search_words'); ?></label><br />\r
+                       <input type="text" name="q" size="30" id="keywords" value="<?php echo htmlspecialchars($stripslashes($_GET['q'])); ?>" />\r
+               </div>\r
+\r
+               <div class="row buttons">\r
+                       <input type="hidden" name="submit" value="<?php echo _AT('search'); ?>"/>\r
+                       <input type="submit"  accesskey="s" />\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <small><?php echo _AT('powered_by_google'); ?></small>\r
+               </div>\r
+       </div>\r
+       </form>\r
+\r
+<?php\r
+} elseif ($_config['gtype']==GOOGLE_TYPE_AJAX){  \r
+       $side_menu_q = stripslashes($_GET['q']);        //side menu query\r
+       include('gsearch.php');\r
+} ?>\r
+\r
+\r
+<?php\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/groups.php b/groups.php
new file mode 100644 (file)
index 0000000..0522449
--- /dev/null
@@ -0,0 +1,53 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', 'include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+if (!$_SESSION['groups']) {\r
+       $msg->printErrors('NOT_IN_ANY_GROUPS');\r
+       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+$group_list = implode(',', $_SESSION['groups']);\r
+$sql = "SELECT group_id, title, modules FROM ".TABLE_PREFIX."groups WHERE group_id IN ($group_list) ORDER BY title";\r
+$result = mysql_query($sql, $db);\r
+\r
+echo '<ol id="tools">';\r
+\r
+while ($row = mysql_fetch_assoc($result)) {\r
+       echo '<li class="top-tool">'.$row['title'] . ' ';\r
+\r
+       $modules = explode('|', $row['modules']);\r
+       asort($modules);\r
+\r
+       if ($modules) {\r
+               echo '<ul class="child-top-tool">';\r
+               foreach ($modules as $module_name) {\r
+                       $fn = basename($module_name) . '_get_group_url';\r
+                       $module =& $moduleFactory->getModule($module_name);\r
+                       if ($module->isEnabled() && function_exists($fn)) {\r
+                               echo '<li class="child-tool"><a href="'. url_rewrite($fn($row['group_id'])) .'">'._AT($_pages[$module->getGroupTool()]['title_var']).'</a></li>';\r
+                       }\r
+               }\r
+               echo '</ul>';\r
+       }\r
+       echo '</li>';\r
+}\r
+echo '</ol>';\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/headstuff.php b/headstuff.php
new file mode 100644 (file)
index 0000000..e48a59b
--- /dev/null
@@ -0,0 +1,124 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008                                                                                             */
+/* Written by Greg Gay & Joel Kronenberg & Chris Ridpath                               */
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+define('AT_INCLUDE_PATH', 'include/');
+require(AT_INCLUDE_PATH . 'vitals.inc.php');
+
+// hack for eXe content, remove now
+header ('content-type: text/css');
+echo('@import url(exestyles.css);');
+exit;
+
+
+if (isset ($_GET['cid'])){
+       $cid = intval ($_GET['cid']);
+
+       $sql = "SELECT * FROM ".TABLE_PREFIX."head WHERE course_id=$_SESSION[course_id] AND content_id=$cid";
+       $result = mysql_query($sql, $db);
+
+       if (($result != 0) && ($row = mysql_fetch_assoc($result))){
+               // get the CSS used
+               $styleText = get_styles ($row['text'], $_GET['path']);
+
+               header ('content-type: text/css');
+               echo($styleText);
+       }
+}
+
+// Takes the contents of the 'head' section and returns the 'style' and 'link' elements.
+function get_styles ($headText, $path) {
+       $styleText = '';
+
+       // get the contents of all the 'style' elements
+       $styleStartPos = strpos ($headText, '<style');
+       while ($styleStartPos !== false) {
+
+               // remove the start and end 'style' elements
+               // (we're using just the contents of the 'style' element)
+               $styleStartPos = strPos ($headText, '>', $styleStartPos) + 1;
+               $styleEndPos = strPos ($headText, '</style', $styleStartPos) -1;
+
+               // contents of 'style' element
+               $tempString = substr ($headText, $styleStartPos, ($styleEndPos - $styleStartPos) + 1);
+
+               // add full path to any 'import' statements
+               $importStartPos = strpos ($tempString, '@import');
+               if ($importStartPos !== false){
+                       $bracketStartPos = strpos ($tempString, '(', $importStartPos);
+                       if ($bracketStartPos !== false){
+                               $bracketEndPos = strpos ($tempString, ')', $bracketStartPos);
+                               if ($bracketEndPos !== false){
+                                       $uriCss = trim (substr ($tempString, $bracketStartPos + 1, ($bracketEndPos - $bracketStartPos)));
+
+                                       $tempString2 = substr ($tempString, '0', $bracketStartPos);
+                                       $tempString = $tempString2.'('.$path.$uriCss.substr ($tempString, $bracketEndPos + '1');
+                               }
+                       }
+               }
+
+               $styleText = $styleText."\n".$tempString;
+
+               // look for another 'style' element
+               $styleStartPos = strpos ($headText, '<style', $styleEndPos);
+       }
+
+       // get all the links to external stylesheets
+       $linkStartPos = strpos ($headText, '<link');
+       while ($linkStartPos !== false) {
+               $linkEndPos = strPos ($headText, '>', $linkStartPos);
+
+               // ensure this is a 'stylesheet' link
+               $stylesheetPos = strpos ($headText, "\"text/css\"", $linkStartPos);
+               if (($stylesheetPos !== false) && ($stylesheetPos < $linkEndPos)){
+
+                       // get the 'href' attribute value
+                       $hrefPos = strpos ($headText, 'href', $linkStartPos);
+                       if ($hrefPos !== false){
+                               $hrefPos = strpos ($headText, '=', $hrefPos);
+                               if ($hrefPos !== false){
+                                       $hrefPos += '1';
+
+                                       // get first character in attribute value
+                                       $index = $hrefPos;
+
+                                       // find first attribute character
+                                       while (($headText[$index] == " ") || ($headText[$index] == '\'') || ($headText[$index] == "\"")){
+                                               $index++;
+                                               if ($index > strlen($headText)){
+                                                       break;
+                                               }
+                                       }
+                                       $indexStart = $index;
+
+                                       // find end of attribute character
+                                       $indexEnd = $indexStart;
+                                       while (($headText[$indexEnd] != " ") && ($headText[$indexEnd] != '\'') && ($headText[$indexEnd] != "\"")){
+                                               $indexEnd++;
+                                               if ($index > strlen($headText)){
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+
+                       // convert the href attribute value to an "import url" statement
+                       $importStatement = '@import url('.$path.substr ($headText, $indexStart, ($indexEnd - $indexStart)).');';
+                       $styleText = $styleText."\n".$importStatement;
+               }
+
+               // look for another 'link' element
+               $linkStartPos = strpos ($headText, '<link', $linkEndPos);
+       }
+       return $styleText;
+}
+?>
\ No newline at end of file
diff --git a/help/accessibility.php b/help/accessibility.php
new file mode 100644 (file)
index 0000000..f9e2059
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+$_user_location        = 'public';
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+echo _AT('atutor_accessibility_text');
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/help/contact_support.php b/help/contact_support.php
new file mode 100644 (file)
index 0000000..67e004d
--- /dev/null
@@ -0,0 +1,130 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+$_user_location        = 'public';
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php');
+       exit;
+}
+
+$onload = 'document.form.from.focus();';
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if ($_SESSION['member_id']) {
+       $sql    = "SELECT first_name, last_name, email FROM ".TABLE_PREFIX."members WHERE member_id=$_SESSION[member_id]";
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_array($result)) {
+               $student_name = AT_print($row['last_name'], 'members.last_name');
+               $student_name .= (AT_print($row['first_name'], 'members.first_name') ? ', '.AT_print($row['first_name'], 'members.first_name') : '');
+
+               $student_email = AT_print($row['email'], 'members.email');
+       }
+}
+
+if (!$_config['contact_email']) {
+       $msg->printErrors('CONTACT_INFO_NOT_FOUND');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+if (isset($_POST['submit'])) {
+       $missing_fields = array();
+
+       $_POST['subject'] = trim($_POST['subject']);
+       $_POST['body']    = trim($_POST['body']);
+
+       if ($_POST['from'] == '') {
+               $missing_fields[] = _AT('from_name');
+       }
+
+       if ($_POST['from_email'] == '') {
+               $missing_fields[] = _AT('from_email');
+       } else if (!eregi("^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$", $_POST['from_email'])) {
+               $msg->addError('EMAIL_INVALID');
+       }
+
+       if ($_POST['subject'] == '') {
+               $missing_fields[] = _AT('subject');
+       }
+               
+       if ($_POST['body'] == '') {
+               $missing_fields[] = _AT('body');
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       if (!$msg->containsErrors()) {
+
+               require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+
+               $mail = new ATutorMailer;
+
+               $mail->From     = $_POST['from_email'];
+               $mail->FromName = $stripslashes($_POST['from']);
+               $mail->AddAddress($_config['contact_email']);
+               $mail->Subject = $stripslashes($_POST['subject']);
+               $mail->Body    = $stripslashes($_POST['body']);
+
+               if(!$mail->Send()) {
+                  $msg->printErrors('SENDING_ERROR');
+                  exit;
+               }
+               unset($mail);
+               
+               $msg->printFeedbacks('ACTION_COMPLETED_SUCCESSFULLY');
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+}
+
+$msg->printErrors();
+?>
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">
+<div class="input-form">
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="from"><?php echo _AT('from_name'); ?></label><br />
+               <input type="text" name="from" id="from" size="40" value="<?php echo htmlspecialchars($stripslashes($_POST['from'])); ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="from_email"><?php echo _AT('from_email'); ?></label><br />
+               <input type="text" name="from_email" id="from_email" size="40" value="<?php echo htmlspecialchars($stripslashes($_POST['from_email'])); ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="subject"><?php echo _AT('subject'); ?></label><br />
+               <input type="text" name="subject" id="subject" size="40" value="<?php echo htmlspecialchars($stripslashes($_POST['subject'])); ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="body_text"><?php echo _AT('body'); ?></label><br />
+               <textarea cols="55" rows="15" id="body_text" name="body"><?php echo htmlspecialchars($stripslashes($_POST['body'])); ?></textarea>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('send'); ?>" accesskey="s" /> 
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/help/index.php b/help/index.php
new file mode 100644 (file)
index 0000000..9224d85
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+$_user_location        = 'public';
+
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+require (AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<ul>
+       <li style="padding-bottom: 20px;"><a href="documentation/index_list.php?lang=<?php echo $_SESSION['lang']; ?>" onclick="poptastic('<?php echo AT_BASE_HREF; ?>documentation/index_list.php?lang=<?php echo $_SESSION['lang']; ?>'); return false;" target="_new"><?php echo _AT('atutor_handbook');?></a><br />
+               <?php echo _AT('general_help', AT_GUIDES_PATH); ?></li>
+
+       <li style="padding-bottom: 20px;"><a href="help/accessibility.php"><?php echo _AT('accessibility_features'); ?></a>
+               <br /><?php echo _AT('accessibility_features_text'); ?></li>
+
+       <li><a href="help/contact_support.php"><?php echo _AT('contact_support'); ?></a></li>
+</ul>
+
+<h3><?php echo _AT('external_help'); ?></h3>
+<ul>
+
+       <li style="padding-bottom: 20px;"><?php echo _AT('howto_course'); ?>
+               <br /><?php echo _AT('howto_course_text'); ?></li>
+
+       <li><a href="http://www.atutor.ca/forum/7/1.html"><?php echo _AT('tech_support_forum'); ?></a>
+               <br /><?php echo _AT('tech_support_forum_text'); ?></li>
+</ul>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/images/after.gif b/images/after.gif
new file mode 100644 (file)
index 0000000..c05f3ed
Binary files /dev/null and b/images/after.gif differ
diff --git a/images/archive.gif b/images/archive.gif
new file mode 100644 (file)
index 0000000..06c4daa
Binary files /dev/null and b/images/archive.gif differ
diff --git a/images/arrow_ltr.gif b/images/arrow_ltr.gif
new file mode 100644 (file)
index 0000000..90da978
Binary files /dev/null and b/images/arrow_ltr.gif differ
diff --git a/images/arrowicon.gif b/images/arrowicon.gif
new file mode 100644 (file)
index 0000000..86f9cf5
Binary files /dev/null and b/images/arrowicon.gif differ
diff --git a/images/at-logo.gif b/images/at-logo.gif
new file mode 100644 (file)
index 0000000..c15d18d
Binary files /dev/null and b/images/at-logo.gif differ
diff --git a/images/at-logo.v.3.gif b/images/at-logo.v.3.gif
new file mode 100644 (file)
index 0000000..c15d18d
Binary files /dev/null and b/images/at-logo.v.3.gif differ
diff --git a/images/bad.gif b/images/bad.gif
new file mode 100644 (file)
index 0000000..80a2e7b
Binary files /dev/null and b/images/bad.gif differ
diff --git a/images/before.gif b/images/before.gif
new file mode 100644 (file)
index 0000000..a1ba559
Binary files /dev/null and b/images/before.gif differ
diff --git a/images/blue.gif b/images/blue.gif
new file mode 100644 (file)
index 0000000..c824807
Binary files /dev/null and b/images/blue.gif differ
diff --git a/images/calendar.gif b/images/calendar.gif
new file mode 100644 (file)
index 0000000..dc1f31c
Binary files /dev/null and b/images/calendar.gif differ
diff --git a/images/changes_bullet.gif b/images/changes_bullet.gif
new file mode 100644 (file)
index 0000000..d44d47b
Binary files /dev/null and b/images/changes_bullet.gif differ
diff --git a/images/check.gif b/images/check.gif
new file mode 100644 (file)
index 0000000..14834e9
Binary files /dev/null and b/images/check.gif differ
diff --git a/images/checkbox_check.gif b/images/checkbox_check.gif
new file mode 100644 (file)
index 0000000..d374e92
Binary files /dev/null and b/images/checkbox_check.gif differ
diff --git a/images/checkbox_empty.gif b/images/checkbox_empty.gif
new file mode 100644 (file)
index 0000000..b14f6e3
Binary files /dev/null and b/images/checkbox_empty.gif differ
diff --git a/images/checkmark.gif b/images/checkmark.gif
new file mode 100644 (file)
index 0000000..712c1db
Binary files /dev/null and b/images/checkmark.gif differ
diff --git a/images/child_of.gif b/images/child_of.gif
new file mode 100644 (file)
index 0000000..3b48afb
Binary files /dev/null and b/images/child_of.gif differ
diff --git a/images/clr.gif b/images/clr.gif
new file mode 100644 (file)
index 0000000..758ed52
Binary files /dev/null and b/images/clr.gif differ
diff --git a/images/content_pkg.gif b/images/content_pkg.gif
new file mode 100644 (file)
index 0000000..0d225fb
Binary files /dev/null and b/images/content_pkg.gif differ
diff --git a/images/courses/3dgraph.jpg b/images/courses/3dgraph.jpg
new file mode 100644 (file)
index 0000000..8aa608c
Binary files /dev/null and b/images/courses/3dgraph.jpg differ
diff --git a/images/courses/anotomy.jpg b/images/courses/anotomy.jpg
new file mode 100644 (file)
index 0000000..eb138eb
Binary files /dev/null and b/images/courses/anotomy.jpg differ
diff --git a/images/courses/art_supplies.jpg b/images/courses/art_supplies.jpg
new file mode 100644 (file)
index 0000000..3e8f7de
Binary files /dev/null and b/images/courses/art_supplies.jpg differ
diff --git a/images/courses/astronaut.jpg b/images/courses/astronaut.jpg
new file mode 100644 (file)
index 0000000..099e6b9
Binary files /dev/null and b/images/courses/astronaut.jpg differ
diff --git a/images/courses/bar_graph.jpg b/images/courses/bar_graph.jpg
new file mode 100644 (file)
index 0000000..5a2cca3
Binary files /dev/null and b/images/courses/bar_graph.jpg differ
diff --git a/images/courses/books.jpg b/images/courses/books.jpg
new file mode 100644 (file)
index 0000000..594e3e6
Binary files /dev/null and b/images/courses/books.jpg differ
diff --git a/images/courses/botany.jpg b/images/courses/botany.jpg
new file mode 100644 (file)
index 0000000..5118b9f
Binary files /dev/null and b/images/courses/botany.jpg differ
diff --git a/images/courses/brain2.jpg b/images/courses/brain2.jpg
new file mode 100644 (file)
index 0000000..6effd62
Binary files /dev/null and b/images/courses/brain2.jpg differ
diff --git a/images/courses/business.jpg b/images/courses/business.jpg
new file mode 100644 (file)
index 0000000..94c3552
Binary files /dev/null and b/images/courses/business.jpg differ
diff --git a/images/courses/business_service.jpg b/images/courses/business_service.jpg
new file mode 100644 (file)
index 0000000..d31d35b
Binary files /dev/null and b/images/courses/business_service.jpg differ
diff --git a/images/courses/caduceus.jpg b/images/courses/caduceus.jpg
new file mode 100644 (file)
index 0000000..5f54574
Binary files /dev/null and b/images/courses/caduceus.jpg differ
diff --git a/images/courses/car_wireframe.jpg b/images/courses/car_wireframe.jpg
new file mode 100644 (file)
index 0000000..c92954f
Binary files /dev/null and b/images/courses/car_wireframe.jpg differ
diff --git a/images/courses/cell-anatomy.jpg b/images/courses/cell-anatomy.jpg
new file mode 100644 (file)
index 0000000..e009909
Binary files /dev/null and b/images/courses/cell-anatomy.jpg differ
diff --git a/images/courses/chemistry.jpg b/images/courses/chemistry.jpg
new file mode 100644 (file)
index 0000000..7451eb3
Binary files /dev/null and b/images/courses/chemistry.jpg differ
diff --git a/images/courses/columbus.jpg b/images/courses/columbus.jpg
new file mode 100644 (file)
index 0000000..14fdc85
Binary files /dev/null and b/images/courses/columbus.jpg differ
diff --git a/images/courses/disabled_sign.gif b/images/courses/disabled_sign.gif
new file mode 100644 (file)
index 0000000..7d7e7e0
Binary files /dev/null and b/images/courses/disabled_sign.gif differ
diff --git a/images/courses/drafting.jpg b/images/courses/drafting.jpg
new file mode 100644 (file)
index 0000000..f85557a
Binary files /dev/null and b/images/courses/drafting.jpg differ
diff --git a/images/courses/engine.jpg b/images/courses/engine.jpg
new file mode 100644 (file)
index 0000000..e3f34c2
Binary files /dev/null and b/images/courses/engine.jpg differ
diff --git a/images/courses/feather-pen.jpg b/images/courses/feather-pen.jpg
new file mode 100644 (file)
index 0000000..b333a6d
Binary files /dev/null and b/images/courses/feather-pen.jpg differ
diff --git a/images/courses/fire_helmut.jpg b/images/courses/fire_helmut.jpg
new file mode 100644 (file)
index 0000000..131e2e6
Binary files /dev/null and b/images/courses/fire_helmut.jpg differ
diff --git a/images/courses/fractal.jpg b/images/courses/fractal.jpg
new file mode 100644 (file)
index 0000000..17ad0f2
Binary files /dev/null and b/images/courses/fractal.jpg differ
diff --git a/images/courses/head_wireframe.jpg b/images/courses/head_wireframe.jpg
new file mode 100644 (file)
index 0000000..d994e2b
Binary files /dev/null and b/images/courses/head_wireframe.jpg differ
diff --git a/images/courses/helix.jpg b/images/courses/helix.jpg
new file mode 100644 (file)
index 0000000..e5d661a
Binary files /dev/null and b/images/courses/helix.jpg differ
diff --git a/images/courses/helmet.jpg b/images/courses/helmet.jpg
new file mode 100644 (file)
index 0000000..054241f
Binary files /dev/null and b/images/courses/helmet.jpg differ
diff --git a/images/courses/light-bulb.jpg b/images/courses/light-bulb.jpg
new file mode 100644 (file)
index 0000000..34424b3
Binary files /dev/null and b/images/courses/light-bulb.jpg differ
diff --git a/images/courses/map.jpg b/images/courses/map.jpg
new file mode 100644 (file)
index 0000000..45761df
Binary files /dev/null and b/images/courses/map.jpg differ
diff --git a/images/courses/microchip.jpg b/images/courses/microchip.jpg
new file mode 100644 (file)
index 0000000..3833b8b
Binary files /dev/null and b/images/courses/microchip.jpg differ
diff --git a/images/courses/microscope.jpg b/images/courses/microscope.jpg
new file mode 100644 (file)
index 0000000..225466e
Binary files /dev/null and b/images/courses/microscope.jpg differ
diff --git a/images/courses/molecule.jpg b/images/courses/molecule.jpg
new file mode 100644 (file)
index 0000000..85db73d
Binary files /dev/null and b/images/courses/molecule.jpg differ
diff --git a/images/courses/nav_wheel.jpg b/images/courses/nav_wheel.jpg
new file mode 100644 (file)
index 0000000..a8ff953
Binary files /dev/null and b/images/courses/nav_wheel.jpg differ
diff --git a/images/courses/normal_surfaces.jpg b/images/courses/normal_surfaces.jpg
new file mode 100644 (file)
index 0000000..e0137bf
Binary files /dev/null and b/images/courses/normal_surfaces.jpg differ
diff --git a/images/courses/pedal.jpg b/images/courses/pedal.jpg
new file mode 100644 (file)
index 0000000..1baac07
Binary files /dev/null and b/images/courses/pedal.jpg differ
diff --git a/images/courses/pharao.jpg b/images/courses/pharao.jpg
new file mode 100644 (file)
index 0000000..efd8c34
Binary files /dev/null and b/images/courses/pharao.jpg differ
diff --git a/images/courses/pharmacy.jpg b/images/courses/pharmacy.jpg
new file mode 100644 (file)
index 0000000..39154e5
Binary files /dev/null and b/images/courses/pharmacy.jpg differ
diff --git a/images/courses/planet-earth.jpg b/images/courses/planet-earth.jpg
new file mode 100644 (file)
index 0000000..b06b188
Binary files /dev/null and b/images/courses/planet-earth.jpg differ
diff --git a/images/courses/police_hat.jpg b/images/courses/police_hat.jpg
new file mode 100644 (file)
index 0000000..f61197a
Binary files /dev/null and b/images/courses/police_hat.jpg differ
diff --git a/images/courses/recycling.jpg b/images/courses/recycling.jpg
new file mode 100644 (file)
index 0000000..677e812
Binary files /dev/null and b/images/courses/recycling.jpg differ
diff --git a/images/courses/skull.jpg b/images/courses/skull.jpg
new file mode 100644 (file)
index 0000000..9e50666
Binary files /dev/null and b/images/courses/skull.jpg differ
diff --git a/images/courses/skull_wireframe.jpg b/images/courses/skull_wireframe.jpg
new file mode 100644 (file)
index 0000000..d6b5732
Binary files /dev/null and b/images/courses/skull_wireframe.jpg differ
diff --git a/images/courses/sl_logo.gif b/images/courses/sl_logo.gif
new file mode 100644 (file)
index 0000000..c828432
Binary files /dev/null and b/images/courses/sl_logo.gif differ
diff --git a/images/courses/snail.jpg b/images/courses/snail.jpg
new file mode 100644 (file)
index 0000000..7aad5a0
Binary files /dev/null and b/images/courses/snail.jpg differ
diff --git a/images/courses/sphere.jpg b/images/courses/sphere.jpg
new file mode 100644 (file)
index 0000000..7755478
Binary files /dev/null and b/images/courses/sphere.jpg differ
diff --git a/images/courses/sphinx.jpg b/images/courses/sphinx.jpg
new file mode 100644 (file)
index 0000000..031bb44
Binary files /dev/null and b/images/courses/sphinx.jpg differ
diff --git a/images/courses/toolbox.jpg b/images/courses/toolbox.jpg
new file mode 100644 (file)
index 0000000..3a3f881
Binary files /dev/null and b/images/courses/toolbox.jpg differ
diff --git a/images/courses/triangle.jpg b/images/courses/triangle.jpg
new file mode 100644 (file)
index 0000000..e62f7e1
Binary files /dev/null and b/images/courses/triangle.jpg differ
diff --git a/images/courses/two_roads.jpg b/images/courses/two_roads.jpg
new file mode 100644 (file)
index 0000000..1f2d9fb
Binary files /dev/null and b/images/courses/two_roads.jpg differ
diff --git a/images/edit.gif b/images/edit.gif
new file mode 100644 (file)
index 0000000..2fa804d
Binary files /dev/null and b/images/edit.gif differ
diff --git a/images/feedback.gif b/images/feedback.gif
new file mode 100644 (file)
index 0000000..e285230
Binary files /dev/null and b/images/feedback.gif differ
diff --git a/images/file.gif b/images/file.gif
new file mode 100644 (file)
index 0000000..229756d
Binary files /dev/null and b/images/file.gif differ
diff --git a/images/file_types/audio.gif b/images/file_types/audio.gif
new file mode 100644 (file)
index 0000000..ea9ee78
Binary files /dev/null and b/images/file_types/audio.gif differ
diff --git a/images/file_types/binary.gif b/images/file_types/binary.gif
new file mode 100644 (file)
index 0000000..2fca556
Binary files /dev/null and b/images/file_types/binary.gif differ
diff --git a/images/file_types/csv.gif b/images/file_types/csv.gif
new file mode 100644 (file)
index 0000000..dc94f55
Binary files /dev/null and b/images/file_types/csv.gif differ
diff --git a/images/file_types/doc.gif b/images/file_types/doc.gif
new file mode 100644 (file)
index 0000000..438cfd3
Binary files /dev/null and b/images/file_types/doc.gif differ
diff --git a/images/file_types/dvi.gif b/images/file_types/dvi.gif
new file mode 100644 (file)
index 0000000..6c4e71e
Binary files /dev/null and b/images/file_types/dvi.gif differ
diff --git a/images/file_types/generic.gif b/images/file_types/generic.gif
new file mode 100644 (file)
index 0000000..a733f5b
Binary files /dev/null and b/images/file_types/generic.gif differ
diff --git a/images/file_types/image.gif b/images/file_types/image.gif
new file mode 100644 (file)
index 0000000..01f4c07
Binary files /dev/null and b/images/file_types/image.gif differ
diff --git a/images/file_types/mdb.gif b/images/file_types/mdb.gif
new file mode 100644 (file)
index 0000000..766d352
Binary files /dev/null and b/images/file_types/mdb.gif differ
diff --git a/images/file_types/mpp.gif b/images/file_types/mpp.gif
new file mode 100644 (file)
index 0000000..441097d
Binary files /dev/null and b/images/file_types/mpp.gif differ
diff --git a/images/file_types/ood.gif b/images/file_types/ood.gif
new file mode 100644 (file)
index 0000000..ac078af
Binary files /dev/null and b/images/file_types/ood.gif differ
diff --git a/images/file_types/oop.gif b/images/file_types/oop.gif
new file mode 100644 (file)
index 0000000..36c455f
Binary files /dev/null and b/images/file_types/oop.gif differ
diff --git a/images/file_types/oos.gif b/images/file_types/oos.gif
new file mode 100644 (file)
index 0000000..1252de5
Binary files /dev/null and b/images/file_types/oos.gif differ
diff --git a/images/file_types/oot.gif b/images/file_types/oot.gif
new file mode 100644 (file)
index 0000000..853f444
Binary files /dev/null and b/images/file_types/oot.gif differ
diff --git a/images/file_types/pdf.gif b/images/file_types/pdf.gif
new file mode 100644 (file)
index 0000000..ae9b357
Binary files /dev/null and b/images/file_types/pdf.gif differ
diff --git a/images/file_types/ppt.gif b/images/file_types/ppt.gif
new file mode 100644 (file)
index 0000000..3e706b6
Binary files /dev/null and b/images/file_types/ppt.gif differ
diff --git a/images/file_types/ps.gif b/images/file_types/ps.gif
new file mode 100644 (file)
index 0000000..ced7c63
Binary files /dev/null and b/images/file_types/ps.gif differ
diff --git a/images/file_types/psd.gif b/images/file_types/psd.gif
new file mode 100644 (file)
index 0000000..4f69797
Binary files /dev/null and b/images/file_types/psd.gif differ
diff --git a/images/file_types/qt.gif b/images/file_types/qt.gif
new file mode 100644 (file)
index 0000000..87e187c
Binary files /dev/null and b/images/file_types/qt.gif differ
diff --git a/images/file_types/rtf.gif b/images/file_types/rtf.gif
new file mode 100644 (file)
index 0000000..67b9390
Binary files /dev/null and b/images/file_types/rtf.gif differ
diff --git a/images/file_types/sql.gif b/images/file_types/sql.gif
new file mode 100644 (file)
index 0000000..f51298b
Binary files /dev/null and b/images/file_types/sql.gif differ
diff --git a/images/file_types/sql2.gif b/images/file_types/sql2.gif
new file mode 100644 (file)
index 0000000..adc157b
Binary files /dev/null and b/images/file_types/sql2.gif differ
diff --git a/images/file_types/src.gif b/images/file_types/src.gif
new file mode 100644 (file)
index 0000000..bc0aa60
Binary files /dev/null and b/images/file_types/src.gif differ
diff --git a/images/file_types/swf.gif b/images/file_types/swf.gif
new file mode 100644 (file)
index 0000000..71dd920
Binary files /dev/null and b/images/file_types/swf.gif differ
diff --git a/images/file_types/treeview.gif b/images/file_types/treeview.gif
new file mode 100644 (file)
index 0000000..8205750
Binary files /dev/null and b/images/file_types/treeview.gif differ
diff --git a/images/file_types/txt.gif b/images/file_types/txt.gif
new file mode 100644 (file)
index 0000000..3a7f303
Binary files /dev/null and b/images/file_types/txt.gif differ
diff --git a/images/file_types/video.gif b/images/file_types/video.gif
new file mode 100644 (file)
index 0000000..5ddc738
Binary files /dev/null and b/images/file_types/video.gif differ
diff --git a/images/file_types/viewlet.gif b/images/file_types/viewlet.gif
new file mode 100644 (file)
index 0000000..5de854b
Binary files /dev/null and b/images/file_types/viewlet.gif differ
diff --git a/images/file_types/vsd.gif b/images/file_types/vsd.gif
new file mode 100644 (file)
index 0000000..aa77d3c
Binary files /dev/null and b/images/file_types/vsd.gif differ
diff --git a/images/file_types/xls.gif b/images/file_types/xls.gif
new file mode 100644 (file)
index 0000000..8da8f41
Binary files /dev/null and b/images/file_types/xls.gif differ
diff --git a/images/file_types/xml.gif b/images/file_types/xml.gif
new file mode 100644 (file)
index 0000000..e40ecfa
Binary files /dev/null and b/images/file_types/xml.gif differ
diff --git a/images/file_types/zip.gif b/images/file_types/zip.gif
new file mode 100644 (file)
index 0000000..addcd22
Binary files /dev/null and b/images/file_types/zip.gif differ
diff --git a/images/folder.gif b/images/folder.gif
new file mode 100644 (file)
index 0000000..8c7515e
Binary files /dev/null and b/images/folder.gif differ
diff --git a/images/forum/19.gif b/images/forum/19.gif
new file mode 100644 (file)
index 0000000..0a5a37f
Binary files /dev/null and b/images/forum/19.gif differ
diff --git a/images/forum/27.gif b/images/forum/27.gif
new file mode 100644 (file)
index 0000000..6292ecf
Binary files /dev/null and b/images/forum/27.gif differ
diff --git a/images/forum/3.gif b/images/forum/3.gif
new file mode 100644 (file)
index 0000000..fe5e522
Binary files /dev/null and b/images/forum/3.gif differ
diff --git a/images/forum/30.gif b/images/forum/30.gif
new file mode 100644 (file)
index 0000000..1006369
Binary files /dev/null and b/images/forum/30.gif differ
diff --git a/images/forum/51.gif b/images/forum/51.gif
new file mode 100644 (file)
index 0000000..87bbccc
Binary files /dev/null and b/images/forum/51.gif differ
diff --git a/images/forum/52.gif b/images/forum/52.gif
new file mode 100644 (file)
index 0000000..a7a36da
Binary files /dev/null and b/images/forum/52.gif differ
diff --git a/images/forum/54.gif b/images/forum/54.gif
new file mode 100644 (file)
index 0000000..7204cee
Binary files /dev/null and b/images/forum/54.gif differ
diff --git a/images/forum/55.gif b/images/forum/55.gif
new file mode 100644 (file)
index 0000000..6215fbe
Binary files /dev/null and b/images/forum/55.gif differ
diff --git a/images/forum/56.gif b/images/forum/56.gif
new file mode 100644 (file)
index 0000000..4a943ee
Binary files /dev/null and b/images/forum/56.gif differ
diff --git a/images/forum/57.gif b/images/forum/57.gif
new file mode 100644 (file)
index 0000000..41df3de
Binary files /dev/null and b/images/forum/57.gif differ
diff --git a/images/forum/58.gif b/images/forum/58.gif
new file mode 100644 (file)
index 0000000..e79c9d7
Binary files /dev/null and b/images/forum/58.gif differ
diff --git a/images/forum/frown.gif b/images/forum/frown.gif
new file mode 100644 (file)
index 0000000..b99883b
Binary files /dev/null and b/images/forum/frown.gif differ
diff --git a/images/forum/happy.gif b/images/forum/happy.gif
new file mode 100644 (file)
index 0000000..fc136ce
Binary files /dev/null and b/images/forum/happy.gif differ
diff --git a/images/forum/index.html b/images/forum/index.html
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/images/forum/move.gif b/images/forum/move.gif
new file mode 100644 (file)
index 0000000..d824773
Binary files /dev/null and b/images/forum/move.gif differ
diff --git a/images/forum/ohwell.gif b/images/forum/ohwell.gif
new file mode 100644 (file)
index 0000000..82d6ec1
Binary files /dev/null and b/images/forum/ohwell.gif differ
diff --git a/images/forum/smile.gif b/images/forum/smile.gif
new file mode 100644 (file)
index 0000000..a2f5936
Binary files /dev/null and b/images/forum/smile.gif differ
diff --git a/images/forum/sticky.gif b/images/forum/sticky.gif
new file mode 100644 (file)
index 0000000..2f6c5f6
Binary files /dev/null and b/images/forum/sticky.gif differ
diff --git a/images/forum/tongue.gif b/images/forum/tongue.gif
new file mode 100644 (file)
index 0000000..569d95c
Binary files /dev/null and b/images/forum/tongue.gif differ
diff --git a/images/forum/topic_stick.gif b/images/forum/topic_stick.gif
new file mode 100644 (file)
index 0000000..e6d6bf6
Binary files /dev/null and b/images/forum/topic_stick.gif differ
diff --git a/images/forum/wink.gif b/images/forum/wink.gif
new file mode 100644 (file)
index 0000000..a86e6db
Binary files /dev/null and b/images/forum/wink.gif differ
diff --git a/images/glossary.gif b/images/glossary.gif
new file mode 100644 (file)
index 0000000..957e3c2
Binary files /dev/null and b/images/glossary.gif differ
diff --git a/images/glossary_small.gif b/images/glossary_small.gif
new file mode 100644 (file)
index 0000000..368df1d
Binary files /dev/null and b/images/glossary_small.gif differ
diff --git a/images/graph.gif b/images/graph.gif
new file mode 100644 (file)
index 0000000..b601b14
Binary files /dev/null and b/images/graph.gif differ
diff --git a/images/grey.gif b/images/grey.gif
new file mode 100644 (file)
index 0000000..abca14c
Binary files /dev/null and b/images/grey.gif differ
diff --git a/images/help3.gif b/images/help3.gif
new file mode 100644 (file)
index 0000000..e802ee6
Binary files /dev/null and b/images/help3.gif differ
diff --git a/images/help4.gif b/images/help4.gif
new file mode 100644 (file)
index 0000000..94d8d7f
Binary files /dev/null and b/images/help4.gif differ
diff --git a/images/home-acollab.gif b/images/home-acollab.gif
new file mode 100644 (file)
index 0000000..cac789b
Binary files /dev/null and b/images/home-acollab.gif differ
diff --git a/images/home-blogs.gif b/images/home-blogs.gif
new file mode 100644 (file)
index 0000000..a42468d
Binary files /dev/null and b/images/home-blogs.gif differ
diff --git a/images/home-chat.gif b/images/home-chat.gif
new file mode 100644 (file)
index 0000000..3d90f7c
Binary files /dev/null and b/images/home-chat.gif differ
diff --git a/images/home-directory.gif b/images/home-directory.gif
new file mode 100644 (file)
index 0000000..09edd7f
Binary files /dev/null and b/images/home-directory.gif differ
diff --git a/images/home-export_content.gif b/images/home-export_content.gif
new file mode 100644 (file)
index 0000000..7b9a546
Binary files /dev/null and b/images/home-export_content.gif differ
diff --git a/images/home-file_storage.gif b/images/home-file_storage.gif
new file mode 100644 (file)
index 0000000..8269127
Binary files /dev/null and b/images/home-file_storage.gif differ
diff --git a/images/home-forums.gif b/images/home-forums.gif
new file mode 100644 (file)
index 0000000..1ed32ce
Binary files /dev/null and b/images/home-forums.gif differ
diff --git a/images/home-glossary.gif b/images/home-glossary.gif
new file mode 100644 (file)
index 0000000..41e8646
Binary files /dev/null and b/images/home-glossary.gif differ
diff --git a/images/home-links.gif b/images/home-links.gif
new file mode 100644 (file)
index 0000000..2e8639a
Binary files /dev/null and b/images/home-links.gif differ
diff --git a/images/home-polls.gif b/images/home-polls.gif
new file mode 100644 (file)
index 0000000..6f3fb36
Binary files /dev/null and b/images/home-polls.gif differ
diff --git a/images/home-reading_list.gif b/images/home-reading_list.gif
new file mode 100644 (file)
index 0000000..b697c64
Binary files /dev/null and b/images/home-reading_list.gif differ
diff --git a/images/home-site_map.gif b/images/home-site_map.gif
new file mode 100644 (file)
index 0000000..33c150f
Binary files /dev/null and b/images/home-site_map.gif differ
diff --git a/images/home-tests.gif b/images/home-tests.gif
new file mode 100644 (file)
index 0000000..c79d90c
Binary files /dev/null and b/images/home-tests.gif differ
diff --git a/images/home-tile_search.gif b/images/home-tile_search.gif
new file mode 100644 (file)
index 0000000..5d6b89e
Binary files /dev/null and b/images/home-tile_search.gif differ
diff --git a/images/home-tracker.gif b/images/home-tracker.gif
new file mode 100644 (file)
index 0000000..0bfba80
Binary files /dev/null and b/images/home-tracker.gif differ
diff --git a/images/icon-zip.gif b/images/icon-zip.gif
new file mode 100644 (file)
index 0000000..c29470c
Binary files /dev/null and b/images/icon-zip.gif differ
diff --git a/images/icon_delete.gif b/images/icon_delete.gif
new file mode 100644 (file)
index 0000000..1153ba5
Binary files /dev/null and b/images/icon_delete.gif differ
diff --git a/images/icon_minipost.gif b/images/icon_minipost.gif
new file mode 100644 (file)
index 0000000..d172abb
Binary files /dev/null and b/images/icon_minipost.gif differ
diff --git a/images/index.html b/images/index.html
new file mode 100644 (file)
index 0000000..945c9b4
--- /dev/null
@@ -0,0 +1 @@
+.
\ No newline at end of file
diff --git a/images/lock.gif b/images/lock.gif
new file mode 100644 (file)
index 0000000..af1eda7
Binary files /dev/null and b/images/lock.gif differ
diff --git a/images/logo.gif b/images/logo.gif
new file mode 100644 (file)
index 0000000..e622389
Binary files /dev/null and b/images/logo.gif differ
diff --git a/images/move-down.gif b/images/move-down.gif
new file mode 100644 (file)
index 0000000..1e9beb8
Binary files /dev/null and b/images/move-down.gif differ
diff --git a/images/move-up.gif b/images/move-up.gif
new file mode 100644 (file)
index 0000000..86e1aed
Binary files /dev/null and b/images/move-up.gif differ
diff --git a/images/new.gif b/images/new.gif
new file mode 100644 (file)
index 0000000..09eac83
Binary files /dev/null and b/images/new.gif differ
diff --git a/images/pen.gif b/images/pen.gif
new file mode 100644 (file)
index 0000000..bff8964
Binary files /dev/null and b/images/pen.gif differ
diff --git a/images/pen2.gif b/images/pen2.gif
new file mode 100644 (file)
index 0000000..1a15c9b
Binary files /dev/null and b/images/pen2.gif differ
diff --git a/images/pen3.gif b/images/pen3.gif
new file mode 100644 (file)
index 0000000..adf2211
Binary files /dev/null and b/images/pen3.gif differ
diff --git a/images/pub_default.jpg b/images/pub_default.jpg
new file mode 100644 (file)
index 0000000..4ccdd63
Binary files /dev/null and b/images/pub_default.jpg differ
diff --git a/images/question.gif b/images/question.gif
new file mode 100644 (file)
index 0000000..02fd449
Binary files /dev/null and b/images/question.gif differ
diff --git a/images/red.gif b/images/red.gif
new file mode 100644 (file)
index 0000000..bf30e6e
Binary files /dev/null and b/images/red.gif differ
diff --git a/images/rtl_tree/index.html b/images/rtl_tree/index.html
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/images/rtl_tree/tree_collapse.gif b/images/rtl_tree/tree_collapse.gif
new file mode 100644 (file)
index 0000000..1f05065
Binary files /dev/null and b/images/rtl_tree/tree_collapse.gif differ
diff --git a/images/rtl_tree/tree_end.gif b/images/rtl_tree/tree_end.gif
new file mode 100644 (file)
index 0000000..b33f857
Binary files /dev/null and b/images/rtl_tree/tree_end.gif differ
diff --git a/images/rtl_tree/tree_expand.gif b/images/rtl_tree/tree_expand.gif
new file mode 100644 (file)
index 0000000..b25feba
Binary files /dev/null and b/images/rtl_tree/tree_expand.gif differ
diff --git a/images/rtl_tree/tree_horizontal.gif b/images/rtl_tree/tree_horizontal.gif
new file mode 100644 (file)
index 0000000..c654fb6
Binary files /dev/null and b/images/rtl_tree/tree_horizontal.gif differ
diff --git a/images/rtl_tree/tree_split.gif b/images/rtl_tree/tree_split.gif
new file mode 100644 (file)
index 0000000..cbf5395
Binary files /dev/null and b/images/rtl_tree/tree_split.gif differ
diff --git a/images/rtl_tree/tree_vertline.gif b/images/rtl_tree/tree_vertline.gif
new file mode 100644 (file)
index 0000000..5420936
Binary files /dev/null and b/images/rtl_tree/tree_vertline.gif differ
diff --git a/images/search.gif b/images/search.gif
new file mode 100644 (file)
index 0000000..bbca743
Binary files /dev/null and b/images/search.gif differ
diff --git a/images/star.gif b/images/star.gif
new file mode 100644 (file)
index 0000000..e53b7d5
Binary files /dev/null and b/images/star.gif differ
diff --git a/images/toc.gif b/images/toc.gif
new file mode 100644 (file)
index 0000000..fe3627a
Binary files /dev/null and b/images/toc.gif differ
diff --git a/images/topic_lock.gif b/images/topic_lock.gif
new file mode 100644 (file)
index 0000000..fe32fea
Binary files /dev/null and b/images/topic_lock.gif differ
diff --git a/images/transfer.gif b/images/transfer.gif
new file mode 100644 (file)
index 0000000..3131207
Binary files /dev/null and b/images/transfer.gif differ
diff --git a/images/tree/index.html b/images/tree/index.html
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/images/tree/tree_collapse.gif b/images/tree/tree_collapse.gif
new file mode 100644 (file)
index 0000000..1f05065
Binary files /dev/null and b/images/tree/tree_collapse.gif differ
diff --git a/images/tree/tree_disabled.gif b/images/tree/tree_disabled.gif
new file mode 100644 (file)
index 0000000..7893680
Binary files /dev/null and b/images/tree/tree_disabled.gif differ
diff --git a/images/tree/tree_end.gif b/images/tree/tree_end.gif
new file mode 100644 (file)
index 0000000..1eead99
Binary files /dev/null and b/images/tree/tree_end.gif differ
diff --git a/images/tree/tree_expand.gif b/images/tree/tree_expand.gif
new file mode 100644 (file)
index 0000000..b25feba
Binary files /dev/null and b/images/tree/tree_expand.gif differ
diff --git a/images/tree/tree_horizontal.gif b/images/tree/tree_horizontal.gif
new file mode 100644 (file)
index 0000000..c654fb6
Binary files /dev/null and b/images/tree/tree_horizontal.gif differ
diff --git a/images/tree/tree_space.gif b/images/tree/tree_space.gif
new file mode 100644 (file)
index 0000000..33c60e5
Binary files /dev/null and b/images/tree/tree_space.gif differ
diff --git a/images/tree/tree_split.gif b/images/tree/tree_split.gif
new file mode 100644 (file)
index 0000000..e89ce80
Binary files /dev/null and b/images/tree/tree_split.gif differ
diff --git a/images/tree/tree_vertline.gif b/images/tree/tree_vertline.gif
new file mode 100644 (file)
index 0000000..5420936
Binary files /dev/null and b/images/tree/tree_vertline.gif differ
diff --git a/images/unlock.gif b/images/unlock.gif
new file mode 100644 (file)
index 0000000..87823b7
Binary files /dev/null and b/images/unlock.gif differ
diff --git a/images/x.gif b/images/x.gif
new file mode 100644 (file)
index 0000000..2a0056f
Binary files /dev/null and b/images/x.gif differ
diff --git a/inbox/export.php b/inbox/export.php
new file mode 100644 (file)
index 0000000..e7e9613
--- /dev/null
@@ -0,0 +1,111 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+$_user_location        = 'public';
+
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+if (!$_SESSION['valid_user']) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->printInfos('INVALID_USER');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+} else if (isset($_POST['export'], $_POST['messages'])) {
+       $inbox_messages = $sent_messages = '';
+
+       $my_display_name = get_display_name($_SESSION['member_id']);
+
+       // inbox messages
+       if ($_POST['messages'] == 1 || $_POST['messages'] == 2) {
+               $sql = "SELECT * FROM ".TABLE_PREFIX."messages WHERE to_member_id=$_SESSION[member_id] ORDER BY date_sent";
+               $result = mysql_query($sql, $db);
+               while ($row = mysql_fetch_assoc($result)) {
+                       $msg  = _AT('from')   .': ' . get_display_name($row['from_member_id']) . "\r\n";
+                       $msg .= _AT('to')     .': ' . $my_display_name . "\r\n";
+                       $msg .= _AT('subject').': ' . $row['subject'] . "\r\n";
+                       $msg .= _AT('date')   .': ' . $row['date_sent'] . "\r\n";
+                       $msg .= _AT('body')   .': ' . $row['body'] . "\r\n";
+                       $msg .= "\r\n=============================================\r\n\r\n";
+
+                       $inbox_messages .= $msg;
+               }
+       }
+
+       // sent messages
+       if ($_POST['messages'] == 1 || $_POST['messages'] == 3) {
+               $sql = "SELECT * FROM ".TABLE_PREFIX."messages_sent WHERE from_member_id=$_SESSION[member_id] ORDER BY date_sent";
+               $result = mysql_query($sql, $db);
+               while ($row = mysql_fetch_assoc($result)) {
+                       $msg  = _AT('from')   .': ' . $my_display_name  . "\r\n";
+                       $msg .= _AT('to')     .': ' . get_display_name($row['from_member_id']). "\r\n";
+                       $msg .= _AT('subject').': ' . $row['subject'] . "\r\n";
+                       $msg .= _AT('date')   .': ' . $row['date_sent'] . "\r\n";
+                       $msg .= _AT('body')   .': ' . $row['body'] . "\r\n";
+                       $msg .= "\r\n=============================================\r\n\r\n";
+
+                       $sent_messages .= $msg;
+               }
+       }
+
+       if ($inbox_messages && $sent_messages) {
+               // add the two to a zip file
+               require(AT_INCLUDE_PATH.'classes/zipfile.class.php'); // for zipfile
+               $zipfile = new zipfile();
+               $zipfile->add_file($inbox_messages, _AT('inbox').'.txt');
+               $zipfile->add_file($sent_messages, _AT('sent_messages').'.txt');
+               $zipfile->close();
+               $zipfile->send_file(_AT('inbox').'-'.date('Ymd'));
+               exit;
+       } else if ($inbox_messages) {
+               header('Content-Type: text/plain');
+               header('Content-Disposition: attachment; filename="'._AT('inbox').'-'.date('Ymd').'.txt"');
+               header('Expires: 0');
+               header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+               header('Pragma: public');
+               header('Content-Length: '.strlen($inbox_messages));
+
+               echo $inbox_messages;
+               exit;
+       } else if ($sent_messages) {
+               header('Content-Type: text/plain');
+               header('Content-Disposition: attachment; filename="'._AT('sent_messages').'-'.date('Ymd').'.txt"');
+               header('Expires: 0');
+               header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+               header('Pragma: public');
+               header('Content-Length: '.strlen($sent_messages));
+
+               echo $sent_messages;
+               exit;
+       } // else. nothing to export
+
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>"/>
+<div class="input-form">
+       <div class="row">
+               <?php echo _AT('export'); ?><br />
+               <input type="radio" name="messages" value="1" id="m1" checked="checked"><label for="m1"><?php echo _AT('all'); ?></label><br />
+               <input type="radio" name="messages" value="2" id="m2"><label for="m2"><?php echo _AT('inbox'); ?></label><br />
+               <input type="radio" name="messages" value="3" id="m3"><label for="m3"><?php echo _AT('sent_messages'); ?></label><br />
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="export" value="<?php echo _AT('export'); ?>"/>
+       </div>
+</div>
+</form>
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/inbox/index.php b/inbox/index.php
new file mode 100644 (file)
index 0000000..ac6a760
--- /dev/null
@@ -0,0 +1,181 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+$_user_location        = 'public';
+
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+if (!$_SESSION['valid_user']) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->printInfos('INVALID_USER');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+$_GET['view'] = intval($_GET['view']);
+
+if ($_GET['view']) {
+       $result = mysql_query("UPDATE ".TABLE_PREFIX."messages SET new=0, date_sent=date_sent WHERE to_member_id=$_SESSION[member_id] AND message_id=$_GET[view]",$db);
+}
+
+if (isset($_GET['delete'])) {
+       $_GET['delete'] = intval($_GET['delete']);
+
+       if($result = mysql_query("DELETE FROM ".TABLE_PREFIX."messages WHERE to_member_id=$_SESSION[member_id] AND message_id=$_GET[delete]",$db)){
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       }
+
+       header('Location: index.php');
+       exit;
+} else if (isset($_POST['submit_yes'], $_POST['ids'])) {
+       $ids = $addslashes($_POST['ids']);
+
+       $sql = "DELETE FROM ".TABLE_PREFIX."messages WHERE to_member_id=$_SESSION[member_id] AND message_id IN ($ids)";
+       mysql_query($sql, $db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+
+       header('Location: index.php');
+       exit;
+} else if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+
+       header('Location: index.php');
+       exit;
+} else if (isset($_POST['delete']) && !isset($_POST['id'])) {
+       $msg->addError('NO_ITEM_SELECTED');
+       header('Location: index.php');
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if (isset($_GET['view']) && $_GET['view']) {
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."messages WHERE message_id=$_GET[view] AND to_member_id=$_SESSION[member_id]";
+       $result = mysql_query($sql, $db);
+
+       if ($row = mysql_fetch_assoc($result)) {
+?>
+       <ul id="inbox-msg">
+       <li>
+               <div class="forum-post-author">
+                       <a href="profile.php?id=<?php echo $row['from_member_id']; ?>" class="title"><?php echo get_display_name($row['from_member_id']); ?></a><br />
+                       <?php print_profile_img($row['from_member_id']); ?>
+               </div>
+
+               <div class="forum-post-content">
+                       <h3><?php echo AT_Print(htmlspecialchars($row['subject'], ENT_COMPAT, "UTF-8"), 'messages.subject'); ?></h3>
+                       <div>
+                               <div class="forum-post-ctrl">
+                                       <a href="inbox/send_message.php?reply=<?php echo $_GET['view']; ?>"><?php echo _AT('reply'); ?></a> | <a href="<?php echo $_SERVER['PHP_SELF']; ?>?delete=<?php echo $_GET['view']; ?>"><?php echo _AT('delete'); ?></a>
+                               </div>
+                               <p class="date"><?php echo AT_date(_AT('forum_date_format'), $row['date_sent'], AT_DATE_MYSQL_DATETIME); ?></p>
+                       </div>
+
+                       <div class="body">
+                               <p><?php echo AT_print(htmlspecialchars($row['body'], ENT_COMPAT, "UTF-8"), 'messages.body'); ?></p>
+                       </div>
+               </div>
+
+       </li>
+       </ul><br /><br />
+       <?php
+       }
+} else if (isset($_POST['delete'], $_POST['id'])) {
+       $hidden_vars['ids'] = implode(',', $_POST['id']);
+
+       $msg->addConfirm('DELETE_MSGS', $hidden_vars);
+       $msg->printConfirm();
+}
+
+$sql   = "SELECT * FROM ".TABLE_PREFIX."messages WHERE to_member_id=$_SESSION[member_id] ORDER BY date_sent DESC";
+$result = mysql_query($sql,$db);
+?>
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<table class="data static" summary="" rules="rows" width="55%">
+<thead>
+<tr>
+       <th scope="col">&nbsp;</th>
+       <th scope="col">&nbsp;</th>
+       <th scope="col" ><?php echo _AT('from');   ?></th>
+       <th scope="col" ><?php echo _AT('subject');?></th>
+       <th scope="col" ><?php echo _AT('date');   ?></th>
+</tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="5"><input type="submit" name="delete" value="<?php echo _AT('delete'); ?>"/></td>
+</tr>
+</tfoot>
+<tbody>
+<?php if ($row = mysql_fetch_assoc($result)): ?>
+       <?php do { ?>
+               <?php if ($row['message_id'] == $_GET['view']): ?>
+                       <tr class="selected">
+               <?php else: ?>
+                       <tr>
+               <?php endif; ?>
+               <td><input type="checkbox" name="id[]" value="<?php echo $row['message_id']; ?>" id="m<?php echo $row['message_id']; ?>" <?php if (isset($_POST['id']) && in_array($row['message_id'], $_POST['id'])) { echo 'checked="checked"'; } ?> title="<?php echo _AT('delete').': '.AT_print($row['subject'], 'messages.subject');?>"/></td>
+               <td valign="middle">
+               <?php
+               if ($row['new'] == 1)   {
+                       echo _AT('new');
+               } else if ($row['replied'] == 1) {
+                       echo _AT('replied');
+               }
+               echo '</td>';
+
+               $name = get_display_name($row['from_member_id']);
+
+               echo '<td align="left" valign="middle">';
+
+               if ($_GET['view'] != $row['message_id']) {
+                       echo $name;
+               } else {
+                       echo '<strong>'.$name.'</strong>';
+               }
+               echo '</td>';
+
+               echo '<td>';
+               if ($_GET['view'] != $row['message_id']) {
+                       echo '<a href="'.$_SERVER['PHP_SELF'].'?view='.$row['message_id'].'">'.AT_print($row['subject'], 'messages.subject').'</a>';
+               } else {
+                       echo '<strong>'.AT_print($row['subject'], 'messages.subject').'</strong>';
+               }
+               echo '</td>';
+       
+               echo '<td valign="middle" align="left" nowrap="nowrap">';
+               echo AT_date(_AT('inbox_date_format'),  $row['date_sent'], AT_DATE_MYSQL_DATETIME);
+               echo '</td>';
+               echo '</tr>';
+       } while ($row = mysql_fetch_assoc($result)); ?>
+<?php else: ?>
+       <tr>
+               <td colspan="5"><?php echo _AT('none_found'); ?></td>
+       </tr>
+<?php endif; ?>
+</tbody>
+</table>
+</form>
+
+<?php
+// since Inbox isn't a module, it can't have a cron job.
+// so, we delete the expires sent messages with P =  1/7.
+if (!rand(0, 6)) {
+       $sql = "DELETE FROM ".TABLE_PREFIX."messages_sent WHERE from_member_id=$_SESSION[member_id] AND TO_DAYS(date_sent) < (TO_DAYS(NOW()) - {$_config['sent_msgs_ttl']}) LIMIT 100";
+       mysql_query($sql, $db);
+}
+?>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/inbox/send_message.php b/inbox/send_message.php
new file mode 100644 (file)
index 0000000..413637c
--- /dev/null
@@ -0,0 +1,245 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+$_user_location        = 'public';
+
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+
+if (!$_SESSION['valid_user']) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+
+       $msg->printInfos('MSG_SEND_LOGIN');
+       
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php');
+       exit;
+} else if (($_POST['submit']) || ($_POST['submit_delete'])) {
+       $missing_fields = array();
+
+       if (($_POST['to'] == '') || ($_POST['to'] == 0)) {
+               $missing_fields[] = _AT('to');
+       }
+       if ($_POST['subject'] == '') {
+               $missing_fields[] = _AT('subject');
+       }
+       if ($_POST['message'] == '') {
+               $missing_fields[] = _AT('body');
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['subject'] = $addslashes($_POST['subject']);
+               $_POST['message'] = $addslashes($_POST['message']);
+               $_POST['to'] = intval($_POST['to']);
+
+               $sql = "INSERT INTO ".TABLE_PREFIX."messages VALUES (NULL, $_SESSION[course_id], $_SESSION[member_id], $_POST[to], NOW(), 1, 0, '$_POST[subject]', '$_POST[message]')";
+               $result = mysql_query($sql,$db);
+
+               // sent message box:
+               $sql = "INSERT INTO ".TABLE_PREFIX."messages_sent VALUES (NULL, $_SESSION[course_id], $_SESSION[member_id], $_POST[to], NOW(), '$_POST[subject]', '$_POST[message]')";
+               $result = mysql_query($sql,$db);
+
+               //send email notification if recipient has message notification enabled
+               $sql_notify = "SELECT first_name, last_name, email, inbox_notify FROM ".TABLE_PREFIX."members WHERE member_id=$_POST[to]";
+               $result_notify = mysql_query($sql_notify, $db);
+               $row_notify = mysql_fetch_assoc($result_notify);
+
+               if ($row_notify['inbox_notify'] == 1) {
+                       require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+
+                       $body = _AT('notification_new_inbox', get_display_name($_SESSION['member_id']), $_base_href.'bounce.php?course='.$_SESSION['course_id']);
+                       $sender = get_display_name($_SESSION['member_id']);
+                       $mail = new ATutorMailer;
+                       $mail->AddAddress($row_notify['email'], $sender);
+                       $mail->FromName = $_config['site_name'];
+                       $mail->From     = $_config['contact_email'];
+                       $mail->Subject  = _AT('message_notification');
+                       $mail->Body     = $body;
+
+                       if(!$mail->Send()) {
+                               $msg->addError('SENDING_ERROR');
+                       }
+                       unset($mail);
+               }
+
+               if ($_POST['submit_delete']) {
+                       $result = mysql_query("DELETE FROM ".TABLE_PREFIX."messages WHERE message_id=$_POST[replied] AND to_member_id=$_SESSION[member_id]",$db);
+               } else if ($_POST['replied'] != '') {
+                       $result = mysql_query("UPDATE ".TABLE_PREFIX."messages SET replied=1, date_sent=date_sent WHERE message_id=$_POST[replied]",$db);
+               }
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+
+               header('Location: index.php');
+               exit;
+       }
+}
+
+$sql   = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."course_enrollment WHERE member_id=$_SESSION[member_id] AND (approved='y' OR approved='a')";
+$result = mysql_query($sql, $db);
+$row   = mysql_fetch_array($result);
+
+if ($row['cnt'] == 0) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+
+       $msg->printErrors('SEND_ENROL');
+
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+
+if (($_GET['reply'] == '') && $_GET['id']) {
+       $onload = 'document.form.subject.focus();';
+} else if ($_GET['reply'] == '') {
+       $onload = 'document.form.to.focus();';
+} else {
+       $onload = 'document.form.body.focus();';
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$_GET['reply'] = intval($_GET['reply']);
+$_GET['forward'] = intval($_GET['forward']);
+
+if ($_GET['reply']) {
+       // get the member_id of the sender
+       $result = mysql_query("SELECT from_member_id,subject,body FROM ".TABLE_PREFIX."messages WHERE message_id=$_GET[reply] AND to_member_id=$_SESSION[member_id]",$db);
+       if ($myinfo = mysql_fetch_assoc($result)) {
+               $reply_to       = $myinfo['from_member_id'];
+               $subject        = $myinfo['subject'];
+               $body           = $myinfo['body'];
+       }
+} else if ($_GET['forward']) {
+       // get the member_id of the sender
+       $result = mysql_query("SELECT subject, body FROM ".TABLE_PREFIX."messages_sent WHERE message_id=$_GET[forward] AND from_member_id=$_SESSION[member_id]",$db);
+       if ($myinfo = mysql_fetch_assoc($result)) {
+               $reply_to       = 0;
+               $subject        = $myinfo['subject'];
+               $body           = $myinfo['body'];
+       }
+}
+if (isset($_GET['id'])) {
+       $reply_to = intval($_GET['id']);
+}
+
+/* check to make sure we're in the same course */
+if ($reply_to) {
+       $sql    = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."course_enrollment E1, ".TABLE_PREFIX."course_enrollment E2 WHERE E1.member_id=$_SESSION[member_id] AND E2.member_id=$reply_to AND E1.course_id=E2.course_id AND (E1.approved='y' OR E1.approved='a') AND (E2.approved='y' OR E2.approved='a')";
+       $result = mysql_query($sql, $db);
+       $row    = mysql_fetch_assoc($result);
+
+       if ($row['cnt'] == 0) {
+               $msg->printErrors('SEND_MEMBERS');
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+
+}
+
+?>
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">
+<input type="hidden" name="replied" value="<?php echo $_GET['reply']; ?>" />
+
+<div class="input-form">
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="to"><?php echo _AT('to'); ?></label><br />
+               <?php
+                       if (!$reply_to) {
+                               $sql    = "SELECT DISTINCT M.first_name, M.second_name, M.last_name, M.login, M.member_id FROM ".TABLE_PREFIX."members M, ".TABLE_PREFIX."course_enrollment E1, ".TABLE_PREFIX."course_enrollment E2 WHERE E2.member_id=$_SESSION[member_id] AND E2.course_id=E1.course_id AND M.member_id=E1.member_id AND (E1.approved='y' OR E1.approved='a') AND (E2.approved='y' OR E2.approved='a') ORDER BY M.first_name, M.second_name, M.last_name, M.login";
+
+                               $result = mysql_query($sql, $db);
+                               $row    = mysql_fetch_assoc($result);
+                               echo '<select name="to" size="1" id="to">';
+                               do {
+                                       echo '<option value="'.$row['member_id'].'"';
+                                       if ($reply_to == $row['member_id']){
+                                               echo ' selected="selected"';
+                                       } else if (isset($_POST['to']) && $_POST['to'] == $row['member_id']) {
+                                               echo ' selected="selected"';
+                                       }
+                                       echo '>';
+                                       echo get_display_name($row['member_id']);
+                                       echo '</option>';
+                               } while ($row = mysql_fetch_assoc($result));
+                               echo '</select>';
+                       } else {
+                               echo '<strong>'.get_display_name($reply_to).'</strong>';
+                               echo '<input type="hidden" name="to" value="'.$reply_to.'" />';
+                       } ?>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="subject"><?php echo _AT('subject'); ?></label><br />
+               <input type="text" name="subject" id="subject" value="<?php
+                       if (($subject != '') && ($_POST['subject'] == '')) {
+                               if ($_GET['reply'] && !($substr($subject, 0, 2) == _AT('re'))) {
+                                       $subject = _AT('re').' : '.$subject;
+                               } else if ($_GET['forward'] && !($substr($subject, 0, 2) == _AT('fwd'))) {
+                                       $subject = _AT('fwd').' : '.$subject;
+                               }
+                               echo ContentManager::cleanOutput($subject);
+                       } else {
+                               echo ContentManager::cleanOutput($_POST['subject']);
+                       }
+                       ?>" size="40" maxlength="100" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="body"><?php echo _AT('message'); ?></label><br />
+               <textarea name="message" id="body" rows="15" cols="55"><?php
+                       if ($body != '') {
+                               if ($strlen($body) > 400){
+                                       $body = $substr($body,0,400);
+                                       $pos = $strrpos($body,' ');
+                                       if ($pos===false){
+                                               /* Unicode problem, not all language has spaces in between characters
+                                                * No space found, chop off right on 400.
+                                                */
+                                                $body = $substr($body,0,400);
+                                       } else {
+                                               $body = $substr($body,0,$pos);
+                                       }
+                                       $body .= ' ...';
+                               }
+                               $body  = "\n\n\n"._AT('in_reply_to').":\n".$body;
+                               echo $body;
+                       } else {
+                               echo $_POST['message'];
+                       }
+               ?></textarea>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('send'); ?>" accesskey="s" /><?php
+               if ($reply != '') {
+                       echo '<input type="submit" name="submit_delete" value="'._AT('send_delete').'" accesskey="n" /> ';
+               }
+               ?> <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+</div>
+</form> 
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/inbox/sent_messages.php b/inbox/sent_messages.php
new file mode 100644 (file)
index 0000000..103ce42
--- /dev/null
@@ -0,0 +1,182 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+$_user_location        = 'public';
+
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+if (!$_SESSION['valid_user']) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->printInfos('INVALID_USER');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+$_GET['view'] = intval($_GET['view']);
+
+if ($_GET['delete']) {
+       $_GET['delete'] = intval($_GET['delete']);
+
+       if($result = mysql_query("DELETE FROM ".TABLE_PREFIX."messages_sent WHERE from_member_id=$_SESSION[member_id] AND message_id=$_GET[delete]",$db)){
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       }
+
+       header('Location: '.$_SERVER['PHP_SELF']);
+       exit;
+} else if (isset($_POST['submit_yes'], $_POST['ids'])) {
+       $ids = $addslashes($_POST['ids']);
+
+       $sql = "DELETE FROM ".TABLE_PREFIX."messages_sent WHERE from_member_id=$_SESSION[member_id] AND message_id IN ($ids)";
+       mysql_query($sql, $db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+
+       header('Location: '.$_SERVER['PHP_SELF']);
+       exit;
+} else if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+
+       header('Location: '.$_SERVER['PHP_SELF']);
+       exit;
+} else if (isset($_POST['move'], $_POST['id'])) {
+       $_POST['id'][] = 0; // to make it non-empty
+       $_POST['id'] = implode(',', $_POST['id']);
+       $ids = $addslashes($_POST['id']);
+
+       $sql = "INSERT INTO ".TABLE_PREFIX."messages SELECT 0, course_id, from_member_id, {$_SESSION['member_id']}, date_sent, 0, 0, subject, body FROM ".TABLE_PREFIX."messages_sent WHERE from_member_id=$_SESSION[member_id] AND message_id IN ($ids)";
+       mysql_query($sql, $db);
+
+       $sql = "DELETE FROM ".TABLE_PREFIX."messages_sent WHERE from_member_id=$_SESSION[member_id] AND message_id IN ($ids)";
+       mysql_query($sql, $db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+
+       header('Location: '.$_SERVER['PHP_SELF']);
+       exit;
+} else if ((isset($_POST['delete']) || isset($_POST['move'])) && !isset($_POST['id'])) {
+       $msg->addError('NO_ITEM_SELECTED');
+       header('Location: '.$_SERVER['PHP_SELF']);
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if (isset($_GET['view']) && $_GET['view']) {
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."messages_sent WHERE message_id=$_GET[view] AND from_member_id=$_SESSION[member_id]";
+       $result = mysql_query($sql, $db);
+
+       if ($row = mysql_fetch_assoc($result)) {
+?>
+       <ul id="inbox-msg">
+       <li>
+               <div class="forum-post-author">
+                       <a href="profile.php?id=<?php echo $row['to_member_id']; ?>" class="title"><?php echo get_display_name($row['to_member_id']); ?></a><br />
+                       <?php print_profile_img($row['to_member_id']); ?>
+               </div>
+
+               <div class="forum-post-content">
+                       <h3><?php echo AT_Print(htmlspecialchars($row['subject'], ENT_COMPAT, "UTF-8"), 'messages.subject'); ?></h3>
+                       <div>
+                               <div class="forum-post-ctrl">
+                                       <a href="inbox/send_message.php?forward=<?php echo $_GET['view']; ?>"><?php echo _AT('forward'); ?></a> | <a href="<?php echo $_SERVER['PHP_SELF']; ?>?delete=<?php echo $_GET['view']; ?>"><?php echo _AT('delete'); ?></a>
+                               </div>
+                               <p class="date"><?php echo AT_date(_AT('forum_date_format'), $row['date_sent'], AT_DATE_MYSQL_DATETIME); ?></p>
+                       </div>
+
+                       <div class="body">
+                               <p><?php echo AT_print(htmlspecialchars($row['body'], ENT_COMPAT, "UTF-8"), 'messages.body'); ?></p>
+                       </div>
+                       <div style="clear: both; font-size:0.1em"></div>
+               </div>
+       </div>
+       </li>
+       </ul>
+       <?php
+       }
+} else if (isset($_POST['delete'], $_POST['id'])) {
+       $hidden_vars['ids'] = implode(',', $_POST['id']);
+
+       $msg->addConfirm('DELETE_MSGS', $hidden_vars);
+       $msg->printConfirm();
+}
+
+$msg->printInfos(array('INBOX_SENT_MSGS_TTL', $_config['sent_msgs_ttl']));
+
+$sql   = "SELECT * FROM ".TABLE_PREFIX."messages_sent WHERE from_member_id=$_SESSION[member_id] ORDER BY date_sent DESC";
+$result = mysql_query($sql,$db);
+?>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<table class="data static" summary="" rules="rows">
+<thead>
+<tr>
+       <th scope="col">&nbsp;</th>
+       <th scope="col" ><?php echo _AT('to');   ?></th>
+       <th scope="col" ><?php echo _AT('subject');?></th>
+       <th scope="col" ><?php echo _AT('date');   ?></th>
+</tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="4">
+               <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>"/>
+               <input type="submit" name="move" value="<?php echo _AT('move_to_inbox'); ?>"/>
+       </td>
+</tr>
+</tfoot>
+<tbody>
+<?php if ($row = mysql_fetch_assoc($result)): ?>
+       <?php do { ?>
+               <?php if ($row['message_id'] == $_GET['view']): ?>
+                       <tr class="selected">
+               <?php else: ?>
+                       <tr>
+               <?php endif; ?>
+               <td><input type="checkbox" name="id[]" value="<?php echo $row['message_id']; ?>" id="m<?php echo $row['message_id']; ?>" <?php if (isset($_POST['id']) && in_array($row['message_id'], $_POST['id'])) { echo 'checked="checked"'; } ?> title="<?php echo _AT('delete').': '.AT_print($row['subject'], 'messages.subject');?>"/></td>
+               <?php
+
+               $name = get_display_name($row['to_member_id']);
+
+               echo '<td align="left" valign="middle">';
+
+               if ($_GET['view'] != $row['message_id']) {
+                       echo $name;
+               } else {
+                       echo '<strong>'.$name.'</strong>';
+               }
+               echo '</td>';
+
+               echo '<td>';
+               if ($_GET['view'] != $row['message_id']) {
+                       echo '<a href="'.$_SERVER['PHP_SELF'].'?view='.$row['message_id'].'">'.AT_print($row['subject'], 'messages.subject').'</a>';
+               } else {
+                       echo '<strong>'.AT_print($row['subject'], 'messages.subject').'</strong>';
+               }
+               echo '</td>';
+       
+               echo '<td valign="middle" align="left" nowrap="nowrap">';
+               echo AT_date(_AT('inbox_date_format'),  $row['date_sent'], AT_DATE_MYSQL_DATETIME);
+               echo '</td>';
+               echo '</tr>';
+       } while ($row = mysql_fetch_assoc($result)); ?>
+<?php else: ?>
+       <tr>
+               <td colspan="4"><?php echo _AT('none_found'); ?></td>
+       </tr>
+<?php endif; ?>
+</tbody>
+</table>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/include/classes/Backup/Backup.class.php b/include/classes/Backup/Backup.class.php
new file mode 100644 (file)
index 0000000..09efdf6
--- /dev/null
@@ -0,0 +1,460 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+require_once(AT_INCLUDE_PATH.'classes/zipfile.class.php');
+
+define('NUMBER',       1);
+define('TEXT',         2);
+
+/**
+* Backup
+* Class for creating and managing course backups
+* @access      public
+* @author      Joel Kronenberg
+* @package     Backup
+*/
+class Backup {
+
+       // private
+       // number of backups in the backup dir
+       var $num_backups;
+
+       // private
+       // the current course id
+       var $course_id;
+
+       // private
+       // where to store the backup
+       var $backup_dir;
+
+       // private
+       // db handler
+       var $db;
+
+       // the backup zipfile Object
+       var $zipfile;
+
+       // the timestamp for the zip files
+       var $timestamp;
+
+       // private
+       // array of installed modules that support backups
+       var $modules;
+
+       var $backup_tables;
+
+       // constructor
+       function Backup(&$db, $course_id = 0) {
+
+               $this->db = $db;
+
+               $this->setCourseID($course_id);
+       }
+
+       // public
+       // should be used by the admin section
+       function setCourseID($course_id) {
+               $this->course_id  = $course_id;
+               $this->backup_dir = AT_BACKUP_DIR . $course_id . DIRECTORY_SEPARATOR;
+       }
+
+
+       // public
+       // call staticly
+       function generateFileName( ) {
+               global $system_courses;
+               $title = $system_courses[$this->course_id]['title'];
+
+               $title = str_replace(' ',  '_', $title);
+               $title = str_replace('%',  '',  $title);
+               $title = str_replace('\'', '',  $title);
+               $title = str_replace('"',  '',  $title);
+               $title = str_replace('`',  '',  $title);
+
+               $title .= '_' . date('d_M_y') . '.zip';
+
+               return $title;
+       }
+
+       // public
+       // NOTE: should the create() deal with saving it to disk as well? or should it be general to just create it, and not actually
+       // responsible for where to save it? (write a diff method to save it after)
+       function create($description) {
+               global $addslashes, $moduleFactory;
+
+               if ($this->getNumAvailable() >= AT_COURSE_BACKUPS) {
+                       return FALSE;
+               }
+
+               $timestamp = time();
+
+               $zipfile =& new zipfile();
+
+               $package_identifier = VERSION."\n\n\n".'Do not change the first line of this file it contains the ATutor version this backup was created with.';
+               $zipfile->add_file($package_identifier, 'atutor_backup_version', $timestamp);
+
+               // backup course properties. ONLY BANNER FOR NOW.
+               require_once(AT_INCLUDE_PATH . 'classes/CSVExport.class.php');
+               $CSVExport = new CSVExport();
+               $now = time();
+               
+               $sql = 'SELECT banner 
+              FROM '.TABLE_PREFIX.'courses 
+             WHERE course_id='.$this->course_id;
+               $properties = $CSVExport->export($sql, $course_id);
+               $zipfile->add_file($properties, 'properties.csv', $now);
+
+               // backup modules
+               $modules = $moduleFactory->getModules(AT_MODULE_STATUS_ENABLED | AT_MODULE_STATUS_DISABLED);
+               $keys = array_keys($modules);
+               foreach($keys as $module_name) {
+                       $module =& $modules[$module_name];
+                       $module->backup($this->course_id, $zipfile);
+               }
+               $zipfile->close();
+
+               $system_file_name = md5($timestamp);
+               
+               if (!is_dir(AT_BACKUP_DIR)) {
+                       @mkdir(AT_BACKUP_DIR);
+               }
+
+               if (!is_dir(AT_BACKUP_DIR . $this->course_id)) {
+                       @mkdir(AT_BACKUP_DIR . $this->course_id);
+               }
+
+               $zipfile->write_file(AT_BACKUP_DIR . $this->course_id . DIRECTORY_SEPARATOR . $system_file_name . '.zip');
+
+               $row['description']      = $addslashes($description);
+               $row['contents']         = addslashes(serialize($table_counters));
+               $row['system_file_name'] = $system_file_name;
+               $row['file_size']                = $zipfile->get_size();
+               $row['file_name']        = $this->generateFileName();
+
+               $this->add($row);
+
+               return TRUE;
+       }
+
+       // public
+       function upload($_FILES, $description) {
+               global $addslashes, $msg;
+       
+               $ext = pathinfo($_FILES['file']['name']);
+               $ext = $ext['extension'];
+
+               if (!$_FILES['file']['name'] || !is_uploaded_file($_FILES['file']['tmp_name']) || ($ext != 'zip')) {
+                       if ($_FILES['file']['error'] == 1) { // LEQ to UPLOAD_ERR_INI_SIZE
+                               $errors = array('FILE_TOO_BIG', ini_get('upload_max_filesize'));
+                               $msg->addError($errors); 
+                       } else {
+                               $msg->addError('FILE_NOT_SELECTED');
+                       }
+               }
+
+               if ($_FILES['file']['size'] == 0) {
+                       $msg->addError('IMPORTFILE_EMPTY');
+               }
+
+               if($msg->containsErrors()) {
+                       return;
+               }
+
+               $row = array();
+               $row['description'] = $addslashes($description);
+               $row['system_file_name'] =  md5(time());
+               $row['contents'] = '';
+               $row['file_size'] = $_FILES['file']['size'];
+               $row['file_name'] = $addslashes($_FILES['file']['name']);
+
+               if (!is_dir(AT_BACKUP_DIR)) {
+                       @mkdir(AT_BACKUP_DIR);
+               }
+
+               if (!is_dir(AT_BACKUP_DIR . $this->course_id)) {
+                       @mkdir(AT_BACKUP_DIR . $this->course_id);
+               }
+
+               $backup_path = AT_BACKUP_DIR . DIRECTORY_SEPARATOR . $this->course_id . DIRECTORY_SEPARATOR;
+
+               move_uploaded_file($_FILES['file']['tmp_name'], $backup_path . $row['system_file_name'].'.zip');
+
+               $this->add($row);
+
+               return;
+       }
+
+       // private
+       // adds a backup to the database
+       function add($row) {
+               $sql = "INSERT INTO ".TABLE_PREFIX."backups VALUES (NULL, $this->course_id, NOW(), '$row[description]', '$row[file_size]', '$row[system_file_name]', '$row[file_name]', '$row[contents]')";
+               mysql_query($sql, $this->db);
+       }
+
+       // public
+       // get number of backups
+       function getNumAvailable() {
+               // use $num_backups, if not set then do a COUNT(*) on the table
+               if (isset($this->num_backups)) {
+                       return $this->num_backups;
+               }
+
+               $sql    = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."backups WHERE course_id=$this->course_id";
+               $result = mysql_query($sql, $this->db);
+               $row    = mysql_fetch_assoc($result);
+
+               $this->num_backups = $row['cnt'];
+               return $row['cnt'];
+       }
+
+       // public
+       // get list of backups
+       function getAvailableList() {
+               $backup_list = array();
+
+               $sql    = "SELECT *, UNIX_TIMESTAMP(date) AS date_timestamp FROM ".TABLE_PREFIX."backups WHERE course_id=$this->course_id ORDER BY date DESC";
+               $result = mysql_query($sql, $this->db);
+               while ($row = mysql_fetch_assoc($result)) {
+                       $backup_list[$row['backup_id']] = $row;
+                       $backup_list[$row['backup_id']]['contents'] = unserialize($row['contents']);
+               }
+
+               $this->num_backups = count($backup_list);
+
+               return $backup_list;
+       }
+
+       // public
+       function download($backup_id) { // or fetch()
+               $list = $this->getAvailableList($this->course_id);
+               if (!isset($list[$backup_id])) {
+                       // catch the error
+                       //debug('does not belong to us');
+                       exit;
+               }
+
+               $my_backup = $list[$backup_id];
+               $file_name = $my_backup['file_name'];
+
+               header('Content-Type: application/zip');
+               header('Content-transfer-encoding: binary'); 
+               header('Content-Disposition: attachment; filename="'.htmlspecialchars($file_name).'"');
+               header('Expires: 0');
+               header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+               header('Pragma: public');
+               header('Content-Length: '.$my_backup['file_size']);
+
+               // see the note in get.php about the use of x-Sendfile
+               ob_end_clean();
+               header("Content-Encoding: none");
+               header('x-Sendfile: ' . AT_BACKUP_DIR . $this->course_id . DIRECTORY_SEPARATOR . $my_backup['system_file_name']. '.zip');
+               header('x-Sendfile: ', TRUE); // if we get here then it didn't work
+
+               readfile(AT_BACKUP_DIR . $this->course_id . DIRECTORY_SEPARATOR . $my_backup['system_file_name']. '.zip');
+               exit;
+       }
+
+       // public
+       function delete($backup_id) {
+               $list = $this->getAvailableList($this->course_id);
+               if (!isset($list[$backup_id])) {
+                       // catch the error
+                       //debug('does not belong to us');
+                       exit;
+               }
+               $my_backup = $list[$backup_id];
+
+               // delete the backup file:
+               @unlink(AT_BACKUP_DIR . $this->course_id . DIRECTORY_SEPARATOR . $my_backup['system_file_name']. '.zip');
+
+               // delete the row in the table:
+               $sql    = "DELETE FROM ".TABLE_PREFIX."backups WHERE backup_id=$backup_id AND course_id=$this->course_id";
+               $result = mysql_query($sql, $this->db);
+       }
+
+       // public
+       function edit($backup_id, $description) {
+               global $addslashes;
+
+               // sql safe input
+               $backup_id              = abs($backup_id);
+               $description    = $addslashes($description);
+
+               // update description in the table:
+               $sql    = "UPDATE ".TABLE_PREFIX."backups SET description='$description', date=date WHERE backup_id=$backup_id AND course_id=$this->course_id";
+               $result = mysql_query($sql, $this->db);
+
+       }
+
+       // public
+       function getRow($backup_id, $course_id = 0) {
+               // sql safe input
+               $backup_id      = abs($backup_id);
+               $course_id      = abs($course_id);
+
+               if ($course_id) {
+                       $sql    = "SELECT *, UNIX_TIMESTAMP(date) AS date_timestamp FROM ".TABLE_PREFIX."backups WHERE backup_id=$backup_id AND course_id=$course_id";
+               } else {
+                       $sql    = "SELECT *, UNIX_TIMESTAMP(date) AS date_timestamp FROM ".TABLE_PREFIX."backups WHERE backup_id=$backup_id AND course_id=$this->course_id";
+               }
+
+               $result = mysql_query($sql, $this->db);
+               $row = mysql_fetch_assoc($result);
+
+               if ($row) {
+                       $row['contents'] = unserialize($row['contents']);
+               }
+               return $row;
+       }
+
+       // public
+       function translate_whitespace($input) {
+               $input = str_replace('\n', "\n", $input);
+               $input = str_replace('\r', "\r", $input);
+               $input = str_replace('\x00', "\0", $input);
+
+               return $input;
+       }
+
+       // public
+       function getVersion() {
+               if ((file_exists($this->import_dir.'atutor_backup_version')) && ($version = file($this->import_dir.'atutor_backup_version'))) {
+                       return trim($version[0]);
+               } else {
+                       return false;
+               }
+       }
+
+       // public
+       function restore($material, $action, $backup_id, $from_course_id = 0) {
+               global $moduleFactory;
+               require_once(AT_INCLUDE_PATH.'classes/pclzip.lib.php');
+               require_once(AT_INCLUDE_PATH.'lib/filemanager.inc.php');
+
+               if (!$from_course_id) {
+                       $from_course_id = $this->course_id;
+               }
+
+               // 1. get backup row/information
+               $my_backup = $this->getRow($backup_id, $from_course_id);
+
+               @mkdir(AT_CONTENT_DIR . 'import/' . $this->course_id);
+               $this->import_dir = AT_CONTENT_DIR . 'import/' . $this->course_id . '/';
+
+               // 2. extract the backup
+               $archive = new PclZip(AT_BACKUP_DIR . $from_course_id. '/' . $my_backup['system_file_name']. '.zip');
+               if ($archive->extract(  PCLZIP_OPT_PATH,        $this->import_dir, 
+                                                               PCLZIP_CB_PRE_EXTRACT,  'preImportCallBack') == 0) {
+                       die("Error : ".$archive->errorInfo(true));
+               }
+
+               // 3. get the course's max_quota. if backup is too big AND we want to import files then abort/return FALSE
+               /* get the course's max_quota */
+               // $this->getFilesSize();
+
+               // 4. figure out version number
+               $this->version = $this->getVersion();
+               if (!$this->version) {
+                       clr_dir($this->import_dir);
+                       global $msg;
+                       $msg->addError('BACKUP_RESTORE');
+                       header('Location: '.$_SERVER['PHP_SELF']);
+                       exit;
+                       //exit('version not found. backups < 1.3 are not supported.');
+               }
+
+               if (version_compare($this->version, VERSION, '>') == 1) {
+                       clr_dir($this->import_dir);
+                       global $msg;
+
+                       $msg->addError('BACKUP_UNSUPPORTED_GREATER_VERSION');
+                       header('Location: '.$_SERVER['PHP_SELF']);
+                       exit;
+               }
+               if (version_compare($this_version, '1.5.3', '<')) {
+                       if (file_exists($this->import_dir . 'resource_categories.csv')) {
+                               @rename($this->import_dir . 'resource_categories.csv', $this->import_dir. 'links_categories.csv');
+                       }
+                       if (file_exists($this->import_dir . 'resource_links.csv')) {
+                               @rename($this->import_dir . 'resource_links.csv', $this->import_dir. 'links.csv');
+                       }
+               }
+
+               // 5. if override is set then delete the content
+               if ($action == 'overwrite') {
+                       require_once(AT_INCLUDE_PATH.'lib/delete_course.inc.php');
+                       delete_course($this->course_id, $material);
+                       $_SESSION['s_cid'] = 0;
+               } // else: appending content
+
+               if ($material === TRUE) {
+                       // restore the entire backup (used when creating a new course)
+                       $module_list = $moduleFactory->getModules(AT_MODULE_ENABLED | AT_MODULE_CORE);
+                       $_POST['material'] = $module_list;
+               }
+               foreach ($_POST['material'] as $module_name => $garbage) {
+                       // restore course properties, ONLY BANNER FOR NOW.
+                       if ($module_name == 'properties' && file_exists($this->import_dir . "properties.csv"))
+                       {
+                               global $db;
+                               
+                               $properties_str = file_get_contents($this->import_dir . "properties.csv");
+                               $banner_values = explode(',',str_replace('"', '', $properties_str));
+
+                               $sql = "UPDATE ".TABLE_PREFIX."courses 
+                                          SET banner = '". $banner_values[0]. "' 
+                                        WHERE course_id = ".$this->course_id;
+                               $result = mysql_query($sql,$db) or die(mysql_error());
+                       }
+                       
+                       // restore modules
+                       $module =& $moduleFactory->getModule($module_name);
+                       $module->restore($this->course_id, $this->version, $this->import_dir);
+               }
+               clr_dir($this->import_dir);
+       }
+
+       // private
+       // no longer used
+       function restore_files() {
+               $sql    = "SELECT max_quota FROM ".TABLE_PREFIX."courses WHERE course_id=$this->course_id";
+               $result = mysql_query($sql, $this->db);
+               $row    = mysql_fetch_assoc($result);
+
+               if ($row['max_quota'] != AT_COURSESIZE_UNLIMITED) {
+                       global $MaxCourseSize, $MaxCourseFloat;
+
+                       if ($row['max_quota'] == AT_COURSESIZE_DEFAULT) {
+                               $row['max_quota'] = $MaxCourseSize;
+                       }
+                       
+                       $totalBytes   = dirsize($this->import_dir . 'content/');
+                       
+                       $course_total = dirsize(AT_CONTENT_DIR . $this->course_id . '/');
+               
+                       $total_after  = $row['max_quota'] - $course_total - $totalBytes + $MaxCourseFloat;
+
+                       if ($total_after < 0) {
+                               //debug('not enough space. delete everything');
+                               // remove the content dir, since there's no space for it
+                               clr_dir($this->import_dir);
+                               return FALSE;
+                       }
+               }
+
+               copys($this->import_dir.'content/', AT_CONTENT_DIR . $this->course_id);
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/include/classes/Backup/TableBackup.class.php b/include/classes/Backup/TableBackup.class.php
new file mode 100644 (file)
index 0000000..c91a35e
--- /dev/null
@@ -0,0 +1,1132 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+exit(__FILE__ . ' no longer used');\r
+/**\r
+* TableFactory\r
+* Class for creating AbstractTable Objects\r
+* @access      public\r
+* @author      Joel Kronenberg\r
+* @package     Backup\r
+*/\r
+class TableFactory {\r
+       /**\r
+       * The database handler.\r
+       *\r
+       * @access  private\r
+       * @var resource\r
+       */\r
+       var $db;\r
+\r
+       /**\r
+       * The ATutor version this backup was created with.\r
+       *\r
+       * @access private\r
+       * @var string\r
+       */\r
+       var $version;\r
+\r
+       /**\r
+       * The course ID we're restoring into.\r
+       *\r
+       * @access private\r
+       * @var int\r
+       */\r
+       var $course_id;\r
+\r
+       /**\r
+       * The directory unzip backup is found.\r
+       *\r
+       * @access private\r
+       * @var string\r
+       */\r
+       var $import_dir;\r
+\r
+       /**\r
+       * Constructor.\r
+       * \r
+       * @param string $version The backup version.\r
+       * @param resource $db The database handler.\r
+       * @param int $course_id The ID of this course.\r
+       * @param string $import_dir The directory where the backup was unzipped to.\r
+       * \r
+       */\r
+       function TableFactory ($version, $db, $course_id, $import_dir) {\r
+               $this->version    = $version;\r
+               $this->db         = $db;\r
+               $this->course_id  = $course_id;\r
+               $this->import_dir = $import_dir;\r
+       }\r
+\r
+       /**\r
+       * Create and return the specified AbstractTable Object.\r
+       * \r
+       * @access public\r
+       * @param string $table_name The name of the table to create an Object for.\r
+       * @return AbstractTable Object|NULL if $table_name does not match available Objects.\r
+       * @See AbstractTable\r
+       *\r
+       */\r
+       function createTable($table_name) {\r
+               // static hash to keep track of new ID mappings:\r
+               static $id_map;\r
+\r
+               switch ($table_name) {\r
+                       case 'stats':\r
+                               return new CourseStatsTable($this->version, $this->db, $this->course_id, $this->import_dir, $garbage);\r
+                               break;\r
+\r
+                       /*\r
+                       case 'polls':\r
+                               return new PollsTable($this->version, $this->db, $this->course_id, $this->import_dir, $garbage);\r
+                               break;\r
+                       */\r
+\r
+                       case 'tests':\r
+                               return new TestsTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
+                               break;\r
+\r
+                       case 'tests_questions_categories':\r
+                               return new TestsQuestionsCategoriesTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
+                               break;\r
+\r
+                       case 'tests_questions_assoc':\r
+                               return new TestsQuestionsAssocTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
+                               break;\r
+\r
+                       case 'tests_questions':\r
+                               return new TestsQuestionsTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
+                               break;\r
+\r
+                       case 'news':\r
+                               return new NewsTable($this->version, $this->db, $this->course_id, $this->import_dir, $garbage);\r
+                               break;\r
+\r
+                       case 'groups':\r
+                               return new GroupsTable($this->version, $this->db, $this->course_id, $this->import_dir, $garbage);\r
+                               break;\r
+\r
+                       case 'forums':\r
+                               return new ForumsTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
+                               break;\r
+\r
+                       case 'forums_courses':\r
+                               return new ForumsCoursesTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
+                               break;\r
+\r
+                       case 'glossary':\r
+                               return new GlossaryTable($this->version, $this->db, $this->course_id, $this->import_dir, $garbage);\r
+                               break;\r
+\r
+                       case 'resource_links':\r
+                               return new ResourceLinksTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
+                               break;\r
+\r
+                       case 'resource_categories':\r
+                               return new ResourceCategoriesTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
+                               break;\r
+\r
+                       case 'content':\r
+                               return new ContentTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
+                               break;\r
+\r
+                       case 'related_content':\r
+                               return new RelatedContentTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
+                               break;\r
+\r
+                       default:\r
+                               if (class_exists($table_name . 'Table')) {\r
+                                       $table_name = $table_name . 'Table';\r
+                                       return new $table_name($this->version, $this->db, $this->course_id, $this->import_dir, $garbage);\r
+                               }\r
+                               return NULL;\r
+               }\r
+       }\r
+}\r
+\r
+/**\r
+* AbstractTable\r
+* Class for restoring backup tables\r
+* @access      public\r
+* @author      Joel Kronenberg\r
+* @package     Backup\r
+*/\r
+class AbstractTable {\r
+       /**\r
+       * The ATutor version this backup was created with.\r
+       *\r
+       * @access protected\r
+       * @var string\r
+       */\r
+       var $version;\r
+\r
+       /**\r
+       * The database handler.\r
+       *\r
+       * @access  private\r
+       * @var resource\r
+       */\r
+       var $db;\r
+\r
+       /**\r
+       * The CSV table file handler.\r
+       *\r
+       * @access  private\r
+       * @var resource\r
+       */\r
+       var $fp;\r
+\r
+       /**\r
+       * The course ID we're restoring into.\r
+       *\r
+       * @access private\r
+       * @var int\r
+       */\r
+       var $course_id;\r
+\r
+       /**\r
+       * The directory unzip backup is found.\r
+       *\r
+       * @access private\r
+       * @var string\r
+       */\r
+       var $import_dir;\r
+\r
+       /**\r
+       * A hash table associated old ID's (key) with their new ID's (value).\r
+       *\r
+       * @access private\r
+       * @var array\r
+       */\r
+       var $old_ids_to_new_ids;\r
+\r
+       /**\r
+       * Constructor.\r
+       * \r
+       * @param string $version The backup version.\r
+       * @param resource $db The database handler.\r
+       * @param int $course_id The ID of this course.\r
+       * @param string $import_dir The directory where the backup was unzipped to.\r
+       * @param array $old_ids_to_new_ids Reference.\r
+       * \r
+       */\r
+       function AbstractTable($version, $db, $course_id, $import_dir, &$old_ids_to_new_ids) {\r
+               global $db;\r
+               $this->db =& $db;\r
+               $this->course_id = $course_id;\r
+               $this->version = $version;\r
+               $this->import_dir = $import_dir;\r
+\r
+               $this->old_ids_to_new_ids =& $old_ids_to_new_ids;\r
+\r
+               if (!isset($this->old_ids_to_new_ids[$this->tableName])) {\r
+                       $this->old_ids_to_new_ids[$this->tableName] = array();\r
+               }\r
+       }\r
+\r
+       // -- public methods below:\r
+\r
+       /**\r
+       * Restores the table defined in the CSV file, one row at a time.\r
+       * \r
+       * @access public\r
+       * @return void\r
+       *\r
+       * @See getRows()\r
+       * @See insertRow()\r
+       */\r
+       function restore() {\r
+               global $db;\r
+\r
+               // skipLock is used specificially with the `forums_courses` table\r
+               if (!isset($this->skipLock)) {\r
+                       $this->lockTable();\r
+               }\r
+\r
+               $this->getRows();\r
+\r
+               if ($this->rows) {\r
+                       foreach ($this->rows as $row) {\r
+                               \r
+                               $sql = $this->generateSQL($row); \r
+                               mysql_query($sql, $db);\r
+                               //debug($sql);\r
+                               //debug(mysql_error($this->db));\r
+                       }\r
+               }\r
+               if (!isset($this->skipLock)) {\r
+                       $this->unlockTable();\r
+               }\r
+       }\r
+\r
+       // -- protected methods below:\r
+\r
+       /**\r
+       * Converts escaped white space characters to their correct representation.\r
+       * \r
+       * @access protected\r
+       * @param string $input The string to convert.\r
+       * @return string The converted string.\r
+       * @See Backup::quoteCSV()\r
+       */\r
+       function translateWhitespace($input) {\r
+               $input = str_replace('\n', "\n", $input);\r
+               $input = str_replace('\r', "\r", $input);\r
+               $input = str_replace('\x00', "\0", $input);\r
+\r
+               $input = addslashes($input);\r
+               return $input;\r
+       }\r
+\r
+       // protected\r
+       // find the index offset\r
+       function findOffset($id) {\r
+               return $this->rows[$id]['index_offset'];\r
+       }\r
+\r
+       // -- private methods below:\r
+       function getNextID() {\r
+               global $db;\r
+\r
+               $sql      = 'SELECT MAX(' . $this->primaryIDField . ') AS next_id FROM ' . TABLE_PREFIX . $this->tableName;\r
+               $result   = mysql_query($sql, $db);\r
+               $next_index = mysql_fetch_assoc($result);\r
+               return ($next_index['next_id'] + 1);\r
+       }\r
+\r
+       /**\r
+        * Gets the member_id of the instructor who owns a course in the context of a backup restore\r
+        *\r
+        * @param int $id The backup course to query on\r
+        * @access protected\r
+        * @return int The member_id who owns the corresponding backup course\r
+        */\r
+       function resolveBkpOwner($id) {\r
+               global $db;\r
+\r
+               $sql = 'SELECT member_id FROM ' . TABLE_PREFIX . 'courses WHERE course_id = '. $id;\r
+\r
+               $result = mysql_query($sql, $db);\r
+               \r
+               if (!$result) {\r
+                       echo 'Fatal SQL error occured in TableBackup:resolveBkpOwner: ' . mysql_error() . \r
+                                                               ' ' . mysql_error($db) . \r
+                                                               ' Check that the course your are restoring to exists.';\r
+                       return;\r
+               }\r
+               \r
+               $row = mysql_fetch_assoc($result);\r
+               \r
+               if (!$row) {\r
+                       echo 'Fatal SQL error occured in TableBackup:resolveBkpOwner: ' . mysql_error() . \r
+                                                               ' ' . mysql_error($db) . \r
+                                                               ' Check that the course your are restoring to exists.';\r
+                       return;\r
+               }\r
+               \r
+               return $row['member_id'];\r
+       }\r
+       \r
+       /**\r
+       * Reads the CSV table file into array $this->rows.\r
+       * \r
+       * @access private\r
+       * @return void\r
+       *\r
+       * @See openTable()\r
+       * @See closeTable()\r
+       * @See getOldID()\r
+       */\r
+       function getRows() {\r
+               $this->openFile();\r
+               $i = 0;\r
+\r
+               $next_id = $this->getNextID();\r
+\r
+               while ($row = @fgetcsv($this->fp, 70000)) {\r
+                       if (count($row)) {\r
+                               $row[0] = trim($row[0]);\r
+                               if ($row[0] == '') {\r
+                                       continue;\r
+                               }\r
+                       }\r
+                       $row = $this->translateText($row);\r
+                       $row = $this->convert($row);\r
+\r
+                       $row['index_offset'] = $i;\r
+                       $row['new_id'] = $next_id++;\r
+                       if ($this->getOldID($row) === FALSE) {\r
+                               $this->rows[] = $row;\r
+                       } else {\r
+                               $this->rows[$this->getOldID($row)] = $row;\r
+                               $this->old_ids_to_new_ids[$this->tableName][$this->getOldID($row)] = $row['new_id'];\r
+                       }\r
+\r
+                       $i++;\r
+               }\r
+               $this->closeFile();\r
+       }\r
+\r
+       /**\r
+       * Converts $row to be ready for inserting into the db.\r
+       * \r
+       * @param array $row The row to convert.\r
+       * @access private\r
+       * @return array The converted row.\r
+       *\r
+       * @see translateWhitespace()\r
+       */\r
+       function translateText($row) {\r
+               return $row;\r
+               global $backup_tables;\r
+               $count = 0;\r
+\r
+               foreach ($backup_tables[$this->tableName]['fields'] as $field) {\r
+                       if ($field[1] == TEXT) {\r
+                               $row[$count] = $this->translateWhitespace($row[$count]);\r
+                       }\r
+                       $count++;\r
+               }\r
+               return $row;\r
+       }\r
+\r
+       /**\r
+       * Locks the database table for writing or/and also lock the courses table for resolving restore issues\r
+       * in the admin context \r
+       * \r
+       * @access private\r
+       * @return void\r
+       *\r
+       * @See unlockTable()\r
+       */\r
+       function lockTable() {\r
+               global $db;\r
+               $lock_sql;\r
+                       \r
+               if ($_SESSION['member_id'])\r
+                       $lock_sql = 'LOCK TABLES ' . TABLE_PREFIX . $this->tableName. ' WRITE';\r
+               else // admin context\r
+                       $lock_sql = 'LOCK TABLES ' . TABLE_PREFIX . $this->tableName. ', ' . TABLE_PREFIX . 'courses WRITE';\r
+                       \r
+               $result   = mysql_query($lock_sql, $db);\r
+       }\r
+\r
+       /**\r
+       * UnLocks the database table.\r
+       * \r
+       * @access private\r
+       * @return void\r
+       *\r
+       * @See lockTable()\r
+       */\r
+       function unlockTable() {\r
+               global $db;\r
+               $lock_sql = 'UNLOCK TABLES';\r
+               $result   = mysql_query($lock_sql, $db);\r
+       }\r
+\r
+       /**\r
+       * Opens the CSV table file for reading.\r
+       * \r
+       * @access private\r
+       * @return void\r
+       *\r
+       * @See closeFile()\r
+       */\r
+       function openFile() {\r
+               $this->fp = @fopen($this->import_dir . $this->tableName . '.csv', 'rb');\r
+       }\r
+\r
+       /**\r
+       * Closes the CSV table file.\r
+       * \r
+       * @access private\r
+       * @return void\r
+       *\r
+       * @See openFile()\r
+       */\r
+       function closeFile() {\r
+               @fclose($this->fp);\r
+       }\r
+\r
+       /**\r
+       * Gets the entry/row's new ID based on it's old entry ID.\r
+       * \r
+       * @param int $id The old entry ID.\r
+       * @access protected\r
+       * @return int The new entry ID\r
+       *\r
+       */\r
+       function getNewID($id) {\r
+               return $this->rows[$id]['new_id'];\r
+       }\r
+       \r
+       // -- abstract methods below:\r
+       /**\r
+       * Gets the entry/row ID as it appears in the CSV file, or FALSE if n/a.\r
+       * \r
+       * @param array $row The old entry row from the CSV file.\r
+       * @access private\r
+       * @return boolean|int The old ID or FALSE if not applicable.\r
+       *\r
+       */\r
+       function getOldID($row)    { /* abstract */ }\r
+\r
+       /**\r
+       * Convert the entry/row to the current ATutor version.\r
+       * \r
+       * @param array $row The old entry row from the CSV file.\r
+       * @access private\r
+       * @return array The converted row.\r
+       *\r
+       */\r
+       function convert($row)     { /* abstract */ }\r
+\r
+       /**\r
+       * Generate the SQL for this table.\r
+       * \r
+       * Precondition: $row has passed through convert() and \r
+       * translateText().\r
+       *\r
+       * @param array $row The old entry row from the CSV file.\r
+       * @access private\r
+       * @return string The SQL query.\r
+       *\r
+       * @see insertRow()\r
+       */\r
+       function generateSQL($row) { /* abstract */ }\r
+\r
+}\r
+//---------------------------------------------------------------------\r
+\r
+/**\r
+* ForumsTable\r
+* Extends AbstractTable and provides table specific methods and members.\r
+* @access      public\r
+* @author      Joel Kronenberg\r
+* @author      Heidi Hazelton\r
+* @package     Backup\r
+*/\r
+class ForumsTable extends AbstractTable {\r
+       /**\r
+       * The ATutor database table name (w/o prefix).\r
+       * Also the CSV file name (w/o extension).\r
+       *\r
+       * @access private\r
+       * @var const string\r
+       */\r
+       var $tableName      = 'forums';\r
+\r
+       /**\r
+       * The ATutor database table primary ID field.\r
+       *\r
+       * @access private\r
+       * @var const string\r
+       */\r
+       var $primaryIDField = 'forum_id';\r
+\r
+       // -- private methods below:\r
+       function getOldID($row) {\r
+               return $row[0];\r
+       }\r
+\r
+       function convert($row) {\r
+               if (version_compare($this->version, '1.4.3', '<')) {\r
+                       // previous versions didn't have a forum_id field\r
+                       static $count;\r
+                       $count++;\r
+                       for($i=5; $i>0; $i--) {\r
+                               $row[$i] = $row[$i-1];\r
+                       }\r
+                       $row[0] = $count;\r
+               }\r
+               return $row;\r
+       }\r
+\r
+       function generateSQL($row) {\r
+               $sql = 'INSERT INTO '.TABLE_PREFIX.'forums VALUES ';\r
+               $sql .= '('.$row['new_id']. ',';\r
+               $sql .= "'".$row[1]."',"; // title\r
+               $sql .= "'".$row[2]."',"; // description\r
+               $sql .= "$row[3],";       // num_topics\r
+               $sql .= "$row[4],";       // num_posts\r
+               $sql .= "'".$row[5]."')"; // last_post\r
+               \r
+               return $sql;\r
+       }\r
+}\r
+//---------------------------------------------------------------------\r
+/**\r
+* ForumsCoursesTable\r
+* Extends AbstractTable and provides table specific methods and members.\r
+* @access      public\r
+* @author      Heidi Hazelton\r
+* @package     Backup\r
+*/\r
+class ForumsCoursesTable extends AbstractTable {\r
+\r
+       /**\r
+       * The ATutor database table name (w/o prefix).\r
+       * Also the CSV file name (w/o extension).\r
+       *\r
+       * @access private\r
+       * @var const string\r
+       */\r
+       var $tableName      = 'forums';\r
+\r
+       /**\r
+       * The ATutor database table primary ID field.\r
+       *\r
+       * @access private\r
+       * @var const string\r
+       */\r
+       var $primaryIDField = 'forum_id';\r
+\r
+       /**\r
+       * Whether or not lock this table.\r
+       * This is a special case, b/c we read from the `forums` table\r
+       * but insert into the `forums_courses` table. Hence, we lock a different\r
+       * table than we actually insert into (ie. why we don't need/want a lock).\r
+       *\r
+       * @access private\r
+       * @var const boolean\r
+       */\r
+       var $skipLock = TRUE;\r
+\r
+       // -- private methods below:\r
+       function getOldID($row) {\r
+               return FALSE;\r
+       }\r
+\r
+       function convert($row) {\r
+               return $row;\r
+       }\r
+\r
+       function generateSQL($row) {\r
+               $this->count++;\r
+               if (version_compare($this->version, '1.4.3', '<')) {\r
+                       $id = $this->count;\r
+               } else {\r
+                       $id = $row[0];\r
+               }\r
+               $sql = 'INSERT INTO '.TABLE_PREFIX.'forums_courses VALUES ';\r
+               $sql .= '('.$this->old_ids_to_new_ids['forums'][$id] . ',';     // forum_id\r
+               $sql .= $this->course_id .")";          // course_id\r
+\r
+               return $sql;\r
+       }\r
+}\r
+//---------------------------------------------------------------------\r
+class GlossaryTable extends AbstractTable {\r
+       var $tableName      = 'glossary';\r
+       var $primaryIDField = 'word_id';\r
+\r
+       function getOldID($row) {\r
+               return $row[0];\r
+       }\r
+\r
+       // private\r
+       function convert($row) {\r
+               return $row;\r
+       }\r
+\r
+       // private\r
+       function generateSQL($row) {\r
+               // insert row\r
+               $sql = 'INSERT INTO '.TABLE_PREFIX.'glossary VALUES ';\r
+               $sql .= '('.$row['new_id'].','; // word_id  \r
+               $sql .= $this->course_id . ',';    // course_id \r
+               $sql .= "'".$row[1]."',";                  // word\r
+               $sql .= "'".$row[2]."',";                  // definition\r
+               if ($row[3] == 0) {\r
+                       $sql .= 0;\r
+               } else {\r
+                       $sql .= $this->getNewID($row[3]); // related word\r
+               }\r
+               $sql .=  ')';\r
+\r
+               return $sql;\r
+       }\r
+}\r
+//---------------------------------------------------------------------\r
+class ResourceCategoriesTable extends AbstractTable {\r
+       var $tableName = 'resource_categories';\r
+\r
+       var $primaryIDField = 'CatID';\r
+\r
+       function getOldID($row) {\r
+               return $row[0];\r
+       }\r
+\r
+       // private\r
+       function convert($row) {\r
+               return $row;\r
+       }\r
+\r
+       // private\r
+       function generateSQL($row) {\r
+               $sql = 'INSERT INTO '.TABLE_PREFIX.'resource_categories VALUES ';\r
+               $sql .= '('.$row['new_id'].',';\r
+               $sql .= $this->course_id .',';\r
+               // CatName\r
+               $sql .= "'".$row[1]."',";\r
+\r
+               // CatParent\r
+               if ($row[2] == 0) {\r
+                       $sql .= 'NULL';\r
+               } else {\r
+                       $sql .= $this->getNewID($row[2]); // category parent\r
+               }\r
+               $sql .= ')';\r
+\r
+               return $sql;\r
+       }\r
+}\r
+\r
+//---------------------------------------------------------------------\r
+class ResourceLinksTable extends AbstractTable {\r
+       var $tableName = 'resource_links';\r
+\r
+       var $primaryIDField = 'LinkID';\r
+\r
+       function getOldID($row) {\r
+               return FALSE;\r
+       }\r
+\r
+       // private\r
+       function convert($row) {\r
+               // handle the white space issue as well\r
+               return $row;\r
+       }\r
+\r
+       // private\r
+       function generateSQL($row) {\r
+               // insert row\r
+               $sql = 'INSERT INTO '.TABLE_PREFIX.'resource_links VALUES ';\r
+               $sql .= '('.$row['new_id'].', ';\r
+               $sql .= $this->old_ids_to_new_ids['resource_categories'][$row[0]] . ',';\r
+\r
+               $sql .= "'".$row[1]."',"; // URL\r
+               $sql .= "'".$row[2]."',"; // LinkName\r
+               $sql .= "'".$row[3]."',"; // Description\r
+               $sql .= $row[4].',';      // Approved\r
+               $sql .= "'".$row[5]."',"; // SubmitName\r
+               $sql .= "'".$row[6]."',"; // SubmitEmail\r
+               $sql .= "'".$row[7]."',"; // SubmitDate\r
+               $sql .= $row[8]. ')';\r
+\r
+               return $sql;\r
+       }\r
+}\r
+//---------------------------------------------------------------------\r
+class NewsTable extends AbstractTable {\r
+       var $tableName = 'news';\r
+       var $primaryIDField = 'news_id';\r
+\r
+       function getOldID($row) {\r
+               return FALSE;\r
+       }\r
+\r
+       // private\r
+       function convert($row) {\r
+               return $row;\r
+       }\r
+\r
+       // private\r
+       function generateSQL($row) {\r
+               // insert row\r
+               $sql = 'INSERT INTO '.TABLE_PREFIX.'news VALUES ';\r
+               $sql .= '('.$row['new_id'].',';\r
+               $sql .= $this->course_id.',';\r
+               \r
+               /**\r
+                * Admin user does not possess a member_id, assign ownership to instructor of restored course\r
+                */\r
+               if (isset($_SESSION['member_id'])) {\r
+                       $sql .= $_SESSION['member_id'] . ',';\r
+               } else { // admin context\r
+                       $sql .= $this->resolveBkpOwner($this->course_id) . ',';\r
+               }\r
+               \r
+               $sql .= "'".$row[0]."',";           // date\r
+               $sql .= "'".$row[1]."',";           // formatting\r
+               $sql .= "'".$row[2]."',";           // title\r
+               $sql .= "'".$row[3]."')";           // body\r
+\r
+               debug($sql);\r
+\r
+               return $sql;\r
+       }\r
+       \r
+}\r
+//---------------------------------------------------------------------\r
+// -- tests (`tests`, `tests_questions`, `tests_categories`, `tests_questions_assoc`)\r
+class TestsTable extends AbstractTable {\r
+       var $tableName = 'tests';\r
+       var $primaryIDField = 'test_id';\r
+\r
+       function getOldID($row) {\r
+               return $row[0];\r
+       }\r
+\r
+       // private\r
+       function convert($row) {\r
+               // handle the white space issue as well\r
+               if (version_compare($this->version, '1.4', '<')) {\r
+                       $row[8] = 0;\r
+                       $row[9] = 0;\r
+                       $row[10] = 0;\r
+                       $row[11] = 0;\r
+               } \r
+               \r
+               if (version_compare($this->version, '1.4.2', '<')) {\r
+                       $row[12] = 0;\r
+                       $row[13] = 0;\r
+               }\r
+               if (version_compare($this->version, '1.4.3', '<')) {\r
+                       $row[9]  = 0;\r
+                       $row[14] = 0;\r
+               }\r
+               return $row;\r
+       }\r
+\r
+       // private\r
+       function generateSQL($row) {\r
+               $sql = '';\r
+               $sql = 'INSERT INTO '.TABLE_PREFIX.'tests VALUES ';\r
+               $sql .= '('.$row['new_id'].',';\r
+               $sql .= $this->course_id.',';\r
+\r
+               $sql .= "'".$row[1]."',";       // title\r
+               $sql .= "'".$row[2]."',";       // format\r
+               $sql .= "'".$row[3]."',";       // start_date\r
+               $sql .= "'".$row[4]."',";       // end_date\r
+               $sql .= "'".$row[5]."',";       // randomize_order\r
+               $sql .= "'".$row[6]."',";       // num_questions\r
+               $sql .= "'".$row[7]."',";       // instructions\r
+               $sql .= '0,';                           // content_id\r
+               $sql .= $row[9] . ',';          // release_result\r
+               $sql .= $row[10] . ',';         // random\r
+               $sql .= $row[11] . ',';         // difficulty\r
+               $sql .= $row[12] . ',';         // num_takes\r
+               $sql .= $row[13] . ',';         // anonymous\r
+               $sql .= "'".$row[14]."'";   // out_of\r
+               $sql .= ')';\r
+\r
+               return $sql;\r
+       }\r
+}\r
+//---------------------------------------------------------------------\r
+class TestsQuestionsTable extends AbstractTable {\r
+       var $tableName = 'tests_questions';\r
+       var $primaryIDField = 'question_id';\r
+\r
+       function getOldID($row) {\r
+               return $row[0];\r
+       }\r
+\r
+       // private\r
+       function convert($row) {\r
+               if (version_compare($this->version, '1.4.3', '<')) {\r
+                       // basically, rework the fields then recreate the `tests_questions_assoc.csv` file.\r
+                       // create the tests_questions_assoc file using $row[0] as the `test_id` and $row['new_id'] as the new question ID\r
+                       static $count;\r
+                       $test_id  = $row[0];\r
+                       $order    = $row[1];\r
+                       $weight   = $row[3];\r
+                       $required = $row[4];\r
+\r
+                       $count++;\r
+                       $row[0] = $count;  // question id\r
+                       $row[1] = 0;       // category id\r
+                       $row[2] = $row[2]; // type\r
+\r
+                       for($i = 3; $i < 27; $i++) {\r
+                               $row[$i] = $row[$i+2];\r
+                       }\r
+\r
+                       $assoc_data = "$test_id,$count,$weight,$order,$required\n";\r
+                       $fp = fopen($this->import_dir . 'tests_questions_assoc.csv', 'ab');\r
+                       fwrite($fp, $assoc_data);\r
+                       fclose($fp);\r
+               }\r
+\r
+               return $row;\r
+       }\r
+\r
+       // private\r
+       function generateSQL($row) {\r
+               // insert row\r
+\r
+               if (!isset($this->old_ids_to_new_ids['tests_questions_categories'][$row[1]])) {\r
+                       $this->old_ids_to_new_ids['tests_questions_categories'][$row[1]] = 0;\r
+               }\r
+\r
+               $sql = 'INSERT INTO '.TABLE_PREFIX.'tests_questions VALUES ';\r
+               $sql .= '('.$row['new_id'].',' . $this->old_ids_to_new_ids['tests_questions_categories'][$row[1]] . ',';\r
+               $sql .= $this->course_id;\r
+\r
+               for ($i=2; $i <= 26; $i++) {\r
+                       $sql .= ",'".$row[$i]."'";\r
+               }\r
+\r
+               $sql .= ')';\r
+\r
+               return $sql;\r
+       }\r
+}\r
+//---------------------------------------------------------------------\r
+class TestsQuestionsAssocTable extends AbstractTable {\r
+       var $tableName = 'tests_questions_assoc';\r
+       var $primaryIDField = 'question_id';\r
+\r
+       function getOldID($row) {\r
+               return FALSE;\r
+       }\r
+\r
+       // private\r
+       function convert($row) {\r
+               return $row;\r
+       }\r
+\r
+       // private\r
+       function generateSQL($row) {\r
+               // insert row\r
+               $sql = 'INSERT INTO '.TABLE_PREFIX.'tests_questions_assoc VALUES ';\r
+               $sql .= '(' . $this->old_ids_to_new_ids['tests'][$row[0]].',' . $this->old_ids_to_new_ids['tests_questions'][$row[1]];\r
+               $sql .= ",'$row[2]','$row[3]','$row[4]')";\r
+\r
+               return $sql;\r
+       }\r
+}\r
+//---------------------------------------------------------------------\r
+class TestsQuestionsCategoriesTable extends AbstractTable {\r
+       var $tableName = 'tests_questions_categories';\r
+       var $primaryIDField = 'category_id';\r
+\r
+       function getOldID($row) {\r
+               return $row[0];\r
+       }\r
+\r
+       // private\r
+       function convert($row) {\r
+               return $row;\r
+       }\r
+\r
+       // private\r
+       function generateSQL($row) {\r
+               // insert row\r
+               $sql = 'INSERT INTO '.TABLE_PREFIX.'tests_questions_categories VALUES ';\r
+               $sql .= '('.$row['new_id'].',';\r
+               $sql .= $this->course_id;\r
+               $sql .= ',"'.$row[1].'"';\r
+               $sql .= ')';\r
+\r
+               return $sql;\r
+       }\r
+}\r
+//---------------------------------------------------------------------\r
+/*\r
+class PollsTable extends AbstractTable {\r
+       var $tableName = 'polls';\r
+       var $primaryIDField = 'poll_id';\r
+\r
+       function getOldID($row) {\r
+               return FALSE;\r
+       }\r
+\r
+       // private\r
+       function convert($row) {\r
+               return $row;\r
+       }\r
+\r
+       // private\r
+       function generateSQL($row) {\r
+               // insert row\r
+               $sql = 'INSERT INTO '.TABLE_PREFIX.'polls VALUES ';\r
+               $sql .= '('.$row['new_id'].',';\r
+               $sql .= $this->course_id.',';\r
+               $sql .= "'$row[0]',"; // question\r
+               $sql .= "'$row[1]',"; // created date\r
+               $sql .= "0,";         // total\r
+\r
+               for ($i=2; $i<=8; $i++) {\r
+                       $sql .= "'".$row[$i]."',0,";\r
+               }\r
+\r
+               $sql  = substr($sql, 0, -1);\r
+               $sql .= ')';\r
+\r
+               return $sql;\r
+       }\r
+}\r
+*/\r
+//---------------------------------------------------------------------\r
+class ContentTable extends AbstractTable {\r
+       var $tableName = 'content';\r
+\r
+       var $primaryIDField = 'content_id';\r
+\r
+       var $ordering;\r
+\r
+       /**\r
+       * Constructor.\r
+       * \r
+       * @param string $version The backup version.\r
+       * @param resource $db The database handler.\r
+       * @param int $course_id The ID of this course.\r
+       * @param string $import_dir The directory where the backup was unzipped to.\r
+       * @param array $old_id_to_new_id Reference to either the parent ID's or to store current ID's.\r
+       * \r
+       */\r
+       function ContentTable($version, $db, $course_id, $import_dir, &$old_id_to_new_id) {\r
+               // special case for `content` -- we need the max ordering\r
+\r
+               $sql        = 'SELECT MAX(ordering) AS ordering FROM '.TABLE_PREFIX.'content WHERE content_parent_id=0 AND course_id='.$course_id;\r
+               $result     = mysql_query($sql, $db);\r
+               $ordering   = mysql_fetch_assoc($result);\r
+               $this->ordering = $ordering['ordering'] +1;\r
+\r
+               parent::AbstractTable($version, $db, $course_id, $import_dir, $old_id_to_new_id);\r
+       }\r
+\r
+       function getOldID($row) {\r
+               return $row[0];\r
+       }\r
+\r
+       // private\r
+       function convert($row) {\r
+               return $row;\r
+       }\r
+\r
+       // private\r
+       function generateSQL($row) {\r
+               $sql = 'INSERT INTO '.TABLE_PREFIX.'content VALUES ';\r
+               $sql .= '('.$row['new_id'].','; // content_id\r
+               $sql .= $this->course_id .',';  // course_id\r
+               if ($row[1] == 0) { // content_parent_id\r
+                       $sql .= 0;\r
+               } else {\r
+                       $sql .= $this->getNewID($row[1]);\r
+               }\r
+               $sql .= ',';\r
+\r
+               if ($row[1] == 0) {\r
+                       // find the new ordering:\r
+                       $sql .= $this->ordering . ',';\r
+                       $this->ordering ++;\r
+               } else {\r
+                       $sql .= $row[2].',';\r
+               }\r
+\r
+               $sql .= "'".$row[3]."',";    // last_modified\r
+               $sql .= $row[4] . ',';       // revision\r
+               $sql .= $row[5] . ',';       // formatting\r
+               $sql .= "'".$row[6]."',";    // release_date\r
+               $sql .= "'".$row[7]."',";    // keywords\r
+               $sql .= "'".$row[8]."',";    // content_path\r
+               $sql .= "'".$row[9]."',";    // title\r
+               $sql .= "'".$row[10]."',0)"; // text\r
+\r
+               return $sql;\r
+       }\r
+}\r
+\r
+//---------------------------------------------------------------------\r
+class RelatedContentTable extends AbstractTable {\r
+       var $tableName = 'related_content';\r
+\r
+       var $primaryIDField = 'content_id';\r
+\r
+       function getOldID($row) {\r
+               return FALSE;\r
+       }\r
+\r
+       // private\r
+       function convert($row) {\r
+               return $row;\r
+       }\r
+\r
+       // private\r
+       function generateSQL($row) {\r
+               $sql = 'INSERT INTO '.TABLE_PREFIX.'related_content VALUES ';\r
+               $sql .= '('.$this->old_ids_to_new_ids['content'][$row['0']].','. $this->old_ids_to_new_ids['content'][$row[1]].')';\r
+\r
+               return $sql;\r
+       }\r
+}\r
+\r
+//---------------------------------------------------------------------\r
+class CourseStatsTable extends AbstractTable {\r
+       var $tableName = 'course_stats';\r
+       var $primaryIDField = 'login_date'; // never actually used\r
+\r
+       function getOldID($row) {\r
+               return FALSE;\r
+       }\r
+\r
+       function getParentID($row) {\r
+               return FALSE;\r
+       }\r
+\r
+       // private\r
+       function convert($row) {\r
+               return $row;\r
+       }\r
+\r
+       // private\r
+       function generateSQL($row) {\r
+               // insert row\r
+               $sql = 'INSERT INTO '.TABLE_PREFIX.'course_stats VALUES ';\r
+               $sql .= '('.$this->course_id.",";\r
+               $sql .= "'".$row[0]."',"; // login_date\r
+               $sql .= "'".$row[1]."',"; // guests\r
+               $sql .= "'".$row[2]."'";  // members\r
+               $sql .= ')';\r
+\r
+               return $sql;\r
+       }\r
+}\r
+\r
+//---------------------------------------------------------------------\r
+class GroupsTable extends AbstractTable {\r
+       var $tableName = 'groups';\r
+       var $primaryIDField = 'group_id';\r
+\r
+       function getOldID($row) {\r
+               return FALSE;\r
+       }\r
+\r
+       function getParentID($row) {\r
+               return FALSE;\r
+       }\r
+\r
+       // private\r
+       function convert($row) {\r
+               return $row;\r
+       }\r
+\r
+       // private\r
+       function generateSQL($row) {\r
+               // insert row\r
+               $sql = 'INSERT INTO '.TABLE_PREFIX.'groups VALUES ';\r
+               $sql .= '('.$row['new_id'] . ',' . $this->course_id.",";\r
+               $sql .= "'".$row[0]."'"; // title\r
+               $sql .= ')';\r
+\r
+               return $sql;\r
+       }\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/include/classes/CSVExport.class.php b/include/classes/CSVExport.class.php
new file mode 100644 (file)
index 0000000..20b98f6
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+class CSVExport {
+//     var $quote_search  = array('"',  "\n", "\r", "\x00");
+//     var $quote_replace = array('""', '\n', '\r', '\0');
+       var $quote_search  = array("\n", "\r", "\x00");
+       var $quote_replace = array('\n', '\r', '\0');
+
+       // constructor
+       function CSVExport() { }
+
+       // public
+       function export($sql, $course_id) {
+               global $db;
+               $sql = str_replace('?', $course_id , $sql);
+
+               $content = '';
+
+               $result = mysql_query($sql, $db);
+
+               $field_types = $this->detectFieldTypes($result);
+               if (!$field_types) {
+                       return FALSE;
+               }
+               $num_fields = count($field_types);
+
+               while ($row = mysql_fetch_row($result)) {
+                       for ($i=0; $i < $num_fields; $i++) {
+                               if ($types[$i] == 'int' || $types[$i] == 'real') {
+                                       $content .= $row[$i] . ',';
+                               } else {
+                                       $content .= $this->quote($row[$i]) . ',';
+                               }
+                       }
+                       $content = substr($content, 0, -1);
+                       $content .= "\n";
+               }
+               
+               @mysql_free_result($result);
+
+               return $content;
+       }
+
+       // public
+       // given a query result returns an array of field types.
+       // possible field types are int, string, datetime, or blob...
+       function detectFieldTypes(&$result) {
+               $field_types = array();
+               $num_fields = @mysql_num_fields($result);
+
+               if (!$num_fields) {
+                       return array();
+               }
+
+               for ($i=0; $i< $num_fields; $i++) {
+                       $field_types[] = mysql_field_type($result, $i);
+               }
+               return $field_types;
+       }
+
+       // private
+       // quote $line so that it's safe to save as a CSV field
+       function quote($line) {
+               return '"'.str_replace($this->quote_search, $this->quote_replace, $line).'"';
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/include/classes/CSVImport.class.php b/include/classes/CSVImport.class.php
new file mode 100644 (file)
index 0000000..d3a07cb
--- /dev/null
@@ -0,0 +1,160 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+class CSVImport {
+       var $quote_search  = array('\\\n', '\\\r');
+       var $quote_replace = array('\n', '\r');
+
+       // constructor
+       function CSVImport() { }
+
+       // public
+       // returns the primary_key, or false if there is none, or null if more than 1
+       function getPrimaryFieldName($table_name) {
+               global $db;
+
+               $field = false;
+
+               $sql = "SELECT * FROM ".TABLE_PREFIX.$table_name .' WHERE 0';
+               $result = mysql_query($sql, $db);
+               $num_fields = mysql_num_fields($result);
+               for ($i= 0; $i<$num_fields; $i++) {
+                       $flags = explode(' ', mysql_field_flags($result, $i));
+                       if (in_array('primary_key', $flags)) {
+                               if ($field == false) {
+                                       $field = mysql_field_name($result, $i);
+                               } else {
+                                       // there is more than one primary_key
+                                       return NULL;
+                               }
+                       }
+               }
+               return $field;
+       }
+
+
+       // public
+       // given a query result returns an array of field types.
+       // possible field types are int, string, datetime, or blob...
+       function detectFieldTypes($table_name) {
+               global $db;
+
+               $field_types = array();
+
+               $sql = "SELECT * FROM ".TABLE_PREFIX.$table_name .' WHERE 0';
+               $result = @mysql_query($sql, $db);
+               if (!$result) {
+                       return array();
+               }
+               $num_fields = mysql_num_fields($result);
+
+               for ($i=0; $i< $num_fields; $i++) {
+                       $field_types[] = mysql_field_type($result, $i);
+               }
+
+               return $field_types;
+       }
+
+       function translateWhitespace($input) {
+               $input = addslashes($input);
+               $input = str_replace($this->quote_search, $this->quote_replace, $input);
+
+               return $input;
+       }
+
+       // public
+       function import($tableName, $path, $course_id, $version) {
+               global $db;
+               static $table_id_map;
+
+               $fn_name = $tableName.'_convert';
+
+               // lock the tables
+               $lock_sql = 'LOCK TABLES ' . TABLE_PREFIX . $tableName. ', ' . TABLE_PREFIX . 'courses WRITE';
+               $result   = mysql_query($lock_sql, $db);
+
+               // get the field types
+               $field_types = $this->detectFieldTypes($tableName);
+               if (!$field_types) {
+                       return FALSE;
+               }
+
+               // get the name of the primary field
+               $primary_key_field_name = $this->getPrimaryFieldName($tableName);
+               // read the rows into an array
+               $fp = @fopen($path . $tableName . '.csv', 'rb');
+               $i = 0;
+
+               // get the name of the primary ID field and the next index
+               $next_id = 0;
+               if ($primary_key_field_name) {
+                       // get the next primary ID
+                       $sql     = 'SELECT MAX(' . $primary_key_field_name . ') AS next_id FROM ' . TABLE_PREFIX . $tableName;
+                       $result  = mysql_query($sql, $db);
+                       $next_id = mysql_fetch_assoc($result);
+                       $next_id = $next_id['next_id']+1;
+               }
+
+               $rows = array();
+               while ($row = @fgetcsv($fp, 70000)) {
+                       if (count($row) && (trim($row[0]) == '')) {
+                               continue;
+                       }
+
+                       if (function_exists($fn_name)) {
+                               $row = $fn_name($row, $course_id, $table_id_map, $version);
+                       }
+                       if (!$row) {
+                               continue;
+                       }
+                       if ($row[0] == 0) {
+                               $row[0] = $i;
+                       }
+
+                       $table_id_map[$tableName][$row[0]] = $next_id;
+                       if ($primary_key_field_name != NULL) {
+                               $row[0] = $next_id;
+                       }
+
+                       $sql = 'REPLACE INTO '.TABLE_PREFIX.$tableName.' VALUES (';
+
+                       foreach($row as $id => $field) {
+                               if (($field_types[$id] != 'int') && ($field_types[$id] != 'real')) {
+                                       $field = $this->translateWhitespace($field);
+                               } else if ($field_types[$id] == 'int') {
+                                       $field = intval($field);
+                               }
+                               $sql .= "'" . $field."',";
+                       }
+                       $sql = substr($sql, 0, -1);
+                       $sql .= ')';
+
+                       $result = mysql_query($sql, $db);
+                       $i++;
+                       $next_id++;
+               }
+
+               // close the file
+               @fclose($fp);
+
+               // unlock the tables
+               $lock_sql = 'UNLOCK TABLES';
+               $result   = mysql_query($lock_sql, $db);
+       }
+
+}
+
+
+
+?>
\ No newline at end of file
diff --git a/include/classes/ContentManager.class.php b/include/classes/ContentManager.class.php
new file mode 100644 (file)
index 0000000..0306c3d
--- /dev/null
@@ -0,0 +1,951 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+class ContentManager
+{
+       /* db handler   */
+       var $db;
+
+       /*      array           */
+       var $_menu;
+
+       /*      array           */
+       var $_menu_info;
+
+       /* int                  */
+       var $course_id;
+
+       // private
+       var $num_sections;
+
+       // private
+       var $max_depth;
+
+       // private
+       var $content_length;
+
+       /* constructor  */
+       function ContentManager(&$db, $course_id) {
+               $this->db = $db;
+               $this->course_id = $course_id;
+       }
+
+       function initContent( ) {
+               if (!($this->course_id > 0)) {
+                       return;
+               }
+               $sql = "SELECT content_id, content_parent_id, ordering, title, UNIX_TIMESTAMP(release_date) AS u_release_date FROM ".TABLE_PREFIX."content WHERE course_id=$this->course_id ORDER BY content_parent_id, ordering";
+               $result = mysql_query($sql, $this->db);
+
+               /* x could be the ordering or even the content_id       */
+               /* don't really need the ordering anyway.                       */
+               /* $_menu[content_parent_id][x] = array('content_id', 'ordering', 'title') */
+               $_menu = array();
+
+               /* number of content sections */
+               $num_sections = 0;
+
+               $max_depth = array();
+               $_menu_info = array();
+
+               while ($row = mysql_fetch_assoc($result)) {
+                       $num_sections++;
+                       $_menu[$row['content_parent_id']][] = array('content_id'=> $row['content_id'],
+                                                                                                               'ordering'      => $row['ordering'], 
+                                                                                                               'title'         => htmlspecialchars($row['title']));
+
+                       $_menu_info[$row['content_id']] = array('content_parent_id' => $row['content_parent_id'],
+                                                                                                       'title'                         => htmlspecialchars($row['title']),
+                                                                                                       'ordering'                      => $row['ordering'],
+                                                                                                       'u_release_date'      => $row['u_release_date']);
+
+                       if ($row['content_parent_id'] == 0){
+                               $max_depth[$row['content_id']] = 1;
+                       } else {
+                               $max_depth[$row['content_id']] = $max_depth[$row['content_parent_id']]+1;
+                       }
+               }
+
+               $this->_menu = $_menu;
+
+               $this->_menu_info =  $_menu_info;
+
+               $this->num_sections = $num_sections;
+
+               if (count($max_depth) > 1) {
+                       $this->max_depth = max($max_depth);
+               } else {
+                       $this->max_depth = 0;
+               }
+
+               $this->content_length = count($_menu[0]);
+       }
+
+
+       function getContent($parent_id=-1, $length=-1) {
+               if ($parent_id == -1) {
+                       $my_menu_copy = $this->_menu;
+                       if ($length != -1) {
+                               $my_menu_copy[0] = array_slice($my_menu_copy[0], 0, $length);
+                       }
+                       return $my_menu_copy;
+               }
+               return $this->_menu[$parent_id];
+       }
+
+
+       function &getContentPath($content_id) {
+               $path = array();
+
+               $path[] = array('content_id' => $content_id, 'title' => $this->_menu_info[$content_id]['title']);
+
+               $this->getContentPathRecursive($content_id, $path);
+
+               $path = array_reverse($path);
+               return $path;
+       }
+
+
+       function getContentPathRecursive($content_id, &$path) {
+               $parent_id = $this->_menu_info[$content_id]['content_parent_id'];
+
+               if ($parent_id > 0) {
+                       $path[] = array('content_id' => $parent_id, 'title' => $this->_menu_info[$parent_id]['title']);
+                       $this->getContentPathRecursive($parent_id, $path);
+               }
+       }
+
+
+       function addContent($course_id, $content_parent_id, $ordering, $title, $text, $keywords, $related, $formatting, $release_date, $head = '', $use_customized_head = 0) {
+               
+               if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && ($_SESSION['course_id'] != -1)) {
+                       return false;
+               }
+
+               // shift the new neighbouring content down
+               $sql = "UPDATE ".TABLE_PREFIX."content SET ordering=ordering+1 WHERE ordering>=$ordering AND content_parent_id=$content_parent_id AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $this->db);
+
+               /* main topics all have minor_num = 0 */
+               $sql = "INSERT INTO ".TABLE_PREFIX."content
+                              (course_id,
+                               content_parent_id,
+                               ordering,
+                               last_modified,
+                               revision,
+                               formatting,
+                               release_date,
+                               head,
+                               use_customized_head,
+                               keywords,
+                               content_path,
+                               title,
+                               text)
+                       VALUES ($course_id, 
+                               $content_parent_id, 
+                               $ordering, 
+                               NOW(), 
+                               0, 
+                               $formatting, 
+                               '$release_date', 
+                               '$head',
+                               $use_customized_head,
+                               '$keywords', 
+                               '', 
+                               '$title',
+                               '$text')";
+
+               $err = mysql_query($sql, $this->db);
+
+               /* insert the related content */
+               $sql = "SELECT LAST_INSERT_ID() AS insert_id";
+               $result = mysql_query($sql, $this->db);
+               $row = mysql_fetch_assoc($result);
+               $cid = $row['insert_id'];
+
+               $sql = '';
+               if (is_array($related)) {
+                       foreach ($related as $x => $related_content_id) {
+                               $related_content_id = intval($related_content_id);
+
+                               if ($related_content_id != 0) {
+                                       if ($sql != '') {
+                                               $sql .= ', ';
+                                       }
+                                       $sql .= '('.$cid.', '.$related_content_id.')';
+                                       $sql .= ', ('.$related_content_id.', '.$cid.')';
+                               }
+                       }
+
+                       if ($sql != '') {
+                               $sql    = 'INSERT INTO '.TABLE_PREFIX.'related_content VALUES '.$sql;
+                               $result = mysql_query($sql, $this->db);
+                       }
+               }
+
+               return $cid;
+       }
+
+
+       function editContent($content_id, $title, $text, $keywords, $new_content_ordering, $related, $formatting, $new_content_parent_id, $release_date, $head, $use_customized_head) {
+               if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
+                       return FALSE;
+               }
+
+               /* first get the content to make sure it exists */
+               $sql    = "SELECT ordering, content_parent_id FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $this->db);
+               if (!($row = mysql_fetch_assoc($result)) ) {
+                       return FALSE;
+               }
+               $old_ordering           = $row['ordering'];
+               $content_parent_id      = $row['content_parent_id'];
+               if (($content_parent_id != $new_content_parent_id) || ($old_ordering != $new_content_ordering)) {
+                       // remove the gap left by the moved content
+                       $sql = "UPDATE ".TABLE_PREFIX."content SET ordering=ordering-1 WHERE ordering>=$old_ordering AND content_parent_id=$content_parent_id AND content_id<>$content_id AND course_id=$_SESSION[course_id]";
+                       $result = mysql_query($sql, $this->db);
+
+                       // shift the new neighbouring content down
+                       $sql = "UPDATE ".TABLE_PREFIX."content SET ordering=ordering+1 WHERE ordering>=$new_content_ordering AND content_parent_id=$new_content_parent_id AND content_id<>$content_id AND course_id=$_SESSION[course_id]";
+                       $result = mysql_query($sql, $this->db);
+               }
+
+               /* update the title, text of the newly moved (or not) content */
+               $sql    = "UPDATE ".TABLE_PREFIX."content SET title='$title', head='$head', use_customized_head=$use_customized_head, text='$text', keywords='$keywords', formatting=$formatting, content_parent_id=$new_content_parent_id, ordering=$new_content_ordering, revision=revision+1, last_modified=NOW(), release_date='$release_date' WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $this->db);
+
+               /* update the related content */
+               $result = mysql_query("DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id", $this->db);
+               $sql = '';
+               if (is_array($related)) {
+                       foreach ($related as $x => $related_content_id) {
+                               $related_content_id = intval($related_content_id);
+
+                               if ($related_content_id != 0) {
+                                       if ($sql != '') {
+                                               $sql .= ', ';
+                                       }
+                                       $sql .= '('.$content_id.', '.$related_content_id.')';
+                                       $sql .= ', ('.$related_content_id.', '.$content_id.')';
+                               }
+                       }
+
+                       if ($sql != '') {
+                               /* delete the old related content */
+                               $result = mysql_query("DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id", $this->db);
+
+                               /* insert the new, and the old related content again */
+                               $sql    = 'INSERT INTO '.TABLE_PREFIX.'related_content VALUES '.$sql;
+                               $result = mysql_query($sql, $this->db);
+                       }
+               }
+       }
+
+
+       function deleteContent($content_id) {
+               if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
+                       return false;
+               }
+
+               /* check if exists */
+               $sql    = "SELECT ordering, content_parent_id FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $this->db);
+               if (!($row = @mysql_fetch_assoc($result)) ) {
+                       return false;
+               }
+               $ordering                       = $row['ordering'];
+               $content_parent_id      = $row['content_parent_id'];
+
+               /* check if this content has sub content        */
+               $children = $this->_menu[$content_id];
+
+               if (is_array($children) && (count($children)>0) ) {
+                       /* delete its children recursively first*/
+                       foreach ($children as $x => $info) {
+                               $this->deleteContentRecursive($info['content_id']);
+                       }
+               }
+
+               /* delete this content page                                     */
+               $sql    = "DELETE FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $this->db);
+
+               /* delete this content from member tracking page        */
+               $sql    = "DELETE FROM ".TABLE_PREFIX."member_track WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $this->db);
+
+               $sql    = "DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id";
+               $result = mysql_query($sql, $this->db);
+
+               /* re-order the rest of the content */
+               $sql = "UPDATE ".TABLE_PREFIX."content SET ordering=ordering-1 WHERE ordering>=$ordering AND content_parent_id=$content_parent_id AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $this->db);
+               /* end moving block */
+
+               /* remove the "resume" to this page, b/c it was deleted */
+               $sql = "UPDATE ".TABLE_PREFIX."course_enrollment SET last_cid=0 WHERE course_id=$_SESSION[course_id] AND last_cid=$content_id";
+               $result = mysql_query($sql, $this->db);
+
+               return true;
+       }
+
+
+       /* private. call from deleteContent only. */
+       function deleteContentRecursive($content_id) {
+               /* check if this content has sub content        */
+               $children = $this->_menu[$content_id];
+
+               if (is_array($children) && (count($children)>0) ) {
+                       /* delete its children recursively first*/
+                       foreach ($children as $x => $info) {
+                               $this->deleteContent($info['content_id']);
+                       }
+               }
+
+               /* delete this content page                                     */
+               $sql    = "DELETE FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $this->db);
+
+               /* delete this content from member tracking page        */
+               $sql    = "DELETE FROM ".TABLE_PREFIX."member_track WHERE content_id=$content_id";
+               $result = mysql_query($sql, $this->db);
+
+               $sql    = "DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id";
+               $result = mysql_query($sql, $this->db);
+       }
+
+       function & getContentPage($content_id) {
+               $sql    = "SELECT *, DATE_FORMAT(release_date, '%Y-%m-%d %H:%i:00') AS release_date, release_date+0 AS r_date, NOW()+0 AS n_date FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$this->course_id";
+               $result = mysql_query($sql, $this->db);
+
+               return $result;
+       }
+       
+       /* @See editor/edit_content.php include/html/dropdowns/related_topics.inc.php include/lib/editor_tabs_functions.inc.php */
+       function getRelatedContent($content_id, $all=false) {
+               if ($content_id == 0) {
+                       return;
+               }
+               if ($content_id == '') {
+                       return;
+               }
+               $related_content = array();
+
+               if ($all) {
+                       $sql = "SELECT * FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id";
+               } else {
+                       $sql = "SELECT * FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id";
+               }
+               $result = mysql_query($sql, $this->db);
+
+               while ($row = mysql_fetch_assoc($result)) {
+                       if ($row['related_content_id'] != $content_id) {
+                               $related_content[] = $row['related_content_id'];
+                       } else {
+                               $related_content[] = $row['content_id'];
+                       }
+               }
+
+               return $related_content;
+       }
+
+
+       function & cleanOutput($value) {
+               return stripslashes(htmlspecialchars($value));
+       }
+
+
+       /* @See include/html/editor_tabs/properties.inc.php */
+       /* Access: Public */
+       function getNumSections() {
+               return $this->num_sections;
+       }
+
+       /* Access: Public */
+       function getMaxDepth() {
+               return $this->max_depth;
+       }
+
+       /* Access: Public */
+       function getContentLength() {
+               return $this->content_length;
+       }
+
+       /* @See include/html/dropdowns/local_menu.inc.php */
+       function getLocationPositions($parent_id, $content_id) {
+               $siblings = $this->getContent($parent_id);
+               for ($i=0;$i<count($siblings); $i++){
+                       if ($siblings[$i]['content_id'] == $content_id) {
+                               return $i;
+                       }
+               }
+               return 0;       
+       }
+
+       /* Access: Private */
+       function getNumbering($content_id) {
+               $path = $this->getContentPath($content_id);
+               $parent = 0;
+               $numbering = '';
+               foreach ($path as $page) {
+                       $num = $this->getLocationPositions($parent, $page['content_id']) +1;
+                       $parent = $page['content_id'];
+                       $numbering .= $num.'.';
+               }
+               $numbering = substr($numbering, 0, -1);
+
+               return $numbering;
+       }
+
+       /* Access: Private */
+       function getPreviousContent($content_id, $order=0) {
+               $myParent = $this->_menu_info[$content_id]['content_parent_id'];
+               $myOrder  = $this->_menu_info[$content_id]['ordering'];
+
+               if (isset($this->_menu[$myParent][$myOrder-2]) && ($this->_menu[$myParent][$myOrder-2] != '') && ($order==0)) {
+                       // has sibling: checking if sibling has children
+                       
+                       $mySibling = $this->_menu[$myParent][$myOrder-2];
+                       
+                       if ( isset($this->_menu[$mySibling['content_id']]) && is_array($this->_menu[$mySibling['content_id']]) && ($order==0) ) {
+                               $num_children = count($this->_menu[$mySibling['content_id']]);
+
+                               // sibling has $num_children children
+                               return($this->getPreviousContent($this->_menu[$mySibling['content_id']][$num_children-1]['content_id'], 1));
+
+                       } else {
+                               // sibling has no children. return it
+                               return($this->_menu[$myParent][$myOrder-2]);
+                       }
+
+               } else {
+                       if ($myParent == 0) {
+                               /* we're at the top */
+                               return '';
+                       }
+
+                       /* No more siblings */
+                       if ($order == 0) {
+                               return(array('content_id'       => $myParent,
+                                                        'ordering'             => $this->_menu_info[$myParent]['ordering'],
+                                                        'title'                => $this->_menu_info[$myParent]['title']));
+                       } else {
+                               if ( isset($this->_menu[$content_id]) && is_array($this->_menu[$content_id]) ) {
+                                       $num_children = count($this->_menu[$content_id]);
+                                       return ($this->getPreviousContent($this->_menu[$content_id][$num_children-1]['content_id'], 1));
+
+                               } else {
+                                       /* no children */
+                                       return(array('content_id'       => $content_id,
+                                                                'ordering'             => $this->_menu_info[$content_id]['ordering'],
+                                                                'title'                => $this->_menu_info[$content_id]['title']));
+                               }
+                       }
+               }
+       }
+
+       /* Access: Private */
+       function getNextContent($content_id, $order=0) {
+               if (!$content_id) { return; }
+
+               $myParent = $this->_menu_info[$content_id]['content_parent_id'];
+               $myOrder  = $this->_menu_info[$content_id]['ordering'];
+               /* if this content has children, then take the first one. */
+               if ( isset($this->_menu[$content_id]) && is_array($this->_menu[$content_id]) && ($order==0) ) {
+                       /* has children */
+                       return($this->_menu[$content_id][0]);
+               } else {
+                       /* no children */
+                       if (isset($this->_menu[$myParent][$myOrder]) && $this->_menu[$myParent][$myOrder] != '') {
+                               /* Has sibling */
+                               return($this->_menu[$myParent][$myOrder]);
+                       } else {
+                               /* No more siblings */
+                               if ($myParent != 0) {
+                                       return($this->getNextContent($myParent, 1));
+                               }
+                       }
+               }
+       }
+
+       /* @See include/header.inc.php */
+       function generateSequenceCrumbs($cid) {
+               global $_base_path;
+
+               $sequence_links = array();
+
+               $first = $this->getNextContent(0); // get first
+               if ($_SESSION['prefs']['PREF_NUMBERING'] && $first) {
+                       $first['title'] = $this->getNumbering($first['content_id']).' '.$first['title'];
+               }
+               if ($first) {
+                       $first['url'] = $_base_path.url_rewrite('content.php?cid='.$first['content_id']);
+                       $sequence_links['first'] = $first;
+               }
+
+               if (!$cid && $_SESSION['s_cid']) {
+                       $resume['title'] = $this->_menu_info[$_SESSION['s_cid']]['title'];
+
+                       if ($_SESSION['prefs']['PREF_NUMBERING']) {
+                               $resume['title'] = $this->getNumbering($_SESSION['s_cid']).' ' . $resume['title'];
+                       }
+
+                       $resume['url'] = $_base_path.url_rewrite('content.php?cid='.$_SESSION['s_cid']);
+
+                       $sequence_links['resume'] = $resume;
+               } else {
+                       if ($cid) {
+                               $previous = $this->getPreviousContent($cid);
+                       }
+                       $next = $this->getNextContent($cid ? $cid : 0);
+
+                       if ($_SESSION['prefs']['PREF_NUMBERING']) {
+                               $previous['title'] = $this->getNumbering($previous['content_id']).' '.$previous['title'];
+                               $next['title'] = $this->getNumbering($next['content_id']).' '.$next['title'];
+                       }
+
+                       $next['url'] = $_base_path.url_rewrite('content.php?cid='.$next['content_id']);
+                       if (isset($previous['content_id'])) {
+                               $previous['url'] = $_base_path.url_rewrite('content.php?cid='.$previous['content_id']);
+                       }
+                       
+                       if (isset($previous['content_id'])) {
+                               $sequence_links['previous'] = $previous;
+                       } else if ($cid) {
+                               $previous['url']   = $_base_path . url_rewrite('index.php');
+                               $previous['title'] = _AT('home');
+                               $sequence_links['previous'] = $previous;
+                       }
+                       if (!empty($next['content_id'])) {
+                               $sequence_links['next'] = $next;
+                       }
+               }
+
+               return $sequence_links;
+       }
+
+       /* @See include/html/dropdowns/menu_menu.inc.php */
+       function printMainMenu( ) {
+               $parent_id    = 0;
+               $depth        = 0;
+               $path         = '';
+               $children     = array();
+               $truncate     = true;
+               $ignore_state = false;
+
+               $this->start = true;
+               $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
+       }
+
+       /* @See tools/sitemap/index.php */
+       function printSiteMapMenu() {
+               $parent_id    = 0;
+               $depth        = 1;
+               $path         = '';
+               $children     = array();
+               $truncate     = false;
+               $ignore_state = true;
+
+               $this->start = true;
+               $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
+       }
+
+       /* @See index.php */
+       function printTOCMenu($cid, $top_num) {
+               $parent_id    = $cid;
+               $depth        = 1;
+               $path         = $top_num.'.';
+               $children     = array();
+               $truncate     = false;
+               $ignore_state = false;
+
+               $this->start = true;
+               $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
+       }
+
+       /* @See index.php include/html/dropdowns/local_menu.inc.php */
+       function printSubMenu($cid, $top_num) {
+               $parent_id    = $cid;
+               $depth        = 1;
+               $path         = $top_num.'.';
+               $children     = array();
+               $truncate     = true;
+               $ignore_state = false;
+       
+               $this->start = true;
+               $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
+       }
+
+       /* @See include/html/menu_menu.inc.php  */
+       /* Access: PRIVATE */
+       function printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state) {
+               
+               global $cid, $_my_uri, $_base_path, $rtl, $substr, $strlen;
+               static $temp_path;
+
+               if (!isset($temp_path)) {
+                       if ($cid) {
+                               $temp_path      = $this->getContentPath($cid);
+                       } else {
+                               $temp_path      = $this->getContentPath($_SESSION['s_cid']);
+                       }
+               }
+
+               $highlighted = array();
+               if (is_array($temp_path)) {
+                       foreach ($temp_path as $temp_path_item) {
+                               $_SESSION['menu'][$temp_path_item['content_id']] = 1;
+                               $highlighted[$temp_path_item['content_id']] = true;
+                       }
+               }
+
+               if ($this->start) {
+                       reset($temp_path);
+                       $this->start = false;
+               }
+
+               if ( isset($this->_menu[$parent_id]) && is_array($this->_menu[$parent_id]) ) {
+                       $top_level = $this->_menu[$parent_id];
+                       $counter = 1;
+                       $num_items = count($top_level);
+                       foreach ($top_level as $garbage => $content) {
+                               $link = '';
+                               if (!$ignore_state) {
+                                       $link .= '<a name="menu'.$content['content_id'].'"></a>';
+                               }
+
+                               $on = false;
+
+                               if ( ($_SESSION['s_cid'] != $content['content_id']) || ($_SESSION['s_cid'] != $cid) ) {
+                                       if (isset($highlighted[$content['content_id']])) {
+                                               $link .= '<strong>';
+                                               $on = true;
+                                       }
+
+                                       $link .= ' <a href="'.$_base_path.url_rewrite('content.php?cid='.$content['content_id']).'" title="';
+                                       if ($_SESSION['prefs']['PREF_NUMBERING']) {
+                                               $link .= $path.$counter.' ';
+                                       }
+
+                                       $link .= $content['title'].'">';
+
+                                       if ($truncate && ($strlen($content['title']) > (28-$depth*4)) ) {
+                                               $content['title'] = rtrim($substr($content['title'], 0, (28-$depth*4)-4)).'...';
+                                       }
+                                       $link .= $content['title'];
+                                       $link .= '</a>';
+                                       if ($on) {
+                                               $link .= '</strong>';
+                                       }
+                               } else {
+                                       $link .= '<a href="'.$_my_uri.'"><img src="'.$_base_path.'images/clr.gif" alt="'._AT('you_are_here').': '.$content['title'].'" height="1" width="1" border="0" /></a><strong title="'.$content['title'].'">'."\n";
+                                       if ($truncate && ($strlen($content['title']) > (26-$depth*4)) ) {
+                                               $content['title'] = rtrim($substr($content['title'], 0, (26-$depth*4)-4)).'...';
+                                       }
+                                       $link .= trim($content['title']).'</strong>';
+                                       $on = true;
+                               }
+
+                               if ($ignore_state) {
+                                       $on = true;
+                               }
+
+                               if ( isset($this->_menu[$content['content_id']]) && is_array($this->_menu[$content['content_id']]) ) {
+                                       /* has children */
+                                       for ($i=0; $i<$depth; $i++) {
+                                               if ($children[$i] == 1) {
+                                                       echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
+                                               } else {
+                                                       echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
+                                               }
+                                       }
+
+                                       if (($counter == $num_items) && ($depth > 0)) {
+                                               echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
+                                               $children[$depth] = 0;
+                                       } else if ($counter == $num_items) {
+                                               echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
+                                               $children[$depth] = 0;
+                                       } else {
+                                               echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
+                                               $children[$depth] = 1;
+                                       }
+
+                                       if ($_SESSION['s_cid'] == $content['content_id']) {
+                                               if (is_array($this->_menu[$content['content_id']])) {
+                                                       $_SESSION['menu'][$content['content_id']] = 1;
+                                               }
+                                       }
+
+                                       if (isset($_SESSION['menu'][$content['content_id']]) && $_SESSION['menu'][$content['content_id']] == 1) {
+                                               if ($on) {
+                                                       echo '<img src="'.$_base_path.'images/tree/tree_disabled.gif" alt="'._AT('toggle_disabled').'" border="0" width="16" height="16" title="'._AT('toggle_disabled').'" class="img-size-tree" />'."\n";
+
+                                               } else {
+                                                       echo '<a href="'.$_my_uri.'collapse='.$content['content_id'].'">'."\n";
+                                                       echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_collapse.gif" alt="'._AT('collapse').'" border="0" width="16" height="16" title="'._AT('collapse').' '.$content['title'].'" class="img-size-tree" />'."\n";
+                                                       echo '</a>'."\n";
+                                               }
+                                       } else {
+                                               if ($on) {
+                                                       echo '<img src="'.$_base_path.'images/tree/tree_disabled.gif" alt="'._AT('toggle_disabled').'" border="0" width="16" height="16" title="'._AT('toggle_disabled').'" class="img-size-tree" />'."\n";
+
+                                               } else {
+                                                       echo '<a href="'.$_my_uri.'expand='.$content['content_id'].'">'."\n";
+                                                       echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_expand.gif" alt="'._AT('expand').'" border="0" width="16" height="16"   title="'._AT('expand').' '.$content['title'].'" class="img-size-tree" />';
+                                                       echo '</a>'."\n";
+                                               }
+                                       }
+
+                               } else {
+                                       /* doesn't have children */
+                                       if ($counter == $num_items) {
+                                               for ($i=0; $i<$depth; $i++) {
+                                                       if ($children[$i] == 1) {
+                                                               echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
+                                                       } else {
+                                                               echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
+                                                       }
+                                               }
+                                               echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" class="img-size-tree" />'."\n";
+                                       } else {
+                                               for ($i=0; $i<$depth; $i++) {
+                                                       if ($children[$i] == 1) {
+                                                               echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
+                                                       } else {
+                                                               echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_space.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
+                                                       }
+                                               }
+                                               echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
+                                       }
+                                       echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_horizontal.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
+                               }
+
+                               if ($_SESSION['prefs']['PREF_NUMBERING']) {
+                                       echo $path.$counter;
+                               }
+                               
+                               echo $link;
+                               
+                               echo '<br />';
+
+                               if ( $ignore_state || (isset($_SESSION['menu'][$content['content_id']]) && $_SESSION['menu'][$content['content_id']] == 1)) {
+
+                                       $depth ++;
+
+                                       $this->printMenu($content['content_id'],
+                                                                               $depth, 
+                                                                               $path.$counter.'.', 
+                                                                               $children,
+                                                                               $truncate, 
+                                                                               $ignore_state);
+
+                                                                               
+                                       $depth--;
+
+                               }
+                               $counter++;
+                       }
+               }
+       }
+
+       /* @See include/html/editor_tabs/properties.inc.php */
+       function printMoveMenu($menu, $parent_id, $depth, $path, $children) {
+               
+               global $cid, $_my_uri, $_base_path, $rtl;
+
+               static $end, $ignore;
+
+               $top_level = $menu[$parent_id];
+
+               if ( is_array($top_level) ) {
+                       $counter = 1;
+                       $num_items = count($top_level);
+                       foreach ($top_level as $garbage => $content) {
+
+                               $link = ' ';
+
+                               echo '<tr>';
+
+                               if (($parent_id == $_POST['new_pid']) && ($content['ordering'] < $_POST['new_ordering'])) {
+                                       $text = _AT('before_topic', $content['title']);
+                                       $img = 'before.gif';
+                               } else if ($parent_id != $_POST['new_pid']) {
+                                       $text = _AT('before_topic', $content['title']);
+                                       $img = 'before.gif';
+                               } else {
+                                       $text = _AT('after_topic', $content['title']);
+                                       $img = 'after.gif';
+                               }
+                               if ($ignore && ($_POST['cid'] > 0)) {
+                                       $buttons = '<td><small>&nbsp;</small></td><td><small>&nbsp;</small></td><td>';
+                               } else if ($_POST['new_pid'] == $content['content_id']) {
+                                       $buttons = '<td align="center"><small><input type="image" name="move['.$parent_id.'_'.$content['ordering'].']" src="'.$_base_path.'images/'.$img.'" alt="'.$text.'" title="'.$text.'" style="height:1.5em; width:1.9em;" /></small></td><td><small>&nbsp;</small></td><td>';
+                               } else {
+                                       $buttons = '<td align="center"><small><input type="image" name="move['.$parent_id.'_'.$content['ordering'].']" src="'.$_base_path.'images/'.$img.'" title="'.$text.'" style="height:1.5em; width:1.9em;" /></small></td><td><input type="image" name="move['.$content['content_id'].'_1]" src="'.$_base_path.'images/child_of.gif" style="height:1.25em; width:1.7em;" alt="'._AT('child_of', $content['title']).'" title="'._AT('child_of', $content['title']).'" /></td><td>';
+                               }
+
+                               if (( $content['content_id'] == $cid ) || ($content['content_id'] == -1)) {
+                                       $ignore = true;
+                                       $link .= '<strong>'.trim($_POST['title']).' '._AT('current_location').'</strong>';
+                                       $buttons = '<td colspan="2"><small>&nbsp;</small></td><td>';
+                               } else {
+                                       $link .= '<input type="checkbox" name="related[]" value="'.$content['content_id'].'" id="r'.$content['content_id'].'" ';
+                                       if (isset($_POST['related']) && in_array($content['content_id'], $_POST['related'])) {
+                                               $link .= ' checked="checked"';
+                                       }
+                                       $link .= ' /><label for="r'.$content['content_id'].'">'.$content['title'].'</label>';
+                               }
+
+                               if ( is_array($menu[$content['content_id']]) && !empty($menu[$content['content_id']]) ) {
+                                       /* has children */
+
+                                       for ($i=0; $i<$depth; $i++) {
+                                               if ($children[$i] == 1) {
+                                                       echo $buttons;
+                                                       unset($buttons);
+                                                       if ($end && ($i==0)) {
+                                                               echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
+                                                       } else {
+                                                               echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" />';
+                                                       }
+                                               } else {
+                                                       echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
+                                               }
+                                       }
+
+                                       if (($counter == $num_items) && ($depth > 0)) {
+                                               echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" width="16" height="16" />';
+                                               $children[$depth] = 0;
+                                       } else {
+                                               echo $buttons;
+                                               if (($num_items == $counter) && ($parent_id == 0)) {
+                                                       echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" width="16" height="16" />';
+                                                       $end = true;
+                                               } else {
+                                                       echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" />';
+                                               }
+                                               $children[$depth] = 1;
+                                       }
+
+                                       if ($_SESSION['s_cid'] == $content['content_id']) {
+                                               if (is_array($menu[$content['content_id']])) {
+                                                       $_SESSION['menu'][$content['content_id']] = 1;
+                                               }
+                                       }
+
+                                       if ($_SESSION['menu'][$content['content_id']] == 1) {
+                                               echo '<img src="'.$_base_path.'images/tree/tree_disabled.gif" alt="'._AT('toggle_disabled').'" border="0" width="16" height="16" title="'._AT('toggle_disabled').'" />';
+
+                                       } else {
+                                               echo '<img src="'.$_base_path.'images/tree/tree_disabled.gif" alt="'._AT('toggle_disabled').'" border="0" width="16" height="16" title="'._AT('toggle_disabled').'" />';
+                                       }
+
+                               } else {
+                                       /* doesn't have children */
+                                       if ($counter == $num_items) {
+                                               if ($depth) {
+                                                       echo $buttons;
+                                                       for ($i=0; $i<$depth; $i++) {
+                                                               if ($children[$i] == 1) {
+                                                                       if ($end && ($i == 0)) {
+                                                                               echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
+                                                                       } else {
+                                                                               echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" />';
+                                                                       }
+                                                               } else {
+                                                                       echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
+                                                               }
+                                                       }
+                                               } else {
+                                                       echo $buttons;
+                                               }
+                                               echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" />';
+                                       } else {
+                                               if ($depth) {
+                                                       echo $buttons;
+                                                       $print = false;
+                                                       for ($i=0; $i<$depth; $i++) {
+                                                               if ($children[$i] == 1) {
+                                                                       if ($end && !$print) {
+                                                                               $print = true;
+                                                                               echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_space.gif" alt="" border="0" width="16" height="16" />';
+                                                                       } else {
+                                                                               echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" />';
+                                                                       }
+                                                               } else {
+                                                                       echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_space.gif" alt="" border="0" width="16" height="16" />';
+                                                               }
+                                                       }
+                                                       $print = false;
+                                               } else {
+                                                       echo $buttons;
+                                               }
+               
+                                               echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" />';
+                                       }
+                                       echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_horizontal.gif" alt="" border="0" width="16" height="16" />';
+                               }
+
+                               echo '<small> '.$path.$counter;
+                               
+                               echo $link;
+                               
+                               echo '</small></td></tr>';
+
+                               $this->printMoveMenu($menu,
+                                                                       $content['content_id'],
+                                                                       ++$depth, 
+                                                                       $path.$counter.'.', 
+                                                                       $children);
+                               $depth--;
+
+                               $counter++;
+
+                               if ( $content['content_id'] == $cid ) {
+                                       $ignore =false;
+                               }
+                       }
+               }
+       }
+
+
+       /* returns the timestamp of release if this page has not yet been released, or is under a page that has not been released, true otherwise */
+       /* finds the max(timestamp) of all parents and returns that, true if less than now */
+       /* Access: public */
+       function isReleased($cid) {
+               if ($this->_menu_info[$cid]['content_parent_id'] == 0) {
+                       // this $cid has no parent, so we check its release date directly
+                       if ($this->_menu_info[$cid]['u_release_date'] <= time()) {      
+                               // yup! it's released
+                               return true;
+                       } else {
+                               // nope! not released
+                               return $this->_menu_info[$cid]['u_release_date'];
+                       }
+               }
+               // this is a sub page, need to check ALL its parents
+               $parent = $this->isReleased($this->_menu_info[$cid]['content_parent_id']); // recursion
+
+               if ($parent !== TRUE && $parent > $this->_menu_info[$cid]['u_release_date']) {
+                       return $parent;
+               } else if ($this->_menu_info[$cid]['u_release_date'] <= time()) {
+                       return true;
+               } else {
+                       return $this->_menu_info[$cid]['u_release_date'];
+               }
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/include/classes/ErrorHandler/ErrorHandler.class.php b/include/classes/ErrorHandler/ErrorHandler.class.php
new file mode 100644 (file)
index 0000000..4bdb76d
--- /dev/null
@@ -0,0 +1,530 @@
+<?php 
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+               
+/**
+* ErrorHandler
+* Custom ErrorHandler for php. Ability to log and send errors over e-mail
+* @access      public
+* @author      Jacek Materna
+*/
+
+class ErrorHandler { 
+
+       /** 
+       * Log errors to file?
+       * 
+       * @var Boolean 
+       * @access public 
+       */ 
+       var $LOG_ERR_TO_FILE; 
+       
+       /** 
+       * Log warnings to file? 
+       * 
+       * @var Boolean 
+       * @access public  
+       */ 
+       var $LOG_WARN_TO_FILE;   
+       
+       /**
+        * Message object
+        *
+        * @var object
+        * @access public
+        */
+       var $msg;
+       
+       /**
+        * Container to store errors until we decide to print them all
+        *
+        * @var array
+        * @access public
+        */
+       var $container;
+        
+       /** 
+       * Constructor for this class
+       * @return void 
+       * @access public 
+       */ 
+       function ErrorHandler() {  
+               
+               $this->setFlags(); // false by default
+               set_error_handler(array(&$this, 'ERROR_HOOK')); 
+               $this->container = array();
+               
+               /**
+                * check first if the log directory is setup, if not then create a logs dir with a+w && a-r
+                */
+               if (!file_exists(AT_CONTENT_DIR . 'logs/') || !realpath(AT_CONTENT_DIR. 'logs/')) {
+                       $this->makeLogDir();
+               } else if (!is_dir(AT_CONTENT_DIR .'logs/')) {
+                       $this->makeLogDir();
+               } 
+       }
+       
+       /** 
+       * The error handling routine set by set_error_handler(). Mimicking and Exception implementation in OOA
+       * Must be as quick as possible. Note a few: '\n' -> chr(10) - avoids inline translation in php engine
+       *                                                                                        'single quotes', avoid translation again
+       * Ability define custom errors. See case 'VITAL':
+       * 
+       * eg call from script, trigger_error('VITAL#There was a problem with the database.','E_USER_ERROR');
+       *
+       * @param string $error_type The type of error being handled. 
+       * @param string $error_msg The error message being handled. 
+       * @param string $error_file The file in which the error occurred. 
+       * @param integer $error_ln The line in which the error occurred. 
+       * @param string $error_context The context in which the error occurred.
+       * @return Boolean 
+       * @access public 
+       */ 
+       function ERROR_HOOK($error_type, $error_msg, $error_file, $error_ln, $error_context) { 
+               if ($error_type == E_NOTICE || $error_type == E_USER_NOTICE) return;
+               
+               $val_phpinfo = '';
+               $val_phpinfo_foot = '';
+               $val_phpinfo_printed  = false; // used to track for the scope of this method whether the server
+                                                                               // has been attached to a log file or e-mail buffer previously
+               
+               /**
+                * Only produce the server configuration once per file
+                */
+               if ($this->todayLogFileExists() === false) {
+                       // lets get some info about the system used by all error codes
+                       ob_start();
+                       
+                       // grab usefull data from php_info
+                       phpinfo(INFO_GENERAL ^ INFO_CONFIGURATION);
+                       $val_phpinfo .= ob_get_contents();
+                       ob_end_clean();
+                       
+                       /*
+                        * Parse $val_phpinfo
+                        */
+                       
+                       // get a substring of the php info to get rid of the html, head, title, etc.
+                       $val_phpinfo = substr($val_phpinfo, 760, -19);
+                       $val_phpinfo = substr($val_phpinfo, 552);
+                       $val_phpinfo = substr($val_phpinfo, strpos($val_phpinfo, 'System'));
+                       $val_phpinfo .= chr(10);
+                       
+                       $msql_str = '';
+                       if (defined('MYSQL_NUM'))
+                               $msql_str = "Yes";
+                       else
+                               $msql_str = "No";
+                       
+                       $val_phpinfo .= 'MySQL installed? ' . $msql_str . '<br/><br/>';
+                       
+                       // replace the </td>'s with tabs and the $nbsp;'s with spaces
+                       $val_phpinfo = str_replace( '</td>', '    ', $val_phpinfo);
+                       $val_phpinfo = str_replace( '&nbsp;', ' ', $val_phpinfo);
+                       $val_phpinfo = str_replace( '</body>', ' ', $val_phpinfo);
+                       $val_phpinfo = str_replace( '</html>', ' ', $val_phpinfo);
+                       
+                       $val_phpinfo = str_replace('This program makes use of the Zend Scripting Language Engine:<br />Zend Engine v1.3.0, Copyright (c) 1998-2003 Zend Technologies', '', $val_phpinfo);
+               
+                       $val_phpinfo_foot .= '$_ENV:' . chr(10) . $this->debug($_ENV) . '<br/><br/>';
+               } 
+               
+               // Everytime
+               $val_phpuser = '$_SESSION:' . chr(10) . $this->debug($_SESSION);
+               $val_phpuser .= '$_REQUEST:' . chr(10) . $this->debug($_REQUEST);
+               $val_phpuser .= '$_COOKIE:' . chr(10) . $this->debug($_COOKIE);
+               $val_phpuser .= '$_GET:' . chr(10) . $this->debug($_GET);
+               $val_phpuser .= '$_POST:' . chr(10) . $this->debug($_POST);
+               
+               // replace the </td>'s with tabs and the $nbsp;'s with spaces
+               $val_phpuser = str_replace( '</td>', '    ', $val_phpuser);
+               $val_phpuser = str_replace( '&nbsp;', ' ', $val_phpuser) . '<br/>';
+               
+               switch($error_type) {
+                       
+                       case E_ERROR: // caught below
+                       case E_USER_ERROR: 
+
+                               if (substr_count($error_msg, "#") > 0) {
+                                       $_error = explode("#", $error_msg);
+                               } else {
+                                       $_error = array('', $error_msg);
+                               }
+
+                               /**
+                                * eg call, trigger_error('VITAL;There was a problem with the database.',E_USER_ERROR);
+                                *
+                                * List of custom errors go here and the appropriate action is taken
+                                *@
+                                */
+                               switch($_error[0]) {
+                                       /**
+                                        * Custom errors are not guaranteed to be printed for example in footer.inc.php
+                                        * Hanlde on a case-by-case basis
+                                        */
+                                       case 'VITAL': // @see vital.inc.php
+                                               if ($this->LOG_ERR_TO_FILE) { 
+                                                               if ($val_phhinfo_printed === true) {
+                                                                       $val_phpinfo = '';
+                                                               }
+                                                               $this->log_to_files($val_phpinfo, $val_phpinfo_foot, 'ATutor v' . VERSION . '<br/>'. 'PHP ERROR MESSAGE:' . '<br/><p>'
+                                                                               . $error_msg . ' (error type ' . $error_type . ' in ' 
+                                                                               . $error_file . ' on line ' . $error_ln . ') [context: ' 
+                                                                               . $error_context . ']</p>' . chr(10) .chr(10) . $val_phpuser );
+                                                                               
+                                                               $val_phpinfo_printed = true;
+                                                               
+                                               }                                       
+                                               
+                                               $this->printError('<strong>ATutor has detected an Error<strong> - ' .
+                                                                                                               $_error[1]);
+
+                                               exit; // done here
+                                               break;
+                                               
+                                       case 'BKP_MEMBER': // @see TableBackup.class.php
+                                               if ($this->LOG_ERR_TO_FILE) { 
+                                                               if ($val_phhinfo_printed === true) {
+                                                                       $val_phpinfo = '';
+                                                               }
+                                                               $this->log_to_files($val_phpinfo, $val_phpinfo_foot, 'ATutor v' . VERSION . '<br/>'. 'PHP ERROR MESSAGE:' . '<br/><p>'
+                                                                               . $error_msg . ' (error type ' . $error_type . ' in ' 
+                                                                               . $error_file . ' on line ' . $error_ln . ') [context: ' 
+                                                                               . $error_context . ']</p>' . chr(10) .chr(10) . $val_phpuser );
+                                                                               
+                                                               $val_phpinfo_printed = true;
+                                                               
+                                               }
+                                               
+                                               $this->printError('<strong>ATutor has detected an Error<strong> - ' .
+                                                                                                               $_error[1]);
+                                       
+                                               exit;
+                                               break;
+                                       
+                                       default: // standard user error without custom prefix
+                                               if ($this->LOG_ERR_TO_FILE) { 
+                                                               if ($val_phhinfo_printed === true) {
+                                                                       $val_phpinfo = '';
+                                                               }
+                                                               
+                                                               $this->log_to_files($val_phpinfo, $val_phpinfo_foot, 'ATutor v' . VERSION . '<br/>'. 'PHP ERROR MESSAGE:' . '<br/><p>'
+                                                                               . $error_msg . ' (error type ' . $error_type . ' in ' 
+                                                                               . $error_file . ' on line ' . $error_ln . ') [context: ' 
+                                                                               . $error_context . ']</p>' . chr(10) .chr(10) . $val_phpuser);
+                                                               
+                                                               $val_phpinfo_printed = true;
+                                               }                                       
+                               }
+                               
+                               //$this->printError('<strong>ATutor has detected an Error<strong> - ' . 'Problem spot: ' . $error_msg . ' in ' 
+                               //                              . $this->stripbase($error_file) . ' on line ' . $error_ln);
+                               array_push($this->container, 'Problem spot: ' . $error_msg . ' in ' . $this->stripbase($error_file) . ' on line ' . $error_ln);
+                                                                       
+                               break;
+                       
+                       case E_WARNING: 
+                       case E_USER_WARNING: 
+                               if ($this->LOG_WARN_TO_FILE) { 
+                                       if ($val_phhinfo_printed === true) {
+                                               $val_phpinfo = '';
+                                       }
+                                                               
+                                       $this->log_to_files($val_phpinfo, $val_phpinfo_foot, 'ATutor v' . VERSION . '<br/>'. 'PHP ERROR MESSAGE:' . '<br/><p>'
+                                                       . $error_msg . ' (error type ' . $error_type . ' in ' 
+                                                       . $error_file . ' on line ' . $error_ln . ') [context: ' 
+                                                       . $error_context . ']</p>' . chr(10) . chr(10) . $val_phpuser);                 
+                               
+                                       $val_phpinfo_printed = true;
+                               }
+
+                               //$this->printError('<strong>ATutor has detected an Error</strong> - ' . 'Problem spot: ' . $error_msg . ' in ' 
+                               //                              . $this->stripbase($error_file) . ' on line ' . $error_ln);
+                               array_push($this->container, 'Problem spot: ' . $error_msg . ' in ' . $this->stripbase($error_file) . ' on line ' . $error_ln);
+       
+                               break;
+                        default:
+               }
+
+               return true; 
+       }
+       
+       /** 
+ÊÊ     * Dump the current error into a file along with an updated profile for that error
+ÊÊ     * 
+       * @param string the profile to log
+       * @param string the bug to log 
+ÊÊ     * @access public
+ÊÊ     */
+       function log_to_files($profile, $profile_foot, $buf) {
+               
+               if ($profile == '' || $profile_foor = '' || $buf == '') return;
+               
+               /**
+                * Redundancy control for profile/error log creation
+                */
+                $profile_created = true;
+                $error_created = true;
+                
+               $php_head = '<?php echo \'Only viewable as Admin user\'; exit; ?>' . chr(10);
+               
+               // Lets make a unqiue profile key, strip away circumventors of the md5 hashing algo. @see md5 algo src
+               $temp = strip_tags($profile);
+               $temp = stripslashes($temp);
+               $temp = str_replace('/', ' ', $temp);
+               $temp = str_replace('\$', ' ', $temp);
+               $temp = str_replace('$', ' ', $temp);
+               $temp = str_replace('\&' , ' ', $temp);
+               $temp = str_replace('&' , ' ', $temp);
+               $temp = str_replace('*' , ' ', $temp);
+               $temp = str_replace('~' , ' ', $temp);
+               $temp = str_replace('.' , ' ', $temp);
+               $temp = str_replace(';' , ' ', $temp);
+               $temp = str_replace(':' , ' ', $temp);
+               $temp = str_replace('-' , ' ', $temp);
+               $temp = str_replace('_' , ' ', $temp);
+               $temp = str_replace('\'' , ' ', $temp);
+               $temp = str_replace(',' , ' ', $temp);
+               $temp = str_replace('@' , ' ', $temp);
+               $temp = str_replace('#' , ' ', $temp);
+
+               $profile_key = md5($temp);
+               
+               $today = getdate(); 
+               
+               // Uniqueness assumend to be coupled to epoch timestamp
+               $timestamp_ = $today['mon'] . '-' . $today['mday'] . '-' . $today['year'];
+               
+               /**
+                * Lets make sure we have a log directory made for today
+                */ 
+               if (!is_dir(AT_CONTENT_DIR . 'logs/' . $timestamp_)) { // create it
+                       $result = @mkdir(AT_CONTENT_DIR . 'logs/' . $timestamp_, 0771); // r+w for owner
+       
+                       if ($result == 0) {
+                               $this->printError('Fatal. Could not create /content/logs' . '/' . $timestamp_ . '. Please resolve');
+                       }
+               } // else already there
+               
+               /**
+                * Go through all the profiles in our directory and lets try and map our md5 key to one of them,
+                * if its not found then we must be dealing with a new profile, thus create it
+                */
+                $dir_ = AT_CONTENT_DIR . 'logs/' . $timestamp_;
+               
+               if (!($dir = opendir($dir_))) {
+                       $msg->printNoLookupFeedback('Could not access /content/logs/' . $timestamp_ . '. Check that the permission for the <strong>Server</string> user are r+w to it');
+                       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+                       
+                       exit;
+               }
+               
+               /**
+                * Run through the todays logs directory and lets get all the profiles
+                */ 
+               $use_profile = null;
+               
+               // loop through folder todays log folder and try and match a profile to our error profile md5 key
+               while (($file = readdir($dir)) !== false) {
+               
+                       /* if the name is not a directory */
+                       if( ($file == '.') || ($file == '..') || is_dir($file) ) {
+                               continue;
+                       }
+               
+                       if (strpos($file, 'profile') >= 0) {
+                               $check_key = substr($file, strpos($file, '_') + 1);
+                               $check_key = substr($check_key, 0, strpos($check_key, '.log.php'));
+
+                               if ($check_key === $profile_key) { // found!
+                                       $use_profile = $file;
+                                       $profile_created = true;
+                                       break;
+                               }
+                       }
+               }
+               closedir($dir); // clean it up
+               
+               // if $use_profile == null here then we must create a new profile for this error
+               if ($use_profile == null) {
+                       $use_profile = 'profile_' . $profile_key . '.log.php';
+                       if ($file_handle = fopen(AT_CONTENT_DIR . 'logs/' . $timestamp_ . '/' . $use_profile, "w")) {
+                               if (!fwrite($file_handle, $php_head . chr(10) . $profile . $profile_foot)) { $profile_created = false; }
+                       } else { $profile_created = false; }
+                       fclose($file_handle);
+               } // else just use $use_profile as the profile for this error
+               
+               // if the creation of the profile_created = false then creation failed and we didnt have an already
+               // existant one in the dir, profile must exist
+               if ($profile_created === false) return;
+               
+               $timestamp = $timestamp_ . '_' . $today[0];
+                                       
+               // create a unique error filename including the epoch timestamp + and the profile mapping
+               $unique_error_log = $timestamp . '_pr' . $profile_key;
+
+               if (is_file(AT_CONTENT_DIR . 'logs/' . $timestamp_ . '/' . $unique_error_log)) {
+                       $unique_error_log .= rand(); // should be enough
+               }
+               
+               $unique_error_log .= '.log.php'; // append suffix
+               
+               /* Create error log file */
+               if ($file_handle = fopen(AT_CONTENT_DIR . 'logs/' . $timestamp_ . '/' . $unique_error_log, "w")) {
+                       if (!fwrite($file_handle, $php_head . chr(10) . $buf)) {  $error_created = false;  }
+               } else {
+                       $error_created = false;
+               }
+               fclose($file_handle);
+               
+               // check that we created a profile and its error or used an existing profile and created its error
+               if ($profile_created === true && $error_created === true) { // ok
+                       chmod(AT_CONTENT_DIR . 'logs/' . $timestamp_ . '/' . $unique_error_log, 0771);
+                       chmod(AT_CONTENT_DIR . 'logs/' . $timestamp_ . '/' . $use_profile, 0771);
+               } else if ($profile_create === true && $error_created === false) { // remove profile
+                       unlink(AT_CONTENT_DIR . 'logs/' . $timestamp_ . '/' . $use_profile);
+               } 
+       }
+
+       /** 
+ÊÊ     * Restores the error handler to the default error handler 
+ÊÊ     * 
+ÊÊ     * @return void 
+ÊÊ     * @access public
+ÊÊ     */
+       function restoreOrigHandler() {
+               restore_error_handler();
+       }
+
+       /** 
+Ê      * Returns the error handler to ERROR_HOOK() 
+Ê      * 
+ÊÊ     * @return void 
+ÊÊ     * @access public  
+ÊÊ     */
+       function returnHandler() {
+               set_error_handler(array(&$this, 'ERROR_HOOK'));
+       }
+       
+       /** 
+ÊÊ     * Changes the logging preferences
+ÊÊ     * 
+       * @param Boolean $error_flag Log errors to file? 
+ÊÊ     * @param Boolean $warning_flag Log warnings to file? 
+ÊÊ     * @return void 
+ÊÊ     * @access public 
+ÊÊ     */
+       function setFlags($error_flag = true, $warning_flag = true) {                            
+               
+               $this->LOG_ERR_TO_FILE = $error_flag;
+               $this->LOG_WARN_TO_FILE = $warning_flag;
+       }
+       
+       /**
+        * Construct a nicely formatted tree view of a variable
+        * @param var String is the varialbe to construct the output from
+        * @access private
+        */
+       function debug($var) {          
+               $str_ = '<pre>';
+               
+               ob_start();
+               print_r($var);
+               $str = ob_get_contents();
+               ob_end_clean();
+       
+               $str = str_replace('<', '&lt;', $str);
+       
+               $str = str_replace('[', '<span style="color: red; font-weight: bold;">[', $str);
+               $str = str_replace(']', ']</span>', $str);
+               $str = str_replace('=>', '<span style="color: blue; font-weight: bold;">=></span>', $str);
+               $str = str_replace('Array', '<span style="color: purple; font-weight: bold;">Array</span>', $str);
+               $str .= '</pre>';
+               
+               $str = $str_ . $str;
+               return $str;
+       }
+       
+       /**
+        * Function which strips the path base off a file URL since it is a security risk
+        * @param String str is the path string
+        * @return String only the script filename where the error occured
+        */
+       function stripbase($str) {
+               
+               $to_root = $_SERVER["PATH_TRANSLATED"];
+               
+               $pos_last = strrpos($to_root, "/");
+               $to_root = substr($to_root, $pos_last + 1);
+               return $to_root;
+       }
+       
+       /**
+        * Print the error to the browser, dont use any templates or css sheets for flexibility
+        * @access private
+        */
+       function printError($str) {
+               if (!AT_DEVEL) return;
+               
+               echo '<br />';
+               echo '<table bgcolor="#FF0000" border="0" cellpadding="3" cellspacing="2" width="90%" summary="" align="center">';
+               echo '<tr bgcolor="#FEF1F1" align="top">';
+               echo '<td>';
+               echo '<h3><span style="font-family: arial verdana">Internal Error Detected</span></small></h3>';
+               echo '<ul>';
+               echo '<li><small><span style="font-family: arial verdana">'. $str .'</span></small></li>';
+               echo'</ul>';
+               echo '</td>';
+               echo '</tr>';
+               echo '</table>';
+               echo '<br />';
+       }
+       
+       /**
+        * Create restricted access logs dir
+        */
+       function makeLogDir() {
+               
+               $result = @mkdir(AT_CONTENT_DIR . 'logs', 0771); // r+w for owner               
+               if ($result == 0) {
+                       $this->printError('Fatal. Could not create /content/logs. Please resolve');
+               }
+       
+       }
+       
+       /**
+        * Determine wheter a log file exists for today
+        * @access private
+        */
+       function todayLogFileExists() {
+               $today = getdate(); 
+
+               $timestamp = $today['mon'] . '-' . $today['mday'] . '-' . $today['year'];
+               
+               return (is_file(AT_CONTENT_DIR . 'logs/' . $timestamp . '.log'));
+       }
+       
+       /**
+        * Run through $container and print all the errors on this page.
+        * Used to prevent errors from breaking content on the page
+        * @access public
+        */
+       function showErrors() {
+
+               foreach($this->container as $elem) {
+                       $this->printError('<strong>ATutor has detected an Error<strong> - ' .
+                                                                                                                       $elem);
+                       unset($elem);
+               }
+       }
+} 
+?> 
\ No newline at end of file
diff --git a/include/classes/FileManager.class.php b/include/classes/FileManager.class.php
new file mode 100644 (file)
index 0000000..fa075f8
--- /dev/null
@@ -0,0 +1,544 @@
+<?php\r
+exit('not yet complete');\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+/**\r
+ *\r
+ * This a class I'm writing to replace the un-cohesive operations of\r
+ * the existing file manager.\r
+ *\r
+ * The focus of these methods is security. This file manager is written\r
+ * to be much more secure and easier to maintain then the existing code.\r
+ *\r
+ **/\r
+\r
+/**\r
+* Class for dealing with files/directories in the course content directory\r
+* @access      public\r
+* @author      Joel Kronenberg\r
+*/\r
+class FileManager {\r
+\r
+       /**\r
+       * string $contentDirectory - the full path to this course's content directory\r
+       * @access  private\r
+       */\r
+       var $contentDirectory; // path to content dir\r
+\r
+\r
+       /**\r
+       * Constructor method.  Initialises variables.\r
+       * @access       public\r
+       * @author       Joel Kronenberg\r
+       */\r
+       function FileManager( ) {\r
+               $this->contentDirectory = AT_CONTENT_DIR . $_SESSION['course_id'];\r
+       }\r
+\r
+       /**\r
+       * Creates a directory recursivelly.\r
+       * @access  public\r
+       * @param   string $dir      relative path and name of the directory to create.\r
+       *                           dir can be a full path of a dir structure to create.\r
+       * @return  boolean                      whether or not the directory was created\r
+       * @author  Joel Kronenberg\r
+       */\r
+       function createDirectory($dir) {\r
+               // break $dir into the end part\r
+               // check that the path to the new dir is safe\r
+               // sanitise the dir name\r
+\r
+               // Note: would it be easier to receive the path and directory name separately?\r
+               \r
+       }\r
+\r
+       /**\r
+       * Copies a file or directory\r
+       * @access  public\r
+       * @param   string $src  relative path to the source directory or file\r
+       * @param   string $dst  relative path to the destination directory or file\r
+       * @return  boolean      TRUE or FALSE whether or not the action was successful\r
+       * @author  Joel Kronenberg\r
+       */\r
+       function copy($src, $dst) {\r
+\r
+       }\r
+\r
+       /**\r
+       * Moves a file or directory\r
+       * @access  public\r
+       * @param   string $src  relative path to the source directory or file\r
+       * @param   string $dst  relative path to the destination directory or file\r
+       * @return  boolean      TRUE or FALSE whether or not the action was successful\r
+       * @author  Joel Kronenberg\r
+       */\r
+       function move($src, $dst) {\r
+\r
+       }\r
+\r
+       /**\r
+       * Rename a file or directory\r
+       * @access  public\r
+       * @param   string $old_name   relative path and old name of the directory or file to rename\r
+       * @param   string $new_name   relative path and new name of the directory or file to rename\r
+       * @return  boolean            TRUE or FALSE whether or not the action was successful\r
+       * @author  Joel Kronenberg\r
+       */\r
+       function rename($old_name, $new_name) {\r
+\r
+       }\r
+\r
+       /**\r
+       * Delete a file or directory (recusively)\r
+       * @access  public\r
+       * @param   string $file   relative path and name of the file or directory to delete\r
+       * @return  boolean        TRUE or FALSE whether or not the action was successful\r
+       * @author  Joel Kronenberg\r
+       */\r
+       function delete($file) {\r
+               // if it's a dir, then call the $this->_deleteDir($file) private method\r
+               // else if it's a file call the $this->_deleteFile($file) private method\r
+       }\r
+\r
+       /**\r
+       * Extracts a zip archive\r
+       * @access  public\r
+       * @param   string $archive  relative path and name of the zip file to extract\r
+       * @param   string $dst      relative path and name of the directory to extract the files into\r
+       * @return  boolean          TRUE or FALSE whether or not the action was successful\r
+       * @author  Joel Kronenberg\r
+       */\r
+       function extract($archive, $dst) {\r
+\r
+       }\r
+\r
+       /**\r
+       * Saves contents to a file\r
+       * @access  public\r
+       * @param   string $file       relative path to the file to save to\r
+       * @param   string $contents   the contents of the file to save to\r
+       * @param   boolean $overwrite whether or not to overwrite the file if it exists\r
+       * @return  boolean          TRUE or FALSE whether or not the action was successful\r
+       * @author  Joel Kronenberg\r
+       */\r
+       function saveFile($file, $contents, $overwrite = FALSE) {\r
+\r
+       }\r
+\r
+       /**\r
+       * Saves an uploded file\r
+       * @access  public\r
+       * @return  boolean          TRUE or FALSE whether or not the action was successful\r
+       * @author  Joel Kronenberg\r
+       */\r
+       function saveUploadFile( ) {\r
+\r
+       }\r
+\r
+       /**\r
+       * Returns size of a directory (recursively)\r
+       * @access  public\r
+       * @param   string $dir         relative path to the directory\r
+       * @param   boolean $recursive  whether or not to recurse down directories\r
+       * @return  int                 size of directory in Bytes, FALSE on failure\r
+       * @author  Joel Kronenberg\r
+       */\r
+       function getDirectorySize($dir, $recursive = TRUE) {\r
+               $dir = $this->_getRealPath($dir);\r
+\r
+               if (($dir !== FALSE) && is_dir($dir)) {\r
+                       $dh = @opendir($dir);\r
+               }\r
+               if (!$dh) {\r
+                       return -1;\r
+               }\r
+               $size = 0;\r
+               while (($file = readdir($dh)) !== false) {\r
+                       if (($file != '.') && ($file != '..')) {\r
+                               $path = $dir . $file;\r
+                               if (is_dir($path) && ($recursive === TRUE)) {\r
+                                       $size += $this->getDirectorySize($path . DIRECTORY_SEPARATOR);\r
+                               } elseif (is_file($path)) {\r
+                                       $size += filesize($path);\r
+                               }\r
+                       }\r
+                       \r
+               }\r
+               closedir($dh);\r
+               return $size;\r
+       }\r
+\r
+       /**\r
+       * Returns listing of files and directories\r
+       * @access  public\r
+       * @param   string $dir     relative path to the directory\r
+       * @return  array           array of files and directories in $dir\r
+       * @author  Joel Kronenberg\r
+       */\r
+       function getDirectoryListing($dir) {\r
+\r
+       }\r
+\r
+       /**\r
+       * Returns whether or not the $fileName is an editable type of file\r
+       * @access  public\r
+       * @param   string $fileName    name of the file to check\r
+       * @return  boolean             TRUE if the file can be edited, FALSE otherwise\r
+       * @author  Joel Kronenberg\r
+       */\r
+       function isEditable($fileName) {\r
+               // check if $fileName is in the list of editable files\r
+\r
+       }\r
+\r
+       /**\r
+       * Returns whether or not the $fileName is an archive that can be extracted\r
+       * @access  public\r
+       * @param   string $fileName    name of the file to check\r
+       * @return  boolean             TRUE if the file can be extracted, FALSE otherwise\r
+       * @author  Joel Kronenberg\r
+       */\r
+       function isExtractable($fileName) {\r
+               // check if $fileName is in the list of extractable files\r
+\r
+               // Note: could possibly call this isArchive() (but that doesn't directly imply extractability)\r
+       }\r
+\r
+       // -- private methods below\r
+\r
+       /**\r
+       * Returns a safe to use file or directory name\r
+       * @access  private\r
+       * @param   string $file         the file or directory name to sanitise\r
+       * @return  string|boolean   the sanitised file/directory name, or FALSE if the result is empty\r
+       * @author  Joel Kronenberg\r
+       */\r
+       function _getCleanName($fileName) {\r
+               $fileName = trim($fileName);\r
+               $fileName = str_replace(' ', '_', $fileName);\r
+               $fileName = str_replace(array(' ', '/', '\\', ':', '*', '?', '"', '<', '>', '|', '\''), '', $fileName);\r
+\r
+               return $fileName;\r
+       }\r
+\r
+       /**\r
+       * Returns canonicalized absolute pathname\r
+       * @access  private\r
+       * @param   string $file         the relative path to a file or directory\r
+       * @return  string|boolean   the canonicalized pathname, or FALSE if the file is not in the content directory\r
+       * @author  Joel Kronenberg\r
+       */\r
+       function _getRealPath($file) {\r
+               // determine the real path of the file/directory\r
+               $real = realpath($this->contentDirectory . DIRECTORY_SEPARATOR . $file);\r
+               \r
+               if (!file_exists($real)) {\r
+                       // the file or directory does not exist\r
+                       return FALSE;\r
+\r
+               } else if (substr($real, 0, strlen($this->contentDirectory)) != $this->contentDirectory) {\r
+                       // the file or directory is not in the content path\r
+                       return FALSE;\r
+\r
+               } else {\r
+                       // otherwise return the real path of the file\r
+                       return $real;\r
+               }\r
+       }\r
+\r
+       /**\r
+       * Delete a file\r
+       * @access  private\r
+       * @param   string $file   relative path and name of the file or directory to delete\r
+       * @return  boolean        TRUE or FALSE whether or not the action was successful\r
+       * @author  Joel Kronenberg\r
+       */\r
+       function _deleteFile($file) {\r
+\r
+       }\r
+\r
+       /**\r
+       * Delete this directory recursively\r
+       * @access  private\r
+       * @param   string $dir   relative path and name of the directory to delete\r
+       * @return  boolean       TRUE or FALSE whether or not the action was successful\r
+       * @author  Joel Kronenberg\r
+       */\r
+       function _deleteDirectory($dir) {\r
+\r
+       }\r
+}\r
+\r
+\r
+/**\r
+* FileManagerFactory\r
+* Class for creating AbstractFileManager Objects\r
+* @access      public\r
+* @author      Joel Kronenberg\r
+* @package     FileManager\r
+*/\r
+class FileManagerFactory {\r
+\r
+       function FileManagerFactory() { }\r
+\r
+       function createFileManagerFile($name) {\r
+               $obj = new FileManagerFile($name);\r
+               if ($obj->isOkay()) {\r
+                       return $obj;\r
+               }\r
+               return NULL;\r
+       }\r
+       function createFileManagerDirectory($name) {\r
+               $obj= new FileManagerDirectory($name);\r
+               if ($obj->isOkay()) {\r
+                       return $obj;\r
+               }\r
+               return NULL;\r
+       }\r
+\r
+       function open($name) {\r
+               if (is_dir($name)) {\r
+                       $obj = new FileManagerDirectory($name);\r
+               } else if (is_file($name)) {\r
+                       $obj = new FileManagerFile($name);\r
+               } else {\r
+                       // file not found\r
+                       return NULL;\r
+               }\r
+               if ($obj->isOkay()) {\r
+                       return $obj;\r
+               }\r
+               return NULL;\r
+       }\r
+}\r
+\r
+class AbstractFileManager {\r
+       var $_type; // private\r
+       var $_name; // private\r
+       var $_path; // private\r
+       var $_filename; // private\r
+       var $_exists; // private\r
+\r
+       // var $_old_filename;\r
+       // var $_old_path; // maybe?\r
+\r
+       var $_fp; // private, file/dir pointer\r
+\r
+       function AbstractFileManager( ) {\r
+               $this->contentDirectory = AT_CONTENT_DIR . $_SESSION['course_id'];\r
+       }\r
+\r
+       function create() { }\r
+\r
+       function isOkay() {\r
+               // this is where the important authentication check is done!\r
+               echo 'authenticating '.$this->_filename.'<br>';\r
+               if (file_exists($this->_path . DIRECTORY_SEPARATOR . $this->_filename)) {\r
+                       $this->_exists = TRUE;\r
+               }\r
+               $this->_exists = FALSE;\r
+               if ($this->isIllegalType()) {\r
+                       return FALSE;\r
+               }\r
+               return TRUE;\r
+       }\r
+       \r
+       function exists() {\r
+               return $this->_exists;\r
+       }\r
+\r
+}\r
+\r
+class FileManagerFile extends AbstractFileManager {\r
+       var $_extension; // private\r
+\r
+       function FileManagerFile($file) {\r
+               $this->_type = 'file';\r
+\r
+               $pathinfo = pathinfo($file);\r
+               $this->_extension = $pathinfo['extension'];\r
+               $this->_path      = $pathinfo['dirname'];\r
+               $this->_filename  = $pathinfo['basename'];\r
+\r
+               // set whether or not this file/dir is safe.\r
+       }\r
+\r
+       function rename($newName) {\r
+               $return = FALSE;\r
+\r
+               $fileManagerFactory = new FileManagerFactory();\r
+               $fileObj = $fileManagerFactory->createFileManagerFile($this->_path . DIRECTORY_SEPARATOR . $newName);\r
+               if (($fileObj !== NULL) && !$fileObj->exists()) {\r
+                       if (@rename($this->_path . DIRECTORY_SEPARATOR . $this->_filename, $this->_path . DIRECTORY_SEPARATOR . $newName)) {\r
+                               $this->_filename = $newName;\r
+                               $return = TRUE;\r
+                       }\r
+               }\r
+               return $return;\r
+       }\r
+\r
+       function delete() {\r
+               return unlink($this->_path . DIRECTORY_SEPARATOR . $this->_filename);\r
+       }\r
+\r
+       function isIllegalType($name = '') {\r
+               // get file extension\r
+               if ($name) {\r
+                       $pathinfo = pathinfo($name);\r
+                       $ext = $pathinfo['extension'];\r
+               } else {\r
+                       $ext = $this->_extension;\r
+               }\r
+\r
+               if (in_array($ext, array('txt', 'html'))) {\r
+                       return FALSE;\r
+               }\r
+               return TRUE;\r
+       }\r
+\r
+       function create($content) {\r
+               if (!is_dir($this->_path)) {\r
+                       $fileManagerFactory = new FileManagerFactory();\r
+                       $dirObj = $fileManagerFactory->createFileManagerDirectory($this->_path);\r
+                       if ($dirObj !== NULL) {\r
+                               $dirObj->create(0666);\r
+                       }\r
+               }\r
+\r
+               // save $contents into $file\r
+               $return = FALSE;\r
+               if (($fp = @fopen($this->_path . DIRECTORY_SEPARATOR . $this->_filename, 'wb+')) !== FALSE) {\r
+                       $return = @fwrite($fp, $content, strlen($content));\r
+                       @fclose($fp);\r
+               }\r
+               return $return;\r
+       }\r
+\r
+}\r
+\r
+class FileManagerDirectory extends AbstractFileManager {\r
+\r
+       function FileManagerDirectory($dir) {\r
+               $this->_type = 'directory';\r
+\r
+               $pathinfo = pathinfo($dir);\r
+               $this->_path     = $pathinfo['dirname'];\r
+               $this->_filename = $pathinfo['basename'];\r
+       }\r
+\r
+       function isIllegalType() {\r
+               return FALSE;\r
+       }\r
+\r
+       function getDirectoryListing() {\r
+\r
+       }\r
+\r
+       // creates dir\r
+       function create($mode = 0666) {\r
+               if (is_dir($this->_path)) {\r
+                       return @mkdir($this->_path . DIRECTORY_SEPARATOR . $this->_filename, $mode);\r
+               } else {\r
+                       $fileManagerFactory = new FileManagerFactory();\r
+                       $dirObj = $fileManagerFactory->createFileManagerDirectory($this->_path);\r
+                       if ($dirObj !== NULL) {\r
+                               if ($dirObj->create(0666) !== FALSE) {\r
+                                       return @mkdir($this->_path . DIRECTORY_SEPARATOR . $this->_filename, $mode);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       function delete() {}\r
+\r
+       function getDirectorySize($recursive = TRUE) {\r
+\r
+       }\r
+\r
+       // private\r
+       function _getDirectorySize($recursive = TRUE) {\r
+\r
+       }\r
+\r
+}\r
+\r
+$fileManagerFactory = new FileManagerFactory();\r
+\r
+$fileObj = $fileManagerFactory->createFileManagerFile('/content/meow.txt');\r
+\r
+if ($fileObj !== NULL) {\r
+       $data = 'stuff goes in here';\r
+       if ($fileObj->create($data) !== FALSE) {\r
+               echo 'create good: ' . $fileObj->_filename .' in '. $fileObj->_path;\r
+       }\r
+}\r
+echo '<hr>';\r
+\r
+$fileObj = $fileManagerFactory->open('/content/meow.txt');\r
+if ($fileObj !== NULL) {\r
+       if ($fileObj->rename('cow.txt') !== FALSE) {\r
+               echo 'rename good: ' . $fileObj->_filename .' in '. $fileObj->_path;\r
+       }\r
+}\r
+\r
+echo '<hr>';\r
+\r
+$fileObj = $fileManagerFactory->open('/content/cow.txt');\r
+if ($fileObj !== NULL) {\r
+       if ($fileObj->delete() !== FALSE) {\r
+               echo 'delete good: ' . $fileObj->_filename .' in '. $fileObj->_path;\r
+       }\r
+}\r
+\r
+echo '<hr>';\r
+\r
+$dirObj = $fileManagerFactory->createFileManagerDirectory('/content/test1/test2/test3/test4/');\r
+if ($dirObj !== NULL) {\r
+       if ($dirObj->create(0666) !== FALSE) {\r
+               echo 'create good: ' . $dirObj->_filename .' in '. $dirObj->_path;\r
+       } else {\r
+               echo 'dir exists: ' . $dirObj->_filename .' in '. $dirObj->_path;\r
+       }\r
+}\r
+\r
+echo '<hr>';\r
+\r
+\r
+$fileObj = $fileManagerFactory->createFileManagerFile('/content/test3/test122/quack.txt');\r
+if ($fileObj !== NULL) {\r
+       $data = 'quack file goes here';\r
+       if ($fileObj->create($data) !== FALSE) {\r
+               echo 'create good: ' . $fileObj->_filename .' in '. $fileObj->_path;\r
+       }\r
+}\r
+\r
+echo '<hr>';\r
+\r
+/*\r
+- create/overwrite file\r
+- move file\r
+- rename file\r
+- delete file\r
+- copy file\r
+\r
+\r
+- create dir\r
+- move dir (and its files)\r
+- rename dir\r
+- delete dir\r
+- copy dir\r
+\r
+\r
+*/\r
+?>
\ No newline at end of file
diff --git a/include/classes/Language/Language.class.php b/include/classes/Language/Language.class.php
new file mode 100644 (file)
index 0000000..6b80c85
--- /dev/null
@@ -0,0 +1,221 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_LANGUAGE_LOCALE_SEP', '-');
+
+/**
+* Language
+* Class for accessing information about a single language.
+* @access      public
+* @author      Joel Kronenberg
+* @see         LanguageManager::getLanguage()
+* @see         LanguageManager::getMyLanguage()
+* @package     Language
+*/
+class Language {
+       // all private
+       var $code;
+       var $characterSet;
+       var $direction;
+       var $regularExpression;
+       var $nativeName;
+       var $englishName;
+       var $status;
+       var $atutor_version;
+
+       var $db;
+
+       // constructor
+       function Language($language_row) {
+               global $db;
+
+               $this->db = $db;
+
+               if (is_array($language_row)) {
+                       $this->code              = $language_row['language_code'];
+                       $this->characterSet      = $language_row['char_set'];
+                       $this->direction         = $language_row['direction'];
+                       $this->regularExpression = $language_row['reg_exp'];
+                       $this->nativeName        = $language_row['native_name'];
+                       $this->englishName       = $language_row['english_name'];
+                       $this->status            = $language_row['status'];
+                       $this->atutor_version    = isset($language_row['version']) ? $language_row['version'] : VERSION;
+
+               } else if (is_object($language_row)) {
+                       $this->cloneThis($language_row);
+               }
+       }
+
+       // private
+       // copies the properties from $from to $this Object
+       function cloneThis($from) {
+               $vars = get_object_vars($from);
+               foreach ($vars as $key => $value) {
+                       $this->$key = $value;
+               }
+       }
+
+       // returns whether or not the $search_string matches the regular expression
+       function isMatchHttpAcceptLanguage($search_string) {
+               return eregi('^(' . $this->regularExpression . ')(;q=[0-9]\\.[0-9])?$', $search_string);
+       }
+
+       // returns boolean whether or not $search_string is in HTTP_USER_AGENT
+       function isMatchHttpUserAgent($search_string) {
+               return eregi('(\(|\[|;[[:space:]])(' . $this->regularExpression . ')(;|\]|\))', $search_string);
+
+       }
+
+       function getCode() {
+               return $this->code;
+       }
+
+       function getCharacterSet() {
+               return $this->characterSet;
+       }
+
+       function getDirection() {
+               return $this->direction;
+       }
+
+       function getRegularExpression() {
+               return $this->regularExpression;
+       }
+
+       function getAtutorVersion() {
+               return $this->atutor_version;
+       }
+
+       function getTranslatedName() {
+               if ($this->code == $_SESSION['lang']) {
+                       return $this->nativeName;
+               }
+               // this code has to be translated:
+               return _AT('lang_' . str_replace('-', '_', $this->code));
+       }
+
+       function getNativeName() {
+               return $this->nativeName;
+       }
+
+       function getEnglishName() {
+               return $this->englishName;
+       }
+
+       function getStatus() {
+               return $this->status;
+       }
+
+
+       // public
+       function sendContentTypeHeader() {
+               header('Content-Type: text/html; charset=' . $this->characterSet);
+       }
+
+       // public
+       function saveToSession() {
+               $_SESSION['lang'] = $this->code;
+       }
+
+       /* 
+        * public
+        * @param       member_id or login for members and admin respectively
+        * @param       1 for admin, 0 for members, all other integers are ignored. 
+        */
+       function saveToPreferences($id, $is_admin) {
+               global $db;
+               if ($id) {
+                       if ($is_admin === 0) {
+                               $sql = "UPDATE ".TABLE_PREFIX."members SET language='".$this->code."', creation_date=creation_date, last_login=last_login WHERE member_id=$id";
+                       } elseif ($is_admin === 1) {
+                               $sql = "UPDATE ".TABLE_PREFIX."admins SET language='".$this->code."', last_login=last_login WHERE login='$id'";
+                       }
+                       mysql_query($sql,$db);
+               }
+       }
+
+       // public
+       // returns whether or not this language is right-to-left
+       // possible langues are: arabic, farsi, hebrew, urdo
+       function isRTL() {
+               if ($this->direction == 'rtl') {
+                       return true;
+               } // else:
+
+               return false;
+       }
+
+       // public
+       // can be called staticly
+       function getParentCode($code = '') {
+               if (!$code && isset($this)) {
+                       $code = $this->code;
+               }
+               $peices = explode(AT_LANGUAGE_LOCALE_SEP, $code, 2);
+               return $peices[0];
+       }
+
+       // public
+       // can be called staticly
+       function getLocale($code = '') {
+               if (!$code && isset($this)) {
+                       $code = $this->code;
+               }
+               $peices = explode(AT_LANGUAGE_LOCALE_SEP, $code, 2);
+               return $peices[1];
+       }
+
+       
+       // public
+       function getTerm($term) {
+               $sql = "SELECT *, UNIX_TIMESTAMP(L.revised_date) AS revised_date_unix FROM ".TABLE_PREFIX."language_text L WHERE L.language_code='".$this->getCode()."' AND L.variable='_template' AND L.term='$term'";
+
+               $result = mysql_query($sql, $this->db);
+               $row = mysql_fetch_assoc($result);
+               return $row;
+       }
+
+       function getXML($part=FALSE) {
+               if (!$part) {
+                       $xml = '<?xml version="1.0" encoding="iso-8859-1"?>
+                       <!-- This is an ATutor language pack - http://www.atutor.ca-->
+
+                       <!DOCTYPE language [
+                          <!ELEMENT atutor-version (#PCDATA)>
+                          <!ELEMENT code (#PCDATA)>
+                          <!ELEMENT charset (#PCDATA)>
+                          <!ELEMENT direction (#PCDATA)>
+                          <!ELEMENT reg-exp (#PCDATA)>
+                          <!ELEMENT native-name (#PCDATA)>
+                          <!ELEMENT english-name (#PCDATA)>
+                          <!ELEMENT status (#PCDATA)>
+
+                          <!ATTLIST language code ID #REQUIRED>
+                       ]>';
+               } 
+
+               $xml .= '<language code="'.$this->code.'">
+                       <atutor-version>'.VERSION.'</atutor-version>
+                       <charset>'.$this->characterSet.'</charset>
+                       <direction>'.$this->direction.'</direction>
+                       <reg-exp>'.$this->regularExpression.'</reg-exp>
+                       <native-name>'.$this->nativeName.'</native-name>
+                       <english-name>'.$this->englishName.'</english-name>
+                       <status>'.$this->status.'</status>
+               </language>';
+
+               return $xml;
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/Language/LanguageEditor.class.php b/include/classes/Language/LanguageEditor.class.php
new file mode 100644 (file)
index 0000000..7eaa0f5
--- /dev/null
@@ -0,0 +1,436 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+/**
+* LanguageEditor
+* Class for adding/editing language.
+* @access      public
+* @author      Heidi Hazelton
+* @author      Joel Kronenberg
+* @package     Language
+*/
+class LanguageEditor extends Language {
+
+       var $addslashes;
+
+       // array of missing terms
+       var $missingTerms;
+
+       // array of filters ['new', 'update']
+       var $filters;
+       
+       /**
+       * Constructor.
+       * 
+       * Initializes db and parent properties.
+       */
+       function LanguageEditor($myLang) {
+               global $db, $addslashes, $msg;
+               
+               global $savant;
+               $this->msg =& $msg;
+
+               $this->addslashes = $addslashes;
+
+               if (isset($myLang)) {
+                       $this->Language($myLang);
+               }
+               $this->missingTerms = array();
+       }
+
+       /**
+       * Inserts a new language def'n into the database.
+       * @access       public
+       * @param        array $row              The language def'n fields as an assoc array.
+       * @return       boolean                 Returns TRUE if the def'n was inserted correctly, 
+       *                                                       or FALSE, otherwise.
+       * call staticly only!
+       */
+    function addLanguage($row, $db) {
+               global $addslashes;
+               global $msg;
+               
+               $row['code']         = trim($row['code']);
+               $row['locale']       = trim($row['locale']);
+               $row['charset']      = trim($row['charset']);
+               $row['reg_exp']      = trim($row['reg_exp']);
+               $row['native_name']  = trim($row['native_name']);
+               $row['english_name'] = trim($row['english_name']);
+
+               $missing_fields = array();
+
+               if ($row['code'] == '') {
+                       $missing_fields[] = _AT('lang_code');
+               }
+               if ($row['charset'] == '') {
+                       $missing_fields[] = _AT('charset');
+               }
+               if ($row['reg_exp'] == '') {
+                       $missing_fields[] = _AT('reg_exp');
+               }
+               if ($row['native_name'] == '') {
+                       $missing_fields[] = _AT('name_in_language');
+               }
+               if ($row['english_name'] == '') {
+                       $missing_fields[] = _AT('name_in_english');
+               }
+               
+               if ($missing_fields) {
+                       $missing_fields = implode(', ', $missing_fields);
+                       $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+               }
+
+               if (!$msg->containsErrors()) {
+                       $row['code']         = $addslashes($row['code']);
+                       $row['locale']       = $addslashes($row['locale']);
+                       $row['charset']      = $addslashes($row['charset']);
+                       $row['direction']    = $addslashes($row['direction']);
+                       $row['reg_exp']      = $addslashes($row['reg_exp']);
+                       $row['native_name']  = $addslashes($row['native_name']);
+                       $row['english_name'] = $addslashes($row['english_name']);
+
+                       if (!empty($row['locale'])) { 
+                               $row['code'] .= AT_LANGUAGE_LOCALE_SEP . strtolower($row['locale']);
+                       }
+
+                       $sql    = "INSERT INTO ".TABLE_PREFIX."languages VALUES ('$row[code]', '$row[charset]', '$row[direction]', '$row[reg_exp]', '$row[native_name]', '$row[english_name]', 3)";
+
+                       if (mysql_query($sql, $db)) {
+                               return TRUE;
+                       } else {
+                               return FALSE;
+                       }
+               }
+
+               return FALSE;
+    }
+
+       // public
+       // $row = the language info array
+       // $new_exists whether the new code+locale exists already
+       // returns true or false, depending on success if db update
+       // can be called staticly
+    function updateLanguage($row, $new_exists) {
+               $missing_fields = array();
+
+               if ($row['code'] == '') {
+                       $missing_fields[] = _AT('lang_code');
+               }
+               if ($row['charset'] == '') {
+                       $missing_fields[] = _AT('charset');
+               }
+               if ($row['reg_exp'] == '') {
+                       $missing_fields[] = _AT('reg_exp');
+               }
+               if ($row['native_name'] == '') {
+                       $missing_fields[] = _AT('name_in_language');
+               }
+               if ($row['english_name'] == '') {
+                       $missing_fields[] = _AT('name_in_english');
+               }
+               
+               if ($missing_fields) {
+                       $missing_fields = implode(', ', $missing_fields);
+                       $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+               }
+
+
+               if (!$this->msg->containsErrors()) {
+                       global $addslashes;
+                       global $db;
+
+                       $row['code']         = strtolower($addslashes($row['code']));
+                       if (!empty($row['locale'])) { 
+                               $row['code'] .= AT_LANGUAGE_LOCALE_SEP . strtolower($addslashes($row['locale']));
+                       }
+                       $row['charset']      = strtolower($addslashes($row['charset']));
+                       $row['direction']    = strtolower($addslashes($row['direction']));
+                       $row['reg_exp']      = strtolower($addslashes($row['reg_exp']));
+                       $row['native_name']  = $addslashes($row['native_name']);
+                       $row['english_name'] = $addslashes($row['english_name']);
+                       if (isset($row['status'])) {
+                               $row['status']       = intval($row['status']);
+                               $status_sql = ', status='.$row['status'];
+                       } else {
+                               $status_sql = '';
+                       }
+
+                       if ($row['old_code'] == $row['code']) {
+                               $sql    = "UPDATE ".TABLE_PREFIX."languages SET char_set='$row[charset]', direction='$row[direction]', reg_exp='$row[reg_exp]', native_name='$row[native_name]', english_name='$row[english_name]' $status_sql WHERE language_code='$row[code]'";
+                               mysql_query($sql, $db);
+
+                               return TRUE;
+                       } else if ($new_exists) {
+                               $this->msg->addError('LANG_EXISTS');
+                               return FALSE;
+                       } else {
+                               $sql    = "UPDATE ".TABLE_PREFIX."languages SET language_code='$row[code]', char_set='$row[charset]', direction='$row[direction]', reg_exp='$row[reg_exp]', native_name='$row[native_name]', english_name='$row[english_name]' $status_sql WHERE language_code='$row[old_code]'";
+                               mysql_query($sql, $db);
+
+                               $sql = "UPDATE ".TABLE_PREFIX."language_text SET language_code='$row[code]' WHERE language_code='$row[old_code]'";
+                               mysql_query($sql, $db);
+
+                               return TRUE;
+                       }
+
+               }
+               return FALSE;
+    }
+
+    function deleteLanguage() {
+               $sql = "DELETE FROM ".TABLE_PREFIX."languages WHERE language_code='$this->code'";
+               mysql_query($sql, $this->db);
+
+               $sql = "DELETE FROM ".TABLE_PREFIX."language_text WHERE language_code='$this->code'";
+               mysql_query($sql, $this->db);
+
+               $sql = "UPDATE ".TABLE_PREFIX."members SET language='".DEFAULT_LANGUAGE."', creation_date=creation_date, last_login=last_login WHERE language='$this->code'";
+               mysql_query($sql, $this->db);
+
+               $sql = "UPDATE ".TABLE_PREFIX."courses SET primary_language='".DEFAULT_LANGUAGE."' WHERE primary_language='$this->code'";
+               mysql_query($sql, $this->db);
+
+               cache_purge('system_langs', 'system_langs');
+       }
+
+       // public
+       function updateTerm($variable, $term, $text) {
+               $addslashes = $this->addslashes;
+
+               $variable = $addslashes($variable);
+               $term     = $addslashes($term);
+               $text     = $addslashes($text);
+               $code     = $addslashes($this->getCode());
+
+               $sql    = "UPDATE ".TABLE_PREFIX."language_text SET text='$text', revised_date=NOW() WHERE language_code='$code' AND variable='$variable' AND term='$term'";
+
+               /*
+               if (mysql_query($sql, $this->db)) {
+                       return TRUE;
+               } else {
+                       debug(mysql_error($this->db));
+                       return FALSE;
+               }
+               */
+       }
+
+       // public
+       function insertTerm($variable, $key, $text, $context) {
+               $addslashes = $this->addslashes;
+
+               $variable = $addslashes($variable);
+               $key      = $addslashes($key);
+               $text     = $addslashes($text);
+               $code     = $addslashes($this->getCode());
+               $context  = $addslashes($context);
+
+               $sql = "INSERT INTO ".TABLE_PREFIX."language_text VALUES('$code', '$variable', '$key', '$text', NOW(), '$context')";
+       }
+
+       // public
+       function showMissingTermsFrame(){
+               global $_base_path, $addslashes;
+               //$terms = array_slice($this->missingTerms, 0, 20);
+               $terms = $this->missingTerms;
+               $terms = serialize($terms);
+               $terms = urlencode($terms);
+
+               echo '<div align="center"><iframe src="'.$_base_path.'admin/missing_language.php?terms='.$terms.SEP.'lang='.$_SESSION['lang'].'" width="99%" height="300"></div>';
+       }
+
+       // public
+       // doesn't actually check if params is one of the possible ones.
+       // possible params should be array ('new', 'update')
+       function setFilter($params){
+               if (!is_array($params)) {
+                       return;
+               }
+
+               foreach($params as $param => $garbage) {
+                       $this->filters[$param] = true;
+               }
+       }
+
+       // private
+       function checkFilter($param) {
+               if ($this->filters[$param]) {
+                       return true;
+               }
+               return false;
+       }
+
+       // public
+       function printTerms($terms){
+               global $addslashes, $languageManager; // why won't $addslashes = $this->addslashes; work?
+
+               $counter = 0;
+
+               $terms = unserialize(stripslashes($addslashes($terms)));
+
+               natcasesort($terms);
+
+               if ($this->checkFilter('new')) {
+                       $new_check = ' checked="checked"';
+               }
+               if ($this->checkFilter('update')) {
+                       $update_check = ' checked="checked"';
+               }
+
+               $fromLanguage =& $languageManager->getLanguage('en');
+
+               echo '<form method="post" action="'.htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES).'">';
+               echo '<table border="0" cellpadding="0" cellspacing="2">';
+               echo '<tr>';
+               echo '<td>Show: ';
+               echo '<input name="filter_new" id="n" value="1" type="checkbox" '.$new_check.' /><label for="n">New Language</label>, ';
+               echo '<input name="filter_update" id="u" value="1" type="checkbox" '.$update_check.' /><label for="u">Updated Language</label> ';
+               echo '</td>';
+               echo '</tr>';
+
+               foreach($terms as $term => $garbage) {
+                       $to_term   = $this->getTerm($term);
+                       $from_term = $fromLanguage->getTerm($term);
+
+                       $is_new = false;
+                       if ($to_term === false) {
+                               $is_new = true;
+                       }
+
+                       $is_old = false;
+                       if ($to_term['revised_date_unix'] < $from_term['revised_date_unix']) {
+                               $is_old = true;
+                       }
+
+
+                       if ($this->checkFilter('new') && !$is_new) {
+                               continue;
+                       }
+
+                       if ($this->checkFilter('update') && !$is_old) {
+                               continue;
+                       }
+
+                       if (($counter % 10) == 0) {
+                               echo '<tr>';
+                               echo '<td align="center"><input type="submit" name="submit" value="Save Changes" class="button" /></td>';
+                               echo '</tr>';
+                       }
+
+                       $style = '';
+                       if ($is_new) {
+                               $style = 'style="background-color: white; border: red 2px solid;"';
+                       } else {
+                               $style = 'style="background-color: white; border: yellow 1px solid;"';
+                       }
+
+                       echo '<tr>';
+                       echo '<td><strong>[ ' . $term . ' ] '.htmlspecialchars($from_term['text']).'</strong></td></tr>';
+                       echo '<tr><td><input type="text" name="'.$term.'" '.$style.' size="100" value="'.htmlspecialchars($to_term['text']).'" />';
+                       echo '<input type="hidden" name="old['.$term.']" '.$style.' size="100" value="'.htmlspecialchars($to_term['text']).'" /></td>';
+                       echo '</tr>';
+
+                       $counter++;
+               }
+               echo '</table>';
+               echo '</form>';
+       }
+
+       // public
+       function updateTerms($terms) {
+               global $addslashes;
+
+               foreach($terms as $term => $text) {
+                       $text = $addslashes($text);
+                       $term = $addslashes($term);
+               
+                       if (($text != '') && ($text != $_POST['old'][$term])) {
+                               $sql = "REPLACE INTO ".TABLE_PREFIX."language_text VALUES ('".$this->getCode()."', '_template', '$term', '$text', NOW(), '')";
+                               mysql_query($sql, $this->db);
+                       }
+               }
+       }
+
+       // public
+       function addMissingTerm($term) {
+               if (!isset($this->missingTerms[$term])) {
+                       $this->missingTerms[$term] = '';
+               }
+       }
+
+
+       // this method should be called staticly: LanguageEditor::import()
+       // public
+       function import($language_sql_file) {
+               // move sql import class from install/ to include/classes/
+               // store the lang def'n in a .ini file and use insertLang 
+               // after checking if it already exists
+
+               // use the sql class to insert the language into the db
+
+               // check if this language exists before calling this method
+
+               require_once(AT_INCLUDE_PATH . 'classes/sqlutility.class.php');
+               $sqlUtility =& new SqlUtility();
+
+               $sqlUtility->queryFromFile($language_sql_file, TABLE_PREFIX);
+       }
+
+       // sends the generated language pack to the browser
+       // public
+       function export($filename = '') {
+               $search  = array('"', "'", "\x00", "\x0a", "\x0d", "\x1a"); //\x08\\x09, not required
+               $replace = array('\"', "\'", '\0', '\n', '\r', '\Z');
+
+               // use a function to generate the ini file
+               // use a diff fn to generate the sql dump
+               // use the zipfile class to package the ini file and the sql dump
+               $sql_dump = "INSERT INTO `languages` VALUES ('$this->code', '$this->characterSet', '$this->direction', '$this->regularExpression', '$this->nativeName', '$this->englishName', $this->status);\r\n\r\n";
+
+               $sql_dump .= "INSERT INTO `language_text` VALUES ";
+
+               $sql    = "SELECT * FROM ".TABLE_PREFIX."language_text WHERE language_code='$this->code' ORDER BY variable, term";
+               $result = mysql_query($sql, $this->db);
+               if ($row = mysql_fetch_assoc($result)) {
+                       do {
+                               $row['text']    = str_replace($search, $replace, $row['text']);
+                               $row['context'] = str_replace($search, $replace, $row['context']);
+
+                               $sql_dump .= "('$this->code', '$row[variable]', '$row[term]', '$row[text]', '$row[revised_date]', '$row[context]'),\r\n";
+                       } while ($row = mysql_fetch_assoc($result));
+               } else {
+                       $this->msg->addError('LANG_EMPTY');
+               }
+               $sql_dump = substr($sql_dump, 0, -3) . ";";
+
+               $readme = 'This is an ATutor language pack. Use the administrator Language section to import this language pack or manually import the contents of the SQL file into your [table_prefix]language_text table, where `table_prefix` should be replaced with your correct ATutor table prefix as defined in ./include/config.inc.php . Additional Language Packs can be found on http://atutor.ca .';
+
+               require(AT_INCLUDE_PATH . 'classes/zipfile.class.php');
+               $zipfile =& new zipfile();
+
+               $zipfile->add_file($sql_dump, 'language_text.sql');
+               $zipfile->add_file($readme, 'readme.txt');
+               $zipfile->add_file($this->getXML(), 'language.xml');  
+
+               if ($filename) {
+                       $fp = fopen($filename, 'wb+');
+                       fwrite($fp, $zipfile->get_file(), $zipfile->get_size());
+               } else {
+                       $version = str_replace('.','_',VERSION);
+
+                       $zipfile->send_file('atutor_' . $version . '_' . $this->code);
+               }
+       }
+
+}
+?>
\ No newline at end of file
diff --git a/include/classes/Language/LanguageManager.class.php b/include/classes/Language/LanguageManager.class.php
new file mode 100644 (file)
index 0000000..9f5310c
--- /dev/null
@@ -0,0 +1,388 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+require_once(dirname(__FILE__) . '/Language.class.php');
+
+define('AT_LANG_STATUS_EMPTY',       0);
+define('AT_LANG_STATUS_INCOMPLETE',  1);
+define('AT_LANG_STATUS_COMPLETE',    2);
+define('AT_LANG_STATUS_PUBLISHED',   3);
+
+/**
+* LanguageManager
+* Class for managing available languages as Language Objects.
+* @access      public
+* @author      Joel Kronenberg
+* @see         Language.class.php
+* @package     Language
+*/
+class LanguageManager {
+
+       /**
+       * This array stores references to all the Language Objects
+       * that are available in this installation.
+       * @access private
+       * @var array
+       */
+       var $availableLanguages;
+
+       /**
+       * The fallback language if the DEFAULT_LANGUAGE isn't defined.
+       * @access private
+       * @var string
+       */
+       var $default_lang = 'en';
+
+       /**
+       * The fallback charachter set if the DEFAULT_CHARSET isn't defined.
+       * @access private
+       * @var string
+       */
+//     var $default_charset = 'iso-8859-1';
+       var $default_charset = 'utf-8';
+
+       /**
+       * The number of languages that are available. Does not include
+       * character set variations.
+       * @access private
+       * @var integer
+       */
+       var $numLanguages;
+
+       /**
+       * Constructor.
+       * 
+       * Initializes availableLanguages and numLanguages.
+       */
+       function LanguageManager() {
+               global $db;
+
+               $sql    = 'SELECT * FROM '.TABLE_PREFIX.'languages ORDER BY native_name';
+               $result = mysql_query($sql, $db);
+               while($row = mysql_fetch_assoc($result)) {
+                       if (defined('AT_DEVEL_TRANSLATE') && AT_DEVEL_TRANSLATE) {
+                               $row['status'] = AT_LANG_STATUS_PUBLISHED; // b/c the print drop down checks for it.                            
+                       }
+                       $this->availableLanguages[$row['language_code']][$row['char_set']] =& new Language($row);
+               }
+               $this->numLanguages = count($this->availableLanguages);
+       }
+
+
+       /**
+       * Returns a valid Language Object based on the given language $code and optional
+       * $charset, FALSE if it can't be found.
+       * @access       public
+       * @param        string $code            The language code of the language to return.
+       * @param        string $charset         Optionally, the character set of the language to find.
+       * @return       boolean|Language        Returns FALSE if the requested language code and
+       *                                                               character set cannot be found. Returns a Language Object for the
+       *                                                               specified language code and character set.
+       * @see          getMyLanguage()
+       */
+       function getLanguage($code, $charset = '') {
+               if (!$charset) {
+                       if (isset($this->availableLanguages[$code])) {
+                               return current($this->availableLanguages[$code]);
+                       } else {
+                               return FALSE;
+                       }
+               }
+
+               foreach ($this->availableLanguages[$code] as $language) {
+                       if ($language->getCharacterSet() == $charset) {
+                               return $language;
+                       }
+               }
+               return FALSE;
+       }
+
+       /**
+       * Tries to detect the user's current language preference/setting from (in order):
+       * _GET, _POST, _SESSION, HTTP_ACCEPT_LANGUAGE, HTTP_USER_AGENT. If no match can be made
+       * then it tries to detect a default setting (defined in config.inc.php) or a fallback
+       * setting, false if all else fails.
+       * @access       public
+       * @return       boolean|Language        Returns a Language Object matching the user's current session.
+       *                                                               Returns FALSE if a valid Language Object cannot be found
+       *                                                               to match the request
+       * @see          getLanguage()
+       */
+       function getMyLanguage() {
+               global $addslashes, $db; 
+
+               if (isset($_GET) && !empty($_GET['lang']) && isset($this->availableLanguages[$_GET['lang']])) {
+                       $language = $this->getLanguage($_GET['lang']);
+
+                       if ($language) {
+                               return $language;
+                       }
+
+               } 
+               if (isset($_POST) && !empty($_POST['lang']) && isset($this->availableLanguages[$_POST['lang']])) {
+                       $language = $this->getLanguage($_POST['lang']);
+
+                       if ($language) {
+                               return $language;
+                       }
+
+               } 
+               if (isset($_SESSION) && isset($_SESSION['lang']) && !empty($_SESSION['lang']) && isset($this->availableLanguages[$_SESSION['lang']])) {
+                       $language = $this->getLanguage($_SESSION['lang']);
+
+                       if ($language) {
+                               return $language;
+                       }
+               }
+               if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
+
+                       // Language is not defined yet :
+                       // try to find out user's language by checking its HTTP_ACCEPT_LANGUAGE
+                       $accepted    = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
+                       $acceptedCnt = count($accepted);
+                       reset($accepted);
+                       for ($i = 0; $i < $acceptedCnt; $i++) {
+                               foreach ($this->availableLanguages as $codes) {
+                                       foreach ($codes as $language) {
+                                               if ($language->isMatchHttpAcceptLanguage($accepted[$i])) {
+                                                       return $language;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               if (!empty($_SERVER['HTTP_USER_AGENT'])) {
+
+                       // Language is not defined yet :
+                       // try to find out user's language by checking its HTTP_USER_AGENT
+                       foreach ($this->availableLanguages as $codes) {
+                               foreach ($codes as $language) {
+                                       if ($language->isMatchHttpUserAgent($_SERVER['HTTP_USER_AGENT'])) {
+                                               return $language;
+                                       }
+                               }
+                       }
+               }
+
+               // Didn't catch any valid lang : we use the default settings
+               if (isset($this->availableLanguages[DEFAULT_LANGUAGE])) {
+                       $language = $this->getLanguage(DEFAULT_LANGUAGE, DEFAULT_CHARSET);
+
+                       if ($language) {
+                               return $language;
+                       }
+               }
+
+               // fail safe
+               if (isset($this->availableLanguages[$this->default_lang])) {
+                       $language = $this->getLanguage($this->default_lang, $this->default_charset);
+
+                       if ($language) {
+                               return $language;
+                       }
+               }
+
+               // else pick one at random:
+               reset($this->availableLanguages);
+               $uknown_language = current($this->availableLanguages);
+               if ($unknown_language) {
+                       return FALSE;
+               }
+
+               return current($uknown_language);
+       }
+
+       function getAvailableLanguages() {
+               return $this->availableLanguages;
+       }
+
+       // public
+       function printDropdown($current_language, $name, $id) {
+               echo '<select name="'.$name.'" id="'.$id.'">';
+
+               foreach ($this->availableLanguages as $codes) {
+                       $language = current($codes);
+                       if ((defined('AT_DEVEL_TRANSLATE') && AT_DEVEL_TRANSLATE) || ($language->getStatus() == AT_LANG_STATUS_PUBLISHED)) {
+                               echo '<option value="'.$language->getCode().'"';
+                               if ($language->getCode() == $current_language) {
+                                       echo ' selected="selected"';
+                               }
+                               echo '>'.$language->getNativeName().'</option>';
+                       }
+               }
+               echo '</select>';
+       }
+
+       // public
+       function printList($current_language, $name, $id, $url) {
+
+               $delim = false;
+               foreach ($this->availableLanguages as $codes) {
+                       $language = current($codes);
+
+                       if ($language->getStatus() == AT_LANG_STATUS_PUBLISHED) {
+
+                               if ($delim){
+                                       echo ' | ';
+                               }
+
+                               if ($language->getCode() == $current_language) {
+                                       echo '<strong>'.$language->getNativeName().'</strong>';
+                               } else {
+                                       echo '<a href="'.$url.'lang='.$language->getCode().'">'.$language->getNativeName().'</a> ';
+                               }
+
+                               $delim = true;
+                       }
+               }
+       }
+
+       // public
+       function getNumLanguages() {
+               return $this->numLanguages;
+       }
+
+       // public
+       // checks whether or not the language exists/is available
+       function exists($code, $locale = '') {
+               if ($locale) {
+                       return isset($this->availableLanguages[$code . AT_LANGUAGE_LOCALE_SEP . $locale]);
+               }
+               return isset($this->availableLanguages[$code]);
+       }
+
+       // public
+       // import language pack from specified file
+       function import($filename) {
+               global $languageManager, $msg;
+
+               $import_path = AT_CONTENT_DIR . 'import/';
+
+               $archive = new PclZip($filename);
+               if ($archive->extract(  PCLZIP_OPT_PATH,        $import_path) == 0) {
+                       exit('Error : ' . $archive->errorInfo(true));
+               }
+
+               $language_xml = @file_get_contents($import_path.'language.xml');
+
+               $languageParser =& new LanguageParser();
+               $languageParser->parse($language_xml);
+               $languageEditor =& $languageParser->getLanguageEditor(0);
+
+               if (($languageEditor->getAtutorVersion() != VERSION) 
+                       && (!defined('AT_DEVEL_TRANSLATE') || !AT_DEVEL_TRANSLATE)) 
+                       {
+                               $msg->addError('LANG_WRONG_VERSION');
+               }
+
+               if (($languageEditor->getStatus() != AT_LANG_STATUS_PUBLISHED) 
+                       && ($languageEditor->getStatus() != AT_LANG_STATUS_COMPLETE) 
+                       && (!defined('AT_DEVEL_TRANSLATE') || !AT_DEVEL_TRANSLATE)) 
+                       {
+                               $msg->addError('LANG_NOT_COMPLETE');
+               }
+
+               if ($languageManager->exists($languageEditor->getCode())) {
+                       $msg->addError('LANG_EXISTS');
+               }
+
+               if (!$msg->containsErrors()) {
+                       $languageEditor->import($import_path . 'language_text.sql');
+                       $msg->addFeedback('IMPORT_LANG_SUCCESS');
+               }
+
+               // remove the files:
+               @unlink($import_path . 'language.xml');
+               @unlink($import_path . 'language_text.sql');
+               @unlink($import_path . 'readme.txt');
+               @unlink($filename);
+       }
+
+       // public
+       // imports LIVE language from the atutor language database
+       function liveImport($language_code) {
+               global $db;
+
+               $tmp_lang_db = mysql_connect(AT_LANG_DB_HOST, AT_LANG_DB_USER, AT_LANG_DB_PASS);
+               if (!$tmp_lang_db) {
+                       /* AT_ERROR_NO_DB_CONNECT */
+                       echo 'Unable to connect to db.';
+                       exit;
+               }
+               if (!mysql_select_db('dev_atutor_langs', $tmp_lang_db)) {
+                       echo 'DB connection established, but database "dev_atutor_langs" cannot be selected.';
+                       exit;
+               }
+
+               $sql = "SELECT * FROM languages_SVN WHERE language_code='$language_code'";
+               $result = mysql_query($sql, $tmp_lang_db);
+
+               if ($row = mysql_fetch_assoc($result)) {
+                       $row['reg_exp'] = addslashes($row['reg_exp']);
+                       $row['native_name'] = addslashes($row['native_name']);
+                       $row['english_name'] = addslashes($row['english_name']);
+
+                       $sql = "REPLACE INTO ".TABLE_PREFIX."languages VALUES ('{$row['language_code']}', '{$row['char_set']}', '{$row['direction']}', '{$row['reg_exp']}', '{$row['native_name']}', '{$row['english_name']}', 3)";
+                       $result = mysql_query($sql, $db);
+
+                       $sql = "SELECT * FROM language_text_SVN WHERE language_code='$language_code'";
+                       $result = mysql_query($sql, $tmp_lang_db);
+
+                       $sql = "REPLACE INTO ".TABLE_PREFIX."language_text VALUES ";
+                       while ($row = mysql_fetch_assoc($result)) {
+                               $row['text'] = addslashes($row['text']);
+                               $row['context'] = addslashes($row['context']);
+                               $sql .= "('{$row['language_code']}', '{$row['variable']}', '{$row['term']}', '{$row['text']}', '{$row['revised_date']}', '{$row['context']}'),";
+                       }
+                       $sql = substr($sql, 0, -1);
+                       mysql_query($sql, $db);
+               }
+       }
+       
+       function getXML() {
+               global $db;
+
+               $lang_xml = '<?xml version="1.0" encoding="iso-8859-1"?>
+               <!-- These are ATutor language packs - http://www.atutor.ca-->
+
+               <!DOCTYPE languages [
+                  <!ELEMENT language (atutor-version, code, charset, direction, reg-exp, native-name, english-name )>
+                  <!ELEMENT atutor-version (#PCDATA)>
+                  <!ELEMENT code (#PCDATA)>
+                  <!ELEMENT charset (#PCDATA)>
+                  <!ELEMENT direction (#PCDATA)>
+                  <!ELEMENT reg-exp (#PCDATA)>
+                  <!ELEMENT native-name (#PCDATA)>
+                  <!ELEMENT english-name (#PCDATA)>
+                  <!ELEMENT status (#PCDATA)>
+                  <!ATTLIST language code ID #REQUIRED>
+               ]>
+
+               <languages>';
+
+               foreach ($this->availableLanguages as $codes) {
+                       foreach ($codes as $language) {
+                               $lang_xml .= $language->getXML(TRUE);
+                       }
+               }
+
+               $lang_xml .= "\r\n".'</languages>';
+
+               return $lang_xml;
+       }
+}
+
+
+?>
\ No newline at end of file
diff --git a/include/classes/Language/LanguageParser.class.php b/include/classes/Language/LanguageParser.class.php
new file mode 100644 (file)
index 0000000..4b4fdde
--- /dev/null
@@ -0,0 +1,115 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+/**
+* LanguageParser
+* Class for parsing XML language info and returning a Language Object
+* @access      public
+* @author      Joel Kronenberg
+* @package     Language
+*/
+class LanguageParser {
+
+       // all private
+       var $parser; // the XML handler
+       var $language_rows = array(); // the language data used for creating the Language Object
+       var $character_data; // tmp variable for storing the data
+       var $element_path; // array of element paths (basically a stack)
+       var $row_num;
+
+       function LanguageParser() {
+               $this->parser = xml_parser_create(''); 
+
+               xml_set_object($this->parser, $this);
+               xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false); /* conform to W3C specs */
+               xml_set_element_handler($this->parser, 'startElement', 'endElement');
+               xml_set_character_data_handler($this->parser, 'characterData');
+       }
+
+       // public
+       function parse($xml_data) {
+               $this->element_path   = array();
+               $this->language_rows  = array();
+               $this->character_data = '';
+               $this->row_num        = 0;
+               xml_parse($this->parser, $xml_data, TRUE);
+       }
+
+       // public
+       function getLanguage($row_num) {
+               return new Language($this->language_rows[$row_num]);
+       }
+
+       // public
+       function getLanguageEditor($row_num) {
+               require_once(AT_INCLUDE_PATH.'classes/Language/LanguageEditor.class.php');
+               return new LanguageEditor($this->language_rows[$row_num]);
+       }
+
+       // private
+       function startElement($parser, $name, $attributes) {
+               array_push($this->element_path, $name);
+
+               if ($this->element_path == array('language')) {
+                       $this->language_rows[$this->row_num]['language_code'] = $attributes['code'];
+               }
+   }
+
+       // private
+       /* called when an element ends */
+       /* removed the current element from the $path */
+       function endElement($parser, $name) {
+               if ($this->element_path == array('language', 'atutor-version')) {
+                       $this->language_rows[$this->row_num]['version'] = trim($this->character_data);
+
+               } else if ($this->element_path === array('language', 'charset')) {
+                       $this->language_rows[$this->row_num]['char_set'] = trim($this->character_data);
+
+               } else if ($this->element_path === array('language', 'direction')) {
+                       $this->language_rows[$this->row_num]['direction'] = trim($this->character_data);
+
+               } else if ($this->element_path === array('language', 'reg-exp')) {
+                       $this->language_rows[$this->row_num]['reg_exp'] = trim($this->character_data);
+
+               } else if ($this->element_path === array('language', 'native-name')) {
+                       $this->language_rows[$this->row_num]['native_name'] = trim($this->character_data);
+
+               } else if ($this->element_path === array('language', 'english-name')) {
+                       $this->language_rows[$this->row_num]['english_name'] = trim($this->character_data);
+
+               } else if ($this->element_path === array('language', 'status')) {
+                       $this->language_rows[$this->row_num]['status'] = trim($this->character_data);
+
+               } else if ($this->element_path === array('language')) {
+                       $this->row_num++;
+               }
+
+               array_pop($this->element_path);
+               $this->character_data = '';
+       }
+
+       // private
+       function characterData($parser, $data){
+               $this->character_data .= $data;
+       }
+
+       // public
+       function getNumLanguages() {
+               return count($this->language_rows);
+       }
+}
+
+
+
+?>
\ No newline at end of file
diff --git a/include/classes/Language/LanguagesParser.class.php b/include/classes/Language/LanguagesParser.class.php
new file mode 100644 (file)
index 0000000..c7faf0d
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+require_once(dirname(__FILE__) . '/LanguageParser.class.php');
+
+/**
+* LanguagesParser
+* Class for parsing XML languages info and returning a Language Objects
+* @access      public
+* @author      Joel Kronenberg
+* @package     Language
+*/
+class LanguagesParser extends LanguageParser {
+
+       // private
+       function startElement($parser, $name, $attributes) {
+               if ($name == 'languages') {
+                       // strip off the initial 'languages'
+                       $this->element_path = array();
+               } else {
+                       parent::startElement($this->parser, $name, $attributes);
+               }
+   }
+}
+
+?>
\ No newline at end of file
diff --git a/include/classes/Language/RemoteLanguageManager.class.php b/include/classes/Language/RemoteLanguageManager.class.php
new file mode 100644 (file)
index 0000000..d270bbd
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+/**
+* RemoteLanguageManager
+* Class for managing available languages as Language Objects.
+* @access      public
+* @author      Joel Kronenberg
+* @see         Language.class.php
+* @package     Language
+*/
+
+require_once(AT_INCLUDE_PATH.'classes/Language/LanguageParser.class.php');
+require_once(AT_INCLUDE_PATH.'classes/Language/LanguagesParser.class.php');
+
+class RemoteLanguageManager extends LanguageManager {
+
+       function RemoteLanguageManager() {
+               $version = str_replace('.','_',VERSION);
+               $language_xml = @file_get_contents('http://update.atutor.ca/languages/'.$version.'/languages.xml');
+               if ($language_xml === FALSE) {
+                       // fix for bug #2896
+                       $language_xml = @file_get_contents('http://update.atutor.ca/languages/1_5_3/languages.xml');
+               }
+               if ($language_xml !== FALSE) {
+
+                       $languageParser =& new LanguagesParser();
+                       $languageParser->parse($language_xml);
+
+                       $this->numLanguages = $languageParser->getNumLanguages();
+
+                       for ($i = 0; $i < $this->numLanguages; $i++) {
+                               $thisLanguage =& new Language($languageParser->getLanguage($i));
+
+                               $this->availableLanguages[$thisLanguage->getCode()][$thisLanguage->getCharacterSet()] =& $thisLanguage;
+                       }
+               } else {
+                       $this->numLanguages = 0;
+                       $this->availableLanguages = array();
+               }
+       }
+
+       // public
+       function fetchLanguage($language_code, $filename) {
+               $version = str_replace('.','_',VERSION);
+
+               $language_pack = @file_get_contents('http://update.atutor.ca/languages/' . $version . '/atutor_' . $version . '_' . $language_code . '.zip');
+
+               if ($language_pack) {
+                       $fp = fopen($filename, 'wb+');
+                       fwrite($fp, $language_pack, strlen($language_pack));
+
+                       return TRUE;
+               }
+               return FALSE;
+       }
+
+       function import($language_code) {
+               $filename = tempnam(AT_CONTENT_DIR . 'import', $language_code);
+               if ($this->fetchLanguage($language_code, $filename)) {
+                       parent::import($filename);
+               }
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/include/classes/Message/Message.class.php b/include/classes/Message/Message.class.php
new file mode 100644 (file)
index 0000000..d664f07
--- /dev/null
@@ -0,0 +1,463 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+
+/**
+* Message
+* Class acting as MessageHandler for various message types
+* @access      public
+* @author      Jacek Materna
+*/
+
+class Message {
+
+       /*
+       * Reference to savant obj.
+       * @access private
+       * @see /include/classes/Savant/Savant.php
+       * @var object   
+       */
+       var $savant;
+       
+       /*
+       * Stastic assoc. array of message types mapped to Savant template file names
+       * @access private
+       * @see /templates/
+       * @var array
+       */
+       var $tmpl = array(      'error' => 'errormessage.tmpl.php',
+                                               'feedback' => 'feedbackmessage.tmpl.php',
+                                               'warning' => 'warningmessage.tmpl.php',
+                                               'info' => 'infomessage.tmpl.php',
+                                               'help' => 'helpmessage.tmpl.php',
+                                               'confirm' => 'confirmmessage.tmpl.php'
+                               );
+       
+       /*
+       * Static assoc array of message types mapped to Language code prefixes
+       * @access private
+       * @see /include/lib/lang_constant.inc.php
+       * @var array    
+       */
+       var $prefix = array( 'error'  =>'AT_ERROR_',
+                                               'feedback' => 'AT_FEEDBACK_',
+                                               'warning' => 'AT_WARNING_',
+                                               'info' => 'AT_INFOS_',
+                                               'help' => 'AT_HELP_',
+                                               'confirm' => 'AT_CONFIRM_'
+                                 );
+       
+       /**
+       * Constructor
+       * @access  public
+       * @param   obj $savant Reference to Savant object
+       * @author  Jacek Materna
+       */
+       function Message($savant) { 
+               $this->savant = $savant;
+       } 
+               
+       /**
+       * Print message(s) of type $type. Processes stored messages in session var for type $type
+       * and translates them into language spec. Then passes processed data to savant template for display
+       * @access  public
+       * @param   string $type                                 error|warning|info|feedback|help|help_pop
+       * @author  Jacek Materna
+       */
+       function printAbstract($type) {
+               if (!isset($_SESSION['message'][$type])) return;
+
+               $_result = array();
+               
+               foreach($_SESSION['message'][$type] as $e => $item) {
+                       $result = '';
+
+                       if ($type == 'confirm') {
+                               // the confirm msg's have the hidden vars as the last element in the array
+                               $last_item = array_pop($item);
+                               if (count($item) == 1) {
+                                       $item = $item[0];
+                               }
+                       }
+
+                       // $item is either just a code or an array of argument with a particular code
+                       if (is_array($item)) {
+       
+                       
+                               /* this is an array with terms to replace */
+                               $first = array_shift($item);
+                               $result = _AT($first); // lets translate the code
+                               
+                               if ($result == '') { // if the code is not in the db lets just print out the code for easier trackdown
+                                       $result = '[' . $first . ']';
+                               }
+                                                                               
+                               $terms = $item;
+                       
+                               /* replace the tokens with the terms */
+                               $result = vsprintf($result, $terms);
+                               
+                       } else {
+                               $result = _AT($item);
+                               if ($result == '') // if the code is not in the db lets just print out the code for easier trackdown
+                                       $result = '[' . $item . ']';
+                       }
+                       
+                       array_push($_result, $result); // append to array
+               }
+               
+               if (count($_result) > 0) {
+                       $this->savant->assign('item', $_result);        // pass translated payload to savant var for processing
+
+                       if ($type == 'confirm') {
+                               $this->savant->assign('hidden_vars', $last_item);
+                               
+                       } else if ($type == 'help') { // special case for help message, we need to check a few conditions
+                               $a = (!isset($_GET['e']) && !$_SESSION['prefs']['PREF_HELP'] && !$_GET['h']);
+                               $b = ($_SESSION['prefs']['PREF_CONTENT_ICONS'] == 2);
+                               $c = isset($_GET['e']);
+                               $d = $_SESSION['course_id'];
+                               
+                               $this->savant->assign('a', $a);
+                               $this->savant->assign('b', $b);
+                               $this->savant->assign('c', $c);
+                               $this->savant->assign('d', $d);
+                       }
+               
+                       $this->savant->display($this->tmpl[$type]);
+               }
+
+               unset($_SESSION['message'][$type]);
+       }
+
+       /**
+       * Add message to be tracked by session obj
+       * @access  public
+       * @param   string $sync                                 ref to type of message
+       * @param   string|array $code                   code of the message or array(code, args...)
+       * @author  Jacek Materna
+       */
+       function addAbstract($sync, $code) {
+               $first = ''; // key value for storage
+               // Convert to strings
+               if (is_array($code)) {
+                       foreach($code as $e) {
+                               settype($e, "string");
+                       }
+
+                       $code[0] = $this->prefix[$sync] . $code[0]; // add prefix               
+
+                       $first = $code[0];
+               } else {
+                       if (!is_string($code))  
+                               settype($code, "string");
+                       
+                       $code = $this->prefix[$sync] . $code;
+                       $first = $code;         
+               }
+               
+               $payload = $code;
+               
+               if (!isset($_SESSION['message'][$sync]) || count($_SESSION['message'][$sync]) == 0) { // fresh
+                       
+                       // PHP 5 
+                       //try {
+                               $_SESSION['message'][$sync] = array($first => $payload);
+                       //} catch (Exception $e) {
+                       //      return false;
+                       //}
+               } else if (isset($_SESSION['message'][$sync][$first])) { // already data there for that code, append
+                       // existing data is either a collection or a single node
+                       if(is_array($_SESSION['message'][$sync][$first])) { // already an array there
+                               if (is_array($payload)) {
+                                       // lets ignore the code, its already there as the first element
+                                       $elem = array_shift($payload);
+                                       foreach($payload as $elem) {
+                                               array_push($_SESSION['message'][$sync][$first], $elem); // add ourselves to the chain
+                                       }
+                               } else // no array here yet
+                                       $_SESSION['message'][$sync][$first][] = $payload; // add ourselves 
+                               
+                       } else { // just a string
+                               if (is_array($payload)) {
+                                       $temp = $_SESSION['message'][$sync][$first]; // grab it
+                                       unset($_SESSION['message'][$sync][$first]); // make sure its gone
+                                       
+                                       $arr = array($temp);
+                                       
+                                       // skip first elem, we're asserting here that $first === $payload[0]
+                                       $grb = array_shift($payload);
+                                       foreach($payload as $elem) { // lets finish building the array
+                                               array_push($arr, $elem);
+                                       }
+                                       
+                                       $_SESSION['message'][$sync][$first] = $arr; // put it back 
+                               }
+                       }
+               } else {
+               
+                       // Already an array there, could be empty or have something in it, append.
+                       // Store key = value for much faster unset as needed 
+                       
+                       // PHP 5
+                       //try {
+                               $new = array($first => $payload);
+                               $final = array_merge((array) $_SESSION['message'][$sync], (array) $new);
+
+                               unset($_SESSION['message'][$sync]);
+                               $_SESSION['message'][$sync] = $final;
+                       //} catch (exception $e) {
+                       //      return false;
+                       //}
+               }
+       }
+       
+       /**
+       * Simply check is a type $type message isset in the session obj
+       * @access  public
+       * @param   string $type                                 what type of message to check for
+       * @author  Jacek Materna
+       */
+       function abstractContains($type) {
+               return (isset($_SESSION['message'][$type]));
+       }
+       
+       /**
+       * Deletes the tracked message code $code from the Session obj as well as all 
+       * if its children
+       * @access  public
+       * @param   string $type                                 what type of message to delete
+       # @param   string $code                                 The code to delete
+       * @author  Jacek Materna
+       */
+       function abstractDelete($type, $code) {
+               if (!is_string($code))
+                       settype($code, "string");
+
+               // Lets append the right prefic to this code for searching
+               $code = $this->prefix[$type] . $code;
+       
+               if(isset($_SESSION['message'][$type][$code])) {
+                       unset($_SESSION['message'][$type][$code]); // delete it and its children
+               }
+       }
+       
+       /**
+       * Add error message to be tracked by session obj
+       * @access  public
+       * @param   string|array $code                   code of the message or array(code, args...)
+       * @author  Jacek Materna
+       */
+       function addError($code) {
+               $this->addAbstract('error', $code);
+       }
+       
+       /**
+       * Print error messages using Savant template
+       * @access  public
+       * @author  Jacek Materna
+       */
+       function printErrors($optional=null) {
+               if ($optional != null)  // shortcut
+                       $this->addAbstract('error', $optional);
+
+               $this->printAbstract('error');
+       }
+       
+
+       function addConfirm($code, $hidden_vars = '') {
+               $hidden_vars_string = '';
+               if (is_array($hidden_vars)) {
+                       foreach ($hidden_vars as $key => $value) {
+                               $hidden_vars_string .= '<input type="hidden" name="'.$key.'" value="'.$value.'" />';
+                       }
+               }
+               if (!is_array($code)) {
+                       $code = array($code);
+               }
+               $code[] = $hidden_vars_string;
+               $this->addAbstract('confirm', $code);
+       }
+       
+       function printConfirm($optional=null) {
+               if ($optional != null)  // shortcut
+                       $this->addAbstract('confirm', $optional);
+
+               $this->printAbstract('confirm');
+       }
+
+       /**
+       * Add warning message to be tracked by session obj
+       * @access  public
+       * @param   string|array $code                   code of the message or array(code, args...)
+       * @author  Jacek Materna
+       */
+       function addWarning($code) { 
+               $this->addAbstract('warning', $code);
+       }
+       
+       /**
+       * Print warning messages using Savant template
+       * @access  public
+       * @author  Jacek Materna
+       */
+       function printWarnings($optional=null) {
+               if ($optional != null)  // shortcut
+                       $this->addAbstract('warning', $optional);
+               
+               $this->printAbstract('warning');
+       }
+       
+       /**
+       * Add info message to be tracked by session obj
+       * @access  public
+       * @param   string|array $code                   code of the message or array(code, args...)
+       * @author  Jacek Materna
+       */
+       function addInfo($code) { 
+               $this->addAbstract('info', $code);
+       }
+       
+       /**
+       * Print info messages using Savant template
+       * @access  public
+       * @author  Jacek Materna
+       */
+       function printInfos($optional=null) { 
+               if ($optional != null)  // shortcut
+                       $this->addAbstract('info', $optional);
+
+               $this->printAbstract('info');
+       }
+       
+       /**
+       * Add feedback message to be tracked by session obj
+       * @access  public
+       * @param   string|array $code                   code of the message or array(code, args...)
+       * @author  Jacek Materna
+       */
+       function addFeedback($code) { 
+               $this->addAbstract('feedback', $code); 
+       }
+       
+       /**
+       * Print feedback messages using Savant template
+       * @access  public
+       * @author  Jacek Materna
+       */
+       function printFeedbacks($optional=null) {
+               if ($optional != null) // shortcut
+                       $this->addAbstract('feedback', $optional); 
+                       
+               $this->printAbstract('feedback');
+       }
+       
+       /**
+       * Add help message to be tracked by session obj
+       * @access  public
+       * @param   string|array $code                   code of the message or array(code, args...)
+       * @author  Jacek Materna
+       */
+       function addHelp($code) { 
+               $this->addAbstract('help', $code);
+       }
+       
+       /**
+       * Print help messages using Savant template
+       * @access  public
+       * @author  Jacek Materna
+       */
+       function printHelps($optional=null) {
+               if ($optional != null)  // shortcut
+                       $this->addAbstract('help', $optional);
+                       
+               $this->printAbstract('help');
+       }
+        
+       /**
+       * Dump all the messages in the session to the screen in the following order
+       * @access  public
+       * @author  Jacek Materna
+       */
+       function printAll() {
+               $this->printAbstract('feedback');
+               $this->printAbstract('error');
+               $this->printAbstract('warning');
+               $this->printAbstract('help');
+               $this->printAbstract('info');
+       }
+       
+       /**
+       * Print feedback message using Savant template with no Session dialog and
+       * no database dialog, straight text inside feedback box
+       * @access  public
+       * @param String String message to display inside feedback box
+       * @author  Jacek Materna
+       */
+       function printNoLookupFeedback($str) {
+               if (str != null) {
+                       $this->savant->assign('item', array($str));     // pass string to savant var for processing
+                       $this->savant->display($this->tmpl['feedback']);
+               }
+       }
+       
+       /**
+        * Method which simply check if a particular message type exists in the session obj
+        */
+       function containsErrors() {
+               return $this->abstractContains('error');
+       }
+       
+       function containsFeedbacks() {
+               return $this->abstractContains('feedback');
+       }
+       
+       function containsWarnings() {
+               return $this->abstractContains('warning');
+       }
+       
+       function containsInfos() {
+               return $this->abstractContains('info');
+       }
+       
+       function containsHelps() {
+               return $this->abstractContains('help');
+       }
+       
+       /**
+        * Method that allow deletion of individual Message codes form the Session obj
+        */
+       function deleteError($code) {
+               $this->abstractDelete('error', $code);
+       }
+       
+       function deleteFeedback($code) {
+               $this->abstractDelete('feedback', $code);
+       }
+       
+       function deleteWarning($code) {
+               $this->abstractDelete('warning', $code);
+       }
+       
+       function deleteInfo($code) {
+               $this->abstractDelete('info', $code);
+       }
+       
+       function deleteHelp($code) {
+               $this->abstractDelete('help', $code);
+       }
+       
+} // end of class
+
+
+
+?>
\ No newline at end of file
diff --git a/include/classes/Module/Module.class.php b/include/classes/Module/Module.class.php
new file mode 100644 (file)
index 0000000..12ea2d7
--- /dev/null
@@ -0,0 +1,605 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_MODULE_STATUS_DISABLED',    1);
+define('AT_MODULE_STATUS_ENABLED',     2);
+define('AT_MODULE_STATUS_MISSING',     4);
+define('AT_MODULE_STATUS_UNINSTALLED', 8); // not in the db
+
+define('AT_MODULE_TYPE_CORE',     1);
+define('AT_MODULE_TYPE_STANDARD', 2);
+define('AT_MODULE_TYPE_EXTRA',    4);
+
+define('AT_MODULE_DIR_CORE',     '_core');
+define('AT_MODULE_DIR_STANDARD', '_standard');
+
+define('AT_MODULE_PATH', realpath(AT_INCLUDE_PATH.'../mods') . DIRECTORY_SEPARATOR);
+
+/**
+* ModuleFactory
+* 
+* @access      public
+* @author      Joel Kronenberg
+* @package     Module
+*/
+class ModuleFactory {
+       // private
+       var $_modules = NULL; // array of module refs
+
+       function ModuleFactory($auto_load = FALSE) {
+               global $db;
+
+               /* snippit to use when extending Module classes:
+               $sql    = "SELECT dir_name, privilege, admin_privilege, status FROM ". TABLE_PREFIX . "modules WHERE status=".AT_MODULE_STATUS_ENABLED;
+               $result = mysql_query($sql, $db);
+               $row = mysql_fetch_assoc($result);
+               require(AT_MODULE_PATH . $row['dir_name'].'/module.php');
+               $module =& new PropertiesModule($row);
+               ***/
+
+               $this->_modules = array();
+
+               if ($auto_load == TRUE) {
+                       // initialise enabled modules
+                       $sql    = "SELECT dir_name, privilege, admin_privilege, status, cron_interval, cron_last_run FROM ". TABLE_PREFIX . "modules WHERE status=".AT_MODULE_STATUS_ENABLED;
+                       $result = mysql_query($sql, $db);
+                       while($row = mysql_fetch_assoc($result)) {
+                               $module =& new Module($row);
+                               $this->_modules[$row['dir_name']] =& $module;
+                               $module->load();
+                       }
+               }
+       }
+
+       // public
+       // status := enabled | disabled | uninstalled | missing
+       // type  := core | standard | extra
+       // sort  := true | false (by name only)
+       // the results of this method are not cached. call sparingly.
+       function & getModules($status, $type = 0, $sort = FALSE) {
+               global $db;
+
+               $modules     = array();
+               $all_modules = array();
+
+               if ($type == 0) {
+                       $type = AT_MODULE_TYPE_CORE | AT_MODULE_TYPE_STANDARD | AT_MODULE_TYPE_EXTRA;
+               }
+
+               $sql    = "SELECT dir_name, privilege, admin_privilege, status, cron_interval, cron_last_run FROM ". TABLE_PREFIX . "modules";
+               $result = mysql_query($sql, $db);
+               while($row = mysql_fetch_assoc($result)) {
+                       if (!isset($this->_modules[$row['dir_name']])) {
+                               $module =& new Module($row);
+                       } else {
+                               $module =& $this->_modules[$row['dir_name']];
+                       }
+                       $all_modules[$row['dir_name']] =& $module;
+               }
+
+               // small performance addition:
+               if ($status & AT_MODULE_STATUS_UNINSTALLED) {
+                       $dir = opendir(AT_MODULE_PATH);
+                       while (false !== ($dir_name = readdir($dir))) {
+                               if (($dir_name == '.') 
+                                       || ($dir_name == '..') 
+                                       || ($dir_name == '.svn') 
+                                       || ($dir_name == AT_MODULE_DIR_CORE) 
+                                       || ($dir_name == AT_MODULE_DIR_STANDARD)) {
+                                       continue;
+                               }
+
+                               if (is_dir(AT_MODULE_PATH . $dir_name) && !isset($all_modules[$dir_name])) {
+                                       $module =& new Module($dir_name);
+                                       $all_modules[$dir_name] =& $module;
+                               }
+                       }
+                       closedir($dir);
+               }
+
+               $keys = array_keys($all_modules);
+               foreach ($keys as $dir_name) {
+                       $module =& $all_modules[$dir_name];
+                       if ($module->checkStatus($status) && $module->checkType($type)) {
+                               $modules[$dir_name] =& $module;
+                       }
+               }
+
+               if ($sort) {
+                       uasort($modules, array($this, 'compare'));
+               }
+               return $modules;
+       }
+
+       // public.
+       function & getModule($module_dir) {
+               if (!isset($this->_modules[$module_dir])) {
+                       global $db;
+                       $sql    = "SELECT dir_name, privilege, admin_privilege, status FROM ". TABLE_PREFIX . "modules WHERE dir_name='$module_dir'";
+                       $result = mysql_query($sql, $db);
+                       if ($row = mysql_fetch_assoc($result)) {
+                               $module =& new Module($row);
+                       } else {
+                               $module =& new Module($module_dir);
+                       }
+                       $this->_modules[$module_dir] =& $module;
+               }
+               return $this->_modules[$module_dir];
+       }
+
+       // private
+       // used for sorting modules
+       function compare($a, $b) {
+               return strnatcasecmp($a->getName(), $b->getName());
+       }
+}
+
+/**
+* Module
+* 
+* @access      public
+* @author      Joel Kronenberg
+* @package     Module
+*/
+class Module {
+       // private
+       var $_moduleObj;
+       var $_directoryName;
+       var $_status; // core|enabled|disabled
+       var $_privilege; // priv bit(s) | 0 (in dec form)
+       var $_admin_privilege; // priv bit(s) | 0 (in dec form)
+       var $_display_defaults; // bit(s)
+       var $_pages;
+       var $_type; // core, standard, extra
+       var $_properties; // array from xml
+       var $_cron_interval; // cron interval
+       var $_cron_last_run; // cron last run date stamp
+
+       // constructor
+       function Module($row) {
+               if (is_array($row)) {
+                       $this->_directoryName   = $row['dir_name'];
+                       $this->_status          = $row['status'];
+                       $this->_privilege       = $row['privilege'];
+                       $this->_admin_privilege = $row['admin_privilege'];
+                       $this->_display_defaults= isset($row['display_defaults']) ? $row['display_defaults'] : 0;
+                       $this->_cron_interval   = $row['cron_interval'];
+                       $this->_cron_last_run   = $row['cron_last_run'];
+
+                       if (strpos($row['dir_name'], AT_MODULE_DIR_CORE) === 0) {
+                               $this->_type = AT_MODULE_TYPE_CORE;
+                       } else if (strpos($row['dir_name'], AT_MODULE_DIR_STANDARD) === 0) {
+                               $this->_type = AT_MODULE_TYPE_STANDARD;
+                       } else {
+                               $this->_type = AT_MODULE_TYPE_EXTRA;
+                       }
+               } else {
+                       $this->_directoryName   = $row;
+                       $this->_status          = AT_MODULE_STATUS_UNINSTALLED;
+                       $this->_privilege       = 0;
+                       $this->_admin_privilege = 0;
+                       $this->_display_defaults= 0;
+                       $this->_type            = AT_MODULE_TYPE_EXTRA; // standard/core are installed by default
+               }
+       }
+
+       // statuses
+       function checkStatus($status) { return (bool) ($status & $this->_status); }
+       function isUninstalled()  { return ($this->_status == AT_MODULE_STATUS_UNINSTALLED) ? true : false; }
+       function isEnabled()      { return ($this->_status == AT_MODULE_STATUS_ENABLED)     ? true : false; }
+       function isDisabled()     { return ($this->_status == AT_MODULE_STATUS_DISABLED)    ? true : false; }
+       function isMissing()      { return ($this->_status == AT_MODULE_STATUS_MISSING)     ? true : false; }
+
+       // types
+       function checkType($type) { return (bool) ($type & $this->_type); }
+       function isCore()     { return ($this->_type == AT_MODULE_TYPE_CORE)     ? true : false; }
+       function isStandard() { return ($this->_type == AT_MODULE_TYPE_STANDARD) ? true : false; }
+       function isExtra()    { return ($this->_type == AT_MODULE_TYPE_EXTRA)    ? true : false; }
+
+       // privileges
+       function getPrivilege()      { return $this->_privilege;       }
+       function getAdminPrivilege() { return $this->_admin_privilege; }
+
+       function load() {
+               if (is_file(AT_MODULE_PATH . $this->_directoryName.'/module.php')) {
+                       global $_modules, $_pages, $_stacks;
+
+                       require(AT_MODULE_PATH . $this->_directoryName.'/module.php');
+
+                       if (isset($this->_pages)) {
+                               $_pages = array_merge_recursive((array) $_pages, $this->_pages);
+                       }
+
+                       //side menu items
+                       if (isset($this->_stacks)) {
+                               $count = 0;
+                               $_stacks = array_merge((array)$_stacks, $this->_stacks);
+                       }
+
+                       //student tools
+                       if (isset($_student_tool)) {
+                               $this->_student_tool =& $_student_tool;
+                               $_modules[] = $this->_student_tool;
+                       }
+
+                       //group tools
+                       if (isset($_group_tool)) {
+                               $this->_group_tool =& $_group_tool;
+                       }
+               }                                       
+       }
+
+       // private
+       function _initModuleProperties() {
+               if (!isset($this->_properties)) {
+                       require_once(dirname(__FILE__) . '/ModuleParser.class.php');
+                       $moduleParser   =& new ModuleParser();
+                       $moduleParser->parse(@file_get_contents(AT_MODULE_PATH . $this->_directoryName.'/module.xml'));
+                       if ($moduleParser->rows[0]) {
+                               $this->_properties = $moduleParser->rows[0];
+                       } else {
+                               $this->_properties = array();
+                               $this->setIsMissing(); // the xml file may not be found -> the dir may be missing.
+                       }
+               }
+       }
+
+       /**
+       * Get the properties of this module as found in the module.xml file
+       * @access  public
+       * @param   array $properties_list       list of property names
+       * @return  array associative array of property/value pairs
+       * @author  Joel Kronenberg
+       */
+       function getProperties($properties_list) {
+               $this->_initModuleProperties();
+
+               if (!$this->_properties) {
+                       return;
+               }
+               $properties_list = array_flip($properties_list);
+               foreach ($properties_list as $property => $garbage) {
+                       $properties_list[$property] = $this->_properties[$property];
+               }
+               return $properties_list;
+       }
+       /**
+       * Get a single property as found in the module.xml file
+       * @access  public
+       * @param   string $property     name of the property to return
+       * @return  string the value of the property 
+       * @author  Joel Kronenberg
+       */
+       function getProperty($property) {
+               $this->_initModuleProperties();
+
+               if (!$this->_properties) {
+                       return;
+               }
+
+               return $this->_properties[$property];
+       }
+
+       function getCronInterval() {
+               return $this->_cron_interval;
+
+       }
+
+       function getName() {
+               if ($this->isUninstalled()) {
+                       $name = $this->getProperty('name');
+                       return current($name);
+               }
+               return _AT(basename($this->_directoryName));
+       }
+
+       function getDescription($lang = 'en') {
+               $this->_initModuleProperties();
+
+               if (!$this->_properties) {
+                       return;
+               }
+
+               if (isset($this->_properties['description'][$lang])) {
+                       return $this->_properties['description'][$lang];
+               }
+               $description = current($this->_properties['description']);
+               return $description;
+       }
+
+       function getChildPage($page) {
+               if (!is_array($this->_pages)) {
+                       return;
+               }
+               foreach ($this->_pages as $tmp_page => $item) {
+                       if (!empty($item['parent']) && $item['parent'] == $page) {
+                               return $tmp_page;
+                       }
+               }
+       }
+
+       /**
+       * Checks whether or not this module can be backed-up
+       * @access  public
+       * @return  boolean true if this module can be backed-up, false otherwise
+       * @author  Joel Kronenberg
+       */
+       function isBackupable() {
+               return is_file(AT_MODULE_PATH . $this->_directoryName.'/module_backup.php');
+       }
+
+       function createGroup($group_id) {
+               if (is_file(AT_MODULE_PATH . $this->_directoryName.'/module_groups.php')) {
+                       require_once(AT_MODULE_PATH . $this->_directoryName.'/module_groups.php');
+                       $fn_name = basename($this->_directoryName) .'_create_group';
+                       $fn_name($group_id);
+               }
+       }
+
+       function deleteGroup($group_id) {
+               $fn_name = basename($this->_directoryName) .'_delete_group';
+
+               if (!function_exists($fn_name) && is_file(AT_MODULE_PATH . $this->_directoryName.'/module_groups.php')) {
+                       require_once(AT_MODULE_PATH . $this->_directoryName.'/module_groups.php');
+               } 
+               if (function_exists($fn_name)) {
+                       $fn_name($group_id);
+               }
+       }
+
+       function getGroupTool() {
+               if (!isset($this->_group_tool)) {
+                       return;
+               } 
+
+               return $this->_group_tool;
+       }
+
+       function isGroupable() {
+               return is_file(AT_MODULE_PATH . $this->_directoryName.'/module_groups.php');
+       }
+
+       /**
+       * Backup this module for a given course
+       * @access  public
+       * @param   int          $course_id      ID of the course to backup
+       * @param   object       $zipfile        a reference to a zipfile object
+       * @author  Joel Kronenberg
+       */
+       function backup($course_id, &$zipfile) {
+               static $CSVExport;
+
+               if (!isset($CSVExport)) {
+                       require_once(AT_INCLUDE_PATH . 'classes/CSVExport.class.php');
+                       $CSVExport = new CSVExport();
+               }
+               $now = time();
+
+               if ($this->isBackupable()) {
+                       require(AT_MODULE_PATH . $this->_directoryName . '/module_backup.php');
+                       if (isset($sql)) {
+                               foreach ($sql as $file_name => $table_sql) {
+                                       $content = $CSVExport->export($table_sql, $course_id);
+                                       if ($content) {
+                                               $zipfile->add_file($content, $file_name . '.csv', $now);
+                                       }
+                               }
+                       }
+
+                       if (isset($dirs)) {
+                               foreach ($dirs as $dir => $path) {
+                                       $path = str_replace('?', $course_id, $path);
+
+                                       $zipfile->add_dir($path , $dir);
+                               }
+                       }
+               }
+       }
+
+       /**
+       * Restores this module into the given course
+       * @access  public
+       * @param   int          $course_id      ID of the course to restore into
+       * @param   string       $version        version number of the ATutor installation used to make this backup
+       * @param   string       $import_dir     the path to the import directory
+       * @author  Joel Kronenberg
+       */
+       function restore($course_id, $version, $import_dir) {
+               static $CSVImport;
+               if (!file_exists(AT_MODULE_PATH . $this->_directoryName.'/module_backup.php')) {
+                       return;
+               }
+
+               if (!isset($CSVImport)) {
+                       require_once(AT_INCLUDE_PATH . 'classes/CSVImport.class.php');
+                       $CSVImport = new CSVImport();
+               }
+
+               require(AT_MODULE_PATH . $this->_directoryName.'/module_backup.php');
+
+               if (isset($sql)) {
+                       foreach ($sql as $table_name => $table_sql) {
+                               $CSVImport->import($table_name, $import_dir, $course_id, $version);
+                       }
+               }
+               if (isset($dirs)) {
+                       foreach ($dirs as $src => $dest) {
+                               $dest = str_replace('?', $course_id, $dest);
+                               copys($import_dir.$src, $dest);
+                       }
+               }
+       }
+
+       /**
+       * Delete this module's course content. If $groups is specified then it will
+       * delete all content for the groups specified.
+       * @access  public
+       * @param   int   $course_id     ID of the course to delete
+       * @param   array $groups    Array of groups to delete
+       * @author  Joel Kronenberg
+       */
+       function delete($course_id, $groups) {
+               if (is_file(AT_MODULE_PATH . $this->_directoryName.'/module_delete.php')) {
+                       require(AT_MODULE_PATH . $this->_directoryName.'/module_delete.php');
+                       if (function_exists(basename($this->_directoryName).'_delete')) {
+                               $fnctn = basename($this->_directoryName).'_delete';
+                               $fnctn($course_id);
+                       }
+               }
+               if ($groups) {
+                       foreach ($groups as $group_id) {
+                               $this->deleteGroup($group_id);
+                       }
+               }
+       }
+
+       /**
+       * Enables the installed module
+       * @access  public
+       * @author  Joel Kronenberg
+       */
+       function enable() {
+               global $db;
+
+               $sql = 'UPDATE '. TABLE_PREFIX . 'modules SET status='.AT_MODULE_STATUS_ENABLED.' WHERE dir_name="'.$this->_directoryName.'"';
+               $result = mysql_query($sql, $db);
+       }
+
+       /**
+       * Sets the status to missing if the module dir doesn't exist.
+       * @access  public
+       * @param   boolean $force whether or not to force the module to be missing (used for bundled extra modules upon upgrade)
+       * @author  Joel Kronenberg
+       */
+       function setIsMissing($force = false) {
+               global $db;
+               // if the directory doesn't exist then set the status to MISSING
+               if ($force || !is_dir(AT_MODULE_PATH . $this->_directoryName)) {
+                       $sql = 'UPDATE '. TABLE_PREFIX . 'modules SET status='.AT_MODULE_STATUS_MISSING.' WHERE dir_name="'.$this->_directoryName.'"';
+                       $result = mysql_query($sql, $db);
+               }
+       }
+
+       /**
+       * Disables the installed module
+       * @access  public
+       * @author  Joel Kronenberg
+       */
+       function disable() {
+               global $db;
+
+               // remove any privileges admins, students
+               if ($this->_privilege > 1) {
+                       $sql = 'UPDATE '. TABLE_PREFIX . 'course_enrollment SET `privileges`=`privileges`-'.$this->_privilege.' WHERE `privileges` > 1 AND (`privileges` & '.$this->_privilege.')<>0';
+                       $result = mysql_query($sql, $db);
+               }
+
+               if ($this->_admin_privilege > 1) {
+                       $sql = 'UPDATE '. TABLE_PREFIX . 'admins SET `privileges`=`privileges`-'.$this->_admin_privilege.' WHERE `privileges` > 1 AND (`privileges` & '.$this->_admin_privilege.')<>0';
+                       $result = mysql_query($sql, $db);
+               }
+
+               $sql = 'UPDATE '. TABLE_PREFIX . 'modules SET status='.AT_MODULE_STATUS_DISABLED.' WHERE dir_name="'.$this->_directoryName.'"';
+               $result = mysql_query($sql, $db);
+
+               if (function_exists(basename($this->_directoryName).'_disable')) {
+                       $fn_name = basename($this->_directoryName).'_disable';
+                       $fn_name();
+               }
+       }
+
+       /**
+       * Installs the module
+       * @access  public
+       * @author  Joel Kronenberg
+       */
+       function install() {
+               global $msg;
+
+               // should check if this module is already installed...
+
+               if (file_exists(AT_MODULE_PATH . $this->_directoryName . '/module_install.php')) {
+                       require(AT_MODULE_PATH . $this->_directoryName . '/module_install.php');
+               }
+
+               if (!$msg->containsErrors()) {
+                       global $db;
+
+                       $sql = "SELECT MAX(`privilege`) AS `privilege`, MAX(admin_privilege) AS admin_privilege FROM ".TABLE_PREFIX."modules";
+                       $result = mysql_query($sql, $db);
+                       $row = mysql_fetch_assoc($result);
+
+                       if (($_course_privilege === TRUE) || ((string) $_course_privilege == 'new')) {
+                               $priv = $row['privilege'] * 2;
+                       } else if ($_course_privilege == AT_PRIV_ADMIN) {
+                               $priv = AT_PRIV_ADMIN;
+                       } else {
+                               $priv = 0;
+                       }
+
+                       if (($_admin_privilege === TRUE) || ((string) $_admin_privilege == 'new')) {
+                               $admin_priv = $row['admin_privilege'] * 2;
+                       } else {
+                               $admin_priv = AT_ADMIN_PRIV_ADMIN;
+                       }
+
+                       if (isset($_cron_interval)) {
+                               $_cron_interval = abs($_cron_interval);
+                       } else {
+                               $_cron_interval = 0;
+                       }
+
+                       $sql = 'INSERT INTO '. TABLE_PREFIX . 'modules VALUES ("'.$this->_directoryName.'", '.AT_MODULE_STATUS_DISABLED.', '.$priv.', '.$admin_priv.', '.$_cron_interval.', 0)';
+                       mysql_query($sql, $db);
+                       if (mysql_affected_rows($db) != 1) {
+                               // in case this module has to be re-installed (because it was Missing)
+                               $sql = 'UPDATE '. TABLE_PREFIX . 'modules SET status='.AT_MODULE_STATUS_DISABLED.' WHERE dir_name="'.$this->_directoryName.'"';
+                               mysql_query($sql, $db);
+                       }
+               }
+       }
+
+       function getStudentTools() {
+               if (!isset($this->_student_tool)) {
+                       return FALSE;
+               } 
+
+               return $this->_student_tool;
+       }
+
+
+       function runCron() {
+               if ( ($this->_cron_last_run + ($this->_cron_interval * 60)) < time()) {
+                       if (is_file(AT_MODULE_PATH . $this->_directoryName.'/module_cron.php')) {
+                               require(AT_MODULE_PATH . $this->_directoryName.'/module_cron.php');
+                               if (function_exists(basename($this->_directoryName).'_cron')) {
+                                       $fnctn = basename($this->_directoryName).'_cron';
+                                       $fnctn();
+                               }
+                       }
+                       $this->updateCronLastRun();
+               }
+       }
+
+       // i'm private! update the last time the cron was run
+       function updateCronLastRun() {
+               global $db;
+
+               $sql = "UPDATE ".TABLE_PREFIX."modules SET cron_last_run=".time()." WHERE dir_name='$this->_directoryName'";
+               mysql_query($sql, $db);
+
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/include/classes/Module/ModuleParser.class.php b/include/classes/Module/ModuleParser.class.php
new file mode 100644 (file)
index 0000000..90bc130
--- /dev/null
@@ -0,0 +1,131 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+/**
+* ModuleParser
+* Class for parsing XML module info and returning a Module Object
+* @access      public
+* @author      Joel Kronenberg
+* @package     Module
+*/
+class ModuleParser {
+
+       // all private
+       var $parser; // the XML handler
+       var $rows = array(); // the module data used for creating the Module Object
+       var $character_data; // tmp variable for storing the data
+       var $element_path; // array of element paths (basically a stack)
+       var $row_num;
+       var $maintainer_num;
+
+       var $maintainers = array();
+       var $attributes;
+
+       function ModuleParser() {
+       }
+
+       // public
+       function parse($xml_data) {
+               $this->element_path = array();
+               $this->rows         = array();
+               $this->character_data = '';
+               $this->row_num        = 0;
+               $this->maintainer_num = 0;
+
+               $this->parser = xml_parser_create(''); 
+
+               xml_set_object($this->parser, $this);
+               xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false); /* conform to W3C specs */
+               xml_set_element_handler($this->parser, 'startElement', 'endElement');
+               xml_set_character_data_handler($this->parser, 'characterData');
+               xml_parse($this->parser, $xml_data, TRUE);
+       }
+
+       // public
+       function getModule($row_num) {
+               return new Module($this->rows[$row_num]);
+       }
+
+       // public
+       function getNewModule($row_num) {
+               //return new LanguageEditor($this->language_rows[$row_num]);
+       }
+
+       // private
+       function startElement($parser, $name, $attributes) {
+               array_push($this->element_path, $name);
+
+               $this->attributes = $attributes;
+   }
+
+       // private
+       /* called when an element ends */
+       /* removed the current element from the $path */
+       function endElement($parser, $name) {
+               if ($this->element_path == array('module', 'name')) {
+                       if (isset($this->attributes['lang'])) {
+                               $this->rows[$this->row_num]['name'][$this->attributes['lang']] = trim($this->character_data);
+                       } else {
+                               $this->rows[$this->row_num]['name'][] = trim($this->character_data);
+                       }
+
+               } else if ($this->element_path === array('module', 'description')) {
+                       if (isset($this->attributes['lang'])) {
+                               $this->rows[$this->row_num]['description'][$this->attributes['lang']] = trim($this->character_data);
+                       } else {
+                               $this->rows[$this->row_num]['description'][] = trim($this->character_data);
+                       }
+
+               } else if ($this->element_path === array('module', 'url')) {
+                       $this->rows[$this->row_num]['url'] = trim($this->character_data);
+
+               } else if ($this->element_path === array('module', 'license')) {
+                       $this->rows[$this->row_num]['license'] = trim($this->character_data);
+
+               } else if ($this->element_path === array('module', 'maintainers', 'maintainer', 'name')) {
+                       $this->rows[$this->row_num]['maintainers'][$this->maintainer_num]['name'] = trim($this->character_data);
+
+               } else if ($this->element_path === array('module', 'maintainers', 'maintainer', 'email')) {
+                       $this->rows[$this->row_num]['maintainers'][$this->maintainer_num]['email'] = trim($this->character_data);
+
+                       $this->maintainer_num++;
+
+               } else if ($this->element_path === array('module', 'release', 'version')) {
+                       $this->rows[$this->row_num]['version'] = trim($this->character_data);
+
+               } else if ($this->element_path === array('module', 'release', 'date')) {
+                       $this->rows[$this->row_num]['date'] = trim($this->character_data);
+
+               } else if ($this->element_path === array('module', 'release', 'state')) {
+                       $this->rows[$this->row_num]['state'] = trim($this->character_data);
+
+               } else if ($this->element_path === array('module', 'release', 'notes')) {
+                       $this->rows[$this->row_num]['notes'] = trim($this->character_data);
+
+               } else if ($this->element_path === array('module')) {
+                       $this->row_num++;
+               }
+               array_pop($this->element_path);
+               $this->character_data = '';
+       }
+
+       // private
+       function characterData($parser, $data){
+               $this->character_data .= $data;
+       }
+
+}
+
+
+?>
\ No newline at end of file
diff --git a/include/classes/Savant2/Savant2.php b/include/classes/Savant2/Savant2.php
new file mode 100644 (file)
index 0000000..8e8acf3
--- /dev/null
@@ -0,0 +1,1793 @@
+<?php
+
+/**
+* 
+* Error constants.
+* 
+*/
+
+define('SAVANT2_ERROR_ASSIGN',       -1);
+define('SAVANT2_ERROR_ASSIGNREF',    -2);
+define('SAVANT2_ERROR_COMPILER',     -3);
+define('SAVANT2_ERROR_NOFILTER',     -4);
+define('SAVANT2_ERROR_NOPLUGIN',     -5);
+define('SAVANT2_ERROR_NOSCRIPT',     -6);
+define('SAVANT2_ERROR_NOTEMPLATE',   -7);
+define('SAVANT2_ERROR_COMPILE_FAIL', -8);
+
+
+/**
+* 
+* Error messages.
+* 
+*/
+
+if (! isset($GLOBALS['_SAVANT2']['error'])) {
+       $GLOBALS['_SAVANT2']['error'] = array(
+               SAVANT2_ERROR_ASSIGN       => 'assign() parameters not correct',
+               SAVANT2_ERROR_ASSIGNREF    => 'assignRef() parameters not correct',
+               SAVANT2_ERROR_COMPILER     => 'compiler not an object or has no compile() method',
+               SAVANT2_ERROR_NOFILTER     => 'filter file not found',
+               SAVANT2_ERROR_NOPLUGIN     => 'plugin file not found',
+               SAVANT2_ERROR_NOSCRIPT     => 'compiled template script file not found',
+               SAVANT2_ERROR_NOTEMPLATE   => 'template source file not found',
+               SAVANT2_ERROR_COMPILE_FAIL => 'template source failed to compile'
+       );
+}
+
+
+/**
+* 
+* Provides an object-oriented template system.
+* 
+* Savant2 helps you separate model logic from view logic using PHP as
+* the template language. By default, Savant2 does not compile templates.
+* However, you may pass an optional compiler object to compile template
+* source to include-able PHP code.
+* 
+* Please see the documentation at {@link http://phpsavant.com/}, and be
+* sure to donate! :-)
+* 
+* $Id: Savant2.php,v 1.32 2006/03/05 16:58:38 pmjones Exp $
+* 
+* @author Paul M. Jones <pmjones@ciaweb.net>
+* 
+* @package Savant2
+* 
+* @version 2.4.3 stable
+* 
+* @license LGPL http://www.gnu.org/copyleft/lesser.html
+* 
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 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
+* Lesser General Public License for more details.
+* 
+*/
+
+class Savant2 {
+       
+       
+       /**
+       * 
+       * PHP5 ONLY:  Whether or not to use __autoload().  Default is false.
+       * 
+       * @access private
+       * 
+       * @var bool
+       * 
+       */
+       
+       var $_autoload = false;
+       
+       
+       /**
+       * 
+       * PHP5 ONLY: What method __call() will alias to.
+       * 
+       * Generally 'plugin' or 'splugin' (as __call() is intended for those).
+       * 
+       * @access private
+       * 
+       * @var string
+       * 
+       */
+       
+       var $_call = 'plugin';
+       
+       
+       /**
+       * 
+       * The custom compiler (pre-processor) object, if any.
+       * 
+       * @access private
+       * 
+       * @var object
+       * 
+       */
+       
+       var $_compiler = null;
+       
+       
+       /**
+       * 
+       * The class type to use when instantiating error objects.
+       * 
+       * @access private
+       * 
+       * @var string
+       * 
+       */
+       
+       var $_error = null;
+       
+       
+       /**
+       * 
+       * Array of callbacks used to escape output.
+       * 
+       * @access private
+       * 
+       * @var array
+       * 
+       * @see setEscape()
+       * 
+       * @see addEscape()
+       * 
+       * @see escape()
+       * 
+       * @see _()
+       * 
+       */
+       
+       var $_escape = array('htmlspecialchars');
+       
+       
+       /**
+       * 
+       * Whether or not to extract assigned variables into fetch() scope.
+       * 
+       * When true, all variables and references assigned to Savant2 are
+       * extracted into the local scope of the template script at fetch()
+       * time, and may be addressed as "$varname" instead of
+       * "$this->varname".  The "$this->varname" notation will also work.
+       * 
+       * When false, you //must// use "$this->varname" in your templates to
+       * address a variable instead of "$varname".  This has three
+       * benefits: speed (no time spent extracting variables), memory use
+       * (saves RAM by not making new references to variables), and clarity
+       * (any $this->varname is obviously an assigned var, and vars created
+       * within the template are not prefixed with $this).
+       * 
+       * @access private
+       * 
+       * @var bool
+       * 
+       */
+       
+       var $_extract = false;
+       
+       
+       /**
+       * 
+       * The output of the template script.
+       * 
+       * @access private
+       * 
+       * @var string
+       * 
+       */
+       
+       var $_output = null;
+       
+       
+       /**
+       * 
+       * The set of search directories for resources (plugins/filters) and
+       * templates.
+       * 
+       * @access private
+       * 
+       * @var array
+       * 
+       */
+       
+       var $_path = array(
+               'resource' => array(),
+               'template' => array()
+       );
+       
+       
+       /**
+       * 
+       * Array of resource (plugin/filter) object instances.
+       * 
+       * @access private
+       * 
+       * @var array
+       * 
+       */
+       
+       var $_resource = array(
+               'plugin' => array(),
+               'filter' => array()
+       );
+       
+       
+       /**
+       * 
+       * Whether or not to automatically self-reference in plugins and filters.
+       * 
+       * @access private
+       * 
+       * @var bool
+       * 
+       */
+       
+       var $_reference = false;
+       
+       
+       /**
+       * 
+       * Whether or not to restrict template includes only to registered paths.
+       * 
+       * @access private
+       * 
+       * @var bool
+       * 
+       */
+       
+       var $_restrict = false;
+       
+       
+       /**
+       * 
+       * The path to the compiled template script file.
+       * 
+       * By default, the template source and template script are the same file.
+       *
+       * @access private
+       * 
+       * @var string
+       * 
+       */
+       
+       var $_script = null;
+       
+       
+       /**
+       * 
+       * The name of the default template source file.
+       * 
+       * @access private
+       * 
+       * @var string
+       * 
+       */
+       
+       var $_template = null;
+       
+       
+       // -----------------------------------------------------------------
+       //
+       // Constructor and general property setters
+       //
+       // -----------------------------------------------------------------
+       
+       
+       /**
+       * 
+       * Constructor.
+       * 
+       * @access public
+       * 
+       * @param array $conf An associative array of configuration keys for
+       * the Savant2 object.  Any, or none, of the keys may be set. The
+       * keys are:
+       * 
+       * 'template_path' => The default path string or array of directories
+       * to search for templates.
+       * 
+       * 'resource_path' => The default path string or array of directories
+       * to search for plugin and filter resources.
+       * 
+       * 'error' => The custom error class that Savant2 should use
+       * when returning errors.
+       * 
+       * 'extract' => Whether or not to extract variables into the local
+       * scope when executing a template.
+       * 
+       * 'template' => The default template source name to use.
+       * 
+       */
+       
+       function Savant2($conf = array())
+       {
+               // set the default template search dirs
+               if (isset($conf['template_path'])) {
+                       // user-defined dirs
+                       $this->setPath('template', $conf['template_path']);
+               } else {
+                       // default directory only
+                       $this->setPath('template', null);
+               }
+               
+               // set the default filter search dirs
+               if (isset($conf['resource_path'])) {
+                       // user-defined dirs
+                       $this->setPath('resource', $conf['resource_path']);
+               } else {
+                       // default directory only
+                       $this->setPath('resource', null);
+               }
+               
+               // do we allow __autoload() use?
+               if (isset($conf['autoload'])) {
+                       $this->setAutoload($conf['autoload']);
+               }
+               
+               // set the error class
+               if (isset($conf['error'])) {
+                       $this->setError($conf['error']);
+               }
+               
+               // set the extraction flag
+               if (isset($conf['extract'])) {
+                       $this->setExtract($conf['extract']);
+               }
+               
+               // set the restrict flag
+               if (isset($conf['restrict'])) {
+                       $this->setRestrict($conf['restrict']);
+               }
+               
+               // set the Savant reference flag
+               if (isset($conf['reference'])) {
+                       $this->setReference($conf['reference']);
+               }
+               
+               // set the default template
+               if (isset($conf['template'])) {
+                       $this->setTemplate($conf['template']);
+               }
+               
+               // set the output escaping callbacks
+               if (isset($config['escape'])) {
+                       call_user_func_array(
+                               array($this, 'setEscape'),
+                               (array) $config['escape']
+                       );
+               }       
+       }
+       
+       /**
+       * 
+       * Sets whether or not __autoload() is used when loading classes.
+       * 
+       * @access public
+       * 
+       * @param bool $flag True to use __autoload(), false to not use it.
+       * 
+       * @return void
+       * 
+       */
+       
+       function setAutoload($flag) {
+               $this->_autoload = (bool) $flag;
+       }
+       
+       
+       /**
+       * 
+       * Sets a custom compiler/pre-processor for template sources.
+       * 
+       * By default, Savant2 does not use a compiler; use this to set your
+       * own custom compiler (pre-processor) for template sources.
+       * 
+       * @access public
+       * 
+       * @param object $compiler The compiler object; it must have a
+       * "compile()" method.  If null or false, the current compiler object
+       * is removed from Savant2.
+       * 
+       * @return void
+       * 
+       * @throws object An error object with a SAVANT2_ERROR_COMPILER code.
+       * 
+       */
+       
+       function setCompiler(&$compiler)
+       {
+               if (! $compiler) {
+                       // nullify any current compiler
+                       $this->_compiler = null;
+               } elseif (is_object($compiler) && method_exists($compiler, 'compile')) {
+                       // refer to a compiler object
+                       $this->_compiler =& $compiler;
+               } else {
+                       // no usable compiler passed
+                       $this->_compiler = null;
+                       return $this->error(SAVANT2_ERROR_COMPILER);
+               }
+       }
+       
+       
+       /**
+       * 
+       * Sets the method that __call() will alias to.
+       * 
+       * @access public
+       * 
+       * @param string $method The Savant2 method for __call() to alias to,
+       * generally 'plugin' or 'splugin'.
+       * 
+       * @return void
+       * 
+       */
+       
+       function setCall($method = 'plugin')
+       {
+               $this->_call = $method;
+       }
+       
+       
+       /**
+       * 
+       * Sets the custom error class for Savant2 errors.
+       * 
+       * @access public
+       * 
+       * @param string $error The name of the custom error class name; if
+       * null or false, resets the error class to 'Savant2_Error'.
+       * 
+       * @return void
+       * 
+       */
+       
+       function setError($error)
+       {
+               if (! $error) {
+                       $this->_error = null;
+               } else {
+                       $this->_error = $error;
+               }
+       }
+       
+       
+       /**
+       *
+       * Turns path checking on/off.
+       * 
+       * @access public
+       *
+       * @param bool $flag True to turn on path checks, false to turn off.
+       *
+       * @return void
+       *
+       */
+       
+       function setRestrict($flag = false)
+       {
+               if ($flag) {
+                       $this->_restrict = true;
+               } else {
+                       $this->_restrict = false;
+               }
+       }
+       
+       
+       /**
+       *
+       * Turns extraction of variables on/off.
+       * 
+       * @access public
+       *
+       * @param bool $flag True to turn on extraction, false to turn off.
+       *
+       * @return void
+       *
+       */
+       
+       function setExtract($flag = true)
+       {
+               if ($flag) {
+                       $this->_extract = true;
+               } else {
+                       $this->_extract = false;
+               }
+       }
+       
+       
+       /**
+       *
+       * Sets the automated Savant reference for plugins and filters.
+       *
+       * @access public
+       *
+       * @param bool $flag Whether to reference Savant2 or not.
+       *
+       * @return void
+       *
+       */
+       
+       function setReference($flag = false)
+       {
+               $this->_reference = $flag;
+       }
+       
+       
+       /**
+       *
+       * Sets the default template name.
+       *
+       * @access public
+       *
+       * @param string $template The default template name.
+       *
+       * @return void
+       *
+       */
+       
+       function setTemplate($template)
+       {
+               $this->_template = $template;
+       }
+       
+       
+       /**
+       * 
+       * Internal version of class_exists() to allow for differing behaviors.
+       * 
+       * Under PHP4, there is only 1 param to class_exists(); in PHP5, there 
+       * are two.  However, if you pass 2 params to the PHP4 version, you get
+       * a parameter count warning; hence, this method.
+       * 
+       * Under PHP5, checks $this->_autload to see if __autoload() should be
+       * called.
+       * 
+       * @access public
+       * 
+       * @param string $class A class name.
+       * 
+       * @return bool Whether or not the class exists.
+       * 
+       */
+       
+       function _classExists($class) {
+               if (PHP_VERSION < '5') {
+                       // version 4.x
+                       return class_exists($class);
+               } else {
+                       // version 5.x
+                       return class_exists($class, $this->_autoload);
+               }
+       }
+       
+       
+       // -----------------------------------------------------------------
+       //
+       // Output escaping and management.
+       //
+       // -----------------------------------------------------------------
+       
+       
+       /**
+       * 
+       * Clears then sets the callbacks to use when calling $this->escape().
+       * 
+       * Each parameter passed to this function is treated as a separate
+       * callback.  For example:
+       * 
+       * <code>
+       * $savant->setEscape(
+       *        'stripslashes',
+       *        'htmlspecialchars',
+       *        array('StaticClass', 'method'),
+       *        array($object, $method)
+       * );
+       * </code>
+       * 
+       * @access public
+       *
+       * @return void
+       *
+       */
+       
+       function setEscape()
+       {
+               $this->_escape = func_get_args();
+       }
+       
+       
+       /**
+       * 
+       * Adds to the callbacks used when calling $this->escape().
+       * 
+       * Each parameter passed to this function is treated as a separate
+       * callback.  For example:
+       * 
+       * <code>
+       * $savant->addEscape(
+       *        'stripslashes',
+       *        'htmlspecialchars',
+       *        array('StaticClass', 'method'),
+       *        array($object, $method)
+       * );
+       * </code>
+       * 
+       * @access public
+       *
+       * @return void
+       *
+       */
+       
+       function addEscape()
+       {
+               $args = func_get_args();
+               $this->_escape = array_merge($this->_escape, $args);
+       }
+       
+       
+       /**
+       *
+       * Gets the array of output-escaping callbacks.
+       *
+       * @access public
+       *
+       * @return array The array of output-escaping callbacks.
+       *
+       */
+       
+       function getEscape()
+       {
+               return $this->_escape;
+       }
+       
+       
+       /**
+       *
+       * Applies escaping to a value.
+       * 
+       * You can override the predefined escaping callbacks by passing
+       * added parameters as replacement callbacks.
+       * 
+       * <code>
+       * // use predefined callbacks
+       * $result = $savant->escape($value);
+       * 
+       * // use replacement callbacks
+       * $result = $savant->escape(
+       *        $value,
+       *        'stripslashes',
+       *        'htmlspecialchars',
+       *        array('StaticClass', 'method'),
+       *        array($object, $method)
+       * );
+       * </code>
+       * 
+       * @access public
+       * 
+       * @param mixed $value The value to be escaped.
+       * 
+       * @return mixed
+       *
+       */
+       
+       function escape($value)
+       {
+               // were custom callbacks passed?
+               if (func_num_args() == 1) {
+               
+                       // no, only a value was passed.
+                       // loop through the predefined callbacks.
+                       foreach ($this->_escape as $func) {
+                               $value = call_user_func($func, $value);
+                       }
+                       
+               } else {
+               
+                       // yes, use the custom callbacks instead.
+                       $callbacks = func_get_args();
+                       
+                       // drop $value
+                       array_shift($callbacks);
+                       
+                       // loop through custom callbacks.
+                       foreach ($callbacks as $func) {
+                               $value = call_user_func($func, $value);
+                       }
+                       
+               }
+               
+               return $value;
+       }
+       
+       
+       /**
+       *
+       * Prints a value after escaping it for output.
+       * 
+       * You can override the predefined escaping callbacks by passing
+       * added parameters as replacement callbacks.
+       * 
+       * <code>
+       * // use predefined callbacks
+       * $this->_($value);
+       * 
+       * // use replacement callbacks
+       * $this->_(
+       *        $value,
+       *        'stripslashes',
+       *        'htmlspecialchars',
+       *        array('StaticClass', 'method'),
+       *        array($object, $method)
+       * );
+       * </code>
+       * 
+       * @access public
+       * 
+       * @param mixed $value The value to be escaped and printed.
+       * 
+       * @return void
+       *
+       */
+       
+       function eprint($value)
+       {
+               $args = func_get_args();
+               echo call_user_func_array(
+                       array($this, 'escape'),
+                       $args
+               );
+       }
+       
+       
+       /**
+       *
+       * Alias to eprint() and identical in every way.
+       * 
+       * @access public
+       * 
+       * @param mixed $value The value to be escaped and printed.
+       * 
+       * @return void
+       *
+       */
+       
+       function _($value)
+       {
+               $args = func_get_args();
+               return call_user_func_array(
+                       array($this, 'eprint'),
+                       $args
+               );
+       }
+       
+       
+       
+       // -----------------------------------------------------------------
+       //
+       // Path management and file finding
+       //
+       // -----------------------------------------------------------------
+       
+       
+       /**
+       *
+       * Sets an entire array of search paths.
+       *
+       * @access public
+       *
+       * @param string $type The type of path to set, typcially 'template'
+       * or 'resource'.
+       * 
+       * @param string|array $new The new set of search paths.  If null or
+       * false, resets to the current directory only.
+       *
+       * @return void
+       *
+       */
+       
+       function setPath($type, $new)
+       {
+               // clear out the prior search dirs
+               $this->_path[$type] = array();
+               
+               // convert from string to path
+               if (is_string($new) && ! strpos($new, '://')) {
+                       // the search config is a string, and it's not a stream
+                       // identifier (the "://" piece), add it as a path
+                       // string.
+                       $new = explode(PATH_SEPARATOR, $new);
+               } else {
+                       // force to array
+                       settype($new, 'array');
+               }
+               
+               // always add the fallback directories as last resort
+               switch (strtolower($type)) {
+               case 'template':
+                       $this->addPath($type, '.');
+                       break;
+               case 'resource':
+                       $this->addPath($type, dirname(__FILE__) . '/Savant2/');
+                       break;
+               }
+               
+               // actually add the user-specified directories
+               foreach ($new as $dir) {
+                       $this->addPath($type, $dir);
+               }
+       }
+       
+       
+       /**
+       *
+       * Adds a search directory for templates.
+       *
+       * @access public
+       *
+       * @param string $dir The directory or stream to search.
+       *
+       * @return void
+       *
+       */
+       
+       function addPath($type, $dir)
+       {
+               // no surrounding spaces allowed!
+               $dir = trim($dir);
+               
+               // add trailing separators as needed
+               if (strpos($dir, '://') && substr($dir, -1) != '/') {
+                       // stream
+                       $dir .= '/';
+               } elseif (substr($dir, -1) != DIRECTORY_SEPARATOR) {
+                       // directory
+                       $dir .= DIRECTORY_SEPARATOR;
+               }
+               
+               // add to the top of the search dirs
+               array_unshift($this->_path[$type], $dir);
+       }
+       
+       
+       /**
+       *
+       * Gets the array of search directories for template sources.
+       *
+       * @access public
+       *
+       * @return array The array of search directories for template sources.
+       *
+       */
+       
+       function getPath($type = null)
+       {
+               if (! $type) {
+                       return $this->_path;
+               } else {
+                       return $this->_path[$type];
+               }
+       }
+       
+       
+       /**
+       * 
+       * Searches a series of paths for a given file.
+       * 
+       * @param array $type The type of paths to search (template, plugin,
+       * or filter).
+       * 
+       * @param string $file The file name to look for.
+       * 
+       * @return string|bool The full path and file name for the target file,
+       * or boolean false if the file is not found in any of the paths.
+       *
+       */
+       
+       function findFile($type, $file)
+       {
+               // get the set of paths
+               $set = $this->getPath($type);
+               
+               // start looping through them
+               foreach ($set as $path) {
+                       
+                       // get the path to the file
+                       $fullname = $path . $file;
+                       
+                       // are we doing path checks?
+                       if (! $this->_restrict) {
+                       
+                               // no.  this is faster but less secure.
+                               if (file_exists($fullname) && is_readable($fullname)) {
+                                       return $fullname;
+                               }
+                               
+                       } else {
+                               
+                               // yes.  this is slower, but attempts to restrict
+                               // access only to defined paths.
+                               
+                               // is the path based on a stream?
+                               if (strpos($path, '://') === false) {
+                                       // not a stream, so do a realpath() to avoid
+                                       // directory traversal attempts on the local file
+                                       // system. Suggested by Ian Eure, initially
+                                       // rejected, but then adopted when the secure
+                                       // compiler was added.
+                                       $path = realpath($path); // needed for substr() later
+                                       $fullname = realpath($fullname);
+                               }
+                               
+                               // the substr() check added by Ian Eure to make sure
+                               // that the realpath() results in a directory registered
+                               // with Savant so that non-registered directores are not
+                               // accessible via directory traversal attempts.
+                               if (file_exists($fullname) && is_readable($fullname) &&
+                                       substr($fullname, 0, strlen($path)) == $path) {
+                                       return $fullname;
+                               }
+                       }
+               }
+               
+               // could not find the file in the set of paths
+               return false;
+       }
+       
+       
+       // -----------------------------------------------------------------
+       //
+       // Variable and reference assignment
+       //
+       // -----------------------------------------------------------------
+       
+       
+       /**
+       * 
+       * Sets variables for the template.
+       * 
+       * This method is overloaded; you can assign all the properties of
+       * an object, an associative array, or a single value by name.
+       * 
+       * You are not allowed to set variables that begin with an underscore;
+       * these are either private properties for Savant2 or private variables
+       * within the template script itself.
+       * 
+       * <code>
+       * 
+       * $Savant2 =& new Savant2();
+       * 
+       * // assign directly
+       * $Savant2->var1 = 'something';
+       * $Savant2->var2 = 'else';
+       * 
+       * // assign by name and value
+       * $Savant2->assign('var1', 'something');
+       * $Savant2->assign('var2', 'else');
+       * 
+       * // assign by assoc-array
+       * $ary = array('var1' => 'something', 'var2' => 'else');
+       * $Savant2->assign($obj);
+       * 
+       * // assign by object
+       * $obj = new stdClass;
+       * $obj->var1 = 'something';
+       * $obj->var2 = 'else';
+       * $Savant2->assign($obj);
+       * 
+       * </code>
+       * 
+       * Greg Beaver came up with the idea of assigning to public class
+       * properties.
+       * 
+       * @access public
+       * 
+       * @return void
+       * 
+       * @throws object An error object with a SAVANT2_ERROR_ASSIGN code.
+       * 
+       */
+       
+       function assign()
+       {
+               // this method is overloaded.
+               $arg = func_get_args();
+               
+               // must have at least one argument. no error, just do nothing.
+               if (! isset($arg[0])) {
+                       return;
+               }
+               
+               // assign by object
+               if (is_object($arg[0])) {
+                       // assign public properties
+                       foreach (get_object_vars($arg[0]) as $key => $val) {
+                               if (substr($key, 0, 1) != '_') {
+                                       $this->$key = $val;
+                               }
+                       }
+                       return;
+               }
+               
+               // assign by associative array
+               if (is_array($arg[0])) {
+                       foreach ($arg[0] as $key => $val) {
+                               if (substr($key, 0, 1) != '_') {
+                                       $this->$key = $val;
+                               }
+                       }
+                       return;
+               }
+               
+               // assign by string name and mixed value.
+               // 
+               // we use array_key_exists() instead of isset() becuase isset()
+               // fails if the value is set to null.
+               if (is_string($arg[0]) &&
+                       substr($arg[0], 0, 1) != '_' &&
+                       array_key_exists(1, $arg)) {
+                       $this->$arg[0] = $arg[1];
+               } else {
+                       return $this->error(SAVANT2_ERROR_ASSIGN, $arg);
+               }
+       }
+       
+       
+       /**
+       * 
+       * Sets references for the template.
+       * 
+       * // assign by name and value
+       * $Savant2->assignRef('ref', $reference);
+       * 
+       * // assign directly
+       * $Savant2->ref =& $reference;
+       * 
+       * Greg Beaver came up with the idea of assigning to public class
+       * properties.
+       * 
+       * @access public
+       * 
+       * @param string $key The name for the reference in the template.
+       *
+       * @param mixed &$val The referenced variable.
+       * 
+       * @return void
+       * 
+       * @throws object An error object with a SAVANT2_ERROR_ASSIGNREF code.
+       * 
+       */
+       
+       function assignRef($key, &$val)
+       {
+               if (is_string($key) && substr($key, 0, 1) != '_') {
+                       $this->$key =& $val;
+               } else {
+                       return $this->error(
+                               SAVANT2_ERROR_ASSIGNREF,
+                               array('key' => $key, 'val' => $val)
+                       );
+               }
+       }
+       
+       
+       /**
+       *
+       * Unsets assigned variables and references.
+       * 
+       * @access public
+       * 
+       * @param mixed $var If null, clears all variables; if a string, clears
+       * the one variable named by the string; if a sequential array, clears
+       * the variables names in that array.
+       * 
+       * @return void
+       *
+       */
+       
+       function clear($var = null)
+       {
+               if (is_null($var)) {
+                       // clear all variables
+                       $var = array_keys(get_object_vars($this));
+               } else {
+                       // clear specific variables
+                       settype($var, 'array');
+               }
+               
+               // clear out the selected variables
+               foreach ($var as $name) {
+                       if (substr($name, 0, 1) != '_' && isset($this->$name)) {
+                               unset($this->$name);
+                       }
+               }
+       }
+       
+       
+       /**
+       * 
+       * Gets the current value of one, many, or all assigned variables.
+       * 
+       * Never returns variables starting with an underscore; these are
+       * reserved for internal Savant2 use.
+       * 
+       * @access public
+       * 
+       * @param mixed $key If null, returns a copy of all variables and
+       * their values; if an array, returns an only those variables named
+       * in the array; if a string, returns only that variable.
+       * 
+       * @return mixed If multiple variables were reqested, returns an
+       * associative array where the key is the variable name and the 
+       * value is the variable value; if one variable was requested,
+       * returns the variable value only.
+       * 
+       */
+       
+       function getVars($key = null)
+       {
+               if (is_null($key)) {
+                       $key = array_keys(get_object_vars($this));
+               }
+               
+               if (is_array($key)) {
+                       // return a series of vars
+                       $tmp = array();
+                       foreach ($key as $var) {
+                               if (substr($var, 0, 1) != '_' && isset($this->$var)) {
+                                       $tmp[$var] = $this->$var;
+                               }
+                       }
+                       return $tmp;
+               } else {
+                       // return a single var
+                       if (substr($key, 0, 1) != '_' && isset($this->$key)) {
+                               return $this->$key;
+                       }
+               }
+       }
+       
+       
+       // -----------------------------------------------------------------
+       //
+       // Template processing
+       //
+       // -----------------------------------------------------------------
+       
+       
+       /**
+       *
+       * Loads a template script for execution (does not execute the script).
+       * 
+       * This will optionally compile the template source into a PHP script
+       * if a compiler object has been passed into Savant2.
+       * 
+       * Also good for including templates from the template paths within
+       * another template, like so:
+       *
+       * include $this->loadTemplate('template.tpl.php');
+       * 
+       * @access public
+       *
+       * @param string $tpl The template source name to look for.
+       * 
+       * @param bool $setScript Default false; if true, sets the $this->_script
+       * property to the resulting script path (or null on error).  Normally,
+       * only $this->fetch() will need to set this to true.
+       * 
+       * @return string The full path to the compiled template script.
+       * 
+       * @throws object An error object with a SAVANT2_ERROR_NOTEMPLATE code.
+       * 
+       */
+       
+       function loadTemplate($tpl = null, $setScript = false)
+       {
+               // set to default template if none specified.
+               if (is_null($tpl)) {
+                       $tpl = $this->_template;
+               }
+               
+               // find the template source.
+               $file = $this->findFile('template', $tpl);
+               if (! $file) {
+                       return $this->error(
+                               SAVANT2_ERROR_NOTEMPLATE,
+                               array('template' => $tpl)
+                       );
+               }
+               
+               // are we compiling source into a script?
+               if (is_object($this->_compiler)) {
+                       // compile the template source and get the path to the
+                       // compiled script (will be returned instead of the
+                       // source path)
+                       $result = $this->_compiler->compile($file);
+               } else {
+                       // no compiling requested, return the source path
+                       $result = $file;
+               }
+               
+               // is there a script from the compiler?
+               if (! $result || $this->isError($result)) {
+               
+                       if ($setScript) {
+                               $this->_script = null;
+                       }
+                       
+                       // return an error, along with any error info
+                       // generated by the compiler.
+                       return $this->error(
+                               SAVANT2_ERROR_NOSCRIPT,
+                               array(
+                                       'template' => $tpl,
+                                       'compiler' => $result
+                               )
+                       );
+                       
+               } else {
+               
+                       if ($setScript) {
+                               $this->_script = $result;
+                       }
+                       
+                       return $result;
+                       
+               }
+       }
+       
+       
+       /**
+       * 
+       * This is a an alias to loadTemplate() that cannot set the script.
+       * 
+       * @access public
+       *
+       * @param string $tpl The template source name to look for.
+       * 
+       * @return string The full path to the compiled template script.
+       * 
+       * @throws object An error object with a SAVANT2_ERROR_NOTEMPLATE code.
+       * 
+       */
+       
+       function findTemplate($tpl = null)
+       {
+               return $this->loadTemplate($tpl, false);
+       }
+       
+       
+       /**
+       * 
+       * Executes a template script and returns the results as a string.
+       * 
+       * @param string $_tpl The name of the template source file ...
+       * automatically searches the template paths and compiles as needed.
+       * 
+       * @return string The output of the the template script.
+       * 
+       * @throws object An error object with a SAVANT2_ERROR_NOSCRIPT code.
+       * 
+       */
+       
+       function fetch($_tpl = null)
+       {
+               // clear prior output
+               $this->_output = null;
+               
+               // load the template script
+               $_result = $this->loadTemplate($_tpl, true);
+               
+               // is there a template script to be processed?
+               if ($this->isError($_result)) {
+                       return $_result;
+               }
+               
+               // unset so as not to introduce into template scope
+               unset($_tpl);
+               unset($_result);
+               
+               // never allow a 'this' property
+               if (isset($this->this)) {
+                       unset($this->this);
+               }
+               
+               // are we extracting variables into local scope?
+               if ($this->_extract) {
+                       // extract references to this object's public properties.
+                       // this allows variables assigned by-reference to refer all
+                       // the way back to the model logic.  variables assigned
+                       // by-copy only refer back to the property.
+                       foreach (array_keys(get_object_vars($this)) as $_prop) {
+                               if (substr($_prop, 0, 1) != '_') {
+                                       // set a variable-variable to an object property
+                                       // reference
+                                       $$_prop =& $this->$_prop;
+                               }
+                       }
+                       
+                       // unset private loop vars
+                       unset($_prop);
+               }
+               
+               // start capturing output into a buffer
+               ob_start();
+               
+               // include the requested template filename in the local scope
+               // (this will execute the view logic).
+               include $this->_script;
+               
+               // done with the requested template; get the buffer and 
+               // clear it.
+               $this->_output = ob_get_contents();
+               ob_end_clean();
+               
+               // done!
+               return $this->applyFilters();
+       }
+       
+       
+       /**
+       * 
+       * Execute and display a template script.
+       * 
+       * @param string $tpl The name of the template file to parse;
+       * automatically searches through the template paths.
+       * 
+       * @return void
+       * 
+       * @throws object An error object with a SAVANT2_ERROR_NOSCRIPT code.
+       * 
+       * @see fetch()
+       * 
+       */
+       
+       function display($tpl = null)
+       {
+               $result = $this->fetch($tpl);
+               if ($this->isError($result)) {
+                       return $result;
+               } else {
+                       echo $result;
+               }
+       }
+       
+       
+       // -----------------------------------------------------------------
+       //
+       // Plugins
+       //
+       // -----------------------------------------------------------------
+       
+       
+       /**
+       *
+       * Loads a plugin class and instantiates it within Savant2.
+       *
+       * @access public
+       *
+       * @param string $name The plugin name (not including Savant2_Plugin_
+       * prefix).
+       *
+       * @param array $conf An associative array of plugin configuration
+       * options.
+       *
+       * @param bool $savantRef Default false.  When true, sets the $Savant
+       * property of the filter to a reference to this Savant object.
+       *
+       * @return void
+       * 
+       * @throws object An error object with a SAVANT2_ERROR_NOPLUGIN code.
+       * 
+       */
+       
+       function loadPlugin($name, $conf = array(), $savantRef = null)
+       {
+               // if no $savantRef is provided, use the default.
+               if (is_null($savantRef)) {
+                       $savantRef = $this->_reference;
+               }
+               
+               // some basic information
+               $class = "Savant2_Plugin_$name";
+               $file = "$class.php";
+               
+               // is it loaded?
+               if (! $this->_classExists($class)) {
+                       
+                       $result = $this->findFile('resource', $file);
+                       if (! $result) {
+                               return $this->error(
+                                       SAVANT2_ERROR_NOPLUGIN,
+                                       array('plugin' => $name)
+                               );
+                       } else {
+                               include_once $result;
+                       }
+               }
+               
+               // is it instantiated?
+               if (! isset($this->_resource['plugin'][$name]) ||
+                       ! is_object($this->_resource['plugin'][$name]) ||
+                       ! is_a($this->_resource['plugin'][$name], $class)) {
+                       
+                       // instantiate it
+                       $this->_resource['plugin'][$name] =& new $class($conf);
+                       
+                       // add a Savant reference if requested
+                       if ($savantRef) {
+                               $this->_resource['plugin'][$name]->Savant =& $this;
+                       }
+                       
+               }
+       }
+       
+       
+       /**
+       *
+       * Unloads one or more plugins from Savant2.
+       *
+       * @access public
+       *
+       * @param string|array $name The plugin name (not including Savant2_Plugin_
+       * prefix).  If null, unloads all plugins; if a string, unloads that one
+       * plugin; if an array, unloads all plugins named as values in the array.
+       *
+       * @return void
+       * 
+       */
+       
+       function unloadPlugin($name = null)
+       {
+               if (is_null($name)) {
+                       $this->_resource['plugin'] = array();
+               } else {
+                       settype($name, 'array');
+                       foreach ($name as $key) {
+                               if (isset($this->_resource['plugin'][$key])) {
+                                       unset($this->_resource['plugin'][$key]);
+                               }
+                       }
+               }
+       }
+       
+       
+       /**
+       *
+       * Executes a plugin with arbitrary parameters and returns the
+       * result.
+       * 
+       * @access public
+       * 
+       * @param string $name The plugin name (not including Savant2_Plugin_
+       * prefix).
+       *
+       * @return mixed The plugin results.
+       *
+       * @throws object An error object with a SAVANT2_ERROR_NOPLUGIN code.
+       * 
+       * @see loadPlugin()
+       * 
+       */
+       
+       function splugin($name)
+       {
+               // attempt to load the plugin
+               $result = $this->loadPlugin($name);
+               if ($this->isError($result)) {
+                       return $result;
+               }
+               
+               // call the plugin's "plugin()" method with arguments,
+               // dropping the first argument (the plugin name)
+               $args = func_get_args();
+               array_shift($args);
+               return call_user_func_array(
+                       array(&$this->_resource['plugin'][$name], 'plugin'), $args
+               );
+       }
+       
+       
+       /**
+       *
+       * Executes a plugin with arbitrary parameters and displays the
+       * result.
+       * 
+       * @access public
+       * 
+       * @param string $name The plugin name (not including Savant2_Plugin_
+       * prefix).
+       *
+       * @return void
+       * 
+       * @throws object An error object with a SAVANT2_ERROR_NOPLUGIN code.
+       * 
+       */
+       
+       function plugin($name)
+       {
+               $args = func_get_args();
+               
+               $result = call_user_func_array(
+                       array(&$this, 'splugin'),
+                       $args
+               );
+               
+               if ($this->isError($result)) {
+                       return $result;
+               } else {
+                       echo $result;
+               }
+       }
+       
+       
+       /**
+       *
+       * PHP5 ONLY: Magic method alias to plugin().
+       * 
+       * E.g., instead of $this->plugin('form', ...) you would use
+       * $this->form(...).  You can set this to use any other Savant2 method
+       * by issuing, for example, setCall('splugin') to use splugin() ... which 
+       * is really the only other sensible choice.
+       * 
+       * @access public
+       * 
+       * @param string $func The plugin name.
+       *
+       * @param array $args Arguments passed to the plugin.
+       *
+       * @return void
+       * 
+       * @throws object An error object with a SAVANT2_ERROR_NOPLUGIN code.
+       * 
+       */
+       
+       function __call($func, $args)
+       {
+               // add the plugin name to the args
+               array_unshift($args, $func);
+               
+               // call the plugin() method
+               return call_user_func_array(
+                       array(&$this, $this->_call),
+                       $args
+               );
+       }
+       
+       
+       // -----------------------------------------------------------------
+       //
+       // Filters
+       //
+       // -----------------------------------------------------------------
+       
+       
+       /**
+       *
+       * Loads a filter class and instantiates it within Savant2.
+       *
+       * @access public
+       *
+       * @param string $name The filter name (not including Savant2_Filter_
+       * prefix).
+       *
+       * @param array $conf An associative array of filter configuration
+       * options.
+       * 
+       * @param bool $savantRef Default false.  When true, sets the $Savant
+       * property of the filter to a reference to this Savant object.
+       *
+       * @return void
+       * 
+       * @throws object An error object with a SAVANT2_ERROR_NOFILTER code.
+       * 
+       */
+       
+       function loadFilter($name, $conf = array(), $savantRef = null)
+       {
+               // if no $savantRef is provided, use the default.
+               if (is_null($savantRef)) {
+                       $savantRef = $this->_reference;
+               }
+               
+               // some basic information
+               $class = "Savant2_Filter_$name";
+               $file = "$class.php";
+               
+               // is it loaded?
+               if (! $this->_classExists($class)) {
+                       
+                       $result = $this->findFile('resource', $file);
+                       if (! $result) {
+                               return $this->error(
+                                       SAVANT2_ERROR_NOFILTER,
+                                       array('filter' => $name)
+                               );
+                       } else {
+                               include_once $result;
+                       }
+               }
+               
+               // is it instantiated?
+               if (! isset($this->_resource['filter'][$name]) ||
+                       ! is_object($this->_resource['filter'][$name]) ||
+                       ! is_a($this->_resource['filter'][$name], $class)) {
+                       
+                       // instantiate it
+                       $this->_resource['filter'][$name] =& new $class($conf);
+                       
+                       // add a Savant reference if requested
+                       if ($savantRef) {
+                               $this->_resource['filter'][$name]->Savant =& $this;
+                       }
+                       
+               }
+       }
+       
+       
+       /**
+       *
+       * Unloads one or more filters from Savant2.
+       *
+       * @access public
+       *
+       * @param string|array $name The filter name (not including Savant2_Filter_
+       * prefix).  If null, unloads all filters; if a string, unloads that one
+       * filter; if an array, unloads all filters named as values in the array.
+       *
+       * @return void
+       * 
+       */
+       
+       function unloadFilter($name = null)
+       {
+               if (is_null($name)) {
+                       $this->_resource['filter'] = array();
+               } else {
+                       settype($name, 'array');
+                       foreach ($name as $key) {
+                               if (isset($this->_resource['filter'][$key])) {
+                                       unset($this->_resource['filter'][$key]);
+                               }
+                       }
+               }
+       }
+       
+       
+       /**
+       *
+       * Apply all loaded filters, in order, to text.
+       *
+       * @access public
+       *
+       * @param string $text The text to which filters should be applied. 
+       * If null, sets the text to $this->_output.
+       * 
+       * @return string The text after being passed through all loded
+       * filters.
+       * 
+       */
+       
+       function applyFilters($text = null)
+       {
+               // set to output text if no text specified
+               if (is_null($text)) {
+                       $text = $this->_output;
+               }
+               
+               // get the list of filter names...
+               $filter = array_keys($this->_resource['filter']);
+               
+               // ... and apply them each in turn.
+               foreach ($filter as $name) {
+                       $this->_resource['filter'][$name]->filter($text);
+               }
+               
+               // done
+               return $text;
+       }
+       
+       
+       // -----------------------------------------------------------------
+       //
+       // Error handling
+       //
+       // -----------------------------------------------------------------
+       
+       
+       /**
+       *
+       * Returns an error object.
+       * 
+       * @access public
+       * 
+       * @param int $code A SAVANT2_ERROR_* constant.
+       * 
+       * @param array $info An array of error-specific information.
+       * 
+       * @return object An error object of the type specified by
+       * $this->_error.
+       * 
+       */
+       
+       function &error($code, $info = array())
+       {
+               // the error config array
+               $conf = array(
+                       'code' => $code,
+                       'text' => 'Savant2: ',
+                       'info' => (array) $info
+               );
+               
+               // set an error message from the globals
+               if (isset($GLOBALS['_SAVANT2']['error'][$code])) {
+                       $conf['text'] .= $GLOBALS['_SAVANT2']['error'][$code];
+               } else {
+                       $conf['text'] .= '???';
+               }
+               
+               // set up the error class name
+               if ($this->_error) {
+                       $class = 'Savant2_Error_' . $this->_error;
+               } else {
+                       $class = 'Savant2_Error';
+               }
+
+               // set up the error class file name
+               $file = $class . '.php';
+               
+               // is it loaded?
+               if (! $this->_classExists($class)) {
+                       
+                       // find the error class
+                       $result = $this->findFile('resource', $file);
+                       if (! $result) {
+                               // could not find the custom error class, revert to
+                               // Savant_Error base class.
+                               $class = 'Savant2_Error';
+                               $result = dirname(__FILE__) . '/Savant2/Error.php';
+                       }
+                       
+                       // include the error class
+                       include_once $result;
+               }
+               
+               // instantiate and return the error class
+               $err =& new $class($conf);
+               return $err;
+       }
+       
+       
+       /**
+       *
+       * Tests if an object is of the Savant2_Error class.
+       * 
+       * @access public
+       * 
+       * @param object &$obj The object to be tested.
+       * 
+       * @return boolean True if $obj is an error object of the type
+       * Savant2_Error, or is a subclass that Savant2_Error. False if not.
+       *
+       */
+       
+       function isError(&$obj)
+       {
+               if (is_object($obj)) {
+                       if (is_a($obj, 'Savant2_Error') ||
+                               is_subclass_of($obj, 'Savant2_Error')) {
+                               return true;
+                       }
+               }
+               
+               return false;
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/Savant2/Savant2/Compiler.php b/include/classes/Savant2/Savant2/Compiler.php
new file mode 100644 (file)
index 0000000..6333177
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+
+/**
+* 
+* Abstract Savant2_Compiler class.
+* 
+* You have to extend this class for it to be useful; e.g., "class
+* Savant2_Plugin_example extends Savant2_Plugin".
+* 
+* $Id: Compiler.php,v 1.5 2005/08/09 22:19:39 pmjones Exp $
+* 
+* @author Paul M. Jones <pmjones@ciaweb.net>
+* 
+* @package Savant2
+* 
+* @license LGPL http://www.gnu.org/copyleft/lesser.html
+* 
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 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
+* Lesser General Public License for more details.
+*
+*/
+
+class Savant2_Compiler {
+       
+       /**
+       * 
+       * Reference to the "parent" Savant object.
+       *
+       */
+       
+       var $Savant = null;
+       
+       
+       /**
+       * 
+       * Constructor.
+       * 
+       * @access public
+       * 
+       */
+       
+       function Savant2_Compiler($conf = array())
+       {
+               settype($conf, 'array');
+               foreach ($conf as $key => $val) {
+                       $this->$key = $val;
+               }
+       }
+       
+       
+       /**
+       * 
+       * Stub method for extended behaviors.
+       *
+       * @access public
+       * 
+       * @return void
+       *
+       */
+       
+       function compile($tpl)
+       {
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/Savant2/Savant2/Error.php b/include/classes/Savant2/Savant2/Error.php
new file mode 100644 (file)
index 0000000..f18da71
--- /dev/null
@@ -0,0 +1,125 @@
+<?php
+
+/**
+* 
+* Provides a simple error class for Savant.
+*
+* $Id: Error.php,v 1.2 2005/08/09 22:19:39 pmjones Exp $
+* 
+* @author Paul M. Jones <pmjones@ciaweb.net>
+* 
+* @package Savant2
+* 
+* @license LGPL http://www.gnu.org/copyleft/lesser.html
+* 
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 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
+* Lesser General Public License for more details.
+* 
+*/
+
+class Savant2_Error {
+       
+       
+       /**
+       * 
+       * The error code, typically a SAVANT_ERROR_* constant.
+       * 
+       * @access public
+       *
+       * @var int
+       *
+       */
+       
+       var $code = null;
+       
+       
+       /**
+       * 
+       * An array of error-specific information.
+       * 
+       * @access public
+       *
+       * @var array
+       *
+       */
+       
+       var $info = array();
+       
+       
+       /**
+       * 
+       * The error message text.
+       *
+       * @access public
+       *
+       * @var string
+       *
+       */
+       
+       var $text = null;
+       
+       
+       /**
+       * 
+       * A debug backtrace for the error, if any.
+       *
+       * @access public
+       *
+       * @var array
+       *
+       */
+       
+       var $backtrace = null;
+       
+       
+       /**
+       * 
+       * Constructor.
+       *
+       * @access public
+       *
+       * @param array $conf An associative array where the key is a
+       * Savant2_Error property and the value is the value for that
+       * property.
+       *
+       */
+       
+       function Savant2_Error($conf = array())
+       {
+               // set public properties
+               foreach ($conf as $key => $val) {
+                       $this->$key = $val;
+               }
+               
+               // generate a backtrace
+               if (function_exists('debug_backtrace')) {
+                       $this->backtrace = debug_backtrace();
+               }
+               
+               // extended behaviors
+               $this->error();
+       }
+       
+       
+       /**
+       * 
+       * Stub method for extended behaviors.
+       *
+       * @access public
+       * 
+       * @return void
+       *
+       */
+       
+       function error()
+       {
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/Savant2/Savant2/Filter.php b/include/classes/Savant2/Savant2/Filter.php
new file mode 100644 (file)
index 0000000..6adb652
--- /dev/null
@@ -0,0 +1,76 @@
+<?php
+
+/**
+* 
+* Abstract Savant2_Filter class.
+* 
+* You have to extend this class for it to be useful; e.g., "class
+* Savant2_Filter_example extends Savant2_Filter".
+* 
+* $Id: Filter.php,v 1.2 2005/08/09 22:19:39 pmjones Exp $
+* 
+* @author Paul M. Jones <pmjones@ciaweb.net>
+* 
+* @package Savant2
+* 
+* @license LGPL http://www.gnu.org/copyleft/lesser.html
+* 
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 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
+* Lesser General Public License for more details.
+*
+*/
+
+class Savant2_Filter {
+       
+       /**
+       * 
+       * Optional reference to the calling Savant object.
+       * 
+       * @var object
+       * 
+       */
+       
+       var $Savant = null;
+       
+       
+       /**
+       * 
+       * Constructor.
+       * 
+       * @access public
+       * 
+       */
+       
+       function Savant2_Filter($conf = array())
+       {
+               settype($conf, 'array');
+               foreach ($conf as $key => $val) {
+                       $this->$key = $val;
+               }
+       }
+       
+       
+       /**
+       * 
+       * Stub method for extended behaviors.
+       *
+       * @access public
+       * 
+       * @param string &$text The text to filter.
+       *
+       * @return void
+       *
+       */
+       
+       function filter(&$text)
+       {
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/Savant2/Savant2/Plugin.php b/include/classes/Savant2/Savant2/Plugin.php
new file mode 100644 (file)
index 0000000..835e22d
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+
+/**
+* 
+* Abstract Savant2_Plugin class.
+* 
+* You have to extend this class for it to be useful; e.g., "class
+* Savant2_Plugin_example extends Savant2_Plugin".
+* 
+* $Id: Plugin.php,v 1.2 2005/08/09 22:19:39 pmjones Exp $
+* 
+* @author Paul M. Jones <pmjones@ciaweb.net>
+* 
+* @package Savant2
+* 
+* @license LGPL http://www.gnu.org/copyleft/lesser.html
+* 
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 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
+* Lesser General Public License for more details.
+*
+*/
+
+class Savant2_Plugin {
+       
+       /**
+       * 
+       * Optional reference to the calling Savant object.
+       * 
+       * @var object
+       * 
+       */
+       
+       var $Savant = null;
+       
+       
+       /**
+       * 
+       * Constructor.
+       * 
+       * @access public
+       * 
+       */
+       
+       function Savant2_Plugin($conf = array())
+       {
+               settype($conf, 'array');
+               foreach ($conf as $key => $val) {
+                       $this->$key = $val;
+               }
+       }
+       
+       
+       /**
+       * 
+       * Stub method for extended behaviors.
+       *
+       * @access public
+       * 
+       * @return void
+       *
+       */
+       
+       function plugin()
+       {
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/Savant2/Savant2/Savant2_Error_exception.php b/include/classes/Savant2/Savant2/Savant2_Error_exception.php
new file mode 100644 (file)
index 0000000..48e01ad
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+
+/**
+* The base Savant2_Error class.
+*/
+require_once 'Savant2/Error.php';
+
+/**
+* A simple Savant2_Exception class.
+*/
+class Savant2_Exception extends Exception { };
+
+/**
+* 
+* Throws PHP5 exceptions for Savant.
+*
+* $Id: Savant2_Error_exception.php,v 1.4 2005/08/09 22:19:39 pmjones Exp $
+* 
+* @author Paul M. Jones <pmjones@ciaweb.net>
+* 
+* @package Savant2
+* 
+* @license LGPL http://www.gnu.org/copyleft/lesser.html
+* 
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 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
+* Lesser General Public License for more details.
+* 
+*/
+
+class Savant2_Error_exception extends Savant2_Error {
+       
+       
+       /**
+       * 
+       * Throws an Savant2_Exception in PHP5.
+       * 
+       * @return void
+       * 
+       */
+       
+       function error()
+       {
+               throw new Savant2_Exception($this->text, $this->code);
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/Savant2/Savant2/Savant2_Error_pear.php b/include/classes/Savant2/Savant2/Savant2_Error_pear.php
new file mode 100644 (file)
index 0000000..1963122
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+
+/**
+* The base Savant2_Error class.
+*/
+require_once 'Savant2/Error.php';
+
+/**
+* The PEAR_Error class.
+*/
+require_once 'PEAR.php';
+
+/**
+* 
+* Provides an interface to PEAR_ErrorStack class for Savant.
+*
+* $Id: Savant2_Error_pear.php,v 1.2 2005/08/09 22:19:39 pmjones Exp $
+* 
+* @author Paul M. Jones <pmjones@ciaweb.net>
+* 
+* @package Savant2
+* 
+* @license LGPL http://www.gnu.org/copyleft/lesser.html
+* 
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 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
+* Lesser General Public License for more details.
+* 
+*/
+
+class Savant2_Error_pear extends Savant2_Error {
+       
+       
+       /**
+       * 
+       * Extended behavior for PEAR_Error.
+       *
+       * @access public
+       *
+       * @return void
+       *
+       */
+       
+       function error()
+       {
+               // throw a PEAR_Error
+               PEAR::throwError($this->text, $this->code, $this->info);
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/Savant2/Savant2/Savant2_Error_stack.php b/include/classes/Savant2/Savant2/Savant2_Error_stack.php
new file mode 100644 (file)
index 0000000..e532891
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+
+/**
+* The base Savant2_Error class.
+*/
+require_once 'Savant2/Error.php';
+
+/**
+* The PEAR_ErrorStack class.
+*/
+require_once 'PEAR/ErrorStack.php';
+
+/**
+* 
+* Provides an interface to PEAR_ErrorStack class for Savant.
+*
+* $Id: Savant2_Error_stack.php,v 1.2 2005/08/09 22:19:39 pmjones Exp $
+* 
+* @author Paul M. Jones <pmjones@ciaweb.net>
+* 
+* @package Savant2
+* 
+* @license LGPL http://www.gnu.org/copyleft/lesser.html
+* 
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 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
+* Lesser General Public License for more details.
+* 
+*/
+
+class Savant2_Error_stack extends Savant2_Error {
+       
+       
+       /**
+       * 
+       * Pushes an error onto the PEAR_ErrorStack.
+       * 
+       * @return void
+       * 
+       */
+       
+       function error()
+       {
+               // push an error onto the stack
+               PEAR_ErrorStack::staticPush(
+                       'Savant2',       // package name
+                       $this->code,    // error code
+                       null,           // error level
+                       $this->info,    // user info
+                       $this->text     // error message
+               );
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/Savant2/Savant2/Savant2_Plugin_cycle.php b/include/classes/Savant2/Savant2/Savant2_Plugin_cycle.php
new file mode 100644 (file)
index 0000000..5244033
--- /dev/null
@@ -0,0 +1,97 @@
+<?php
+
+/**
+* Base plugin class.
+*/
+require_once 'Savant2/Plugin.php';
+
+/**
+* 
+* Cycles through a series of values.
+* 
+* $Id: Savant2_Plugin_cycle.php,v 1.2 2005/08/09 22:19:39 pmjones Exp $
+* 
+* @author Paul M. Jones <pmjones@ciaweb.net>
+* 
+* @package Savant2
+* 
+* @license LGPL http://www.gnu.org/copyleft/lesser.html
+* 
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 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
+* Lesser General Public License for more details.
+* 
+*/
+
+class Savant2_Plugin_cycle extends Savant2_Plugin {
+       
+       /**
+       * 
+       * An associative array of predefined cycle value sets.
+       * 
+       * You can preset cycle values via Savant::loadPlugin().
+       * 
+       * $conf = array(
+       *     'values' => array(
+       *         'lightdark' => array('light', 'dark'),
+       *         'threesome' => array('one', 'two', 'three')
+       *     )
+       * );
+       * 
+       * $Savant->loadPlugin('cycle', $conf);
+       * 
+       * ... and in your template you can call:
+       * 
+       * $this->plugin('cycle', 'lightdark', $iteration);
+       * 
+       * @access public
+       * 
+       * @var array
+       * 
+       */
+       
+       var $values = array();
+       
+       
+       /**
+       * 
+       * Cycles through a series of values.
+       * 
+       * @access public
+       * 
+       * @param string|array $cycle If a string, the preset cycle value key to use
+       * from $this->cycles; if an array, use the array as the cycle values.
+       * 
+       * @param int $iteration The iteration number for the cycle.
+       * 
+       * @param int $repeat The number of times to repeat each cycle value.
+       * 
+       * @return mixed The value of the cycle iteration.
+       * 
+       */
+       
+       function plugin($cycle, $iteration, $repeat = 1)
+       {
+               // get the proper value set as an array
+               if (is_string($cycle) && isset($this->values[$cycle])) {
+                       $values = (array) $this->values[$cycle];
+               } else {
+                       $values = (array) $cycle;
+               }
+               
+               // prevent divide-by-zero errors
+               if ($repeat == 0) {
+                       $repeat = 1;
+               }
+               
+               // return the perper value for iteration and repetition
+               return $values[($iteration / $repeat) % count($values)];
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/Themes/ThemeParser.class.php b/include/classes/Themes/ThemeParser.class.php
new file mode 100644 (file)
index 0000000..603497a
--- /dev/null
@@ -0,0 +1,84 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+\r
+/**\r
+* ThemeParser\r
+* Class for parsing XML language info and returning a Theme Object\r
+* @access      public\r
+* @author      Shozub Qureshi\r
+* @package     Themes\r
+*/\r
+class ThemeParser {\r
+\r
+       // all private\r
+       var $parser; // the XML handler\r
+       var $theme_rows = array(); // the language data used for creating the Language Object\r
+       var $character_data; // tmp variable for storing the data\r
+       var $element_path; // array of element paths (basically a stack)\r
+       var $row_num;\r
+\r
+       function ThemeParser() {\r
+               $this->parser = xml_parser_create(); \r
+\r
+               xml_set_object($this->parser, $this);\r
+               xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false); /* conform to W3C specs */\r
+               xml_set_element_handler($this->parser, 'startElement', 'endElement');\r
+               xml_set_character_data_handler($this->parser, 'characterData');\r
+       }\r
+\r
+       // public\r
+       function parse($xml_data) {\r
+               $this->element_path   = array();\r
+               $this->theme_rows  = array();\r
+               $this->character_data = '';\r
+               xml_parse($this->parser, $xml_data, TRUE);\r
+       }\r
+\r
+       // private\r
+       function startElement($parser, $name, $attributes) {\r
+               array_push($this->element_path, $name);\r
+   }\r
+\r
+       // private\r
+       /* called when an element ends */\r
+       /* removed the current element from the $path */\r
+       function endElement($parser, $name) {\r
+               if ($this->element_path == array('theme', 'dir_name')) {\r
+                       $this->theme_rows['dir_name'] = trim($this->character_data);\r
+\r
+               } else if ($this->element_path == array('theme', 'title')) {\r
+                       $this->theme_rows['title'] = trim($this->character_data);\r
+\r
+               } else if ($this->element_path == array('theme', 'version')) {\r
+                       $this->theme_rows['version'] = trim($this->character_data);\r
+\r
+               } else if ($this->element_path == array('theme', 'last_updated')) {\r
+                       $this->theme_rows['last_updated'] = trim($this->character_data);\r
+\r
+               } else if ($this->element_path == array('theme', 'extra_info')) {\r
+                       $this->theme_rows['extra_info'] = trim($this->character_data);\r
+\r
+               }\r
+\r
+               array_pop($this->element_path);\r
+               $this->character_data = '';\r
+       }\r
+\r
+       // private\r
+       function characterData($parser, $data){\r
+               $this->character_data .= $data;\r
+       }\r
+\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/include/classes/UrlRewrite/ContentUrl.class.php b/include/classes/UrlRewrite/ContentUrl.class.php
new file mode 100644 (file)
index 0000000..75d0e23
--- /dev/null
@@ -0,0 +1,112 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: ContentUrl.class.php 7603 2008-06-11 14:59:33Z hwong $
+/**
+* ContentUrl
+* Class for rewriting pretty urls.
+* @access      public
+* @author      Harris Wong
+* @package     UrlParser
+*/
+class ContentUrl {
+       // constructor
+       function ContentUrl() {
+               $this->rule = array(0=>'cid');
+       }
+
+       /**
+        * Construct pretty url by the given query string.
+        */
+       function constructPrettyUrl($query){
+               if (empty($query)){
+                       return '';
+               }
+
+               //Take out bookmark
+               if (($pos = strpos($query, '#'))!==FALSE){
+                       $bookmark = substr($query, $pos);
+                       $query = substr($query, 0, $pos);
+               }
+
+               //If this is already a pretty url,but without mod_apache rule
+               //unwrap it and reconstruct
+               if (is_array($query)){
+                       $new_query = '';
+                       foreach($query as $fk=>$fv){
+                               if      (preg_match('/\.php/', $fv)==1){
+                                       continue;       //skip the php file
+                               }
+
+                               //check if this is part of the rule, if so,add it, o/w ignore
+                               if (array_search($fv, $this->rule)!==FALSE){
+                                       $new_query .= $fv . '=' . $query[$fk+1] . SEP;
+                               }
+                       }
+                       $query = $new_query;    //done
+               }
+
+               $temp = explode(SEP, $query);
+               foreach ($temp as $index=>$attributes){
+                       if(empty($attributes)){
+                               //skip the ones that are empty.
+                               continue;
+                       }
+                       list($key, $value) = preg_split('/\=/', $attributes, 2);
+                       $query_parts[$key] = $value;
+               }
+
+               $query_string = '';
+               //construct pretty url on mapping
+               foreach ($this->rule as $key=>$value){
+                       //if this value is empty, the url construction should quit.
+                       if ($query_parts[$value] ==''){
+                               break;
+                       }
+                       $url .= $query_parts[$value].'/';
+
+                       //if the query parts are not in the defined rules, set it back to query string again
+                       if ($query_parts[$this->rule[$key]]!=''){
+                               $query_parts[$this->rule[$key]] = '';
+                       }
+               }
+
+               //Go through the query_parts again, and for those values that are not empty
+               // add it to the querystring
+               foreach($query_parts as $key=>$value){
+                       //paginator are handle differently
+                       if ($value!='' && $key!='page'){
+                               $query_string .= $key.'='.$value.SEP;
+                       }
+               }
+               //take out the last sep.
+               $query_string = substr($query_string, 0, -1);
+
+               //handle paginators
+//             if ($query_parts['page']!=''){
+//                     $url .= '/'.$query_parts['page'].'.html';
+//             }
+
+               //append query string at the back
+               if ($query_string!=''){
+                       $url .= '?'.$query_string;
+               }
+
+               //finally, append bookmark if not emptied
+               if ($bookmark!=''){
+                       $url .= $bookmark;
+               }
+
+               return $url;
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/UrlRewrite/FileStorageUrl.class.php b/include/classes/UrlRewrite/FileStorageUrl.class.php
new file mode 100644 (file)
index 0000000..9307d4b
--- /dev/null
@@ -0,0 +1,153 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: FileStorageUrl.class.php 7603 2008-06-11 14:59:33Z hwong $
+/**
+* FileStorageUrl
+* Class for rewriting pretty urls in tests
+* @access      public
+* @author      Harris Wong
+* @package     UrlParser
+*/
+class FileStorageUrl {
+       // local variables
+       var $rule;              //an array that maps [lvl->query parts]
+
+       // constructor
+       // @param the filename that was being called, this can be index.php, comments.php, revisions.php
+       function FileStorageUrl($filename) {
+               if ($filename == ''){
+                       $filename = 'index.php';
+               }
+               $this->rule = array(0=>'action', 1=>'ot', 2=>'oid', 3=>'folder');       //default 3=folder, but it can be id as well for comment
+               $this->filename = $filename;
+       }
+
+       //
+       function setRule($id, $ruleName){
+               $this->rule[$id] = $ruleName;
+       }
+
+       /**
+        * Construct pretty url by the given query string.
+        * Note:        This method will be a bit different from ForumsUrl, TestsUrl, ContentUrl because it has browse/comment in the rule which 
+        *                      doesn't exist in the actual query.
+        * @param       string  the query string of the url
+        * @param       string  filename of the request, this consists of revisions.php, index.php, comments.php
+        */
+       function constructPrettyUrl($query){
+               if (empty($query)){
+                       return '';
+               }
+
+               //If this is already a pretty url,but without mod_apache rule
+               //unwrap it and reconstruct
+               if (is_array($query)){
+                       $new_query = '';
+                       foreach($query as $fk=>$fv){
+                               if      (preg_match('/\.php/', $fv)==1){
+                                       continue;       //skip the php file
+                               }
+
+                               //check if this is part of the rule, if so,add it, o/w ignore
+                               if (array_search($fv, $this->rule)!==FALSE){
+                                       $new_query .= $fv . '=' . $query[$fk+1] . SEP;
+                               }
+                       }
+                       $query = $new_query;    //done
+               }
+
+               $temp = explode(SEP, $query);
+               foreach ($temp as $index=>$attributes){
+                       if(empty($attributes)){
+                               //skip the ones that are empty.
+                               continue;
+                       }
+                       list($key, $value) = preg_split('/\=/', $attributes, 2);
+                       $query_parts[$key] = $value;
+               }
+
+               $query_string = '';
+               //determine if this uses 'browse' or 'comment'
+               $prefix = $this->configRule($this->filename);
+               if ($prefix != '') {
+                       $url .= $prefix.'/' ;   //add either index, revision or comment to the url
+               }
+
+               //construct pretty url on mapping
+               foreach ($this->rule as $key=>$value){
+
+                       //if this is action, skip it.
+                       if ($value == 'action'){
+                               continue;
+                       } elseif ($query_parts[$value] ==''){
+                               //if this value is empty, the url construction should quit.
+                               break;
+                       }
+                       $url .= $query_parts[$value].'/';
+
+                       //if the query parts are not in the defined rules, set it back to query string again
+                       if ($query_parts[$this->rule[$key]]!=''){
+                               $query_parts[$this->rule[$key]] = '';
+                       }
+               }
+
+               //Go through the query_parts again, and for those values that are not empty
+               // add it to the querystring
+               foreach($query_parts as $key=>$value){
+                       //paginator are handle differently
+                       if ($value!='' && $key!='page'){
+                               $query_string .= $key.'='.$value.SEP;
+                       }
+               }
+               //take out the last sep.
+               $query_string = substr($query_string, 0, -1);
+
+               //handle paginators
+               if ($query_parts['page']!=''){
+                       $url .= '/'.$query_parts['page'].'.html';
+               }
+
+               //append query string at the back
+               if ($query_string!=''){
+                       $url .= '?'.$query_string;
+               }
+
+               return $url;
+       }
+
+
+       /**
+        * A helper method for constructPrettyUrl
+        * @param       string  filename
+        */
+       function configRule($filename){
+               //run through the query once, extract if it uses id or folder.
+               //if 'id', it is comments.php
+               //if 'folder', it is index.php
+               if ($filename=='comments.php'){
+                       $this->setRule(3, 'id');
+                       return 'comments';
+               } elseif ($filename=='revisions.php'){
+                       $this->setRule(3, 'id');
+                       return 'revisions';
+               } else {
+                       $this->setRule(3, 'folder');
+//                     return 'index';
+                       return '';
+               }
+
+       }
+
+
+}
+?>
\ No newline at end of file
diff --git a/include/classes/UrlRewrite/ForumsUrl.class.php b/include/classes/UrlRewrite/ForumsUrl.class.php
new file mode 100644 (file)
index 0000000..90f3c48
--- /dev/null
@@ -0,0 +1,106 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: ForumsUrl.class.php 7603 2008-06-11 14:59:33Z hwong $
+/**
+* UrlParser
+* Class for rewriting pretty urls on forums.
+* @access      public
+* @author      Harris Wong
+* @package     UrlParser
+*/
+class ForumsUrl {
+       // constructor
+       function ForumsUrl() {
+               $this->rule = array(0=>'fid', 1=>'pid');
+       }
+
+
+       /**
+        * Construct pretty url by the given query string.
+        */
+       function constructPrettyUrl($query){
+               if (empty($query)){
+                       return '';
+               }
+
+               //If this is already a pretty url,but without mod_apache rule
+               //unwrap it and reconstruct
+               if (is_array($query)){
+                       $new_query = '';
+                       foreach($query as $fk=>$fv){
+                               if      (preg_match('/\.php/', $fv)==1){
+                                       continue;       //skip the php file
+                               }
+
+                               //check if this is part of the rule, if so,add it, o/w ignore
+                               if (array_search($fv, $this->rule)!==FALSE){
+                                       $new_query .= $fv . '=' . $query[$fk+1] . SEP;
+                               } elseif (preg_match('/([0-9]+)\.html/', $fv, $matches)==1){
+                                       $new_query .= 'page=' . $matches[1] . SEP;
+                               }
+                       }
+                       $query = $new_query;    //done
+               }
+
+               $temp = explode(SEP, $query);
+               foreach ($temp as $index=>$attributes){
+                       if(empty($attributes)){
+                               //skip the ones that are empty.
+                               continue;
+                       }
+                       list($key, $value) = preg_split('/\=/', $attributes, 2);
+                       $query_parts[$key] = $value;
+               }
+
+               $query_string = '';
+
+               //construct pretty url on mapping
+               foreach ($this->rule as $key=>$value){
+
+                       //if this value is empty, the url construction should quit.
+                       if ($query_parts[$value] ==''){
+                               break;
+                       }
+                       $url .= $query_parts[$value].'/';
+
+                       //if the query parts are not in the defined rules, set it back to query string again
+                       if ($query_parts[$this->rule[$key]]!=''){
+                               $query_parts[$this->rule[$key]] = '';
+                       }
+               }
+
+               //Go through the query_parts again, and for those values that are not empty
+               // add it to the querystring
+               foreach($query_parts as $key=>$value){
+                       //paginator are handle differently
+                       if ($value!='' && $key!='page'){
+                               $query_string .= $key.'='.$value.SEP;
+                       }
+               }
+               //take out the last sep.
+               $query_string = substr($query_string, 0, -1);
+
+               //handle paginators
+               if ($query_parts['page']!=''){
+                       $url .= $query_parts['page'].'.html';
+               }
+
+               //append query string at the back
+               if ($query_string!=''){
+                       $url .= '?'.$query_string;
+               }
+
+               return $url;
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/UrlRewrite/GlossaryUrl.class.php b/include/classes/UrlRewrite/GlossaryUrl.class.php
new file mode 100644 (file)
index 0000000..08206b1
--- /dev/null
@@ -0,0 +1,116 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: TestsUrl.class.php 7603 2008-06-11 14:59:33Z hwong $
+/**
+* UrlParser
+* Class for rewriting pretty urls on forums.
+* @access      public
+* @author      Harris Wong
+* @package     UrlParser
+*/
+class GlossaryUrl {
+       // constructor
+       function GlossaryUrl() {
+               $this->rule = array(0=>'p');
+       }
+
+       /**
+        * Construct pretty url by the given query string.
+        */
+       function constructPrettyUrl($query){
+               if (empty($query)){
+                       return '';
+               }
+
+               //Take out bookmark
+               if (($pos = strpos($query, '#'))!==FALSE){
+                       $bookmark = substr($query, $pos);
+                       $query = substr($query, 0, $pos);
+               }
+
+               //If this is already a pretty url,but without mod_apache rule
+               //unwrap it and reconstruct
+               if (is_array($query)){
+                       $new_query = '';
+                       foreach($query as $fk=>$fv){
+                               if      (preg_match('/\.php/', $fv)==1){
+                                       continue;       //skip the php file
+                               }
+
+                               //check if this is part of the rule, if so,add it, o/w ignore
+                               if (array_search($fv, $this->rule)!==FALSE){
+                                       $new_query .= $fv . '=' . $query[$fk+1] . SEP;
+                               } elseif (preg_match('/([0-9]+)\.html/', $fv, $matches)==1){
+                                       $new_query .= 'page=' . $matches[1] . SEP;
+                               }
+                       }
+                       $query = $new_query;    //done
+               }
+
+               $temp = explode(SEP, $query);
+               foreach ($temp as $index=>$attributes){
+                       if(empty($attributes)){
+                               //skip the ones that are empty.
+                               continue;
+                       }
+                       list($key, $value) = preg_split('/\=/', $attributes, 2);
+                       $query_parts[$key] = $value;
+               }
+
+               $query_string = '';
+
+               //construct pretty url on mapping
+               foreach ($this->rule as $key=>$value){
+
+                       //if this value is empty, the url construction should quit.
+                       if ($query_parts[$value] ==''){
+                               break;
+                       }
+                       $url .= $query_parts[$value].'/';
+
+                       //if the query parts are not in the defined rules, set it back to query string again
+                       if ($query_parts[$this->rule[$key]]!=''){
+                               $query_parts[$this->rule[$key]] = '';
+                       }
+               }
+
+               //Go through the query_parts again, and for those values that are not empty
+               // add it to the querystring
+               foreach($query_parts as $key=>$value){
+                       //paginator are handle differently
+                       if ($value!='' && $key!='page'){
+                               $query_string .= $key.'='.$value.SEP;
+                       }
+               }
+               //take out the last sep.
+               $query_string = substr($query_string, 0, -1);
+
+               //handle paginators
+               if ($query_parts['page']!=''){
+                       $url .= $query_parts['page'].'.html';
+               }
+
+               //append query string at the back
+               if ($query_string!=''){
+                       $url .= '?'.$query_string;
+               }
+
+               //finally, append bookmark if not emptied
+               if ($bookmark!=''){
+                       $url .= $bookmark;
+               }
+
+               return $url;
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/UrlRewrite/TestsUrl.class.php b/include/classes/UrlRewrite/TestsUrl.class.php
new file mode 100644 (file)
index 0000000..aee761d
--- /dev/null
@@ -0,0 +1,110 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: TestsUrl.class.php 7603 2008-06-11 14:59:33Z hwong $
+/**
+* UrlParser
+* Class for rewriting pretty urls on forums.
+* @access      public
+* @author      Harris Wong
+* @package     UrlParser
+*/
+class TestsUrl {
+       // local variables
+//     var $rule;              //an array that maps [lvl->query parts]
+//     var $className; //the name of this class
+
+       // constructor
+       function TestsUrl() {
+               $this->rule = array(0=>'tid', 1=>'action');
+       }
+
+
+       /**
+        * Construct pretty url by the given query string.
+        */
+       function constructPrettyUrl($query){
+               if (empty($query)){
+                       return '';
+               }
+
+               //If this is already a pretty url,but without mod_apache rule
+               //unwrap it and reconstruct
+               if (is_array($query)){
+                       $new_query = '';
+                       foreach($query as $fk=>$fv){
+                               if      (preg_match('/\.php/', $fv)==1){
+                                       continue;       //skip the php file
+                               }
+
+                               //check if this is part of the rule, if so,add it, o/w ignore
+                               if (array_search($fv, $this->rule)!==FALSE){
+                                       $new_query .= $fv . '=' . $query[$fk+1] . SEP;
+                               } elseif (preg_match('/([0-9]+)\.html/', $fv, $matches)==1){
+                                       $new_query .= 'page=' . $matches[1] . SEP;
+                               }
+                       }
+                       $query = $new_query;    //done
+               }
+
+               $temp = explode(SEP, $query);
+               foreach ($temp as $index=>$attributes){
+                       if(empty($attributes)){
+                               //skip the ones that are empty.
+                               continue;
+                       }
+                       list($key, $value) = preg_split('/\=/', $attributes, 2);
+                       $query_parts[$key] = $value;
+               }
+
+               $query_string = '';
+
+               //construct pretty url on mapping
+               foreach ($this->rule as $key=>$value){
+
+                       //if this value is empty, the url construction should quit.
+                       if ($query_parts[$value] ==''){
+                               break;
+                       }
+                       $url .= $query_parts[$value].'/';
+
+                       //if the query parts are not in the defined rules, set it back to query string again
+                       if ($query_parts[$this->rule[$key]]!=''){
+                               $query_parts[$this->rule[$key]] = '';
+                       }
+               }
+
+               //Go through the query_parts again, and for those values that are not empty
+               // add it to the querystring
+               foreach($query_parts as $key=>$value){
+                       //paginator are handle differently
+                       if ($value!='' && $key!='page'){
+                               $query_string .= $key.'='.$value.SEP;
+                       }
+               }
+               //take out the last sep.
+               $query_string = substr($query_string, 0, -1);
+
+               //handle paginators
+               if ($query_parts['page']!=''){
+                       $url .= $query_parts['page'].'.html';
+               }
+
+               //append query string at the back
+               if ($query_string!=''){
+                       $url .= '?'.$query_string;
+               }
+
+               return $url;
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/UrlRewrite/UrlParser.class.php b/include/classes/UrlRewrite/UrlParser.class.php
new file mode 100644 (file)
index 0000000..8cf0793
--- /dev/null
@@ -0,0 +1,137 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: UrlParser.class.php 7208 2008-04-15 10:00:24Z harris $
+
+require_once('UrlRewrite.class.php');
+
+/**
+* UrlParser
+* Class for rewriting pretty urls.
+* @access      public
+* @author      Harris Wong
+* @package     UrlParser
+*/
+class UrlParser {
+       //Variables
+       var $path_array;        //an array [0]->course_id; [1]->class obj
+
+       // Constructor
+       function UrlParser($pathinfo=''){
+               if ($pathinfo==''){
+                       $pathinfo = $_SERVER['PATH_INFO'];
+               }
+               $this->parsePathInfo($pathinfo);
+       }
+
+       /**
+        * This function will take the pathinfo and return an array of elements 
+        * retrieved from the path info.
+        * An ATutor pathinfo will always be in the format of /<course_slug>/<type>/<parts>
+        * course_slug is the course_slug defined in course preference (or course id if it's empty)
+        * type is the folder, particularlly forums, content, tests, blogs, mods, etc.
+        * parts is the extra info about this url request.
+        * @param       string  the pathinfo from the URL
+        * @access      private
+        */
+       function parsePathinfo($pathinfo){
+               global $db;
+               $pathinfo = strtolower($pathinfo);
+
+               //remove AT_PRETTY_URL_HANDLER from the path info.
+               if (($pos=strpos($pathinfo, AT_PRETTY_URL_HANDLER))!==FALSE){
+                       $pathinfo = substr($pathinfo, $pos);
+               }
+
+               /* 
+                * matches[1] = course slug/id
+                * matches[2] = path
+                * matches[3] = useless, just a place holder
+                * matches[4] = filename
+                * matches[5] = query string in pretty format
+                * @http://ca3.php.net/preg_match
+                */
+               if (strpos($pathinfo, 'mods')!==FALSE){
+                       //If this is a mod, its file name will be longer with mods/ infront
+                       preg_match('/^\/[\w\-]+\/?$|(\/[\w]+)(\/mods(\/[\w]+)+)\/([\w\_\.]+\.php)([\/\w\W]*)/', $pathinfo, $matches);                   
+               } else {
+                       preg_match('/^\/[\w\-]+\/?$|(\/[\w]+)(([\/\w]*))\/([\w\_\.]+\.php)([\/\w\W]*)/', $pathinfo, $matches);
+               }
+
+               if (empty($matches)){
+                       //no matches.
+                       $matches[1] = 0;
+               } elseif (sizeof($matches)==1){
+                       //if the url consist of just the course slug, the size would be just 2
+                       $matches[1] = $matches[0];
+               } 
+
+               //take out the front slash
+               $matches[1] = preg_replace('/\//', '', $matches[1]);
+               $course_id = $matches[1];
+
+               //check if this is a course slug or course id.
+               if (preg_match('/^[\d]+$/', $matches[1])==0){
+                       //it's a course slug, log into the course.
+                       $sql    = "SELECT course_id FROM ".TABLE_PREFIX."courses WHERE course_dir_name='$matches[1]'";
+                       $result = mysql_query($sql, $db);
+                       $row = mysql_fetch_assoc($result);
+                       if ($row['course_id']!=''){
+                               $course_id = $row['course_id'];
+                       } else {
+                               $course_id = 0;
+                       }
+               }
+
+               //Check if there are any matches for prettied query string, if not, use the actual query.
+               if ($matches[5] == ''){
+                       $matches[5] = $_SERVER['QUERY_STRING'];
+               }
+
+               //Create object based on this path.
+               $url_obj = new UrlRewrite($matches[2], $matches[4], $matches[5]);
+
+               $this->path_array = array($course_id, $url_obj);
+       }
+
+       
+       /**
+        * return the path array
+        */
+       function getPathArray(){
+               return $this->path_array;
+       }
+
+
+       /**
+        * Returns course_id if config_[course_dir_name] is switched off, 
+        * otherwise, return the course dir name.
+        * Called by vitals.inc.php
+        *
+        * @param       int             course id
+        * @return      mixed   course id if config[course_dir_name] is 0, course_dir_name otherwise
+        */
+       function getCourseDirName($course_id){
+               global $db; 
+               $course_id = intval($course_id);
+
+               $sql    = "SELECT course_dir_name FROM ".TABLE_PREFIX."courses WHERE course_id=$course_id";
+               $result = mysql_query($sql, $db);
+               $row = mysql_fetch_assoc($result);
+               if ($row['course_dir_name']!=''){
+                       $course_id = $row['course_dir_name'];
+               } 
+
+               return $course_id;
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/UrlRewrite/UrlRewrite.class.php b/include/classes/UrlRewrite/UrlRewrite.class.php
new file mode 100644 (file)
index 0000000..c0efa9b
--- /dev/null
@@ -0,0 +1,333 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: UrlRewrite.class.php 7603 2008-06-11 14:59:33Z hwong $
+
+//Include all the classes for external rewrite rules
+require_once('ForumsUrl.class.php');
+require_once('ContentUrl.class.php');
+require_once('FileStorageUrl.class.php');
+require_once('TestsUrl.class.php');
+require_once('GlossaryUrl.class.php');
+
+/**
+* UrlRewrite
+* Class for rewriting pretty urls.
+* @access      public
+* @author      Harris Wong
+* @package     UrlRewrite
+*/
+class UrlRewrite  {
+       // local variables
+       var $path;              //the path of this script
+       var $filename;  //script name
+       var $query;             //the queries of the REQUEST
+       var $isEmpty;   //true if path, filename, and query are empty
+
+       // constructor
+       function UrlRewrite($path, $filename, $query) {
+               if ($path=='' && $filename=='' && $query==''){
+                       $this->isEmpty = true;
+               } else {
+                       $this->isEmpty = false;
+               }
+               $this->path = $path;
+               $this->filename = $filename;
+               $this->query = $query;
+       }
+
+       /** 
+        * Returns the link that points to this object as a page.
+        * @access public
+        */
+       function redirect(){
+               //redirect to that url.
+               return '/'.$this->getPage();
+       }
+
+       /** 
+        * Parser for the pathinfo, return an array with mapped key values similar to the querystring.
+        * @access      public
+        * @return      array   key=>value, where keys and values have the same meaning as the ones in the query strings.
+        */
+       function parsePrettyQuery(){
+               global $_config;
+               $result = array();
+
+               //return empty array if query is empty
+               if (empty($this->query)){
+                       return $result;
+               }
+
+               //if course_dir_name is disabled from admin. 
+               if ($_config['pretty_url']==0){
+                       return $this->query;
+               }
+
+               //If the first char is /, cut it
+               if (strpos($this->query, '/') == 0){
+                       $query_parts = explode('/', substr($this->query, 1));
+               } else {
+                       $query_parts = explode('/', $this->query);
+               }
+
+               //dynamically create the array
+               //assumption: pathinfo ALWAYS in the format of key1/value1/key2/value2/key3/value3/etc...
+               foreach ($query_parts as $array_index=>$key_value){
+                       if($array_index%2 == 0 && $query_parts[$array_index]!=''){
+                               $result[$key_value] = $query_parts[$array_index+1];
+                       }
+               }
+               return $result;
+       }
+
+
+       /**
+        * Parser for the querystrings url
+        * @access      public
+        * @param       string  querystring
+        * @return      array   an array of mapped keys and values like the querystrings.
+        *
+        * NOTE:        Stopped using this function since we've decided to dynamically create the URL. 
+        *                      See: parsePrettyQuery()
+        */
+       function parseQuery($query){
+               //return empty array if query is empty
+               if (empty($query)){
+                       return array();
+               }
+
+               parse_str($this->query, $result);
+               return $result;
+       }
+
+
+       /**
+        * Construct the pretty url based on the given query.
+        * @access      public
+        * @param       string  the pathinfo query
+        * @return      string  pretty url
+        */
+       function constructPrettyUrl($query){
+               global $_config; 
+               if (empty($query)){
+                       return '';
+               }
+
+               //Take out bookmark, and store it.
+               if (($pos = strpos($query, '#'))!==FALSE){
+                       $bookmark = substr($query, $pos);
+                       $query = substr($query, 0, $pos);
+               }
+
+               //If this is already a pretty url,but without mod_apache rule
+               //unwrap it and reconstruct
+               if (is_array($query)){
+                       $new_query = '';
+                       foreach($query as $fk=>$fv){
+                               if      (preg_match('/\.php/', $fv)==1){
+                                       continue;       //skip the php file
+                               }
+
+                               //check if this is part of the rule, if so,add it, o/w ignore
+                               if (array_search($fv, $this->rule)!==FALSE){
+                                       $new_query .= $fv . '=' . $query[$fk+1] . SEP;
+                               } elseif (preg_match('/([0-9]+)\.html/', $fv, $matches)==1){
+                                       $new_query .= 'page=' . $matches[1] . SEP;
+                               }
+                       }
+                       $query = $new_query;    //done
+               }
+
+               //do not change query if pretty url is disabled
+               if ($_config['pretty_url'] == 0){
+                       $pretty_url = $query;
+               } else {
+                       $pretty_url = '';               //init url
+                       $query_parts = explode(SEP, $query);
+                       foreach ($query_parts as $index=>$attributes){
+                               if(empty($attributes)){
+                                       //skip the ones that are empty.
+                                       continue;
+                               }
+                               list($key, $value) = preg_split('/\=/', $attributes, 2);
+                               $pretty_url .= $key . '/' . $value .'/';
+                       }
+               }
+
+               //finally, append bookmark if not emptied
+               if ($bookmark!=''){
+                       $pretty_url .= $bookmark;
+               }
+
+               return $pretty_url;
+       }
+
+
+       /**
+        * This function is used to convert the input URL to a pretty URL.
+        * @param       int             course id
+        * @param       string  normal URL, WITHOUT the <prototal>://<host>
+        * @return      pretty url
+        */
+       function convertToPrettyUrl($course_id, $url){
+               global $_config, $db;
+               list($front, $end) = preg_split('/\?/', $url);
+               $front_array = explode('/', $front);
+
+               //find out what kind of link this is, pretty url? relative url? or PHP_SELF url?
+               $dir_deep        = substr_count(AT_INCLUDE_PATH, '..');
+               $url_parts       = explode('/', $_SERVER['PHP_SELF']);
+               $host_dir        = implode('/', array_slice($url_parts, 0, count($url_parts) - $dir_deep-1));
+               //The link is a bounce link
+               if(preg_match('/bounce.php\?course=([\d]+)$/', $url, $matches)==1){
+                       if (!empty($course_id)) {
+                               $pretty_url = $course_id;               //course_id should be assigned by vitals depending on the system pref.
+                       } else {
+                               $pretty_url = $matches[1];              //happens when course dir name is disabled
+                       }
+               } elseif(in_array(AT_PRETTY_URL_HANDLER, $front_array)===TRUE){
+                       //The relative link is a pretty URL
+                       $front_result = array();
+                       //spit out the URL in between AT_PRETTY_URL_HANDLER to *.php
+                       //note, pretty url is defined to be AT_PRETTY_URL_HANDLER/course_slug/type/location/...
+                       //ie. AT_PRETTY_URL_HANDLER/1/forum/view.php/...
+                       while (($needle = array_search(AT_PRETTY_URL_HANDLER, $front_array)) !== FALSE){
+                               $front_array = array_slice($front_array, $needle + 1);
+                       }
+                       $front_array = array_slice($front_array, $needle + 1);  //+2 because we want the entries after the course_slug
+
+                       //Handle url differently IF mod_rewrite is enabled, and if there are no query strings at the back,
+                       //then we will have to reuse the current pathinfo to reconstruct the query.
+                       if ($_config['apache_mod_rewrite'] > 0 && $end==''){
+                               $end = $front_array;    //let the class handles it
+                       } 
+
+                       /* Overwrite pathinfo
+                        * ie. /go.php/1/forum/view.php/fid/1/pid/17/?fid=1&pid=17&page=5
+                        * In the above case, cut off the original pathinfo, and replace it with the new querystrings
+                        * If querystring is empty, then use the old one, ie. /go.php/1/forum/view.php/fid/1/pid/17/.
+                        */
+                       foreach($front_array as $fk=>$fv){
+                               array_push($front_result, $fv);
+                               if      (!empty($end) && preg_match('/\.php/', $fv)==1){
+                                       break;
+                               }
+                       }
+                       $front = implode('/', $front_result);
+               } elseif (strpos($front, $host_dir)!==FALSE){
+                       //Not a relative link, it contains the full PHP_SELF path.
+                       $front = substr($front, strlen($host_dir)+1);  //stripe off the slash after the host_dir as well
+               } elseif ($course_id == ''){
+                       //if this is my start page
+                       return $url;
+               }
+               //Turn querystring to pretty URL
+               if ($pretty_url==''){
+                       //Get the original course id back
+                       $sql    = "SELECT course_id FROM ".TABLE_PREFIX."courses WHERE course_dir_name='$course_id'";
+                       $result = mysql_query($sql, $db);
+                       $row = mysql_fetch_assoc($result);
+                       if ($row['course_id']!=''){
+                               $course_orig = $row['course_id'];
+                       } 
+
+                       //Add course id in if both course_id or course_dir_name are not there
+                       if (preg_match('/^\/?('.$course_id.'|'.$course_orig.')\//', $front)==0){
+                               $pretty_url = $course_id.'/';
+                       }
+
+                       //check if there are any rules overwriting the original rules
+                       //TODO: have a better way to do this
+                       //              extend modularity into this.
+                       $obj =& $this;  //default
+                       //Overwrite the UrlRewrite obj if there are any private rules
+                       if ($_config['apache_mod_rewrite'] > 0){
+                               //take out '.php' if any exists.
+                               if ($end=='' && preg_match('/index\.php$/', $front)==1){
+                                       $pretty_url .= preg_replace('/index.php/', '', $front);
+                               } else {
+                                       $pretty_url .= preg_replace('/\.php/', '', $front);
+                               }
+
+                               if (preg_match('/forum\/(index|view|list)\.php/', $front)==1) {
+                                       $pretty_url = $course_id.'/forum';
+                                       $obj =& new ForumsUrl();
+                               } elseif (preg_match('/(content\.php)(\/cid(\/\d+))?/', $front, $matches)==1){
+                                       $pretty_url = $course_id.'/content';
+                                       //if there are other pretty url queries at the back, append it
+                                       //Note: this is to fix the hopping content problem between diff courses
+                                       if ($matches[3] != ''){
+                                               $pretty_url .= $matches[3];
+                                       }
+                                       $obj =& new ContentUrl();
+                               } elseif (preg_match('/file_storage\/((index|revisions|comments)\.php)?/', $front, $matches)==1){
+                                       $pretty_url = $course_id.'/file_storage';
+                                       $obj =& new FileStorageUrl($matches[1]);
+                               } elseif (preg_match('/tools\/test_intro\.php/', $front)==1){
+                                       $pretty_url = $course_id.'/tests_surveys';
+                                       $obj =& new TestsUrl();
+                               } elseif (preg_match('/glossary\/index\.php/', $front)==1){
+                                       $pretty_url = $course_id.'/glossary';
+                                       $obj =& new GlossaryUrl();
+                               }
+                       } else {
+                               $pretty_url .= $front;
+                       }
+
+                       if ($end != ''){
+                               //if pretty url is turned off, use '?' to separate the querystring.
+                               ($_config['pretty_url'] == 0)? $qs_sep = '?': $qs_sep = '/';
+                                $pretty_url .= $qs_sep.$obj->constructPrettyUrl($end);
+                       }
+               }
+
+               //if mod_rewrite is switched on, defined in constants.inc.php
+               if ($_config['apache_mod_rewrite'] > 0){
+                       return $pretty_url;
+               }
+               return AT_PRETTY_URL_HANDLER.'/'.$pretty_url;
+       }
+
+
+       /**
+        * Return the paths where this script is
+        */
+       function getPath(){
+               if ($this->path != ''){
+                       return substr($this->path, 1).'/';
+               }
+               return '';
+       }
+
+       /**
+        * Return the script name
+        */
+       function getFileName(){
+               return $this->filename;
+       }
+
+       /**
+        * 
+        */
+       function getPage(){
+               return $this->getPath().$this->getFileName();
+       }
+
+       /**
+        * Return true if path, filename, and query are empty.
+        */
+       function isEmpty(){
+               return $this->isEmpty;
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/XML/XML_HTMLSax/HTMLSax/XML_HTMLSax_Decorators.php b/include/classes/XML/XML_HTMLSax/HTMLSax/XML_HTMLSax_Decorators.php
new file mode 100644 (file)
index 0000000..e730bb5
--- /dev/null
@@ -0,0 +1,306 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//
+// +----------------------------------------------------------------------+
+// | PHP Version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2002 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license,      |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/3_0.txt.                                  |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Alexander Zhukov <alex@veresk.ru> Original port from Python |
+// | Authors: Harry Fuecks <hfuecks@phppatterns.com> Port to PEAR + more  |
+// | Authors: Many @ Sitepointforums Advanced PHP Forums                  |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+//
+/**
+* Decorators for dealing with parser options
+* @package XML_HTMLSax
+* @version $Id$
+* @see XML_HTMLSax::set_option
+*/
+/**
+* Trims the contents of element data from whitespace at start and end
+* @package XML_HTMLSax
+* @access protected
+*/
+class XML_HTMLSax_Trim {
+    /**
+    * Original handler object
+    * @var object
+    * @access private
+    */
+    var $orig_obj;
+    /**
+    * Original handler method
+    * @var string
+    * @access private
+    */
+    var $orig_method;
+    /**
+    * Constructs XML_HTMLSax_Trim
+    * @param object handler object being decorated
+    * @param string original handler method
+    * @access protected
+    */
+    function XML_HTMLSax_Trim(&$orig_obj, $orig_method) {
+        $this->orig_obj =& $orig_obj;
+        $this->orig_method = $orig_method;
+    }
+    /**
+    * Trims the data
+    * @param XML_HTMLSax
+    * @param string element data
+    * @access protected
+    */
+    function trimData(&$parser, $data) {
+        $data = trim($data);
+        if ($data != '') {
+            $this->orig_obj->{$this->orig_method}($parser, $data);
+        }
+    }
+}
+/**
+* Coverts tag names to upper case
+* @package XML_HTMLSax
+* @access protected
+*/
+class XML_HTMLSax_CaseFolding {
+    /**
+    * Original handler object
+    * @var object
+    * @access private
+    */
+    var $orig_obj;
+    /**
+    * Original open handler method
+    * @var string
+    * @access private
+    */
+    var $orig_open_method;
+    /**
+    * Original close handler method
+    * @var string
+    * @access private
+    */
+    var $orig_close_method;
+    /**
+    * Constructs XML_HTMLSax_CaseFolding
+    * @param object handler object being decorated
+    * @param string original open handler method
+    * @param string original close handler method
+    * @access protected
+    */
+    function XML_HTMLSax_CaseFolding(&$orig_obj, $orig_open_method, $orig_close_method) {
+        $this->orig_obj =& $orig_obj;
+        $this->orig_open_method = $orig_open_method;
+        $this->orig_close_method = $orig_close_method;
+    }
+    /**
+    * Folds up open tag callbacks
+    * @param XML_HTMLSax
+    * @param string tag name
+    * @param array tag attributes
+    * @access protected
+    */
+    function foldOpen(&$parser, $tag, $attrs=array(), $empty = FALSE) {
+        $this->orig_obj->{$this->orig_open_method}($parser, strtoupper($tag), $attrs, $empty);
+    }
+    /**
+    * Folds up close tag callbacks
+    * @param XML_HTMLSax
+    * @param string tag name
+    * @access protected
+    */
+    function foldClose(&$parser, $tag, $empty = FALSE) {
+        $this->orig_obj->{$this->orig_close_method}($parser, strtoupper($tag), $empty);
+    }
+}
+/**
+* Breaks up data by linefeed characters, resulting in additional
+* calls to the data handler
+* @package XML_HTMLSax
+* @access protected
+*/
+class XML_HTMLSax_Linefeed {
+    /**
+    * Original handler object
+    * @var object
+    * @access private
+    */
+    var $orig_obj;
+    /**
+    * Original handler method
+    * @var string
+    * @access private
+    */
+    var $orig_method;
+    /**
+    * Constructs XML_HTMLSax_LineFeed
+    * @param object handler object being decorated
+    * @param string original handler method
+    * @access protected
+    */
+    function XML_HTMLSax_LineFeed(&$orig_obj, $orig_method) {
+        $this->orig_obj =& $orig_obj;
+        $this->orig_method = $orig_method;
+    }
+    /**
+    * Breaks the data up by linefeeds
+    * @param XML_HTMLSax
+    * @param string element data
+    * @access protected
+    */
+    function breakData(&$parser, $data) {
+        $data = explode("\n",$data);
+        foreach ( $data as $chunk ) {
+            $this->orig_obj->{$this->orig_method}($parser, $chunk);
+        }
+    }
+}
+/**
+* Breaks up data by tab characters, resulting in additional
+* calls to the data handler
+* @package XML_HTMLSax
+* @access protected
+*/
+class XML_HTMLSax_Tab {
+    /**
+    * Original handler object
+    * @var object
+    * @access private
+    */
+    var $orig_obj;
+    /**
+    * Original handler method
+    * @var string
+    * @access private
+    */
+    var $orig_method;
+    /**
+    * Constructs XML_HTMLSax_Tab
+    * @param object handler object being decorated
+    * @param string original handler method
+    * @access protected
+    */
+    function XML_HTMLSax_Tab(&$orig_obj, $orig_method) {
+        $this->orig_obj =& $orig_obj;
+        $this->orig_method = $orig_method;
+    }
+    /**
+    * Breaks the data up by linefeeds
+    * @param XML_HTMLSax
+    * @param string element data
+    * @access protected
+    */
+    function breakData(&$parser, $data) {
+        $data = explode("\t",$data);
+        foreach ( $data as $chunk ) {
+            $this->orig_obj->{$this->orig_method}($this, $chunk);
+        }
+    }
+}
+/**
+* Breaks up data by XML entities and parses them with html_entity_decode(),
+* resulting in additional calls to the data handler<br />
+* Requires PHP 4.3.0+
+* @package XML_HTMLSax
+* @access protected
+*/
+class XML_HTMLSax_Entities_Parsed {
+    /**
+    * Original handler object
+    * @var object
+    * @access private
+    */
+    var $orig_obj;
+    /**
+    * Original handler method
+    * @var string
+    * @access private
+    */
+    var $orig_method;
+    /**
+    * Constructs XML_HTMLSax_Entities_Parsed
+    * @param object handler object being decorated
+    * @param string original handler method
+    * @access protected
+    */
+    function XML_HTMLSax_Entities_Parsed(&$orig_obj, $orig_method) {
+        $this->orig_obj =& $orig_obj;
+        $this->orig_method = $orig_method;
+    }
+    /**
+    * Breaks the data up by XML entities
+    * @param XML_HTMLSax
+    * @param string element data
+    * @access protected
+    */
+    function breakData(&$parser, $data) {
+        $data = preg_split('/(&.+?;)/',$data,-1,PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
+        foreach ( $data as $chunk ) {
+            $chunk = html_entity_decode($chunk,ENT_NOQUOTES);
+            $this->orig_obj->{$this->orig_method}($this, $chunk);
+        }
+    }
+}
+/**
+* Compatibility with older PHP versions
+*/
+if (version_compare(phpversion(), '4.3', '<') && !function_exists('html_entity_decode') ) {
+    function html_entity_decode($str, $style=ENT_NOQUOTES) {
+        return strtr($str,
+            array_flip(get_html_translation_table(HTML_ENTITIES,$style)));
+    }
+}
+/**
+* Breaks up data by XML entities but leaves them unparsed,
+* resulting in additional calls to the data handler<br />
+* @package XML_HTMLSax
+* @access protected
+*/
+class XML_HTMLSax_Entities_Unparsed {
+    /**
+    * Original handler object
+    * @var object
+    * @access private
+    */
+    var $orig_obj;
+    /**
+    * Original handler method
+    * @var string
+    * @access private
+    */
+    var $orig_method;
+    /**
+    * Constructs XML_HTMLSax_Entities_Unparsed
+    * @param object handler object being decorated
+    * @param string original handler method
+    * @access protected
+    */
+    function XML_HTMLSax_Entities_Unparsed(&$orig_obj, $orig_method) {
+        $this->orig_obj =& $orig_obj;
+        $this->orig_method = $orig_method;
+    }
+    /**
+    * Breaks the data up by XML entities
+    * @param XML_HTMLSax
+    * @param string element data
+    * @access protected
+    */
+    function breakData(&$parser, $data) {
+        $data = preg_split('/(&.+?;)/',$data,-1,PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
+        foreach ( $data as $chunk ) {
+            $this->orig_obj->{$this->orig_method}($this, $chunk);
+        }
+    }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/XML/XML_HTMLSax/HTMLSax/XML_HTMLSax_States.php b/include/classes/XML/XML_HTMLSax/HTMLSax/XML_HTMLSax_States.php
new file mode 100644 (file)
index 0000000..35bb496
--- /dev/null
@@ -0,0 +1,292 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//
+// +----------------------------------------------------------------------+
+// | PHP Version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2002 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license,      |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/3_0.txt.                                  |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Alexander Zhukov <alex@veresk.ru> Original port from Python |
+// | Authors: Harry Fuecks <hfuecks@phppatterns.com> Port to PEAR + more  |
+// | Authors: Many @ Sitepointforums Advanced PHP Forums                  |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+//
+/**
+* Main parser components
+* @package XML_HTMLSax
+* @version $Id$
+*/
+/**
+* Define parser states
+*/
+define('XML_HTMLSAX_STATE_STOP', 0);
+define('XML_HTMLSAX_STATE_START', 1);
+define('XML_HTMLSAX_STATE_TAG', 2);
+define('XML_HTMLSAX_STATE_OPENING_TAG', 3);
+define('XML_HTMLSAX_STATE_CLOSING_TAG', 4);
+define('XML_HTMLSAX_STATE_ESCAPE', 6);
+define('XML_HTMLSAX_STATE_JASP', 7);
+define('XML_HTMLSAX_STATE_PI', 8);
+/**
+* StartingState searches for the start of any XML tag
+* @package XML_HTMLSax
+* @access protected
+*/
+class XML_HTMLSax_StartingState  {
+    /**
+    * @param XML_HTMLSax_StateParser subclass
+    * @return constant XML_HTMLSAX_STATE_TAG
+    * @access protected
+    */
+    function parse(&$context) {
+        $data = $context->scanUntilString('<');
+        if ($data != '') {
+            $context->handler_object_data->
+                {$context->handler_method_data}($context->htmlsax, $data);
+        }
+        $context->IgnoreCharacter();
+        return XML_HTMLSAX_STATE_TAG;
+    }
+}
+/**
+* Decides which state to move one from after StartingState
+* @package XML_HTMLSax
+* @access protected
+*/
+class XML_HTMLSax_TagState {
+    /**
+    * @param XML_HTMLSax_StateParser subclass
+    * @return constant the next state to move into
+    * @access protected
+    */
+    function parse(&$context) {
+        switch($context->ScanCharacter()) {
+        case '/':
+            return XML_HTMLSAX_STATE_CLOSING_TAG;
+            break;
+        case '?':
+            return XML_HTMLSAX_STATE_PI;
+            break;
+        case '%':
+            return XML_HTMLSAX_STATE_JASP;
+            break;
+        case '!':
+            return XML_HTMLSAX_STATE_ESCAPE;
+            break;
+        default:
+            $context->unscanCharacter();
+            return XML_HTMLSAX_STATE_OPENING_TAG;
+        }
+    }
+}
+/**
+* Dealing with closing XML tags
+* @package XML_HTMLSax
+* @access protected
+*/
+class XML_HTMLSax_ClosingTagState {
+    /**
+    * @param XML_HTMLSax_StateParser subclass
+    * @return constant XML_HTMLSAX_STATE_START
+    * @access protected
+    */
+    function parse(&$context) {
+        $tag = $context->scanUntilCharacters('/>');
+        if ($tag != '') {
+            $char = $context->scanCharacter();
+            if ($char == '/') {
+                $char = $context->scanCharacter();
+                if ($char != '>') {
+                    $context->unscanCharacter();
+                }
+            }
+            $context->handler_object_element->
+                {$context->handler_method_closing}($context->htmlsax, $tag, FALSE);
+        }
+        return XML_HTMLSAX_STATE_START;
+    }
+}
+/**
+* Dealing with opening XML tags
+* @package XML_HTMLSax
+* @access protected
+*/
+class XML_HTMLSax_OpeningTagState {
+    /**
+    * Handles attributes
+    * @param string attribute name
+    * @param string attribute value
+    * @return void
+    * @access protected
+    * @see XML_HTMLSax_AttributeStartState
+    */
+    function parseAttributes(&$context) {
+        $Attributes = array();
+    
+        $context->ignoreWhitespace();
+        $attributename = $context->scanUntilCharacters("=/> \n\r\t");
+        while ($attributename != '') {
+            $attributevalue = NULL;
+            $context->ignoreWhitespace();
+            $char = $context->scanCharacter();
+            if ($char == '=') {
+                $context->ignoreWhitespace();
+                $char = $context->ScanCharacter();
+                if ($char == '"') {
+                    $attributevalue= $context->scanUntilString('"');
+                    $context->IgnoreCharacter();
+                } else if ($char == "'") {
+                    $attributevalue = $context->scanUntilString("'");
+                    $context->IgnoreCharacter();
+                } else {
+                    $context->unscanCharacter();
+                    $attributevalue =
+                        $context->scanUntilCharacters("> \n\r\t");
+                }
+            } else if ($char !== NULL) {
+                $attributevalue = true;
+                $context->unscanCharacter();
+            }
+            $Attributes[$attributename] = $attributevalue;
+            
+            $context->ignoreWhitespace();
+            $attributename = $context->scanUntilCharacters("=/> \n\r\t");
+        }
+        return $Attributes;
+    }
+
+    /**
+    * @param XML_HTMLSax_StateParser subclass
+    * @return constant XML_HTMLSAX_STATE_START
+    * @access protected
+    */
+    function parse(&$context) {
+        $tag = $context->scanUntilCharacters("/> \n\r\t");
+        if ($tag != '') {
+            $this->attrs = array();
+            $Attributes = $this->parseAttributes($context);
+            $char = $context->scanCharacter();
+            if ($char == '/') {
+                $char = $context->scanCharacter();
+                if ($char != '>') {
+                    $context->unscanCharacter();
+                }
+                $context->handler_object_element->
+                    {$context->handler_method_opening}($context->htmlsax, $tag, 
+                    $Attributes, TRUE);
+                $context->handler_object_element->
+                    {$context->handler_method_closing}($context->htmlsax, $tag, 
+                    TRUE);
+            } else {
+                $context->handler_object_element->
+                    {$context->handler_method_opening}($context->htmlsax, $tag, 
+                    $Attributes, FALSE);
+            }
+        }
+        return XML_HTMLSAX_STATE_START;
+    }
+}
+
+/**
+* Deals with XML escapes handling comments and CDATA correctly
+* @package XML_HTMLSax
+* @access protected
+*/
+class XML_HTMLSax_EscapeState {
+    /**
+    * @param XML_HTMLSax_StateParser subclass
+    * @return constant XML_HTMLSAX_STATE_START
+    * @access protected
+    */
+    function parse(&$context) {
+        if ($context->parser_options['XML_OPTION_FULL_ESCAPES']==0) {
+            $char = $context->ScanCharacter();
+            if ($char == '-') {
+                $char = $context->ScanCharacter();
+                if ($char == '-') {
+                    $text = $context->scanUntilString('-->');
+                    $context->IgnoreCharacter();
+                    $context->IgnoreCharacter();
+                } else {
+                    $context->unscanCharacter();
+                    $text = $context->scanUntilString('>');
+                }
+            } else if ( $char == '[') {
+                $context->scanUntilString('CDATA[');
+                for ( $i=0;$i<6;$i++ ) {
+                    $context->IgnoreCharacter();
+                }
+                $text = $context->scanUntilString(']]>');
+                $context->IgnoreCharacter();
+                $context->IgnoreCharacter();
+            } else {
+                $context->unscanCharacter();
+                $text = $context->scanUntilString('>');
+            }
+        } else {
+            $text = $context->scanUntilString('>');
+        }
+        $context->IgnoreCharacter();
+        if ($text != '') {
+            $context->handler_object_escape->
+            {$context->handler_method_escape}($context->htmlsax, $text);
+        }
+        return XML_HTMLSAX_STATE_START;
+    }
+}
+/**
+* Deals with JASP/ASP markup
+* @package XML_HTMLSax
+* @access protected
+*/
+class XML_HTMLSax_JaspState {
+    /**
+    * @param XML_HTMLSax_StateParser subclass
+    * @return constant XML_HTMLSAX_STATE_START
+    * @access protected
+    */
+    function parse(&$context) {
+        $text = $context->scanUntilString('%>');
+        if ($text != '') {
+            $context->handler_object_jasp->
+                {$context->handler_method_jasp}($context->htmlsax, $text);
+        }
+        $context->IgnoreCharacter();
+        $context->IgnoreCharacter();
+        return XML_HTMLSAX_STATE_START;
+    }
+}
+/**
+* Deals with XML processing instructions
+* @package XML_HTMLSax
+* @access protected
+*/
+class XML_HTMLSax_PiState {
+    /**
+    * @param XML_HTMLSax_StateParser subclass
+    * @return constant XML_HTMLSAX_STATE_START
+    * @access protected
+    */
+    function parse(&$context) {
+        $target = $context->scanUntilCharacters(" \n\r\t");
+        $data = $context->scanUntilString('?>');
+        if ($data != '') {
+            $context->handler_object_pi->
+            {$context->handler_method_pi}($context->htmlsax, $target, $data);
+        }
+        $context->IgnoreCharacter();
+        $context->IgnoreCharacter();
+        return XML_HTMLSAX_STATE_START;
+    }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/XML/XML_HTMLSax/OS/Guess.php b/include/classes/XML/XML_HTMLSax/OS/Guess.php
new file mode 100644 (file)
index 0000000..d982def
--- /dev/null
@@ -0,0 +1,343 @@
+<?php\r
+/**\r
+ * The OS_Guess class\r
+ *\r
+ * PHP versions 4 and 5\r
+ *\r
+ * LICENSE: This source file is subject to version 3.0 of the PHP license\r
+ * that is available through the world-wide-web at the following URI:\r
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of\r
+ * the PHP License and are unable to obtain it through the web, please\r
+ * send a note to license@php.net so we can mail you a copy immediately.\r
+ *\r
+ * @category   pear\r
+ * @package    PEAR\r
+ * @author     Stig Bakken <ssb@php.net>\r
+ * @author     Gregory Beaver <cellog@php.net>\r
+ * @copyright  1997-2008 The PHP Group\r
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0\r
+ * @version    CVS: $Id$\r
+ * @link       http://pear.php.net/package/PEAR\r
+ * @since      File available since PEAR 0.1\r
+ */\r
+\r
+// {{{ uname examples\r
+\r
+// php_uname() without args returns the same as 'uname -a', or a PHP-custom\r
+// string for Windows.\r
+// PHP versions prior to 4.3 return the uname of the host where PHP was built,\r
+// as of 4.3 it returns the uname of the host running the PHP code.\r
+//\r
+// PC RedHat Linux 7.1:\r
+// Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown\r
+//\r
+// PC Debian Potato:\r
+// Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown\r
+//\r
+// PC FreeBSD 3.3:\r
+// FreeBSD host.example.com 3.3-STABLE FreeBSD 3.3-STABLE #0: Mon Feb 21 00:42:31 CET 2000     root@example.com:/usr/src/sys/compile/CONFIG  i386\r
+//\r
+// PC FreeBSD 4.3:\r
+// FreeBSD host.example.com 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Mon Jun 25 11:19:43 EDT 2001     root@example.com:/usr/src/sys/compile/CONFIG  i386\r
+//\r
+// PC FreeBSD 4.5:\r
+// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb  6 23:59:23 CET 2002     root@example.com:/usr/src/sys/compile/CONFIG  i386\r
+//\r
+// PC FreeBSD 4.5 w/uname from GNU shellutils:\r
+// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb  i386 unknown\r
+//\r
+// HP 9000/712 HP-UX 10:\r
+// HP-UX iq B.10.10 A 9000/712 2008429113 two-user license\r
+//\r
+// HP 9000/712 HP-UX 10 w/uname from GNU shellutils:\r
+// HP-UX host B.10.10 A 9000/712 unknown\r
+//\r
+// IBM RS6000/550 AIX 4.3:\r
+// AIX host 3 4 000003531C00\r
+//\r
+// AIX 4.3 w/uname from GNU shellutils:\r
+// AIX host 3 4 000003531C00 unknown\r
+//\r
+// SGI Onyx IRIX 6.5 w/uname from GNU shellutils:\r
+// IRIX64 host 6.5 01091820 IP19 mips\r
+//\r
+// SGI Onyx IRIX 6.5:\r
+// IRIX64 host 6.5 01091820 IP19\r
+//\r
+// SparcStation 20 Solaris 8 w/uname from GNU shellutils:\r
+// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc\r
+//\r
+// SparcStation 20 Solaris 8:\r
+// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20\r
+//\r
+// Mac OS X (Darwin)\r
+// Darwin home-eden.local 7.5.0 Darwin Kernel Version 7.5.0: Thu Aug  5 19:26:16 PDT 2004; root:xnu/xnu-517.7.21.obj~3/RELEASE_PPC  Power Macintosh\r
+//\r
+// Mac OS X early versions\r
+// \r
+\r
+// }}}\r
+\r
+/* TODO:\r
+ * - define endianness, to allow matchSignature("bigend") etc.\r
+ */\r
+\r
+/**\r
+ * Retrieves information about the current operating system\r
+ *\r
+ * This class uses php_uname() to grok information about the current OS\r
+ *\r
+ * @category   pear\r
+ * @package    PEAR\r
+ * @author     Stig Bakken <ssb@php.net>\r
+ * @author     Gregory Beaver <cellog@php.net>\r
+ * @copyright  1997-2008 The PHP Group\r
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0\r
+ * @version    Release: 1.4.4\r
+ * @link       http://pear.php.net/package/PEAR\r
+ * @since      Class available since Release 0.1\r
+ */\r
+class OS_Guess\r
+{\r
+    var $sysname;\r
+    var $nodename;\r
+    var $cpu;\r
+    var $release;\r
+    var $extra;\r
+\r
+    function OS_Guess($uname = null)\r
+    {\r
+        list($this->sysname,\r
+             $this->release,\r
+             $this->cpu,\r
+             $this->extra,\r
+             $this->nodename) = $this->parseSignature($uname);\r
+    }\r
+\r
+    function parseSignature($uname = null)\r
+    {\r
+        static $sysmap = array(\r
+            'HP-UX' => 'hpux',\r
+            'IRIX64' => 'irix',\r
+        );\r
+        static $cpumap = array(\r
+            'i586' => 'i386',\r
+            'i686' => 'i386',\r
+            'ppc' => 'powerpc',\r
+        );\r
+        if ($uname === null) {\r
+            $uname = php_uname();\r
+        }\r
+        $parts = split('[[:space:]]+', trim($uname));\r
+        $n = count($parts);\r
+\r
+        $release = $machine = $cpu = '';\r
+        $sysname = $parts[0];\r
+        $nodename = $parts[1];\r
+        $cpu = $parts[$n-1];\r
+        $extra = '';\r
+        if ($cpu == 'unknown') {\r
+            $cpu = $parts[$n-2];\r
+        }\r
+\r
+        switch ($sysname) {\r
+            case 'AIX' :\r
+                $release = "$parts[3].$parts[2]";\r
+                break;\r
+            case 'Windows' :\r
+                switch ($parts[1]) {\r
+                    case '95/98':\r
+                        $release = '9x';\r
+                        break;\r
+                    default:\r
+                        $release = $parts[1];\r
+                        break;\r
+                }\r
+                $cpu = 'i386';\r
+                break;\r
+            case 'Linux' :\r
+                $extra = $this->_detectGlibcVersion();\r
+                // use only the first two digits from the kernel version\r
+                $release = ereg_replace('^([[:digit:]]+\.[[:digit:]]+).*', '\1', $parts[2]);\r
+                break;\r
+            case 'Mac' :\r
+                $sysname = 'darwin';\r
+                $nodename = $parts[2];\r
+                $release = $parts[3];\r
+                if ($cpu == 'Macintosh') {\r
+                    if ($parts[$n - 2] == 'Power') {\r
+                        $cpu = 'powerpc';\r
+                    }\r
+                }\r
+                break;\r
+            case 'Darwin' :\r
+                if ($cpu == 'Macintosh') {\r
+                    if ($parts[$n - 2] == 'Power') {\r
+                        $cpu = 'powerpc';\r
+                    }\r
+                }\r
+                $release = ereg_replace('^([[:digit:]]+\.[[:digit:]]+).*', '\1', $parts[2]);\r
+                break;\r
+            default:\r
+                $release = ereg_replace('-.*', '', $parts[2]);\r
+                break;\r
+        }\r
+\r
+\r
+        if (isset($sysmap[$sysname])) {\r
+            $sysname = $sysmap[$sysname];\r
+        } else {\r
+            $sysname = strtolower($sysname);\r
+        }\r
+        if (isset($cpumap[$cpu])) {\r
+            $cpu = $cpumap[$cpu];\r
+        }\r
+        return array($sysname, $release, $cpu, $extra, $nodename);\r
+    }\r
+\r
+    function _detectGlibcVersion()\r
+    {\r
+        static $glibc = false;\r
+        if ($glibc !== false) {\r
+            return $glibc; // no need to run this multiple times\r
+        }\r
+        include_once "System.php";\r
+        if (!file_exists('/usr/bin/cpp') || !is_executable('/usr/bin/cpp')) {\r
+            // Use glibc's <features.h> header file to\r
+            // get major and minor version number:\r
+            if ($features_file = @fopen('/usr/include/features.h', 'rb') ) {\r
+                while (!feof($features_file)) {\r
+                    $line = fgets($features_file, 8192);\r
+                    if (!$line || (strpos($line, '#define') === false)) {\r
+                        continue;\r
+                    }\r
+                    if (strpos($line, '__GLIBC__')) {\r
+                        // major version number #define __GLIBC__ version\r
+                        $line = preg_split('/\s+/', $line);\r
+                        $glibc_major = trim($line[2]);\r
+                        if (isset($glibc_minor)) {\r
+                            break;\r
+                        }\r
+                        continue;\r
+                    }\r
+                    if (strpos($line, '__GLIBC_MINOR__'))  {\r
+                        // got the minor version number\r
+                        // #define __GLIBC_MINOR__ version\r
+                        $line = preg_split('/\s+/', $line);\r
+                        $glibc_minor = trim($line[2]);\r
+                        if (isset($glibc_major)) {\r
+                            break;\r
+                        }\r
+                        continue;\r
+                    }\r
+                }\r
+                fclose($features_file);\r
+                if (!isset($glibc_major) || !isset($glibc_minor)) {\r
+                    return $glibc = '';\r
+                }\r
+                return $glibc = 'glibc' . trim($glibc_major) . "." . trim($glibc_minor) ;\r
+            }\r
+            return $glibc = '';\r
+        }\r
+        $tmpfile = System::mktemp("glibctest");\r
+        $fp = fopen($tmpfile, "w");\r
+        fwrite($fp, "#include <features.h>\n__GLIBC__ __GLIBC_MINOR__\n");\r
+        fclose($fp);\r
+        $cpp = popen("/usr/bin/cpp $tmpfile", "r");\r
+        $major = $minor = 0;\r
+        while ($line = fgets($cpp, 1024)) {\r
+            if ($line{0} == '#' || trim($line) == '') {\r
+                continue;\r
+            }\r
+            if (list($major, $minor) = explode(' ', trim($line))) {\r
+                break;\r
+            }\r
+        }\r
+        pclose($cpp);\r
+        unlink($tmpfile);\r
+        if (!($major && $minor) && is_link('/lib/libc.so.6')) {\r
+            // Let's try reading the libc.so.6 symlink\r
+            if (ereg('^libc-([.*])\.so$', basename(readlink('/lib/libc.so.6')), $matches)) {\r
+                list($major, $minor) = explode('.', $matches);\r
+            }\r
+        }\r
+        if (!($major && $minor)) {\r
+            return $glibc = '';\r
+        }\r
+        return $glibc = "glibc{$major}.{$minor}";\r
+    }\r
+\r
+    function getSignature()\r
+    {\r
+        if (empty($this->extra)) {\r
+            return "{$this->sysname}-{$this->release}-{$this->cpu}";\r
+        }\r
+        return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}";\r
+    }\r
+\r
+    function getSysname()\r
+    {\r
+        return $this->sysname;\r
+    }\r
+\r
+    function getNodename()\r
+    {\r
+        return $this->nodename;\r
+    }\r
+\r
+    function getCpu()\r
+    {\r
+        return $this->cpu;\r
+    }\r
+\r
+    function getRelease()\r
+    {\r
+        return $this->release;\r
+    }\r
+\r
+    function getExtra()\r
+    {\r
+        return $this->extra;\r
+    }\r
+\r
+    function matchSignature($match)\r
+    {\r
+        if (is_array($match)) {\r
+            $fragments = $match;\r
+        } else {\r
+            $fragments = explode('-', $match);\r
+        }\r
+        $n = count($fragments);\r
+        $matches = 0;\r
+        if ($n > 0) {\r
+            $matches += $this->_matchFragment($fragments[0], $this->sysname);\r
+        }\r
+        if ($n > 1) {\r
+            $matches += $this->_matchFragment($fragments[1], $this->release);\r
+        }\r
+        if ($n > 2) {\r
+            $matches += $this->_matchFragment($fragments[2], $this->cpu);\r
+        }\r
+        if ($n > 3) {\r
+            $matches += $this->_matchFragment($fragments[3], $this->extra);\r
+        }\r
+        return ($matches == $n);\r
+    }\r
+\r
+    function _matchFragment($fragment, $value)\r
+    {\r
+        if (strcspn($fragment, '*?') < strlen($fragment)) {\r
+            $reg = '^' . str_replace(array('*', '?', '/'), array('.*', '.', '\\/'), $fragment) . '$';\r
+            return eregi($reg, $value);\r
+        }\r
+        return ($fragment == '*' || !strcasecmp($fragment, $value));\r
+    }\r
+\r
+}\r
+/*\r
+ * Local Variables:\r
+ * indent-tabs-mode: nil\r
+ * c-basic-offset: 4\r
+ * End:\r
+ */\r
+?>\r
diff --git a/include/classes/XML/XML_HTMLSax/PEAR.php b/include/classes/XML/XML_HTMLSax/PEAR.php
new file mode 100644 (file)
index 0000000..ffc9665
--- /dev/null
@@ -0,0 +1,1095 @@
+<?php\r
+/**\r
+ * PEAR, the PHP Extension and Application Repository\r
+ *\r
+ * PEAR class and PEAR_Error class\r
+ *\r
+ * PHP versions 4 and 5\r
+ *\r
+ * LICENSE: This source file is subject to version 3.0 of the PHP license\r
+ * that is available through the world-wide-web at the following URI:\r
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of\r
+ * the PHP License and are unable to obtain it through the web, please\r
+ * send a note to license@php.net so we can mail you a copy immediately.\r
+ *\r
+ * @category   pear\r
+ * @package    PEAR\r
+ * @author     Sterling Hughes <sterling@php.net>\r
+ * @author     Stig Bakken <ssb@php.net>\r
+ * @author     Tomas V.V.Cox <cox@idecnet.com>\r
+ * @author     Greg Beaver <cellog@php.net>\r
+ * @copyright  1997-2008 The PHP Group\r
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0\r
+ * @version    CVS: $Id$\r
+ * @link       http://pear.php.net/package/PEAR\r
+ * @since      File available since Release 0.1\r
+ */\r
+\r
+/**#@+\r
+ * ERROR constants\r
+ */\r
+define('PEAR_ERROR_RETURN',     1);\r
+define('PEAR_ERROR_PRINT',      2);\r
+define('PEAR_ERROR_TRIGGER',    4);\r
+define('PEAR_ERROR_DIE',        8);\r
+define('PEAR_ERROR_CALLBACK',  16);\r
+/**\r
+ * WARNING: obsolete\r
+ * @deprecated\r
+ */\r
+define('PEAR_ERROR_EXCEPTION', 32);\r
+/**#@-*/\r
+define('PEAR_ZE2', (function_exists('version_compare') &&\r
+                    version_compare(zend_version(), "2-dev", "ge")));\r
+\r
+if (substr(PHP_OS, 0, 3) == 'WIN') {\r
+    define('OS_WINDOWS', true);\r
+    define('OS_UNIX',    false);\r
+    define('PEAR_OS',    'Windows');\r
+} else {\r
+    define('OS_WINDOWS', false);\r
+    define('OS_UNIX',    true);\r
+    define('PEAR_OS',    'Unix'); // blatant assumption\r
+}\r
+\r
+// instant backwards compatibility\r
+if (!defined('PATH_SEPARATOR')) {\r
+    if (OS_WINDOWS) {\r
+        define('PATH_SEPARATOR', ';');\r
+    } else {\r
+        define('PATH_SEPARATOR', ':');\r
+    }\r
+}\r
+\r
+$GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;\r
+$GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;\r
+$GLOBALS['_PEAR_destructor_object_list'] = array();\r
+$GLOBALS['_PEAR_shutdown_funcs']         = array();\r
+$GLOBALS['_PEAR_error_handler_stack']    = array();\r
+\r
+@ini_set('track_errors', true);\r
+\r
+/**\r
+ * Base class for other PEAR classes.  Provides rudimentary\r
+ * emulation of destructors.\r
+ *\r
+ * If you want a destructor in your class, inherit PEAR and make a\r
+ * destructor method called _yourclassname (same name as the\r
+ * constructor, but with a "_" prefix).  Also, in your constructor you\r
+ * have to call the PEAR constructor: $this->PEAR();.\r
+ * The destructor method will be called without parameters.  Note that\r
+ * at in some SAPI implementations (such as Apache), any output during\r
+ * the request shutdown (in which destructors are called) seems to be\r
+ * discarded.  If you need to get any debug information from your\r
+ * destructor, use error_log(), syslog() or something similar.\r
+ *\r
+ * IMPORTANT! To use the emulated destructors you need to create the\r
+ * objects by reference: $obj =& new PEAR_child;\r
+ *\r
+ * @category   pear\r
+ * @package    PEAR\r
+ * @author     Stig Bakken <ssb@php.net>\r
+ * @author     Tomas V.V. Cox <cox@idecnet.com>\r
+ * @author     Greg Beaver <cellog@php.net>\r
+ * @copyright  1997-2008 The PHP Group\r
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0\r
+ * @version    Release: 1.4.4\r
+ * @link       http://pear.php.net/package/PEAR\r
+ * @see        PEAR_Error\r
+ * @since      Class available since PHP 4.0.2\r
+ * @link        http://pear.php.net/manual/en/core.pear.php#core.pear.pear\r
+ */\r
+class PEAR\r
+{\r
+    // {{{ properties\r
+\r
+    /**\r
+     * Whether to enable internal debug messages.\r
+     *\r
+     * @var     bool\r
+     * @access  private\r
+     */\r
+    var $_debug = false;\r
+\r
+    /**\r
+     * Default error mode for this object.\r
+     *\r
+     * @var     int\r
+     * @access  private\r
+     */\r
+    var $_default_error_mode = null;\r
+\r
+    /**\r
+     * Default error options used for this object when error mode\r
+     * is PEAR_ERROR_TRIGGER.\r
+     *\r
+     * @var     int\r
+     * @access  private\r
+     */\r
+    var $_default_error_options = null;\r
+\r
+    /**\r
+     * Default error handler (callback) for this object, if error mode is\r
+     * PEAR_ERROR_CALLBACK.\r
+     *\r
+     * @var     string\r
+     * @access  private\r
+     */\r
+    var $_default_error_handler = '';\r
+\r
+    /**\r
+     * Which class to use for error objects.\r
+     *\r
+     * @var     string\r
+     * @access  private\r
+     */\r
+    var $_error_class = 'PEAR_Error';\r
+\r
+    /**\r
+     * An array of expected errors.\r
+     *\r
+     * @var     array\r
+     * @access  private\r
+     */\r
+    var $_expected_errors = array();\r
+\r
+    // }}}\r
+\r
+    // {{{ constructor\r
+\r
+    /**\r
+     * Constructor.  Registers this object in\r
+     * $_PEAR_destructor_object_list for destructor emulation if a\r
+     * destructor object exists.\r
+     *\r
+     * @param string $error_class  (optional) which class to use for\r
+     *        error objects, defaults to PEAR_Error.\r
+     * @access public\r
+     * @return void\r
+     */\r
+    function PEAR($error_class = null)\r
+    {\r
+        $classname = strtolower(get_class($this));\r
+        if ($this->_debug) {\r
+            print "PEAR constructor called, class=$classname\n";\r
+        }\r
+        if ($error_class !== null) {\r
+            $this->_error_class = $error_class;\r
+        }\r
+        while ($classname && strcasecmp($classname, "pear")) {\r
+            $destructor = "_$classname";\r
+            if (method_exists($this, $destructor)) {\r
+                global $_PEAR_destructor_object_list;\r
+                $_PEAR_destructor_object_list[] = &$this;\r
+                if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {\r
+                    register_shutdown_function("_PEAR_call_destructors");\r
+                    $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;\r
+                }\r
+                break;\r
+            } else {\r
+                $classname = get_parent_class($classname);\r
+            }\r
+        }\r
+    }\r
+\r
+    // }}}\r
+    // {{{ destructor\r
+\r
+    /**\r
+     * Destructor (the emulated type of...).  Does nothing right now,\r
+     * but is included for forward compatibility, so subclass\r
+     * destructors should always call it.\r
+     *\r
+     * See the note in the class desciption about output from\r
+     * destructors.\r
+     *\r
+     * @access public\r
+     * @return void\r
+     */\r
+    function _PEAR() {\r
+        if ($this->_debug) {\r
+            printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));\r
+        }\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getStaticProperty()\r
+\r
+    /**\r
+    * If you have a class that's mostly/entirely static, and you need static\r
+    * properties, you can use this method to simulate them. Eg. in your method(s)\r
+    * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');\r
+    * You MUST use a reference, or they will not persist!\r
+    *\r
+    * @access public\r
+    * @param  string $class  The calling classname, to prevent clashes\r
+    * @param  string $var    The variable to retrieve.\r
+    * @return mixed   A reference to the variable. If not set it will be\r
+    *                 auto initialised to NULL.\r
+    */\r
+    function &getStaticProperty($class, $var)\r
+    {\r
+        static $properties;\r
+        return $properties[$class][$var];\r
+    }\r
+\r
+    // }}}\r
+    // {{{ registerShutdownFunc()\r
+\r
+    /**\r
+    * Use this function to register a shutdown method for static\r
+    * classes.\r
+    *\r
+    * @access public\r
+    * @param  mixed $func  The function name (or array of class/method) to call\r
+    * @param  mixed $args  The arguments to pass to the function\r
+    * @return void\r
+    */\r
+    function registerShutdownFunc($func, $args = array())\r
+    {\r
+        $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);\r
+    }\r
+\r
+    // }}}\r
+    // {{{ isError()\r
+\r
+    /**\r
+     * Tell whether a value is a PEAR error.\r
+     *\r
+     * @param   mixed $data   the value to test\r
+     * @param   int   $code   if $data is an error object, return true\r
+     *                        only if $code is a string and\r
+     *                        $obj->getMessage() == $code or\r
+     *                        $code is an integer and $obj->getCode() == $code\r
+     * @access  public\r
+     * @return  bool    true if parameter is an error\r
+     */\r
+    function isError($data, $code = null)\r
+    {\r
+        if (is_a($data, 'PEAR_Error')) {\r
+            if (is_null($code)) {\r
+                return true;\r
+            } elseif (is_string($code)) {\r
+                return $data->getMessage() == $code;\r
+            } else {\r
+                return $data->getCode() == $code;\r
+            }\r
+        }\r
+        return false;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ setErrorHandling()\r
+\r
+    /**\r
+     * Sets how errors generated by this object should be handled.\r
+     * Can be invoked both in objects and statically.  If called\r
+     * statically, setErrorHandling sets the default behaviour for all\r
+     * PEAR objects.  If called in an object, setErrorHandling sets\r
+     * the default behaviour for that object.\r
+     *\r
+     * @param int $mode\r
+     *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,\r
+     *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,\r
+     *        PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.\r
+     *\r
+     * @param mixed $options\r
+     *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one\r
+     *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).\r
+     *\r
+     *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected\r
+     *        to be the callback function or method.  A callback\r
+     *        function is a string with the name of the function, a\r
+     *        callback method is an array of two elements: the element\r
+     *        at index 0 is the object, and the element at index 1 is\r
+     *        the name of the method to call in the object.\r
+     *\r
+     *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is\r
+     *        a printf format string used when printing the error\r
+     *        message.\r
+     *\r
+     * @access public\r
+     * @return void\r
+     * @see PEAR_ERROR_RETURN\r
+     * @see PEAR_ERROR_PRINT\r
+     * @see PEAR_ERROR_TRIGGER\r
+     * @see PEAR_ERROR_DIE\r
+     * @see PEAR_ERROR_CALLBACK\r
+     * @see PEAR_ERROR_EXCEPTION\r
+     *\r
+     * @since PHP 4.0.5\r
+     */\r
+\r
+    function setErrorHandling($mode = null, $options = null)\r
+    {\r
+        if (isset($this) && is_a($this, 'PEAR')) {\r
+            $setmode     = &$this->_default_error_mode;\r
+            $setoptions  = &$this->_default_error_options;\r
+        } else {\r
+            $setmode     = &$GLOBALS['_PEAR_default_error_mode'];\r
+            $setoptions  = &$GLOBALS['_PEAR_default_error_options'];\r
+        }\r
+\r
+        switch ($mode) {\r
+            case PEAR_ERROR_EXCEPTION:\r
+            case PEAR_ERROR_RETURN:\r
+            case PEAR_ERROR_PRINT:\r
+            case PEAR_ERROR_TRIGGER:\r
+            case PEAR_ERROR_DIE:\r
+            case null:\r
+                $setmode = $mode;\r
+                $setoptions = $options;\r
+                break;\r
+\r
+            case PEAR_ERROR_CALLBACK:\r
+                $setmode = $mode;\r
+                // class/object method callback\r
+                if (is_callable($options)) {\r
+                    $setoptions = $options;\r
+                } else {\r
+                    trigger_error("invalid error callback", E_USER_WARNING);\r
+                }\r
+                break;\r
+\r
+            default:\r
+                trigger_error("invalid error mode", E_USER_WARNING);\r
+                break;\r
+        }\r
+    }\r
+\r
+    // }}}\r
+    // {{{ expectError()\r
+\r
+    /**\r
+     * This method is used to tell which errors you expect to get.\r
+     * Expected errors are always returned with error mode\r
+     * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,\r
+     * and this method pushes a new element onto it.  The list of\r
+     * expected errors are in effect until they are popped off the\r
+     * stack with the popExpect() method.\r
+     *\r
+     * Note that this method can not be called statically\r
+     *\r
+     * @param mixed $code a single error code or an array of error codes to expect\r
+     *\r
+     * @return int     the new depth of the "expected errors" stack\r
+     * @access public\r
+     */\r
+    function expectError($code = '*')\r
+    {\r
+        if (is_array($code)) {\r
+            array_push($this->_expected_errors, $code);\r
+        } else {\r
+            array_push($this->_expected_errors, array($code));\r
+        }\r
+        return sizeof($this->_expected_errors);\r
+    }\r
+\r
+    // }}}\r
+    // {{{ popExpect()\r
+\r
+    /**\r
+     * This method pops one element off the expected error codes\r
+     * stack.\r
+     *\r
+     * @return array   the list of error codes that were popped\r
+     */\r
+    function popExpect()\r
+    {\r
+        return array_pop($this->_expected_errors);\r
+    }\r
+\r
+    // }}}\r
+    // {{{ _checkDelExpect()\r
+\r
+    /**\r
+     * This method checks unsets an error code if available\r
+     *\r
+     * @param mixed error code\r
+     * @return bool true if the error code was unset, false otherwise\r
+     * @access private\r
+     * @since PHP 4.3.0\r
+     */\r
+    function _checkDelExpect($error_code)\r
+    {\r
+        $deleted = false;\r
+\r
+        foreach ($this->_expected_errors AS $key => $error_array) {\r
+            if (in_array($error_code, $error_array)) {\r
+                unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);\r
+                $deleted = true;\r
+            }\r
+\r
+            // clean up empty arrays\r
+            if (0 == count($this->_expected_errors[$key])) {\r
+                unset($this->_expected_errors[$key]);\r
+            }\r
+        }\r
+        return $deleted;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ delExpect()\r
+\r
+    /**\r
+     * This method deletes all occurences of the specified element from\r
+     * the expected error codes stack.\r
+     *\r
+     * @param  mixed $error_code error code that should be deleted\r
+     * @return mixed list of error codes that were deleted or error\r
+     * @access public\r
+     * @since PHP 4.3.0\r
+     */\r
+    function delExpect($error_code)\r
+    {\r
+        $deleted = false;\r
+\r
+        if ((is_array($error_code) && (0 != count($error_code)))) {\r
+            // $error_code is a non-empty array here;\r
+            // we walk through it trying to unset all\r
+            // values\r
+            foreach($error_code as $key => $error) {\r
+                if ($this->_checkDelExpect($error)) {\r
+                    $deleted =  true;\r
+                } else {\r
+                    $deleted = false;\r
+                }\r
+            }\r
+            return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME\r
+        } elseif (!empty($error_code)) {\r
+            // $error_code comes alone, trying to unset it\r
+            if ($this->_checkDelExpect($error_code)) {\r
+                return true;\r
+            } else {\r
+                return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME\r
+            }\r
+        } else {\r
+            // $error_code is empty\r
+            return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME\r
+        }\r
+    }\r
+\r
+    // }}}\r
+    // {{{ raiseError()\r
+\r
+    /**\r
+     * This method is a wrapper that returns an instance of the\r
+     * configured error class with this object's default error\r
+     * handling applied.  If the $mode and $options parameters are not\r
+     * specified, the object's defaults are used.\r
+     *\r
+     * @param mixed $message a text error message or a PEAR error object\r
+     *\r
+     * @param int $code      a numeric error code (it is up to your class\r
+     *                  to define these if you want to use codes)\r
+     *\r
+     * @param int $mode      One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,\r
+     *                  PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,\r
+     *                  PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.\r
+     *\r
+     * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter\r
+     *                  specifies the PHP-internal error level (one of\r
+     *                  E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).\r
+     *                  If $mode is PEAR_ERROR_CALLBACK, this\r
+     *                  parameter specifies the callback function or\r
+     *                  method.  In other error modes this parameter\r
+     *                  is ignored.\r
+     *\r
+     * @param string $userinfo If you need to pass along for example debug\r
+     *                  information, this parameter is meant for that.\r
+     *\r
+     * @param string $error_class The returned error object will be\r
+     *                  instantiated from this class, if specified.\r
+     *\r
+     * @param bool $skipmsg If true, raiseError will only pass error codes,\r
+     *                  the error message parameter will be dropped.\r
+     *\r
+     * @access public\r
+     * @return object   a PEAR error object\r
+     * @see PEAR::setErrorHandling\r
+     * @since PHP 4.0.5\r
+     */\r
+    function &raiseError($message = null,\r
+                         $code = null,\r
+                         $mode = null,\r
+                         $options = null,\r
+                         $userinfo = null,\r
+                         $error_class = null,\r
+                         $skipmsg = false)\r
+    {\r
+        // The error is yet a PEAR error object\r
+        if (is_object($message)) {\r
+            $code        = $message->getCode();\r
+            $userinfo    = $message->getUserInfo();\r
+            $error_class = $message->getType();\r
+            $message->error_message_prefix = '';\r
+            $message     = $message->getMessage();\r
+        }\r
+\r
+        if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) {\r
+            if ($exp[0] == "*" ||\r
+                (is_int(reset($exp)) && in_array($code, $exp)) ||\r
+                (is_string(reset($exp)) && in_array($message, $exp))) {\r
+                $mode = PEAR_ERROR_RETURN;\r
+            }\r
+        }\r
+        // No mode given, try global ones\r
+        if ($mode === null) {\r
+            // Class error handler\r
+            if (isset($this) && isset($this->_default_error_mode)) {\r
+                $mode    = $this->_default_error_mode;\r
+                $options = $this->_default_error_options;\r
+            // Global error handler\r
+            } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {\r
+                $mode    = $GLOBALS['_PEAR_default_error_mode'];\r
+                $options = $GLOBALS['_PEAR_default_error_options'];\r
+            }\r
+        }\r
+\r
+        if ($error_class !== null) {\r
+            $ec = $error_class;\r
+        } elseif (isset($this) && isset($this->_error_class)) {\r
+            $ec = $this->_error_class;\r
+        } else {\r
+            $ec = 'PEAR_Error';\r
+        }\r
+        if ($skipmsg) {\r
+            $a = &new $ec($code, $mode, $options, $userinfo);\r
+            return $a;\r
+        } else {\r
+            $a = &new $ec($message, $code, $mode, $options, $userinfo);\r
+            return $a;\r
+        }\r
+    }\r
+\r
+    // }}}\r
+    // {{{ throwError()\r
+\r
+    /**\r
+     * Simpler form of raiseError with fewer options.  In most cases\r
+     * message, code and userinfo are enough.\r
+     *\r
+     * @param string $message\r
+     *\r
+     */\r
+    function &throwError($message = null,\r
+                         $code = null,\r
+                         $userinfo = null)\r
+    {\r
+        if (isset($this) && is_a($this, 'PEAR')) {\r
+            $a = &$this->raiseError($message, $code, null, null, $userinfo);\r
+            return $a;\r
+        } else {\r
+            $a = &PEAR::raiseError($message, $code, null, null, $userinfo);\r
+            return $a;\r
+        }\r
+    }\r
+\r
+    // }}}\r
+    function staticPushErrorHandling($mode, $options = null)\r
+    {\r
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];\r
+        $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];\r
+        $def_options = &$GLOBALS['_PEAR_default_error_options'];\r
+        $stack[] = array($def_mode, $def_options);\r
+        switch ($mode) {\r
+            case PEAR_ERROR_EXCEPTION:\r
+            case PEAR_ERROR_RETURN:\r
+            case PEAR_ERROR_PRINT:\r
+            case PEAR_ERROR_TRIGGER:\r
+            case PEAR_ERROR_DIE:\r
+            case null:\r
+                $def_mode = $mode;\r
+                $def_options = $options;\r
+                break;\r
+\r
+            case PEAR_ERROR_CALLBACK:\r
+                $def_mode = $mode;\r
+                // class/object method callback\r
+                if (is_callable($options)) {\r
+                    $def_options = $options;\r
+                } else {\r
+                    trigger_error("invalid error callback", E_USER_WARNING);\r
+                }\r
+                break;\r
+\r
+            default:\r
+                trigger_error("invalid error mode", E_USER_WARNING);\r
+                break;\r
+        }\r
+        $stack[] = array($mode, $options);\r
+        return true;\r
+    }\r
+\r
+    function staticPopErrorHandling()\r
+    {\r
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];\r
+        $setmode     = &$GLOBALS['_PEAR_default_error_mode'];\r
+        $setoptions  = &$GLOBALS['_PEAR_default_error_options'];\r
+        array_pop($stack);\r
+        list($mode, $options) = $stack[sizeof($stack) - 1];\r
+        array_pop($stack);\r
+        switch ($mode) {\r
+            case PEAR_ERROR_EXCEPTION:\r
+            case PEAR_ERROR_RETURN:\r
+            case PEAR_ERROR_PRINT:\r
+            case PEAR_ERROR_TRIGGER:\r
+            case PEAR_ERROR_DIE:\r
+            case null:\r
+                $setmode = $mode;\r
+                $setoptions = $options;\r
+                break;\r
+\r
+            case PEAR_ERROR_CALLBACK:\r
+                $setmode = $mode;\r
+                // class/object method callback\r
+                if (is_callable($options)) {\r
+                    $setoptions = $options;\r
+                } else {\r
+                    trigger_error("invalid error callback", E_USER_WARNING);\r
+                }\r
+                break;\r
+\r
+            default:\r
+                trigger_error("invalid error mode", E_USER_WARNING);\r
+                break;\r
+        }\r
+        return true;\r
+    }\r
+\r
+    // {{{ pushErrorHandling()\r
+\r
+    /**\r
+     * Push a new error handler on top of the error handler options stack. With this\r
+     * you can easily override the actual error handler for some code and restore\r
+     * it later with popErrorHandling.\r
+     *\r
+     * @param mixed $mode (same as setErrorHandling)\r
+     * @param mixed $options (same as setErrorHandling)\r
+     *\r
+     * @return bool Always true\r
+     *\r
+     * @see PEAR::setErrorHandling\r
+     */\r
+    function pushErrorHandling($mode, $options = null)\r
+    {\r
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];\r
+        if (isset($this) && is_a($this, 'PEAR')) {\r
+            $def_mode    = &$this->_default_error_mode;\r
+            $def_options = &$this->_default_error_options;\r
+        } else {\r
+            $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];\r
+            $def_options = &$GLOBALS['_PEAR_default_error_options'];\r
+        }\r
+        $stack[] = array($def_mode, $def_options);\r
+\r
+        if (isset($this) && is_a($this, 'PEAR')) {\r
+            $this->setErrorHandling($mode, $options);\r
+        } else {\r
+            PEAR::setErrorHandling($mode, $options);\r
+        }\r
+        $stack[] = array($mode, $options);\r
+        return true;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ popErrorHandling()\r
+\r
+    /**\r
+    * Pop the last error handler used\r
+    *\r
+    * @return bool Always true\r
+    *\r
+    * @see PEAR::pushErrorHandling\r
+    */\r
+    function popErrorHandling()\r
+    {\r
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];\r
+        array_pop($stack);\r
+        list($mode, $options) = $stack[sizeof($stack) - 1];\r
+        array_pop($stack);\r
+        if (isset($this) && is_a($this, 'PEAR')) {\r
+            $this->setErrorHandling($mode, $options);\r
+        } else {\r
+            PEAR::setErrorHandling($mode, $options);\r
+        }\r
+        return true;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ loadExtension()\r
+\r
+    /**\r
+    * OS independant PHP extension load. Remember to take care\r
+    * on the correct extension name for case sensitive OSes.\r
+    *\r
+    * @param string $ext The extension name\r
+    * @return bool Success or not on the dl() call\r
+    */\r
+    function loadExtension($ext)\r
+    {\r
+        if (!extension_loaded($ext)) {\r
+            // if either returns true dl() will produce a FATAL error, stop that\r
+            if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) {\r
+                return false;\r
+            }\r
+            if (OS_WINDOWS) {\r
+                $suffix = '.dll';\r
+            } elseif (PHP_OS == 'HP-UX') {\r
+                $suffix = '.sl';\r
+            } elseif (PHP_OS == 'AIX') {\r
+                $suffix = '.a';\r
+            } elseif (PHP_OS == 'OSX') {\r
+                $suffix = '.bundle';\r
+            } else {\r
+                $suffix = '.so';\r
+            }\r
+            return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);\r
+        }\r
+        return true;\r
+    }\r
+\r
+    // }}}\r
+}\r
+\r
+// {{{ _PEAR_call_destructors()\r
+\r
+function _PEAR_call_destructors()\r
+{\r
+    global $_PEAR_destructor_object_list;\r
+    if (is_array($_PEAR_destructor_object_list) &&\r
+        sizeof($_PEAR_destructor_object_list))\r
+    {\r
+        reset($_PEAR_destructor_object_list);\r
+        if (@PEAR::getStaticProperty('PEAR', 'destructlifo')) {\r
+            $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);\r
+        }\r
+        while (list($k, $objref) = each($_PEAR_destructor_object_list)) {\r
+            $classname = get_class($objref);\r
+            while ($classname) {\r
+                $destructor = "_$classname";\r
+                if (method_exists($objref, $destructor)) {\r
+                    $objref->$destructor();\r
+                    break;\r
+                } else {\r
+                    $classname = get_parent_class($classname);\r
+                }\r
+            }\r
+        }\r
+        // Empty the object list to ensure that destructors are\r
+        // not called more than once.\r
+        $_PEAR_destructor_object_list = array();\r
+    }\r
+\r
+    // Now call the shutdown functions\r
+    if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) {\r
+        foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {\r
+            call_user_func_array($value[0], $value[1]);\r
+        }\r
+    }\r
+}\r
+\r
+// }}}\r
+/**\r
+ * Standard PEAR error class for PHP 4\r
+ *\r
+ * This class is supserseded by {@link PEAR_Exception} in PHP 5\r
+ *\r
+ * @category   pear\r
+ * @package    PEAR\r
+ * @author     Stig Bakken <ssb@php.net>\r
+ * @author     Tomas V.V. Cox <cox@idecnet.com>\r
+ * @author     Gregory Beaver <cellog@php.net>\r
+ * @copyright  1997-2008 The PHP Group\r
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0\r
+ * @version    Release: 1.4.4\r
+ * @link       http://pear.php.net/manual/en/core.pear.pear-error.php\r
+ * @see        PEAR::raiseError(), PEAR::throwError()\r
+ * @since      Class available since PHP 4.0.2\r
+ */\r
+class PEAR_Error\r
+{\r
+    // {{{ properties\r
+\r
+    var $error_message_prefix = '';\r
+    var $mode                 = PEAR_ERROR_RETURN;\r
+    var $level                = E_USER_NOTICE;\r
+    var $code                 = -1;\r
+    var $message              = '';\r
+    var $userinfo             = '';\r
+    var $backtrace            = null;\r
+\r
+    // }}}\r
+    // {{{ constructor\r
+\r
+    /**\r
+     * PEAR_Error constructor\r
+     *\r
+     * @param string $message  message\r
+     *\r
+     * @param int $code     (optional) error code\r
+     *\r
+     * @param int $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,\r
+     * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,\r
+     * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION\r
+     *\r
+     * @param mixed $options   (optional) error level, _OR_ in the case of\r
+     * PEAR_ERROR_CALLBACK, the callback function or object/method\r
+     * tuple.\r
+     *\r
+     * @param string $userinfo (optional) additional user/debug info\r
+     *\r
+     * @access public\r
+     *\r
+     */\r
+    function PEAR_Error($message = 'unknown error', $code = null,\r
+                        $mode = null, $options = null, $userinfo = null)\r
+    {\r
+        if ($mode === null) {\r
+            $mode = PEAR_ERROR_RETURN;\r
+        }\r
+        $this->message   = $message;\r
+        $this->code      = $code;\r
+        $this->mode      = $mode;\r
+        $this->userinfo  = $userinfo;\r
+        if (function_exists("debug_backtrace")) {\r
+            if (@!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) {\r
+                $this->backtrace = debug_backtrace();\r
+            }\r
+        }\r
+        if ($mode & PEAR_ERROR_CALLBACK) {\r
+            $this->level = E_USER_NOTICE;\r
+            $this->callback = $options;\r
+        } else {\r
+            if ($options === null) {\r
+                $options = E_USER_NOTICE;\r
+            }\r
+            $this->level = $options;\r
+            $this->callback = null;\r
+        }\r
+        if ($this->mode & PEAR_ERROR_PRINT) {\r
+            if (is_null($options) || is_int($options)) {\r
+                $format = "%s";\r
+            } else {\r
+                $format = $options;\r
+            }\r
+            printf($format, $this->getMessage());\r
+        }\r
+        if ($this->mode & PEAR_ERROR_TRIGGER) {\r
+            trigger_error($this->getMessage(), $this->level);\r
+        }\r
+        if ($this->mode & PEAR_ERROR_DIE) {\r
+            $msg = $this->getMessage();\r
+            if (is_null($options) || is_int($options)) {\r
+                $format = "%s";\r
+                if (substr($msg, -1) != "\n") {\r
+                    $msg .= "\n";\r
+                }\r
+            } else {\r
+                $format = $options;\r
+            }\r
+            die(sprintf($format, $msg));\r
+        }\r
+        if ($this->mode & PEAR_ERROR_CALLBACK) {\r
+            if (is_callable($this->callback)) {\r
+                call_user_func($this->callback, $this);\r
+            }\r
+        }\r
+        if ($this->mode & PEAR_ERROR_EXCEPTION) {\r
+            trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);\r
+            eval('$e = new Exception($this->message, $this->code);throw($e);');\r
+        }\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getMode()\r
+\r
+    /**\r
+     * Get the error mode from an error object.\r
+     *\r
+     * @return int error mode\r
+     * @access public\r
+     */\r
+    function getMode() {\r
+        return $this->mode;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getCallback()\r
+\r
+    /**\r
+     * Get the callback function/method from an error object.\r
+     *\r
+     * @return mixed callback function or object/method array\r
+     * @access public\r
+     */\r
+    function getCallback() {\r
+        return $this->callback;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getMessage()\r
+\r
+\r
+    /**\r
+     * Get the error message from an error object.\r
+     *\r
+     * @return  string  full error message\r
+     * @access public\r
+     */\r
+    function getMessage()\r
+    {\r
+        return ($this->error_message_prefix . $this->message);\r
+    }\r
+\r
+\r
+    // }}}\r
+    // {{{ getCode()\r
+\r
+    /**\r
+     * Get error code from an error object\r
+     *\r
+     * @return int error code\r
+     * @access public\r
+     */\r
+     function getCode()\r
+     {\r
+        return $this->code;\r
+     }\r
+\r
+    // }}}\r
+    // {{{ getType()\r
+\r
+    /**\r
+     * Get the name of this error/exception.\r
+     *\r
+     * @return string error/exception name (type)\r
+     * @access public\r
+     */\r
+    function getType()\r
+    {\r
+        return get_class($this);\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getUserInfo()\r
+\r
+    /**\r
+     * Get additional user-supplied information.\r
+     *\r
+     * @return string user-supplied information\r
+     * @access public\r
+     */\r
+    function getUserInfo()\r
+    {\r
+        return $this->userinfo;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getDebugInfo()\r
+\r
+    /**\r
+     * Get additional debug information supplied by the application.\r
+     *\r
+     * @return string debug information\r
+     * @access public\r
+     */\r
+    function getDebugInfo()\r
+    {\r
+        return $this->getUserInfo();\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getBacktrace()\r
+\r
+    /**\r
+     * Get the call backtrace from where the error was generated.\r
+     * Supported with PHP 4.3.0 or newer.\r
+     *\r
+     * @param int $frame (optional) what frame to fetch\r
+     * @return array Backtrace, or NULL if not available.\r
+     * @access public\r
+     */\r
+    function getBacktrace($frame = null)\r
+    {\r
+        if (defined('PEAR_IGNORE_BACKTRACE')) {\r
+            return null;\r
+        }\r
+        if ($frame === null) {\r
+            return $this->backtrace;\r
+        }\r
+        return $this->backtrace[$frame];\r
+    }\r
+\r
+    // }}}\r
+    // {{{ addUserInfo()\r
+\r
+    function addUserInfo($info)\r
+    {\r
+        if (empty($this->userinfo)) {\r
+            $this->userinfo = $info;\r
+        } else {\r
+            $this->userinfo .= " ** $info";\r
+        }\r
+    }\r
+\r
+    // }}}\r
+    // {{{ toString()\r
+\r
+    /**\r
+     * Make a string representation of this object.\r
+     *\r
+     * @return string a string with an object summary\r
+     * @access public\r
+     */\r
+    function toString() {\r
+        $modes = array();\r
+        $levels = array(E_USER_NOTICE  => 'notice',\r
+                        E_USER_WARNING => 'warning',\r
+                        E_USER_ERROR   => 'error');\r
+        if ($this->mode & PEAR_ERROR_CALLBACK) {\r
+            if (is_array($this->callback)) {\r
+                $callback = (is_object($this->callback[0]) ?\r
+                    strtolower(get_class($this->callback[0])) :\r
+                    $this->callback[0]) . '::' .\r
+                    $this->callback[1];\r
+            } else {\r
+                $callback = $this->callback;\r
+            }\r
+            return sprintf('[%s: message="%s" code=%d mode=callback '.\r
+                           'callback=%s prefix="%s" info="%s"]',\r
+                           strtolower(get_class($this)), $this->message, $this->code,\r
+                           $callback, $this->error_message_prefix,\r
+                           $this->userinfo);\r
+        }\r
+        if ($this->mode & PEAR_ERROR_PRINT) {\r
+            $modes[] = 'print';\r
+        }\r
+        if ($this->mode & PEAR_ERROR_TRIGGER) {\r
+            $modes[] = 'trigger';\r
+        }\r
+        if ($this->mode & PEAR_ERROR_DIE) {\r
+            $modes[] = 'die';\r
+        }\r
+        if ($this->mode & PEAR_ERROR_RETURN) {\r
+            $modes[] = 'return';\r
+        }\r
+        return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.\r
+                       'prefix="%s" info="%s"]',\r
+                       strtolower(get_class($this)), $this->message, $this->code,\r
+                       implode("|", $modes), $levels[$this->level],\r
+                       $this->error_message_prefix,\r
+                       $this->userinfo);\r
+    }\r
+\r
+    // }}}\r
+}\r
+\r
+/*\r
+ * Local Variables:\r
+ * mode: php\r
+ * tab-width: 4\r
+ * c-basic-offset: 4\r
+ * End:\r
+ */\r
+?>\r
diff --git a/include/classes/XML/XML_HTMLSax/PEAR/Autoloader.php b/include/classes/XML/XML_HTMLSax/PEAR/Autoloader.php
new file mode 100644 (file)
index 0000000..2159efb
--- /dev/null
@@ -0,0 +1,223 @@
+<?php\r
+/**\r
+ * Class auto-loader\r
+ *\r
+ * PHP versions 4\r
+ *\r
+ * LICENSE: This source file is subject to version 3.0 of the PHP license\r
+ * that is available through the world-wide-web at the following URI:\r
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of\r
+ * the PHP License and are unable to obtain it through the web, please\r
+ * send a note to license@php.net so we can mail you a copy immediately.\r
+ *\r
+ * @category   pear\r
+ * @package    PEAR\r
+ * @author     Stig Bakken <ssb@php.net>\r
+ * @copyright  1997-2008 The PHP Group\r
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0\r
+ * @version    CVS: $Id$\r
+ * @link       http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader\r
+ * @since      File available since Release 0.1\r
+ * @deprecated File deprecated in Release 1.4.0a1\r
+ */\r
+\r
+// /* vim: set expandtab tabstop=4 shiftwidth=4: */\r
+\r
+if (!extension_loaded("overload")) {\r
+    // die hard without ext/overload\r
+    die("Rebuild PHP with the `overload' extension to use PEAR_Autoloader");\r
+}\r
+\r
+/**\r
+ * Include for PEAR_Error and PEAR classes\r
+ */\r
+require_once "PEAR.php";\r
+\r
+/**\r
+ * This class is for objects where you want to separate the code for\r
+ * some methods into separate classes.  This is useful if you have a\r
+ * class with not-frequently-used methods that contain lots of code\r
+ * that you would like to avoid always parsing.\r
+ *\r
+ * The PEAR_Autoloader class provides autoloading and aggregation.\r
+ * The autoloading lets you set up in which classes the separated\r
+ * methods are found.  Aggregation is the technique used to import new\r
+ * methods, an instance of each class providing separated methods is\r
+ * stored and called every time the aggregated method is called.\r
+ *\r
+ * @category   pear\r
+ * @package    PEAR\r
+ * @author Stig Bakken <ssb@php.net>\r
+ * @copyright  1997-2008 The PHP Group\r
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0\r
+ * @version    Release: 1.4.4\r
+ * @link       http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader\r
+ * @since      File available since Release 0.1\r
+ * @deprecated File deprecated in Release 1.4.0a1\r
+ */\r
+class PEAR_Autoloader extends PEAR\r
+{\r
+    // {{{ properties\r
+\r
+    /**\r
+     * Map of methods and classes where they are defined\r
+     *\r
+     * @var array\r
+     *\r
+     * @access private\r
+     */\r
+    var $_autoload_map = array();\r
+\r
+    /**\r
+     * Map of methods and aggregate objects\r
+     *\r
+     * @var array\r
+     *\r
+     * @access private\r
+     */\r
+    var $_method_map = array();\r
+\r
+    // }}}\r
+    // {{{ addAutoload()\r
+\r
+    /**\r
+     * Add one or more autoload entries.\r
+     *\r
+     * @param string $method     which method to autoload\r
+     *\r
+     * @param string $classname  (optional) which class to find the method in.\r
+     *                           If the $method parameter is an array, this\r
+     *                           parameter may be omitted (and will be ignored\r
+     *                           if not), and the $method parameter will be\r
+     *                           treated as an associative array with method\r
+     *                           names as keys and class names as values.\r
+     *\r
+     * @return void\r
+     *\r
+     * @access public\r
+     */\r
+    function addAutoload($method, $classname = null)\r
+    {\r
+        if (is_array($method)) {\r
+            array_walk($method, create_function('$a,&$b', '$b = strtolower($b);'));\r
+            $this->_autoload_map = array_merge($this->_autoload_map, $method);\r
+        } else {\r
+            $this->_autoload_map[strtolower($method)] = $classname;\r
+        }\r
+    }\r
+\r
+    // }}}\r
+    // {{{ removeAutoload()\r
+\r
+    /**\r
+     * Remove an autoload entry.\r
+     *\r
+     * @param string $method  which method to remove the autoload entry for\r
+     *\r
+     * @return bool TRUE if an entry was removed, FALSE if not\r
+     *\r
+     * @access public\r
+     */\r
+    function removeAutoload($method)\r
+    {\r
+        $method = strtolower($method);\r
+        $ok = isset($this->_autoload_map[$method]);\r
+        unset($this->_autoload_map[$method]);\r
+        return $ok;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ addAggregateObject()\r
+\r
+    /**\r
+     * Add an aggregate object to this object.  If the specified class\r
+     * is not defined, loading it will be attempted following PEAR's\r
+     * file naming scheme.  All the methods in the class will be\r
+     * aggregated, except private ones (name starting with an\r
+     * underscore) and constructors.\r
+     *\r
+     * @param string $classname  what class to instantiate for the object.\r
+     *\r
+     * @return void\r
+     *\r
+     * @access public\r
+     */\r
+    function addAggregateObject($classname)\r
+    {\r
+        $classname = strtolower($classname);\r
+        if (!class_exists($classname)) {\r
+            $include_file = preg_replace('/[^a-z0-9]/i', '_', $classname);\r
+            include_once $include_file;\r
+        }\r
+        $obj =& new $classname;\r
+        $methods = get_class_methods($classname);\r
+        foreach ($methods as $method) {\r
+            // don't import priviate methods and constructors\r
+            if ($method{0} != '_' && $method != $classname) {\r
+                $this->_method_map[$method] = $obj;\r
+            }\r
+        }\r
+    }\r
+\r
+    // }}}\r
+    // {{{ removeAggregateObject()\r
+\r
+    /**\r
+     * Remove an aggregate object.\r
+     *\r
+     * @param string $classname  the class of the object to remove\r
+     *\r
+     * @return bool  TRUE if an object was removed, FALSE if not\r
+     *\r
+     * @access public\r
+     */\r
+    function removeAggregateObject($classname)\r
+    {\r
+        $ok = false;\r
+        $classname = strtolower($classname);\r
+        reset($this->_method_map);\r
+        while (list($method, $obj) = each($this->_method_map)) {\r
+            if (is_a($obj, $classname)) {\r
+                unset($this->_method_map[$method]);\r
+                $ok = true;\r
+            }\r
+        }\r
+        return $ok;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ __call()\r
+\r
+    /**\r
+     * Overloaded object call handler, called each time an\r
+     * undefined/aggregated method is invoked.  This method repeats\r
+     * the call in the right aggregate object and passes on the return\r
+     * value.\r
+     *\r
+     * @param string $method  which method that was called\r
+     *\r
+     * @param string $args    An array of the parameters passed in the\r
+     *                        original call\r
+     *\r
+     * @return mixed  The return value from the aggregated method, or a PEAR\r
+     *                error if the called method was unknown.\r
+     */\r
+    function __call($method, $args, &$retval)\r
+    {\r
+        $method = strtolower($method);\r
+        if (empty($this->_method_map[$method]) && isset($this->_autoload_map[$method])) {\r
+            $this->addAggregateObject($this->_autoload_map[$method]);\r
+        }\r
+        if (isset($this->_method_map[$method])) {\r
+            $retval = call_user_func_array(array($this->_method_map[$method], $method), $args);\r
+            return true;\r
+        }\r
+        return false;\r
+    }\r
+\r
+    // }}}\r
+}\r
+\r
+overload("PEAR_Autoloader");\r
+\r
+?>\r
diff --git a/include/classes/XML/XML_HTMLSax/PEAR/Common.php b/include/classes/XML/XML_HTMLSax/PEAR/Common.php
new file mode 100644 (file)
index 0000000..ed20c06
--- /dev/null
@@ -0,0 +1,1140 @@
+<?php\r
+/**\r
+ * PEAR_Common, the base class for the PEAR Installer\r
+ *\r
+ * PHP versions 4 and 5\r
+ *\r
+ * LICENSE: This source file is subject to version 3.0 of the PHP license\r
+ * that is available through the world-wide-web at the following URI:\r
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of\r
+ * the PHP License and are unable to obtain it through the web, please\r
+ * send a note to license@php.net so we can mail you a copy immediately.\r
+ *\r
+ * @category   pear\r
+ * @package    PEAR\r
+ * @author     Stig Bakken <ssb@php.net>\r
+ * @author     Tomas V. V. Cox <cox@idecnet.com>\r
+ * @author     Greg Beaver <cellog@php.net>\r
+ * @copyright  1997-2008 The PHP Group\r
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0\r
+ * @version    CVS: $Id$\r
+ * @link       http://pear.php.net/package/PEAR\r
+ * @since      File available since Release 0.1.0\r
+ * @deprecated File deprecated since Release 1.4.0a1\r
+ */\r
+\r
+/**\r
+ * Include error handling\r
+ */\r
+require_once 'PEAR.php';\r
+\r
+// {{{ constants and globals\r
+\r
+/**\r
+ * PEAR_Common error when an invalid PHP file is passed to PEAR_Common::analyzeSourceCode()\r
+ */\r
+define('PEAR_COMMON_ERROR_INVALIDPHP', 1);\r
+define('_PEAR_COMMON_PACKAGE_NAME_PREG', '[A-Za-z][a-zA-Z0-9_]+');\r
+define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '$/');\r
+\r
+// this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1\r
+define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?');\r
+define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '$/i');\r
+\r
+// XXX far from perfect :-)\r
+define('_PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '(' . _PEAR_COMMON_PACKAGE_NAME_PREG .\r
+    ')(-([.0-9a-zA-Z]+))?');\r
+define('PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_PACKAGE_DOWNLOAD_PREG .\r
+    '$/');\r
+\r
+define('_PEAR_CHANNELS_NAME_PREG', '[A-Za-z][a-zA-Z0-9_\.]+');\r
+define('PEAR_CHANNELS_NAME_PREG', '/^' . _PEAR_CHANNELS_NAME_PREG . '$/');\r
+\r
+// this should allow any dns or IP address, plus a path - NO UNDERSCORES ALLOWED\r
+define('_PEAR_CHANNELS_SERVER_PREG', '[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*(\/[a-zA-Z0-9-]+)*');\r
+define('PEAR_CHANNELS_SERVER_PREG', '/^' . _PEAR_CHANNELS_SERVER_PREG . '$/i');\r
+\r
+define('_PEAR_CHANNELS_PACKAGE_PREG',  '(' ._PEAR_CHANNELS_SERVER_PREG . ')\/('\r
+         . _PEAR_COMMON_PACKAGE_NAME_PREG . ')');\r
+define('PEAR_CHANNELS_PACKAGE_PREG', '/^' . _PEAR_CHANNELS_PACKAGE_PREG . '$/i');\r
+\r
+define('_PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '(' . _PEAR_CHANNELS_NAME_PREG . ')::('\r
+    . _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?');\r
+define('PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_CHANNEL_DOWNLOAD_PREG . '$/');\r
+\r
+/**\r
+ * List of temporary files and directories registered by\r
+ * PEAR_Common::addTempFile().\r
+ * @var array\r
+ */\r
+$GLOBALS['_PEAR_Common_tempfiles'] = array();\r
+\r
+/**\r
+ * Valid maintainer roles\r
+ * @var array\r
+ */\r
+$GLOBALS['_PEAR_Common_maintainer_roles'] = array('lead','developer','contributor','helper');\r
+\r
+/**\r
+ * Valid release states\r
+ * @var array\r
+ */\r
+$GLOBALS['_PEAR_Common_release_states'] = array('alpha','beta','stable','snapshot','devel');\r
+\r
+/**\r
+ * Valid dependency types\r
+ * @var array\r
+ */\r
+$GLOBALS['_PEAR_Common_dependency_types'] = array('pkg','ext','php','prog','ldlib','rtlib','os','websrv','sapi');\r
+\r
+/**\r
+ * Valid dependency relations\r
+ * @var array\r
+ */\r
+$GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not', 'ne');\r
+\r
+/**\r
+ * Valid file roles\r
+ * @var array\r
+ */\r
+$GLOBALS['_PEAR_Common_file_roles'] = array('php','ext','test','doc','data','src','script');\r
+\r
+/**\r
+ * Valid replacement types\r
+ * @var array\r
+ */\r
+$GLOBALS['_PEAR_Common_replacement_types'] = array('php-const', 'pear-config', 'package-info');\r
+\r
+/**\r
+ * Valid "provide" types\r
+ * @var array\r
+ */\r
+$GLOBALS['_PEAR_Common_provide_types'] = array('ext', 'prog', 'class', 'function', 'feature', 'api');\r
+\r
+/**\r
+ * Valid "provide" types\r
+ * @var array\r
+ */\r
+$GLOBALS['_PEAR_Common_script_phases'] = array('pre-install', 'post-install', 'pre-uninstall', 'post-uninstall', 'pre-build', 'post-build', 'pre-configure', 'post-configure', 'pre-setup', 'post-setup');\r
+\r
+// }}}\r
+\r
+/**\r
+ * Class providing common functionality for PEAR administration classes.\r
+ * @category   pear\r
+ * @package    PEAR\r
+ * @author     Stig Bakken <ssb@php.net>\r
+ * @author     Tomas V. V. Cox <cox@idecnet.com>\r
+ * @author     Greg Beaver <cellog@php.net>\r
+ * @copyright  1997-2008 The PHP Group\r
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0\r
+ * @version    Release: 1.4.4\r
+ * @link       http://pear.php.net/package/PEAR\r
+ * @since      Class available since Release 1.4.0a1\r
+ * @deprecated This class will disappear, and its components will be spread\r
+ *             into smaller classes, like the AT&T breakup, as of Release 1.4.0a1\r
+ */\r
+class PEAR_Common extends PEAR\r
+{\r
+    // {{{ properties\r
+\r
+    /** stack of elements, gives some sort of XML context */\r
+    var $element_stack = array();\r
+\r
+    /** name of currently parsed XML element */\r
+    var $current_element;\r
+\r
+    /** array of attributes of the currently parsed XML element */\r
+    var $current_attributes = array();\r
+\r
+    /** assoc with information about a package */\r
+    var $pkginfo = array();\r
+\r
+    /**\r
+     * User Interface object (PEAR_Frontend_* class).  If null,\r
+     * the log() method uses print.\r
+     * @var object\r
+     */\r
+    var $ui = null;\r
+\r
+    /**\r
+     * Configuration object (PEAR_Config).\r
+     * @var object\r
+     */\r
+    var $config = null;\r
+\r
+    var $current_path = null;\r
+\r
+    /**\r
+     * PEAR_SourceAnalyzer instance\r
+     * @var object\r
+     */\r
+    var $source_analyzer = null;\r
+    /**\r
+     * Flag variable used to mark a valid package file\r
+     * @var boolean\r
+     * @access private\r
+     */\r
+    var $_validPackageFile;\r
+\r
+    // }}}\r
+\r
+    // {{{ constructor\r
+\r
+    /**\r
+     * PEAR_Common constructor\r
+     *\r
+     * @access public\r
+     */\r
+    function PEAR_Common()\r
+    {\r
+        parent::PEAR();\r
+        $this->config = &PEAR_Config::singleton();\r
+        $this->debug = $this->config->get('verbose');\r
+    }\r
+\r
+    // }}}\r
+    // {{{ destructor\r
+\r
+    /**\r
+     * PEAR_Common destructor\r
+     *\r
+     * @access private\r
+     */\r
+    function _PEAR_Common()\r
+    {\r
+        // doesn't work due to bug #14744\r
+        //$tempfiles = $this->_tempfiles;\r
+        $tempfiles =& $GLOBALS['_PEAR_Common_tempfiles'];\r
+        while ($file = array_shift($tempfiles)) {\r
+            if (@is_dir($file)) {\r
+                if (!class_exists('System')) {\r
+                    require_once 'System.php';\r
+                }\r
+                System::rm(array('-rf', $file));\r
+            } elseif (file_exists($file)) {\r
+                unlink($file);\r
+            }\r
+        }\r
+    }\r
+\r
+    // }}}\r
+    // {{{ addTempFile()\r
+\r
+    /**\r
+     * Register a temporary file or directory.  When the destructor is\r
+     * executed, all registered temporary files and directories are\r
+     * removed.\r
+     *\r
+     * @param string  $file  name of file or directory\r
+     *\r
+     * @return void\r
+     *\r
+     * @access public\r
+     */\r
+    function addTempFile($file)\r
+    {\r
+        if (!class_exists('PEAR_Frontend')) {\r
+            require_once 'PEAR/Frontend.php';\r
+        }\r
+        PEAR_Frontend::addTempFile($file);\r
+    }\r
+\r
+    // }}}\r
+    // {{{ mkDirHier()\r
+\r
+    /**\r
+     * Wrapper to System::mkDir(), creates a directory as well as\r
+     * any necessary parent directories.\r
+     *\r
+     * @param string  $dir  directory name\r
+     *\r
+     * @return bool TRUE on success, or a PEAR error\r
+     *\r
+     * @access public\r
+     */\r
+    function mkDirHier($dir)\r
+    {\r
+        $this->log(2, "+ create dir $dir");\r
+        if (!class_exists('System')) {\r
+            require_once 'System.php';\r
+        }\r
+        return System::mkDir(array('-p', $dir));\r
+    }\r
+\r
+    // }}}\r
+    // {{{ log()\r
+\r
+    /**\r
+     * Logging method.\r
+     *\r
+     * @param int    $level  log level (0 is quiet, higher is noisier)\r
+     * @param string $msg    message to write to the log\r
+     *\r
+     * @return void\r
+     *\r
+     * @access public\r
+     * @static\r
+     */\r
+    function log($level, $msg, $append_crlf = true)\r
+    {\r
+        if ($this->debug >= $level) {\r
+            if (!class_exists('PEAR_Frontend')) {\r
+                require_once 'PEAR/Frontend.php';\r
+            }\r
+            $ui = &PEAR_Frontend::singleton();\r
+            if (is_a($ui, 'PEAR_Frontend')) {\r
+                $ui->log($msg, $append_crlf);\r
+            } else {\r
+                print "$msg\n";\r
+            }\r
+        }\r
+    }\r
+\r
+    // }}}\r
+    // {{{ mkTempDir()\r
+\r
+    /**\r
+     * Create and register a temporary directory.\r
+     *\r
+     * @param string $tmpdir (optional) Directory to use as tmpdir.\r
+     *                       Will use system defaults (for example\r
+     *                       /tmp or c:\windows\temp) if not specified\r
+     *\r
+     * @return string name of created directory\r
+     *\r
+     * @access public\r
+     */\r
+    function mkTempDir($tmpdir = '')\r
+    {\r
+        if ($tmpdir) {\r
+            $topt = array('-t', $tmpdir);\r
+        } else {\r
+            $topt = array();\r
+        }\r
+        $topt = array_merge($topt, array('-d', 'pear'));\r
+        if (!class_exists('System')) {\r
+            require_once 'System.php';\r
+        }\r
+        if (!$tmpdir = System::mktemp($topt)) {\r
+            return false;\r
+        }\r
+        $this->addTempFile($tmpdir);\r
+        return $tmpdir;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ setFrontendObject()\r
+\r
+    /**\r
+     * Set object that represents the frontend to be used.\r
+     *\r
+     * @param  object Reference of the frontend object\r
+     * @return void\r
+     * @access public\r
+     */\r
+    function setFrontendObject(&$ui)\r
+    {\r
+        $this->ui = &$ui;\r
+    }\r
+\r
+    // }}}\r
+\r
+    // {{{ infoFromTgzFile()\r
+\r
+    /**\r
+     * Returns information about a package file.  Expects the name of\r
+     * a gzipped tar file as input.\r
+     *\r
+     * @param string  $file  name of .tgz file\r
+     *\r
+     * @return array  array with package information\r
+     *\r
+     * @access public\r
+     * @deprecated use PEAR_PackageFile->fromTgzFile() instead\r
+     *\r
+     */\r
+    function infoFromTgzFile($file)\r
+    {\r
+        $packagefile = &new PEAR_PackageFile($this->config);\r
+        $pf = &$packagefile->fromTgzFile($file, PEAR_VALIDATE_NORMAL);\r
+        if (PEAR::isError($pf)) {\r
+            $errs = $pf->getUserinfo();\r
+            if (is_array($errs)) {\r
+                foreach ($errs as $error) {\r
+                    $e = $this->raiseError($error['message'], $error['code'], null, null, $error);\r
+                }\r
+            }\r
+            return $pf;\r
+        }\r
+        return $this->_postProcessValidPackagexml($pf);\r
+    }\r
+\r
+    // }}}\r
+    // {{{ infoFromDescriptionFile()\r
+\r
+    /**\r
+     * Returns information about a package file.  Expects the name of\r
+     * a package xml file as input.\r
+     *\r
+     * @param string  $descfile  name of package xml file\r
+     *\r
+     * @return array  array with package information\r
+     *\r
+     * @access public\r
+     * @deprecated use PEAR_PackageFile->fromPackageFile() instead\r
+     *\r
+     */\r
+    function infoFromDescriptionFile($descfile)\r
+    {\r
+        $packagefile = &new PEAR_PackageFile($this->config);\r
+        $pf = &$packagefile->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);\r
+        if (PEAR::isError($pf)) {\r
+            $errs = $pf->getUserinfo();\r
+            if (is_array($errs)) {\r
+                foreach ($errs as $error) {\r
+                    $e = $this->raiseError($error['message'], $error['code'], null, null, $error);\r
+                }\r
+            }\r
+            return $pf;\r
+        }\r
+        return $this->_postProcessValidPackagexml($pf);\r
+    }\r
+\r
+    // }}}\r
+    // {{{ infoFromString()\r
+\r
+    /**\r
+     * Returns information about a package file.  Expects the contents\r
+     * of a package xml file as input.\r
+     *\r
+     * @param string  $data  contents of package.xml file\r
+     *\r
+     * @return array   array with package information\r
+     *\r
+     * @access public\r
+     * @deprecated use PEAR_PackageFile->fromXmlstring() instead\r
+     *\r
+     */\r
+    function infoFromString($data)\r
+    {\r
+        $packagefile = &new PEAR_PackageFile($this->config);\r
+        $pf = &$packagefile->fromXmlString($data, PEAR_VALIDATE_NORMAL, false);\r
+        if (PEAR::isError($pf)) {\r
+            $errs = $pf->getUserinfo();\r
+            if (is_array($errs)) {\r
+                foreach ($errs as $error) {\r
+                    $e = $this->raiseError($error['message'], $error['code'], null, null, $error);\r
+                }\r
+            }\r
+            return $pf;\r
+        }\r
+        return $this->_postProcessValidPackagexml($pf);\r
+    }\r
+    // }}}\r
+\r
+    /**\r
+     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2\r
+     * @return array\r
+     */\r
+    function _postProcessValidPackagexml(&$pf)\r
+    {\r
+        if (is_a($pf, 'PEAR_PackageFile_v2')) {\r
+            // sort of make this into a package.xml 1.0-style array\r
+            // changelog is not converted to old format.\r
+            $arr = $pf->toArray(true);\r
+            $arr = array_merge($arr, $arr['old']);\r
+            unset($arr['old']);\r
+            unset($arr['xsdversion']);\r
+            unset($arr['contents']);\r
+            unset($arr['compatible']);\r
+            unset($arr['channel']);\r
+            unset($arr['uri']);\r
+            unset($arr['dependencies']);\r
+            unset($arr['phprelease']);\r
+            unset($arr['extsrcrelease']);\r
+            unset($arr['extbinrelease']);\r
+            unset($arr['bundle']);\r
+            unset($arr['lead']);\r
+            unset($arr['developer']);\r
+            unset($arr['helper']);\r
+            unset($arr['contributor']);\r
+            $arr['filelist'] = $pf->getFilelist();\r
+            $this->pkginfo = $arr;\r
+            return $arr;\r
+        } else {\r
+            $this->pkginfo = $pf->toArray();\r
+            return $this->pkginfo;\r
+        }\r
+    }\r
+    // {{{ infoFromAny()\r
+\r
+    /**\r
+     * Returns package information from different sources\r
+     *\r
+     * This method is able to extract information about a package\r
+     * from a .tgz archive or from a XML package definition file.\r
+     *\r
+     * @access public\r
+     * @param  string Filename of the source ('package.xml', '<package>.tgz')\r
+     * @return string\r
+     * @deprecated use PEAR_PackageFile->fromAnyFile() instead\r
+     */\r
+    function infoFromAny($info)\r
+    {\r
+        if (is_string($info) && file_exists($info)) {\r
+            $packagefile = &new PEAR_PackageFile($this->config);\r
+            $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);\r
+            if (PEAR::isError($pf)) {\r
+                $errs = $pf->getUserinfo();\r
+                if (is_array($errs)) {\r
+                    foreach ($errs as $error) {\r
+                        $e = $this->raiseError($error['message'], $error['code'], null, null, $error);\r
+                    }\r
+                }\r
+                return $pf;\r
+            }\r
+            return $this->_postProcessValidPackagexml($pf);\r
+        }\r
+        return $info;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ xmlFromInfo()\r
+\r
+    /**\r
+     * Return an XML document based on the package info (as returned\r
+     * by the PEAR_Common::infoFrom* methods).\r
+     *\r
+     * @param array  $pkginfo  package info\r
+     *\r
+     * @return string XML data\r
+     *\r
+     * @access public\r
+     * @deprecated use a PEAR_PackageFile_v* object's generator instead\r
+     */\r
+    function xmlFromInfo($pkginfo)\r
+    {\r
+        $config = &PEAR_Config::singleton();\r
+        $packagefile = &new PEAR_PackageFile($config);\r
+        $pf = &$packagefile->fromArray($pkginfo);\r
+        $gen = &$pf->getDefaultGenerator();\r
+        return $gen->toXml(PEAR_VALIDATE_PACKAGING);\r
+    }\r
+\r
+    // }}}\r
+    // {{{ validatePackageInfo()\r
+\r
+    /**\r
+     * Validate XML package definition file.\r
+     *\r
+     * @param  string $info Filename of the package archive or of the\r
+     *                package definition file\r
+     * @param  array $errors Array that will contain the errors\r
+     * @param  array $warnings Array that will contain the warnings\r
+     * @param  string $dir_prefix (optional) directory where source files\r
+     *                may be found, or empty if they are not available\r
+     * @access public\r
+     * @return boolean\r
+     * @deprecated use the validation of PEAR_PackageFile objects\r
+     */\r
+    function validatePackageInfo($info, &$errors, &$warnings, $dir_prefix = '')\r
+    {\r
+        $config = &PEAR_Config::singleton();\r
+        $packagefile = &new PEAR_PackageFile($config);\r
+        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);\r
+        if (strpos($info, '<?xml') !== false) {\r
+            $pf = &$packagefile->fromXmlString($info, PEAR_VALIDATE_NORMAL, '');\r
+        } else {\r
+            $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);\r
+        }\r
+        PEAR::staticPopErrorHandling();\r
+        if (PEAR::isError($pf)) {\r
+            $errs = $pf->getUserinfo();\r
+            if (is_array($errs)) {\r
+                foreach ($errs as $error) {\r
+                    if ($error['level'] == 'error') {\r
+                        $errors[] = $error['message'];\r
+                    } else {\r
+                        $warnings[] = $error['message'];\r
+                    }\r
+                }\r
+            }\r
+            return false;\r
+        }\r
+        return true;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ buildProvidesArray()\r
+\r
+    /**\r
+     * Build a "provides" array from data returned by\r
+     * analyzeSourceCode().  The format of the built array is like\r
+     * this:\r
+     *\r
+     *  array(\r
+     *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),\r
+     *    ...\r
+     *  )\r
+     *\r
+     *\r
+     * @param array $srcinfo array with information about a source file\r
+     * as returned by the analyzeSourceCode() method.\r
+     *\r
+     * @return void\r
+     *\r
+     * @access public\r
+     *\r
+     */\r
+    function buildProvidesArray($srcinfo)\r
+    {\r
+        $file = basename($srcinfo['source_file']);\r
+        $pn = '';\r
+        if (isset($this->_packageName)) {\r
+            $pn = $this->_packageName;\r
+        }\r
+        $pnl = strlen($pn);\r
+        foreach ($srcinfo['declared_classes'] as $class) {\r
+            $key = "class;$class";\r
+            if (isset($this->pkginfo['provides'][$key])) {\r
+                continue;\r
+            }\r
+            $this->pkginfo['provides'][$key] =\r
+                array('file'=> $file, 'type' => 'class', 'name' => $class);\r
+            if (isset($srcinfo['inheritance'][$class])) {\r
+                $this->pkginfo['provides'][$key]['extends'] =\r
+                    $srcinfo['inheritance'][$class];\r
+            }\r
+        }\r
+        foreach ($srcinfo['declared_methods'] as $class => $methods) {\r
+            foreach ($methods as $method) {\r
+                $function = "$class::$method";\r
+                $key = "function;$function";\r
+                if ($method{0} == '_' || !strcasecmp($method, $class) ||\r
+                    isset($this->pkginfo['provides'][$key])) {\r
+                    continue;\r
+                }\r
+                $this->pkginfo['provides'][$key] =\r
+                    array('file'=> $file, 'type' => 'function', 'name' => $function);\r
+            }\r
+        }\r
+\r
+        foreach ($srcinfo['declared_functions'] as $function) {\r
+            $key = "function;$function";\r
+            if ($function{0} == '_' || isset($this->pkginfo['provides'][$key])) {\r
+                continue;\r
+            }\r
+            if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {\r
+                $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";\r
+            }\r
+            $this->pkginfo['provides'][$key] =\r
+                array('file'=> $file, 'type' => 'function', 'name' => $function);\r
+        }\r
+    }\r
+\r
+    // }}}\r
+    // {{{ analyzeSourceCode()\r
+\r
+    /**\r
+     * Analyze the source code of the given PHP file\r
+     *\r
+     * @param  string Filename of the PHP file\r
+     * @return mixed\r
+     * @access public\r
+     */\r
+    function analyzeSourceCode($file)\r
+    {\r
+        if (!function_exists("token_get_all")) {\r
+            return false;\r
+        }\r
+        if (!defined('T_DOC_COMMENT')) {\r
+            define('T_DOC_COMMENT', T_COMMENT);\r
+        }\r
+        if (!defined('T_INTERFACE')) {\r
+            define('T_INTERFACE', -1);\r
+        }\r
+        if (!defined('T_IMPLEMENTS')) {\r
+            define('T_IMPLEMENTS', -1);\r
+        }\r
+        if (!$fp = @fopen($file, "r")) {\r
+            return false;\r
+        }\r
+        if (function_exists('file_get_contents')) {\r
+            fclose($fp);\r
+            $contents = file_get_contents($file);\r
+        } else {\r
+            $contents = fread($fp, filesize($file));\r
+            fclose($fp);\r
+        }\r
+        $tokens = token_get_all($contents);\r
+/*\r
+        for ($i = 0; $i < sizeof($tokens); $i++) {\r
+            @list($token, $data) = $tokens[$i];\r
+            if (is_string($token)) {\r
+                var_dump($token);\r
+            } else {\r
+                print token_name($token) . ' ';\r
+                var_dump(rtrim($data));\r
+            }\r
+        }\r
+*/\r
+        $look_for = 0;\r
+        $paren_level = 0;\r
+        $bracket_level = 0;\r
+        $brace_level = 0;\r
+        $lastphpdoc = '';\r
+        $current_class = '';\r
+        $current_interface = '';\r
+        $current_class_level = -1;\r
+        $current_function = '';\r
+        $current_function_level = -1;\r
+        $declared_classes = array();\r
+        $declared_interfaces = array();\r
+        $declared_functions = array();\r
+        $declared_methods = array();\r
+        $used_classes = array();\r
+        $used_functions = array();\r
+        $extends = array();\r
+        $implements = array();\r
+        $nodeps = array();\r
+        $inquote = false;\r
+        $interface = false;\r
+        for ($i = 0; $i < sizeof($tokens); $i++) {\r
+            if (is_array($tokens[$i])) {\r
+                list($token, $data) = $tokens[$i];\r
+            } else {\r
+                $token = $tokens[$i];\r
+                $data = '';\r
+            }\r
+            if ($inquote) {\r
+                if ($token != '"') {\r
+                    continue;\r
+                } else {\r
+                    $inquote = false;\r
+                    continue;\r
+                }\r
+            }\r
+            switch ($token) {\r
+                case T_WHITESPACE:\r
+                    continue;\r
+                case ';':\r
+                    if ($interface) {\r
+                        $current_function = '';\r
+                        $current_function_level = -1;\r
+                    }\r
+                    break;\r
+                case '"':\r
+                    $inquote = true;\r
+                    break;\r
+                case T_CURLY_OPEN:\r
+                case T_DOLLAR_OPEN_CURLY_BRACES:\r
+                case '{': $brace_level++; continue 2;\r
+                case '}':\r
+                    $brace_level--;\r
+                    if ($current_class_level == $brace_level) {\r
+                        $current_class = '';\r
+                        $current_class_level = -1;\r
+                    }\r
+                    if ($current_function_level == $brace_level) {\r
+                        $current_function = '';\r
+                        $current_function_level = -1;\r
+                    }\r
+                    continue 2;\r
+                case '[': $bracket_level++; continue 2;\r
+                case ']': $bracket_level--; continue 2;\r
+                case '(': $paren_level++;   continue 2;\r
+                case ')': $paren_level--;   continue 2;\r
+                case T_INTERFACE:\r
+                    $interface = true;\r
+                case T_CLASS:\r
+                    if (($current_class_level != -1) || ($current_function_level != -1)) {\r
+                        PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",\r
+                            PEAR_COMMON_ERROR_INVALIDPHP);\r
+                        return false;\r
+                    }\r
+                case T_FUNCTION:\r
+                case T_NEW:\r
+                case T_EXTENDS:\r
+                case T_IMPLEMENTS:\r
+                    $look_for = $token;\r
+                    continue 2;\r
+                case T_STRING:\r
+                    if (version_compare(zend_version(), '2.0', '<')) {\r
+                        if (in_array(strtolower($data),\r
+                            array('public', 'private', 'protected', 'abstract',\r
+                                  'interface', 'implements', 'throw') \r
+                                 )) {\r
+                            PEAR::raiseError('Error: PHP5 token encountered in ' . $file . \r
+                            'packaging should be done in PHP 5');\r
+                            return false;\r
+                        }\r
+                    }\r
+                    if ($look_for == T_CLASS) {\r
+                        $current_class = $data;\r
+                        $current_class_level = $brace_level;\r
+                        $declared_classes[] = $current_class;\r
+                    } elseif ($look_for == T_INTERFACE) {\r
+                        $current_interface = $data;\r
+                        $current_class_level = $brace_level;\r
+                        $declared_interfaces[] = $current_interface;\r
+                    } elseif ($look_for == T_IMPLEMENTS) {\r
+                        $implements[$current_class] = $data;\r
+                    } elseif ($look_for == T_EXTENDS) {\r
+                        $extends[$current_class] = $data;\r
+                    } elseif ($look_for == T_FUNCTION) {\r
+                        if ($current_class) {\r
+                            $current_function = "$current_class::$data";\r
+                            $declared_methods[$current_class][] = $data;\r
+                        } elseif ($current_interface) {\r
+                            $current_function = "$current_interface::$data";\r
+                            $declared_methods[$current_interface][] = $data;\r
+                        } else {\r
+                            $current_function = $data;\r
+                            $declared_functions[] = $current_function;\r
+                        }\r
+                        $current_function_level = $brace_level;\r
+                        $m = array();\r
+                    } elseif ($look_for == T_NEW) {\r
+                        $used_classes[$data] = true;\r
+                    }\r
+                    $look_for = 0;\r
+                    continue 2;\r
+                case T_VARIABLE:\r
+                    $look_for = 0;\r
+                    continue 2;\r
+                case T_DOC_COMMENT:\r
+                case T_COMMENT:\r
+                    if (preg_match('!^/\*\*\s!', $data)) {\r
+                        $lastphpdoc = $data;\r
+                        if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {\r
+                            $nodeps = array_merge($nodeps, $m[1]);\r
+                        }\r
+                    }\r
+                    continue 2;\r
+                case T_DOUBLE_COLON:\r
+                    if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) {\r
+                        PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",\r
+                            PEAR_COMMON_ERROR_INVALIDPHP);\r
+                        return false;\r
+                    }\r
+                    $class = $tokens[$i - 1][1];\r
+                    if (strtolower($class) != 'parent') {\r
+                        $used_classes[$class] = true;\r
+                    }\r
+                    continue 2;\r
+            }\r
+        }\r
+        return array(\r
+            "source_file" => $file,\r
+            "declared_classes" => $declared_classes,\r
+            "declared_interfaces" => $declared_interfaces,\r
+            "declared_methods" => $declared_methods,\r
+            "declared_functions" => $declared_functions,\r
+            "used_classes" => array_diff(array_keys($used_classes), $nodeps),\r
+            "inheritance" => $extends,\r
+            "implements" => $implements,\r
+            );\r
+    }\r
+\r
+    // }}}\r
+    // {{{  betterStates()\r
+\r
+    /**\r
+     * Return an array containing all of the states that are more stable than\r
+     * or equal to the passed in state\r
+     *\r
+     * @param string Release state\r
+     * @param boolean Determines whether to include $state in the list\r
+     * @return false|array False if $state is not a valid release state\r
+     */\r
+    function betterStates($state, $include = false)\r
+    {\r
+        static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');\r
+        $i = array_search($state, $states);\r
+        if ($i === false) {\r
+            return false;\r
+        }\r
+        if ($include) {\r
+            $i--;\r
+        }\r
+        return array_slice($states, $i + 1);\r
+    }\r
+\r
+    // }}}\r
+    // {{{ detectDependencies()\r
+\r
+    function detectDependencies($any, $status_callback = null)\r
+    {\r
+        if (!function_exists("token_get_all")) {\r
+            return false;\r
+        }\r
+        if (PEAR::isError($info = $this->infoFromAny($any))) {\r
+            return $this->raiseError($info);\r
+        }\r
+        if (!is_array($info)) {\r
+            return false;\r
+        }\r
+        $deps = array();\r
+        $used_c = $decl_c = $decl_f = $decl_m = array();\r
+        foreach ($info['filelist'] as $file => $fa) {\r
+            $tmp = $this->analyzeSourceCode($file);\r
+            $used_c = @array_merge($used_c, $tmp['used_classes']);\r
+            $decl_c = @array_merge($decl_c, $tmp['declared_classes']);\r
+            $decl_f = @array_merge($decl_f, $tmp['declared_functions']);\r
+            $decl_m = @array_merge($decl_m, $tmp['declared_methods']);\r
+            $inheri = @array_merge($inheri, $tmp['inheritance']);\r
+        }\r
+        $used_c = array_unique($used_c);\r
+        $decl_c = array_unique($decl_c);\r
+        $undecl_c = array_diff($used_c, $decl_c);\r
+        return array('used_classes' => $used_c,\r
+                     'declared_classes' => $decl_c,\r
+                     'declared_methods' => $decl_m,\r
+                     'declared_functions' => $decl_f,\r
+                     'undeclared_classes' => $undecl_c,\r
+                     'inheritance' => $inheri,\r
+                     );\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getUserRoles()\r
+\r
+    /**\r
+     * Get the valid roles for a PEAR package maintainer\r
+     *\r
+     * @return array\r
+     * @static\r
+     */\r
+    function getUserRoles()\r
+    {\r
+        return $GLOBALS['_PEAR_Common_maintainer_roles'];\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getReleaseStates()\r
+\r
+    /**\r
+     * Get the valid package release states of packages\r
+     *\r
+     * @return array\r
+     * @static\r
+     */\r
+    function getReleaseStates()\r
+    {\r
+        return $GLOBALS['_PEAR_Common_release_states'];\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getDependencyTypes()\r
+\r
+    /**\r
+     * Get the implemented dependency types (php, ext, pkg etc.)\r
+     *\r
+     * @return array\r
+     * @static\r
+     */\r
+    function getDependencyTypes()\r
+    {\r
+        return $GLOBALS['_PEAR_Common_dependency_types'];\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getDependencyRelations()\r
+\r
+    /**\r
+     * Get the implemented dependency relations (has, lt, ge etc.)\r
+     *\r
+     * @return array\r
+     * @static\r
+     */\r
+    function getDependencyRelations()\r
+    {\r
+        return $GLOBALS['_PEAR_Common_dependency_relations'];\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getFileRoles()\r
+\r
+    /**\r
+     * Get the implemented file roles\r
+     *\r
+     * @return array\r
+     * @static\r
+     */\r
+    function getFileRoles()\r
+    {\r
+        return $GLOBALS['_PEAR_Common_file_roles'];\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getReplacementTypes()\r
+\r
+    /**\r
+     * Get the implemented file replacement types in\r
+     *\r
+     * @return array\r
+     * @static\r
+     */\r
+    function getReplacementTypes()\r
+    {\r
+        return $GLOBALS['_PEAR_Common_replacement_types'];\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getProvideTypes()\r
+\r
+    /**\r
+     * Get the implemented file replacement types in\r
+     *\r
+     * @return array\r
+     * @static\r
+     */\r
+    function getProvideTypes()\r
+    {\r
+        return $GLOBALS['_PEAR_Common_provide_types'];\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getScriptPhases()\r
+\r
+    /**\r
+     * Get the implemented file replacement types in\r
+     *\r
+     * @return array\r
+     * @static\r
+     */\r
+    function getScriptPhases()\r
+    {\r
+        return $GLOBALS['_PEAR_Common_script_phases'];\r
+    }\r
+\r
+    // }}}\r
+    // {{{ validPackageName()\r
+\r
+    /**\r
+     * Test whether a string contains a valid package name.\r
+     *\r
+     * @param string $name the package name to test\r
+     *\r
+     * @return bool\r
+     *\r
+     * @access public\r
+     */\r
+    function validPackageName($name)\r
+    {\r
+        return (bool)preg_match(PEAR_COMMON_PACKAGE_NAME_PREG, $name);\r
+    }\r
+\r
+\r
+    // }}}\r
+    // {{{ validPackageVersion()\r
+\r
+    /**\r
+     * Test whether a string contains a valid package version.\r
+     *\r
+     * @param string $ver the package version to test\r
+     *\r
+     * @return bool\r
+     *\r
+     * @access public\r
+     */\r
+    function validPackageVersion($ver)\r
+    {\r
+        return (bool)preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver);\r
+    }\r
+\r
+\r
+    // }}}\r
+\r
+    // {{{ downloadHttp()\r
+\r
+    /**\r
+     * Download a file through HTTP.  Considers suggested file name in\r
+     * Content-disposition: header and can run a callback function for\r
+     * different events.  The callback will be called with two\r
+     * parameters: the callback type, and parameters.  The implemented\r
+     * callback types are:\r
+     *\r
+     *  'setup'       called at the very beginning, parameter is a UI object\r
+     *                that should be used for all output\r
+     *  'message'     the parameter is a string with an informational message\r
+     *  'saveas'      may be used to save with a different file name, the\r
+     *                parameter is the filename that is about to be used.\r
+     *                If a 'saveas' callback returns a non-empty string,\r
+     *                that file name will be used as the filename instead.\r
+     *                Note that $save_dir will not be affected by this, only\r
+     *                the basename of the file.\r
+     *  'start'       download is starting, parameter is number of bytes\r
+     *                that are expected, or -1 if unknown\r
+     *  'bytesread'   parameter is the number of bytes read so far\r
+     *  'done'        download is complete, parameter is the total number\r
+     *                of bytes read\r
+     *  'connfailed'  if the TCP connection fails, this callback is called\r
+     *                with array(host,port,errno,errmsg)\r
+     *  'writefailed' if writing to disk fails, this callback is called\r
+     *                with array(destfile,errmsg)\r
+     *\r
+     * If an HTTP proxy has been configured (http_proxy PEAR_Config\r
+     * setting), the proxy will be used.\r
+     *\r
+     * @param string  $url       the URL to download\r
+     * @param object  $ui        PEAR_Frontend_* instance\r
+     * @param object  $config    PEAR_Config instance\r
+     * @param string  $save_dir  (optional) directory to save file in\r
+     * @param mixed   $callback  (optional) function/method to call for status\r
+     *                           updates\r
+     *\r
+     * @return string  Returns the full path of the downloaded file or a PEAR\r
+     *                 error on failure.  If the error is caused by\r
+     *                 socket-related errors, the error object will\r
+     *                 have the fsockopen error code available through\r
+     *                 getCode().\r
+     *\r
+     * @access public\r
+     * @deprecated in favor of PEAR_Downloader::downloadHttp()\r
+     */\r
+    function downloadHttp($url, &$ui, $save_dir = '.', $callback = null)\r
+    {\r
+        if (!class_exists('PEAR_Downloader')) {\r
+            require_once 'PEAR/Downloader.php';\r
+        }\r
+        return PEAR_Downloader::downloadHttp($url, $ui, $save_dir, $callback);\r
+    }\r
+\r
+    // }}}\r
+\r
+    /**\r
+     * @param string $path relative or absolute include path\r
+     * @return boolean\r
+     * @static\r
+     */\r
+    function isIncludeable($path)\r
+    {\r
+        if (file_exists($path) && is_readable($path)) {\r
+            return true;\r
+        }\r
+        $ipath = explode(PATH_SEPARATOR, ini_get('include_path'));\r
+        foreach ($ipath as $include) {\r
+            $test = realpath($include . DIRECTORY_SEPARATOR . $path);\r
+            if (file_exists($test) && is_readable($test)) {\r
+                return true;\r
+            }\r
+        }\r
+        return false;\r
+    }\r
+}\r
+require_once 'PEAR/Config.php';\r
+require_once 'PEAR/PackageFile.php';\r
+if (!function_exists('file_get_contents')) {\r
+    function file_get_contents($filename)\r
+    {\r
+        $fp = fopen($filename, 'rb');\r
+        $ret = '';\r
+        while (!feof($fp)) {\r
+            $ret .= fread($fp, 8092);;\r
+        }\r
+        return $ret;\r
+    }\r
+}\r
+?>
\ No newline at end of file
diff --git a/include/classes/XML/XML_HTMLSax/PEAR/Config.php b/include/classes/XML/XML_HTMLSax/PEAR/Config.php
new file mode 100644 (file)
index 0000000..58708b8
--- /dev/null
@@ -0,0 +1,2054 @@
+<?php\r
+/**\r
+ * PEAR_Config, customized configuration handling for the PEAR Installer\r
+ *\r
+ * PHP versions 4 and 5\r
+ *\r
+ * LICENSE: This source file is subject to version 3.0 of the PHP license\r
+ * that is available through the world-wide-web at the following URI:\r
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of\r
+ * the PHP License and are unable to obtain it through the web, please\r
+ * send a note to license@php.net so we can mail you a copy immediately.\r
+ *\r
+ * @category   pear\r
+ * @package    PEAR\r
+ * @author     Stig Bakken <ssb@php.net>\r
+ * @author     Greg Beaver <cellog@php.net>\r
+ * @copyright  1997-2008 The PHP Group\r
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0\r
+ * @version    CVS: $Id$\r
+ * @link       http://pear.php.net/package/PEAR\r
+ * @since      File available since Release 0.1\r
+ */\r
+\r
+/**\r
+ * Required for error handling\r
+ */\r
+require_once 'PEAR.php';\r
+require_once 'PEAR/Registry.php';\r
+require_once 'PEAR/Installer/Role.php';\r
+require_once 'System.php';\r
+require_once 'PEAR/Remote.php';\r
+\r
+/**\r
+ * Last created PEAR_Config instance.\r
+ * @var object\r
+ */\r
+$GLOBALS['_PEAR_Config_instance'] = null;\r
+if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) {\r
+    $PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear';\r
+} else {\r
+    $PEAR_INSTALL_DIR = PEAR_INSTALL_DIR;\r
+}\r
+\r
+// Below we define constants with default values for all configuration\r
+// parameters except username/password.  All of them can have their\r
+// defaults set through environment variables.  The reason we use the\r
+// PHP_ prefix is for some security, PHP protects environment\r
+// variables starting with PHP_*.\r
+\r
+// default channel and preferred mirror is based on whether we are invoked through\r
+// the "pear" or the "pecl" command\r
+\r
+if (!defined('PEAR_RUNTYPE') || PEAR_RUNTYPE == 'pear') {\r
+    define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pear.php.net');\r
+} else {\r
+    define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pecl.php.net');\r
+}\r
+\r
+if (getenv('PHP_PEAR_SYSCONF_DIR')) {\r
+    define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR'));\r
+} elseif (getenv('SystemRoot')) {\r
+    define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot'));\r
+} else {\r
+    define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR);\r
+}\r
+\r
+// Default for master_server\r
+if (getenv('PHP_PEAR_MASTER_SERVER')) {\r
+    define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER'));\r
+} else {\r
+    define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net');\r
+}\r
+\r
+// Default for http_proxy\r
+if (getenv('PHP_PEAR_HTTP_PROXY')) {\r
+    define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY'));\r
+} elseif (getenv('http_proxy')) {\r
+    define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy'));\r
+} else {\r
+    define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', '');\r
+}\r
+\r
+// Default for php_dir\r
+if (getenv('PHP_PEAR_INSTALL_DIR')) {\r
+    define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR'));\r
+} else {\r
+    if (@is_dir($PEAR_INSTALL_DIR)) {\r
+        define('PEAR_CONFIG_DEFAULT_PHP_DIR',\r
+               $PEAR_INSTALL_DIR);\r
+    } else {\r
+        define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);\r
+    }\r
+}\r
+\r
+// Default for ext_dir\r
+if (getenv('PHP_PEAR_EXTENSION_DIR')) {\r
+    define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR'));\r
+} else {\r
+    if (ini_get('extension_dir')) {\r
+        define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir'));\r
+    } elseif (defined('PEAR_EXTENSION_DIR') && @is_dir(PEAR_EXTENSION_DIR)) {\r
+        define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR);\r
+    } elseif (defined('PHP_EXTENSION_DIR')) {\r
+        define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR);\r
+    } else {\r
+        define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.');\r
+    }\r
+}\r
+\r
+// Default for doc_dir\r
+if (getenv('PHP_PEAR_DOC_DIR')) {\r
+    define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR'));\r
+} else {\r
+    define('PEAR_CONFIG_DEFAULT_DOC_DIR',\r
+           $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs');\r
+}\r
+\r
+// Default for bin_dir\r
+if (getenv('PHP_PEAR_BIN_DIR')) {\r
+    define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR'));\r
+} else {\r
+    define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR);\r
+}\r
+\r
+// Default for data_dir\r
+if (getenv('PHP_PEAR_DATA_DIR')) {\r
+    define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR'));\r
+} else {\r
+    define('PEAR_CONFIG_DEFAULT_DATA_DIR',\r
+           $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data');\r
+}\r
+\r
+// Default for test_dir\r
+if (getenv('PHP_PEAR_TEST_DIR')) {\r
+    define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR'));\r
+} else {\r
+    define('PEAR_CONFIG_DEFAULT_TEST_DIR',\r
+           $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests');\r
+}\r
+\r
+// Default for cache_dir\r
+if (getenv('PHP_PEAR_CACHE_DIR')) {\r
+    define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR'));\r
+} else {\r
+    define('PEAR_CONFIG_DEFAULT_CACHE_DIR',\r
+           System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .\r
+           DIRECTORY_SEPARATOR . 'cache');\r
+}\r
+\r
+// Default for php_bin\r
+if (getenv('PHP_PEAR_PHP_BIN')) {\r
+    define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN'));\r
+} else {\r
+    define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR.\r
+           DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : ''));\r
+}\r
+\r
+// Default for verbose\r
+if (getenv('PHP_PEAR_VERBOSE')) {\r
+    define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE'));\r
+} else {\r
+    define('PEAR_CONFIG_DEFAULT_VERBOSE', 1);\r
+}\r
+\r
+// Default for preferred_state\r
+if (getenv('PHP_PEAR_PREFERRED_STATE')) {\r
+    define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE'));\r
+} else {\r
+    define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable');\r
+}\r
+\r
+// Default for umask\r
+if (getenv('PHP_PEAR_UMASK')) {\r
+    define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK'));\r
+} else {\r
+    define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask()));\r
+}\r
+\r
+// Default for cache_ttl\r
+if (getenv('PHP_PEAR_CACHE_TTL')) {\r
+    define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL'));\r
+} else {\r
+    define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600);\r
+}\r
+\r
+// Default for sig_type\r
+if (getenv('PHP_PEAR_SIG_TYPE')) {\r
+    define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE'));\r
+} else {\r
+    define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg');\r
+}\r
+\r
+// Default for sig_bin\r
+if (getenv('PHP_PEAR_SIG_BIN')) {\r
+    define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN'));\r
+} else {\r
+    define('PEAR_CONFIG_DEFAULT_SIG_BIN',\r
+           System::which(\r
+               'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg'));\r
+}\r
+\r
+// Default for sig_keydir\r
+if (getenv('PHP_PEAR_SIG_KEYDIR')) {\r
+    define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR'));\r
+} else {\r
+    define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR',\r
+           PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys');\r
+}\r
+\r
+/**\r
+ * This is a class for storing configuration data, keeping track of\r
+ * which are system-defined, user-defined or defaulted.\r
+ * @category   pear\r
+ * @package    PEAR\r
+ * @author     Stig Bakken <ssb@php.net>\r
+ * @author     Greg Beaver <cellog@php.net>\r
+ * @copyright  1997-2008 The PHP Group\r
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0\r
+ * @version    Release: 1.4.4\r
+ * @link       http://pear.php.net/package/PEAR\r
+ * @since      Class available since Release 0.1\r
+ */\r
+class PEAR_Config extends PEAR\r
+{\r
+    // {{{ properties\r
+\r
+    /**\r
+     * Array of config files used.\r
+     *\r
+     * @var array layer => config file\r
+     */\r
+    var $files = array(\r
+        'system' => '',\r
+        'user' => '',\r
+        );\r
+\r
+    var $layers = array();\r
+    \r
+    /**\r
+     * Configuration data, two-dimensional array where the first\r
+     * dimension is the config layer ('user', 'system' and 'default'),\r
+     * and the second dimension is keyname => value.\r
+     *\r
+     * The order in the first dimension is important!  Earlier\r
+     * layers will shadow later ones when a config value is\r
+     * requested (if a 'user' value exists, it will be returned first,\r
+     * then 'system' and finally 'default').\r
+     *\r
+     * @var array layer => array(keyname => value, ...)\r
+     */\r
+    var $configuration = array(\r
+        'user' => array(),\r
+        'system' => array(),\r
+        'default' => array(),\r
+        );\r
+    \r
+    /**\r
+     * Configuration values that can be set for a channel\r
+     *\r
+     * All other configuration values can only have a global value\r
+     * @var array\r
+     * @access private\r
+     */\r
+    var $_channelConfigInfo = array(\r
+        'php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir',\r
+        'test_dir', 'php_bin', 'username', 'password', 'verbose',\r
+        'preferred_state', 'umask', 'preferred_mirror',\r
+        );\r
+\r
+    /**\r
+     * Channels that can be accessed\r
+     * @see setChannels()\r
+     * @var array\r
+     * @access private\r
+     */\r
+    var $_channels = array('pear.php.net', 'pecl.php.net', '__uri');\r
+\r
+    /**\r
+     * This variable is used to control the directory values returned\r
+     * @see setInstallRoot();\r
+     * @var string|false\r
+     * @access private\r
+     */\r
+    var $_installRoot = false;\r
+\r
+    /**\r
+     * If requested, this will always refer to the registry\r
+     * contained in php_dir\r
+     * @var PEAR_Registry\r
+     */\r
+    var $_registry = array();\r
+\r
+    /**\r
+     * @var array\r
+     * @access private\r
+     */\r
+    var $_regInitialized = array();\r
+\r
+    /**\r
+     * @var bool\r
+     * @access private\r
+     */\r
+    var $_noRegistry = false;\r
+\r
+    /**\r
+     * amount of errors found while parsing config\r
+     * @var integer\r
+     * @access private\r
+     */\r
+    var $_errorsFound = 0;\r
+    var $_lastError = null;\r
+\r
+    /**\r
+     * Information about the configuration data.  Stores the type,\r
+     * default value and a documentation string for each configuration\r
+     * value.\r
+     *\r
+     * @var array layer => array(infotype => value, ...)\r
+     */\r
+    var $configuration_info = array(\r
+        // Channels/Internet Access\r
+        'default_channel' => array(\r
+            'type' => 'string',\r
+            'default' => PEAR_CONFIG_DEFAULT_CHANNEL,\r
+            'doc' => 'the default channel to use for all non explicit commands',\r
+            'prompt' => 'Default Channel',\r
+            'group' => 'Internet Access',\r
+            ),\r
+        'preferred_mirror' => array(\r
+            'type' => 'string',\r
+            'default' => PEAR_CONFIG_DEFAULT_CHANNEL,\r
+            'doc' => 'the default server or mirror to use for channel actions',\r
+            'prompt' => 'Default Channel Mirror',\r
+            'group' => 'Internet Access',\r
+            ),\r
+        'remote_config' => array(\r
+            'type' => 'password',\r
+            'default' => '',\r
+            'doc' => 'ftp url of remote configuration file to use for synchronized install',\r
+            'prompt' => 'Remote Configuration File',\r
+            'group' => 'Internet Access',\r
+            ),\r
+        'auto_discover' => array(\r
+            'type' => 'integer',\r
+            'default' => 0,\r
+            'doc' => 'whether to automatically discover new channels',\r
+            'prompt' => 'Auto-discover new Channels',\r
+            'group' => 'Internet Access',\r
+            ),\r
+        // Internet Access\r
+        'master_server' => array(\r
+            'type' => 'string',\r
+            'default' => 'pear.php.net',\r
+            'doc' => 'name of the main PEAR server [NOT USED IN THIS VERSION]',\r
+            'prompt' => 'PEAR server [DEPRECATED]',\r
+            'group' => 'Internet Access',\r
+            ),\r
+        'http_proxy' => array(\r
+            'type' => 'string',\r
+            'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY,\r
+            'doc' => 'HTTP proxy (host:port) to use when downloading packages',\r
+            'prompt' => 'HTTP Proxy Server Address',\r
+            'group' => 'Internet Access',\r
+            ),\r
+        // File Locations\r
+        'php_dir' => array(\r
+            'type' => 'directory',\r
+            'default' => PEAR_CONFIG_DEFAULT_PHP_DIR,\r
+            'doc' => 'directory where .php files are installed',\r
+            'prompt' => 'PEAR directory',\r
+            'group' => 'File Locations',\r
+            ),\r
+        'ext_dir' => array(\r
+            'type' => 'directory',\r
+            'default' => PEAR_CONFIG_DEFAULT_EXT_DIR,\r
+            'doc' => 'directory where loadable extensions are installed',\r
+            'prompt' => 'PHP extension directory',\r
+            'group' => 'File Locations',\r
+            ),\r
+        'doc_dir' => array(\r
+            'type' => 'directory',\r
+            'default' => PEAR_CONFIG_DEFAULT_DOC_DIR,\r
+            'doc' => 'directory where documentation is installed',\r
+            'prompt' => 'PEAR documentation directory',\r
+            'group' => 'File Locations',\r
+            ),\r
+        'bin_dir' => array(\r
+            'type' => 'directory',\r
+            'default' => PEAR_CONFIG_DEFAULT_BIN_DIR,\r
+            'doc' => 'directory where executables are installed',\r
+            'prompt' => 'PEAR executables directory',\r
+            'group' => 'File Locations',\r
+            ),\r
+        'data_dir' => array(\r
+            'type' => 'directory',\r
+            'default' => PEAR_CONFIG_DEFAULT_DATA_DIR,\r
+            'doc' => 'directory where data files are installed',\r
+            'prompt' => 'PEAR data directory',\r
+            'group' => 'File Locations (Advanced)',\r
+            ),\r
+        'test_dir' => array(\r
+            'type' => 'directory',\r
+            'default' => PEAR_CONFIG_DEFAULT_TEST_DIR,\r
+            'doc' => 'directory where regression tests are installed',\r
+            'prompt' => 'PEAR test directory',\r
+            'group' => 'File Locations (Advanced)',\r
+            ),\r
+        'cache_dir' => array(\r
+            'type' => 'directory',\r
+            'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR,\r
+            'doc' => 'directory which is used for XMLRPC cache',\r
+            'prompt' => 'PEAR Installer cache directory',\r
+            'group' => 'File Locations (Advanced)',\r
+            ),\r
+        'php_bin' => array(\r
+            'type' => 'file',\r
+            'default' => PEAR_CONFIG_DEFAULT_PHP_BIN,\r
+            'doc' => 'PHP CLI/CGI binary for executing scripts',\r
+            'prompt' => 'PHP CLI/CGI binary',\r
+            'group' => 'File Locations (Advanced)',\r
+            ),\r
+        // Maintainers\r
+        'username' => array(\r
+            'type' => 'string',\r
+            'default' => '',\r
+            'doc' => '(maintainers) your PEAR account name',\r
+            'prompt' => 'PEAR username (for maintainers)',\r
+            'group' => 'Maintainers',\r
+            ),\r
+        'password' => array(\r
+            'type' => 'password',\r
+            'default' => '',\r
+            'doc' => '(maintainers) your PEAR account password',\r
+            'prompt' => 'PEAR password (for maintainers)',\r
+            'group' => 'Maintainers',\r
+            ),\r
+        // Advanced\r
+        'verbose' => array(\r
+            'type' => 'integer',\r
+            'default' => PEAR_CONFIG_DEFAULT_VERBOSE,\r
+            'doc' => 'verbosity level\r
+0: really quiet\r
+1: somewhat quiet\r
+2: verbose\r
+3: debug',\r
+            'prompt' => 'Debug Log Level',\r
+            'group' => 'Advanced',\r
+            ),\r
+        'preferred_state' => array(\r
+            'type' => 'set',\r
+            'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE,\r
+            'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified',\r
+            'valid_set' => array(\r
+                'stable', 'beta', 'alpha', 'devel', 'snapshot'),\r
+            'prompt' => 'Preferred Package State',\r
+            'group' => 'Advanced',\r
+            ),\r
+        'umask' => array(\r
+            'type' => 'mask',\r
+            'default' => PEAR_CONFIG_DEFAULT_UMASK,\r
+            'doc' => 'umask used when creating files (Unix-like systems only)',\r
+            'prompt' => 'Unix file mask',\r
+            'group' => 'Advanced',\r
+            ),\r
+        'cache_ttl' => array(\r
+            'type' => 'integer',\r
+            'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL,\r
+            'doc' => 'amount of secs where the local cache is used and not updated',\r
+            'prompt' => 'Cache TimeToLive',\r
+            'group' => 'Advanced',\r
+            ),\r
+        'sig_type' => array(\r
+            'type' => 'set',\r
+            'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE,\r
+            'doc' => 'which package signature mechanism to use',\r
+            'valid_set' => array('gpg'),\r
+            'prompt' => 'Package Signature Type',\r
+            'group' => 'Maintainers',\r
+            ),\r
+        'sig_bin' => array(\r
+            'type' => 'string',\r
+            'default' => PEAR_CONFIG_DEFAULT_SIG_BIN,\r
+            'doc' => 'which package signature mechanism to use',\r
+            'prompt' => 'Signature Handling Program',\r
+            'group' => 'Maintainers',\r
+            ),\r
+        'sig_keyid' => array(\r
+            'type' => 'string',\r
+            'default' => '',\r
+            'doc' => 'which key to use for signing with',\r
+            'prompt' => 'Signature Key Id',\r
+            'group' => 'Maintainers',\r
+            ),\r
+        'sig_keydir' => array(\r
+            'type' => 'directory',\r
+            'default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR,\r
+            'doc' => 'directory where signature keys are located',\r
+            'prompt' => 'Signature Key Directory',\r
+            'group' => 'Maintainers',\r
+            ),\r
+        // __channels is reserved - used for channel-specific configuration\r
+        );\r
+\r
+    // }}}\r
+\r
+    // {{{ PEAR_Config([file], [defaults_file])\r
+\r
+    /**\r
+     * Constructor.\r
+     *\r
+     * @param string file to read user-defined options from\r
+     * @param string file to read system-wide defaults from\r
+     * @param bool   determines whether a registry object "follows"\r
+     *               the value of php_dir (is automatically created\r
+     *               and moved when php_dir is changed)\r
+     * @param bool   if true, fails if configuration files cannot be loaded\r
+     *\r
+     * @access public\r
+     *\r
+     * @see PEAR_Config::singleton\r
+     */\r
+    function PEAR_Config($user_file = '', $system_file = '', $ftp_file = false,\r
+                         $strict = true)\r
+    {\r
+        $this->PEAR();\r
+        PEAR_Installer_Role::initializeConfig($this);\r
+        $sl = DIRECTORY_SEPARATOR;\r
+        if (empty($user_file)) {\r
+            if (OS_WINDOWS) {\r
+                $user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini';\r
+            } else {\r
+                $user_file = getenv('HOME') . $sl . '.pearrc';\r
+            }\r
+        }\r
+        if (empty($system_file)) {\r
+            if (OS_WINDOWS) {\r
+                $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini';\r
+            } else {\r
+                $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf';\r
+            }\r
+        }\r
+\r
+        $this->layers = array_keys($this->configuration);\r
+        $this->files['user'] = $user_file;\r
+        $this->files['system'] = $system_file;\r
+        if ($user_file && @file_exists($user_file)) {\r
+            $this->pushErrorHandling(PEAR_ERROR_RETURN);\r
+            $this->readConfigFile($user_file, 'user', $strict);\r
+            $this->popErrorHandling();\r
+            if ($this->_errorsFound > 0) {\r
+                return;\r
+            }\r
+        }\r
+\r
+        if ($system_file && @file_exists($system_file)) {\r
+            $this->mergeConfigFile($system_file, false, 'system', $strict);\r
+            if ($this->_errorsFound > 0) {\r
+                return;\r
+            }\r
+\r
+        }\r
+\r
+        if (!$ftp_file) {\r
+            $ftp_file = $this->get('remote_config');\r
+        }\r
+\r
+        if ($ftp_file && defined('PEAR_REMOTEINSTALL_OK')) {\r
+            $this->readFTPConfigFile($ftp_file);\r
+        }\r
+\r
+        foreach ($this->configuration_info as $key => $info) {\r
+            $this->configuration['default'][$key] = $info['default'];\r
+        }\r
+\r
+        $this->_registry['default'] = &new PEAR_Registry($this->configuration['default']['php_dir']);\r
+        $this->_registry['default']->setConfig($this);\r
+        $this->_regInitialized['default'] = false;\r
+        //$GLOBALS['_PEAR_Config_instance'] = &$this;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ singleton([file], [defaults_file])\r
+\r
+    /**\r
+     * Static singleton method.  If you want to keep only one instance\r
+     * of this class in use, this method will give you a reference to\r
+     * the last created PEAR_Config object if one exists, or create a\r
+     * new object.\r
+     *\r
+     * @param string (optional) file to read user-defined options from\r
+     * @param string (optional) file to read system-wide defaults from\r
+     *\r
+     * @return object an existing or new PEAR_Config instance\r
+     *\r
+     * @access public\r
+     *\r
+     * @see PEAR_Config::PEAR_Config\r
+     */\r
+    function &singleton($user_file = '', $system_file = '', $strict = true)\r
+    {\r
+        if (is_object($GLOBALS['_PEAR_Config_instance'])) {\r
+            return $GLOBALS['_PEAR_Config_instance'];\r
+        }\r
+\r
+        $t_conf = &new PEAR_Config($user_file, $system_file, false, $strict);\r
+        if ($t_conf->_errorsFound > 0) {\r
+             return $t_conf->lastError;\r
+        }\r
+\r
+        $GLOBALS['_PEAR_Config_instance'] = &$t_conf;\r
+        return $GLOBALS['_PEAR_Config_instance'];\r
+    }\r
+\r
+    // }}}\r
+    // {{{ validConfiguration()\r
+\r
+    /**\r
+     * Determine whether any configuration files have been detected, and whether a\r
+     * registry object can be retrieved from this configuration.\r
+     * @return bool\r
+     * @since PEAR 1.4.0a1\r
+     */\r
+    function validConfiguration()\r
+    {\r
+        if ($this->isDefinedLayer('user') || $this->isDefinedLayer('system')) {\r
+            return true;\r
+        }\r
+        return false;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ readConfigFile([file], [layer])\r
+\r
+    /**\r
+     * Reads configuration data from a file.  All existing values in\r
+     * the config layer are discarded and replaced with data from the\r
+     * file.\r
+     * @param string file to read from, if NULL or not specified, the\r
+     *               last-used file for the same layer (second param) is used\r
+     * @param string config layer to insert data into ('user' or 'system')\r
+     * @return bool TRUE on success or a PEAR error on failure\r
+     */\r
+    function readConfigFile($file = null, $layer = 'user', $strict = true)\r
+    {\r
+        if (empty($this->files[$layer])) {\r
+            return $this->raiseError("unknown config layer `$layer'");\r
+        }\r
+\r
+        if ($file === null) {\r
+            $file = $this->files[$layer];\r
+        }\r
+\r
+        $data = $this->_readConfigDataFrom($file);\r
+\r
+        if (PEAR::isError($data)) {\r
+            if ($strict) {\r
+                $this->_errorsFound++;\r
+                $this->lastError = $data;\r
+\r
+                return $data;\r
+            } else {\r
+                return true;\r
+            }\r
+        } else {\r
+            $this->files[$layer] = $file;\r
+        }\r
+\r
+        $this->_decodeInput($data);\r
+        $this->configuration[$layer] = $data;\r
+        $this->_setupChannels();\r
+        if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {\r
+            $this->_registry[$layer] = &new PEAR_Registry($phpdir);\r
+            $this->_registry[$layer]->setConfig($this);\r
+            $this->_regInitialized[$layer] = false;\r
+        } else {\r
+            unset($this->_registry[$layer]);\r
+        }\r
+        return true;\r
+    }\r
+\r
+    // }}}\r
+\r
+    /**\r
+     * @param string url to the remote config file, like ftp://www.example.com/pear/config.ini\r
+     * @return true|PEAR_Error\r
+     */\r
+    function readFTPConfigFile($path)\r
+    {\r
+        do { // poor man's try\r
+            if (!class_exists('Net_FTP')) {\r
+                if (!class_exists('PEAR_Common')) {\r
+                    require_once 'PEAR/Common.php';\r
+                }\r
+                if (PEAR_Common::isIncludeable('Net/FTP.php')) {\r
+                    include_once 'Net/FTP.php';\r
+                }\r
+            }\r
+            if (class_exists('Net_FTP') &&\r
+                  (class_exists('PEAR_FTP') || PEAR_Common::isIncludeable('PEAR/FTP.php'))) {\r
+                require_once 'PEAR/FTP.php';\r
+                $this->_ftp = &new PEAR_FTP;\r
+                $this->_ftp->pushErrorHandling(PEAR_ERROR_RETURN);\r
+                $e = $this->_ftp->init($path);\r
+                if (PEAR::isError($e)) {\r
+                    $this->_ftp->popErrorHandling();\r
+                    return $e;\r
+                }\r
+                $tmp = System::mktemp('-d');\r
+                PEAR_Common::addTempFile($tmp);\r
+                $e = $this->_ftp->get(basename($path), $tmp . DIRECTORY_SEPARATOR .\r
+                    'pear.ini', false, FTP_BINARY);\r
+                if (PEAR::isError($e)) {\r
+                    $this->_ftp->popErrorHandling();\r
+                    return $e;\r
+                }\r
+                PEAR_Common::addTempFile($tmp . DIRECTORY_SEPARATOR . 'pear.ini');\r
+                $this->_ftp->disconnect();\r
+                $this->_ftp->popErrorHandling();\r
+                $this->files['ftp'] = $tmp . DIRECTORY_SEPARATOR . 'pear.ini';\r
+                $e = $this->readConfigFile(null, 'ftp');\r
+                if (PEAR::isError($e)) {\r
+                    return $e;\r
+                }\r
+                $fail = array();\r
+                foreach ($this->configuration_info as $key => $val) {\r
+                    if (in_array($this->getGroup($key),\r
+                          array('File Locations', 'File Locations (Advanced)')) &&\r
+                          $this->getType($key) == 'directory') {\r
+                        // any directory configs must be set for this to work\r
+                        if (!isset($this->configuration['ftp'][$key])) {\r
+                            $fail[] = $key;\r
+                        }\r
+                    }\r
+                }\r
+                if (count($fail)) {\r
+                    $fail = '"' . implode('", "', $fail) . '"';\r
+                    unset($this->files['ftp']);\r
+                    unset($this->configuration['ftp']);\r
+                    return PEAR::raiseError('ERROR: Ftp configuration file must set all ' .\r
+                        'directory configuration variables.  These variables were not set: ' .\r
+                        $fail);\r
+                } else {\r
+                    return true;\r
+                }\r
+            } else {\r
+                return PEAR::raiseError('Net_FTP must be installed to use remote config');\r
+            }\r
+        } while (false); // poor man's catch\r
+        unset($this->files['ftp']);\r
+        return PEAR::raiseError('no remote host specified');\r
+    }\r
+\r
+    // {{{ _setupChannels()\r
+    \r
+    /**\r
+     * Reads the existing configurations and creates the _channels array from it\r
+     */\r
+    function _setupChannels()\r
+    {\r
+        $set = array_flip(array_values($this->_channels));\r
+        foreach ($this->configuration as $layer => $data) {\r
+            $i = 1000;\r
+            if (isset($data['__channels'])) {\r
+                foreach ($data['__channels'] as $channel => $info) {\r
+                    $set[$channel] = $i++;\r
+                }\r
+            }\r
+        }\r
+        $this->_channels = array_values(array_flip($set));\r
+        $this->setChannels($this->_channels);\r
+    }\r
+\r
+    // }}}\r
+    // {{{ deleteChannel(channel)\r
+\r
+    function deleteChannel($channel)\r
+    {\r
+        foreach ($this->configuration as $layer => $data) {\r
+            if (isset($data['__channels'])) {\r
+                if (isset($data['__channels'][strtolower($channel)])) {\r
+                    unset($this->configuration[$layer]['__channels'][strtolower($channel)]);\r
+                }\r
+            }\r
+        }\r
+        $this->_channels = array_flip($this->_channels);\r
+        unset($this->_channels[strtolower($channel)]);\r
+        $this->_channels = array_flip($this->_channels);\r
+    }\r
+\r
+    // }}}\r
+    // {{{ mergeConfigFile(file, [override], [layer])\r
+\r
+    /**\r
+     * Merges data into a config layer from a file.  Does the same\r
+     * thing as readConfigFile, except it does not replace all\r
+     * existing values in the config layer.\r
+     * @param string file to read from\r
+     * @param bool whether to overwrite existing data (default TRUE)\r
+     * @param string config layer to insert data into ('user' or 'system')\r
+     * @param string if true, errors are returned if file opening fails\r
+     * @return bool TRUE on success or a PEAR error on failure\r
+     */\r
+    function mergeConfigFile($file, $override = true, $layer = 'user', $strict = true)\r
+    {\r
+        if (empty($this->files[$layer])) {\r
+            return $this->raiseError("unknown config layer `$layer'");\r
+        }\r
+        if ($file === null) {\r
+            $file = $this->files[$layer];\r
+        }\r
+        $data = $this->_readConfigDataFrom($file);\r
+        if (PEAR::isError($data)) {\r
+            if ($strict) {\r
+                $this->_errorsFound++;\r
+                $this->lastError = $data;\r
+\r
+                return $data;\r
+            } else {\r
+                return true;\r
+            }\r
+        }\r
+        $this->_decodeInput($data);\r
+        if ($override) {\r
+            $this->configuration[$layer] =\r
+                PEAR_Config::arrayMergeRecursive($this->configuration[$layer], $data);\r
+        } else {\r
+            $this->configuration[$layer] =\r
+                PEAR_Config::arrayMergeRecursive($data, $this->configuration[$layer]);\r
+        }\r
+        $this->_setupChannels();\r
+        if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {\r
+            $this->_registry[$layer] = &new PEAR_Registry($phpdir);\r
+            $this->_registry[$layer]->setConfig($this);\r
+            $this->_regInitialized[$layer] = false;\r
+        } else {\r
+            unset($this->_registry[$layer]);\r
+        }\r
+        return true;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ arrayMergeRecursive($arr2, $arr1)\r
+    /**\r
+     * @param array\r
+     * @param array\r
+     * @return array\r
+     * @static\r
+     */\r
+    function arrayMergeRecursive($arr2, $arr1)\r
+    {\r
+        $ret = array();\r
+        foreach ($arr2 as $key => $data) {\r
+            if (!isset($arr1[$key])) {\r
+                $ret[$key] = $data;\r
+                unset($arr1[$key]);\r
+                continue;\r
+            }\r
+            if (is_array($data)) {\r
+                if (!is_array($arr1[$key])) {\r
+                    $ret[$key] = $arr1[$key];\r
+                    unset($arr1[$key]);\r
+                    continue;\r
+                }\r
+                $ret[$key] = PEAR_Config::arrayMergeRecursive($arr1[$key], $arr2[$key]);\r
+                unset($arr1[$key]);\r
+            }\r
+        }\r
+        return array_merge($ret, $arr1);\r
+    }\r
+\r
+    // }}}\r
+    // {{{ writeConfigFile([file], [layer])\r
+\r
+    /**\r
+     * Writes data into a config layer from a file.\r
+     *\r
+     * @param string|null file to read from, or null for default\r
+     * @param string config layer to insert data into ('user' or\r
+     *               'system')\r
+     * @param string|null data to write to config file or null for internal data [DEPRECATED]\r
+     * @return bool TRUE on success or a PEAR error on failure\r
+     */\r
+    function writeConfigFile($file = null, $layer = 'user', $data = null)\r
+    {\r
+        $this->_lazyChannelSetup($layer);\r
+        if ($layer == 'both' || $layer == 'all') {\r
+            foreach ($this->files as $type => $file) {\r
+                $err = $this->writeConfigFile($file, $type, $data);\r
+                if (PEAR::isError($err)) {\r
+                    return $err;\r
+                }\r
+            }\r
+            return true;\r
+        }\r
+        if (empty($this->files[$layer])) {\r
+            return $this->raiseError("unknown config file type `$layer'");\r
+        }\r
+        if ($file === null) {\r
+            $file = $this->files[$layer];\r
+        }\r
+        $data = ($data === null) ? $this->configuration[$layer] : $data;\r
+        $this->_encodeOutput($data);\r
+        $opt = array('-p', dirname($file));\r
+        if (!@System::mkDir($opt)) {\r
+            return $this->raiseError("could not create directory: " . dirname($file));\r
+        }\r
+        if (@is_file($file) && !@is_writeable($file)) {\r
+            return $this->raiseError("no write access to $file!");\r
+        }\r
+        $fp = @fopen($file, "w");\r
+        if (!$fp) {\r
+            return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed");\r
+        }\r
+        $contents = "#PEAR_Config 0.9\n" . serialize($data);\r
+        if (!@fwrite($fp, $contents)) {\r
+            return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed");\r
+        }\r
+        return true;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ _readConfigDataFrom(file)\r
+\r
+    /**\r
+     * Reads configuration data from a file and returns the parsed data\r
+     * in an array.\r
+     *\r
+     * @param string file to read from\r
+     *\r
+     * @return array configuration data or a PEAR error on failure\r
+     *\r
+     * @access private\r
+     */\r
+    function _readConfigDataFrom($file)\r
+    {\r
+        $fp = @fopen($file, "r");\r
+        if (!$fp) {\r
+            return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed");\r
+        }\r
+        $size = filesize($file);\r
+        $rt = get_magic_quotes_runtime();\r
+        set_magic_quotes_runtime(0);\r
+        if (function_exists('file_get_contents')) {\r
+            fclose($fp);\r
+            $contents = file_get_contents($file);\r
+        } else {\r
+            $contents = @fread($fp, $size);\r
+            fclose($fp);\r
+        }\r
+        if (empty($contents)) {\r
+            return $this->raiseError('Configuration file "' . $file . '" is empty');\r
+        }\r
+        \r
+        set_magic_quotes_runtime($rt);\r
+\r
+        $version = false;\r
+        if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) {\r
+            $version = $matches[1];\r
+            $contents = substr($contents, strlen($matches[0]));\r
+        } else {\r
+            // Museum config file\r
+            if (substr($contents,0,2) == 'a:') {\r
+                $version = '0.1';\r
+            }\r
+        }\r
+        if ($version && version_compare("$version", '1', '<')) {\r
+\r
+            // no '@', it is possible that unserialize\r
+            // raises a notice but it seems to block IO to\r
+            // STDOUT if a '@' is used and a notice is raise\r
+            $data = unserialize($contents);\r
+\r
+            if (!is_array($data) && !$data) {\r
+                if ($contents == serialize(false)) {\r
+                    $data = array();\r
+                } else {\r
+                    $err = $this->raiseError("PEAR_Config: bad data in $file");\r
+                    return $err;\r
+                }\r
+            }\r
+            if (!is_array($data)) {\r
+                if (strlen(trim($contents)) > 0) {\r
+                    $error = "PEAR_Config: bad data in $file";\r
+                    $err = $this->raiseError($error);\r
+                    return $err;\r
+                } else {\r
+                    $data = array();\r
+                }\r
+            }\r
+        // add parsing of newer formats here...\r
+        } else {\r
+            $err = $this->raiseError("$file: unknown version `$version'");\r
+            return $err; \r
+        }\r
+        return $data;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getConfFile(layer)\r
+    /**\r
+    * Gets the file used for storing the config for a layer\r
+    *\r
+    * @param string $layer 'user' or 'system'\r
+    */\r
+\r
+    function getConfFile($layer)\r
+    {\r
+        return $this->files[$layer];\r
+    }\r
+\r
+    // }}}\r
+\r
+    /**\r
+     * @param array information on a role as parsed from its xml file\r
+     * @return true|PEAR_Error\r
+     * @access private\r
+     */\r
+    function _addConfigVars($vars)\r
+    {\r
+        if (count($vars) > 3) {\r
+            return $this->raiseError('Roles can only define 3 new config variables or less');\r
+        }\r
+        foreach ($vars as $name => $var) {\r
+            if (!is_array($var)) {\r
+                return $this->raiseError('Configuration information must be an array');\r
+            }\r
+            if (!isset($var['type'])) {\r
+                return $this->raiseError('Configuration information must contain a type');\r
+            } else {\r
+                if (!in_array($var['type'],\r
+                      array('string', 'mask', 'password', 'directory', 'file', 'set'))) {\r
+                    return $this->raiseError(\r
+                        'Configuration type must be one of directory, file, string, ' .\r
+                        'mask, set, or password');\r
+                }\r
+            }\r
+            if (!isset($var['default'])) {\r
+                return $this->raiseError(\r
+                    'Configuration information must contain a default value ("default" index)');\r
+            } else {\r
+                if (is_array($var['default'])) {\r
+                    $real_default = '';\r
+                    foreach ($var['default'] as $config_var => $val) {\r
+                        if (strpos($config_var, 'text') === 0) {\r
+                            $real_default .= $val;\r
+                        } elseif (strpos($config_var, 'constant') === 0) {\r
+                            if (defined($val)) {\r
+                                $real_default .= constant($val);\r
+                            } else {\r
+                                return $this->raiseError(\r
+                                    'Unknown constant "' . $val . '" requested in ' .\r
+                                    'default value for configuration variable "' .\r
+                                    $name . '"');\r
+                            }\r
+                        } elseif (isset($this->configuration_info[$config_var])) {\r
+                            $real_default .=\r
+                                $this->configuration_info[$config_var]['default'];\r
+                        } else {\r
+                            return $this->raiseError(\r
+                                'Unknown request for "' . $config_var . '" value in ' .\r
+                                'default value for configuration variable "' .\r
+                                $name . '"');\r
+                        }\r
+                    }\r
+                    $var['default'] = $real_default;\r
+                }\r
+                if ($var['type'] == 'integer') {\r
+                    $var['default'] = (integer) $var['default'];\r
+                }\r
+            }\r
+            if (!isset($var['doc'])) {\r
+                return $this->raiseError(\r
+                    'Configuration information must contain a summary ("doc" index)');\r
+            }\r
+            if (!isset($var['prompt'])) {\r
+                return $this->raiseError(\r
+                    'Configuration information must contain a simple prompt ("prompt" index)');\r
+            }\r
+            if (!isset($var['group'])) {\r
+                return $this->raiseError(\r
+                    'Configuration information must contain a simple group ("group" index)');\r
+            }\r
+            if (isset($this->configuration_info[$name])) {\r
+                return $this->raiseError('Configuration variable "' . $name .\r
+                    '" already exists');\r
+            }\r
+            $this->configuration_info[$name] = $var;\r
+        }\r
+        return true;\r
+    }\r
+\r
+    // {{{ _encodeOutput(&data)\r
+\r
+    /**\r
+     * Encodes/scrambles configuration data before writing to files.\r
+     * Currently, 'password' values will be base64-encoded as to avoid\r
+     * that people spot cleartext passwords by accident.\r
+     *\r
+     * @param array (reference) array to encode values in\r
+     *\r
+     * @return bool TRUE on success\r
+     *\r
+     * @access private\r
+     */\r
+    function _encodeOutput(&$data)\r
+    {\r
+        foreach ($data as $key => $value) {\r
+            if ($key == '__channels') {\r
+                foreach ($data['__channels'] as $channel => $blah) {\r
+                    $this->_encodeOutput($data['__channels'][$channel]);\r
+                }\r
+            }\r
+            if (!isset($this->configuration_info[$key])) {\r
+                continue;\r
+            }\r
+            $type = $this->configuration_info[$key]['type'];\r
+            switch ($type) {\r
+                // we base64-encode passwords so they are at least\r
+                // not shown in plain by accident\r
+                case 'password': {\r
+                    $data[$key] = base64_encode($data[$key]);\r
+                    break;\r
+                }\r
+                case 'mask': {\r
+                    $data[$key] = octdec($data[$key]);\r
+                    break;\r
+                }\r
+            }\r
+        }\r
+        return true;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ _decodeInput(&data)\r
+\r
+    /**\r
+     * Decodes/unscrambles configuration data after reading from files.\r
+     *\r
+     * @param array (reference) array to encode values in\r
+     *\r
+     * @return bool TRUE on success\r
+     *\r
+     * @access private\r
+     *\r
+     * @see PEAR_Config::_encodeOutput\r
+     */\r
+    function _decodeInput(&$data)\r
+    {\r
+        if (!is_array($data)) {\r
+            return true;\r
+        }\r
+        foreach ($data as $key => $value) {\r
+            if ($key == '__channels') {\r
+                foreach ($data['__channels'] as $channel => $blah) {\r
+                    $this->_decodeInput($data['__channels'][$channel]);\r
+                }\r
+            }\r
+            if (!isset($this->configuration_info[$key])) {\r
+                continue;\r
+            }\r
+            $type = $this->configuration_info[$key]['type'];\r
+            switch ($type) {\r
+                case 'password': {\r
+                    $data[$key] = base64_decode($data[$key]);\r
+                    break;\r
+                }\r
+                case 'mask': {\r
+                    $data[$key] = decoct($data[$key]);\r
+                    break;\r
+                }\r
+            }\r
+        }\r
+        return true;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getDefaultChannel([layer])\r
+    /**\r
+     * Retrieve the default channel.\r
+     *\r
+     * On startup, channels are not initialized, so if the default channel is not\r
+     * pear.php.net, then initialize the config.\r
+     * @param string registry layer\r
+     * @return string|false\r
+     */\r
+    function getDefaultChannel($layer = null)\r
+    {\r
+        $ret = false;\r
+        if ($layer === null) {\r
+            foreach ($this->layers as $layer) {\r
+                if (isset($this->configuration[$layer]['default_channel'])) {\r
+                    $ret = $this->configuration[$layer]['default_channel'];\r
+                    break;\r
+                }\r
+            }\r
+        } elseif (isset($this->configuration[$layer]['default_channel'])) {\r
+            $ret = $this->configuration[$layer]['default_channel'];\r
+        }\r
+        if ($ret == 'pear.php.net' && defined('PEAR_RUNTYPE') && PEAR_RUNTYPE == 'pecl') {\r
+            $ret = 'pecl.php.net';\r
+        }\r
+        if ($ret) {\r
+            if ($ret != 'pear.php.net') {\r
+                $this->_lazyChannelSetup();\r
+            }\r
+            return $ret;\r
+        }\r
+        return PEAR_CONFIG_DEFAULT_CHANNEL;\r
+    }\r
+\r
+    // {{{ get(key, [layer])\r
+    /**\r
+     * Returns a configuration value, prioritizing layers as per the\r
+     * layers property.\r
+     *\r
+     * @param string config key\r
+     *\r
+     * @return mixed the config value, or NULL if not found\r
+     *\r
+     * @access public\r
+     */\r
+    function get($key, $layer = null, $channel = false)\r
+    {\r
+        if (!isset($this->configuration_info[$key])) {\r
+            return null;\r
+        }\r
+        if ($key == '__channels') {\r
+            return null;\r
+        }\r
+        if ($key == 'default_channel') {\r
+            return $this->getDefaultChannel($layer);\r
+        }\r
+        if (!$channel) {\r
+            $channel = $this->getDefaultChannel();\r
+        } elseif ($channel != 'pear.php.net') {\r
+            $this->_lazyChannelSetup();\r
+        }\r
+        $channel = strtolower($channel);\r
+        \r
+        $test = (in_array($key, $this->_channelConfigInfo)) ?\r
+            $this->_getChannelValue($key, $layer, $channel) :\r
+            null;\r
+        if ($test !== null) {\r
+            if ($this->_installRoot) {\r
+                if (in_array($this->getGroup($key),\r
+                      array('File Locations', 'File Locations (Advanced)')) &&\r
+                      $this->getType($key) == 'directory') {\r
+                    return $this->_prependPath($test, $this->_installRoot);\r
+                }\r
+            }\r
+            return $test;\r
+        }\r
+        if ($layer === null) {\r
+            foreach ($this->layers as $layer) {\r
+                if (isset($this->configuration[$layer][$key])) {\r
+                    $test = $this->configuration[$layer][$key];\r
+                    if ($this->_installRoot) {\r
+                        if (in_array($this->getGroup($key),\r
+                              array('File Locations', 'File Locations (Advanced)')) &&\r
+                              $this->getType($key) == 'directory') {\r
+                            return $this->_prependPath($test, $this->_installRoot);\r
+                        }\r
+                    }\r
+                    if ($key == 'preferred_mirror') {\r
+                        $reg = &$this->getRegistry();\r
+                        if (is_object($reg)) {\r
+                            $chan = &$reg->getChannel($channel);\r
+                            if (!$chan->getMirror($test) && $chan->getName() != $test) {\r
+                                return $channel; // mirror does not exist\r
+                            }\r
+                        }\r
+                    }\r
+                    return $test;\r
+                }\r
+            }\r
+        } elseif (isset($this->configuration[$layer][$key])) {\r
+            $test = $this->configuration[$layer][$key];\r
+            if ($this->_installRoot) {\r
+                if (in_array($this->getGroup($key),\r
+                      array('File Locations', 'File Locations (Advanced)')) &&\r
+                      $this->getType($key) == 'directory') {\r
+                    return $this->_prependPath($test, $this->_installRoot);\r
+                }\r
+            }\r
+            if ($key == 'preferred_mirror') {\r
+                $reg = &$this->getRegistry();\r
+                if (is_object($reg)) {\r
+                    $chan = &$reg->getChannel($channel);\r
+                    if (!$chan->getMirror($test) && $chan->getName() != $test) {\r
+                        return $channel; // mirror does not exist\r
+                    }\r
+                }\r
+            }\r
+            return $test;\r
+        }\r
+        return null;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ _getChannelValue(key, value, [layer])\r
+    /**\r
+     * Returns a channel-specific configuration value, prioritizing layers as per the\r
+     * layers property.\r
+     *\r
+     * @param string config key\r
+     *\r
+     * @return mixed the config value, or NULL if not found\r
+     *\r
+     * @access private\r
+     */\r
+    function _getChannelValue($key, $layer, $channel)\r
+    {\r
+        if ($key == '__channels' || $channel == 'pear.php.net') {\r
+            return null;\r
+        }\r
+        $ret = null;\r
+        if ($layer === null) {\r
+            foreach ($this->layers as $ilayer) {\r
+                if (isset($this->configuration[$ilayer]['__channels'][$channel][$key])) {\r
+                    $ret = $this->configuration[$ilayer]['__channels'][$channel][$key];\r
+                    break;\r
+                }\r
+            }\r
+        } elseif (isset($this->configuration[$layer]['__channels'][$channel][$key])) {\r
+            $ret = $this->configuration[$layer]['__channels'][$channel][$key];\r
+        }\r
+        if ($key == 'preferred_mirror') {\r
+            if ($ret !== null) {\r
+                $reg = &$this->getRegistry($layer);\r
+                if (is_object($reg)) {\r
+                    $chan = &$reg->getChannel($channel);\r
+                    if (!$chan->getMirror($ret) && $chan->getName() != $ret) {\r
+                        return $channel; // mirror does not exist\r
+                    }\r
+                }\r
+                return $ret;\r
+            }\r
+            if ($channel == $this->getDefaultChannel($layer)) {\r
+                return $channel; // we must use the channel name as the preferred mirror\r
+                                 // if the user has not chosen an alternate\r
+            } else {\r
+                return $this->getDefaultChannel($layer);\r
+            }\r
+        }\r
+        return $ret;\r
+    }\r
+\r
+\r
+    // }}}\r
+    // {{{ set(key, value, [layer])\r
+\r
+    /**\r
+     * Set a config value in a specific layer (defaults to 'user').\r
+     * Enforces the types defined in the configuration_info array.  An\r
+     * integer config variable will be cast to int, and a set config\r
+     * variable will be validated against its legal values.\r
+     *\r
+     * @param string config key\r
+     * @param string config value\r
+     * @param string (optional) config layer\r
+     * @param string channel to set this value for, or null for global value\r
+     * @return bool TRUE on success, FALSE on failure\r
+     */\r
+    function set($key, $value, $layer = 'user', $channel = false)\r
+    {\r
+        if ($key == '__channels') {\r
+            return false;\r
+        }\r
+        if (!isset($this->configuration[$layer])) {\r
+            return false;\r
+        }\r
+        if ($key == 'default_channel') {\r
+            // can only set this value globally\r
+            $channel = 'pear.php.net';\r
+            if ($value != 'pear.php.net') {\r
+                $this->_lazyChannelSetup($layer);\r
+            }\r
+        }\r
+        if ($key == 'preferred_mirror') {\r
+            if ($channel == '__uri') {\r
+                return false; // can't set the __uri pseudo-channel's mirror\r
+            }\r
+            $reg = &$this->getRegistry($layer);\r
+            if (is_object($reg)) {\r
+                $chan = &$reg->getChannel($channel ? $channel : 'pear.php.net');\r
+                if (!$chan->getMirror($value) && $chan->getName() != $value) {\r
+                    return false; // mirror does not exist\r
+                }\r
+            }\r
+        }\r
+        if (empty($this->configuration_info[$key])) {\r
+            return false;\r
+        }\r
+        extract($this->configuration_info[$key]);\r
+        switch ($type) {\r
+            case 'integer':\r
+                $value = (int)$value;\r
+                break;\r
+            case 'set': {\r
+                // If a valid_set is specified, require the value to\r
+                // be in the set.  If there is no valid_set, accept\r
+                // any value.\r
+                if ($valid_set) {\r
+                    reset($valid_set);\r
+                    if ((key($valid_set) === 0 && !in_array($value, $valid_set)) ||\r
+                        (key($valid_set) !== 0 && empty($valid_set[$value])))\r
+                    {\r
+                        return false;\r
+                    }\r
+                }\r
+                break;\r
+            }\r
+        }\r
+        if (!$channel) {\r
+            $channel = $this->get('default_channel', null, 'pear.php.net');\r
+        }\r
+        if (!in_array($channel, $this->_channels)) {\r
+            $this->_lazyChannelSetup($layer);\r
+            $reg = &$this->getRegistry($layer);\r
+            if ($reg) {\r
+                $channel = $reg->channelName($channel);\r
+            }\r
+            if (!in_array($channel, $this->_channels)) {\r
+                return false;\r
+            }\r
+        }\r
+        if ($channel != 'pear.php.net') {\r
+            if (in_array($key, $this->_channelConfigInfo)) {\r
+                $this->configuration[$layer]['__channels'][$channel][$key] = $value;\r
+                return true;\r
+            } else {\r
+                return false;\r
+            }\r
+        } else {\r
+            if ($key == 'default_channel') {\r
+                if (!isset($reg)) {\r
+                    $reg = &$this->getRegistry($layer);\r
+                    if (!$reg) {\r
+                        $reg = &$this->getRegistry();\r
+                    }\r
+                }\r
+                if ($reg) {\r
+                    $value = $reg->channelName($value);\r
+                }\r
+                if (!$value) {\r
+                    return false;\r
+                }\r
+            }\r
+        }\r
+        $this->configuration[$layer][$key] = $value;\r
+        if ($key == 'php_dir' && !$this->_noRegistry) {\r
+            if (!isset($this->_registry[$layer]) ||\r
+                  $value != $this->_registry[$layer]->install_dir) {\r
+                $this->_registry[$layer] = &new PEAR_Registry($value);\r
+                $this->_regInitialized[$layer] = false;\r
+                $this->_registry[$layer]->setConfig($this);\r
+            }\r
+        }\r
+        return true;\r
+    }\r
+\r
+    // }}}\r
+    function _lazyChannelSetup($uselayer = false)\r
+    {\r
+        if ($this->_noRegistry) {\r
+            return;\r
+        }\r
+        $merge = false;\r
+        foreach ($this->_registry as $layer => $p) {\r
+            if ($uselayer && $uselayer != $layer) {\r
+                continue;\r
+            }\r
+            if (!$this->_regInitialized[$layer]) {\r
+                if ($layer == 'default' && isset($this->_registry['user']) ||\r
+                      isset($this->_registry['system'])) {\r
+                    // only use the default registry if there are no alternatives\r
+                    continue;\r
+                }\r
+                if (!is_object($this->_registry[$layer])) {\r
+                    if ($phpdir = $this->get('php_dir', $layer, 'pear.php.net')) {\r
+                        $this->_registry[$layer] = &new PEAR_Registry($phpdir);\r
+                        $this->_registry[$layer]->setConfig($this);\r
+                        $this->_regInitialized[$layer] = false;\r
+                    } else {\r
+                        unset($this->_registry[$layer]);\r
+                        return;\r
+                    }\r
+                }\r
+                $this->setChannels($this->_registry[$layer]->listChannels(), $merge);\r
+                $this->_regInitialized[$layer] = true;\r
+                $merge = true;\r
+            }\r
+        }\r
+    }\r
+    // {{{ setChannels()\r
+    \r
+    /**\r
+     * Set the list of channels.\r
+     *\r
+     * This should be set via a call to {@link PEAR_Registry::listChannels()}\r
+     * @param array\r
+     * @param bool\r
+     * @return bool success of operation\r
+     */\r
+    function setChannels($channels, $merge = false)\r
+    {\r
+        if (!is_array($channels)) {\r
+            return false;\r
+        }\r
+        if ($merge) {\r
+            $this->_channels = array_merge($this->_channels, $channels);\r
+        } else {\r
+            $this->_channels = $channels;\r
+        }\r
+        foreach ($channels as $channel) {\r
+            $channel = strtolower($channel);\r
+            if ($channel == 'pear.php.net') {\r
+                continue;\r
+            }\r
+            foreach ($this->layers as $layer) {\r
+                if (!isset($this->configuration[$layer]['__channels'][$channel])\r
+                      || !is_array($this->configuration[$layer]['__channels'][$channel])) {\r
+                    $this->configuration[$layer]['__channels'][$channel] = array();\r
+                }\r
+            }\r
+        }\r
+        return true;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getType(key)\r
+\r
+    /**\r
+     * Get the type of a config value.\r
+     *\r
+     * @param string  config key\r
+     *\r
+     * @return string type, one of "string", "integer", "file",\r
+     * "directory", "set" or "password".\r
+     *\r
+     * @access public\r
+     *\r
+     */\r
+    function getType($key)\r
+    {\r
+        if (isset($this->configuration_info[$key])) {\r
+            return $this->configuration_info[$key]['type'];\r
+        }\r
+        return false;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getDocs(key)\r
+\r
+    /**\r
+     * Get the documentation for a config value.\r
+     *\r
+     * @param string  config key\r
+     *\r
+     * @return string documentation string\r
+     *\r
+     * @access public\r
+     *\r
+     */\r
+    function getDocs($key)\r
+    {\r
+        if (isset($this->configuration_info[$key])) {\r
+            return $this->configuration_info[$key]['doc'];\r
+        }\r
+        return false;\r
+    }\r
+       // }}}\r
+    // {{{ getPrompt(key)\r
+\r
+    /**\r
+     * Get the short documentation for a config value.\r
+     *\r
+     * @param string  config key\r
+     *\r
+     * @return string short documentation string\r
+     *\r
+     * @access public\r
+     *\r
+     */\r
+    function getPrompt($key)\r
+    {\r
+        if (isset($this->configuration_info[$key])) {\r
+            return $this->configuration_info[$key]['prompt'];\r
+        }\r
+        return false;\r
+    }\r
+    // }}}\r
+    // {{{ getGroup(key)\r
+\r
+    /**\r
+     * Get the parameter group for a config key.\r
+     *\r
+     * @param string  config key\r
+     *\r
+     * @return string parameter group\r
+     *\r
+     * @access public\r
+     *\r
+     */\r
+    function getGroup($key)\r
+    {\r
+        if (isset($this->configuration_info[$key])) {\r
+            return $this->configuration_info[$key]['group'];\r
+        }\r
+        return false;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getGroups()\r
+\r
+    /**\r
+     * Get the list of parameter groups.\r
+     *\r
+     * @return array list of parameter groups\r
+     *\r
+     * @access public\r
+     *\r
+     */\r
+    function getGroups()\r
+    {\r
+        $tmp = array();\r
+        foreach ($this->configuration_info as $key => $info) {\r
+            $tmp[$info['group']] = 1;\r
+        }\r
+        return array_keys($tmp);\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getGroupKeys()\r
+\r
+    /**\r
+     * Get the list of the parameters in a group.\r
+     *\r
+     * @param string $group parameter group\r
+     *\r
+     * @return array list of parameters in $group\r
+     *\r
+     * @access public\r
+     *\r
+     */\r
+    function getGroupKeys($group)\r
+    {\r
+        $keys = array();\r
+        foreach ($this->configuration_info as $key => $info) {\r
+            if ($info['group'] == $group) {\r
+                $keys[] = $key;\r
+            }\r
+        }\r
+        return $keys;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getSetValues(key)\r
+\r
+    /**\r
+     * Get the list of allowed set values for a config value.  Returns\r
+     * NULL for config values that are not sets.\r
+     *\r
+     * @param string  config key\r
+     *\r
+     * @return array enumerated array of set values, or NULL if the\r
+     *               config key is unknown or not a set\r
+     *\r
+     * @access public\r
+     *\r
+     */\r
+    function getSetValues($key)\r
+    {\r
+        if (isset($this->configuration_info[$key]) &&\r
+            isset($this->configuration_info[$key]['type']) &&\r
+            $this->configuration_info[$key]['type'] == 'set')\r
+        {\r
+            $valid_set = $this->configuration_info[$key]['valid_set'];\r
+            reset($valid_set);\r
+            if (key($valid_set) === 0) {\r
+                return $valid_set;\r
+            }\r
+            return array_keys($valid_set);\r
+        }\r
+        return null;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getKeys()\r
+\r
+    /**\r
+     * Get all the current config keys.\r
+     *\r
+     * @return array simple array of config keys\r
+     *\r
+     * @access public\r
+     */\r
+    function getKeys()\r
+    {\r
+        $keys = array();\r
+        foreach ($this->layers as $layer) {\r
+            $test = $this->configuration[$layer];\r
+            if (isset($test['__channels'])) {\r
+                foreach ($test['__channels'] as $channel => $configs) {\r
+                    $keys = array_merge($keys, $configs);\r
+                }\r
+            }\r
+            unset($test['__channels']);\r
+            $keys = array_merge($keys, $test);\r
+        }\r
+        return array_keys($keys);\r
+    }\r
+\r
+    // }}}\r
+    // {{{ remove(key, [layer])\r
+\r
+    /**\r
+     * Remove the a config key from a specific config layer.\r
+     *\r
+     * @param string config key\r
+     *\r
+     * @param string (optional) config layer\r
+     *\r
+     * @return bool TRUE on success, FALSE on failure\r
+     *\r
+     * @access public\r
+     */\r
+    function remove($key, $layer = 'user')\r
+    {\r
+        $channel = $this->getDefaultChannel();\r
+        if ($channel !== 'pear.php.net') {\r
+            if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {\r
+                unset($this->configuration[$layer]['__channels'][$channel][$key]);\r
+                return true;\r
+            }\r
+        }\r
+        if (isset($this->configuration[$layer][$key])) {\r
+            unset($this->configuration[$layer][$key]);\r
+            return true;\r
+        }\r
+        return false;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ removeLayer(layer)\r
+\r
+    /**\r
+     * Temporarily remove an entire config layer.  USE WITH CARE!\r
+     *\r
+     * @param string config key\r
+     *\r
+     * @param string (optional) config layer\r
+     *\r
+     * @return bool TRUE on success, FALSE on failure\r
+     *\r
+     * @access public\r
+     */\r
+    function removeLayer($layer)\r
+    {\r
+        if (isset($this->configuration[$layer])) {\r
+            $this->configuration[$layer] = array();\r
+            return true;\r
+        }\r
+        return false;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ store([layer])\r
+\r
+    /**\r
+     * Stores configuration data in a layer.\r
+     *\r
+     * @param string config layer to store\r
+     *\r
+     * @return bool TRUE on success, or PEAR error on failure\r
+     *\r
+     * @access public\r
+     */\r
+    function store($layer = 'user', $data = null)\r
+    {\r
+        return $this->writeConfigFile(null, $layer, $data);\r
+    }\r
+\r
+    // }}}\r
+    // {{{ toDefault(key)\r
+\r
+    /**\r
+     * Unset the user-defined value of a config key, reverting the\r
+     * value to the system-defined one.\r
+     *\r
+     * @param string config key\r
+     *\r
+     * @return bool TRUE on success, FALSE on failure\r
+     *\r
+     * @access public\r
+     */\r
+    function toDefault($key)\r
+    {\r
+        trigger_error("PEAR_Config::toDefault() deprecated, use PEAR_Config::remove() instead", E_USER_NOTICE);\r
+        return $this->remove($key, 'user');\r
+    }\r
+\r
+    // }}}\r
+    // {{{ definedBy(key)\r
+\r
+    /**\r
+     * Tells what config layer that gets to define a key.\r
+     *\r
+     * @param string config key\r
+     * @param boolean return the defining channel\r
+     *\r
+     * @return string|array the config layer, or an empty string if not found.\r
+     *\r
+     *         if $returnchannel, the return is an array array('layer' => layername,\r
+     *         'channel' => channelname), or an empty string if not found\r
+     *\r
+     * @access public\r
+     */\r
+    function definedBy($key, $returnchannel = false)\r
+    {\r
+        foreach ($this->layers as $layer) {\r
+            $channel = $this->getDefaultChannel();\r
+            if ($channel !== 'pear.php.net') {\r
+                if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {\r
+                    if ($returnchannel) {\r
+                        return array('layer' => $layer, 'channel' => $channel);\r
+                    }\r
+                    return $layer;\r
+                }\r
+            }\r
+            if (isset($this->configuration[$layer][$key])) {\r
+                if ($returnchannel) {\r
+                    return array('layer' => $layer, 'channel' => 'pear.php.net');\r
+                }\r
+                return $layer;\r
+            }\r
+        }\r
+        return '';\r
+    }\r
+\r
+    // }}}\r
+    // {{{ isDefaulted(key)\r
+\r
+    /**\r
+     * Tells whether a config value has a system-defined value.\r
+     *\r
+     * @param string   config key\r
+     *\r
+     * @return bool\r
+     *\r
+     * @access public\r
+     *\r
+     * @deprecated\r
+     */\r
+    function isDefaulted($key)\r
+    {\r
+        trigger_error("PEAR_Config::isDefaulted() deprecated, use PEAR_Config::definedBy() instead", E_USER_NOTICE);\r
+        return $this->definedBy($key) == 'system';\r
+    }\r
+\r
+    // }}}\r
+    // {{{ isDefined(key)\r
+\r
+    /**\r
+     * Tells whether a given key exists as a config value.\r
+     *\r
+     * @param string config key\r
+     *\r
+     * @return bool whether <config key> exists in this object\r
+     *\r
+     * @access public\r
+     */\r
+    function isDefined($key)\r
+    {\r
+        foreach ($this->layers as $layer) {\r
+            if (isset($this->configuration[$layer][$key])) {\r
+                return true;\r
+            }\r
+        }\r
+        return false;\r
+    }\r
+\r
+    // }}}\r
+    // {{{ isDefinedLayer(key)\r
+\r
+    /**\r
+     * Tells whether a given config layer exists.\r
+     *\r
+     * @param string config layer\r
+     *\r
+     * @return bool whether <config layer> exists in this object\r
+     *\r
+     * @access public\r
+     */\r
+    function isDefinedLayer($layer)\r
+    {\r
+        return isset($this->configuration[$layer]);\r
+    }\r
+\r
+    // }}}\r
+    // {{{ getLayers()\r
+\r
+    /**\r
+     * Returns the layers defined (except the 'default' one)\r
+     *\r
+     * @return array of the defined layers\r
+     */\r
+    function getLayers()\r
+    {\r
+        $cf = $this->configuration;\r
+        unset($cf['default']);\r
+        return array_keys($cf);\r
+    }\r
+\r
+    // }}}\r
+    // {{{ apiVersion()\r
+    function apiVersion()\r
+    {\r
+        return '1.1';\r
+    }\r
+    // }}}\r
+\r
+    /**\r
+     * @return PEAR_Registry\r
+     */\r
+    function &getRegistry($use = null)\r
+    {\r
+        if ($use === null) {\r
+            $layer = 'user';\r
+        } else {\r
+            $layer = $use;\r
+        }\r
+        if (isset($this->_registry[$layer])) {\r
+            return $this->_registry[$layer];\r
+        } elseif ($use === null && isset($this->_registry['system'])) {\r
+            return $this->_registry['system'];\r
+        } elseif ($use === null && isset($this->_registry['default'])) {\r
+            return $this->_registry['default'];\r
+        } elseif ($use) {\r
+            $a = false;\r
+            return $a;\r
+        } else {\r
+            // only go here if null was passed in\r
+            die("CRITICAL ERROR: Registry could not be initialized from any value");\r
+        }\r
+    }\r
+    /**\r
+     * This is to allow customization like the use of installroot\r
+     * @param PEAR_Registry\r
+     * @return bool\r
+     */\r
+    function setRegistry(&$reg, $layer = 'user')\r
+    {\r
+        if ($this->_noRegistry) {\r
+            return false;\r
+        }\r
+        if (!in_array($layer, array('user', 'system'))) {\r
+            return false;\r
+        }\r
+        $this->_registry[$layer] = &$reg;\r
+        if (is_object($reg)) {\r
+            $this->_registry[$layer]->setConfig($this);\r
+        }\r
+        return true;\r
+    }\r
+\r
+    function noRegistry()\r
+    {\r
+        $this->_noRegistry = true;\r
+    }\r
+\r
+    /**\r
+     * @return PEAR_Remote\r
+     */\r
+    function &getRemote()\r
+    {\r
+        $remote = &new PEAR_Remote($this);\r
+        return $remote;\r
+    }\r
+\r
+    /**\r
+     * @return PEAR_REST\r
+     */\r
+    function &getREST($version, $options = array())\r
+    {\r
+        $version = str_replace('.', '', $version);\r
+        if (!class_exists($class = 'PEAR_REST_' . $version)) {\r
+            require_once 'PEAR/REST/' . $version . '.php';\r
+        }\r
+        $remote = &new $class($this, $options);\r
+        return $remote;\r
+    }\r
+\r
+    /**\r
+     * The ftp server is set in {@link readFTPConfigFile()}.  It exists only if a\r
+     * remote configuration file has been specified\r
+     * @return PEAR_FTP|false\r
+     */\r
+    function &getFTP()\r
+    {\r
+        if (isset($this->_ftp)) {\r
+            return $this->_ftp;\r
+        } else {\r
+            $a = false;\r
+            return $a;\r
+        }\r
+    }\r
+\r
+    // {{{ _prependPath($path, $prepend)\r
+\r
+    function _prependPath($path, $prepend)\r
+    {\r
+        if (strlen($prepend) > 0) {\r
+            if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {\r
+                if (preg_match('/^[a-z]:/i', $prepend)) {\r
+                    $prepend = substr($prepend, 2);\r
+                } elseif ($prepend{0} != '\\') {\r
+                    $prepend = "\\$prepend";\r
+                }\r
+                $path = substr($path, 0, 2) . $prepend . substr($path, 2);\r
+            } else {\r
+                $path = $prepend . $path;\r
+            }\r
+        }\r
+        return $path;\r
+    }\r
+    // }}}\r
+\r
+    /**\r
+     * @param string|false installation directory to prepend to all _dir variables, or false to\r
+     *                     disable\r
+     */\r
+    function setInstallRoot($root)\r
+    {\r
+        if (substr($root, -1) == DIRECTORY_SEPARATOR) {\r
+            $root = substr($root, 0, -1);\r
+        }\r
+        $old = $this->_installRoot;\r
+        $this->_installRoot = $root;\r
+        if (($old != $root) && !$this->_noRegistry) {\r
+            foreach (array_keys($this->_registry) as $layer) {\r
+                if ($layer == 'ftp' || !isset($this->_registry[$layer])) {\r
+                    continue;\r
+                }\r
+                $this->_registry[$layer] =\r
+                    &new PEAR_Registry($this->get('php_dir', $layer, 'pear.php.net'));\r
+                $this->_registry[$layer]->setConfig($this);\r
+                $this->_regInitialized[$layer] = false;\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+?>\r
diff --git a/include/classes/XML/XML_HTMLSax/PEAR/Remote.php b/include/classes/XML/XML_HTMLSax/PEAR/Remote.php
new file mode 100644 (file)
index 0000000..12d6682
--- /dev/null
@@ -0,0 +1,519 @@
+<?php\r
+/**\r
+ * PEAR_Remote\r
+ *\r
+ * PHP versions 4 and 5\r
+ *\r
+ * LICENSE: This source file is subject to version 3.0 of the PHP license\r
+ * that is available through the world-wide-web at the following URI:\r
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of\r
+ * the PHP License and are unable to obtain it through the web, please\r
+ * send a note to license@php.net so we can mail you a copy immediately.\r
+ *\r
+ * @category   pear\r
+ * @package    PEAR\r
+ * @author     Stig Bakken <ssb@php.net>\r
+ * @author     Greg Beaver <cellog@php.net>\r
+ * @copyright  1997-2008 The PHP Group\r
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0\r
+ * @version    CVS: $Id$\r
+ * @link       http://pear.php.net/package/PEAR\r
+ * @since      File available since Release 0.1\r
+ */\r
+\r
+/**\r
+ * needed for PEAR_Error\r
+ */\r
+require_once 'PEAR.php';\r
+require_once 'PEAR/Config.php';\r
+\r
+/**\r
+ * This is a class for doing remote operations against the central\r
+ * PEAR database.\r
+ *\r
+ * @nodep XML_RPC_Value\r
+ * @nodep XML_RPC_Message\r
+ * @nodep XML_RPC_Client\r
+ * @category   pear\r
+ * @package    PEAR\r
+ * @author     Stig Bakken <ssb@php.net>\r
+ * @author     Greg Beaver <cellog@php.net>\r
+ * @copyright  1997-2008 The PHP Group\r
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0\r
+ * @version    Release: 1.4.4\r
+ * @link       http://pear.php.net/package/PEAR\r
+ * @since      Class available since Release 0.1\r
+ */\r
+class PEAR_Remote extends PEAR\r
+{\r
+    // {{{ properties\r
+\r
+    var $config = null;\r
+    var $cache  = null;\r
+    /**\r
+     * @var PEAR_Registry\r
+     * @access private\r
+     */\r
+    var $_registry;\r
+\r
+    // }}}\r
+\r
+    // {{{ PEAR_Remote(config_object)\r
+\r
+    function PEAR_Remote(&$config)\r
+    {\r
+        $this->PEAR();\r
+        $this->config = &$config;\r
+        $this->_registry = &$this->config->getRegistry();\r
+    }\r
+\r
+    // }}}\r
+    // {{{ setRegistry()\r
+    \r
+    function setRegistry(&$reg)\r
+    {\r
+        $this->_registry = &$reg;\r
+    }\r
+    // }}}\r
+    // {{{ getCache()\r
+\r
+\r
+    function getCache($args)\r
+    {\r
+        $id       = md5(serialize($args));\r
+        $cachedir = $this->config->get('cache_dir');\r
+        $filename = $cachedir . DIRECTORY_SEPARATOR . 'xmlrpc_cache_' . $id;\r
+        if (!file_exists($filename)) {\r
+            return null;\r
+        }\r
+\r
+        $fp = fopen($filename, 'rb');\r
+        if (!$fp) {\r
+            return null;\r
+        }\r
+        if (function_exists('file_get_contents')) {\r
+            fclose($fp);\r
+            $content = file_get_contents($filename);\r
+        } else {\r
+            $content  = fread($fp, filesize($filename));\r
+            fclose($fp);\r
+        }\r
+        $result   = array(\r
+            'age'        => time() - filemtime($filename),\r
+            'lastChange' => filemtime($filename),\r
+            'content'    => unserialize($content),\r
+            );\r
+        return $result;\r
+    }\r
+\r
+    // }}}\r
+\r
+    // {{{ saveCache()\r
+\r
+    function saveCache($args, $data)\r
+    {\r
+        $id       = md5(serialize($args));\r
+        $cachedir = $this->config->get('cache_dir');\r
+        if (!file_exists($cachedir)) {\r
+            System::mkdir(array('-p', $cachedir));\r
+        }\r
+        $filename = $cachedir.'/xmlrpc_cache_'.$id;\r
+\r
+        $fp = @fopen($filename, "wb");\r
+        if ($fp) {\r
+            fwrite($fp, serialize($data));\r
+            fclose($fp);\r
+        }\r
+    }\r
+\r
+    // }}}\r
+\r
+    // {{{ clearCache()\r
+\r
+    function clearCache($method, $args)\r
+    {\r
+        array_unshift($args, $method);\r
+        array_unshift($args, $this->config->get('default_channel')); // cache by channel\r
+        $id       = md5(serialize($args));\r
+        $cachedir = $this->config->get('cache_dir');\r
+        $filename = $cachedir.'/xmlrpc_cache_'.$id;\r
+        if (file_exists($filename)) {\r
+            @unlink($filename);\r
+        }\r
+    }\r
+\r
+    // }}}\r
+    // {{{ call(method, [args...])\r
+\r
+    function call($method)\r
+    {\r
+        $_args = $args = func_get_args();\r
+\r
+        $server_channel = $this->config->get('default_channel');\r
+        $channel = $this->_registry->getChannel($server_channel);\r
+        if ($channel) {\r
+            $mirror = $this->config->get('preferred_mirror');\r
+            if ($channel->getMirror($mirror)) {\r
+                if ($channel->supports('xmlrpc', $method, $mirror)) {\r
+                    $server_channel = $server_host = $mirror; // use the preferred mirror\r
+                    $server_port = $channel->getPort($mirror);\r
+                } elseif (!$channel->supports('xmlrpc', $method)) {\r
+                    return $this->raiseError("Channel $server_channel does not " .\r
+                        "support xml-rpc method $method");\r
+                }\r
+            }\r
+            if (!isset($server_host)) {\r
+                if (!$channel->supports('xmlrpc', $method)) {\r
+                    return $this->raiseError("Channel $server_channel does not support " .\r
+                        "xml-rpc method $method");\r
+                } else {\r
+                    $server_host = $server_channel;\r
+                    $server_port = $channel->getPort();\r
+                }\r
+            }\r
+        } else {\r
+            return $this->raiseError("Unknown channel '$server_channel'");\r
+        }\r
+\r
+        array_unshift($_args, $server_channel); // cache by channel\r
+        $this->cache = $this->getCache($_args);\r
+        $cachettl = $this->config->get('cache_ttl');\r
+        // If cache is newer than $cachettl seconds, we use the cache!\r
+        if ($this->cache !== null && $this->cache['age'] < $cachettl) {\r
+            return $this->cache['content'];\r
+        }\r
+        if (extension_loaded("xmlrpc")) {\r
+            $result = call_user_func_array(array(&$this, 'call_epi'), $args);\r
+            if (!PEAR::isError($result)) {\r
+                $this->saveCache($_args, $result);\r
+            }\r
+            return $result;\r
+        } elseif (!@include_once 'XML/RPC.php') {\r
+            return $this->raiseError("For this remote PEAR operation you need to load the xmlrpc extension or install XML_RPC");\r
+        }\r
+\r
+        array_shift($args);\r
+        $username = $this->config->get('username');\r
+        $password = $this->config->get('password');\r
+        $eargs = array();\r
+        foreach($args as $arg) {\r
+            $eargs[] = $this->_encode($arg);\r
+        }\r
+        $f = new XML_RPC_Message($method, $eargs);\r
+        if ($this->cache !== null) {\r
+            $maxAge = '?maxAge='.$this->cache['lastChange'];\r
+        } else {\r
+            $maxAge = '';\r
+        }\r
+        $proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';\r
+        if ($proxy = parse_url($this->config->get('http_proxy'))) {\r
+            $proxy_host = @$proxy['host'];\r
+            if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') {\r
+                $proxy_host = 'https://' . $proxy_host;\r
+            }\r
+            $proxy_port = @$proxy['port'];\r
+            $proxy_user = @urldecode(@$proxy['user']);\r
+            $proxy_pass = @urldecode(@$proxy['pass']);\r
+        }\r
+        $shost = $server_host;\r
+        if ($channel->getSSL()) {\r
+            $shost = "https://$shost";\r
+        }\r
+        $c = new XML_RPC_Client('/' . $channel->getPath('xmlrpc')\r
+            . $maxAge, $shost, $server_port, $proxy_host, $proxy_port,\r
+            $proxy_user, $proxy_pass);\r
+        if ($username && $password) {\r
+            $c->setCredentials($username, $password);\r
+        }\r
+        if ($this->config->get('verbose') >= 3) {\r
+            $c->setDebug(1);\r
+        }\r
+        $r = $c->send($f);\r
+        if (!$r) {\r
+            return $this->raiseError("XML_RPC send failed");\r
+        }\r
+        $v = $r->value();\r
+        if ($e = $r->faultCode()) {\r
+            if ($e == $GLOBALS['XML_RPC_err']['http_error'] && strstr($r->faultString(), '304 Not Modified') !== false) {\r
+                return $this->cache['content'];\r
+            }\r
+            return $this->raiseError($r->faultString(), $e);\r
+        }\r
+\r
+        $result = XML_RPC_decode($v);\r
+        $this->saveCache($_args, $result);\r
+        return $result;\r
+    }\r
+\r
+    // }}}\r
+\r
+    // {{{ call_epi(method, [args...])\r
+\r
+    function call_epi($method)\r
+    {\r
+        do {\r
+            if (extension_loaded("xmlrpc")) {\r
+                break;\r
+            }\r
+            if (OS_WINDOWS) {\r
+                $ext = 'dll';\r
+            } elseif (PHP_OS == 'HP-UX') {\r
+                $ext = 'sl';\r
+            } elseif (PHP_OS == 'AIX') {\r
+                $ext = 'a';\r
+            } else {\r
+                $ext = 'so';\r
+            }\r
+            $ext = OS_WINDOWS ? 'dll' : 'so';\r
+            @dl("xmlrpc-epi.$ext");\r
+            if (extension_loaded("xmlrpc")) {\r
+                break;\r
+            }\r
+            @dl("xmlrpc.$ext");\r
+            if (extension_loaded("xmlrpc")) {\r
+                break;\r
+            }\r
+            return $this->raiseError("unable to load xmlrpc extension");\r
+        } while (false);\r
+        $server_channel = $this->config->get('default_channel');\r
+        $channel = $this->_registry->getChannel($server_channel);\r
+        if ($channel) {\r
+            $mirror = $this->config->get('preferred_mirror');\r
+            if ($channel->getMirror($mirror)) {\r
+                if ($channel->supports('xmlrpc', $method, $mirror)) {\r
+                    $server_channel = $server_host = $mirror; // use the preferred mirror\r
+                    $server_port = $channel->getPort($mirror);\r
+                } elseif (!$channel->supports('xmlrpc', $method)) {\r
+                    return $this->raiseError("Channel $server_channel does not " .\r
+                        "support xml-rpc method $method");\r
+                }\r
+            }\r
+            if (!isset($server_host)) {\r
+                if (!$channel->supports('xmlrpc', $method)) {\r
+                    return $this->raiseError("Channel $server_channel does not support " .\r
+                        "xml-rpc method $method");\r
+                } else {\r
+                    $server_host = $server_channel;\r
+                    $server_port = $channel->getPort();\r
+                }\r
+            }\r
+        } else {\r
+            return $this->raiseError("Unknown channel '$server_channel'");\r
+        }\r
+        $params = func_get_args();\r
+        array_shift($params);\r
+        $method = str_replace("_", ".", $method);\r
+        $request = xmlrpc_encode_request($method, $params);\r
+        if ($http_proxy = $this->config->get('http_proxy')) {\r
+            $proxy = parse_url($http_proxy);\r
+            $proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';\r
+            $proxy_host = @$proxy['host'];\r
+            if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') {\r
+                $proxy_host = 'ssl://' . $proxy_host;\r
+            }\r
+            $proxy_port = @$proxy['port'];\r
+            $proxy_user = @urldecode(@$proxy['user']);\r
+            $proxy_pass = @urldecode(@$proxy['pass']);\r
+            $fp = @fsockopen($proxy_host, $proxy_port);\r
+            $use_proxy = true;\r
+            if ($channel->getSSL()) {\r
+                $server_host = "https://$server_host";\r
+            }\r
+        } else {\r
+            $use_proxy = false;\r
+            $ssl = $channel->getSSL();\r
+            $fp = @fsockopen(($ssl ? 'ssl://' : '') . $server_host, $server_port);\r
+            if (!$fp) {\r
+                $server_host = "$ssl$server_host"; // for error-reporting\r
+            }\r
+        }\r
+        if (!$fp && $http_proxy) {\r
+            return $this->raiseError("PEAR_Remote::call: fsockopen(`$proxy_host', $proxy_port) failed");\r
+        } elseif (!$fp) {\r
+            return $this->raiseError("PEAR_Remote::call: fsockopen(`$server_host', $server_port) failed");\r
+        }\r
+        $len = strlen($request);\r
+        $req_headers = "Host: $server_host:$server_port\r\n" .\r
+             "Content-type: text/xml\r\n" .\r
+             "Content-length: $len\r\n";\r
+        $username = $this->config->get('username');\r
+        $password = $this->config->get('password');\r
+        if ($username && $password) {\r
+            $req_headers .= "Cookie: PEAR_USER=$username; PEAR_PW=$password\r\n";\r
+            $tmp = base64_encode("$username:$password");\r
+            $req_headers .= "Authorization: Basic $tmp\r\n";\r
+        }\r
+        if ($this->cache !== null) {\r
+            $maxAge = '?maxAge='.$this->cache['lastChange'];\r
+        } else {\r
+            $maxAge = '';\r
+        }\r
+\r
+        if ($use_proxy && $proxy_host != '' && $proxy_user != '') {\r
+            $req_headers .= 'Proxy-Authorization: Basic '\r
+                .base64_encode($proxy_user.':'.$proxy_pass)\r
+                ."\r\n";\r
+        }\r
+\r
+        if ($this->config->get('verbose') > 3) {\r
+            print "XMLRPC REQUEST HEADERS:\n";\r
+            var_dump($req_headers);\r
+            print "XMLRPC REQUEST BODY:\n";\r
+            var_dump($request);\r
+        }\r
+\r
+        if ($use_proxy && $proxy_host != '') {\r
+            $post_string = "POST http://".$server_host;\r
+            if ($proxy_port > '') {\r
+                $post_string .= ':'.$server_port;\r
+            }\r
+        } else {\r
+            $post_string = "POST ";\r
+        }\r
+\r
+        $path = '/' . $channel->getPath('xmlrpc');\r
+        fwrite($fp, ($post_string . $path . "$maxAge HTTP/1.0\r\n$req_headers\r\n$request"));\r
+        $response = '';\r
+        $line1 = fgets($fp, 2048);\r
+        if (!preg_match('!^HTTP/[0-9\.]+ (\d+) (.*)!', $line1, $matches)) {\r
+            return $this->raiseError("PEAR_Remote: invalid HTTP response from XML-RPC server");\r
+        }\r
+        switch ($matches[1]) {\r
+            case "200": // OK\r
+                break;\r
+            case "304": // Not Modified\r
+                return $this->cache['content'];\r
+            case "401": // Unauthorized\r
+                if ($username && $password) {\r
+                    return $this->raiseError("PEAR_Remote ($server_host:$server_port) " .\r
+                        ": authorization failed", 401);\r
+                } else {\r
+                    return $this->raiseError("PEAR_Remote ($server_host:$server_port) " .\r
+                        ": authorization required, please log in first", 401);\r
+                }\r
+            default:\r
+                return $this->raiseError("PEAR_Remote ($server_host:$server_port) : " .\r
+                    "unexpected HTTP response", (int)$matches[1], null, null,\r
+                    "$matches[1] $matches[2]");\r
+        }\r
+        while (trim(fgets($fp, 2048)) != ''); // skip rest of headers\r
+        while ($chunk = fread($fp, 10240)) {\r
+            $response .= $chunk;\r
+        }\r
+        fclose($fp);\r
+        if ($this->config->get('verbose') > 3) {\r
+            print "XMLRPC RESPONSE:\n";\r
+            var_dump($response);\r
+        }\r
+        $ret = xmlrpc_decode($response);\r
+        if (is_array($ret) && isset($ret['__PEAR_TYPE__'])) {\r
+            if ($ret['__PEAR_TYPE__'] == 'error') {\r
+                if (isset($ret['__PEAR_CLASS__'])) {\r
+                    $class = $ret['__PEAR_CLASS__'];\r
+                } else {\r
+                    $class = "PEAR_Error";\r
+                }\r
+                if ($ret['code']     === '') $ret['code']     = null;\r
+                if ($ret['message']  === '') $ret['message']  = null;\r
+                if ($ret['userinfo'] === '') $ret['userinfo'] = null;\r
+                if (strtolower($class) == 'db_error') {\r
+                    $ret = $this->raiseError(PEAR::errorMessage($ret['code']),\r
+                                             $ret['code'], null, null,\r
+                                             $ret['userinfo']);\r
+                } else {\r
+                    $ret = $this->raiseError($ret['message'], $ret['code'],\r
+                                             null, null, $ret['userinfo']);\r
+                }\r
+            }\r
+        } elseif (is_array($ret) && sizeof($ret) == 1 && isset($ret[0])\r
+                  && is_array($ret[0]) &&\r
+                  !empty($ret[0]['faultString']) &&\r
+                  !empty($ret[0]['faultCode'])) {\r
+            extract($ret[0]);\r
+            $faultString = "XML-RPC Server Fault: " .\r
+                 str_replace("\n", " ", $faultString);\r
+            return $this->raiseError($faultString, $faultCode);\r
+        } elseif (is_array($ret) && sizeof($ret) == 2 && !empty($ret['faultString']) &&\r
+              !empty($ret['faultCode'])) {\r
+            extract($ret);\r
+            $faultString = "XML-RPC Server Fault: " .\r
+                 str_replace("\n", " ", $faultString);\r
+            return $this->raiseError($faultString, $faultCode);\r
+        }\r
+        return $ret;\r
+    }\r
+\r
+    // }}}\r
+\r
+    // {{{ _encode\r
+\r
+    // a slightly extended version of XML_RPC_encode\r
+    function _encode($php_val)\r
+    {\r
+        global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double;\r
+        global $XML_RPC_String, $XML_RPC_Array, $XML_RPC_Struct;\r
+\r
+        $type = gettype($php_val);\r
+        $xmlrpcval = new XML_RPC_Value;\r
+\r
+        switch($type) {\r
+            case "array":\r
+                reset($php_val);\r
+                $firstkey = key($php_val);\r
+                end($php_val);\r
+                $lastkey = key($php_val);\r
+                reset($php_val);\r
+                if ($firstkey === 0 && is_int($lastkey) &&\r
+                    ($lastkey + 1) == count($php_val)) {\r
+                    $is_continuous = true;\r
+                    reset($php_val);\r
+                    $size = count($php_val);\r
+                    for ($expect = 0; $expect < $size; $expect++, next($php_val)) {\r
+                        if (key($php_val) !== $expect) {\r
+                            $is_continuous = false;\r
+                            break;\r
+                        }\r
+                    }\r
+                    if ($is_continuous) {\r
+                        reset($php_val);\r
+                        $arr = array();\r
+                        while (list($k, $v) = each($php_val)) {\r
+                            $arr[$k] = $this->_encode($v);\r
+                        }\r
+                        $xmlrpcval->addArray($arr);\r
+                        break;\r
+                    }\r
+                }\r
+                // fall though if not numerical and continuous\r
+            case "object":\r
+                $arr = array();\r
+                while (list($k, $v) = each($php_val)) {\r
+                    $arr[$k] = $this->_encode($v);\r
+                }\r
+                $xmlrpcval->addStruct($arr);\r
+                break;\r
+            case "integer":\r
+                $xmlrpcval->addScalar($php_val, $XML_RPC_Int);\r
+                break;\r
+            case "double":\r
+                $xmlrpcval->addScalar($php_val, $XML_RPC_Double);\r
+                break;\r
+            case "string":\r
+            case "NULL":\r
+                $xmlrpcval->addScalar($php_val, $XML_RPC_String);\r
+                break;\r
+            case "boolean":\r
+                $xmlrpcval->addScalar($php_val, $XML_RPC_Boolean);\r
+                break;\r
+            case "unknown type":\r
+            default:\r
+                return null;\r
+        }\r
+        return $xmlrpcval;\r
+    }\r
+\r
+    // }}}\r
+\r
+}\r
+\r
+?>\r
diff --git a/include/classes/XML/XML_HTMLSax/System.php b/include/classes/XML/XML_HTMLSax/System.php
new file mode 100644 (file)
index 0000000..de4fe38
--- /dev/null
@@ -0,0 +1,580 @@
+<?php\r
+/**\r
+ * File/Directory manipulation\r
+ *\r
+ * PHP versions 4 and 5\r
+ *\r
+ * LICENSE: This source file is subject to version 3.0 of the PHP license\r
+ * that is available through the world-wide-web at the following URI:\r
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of\r
+ * the PHP License and are unable to obtain it through the web, please\r
+ * send a note to license@php.net so we can mail you a copy immediately.\r
+ *\r
+ * @category   pear\r
+ * @package    System\r
+ * @author     Tomas V.V.Cox <cox@idecnet.com>\r
+ * @copyright  1997-2008 The PHP Group\r
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0\r
+ * @version    CVS: $Id$\r
+ * @link       http://pear.php.net/package/PEAR\r
+ * @since      File available since Release 0.1\r
+ */\r
+\r
+/**\r
+ * base class\r
+ */\r
+require_once 'PEAR.php';\r
+require_once 'Console/Getopt.php';\r
+\r
+$GLOBALS['_System_temp_files'] = array();\r
+\r
+/**\r
+* System offers cross plattform compatible system functions\r
+*\r
+* Static functions for different operations. Should work under\r
+* Unix and Windows. The names and usage has been taken from its respectively\r
+* GNU commands. The functions will return (bool) false on error and will\r
+* trigger the error with the PHP trigger_error() function (you can silence\r
+* the error by prefixing a '@' sign after the function call).\r
+*\r
+* Documentation on this class you can find in:\r
+* http://pear.php.net/manual/\r
+*\r
+* Example usage:\r
+* if (!@System::rm('-r file1 dir1')) {\r
+*    print "could not delete file1 or dir1";\r
+* }\r
+*\r
+* In case you need to to pass file names with spaces,\r
+* pass the params as an array:\r
+*\r
+* System::rm(array('-r', $file1, $dir1));\r
+*\r
+* @category   pear\r
+* @package    System\r
+* @author     Tomas V.V. Cox <cox@idecnet.com>\r
+* @copyright  1997-2008 The PHP Group\r
+* @license    http://www.php.net/license/3_0.txt  PHP License 3.0\r
+* @version    Release: 1.4.4\r
+* @link       http://pear.php.net/package/PEAR\r
+* @since      Class available since Release 0.1\r
+*/\r
+class System\r
+{\r
+    /**\r
+    * returns the commandline arguments of a function\r
+    *\r
+    * @param    string  $argv           the commandline\r
+    * @param    string  $short_options  the allowed option short-tags\r
+    * @param    string  $long_options   the allowed option long-tags\r
+    * @return   array   the given options and there values\r
+    * @access private\r
+    */\r
+    function _parseArgs($argv, $short_options, $long_options = null)\r
+    {\r
+        if (!is_array($argv) && $argv !== null) {\r
+            $argv = preg_split('/\s+/', $argv, -1, PREG_SPLIT_NO_EMPTY);\r
+        }\r
+        return Console_Getopt::getopt2($argv, $short_options);\r
+    }\r
+\r
+    /**\r
+    * Output errors with PHP trigger_error(). You can silence the errors\r
+    * with prefixing a "@" sign to the function call: @System::mkdir(..);\r
+    *\r
+    * @param mixed $error a PEAR error or a string with the error message\r
+    * @return bool false\r
+    * @access private\r
+    */\r
+    function raiseError($error)\r
+    {\r
+        if (PEAR::isError($error)) {\r
+            $error = $error->getMessage();\r
+        }\r
+        trigger_error($error, E_USER_WARNING);\r
+        return false;\r
+    }\r
+\r
+    /**\r
+    * Creates a nested array representing the structure of a directory\r
+    *\r
+    * System::_dirToStruct('dir1', 0) =>\r
+    *   Array\r
+    *    (\r
+    *    [dirs] => Array\r
+    *        (\r
+    *            [0] => dir1\r
+    *        )\r
+    *\r
+    *    [files] => Array\r
+    *        (\r
+    *            [0] => dir1/file2\r
+    *            [1] => dir1/file3\r
+    *        )\r
+    *    )\r
+    * @param    string  $sPath      Name of the directory\r
+    * @param    integer $maxinst    max. deep of the lookup\r
+    * @param    integer $aktinst    starting deep of the lookup\r
+    * @return   array   the structure of the dir\r
+    * @access   private\r
+    */\r
+\r
+    function _dirToStruct($sPath, $maxinst, $aktinst = 0)\r
+    {\r
+        $struct = array('dirs' => array(), 'files' => array());\r
+        if (($dir = @opendir($sPath)) === false) {\r
+            System::raiseError("Could not open dir $sPath");\r
+            return $struct; // XXX could not open error\r
+        }\r
+        $struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ?\r
+        $list = array();\r
+        while (false !== ($file = readdir($dir))) {\r
+            if ($file != '.' && $file != '..') {\r
+                $list[] = $file;\r
+            }\r
+        }\r
+        closedir($dir);\r
+        sort($list);\r
+        if ($aktinst < $maxinst || $maxinst == 0) {\r
+            foreach($list as $val) {\r
+                $path = $sPath . DIRECTORY_SEPARATOR . $val;\r
+                if (is_dir($path) && !is_link($path)) {\r
+                    $tmp = System::_dirToStruct($path, $maxinst, $aktinst+1);\r
+                    $struct = array_merge_recursive($tmp, $struct);\r
+                } else {\r
+                    $struct['files'][] = $path;\r
+                }\r
+            }\r
+        }\r
+        return $struct;\r
+    }\r
+\r
+    /**\r
+    * Creates a nested array representing the structure of a directory and files\r
+    *\r
+    * @param    array $files Array listing files and dirs\r
+    * @return   array\r
+    * @see System::_dirToStruct()\r
+    */\r
+    function _multipleToStruct($files)\r
+    {\r
+        $struct = array('dirs' => array(), 'files' => array());\r
+        settype($files, 'array');\r
+        foreach ($files as $file) {\r
+            if (is_dir($file) && !is_link($file)) {\r
+                $tmp = System::_dirToStruct($file, 0);\r
+                $struct = array_merge_recursive($tmp, $struct);\r
+            } else {\r
+                $struct['files'][] = $file;\r
+            }\r
+        }\r
+        return $struct;\r
+    }\r
+\r
+    /**\r
+    * The rm command for removing files.\r
+    * Supports multiple files and dirs and also recursive deletes\r
+    *\r
+    * @param    string  $args   the arguments for rm\r
+    * @return   mixed   PEAR_Error or true for success\r
+    * @access   public\r
+    */\r
+    function rm($args)\r
+    {\r
+        $opts = System::_parseArgs($args, 'rf'); // "f" do nothing but like it :-)\r
+        if (PEAR::isError($opts)) {\r
+            return System::raiseError($opts);\r
+        }\r
+        foreach($opts[0] as $opt) {\r
+            if ($opt[0] == 'r') {\r
+                $do_recursive = true;\r
+            }\r
+        }\r
+        $ret = true;\r
+        if (isset($do_recursive)) {\r
+            $struct = System::_multipleToStruct($opts[1]);\r
+            foreach($struct['files'] as $file) {\r
+                if (!@unlink($file)) {\r
+                    $ret = false;\r
+                }\r
+            }\r
+            foreach($struct['dirs'] as $dir) {\r
+                if (!@rmdir($dir)) {\r
+                    $ret = false;\r
+                }\r
+            }\r
+        } else {\r
+            foreach ($opts[1] as $file) {\r
+                $delete = (is_dir($file)) ? 'rmdir' : 'unlink';\r
+                if (!@$delete($file)) {\r
+                    $ret = false;\r
+                }\r
+            }\r
+        }\r
+        return $ret;\r
+    }\r
+\r
+    /**\r
+    * Make directories.\r
+    *\r
+    * The -p option will create parent directories\r
+    * @param    string  $args    the name of the director(y|ies) to create\r
+    * @return   bool    True for success\r
+    * @access   public\r
+    */\r
+    function mkDir($args)\r
+    {\r
+        $opts = System::_parseArgs($args, 'pm:');\r
+        if (PEAR::isError($opts)) {\r
+            return System::raiseError($opts);\r
+        }\r
+        $mode = 0777; // default mode\r
+        foreach($opts[0] as $opt) {\r
+            if ($opt[0] == 'p') {\r
+                $create_parents = true;\r
+            } elseif($opt[0] == 'm') {\r
+                // if the mode is clearly an octal number (starts with 0)\r
+                // convert it to decimal\r
+                if (strlen($opt[1]) && $opt[1]{0} == '0') {\r
+                    $opt[1] = octdec($opt[1]);\r
+                } else {\r
+                    // convert to int\r
+                    $opt[1] += 0;\r
+                }\r
+                $mode = $opt[1];\r
+            }\r
+        }\r
+        $ret = true;\r
+        if (isset($create_parents)) {\r
+            foreach($opts[1] as $dir) {\r
+                $dirstack = array();\r
+                while (!@is_dir($dir) && $dir != DIRECTORY_SEPARATOR) {\r
+                    array_unshift($dirstack, $dir);\r
+                    $dir = dirname($dir);\r
+                }\r
+                while ($newdir = array_shift($dirstack)) {\r
+                    if (!is_writeable(dirname($newdir))) {\r
+                        $ret = false;\r
+                        break;\r
+                    }\r
+                    if (!mkdir($newdir, $mode)) {\r
+                        $ret = false;\r
+                    }\r
+                }\r
+            }\r
+        } else {\r
+            foreach($opts[1] as $dir) {\r
+                if (!@is_dir($dir) && !mkdir($dir, $mode)) {\r
+                    $ret = false;\r
+                }\r
+            }\r
+        }\r
+        return $ret;\r
+    }\r
+\r
+    /**\r
+    * Concatenate files\r
+    *\r
+    * Usage:\r
+    * 1) $var = System::cat('sample.txt test.txt');\r
+    * 2) System::cat('sample.txt test.txt > final.txt');\r
+    * 3) System::cat('sample.txt test.txt >> final.txt');\r
+    *\r
+    * Note: as the class use fopen, urls should work also (test that)\r
+    *\r
+    * @param    string  $args   the arguments\r
+    * @return   boolean true on success\r
+    * @access   public\r
+    */\r
+    function &cat($args)\r
+    {\r
+        $ret = null;\r
+        $files = array();\r
+        if (!is_array($args)) {\r
+            $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);\r
+        }\r
+        for($i=0; $i < count($args); $i++) {\r
+            if ($args[$i] == '>') {\r
+                $mode = 'wb';\r
+                $outputfile = $args[$i+1];\r
+                break;\r
+            } elseif ($args[$i] == '>>') {\r
+                $mode = 'ab+';\r
+                $outputfile = $args[$i+1];\r
+                break;\r
+            } else {\r
+                $files[] = $args[$i];\r
+            }\r
+        }\r
+        if (isset($mode)) {\r
+            if (!$outputfd = fopen($outputfile, $mode)) {\r
+                $err = System::raiseError("Could not open $outputfile");\r
+                return $err;\r
+            }\r
+            $ret = true;\r
+        }\r
+        foreach ($files as $file) {\r
+            if (!$fd = fopen($file, 'r')) {\r
+                System::raiseError("Could not open $file");\r
+                continue;\r
+            }\r
+            while ($cont = fread($fd, 2048)) {\r
+                if (isset($outputfd)) {\r
+                    fwrite($outputfd, $cont);\r
+                } else {\r
+                    $ret .= $cont;\r
+                }\r
+            }\r
+            fclose($fd);\r
+        }\r
+        if (@is_resource($outputfd)) {\r
+            fclose($outputfd);\r
+        }\r
+        return $ret;\r
+    }\r
+\r
+    /**\r
+    * Creates temporary files or directories. This function will remove\r
+    * the created files when the scripts finish its execution.\r
+    *\r
+    * Usage:\r
+    *   1) $tempfile = System::mktemp("prefix");\r
+    *   2) $tempdir  = System::mktemp("-d prefix");\r
+    *   3) $tempfile = System::mktemp();\r
+    *   4) $tempfile = System::mktemp("-t /var/tmp prefix");\r
+    *\r
+    * prefix -> The string that will be prepended to the temp name\r
+    *           (defaults to "tmp").\r
+    * -d     -> A temporary dir will be created instead of a file.\r
+    * -t     -> The target dir where the temporary (file|dir) will be created. If\r
+    *           this param is missing by default the env vars TMP on Windows or\r
+    *           TMPDIR in Unix will be used. If these vars are also missing\r
+    *           c:\windows\temp or /tmp will be used.\r
+    *\r
+    * @param   string  $args  The arguments\r
+    * @return  mixed   the full path of the created (file|dir) or false\r
+    * @see System::tmpdir()\r
+    * @access  public\r
+    */\r
+    function mktemp($args = null)\r
+    {\r
+        static $first_time = true;\r
+        $opts = System::_parseArgs($args, 't:d');\r
+        if (PEAR::isError($opts)) {\r
+            return System::raiseError($opts);\r
+        }\r
+        foreach($opts[0] as $opt) {\r
+            if($opt[0] == 'd') {\r
+                $tmp_is_dir = true;\r
+            } elseif($opt[0] == 't') {\r
+                $tmpdir = $opt[1];\r
+            }\r
+        }\r
+        $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp';\r
+        if (!isset($tmpdir)) {\r
+            $tmpdir = System::tmpdir();\r
+        }\r
+        if (!System::mkDir(array('-p', $tmpdir))) {\r
+            return false;\r
+        }\r
+        $tmp = tempnam($tmpdir, $prefix);\r
+        if (isset($tmp_is_dir)) {\r
+            unlink($tmp); // be careful possible race condition here\r
+            if (!mkdir($tmp, 0700)) {\r
+                return System::raiseError("Unable to create temporary directory $tmpdir");\r
+            }\r
+        }\r
+        $GLOBALS['_System_temp_files'][] = $tmp;\r
+        if ($first_time) {\r
+            PEAR::registerShutdownFunc(array('System', '_removeTmpFiles'));\r
+            $first_time = false;\r
+        }\r
+        return $tmp;\r
+    }\r
+\r
+    /**\r
+    * Remove temporary files created my mkTemp. This function is executed\r
+    * at script shutdown time\r
+    *\r
+    * @access private\r
+    */\r
+    function _removeTmpFiles()\r
+    {\r
+        if (count($GLOBALS['_System_temp_files'])) {\r
+            $delete = $GLOBALS['_System_temp_files'];\r
+            array_unshift($delete, '-r');\r
+            System::rm($delete);\r
+            $GLOBALS['_System_temp_files'] = array();\r
+        }\r
+    }\r
+\r
+    /**\r
+    * Get the path of the temporal directory set in the system\r
+    * by looking in its environments variables.\r
+    * Note: php.ini-recommended removes the "E" from the variables_order setting,\r
+    * making unavaible the $_ENV array, that s why we do tests with _ENV\r
+    *\r
+    * @return string The temporal directory on the system\r
+    */\r
+    function tmpdir()\r
+    {\r
+        if (OS_WINDOWS) {\r
+            if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) {\r
+                return $var;\r
+            }\r
+            if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) {\r
+                return $var;\r
+            }\r
+            if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) {\r
+                return $var;\r
+            }\r
+            return getenv('SystemRoot') . '\temp';\r
+        }\r
+        if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) {\r
+            return $var;\r
+        }\r
+        return '/tmp';\r
+    }\r
+\r
+    /**\r
+    * The "which" command (show the full path of a command)\r
+    *\r
+    * @param string $program The command to search for\r
+    * @param mixed  $fallback Value to return if $program is not found\r
+    *\r
+    * @return mixed A string with the full path or false if not found\r
+    * @author Stig Bakken <ssb@php.net>\r
+    */\r
+    function which($program, $fallback = false)\r
+    {\r
+        // avaible since 4.3.0RC2\r
+        if (defined('PATH_SEPARATOR')) {\r
+            $path_delim = PATH_SEPARATOR;\r
+        } else {\r
+            $path_delim = OS_WINDOWS ? ';' : ':';\r
+        }\r
+        // full path given\r
+        if (basename($program) != $program) {\r
+            $path_elements[] = dirname($program);\r
+            $program = basename($program);\r
+        } else {\r
+            // Honor safe mode\r
+            if (!ini_get('safe_mode') || !$path = ini_get('safe_mode_exec_dir')) {\r
+                $path = getenv('PATH');\r
+                if (!$path) {\r
+                    $path = getenv('Path'); // some OSes are just stupid enough to do this\r
+                }\r
+            }\r
+            $path_elements = explode($path_delim, $path);\r
+        }\r
+\r
+        if (OS_WINDOWS) {\r
+            $exe_suffixes = getenv('PATHEXT')\r
+                                ? explode($path_delim, getenv('PATHEXT'))\r
+                                : array('.exe','.bat','.cmd','.com');\r
+            // allow passing a command.exe param\r
+            if (strpos($program, '.') !== false) {\r
+                array_unshift($exe_suffixes, '');\r
+            }\r
+            // is_executable() is not available on windows for PHP4\r
+            $pear_is_executable = (function_exists('is_executable')) ? 'is_executable' : 'is_file';\r
+        } else {\r
+            $exe_suffixes = array('');\r
+            $pear_is_executable = 'is_executable';\r
+        }\r
+\r
+        foreach ($exe_suffixes as $suff) {\r
+            foreach ($path_elements as $dir) {\r
+                $file = $dir . DIRECTORY_SEPARATOR . $program . $suff;\r
+                if ($pear_is_executable($file)) {\r
+                    return $file;\r
+                }\r
+            }\r
+        }\r
+        return $fallback;\r
+    }\r
+\r
+    /**\r
+    * The "find" command\r
+    *\r
+    * Usage:\r
+    *\r
+    * System::find($dir);\r
+    * System::find("$dir -type d");\r
+    * System::find("$dir -type f");\r
+    * System::find("$dir -name *.php");\r
+    * System::find("$dir -name *.php -name *.htm*");\r
+    * System::find("$dir -maxdepth 1");\r
+    *\r
+    * Params implmented:\r
+    * $dir            -> Start the search at this directory\r
+    * -type d         -> return only directories\r
+    * -type f         -> return only files\r
+    * -maxdepth <n>   -> max depth of recursion\r
+    * -name <pattern> -> search pattern (bash style). Multiple -name param allowed\r
+    *\r
+    * @param  mixed Either array or string with the command line\r
+    * @return array Array of found files\r
+    *\r
+    */\r
+    function find($args)\r
+    {\r
+        if (!is_array($args)) {\r
+            $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);\r
+        }\r
+        $dir = array_shift($args);\r
+        $patterns = array();\r
+        $depth = 0;\r
+        $do_files = $do_dirs = true;\r
+        for ($i = 0; $i < count($args); $i++) {\r
+            switch ($args[$i]) {\r
+                case '-type':\r
+                    if (in_array($args[$i+1], array('d', 'f'))) {\r
+                        if ($args[$i+1] == 'd') {\r
+                            $do_files = false;\r
+                        } else {\r
+                            $do_dirs = false;\r
+                        }\r
+                    }\r
+                    $i++;\r
+                    break;\r
+                case '-name':\r
+                    if (OS_WINDOWS) {\r
+                        if ($args[$i+1]{0} == '\\') {\r
+                            // prepend drive\r
+                            $args[$i+1] = addslashes(substr(getcwd(), 0, 2) . $args[$i + 1]);\r
+                        }\r
+                    }\r
+                    $patterns[] = "(" . preg_replace(array('/\./', '/\*/'),\r
+                                                     array('\.', '.*', ),\r
+                                                     $args[$i+1])\r
+                                      . ")";\r
+                    $i++;\r
+                    break;\r
+                case '-maxdepth':\r
+                    $depth = $args[$i+1];\r
+                    break;\r
+            }\r
+        }\r
+        $path = System::_dirToStruct($dir, $depth);\r
+        if ($do_files && $do_dirs) {\r
+            $files = array_merge($path['files'], $path['dirs']);\r
+        } elseif ($do_dirs) {\r
+            $files = $path['dirs'];\r
+        } else {\r
+            $files = $path['files'];\r
+        }\r
+        if (count($patterns)) {\r
+            $patterns = implode('|', $patterns);\r
+            $ret = array();\r
+            for ($i = 0; $i < count($files); $i++) {\r
+                if (preg_match("#^$patterns\$#", $files[$i])) {\r
+                    $ret[] = $files[$i];\r
+                }\r
+            }\r
+            return $ret;\r
+        }\r
+        return $files;\r
+    }\r
+}\r
+?>\r
diff --git a/include/classes/XML/XML_HTMLSax/XML_HTMLSax.php b/include/classes/XML/XML_HTMLSax/XML_HTMLSax.php
new file mode 100644 (file)
index 0000000..8788cf9
--- /dev/null
@@ -0,0 +1,671 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//
+// +----------------------------------------------------------------------+
+// | PHP Version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2002 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license,      |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/3_0.txt.                                  |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Alexander Zhukov <alex@veresk.ru> Original port from Python |
+// | Authors: Harry Fuecks <hfuecks@phppatterns.com> Port to PEAR + more  |
+// | Authors: Many @ Sitepointforums Advanced PHP Forums                  |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+//
+/**
+* Main parser components
+* @package XML_HTMLSax
+* @version $Id$
+*/
+/**
+* Required classes
+*/
+require_once(AT_INCLUDE_PATH.'classes/XML/XML_HTMLSax/PEAR.php');
+if (!defined('XML_HTMLSAX')) {
+    define('XML_HTMLSAX', AT_INCLUDE_PATH . 'classes/XML/XML_HTMLSax/'); /*  'XML/' had to be removed to work. joel/ATRC */
+}
+require_once(XML_HTMLSAX . 'HTMLSax/XML_HTMLSax_States.php');
+require_once(XML_HTMLSAX . 'HTMLSax/XML_HTMLSax_Decorators.php');
+/**
+* Base State Parser
+* @package XML_HTMLSax
+* @access protected
+* @abstract
+*/
+class XML_HTMLSax_StateParser {
+    /**
+    * Instance of user front end class to be passed to callbacks
+    * @var XML_HTMLSax
+    * @access private
+    */
+    var $htmlsax;
+    /**
+    * User defined object for handling elements
+    * @var object
+    * @access private
+    */
+    var $handler_object_element;
+    /**
+    * User defined open tag handler method
+    * @var string
+    * @access private
+    */
+    var $handler_method_opening;
+    /**
+    * User defined close tag handler method
+    * @var string
+    * @access private
+    */
+    var $handler_method_closing;
+    /**
+    * User defined object for handling data in elements
+    * @var object
+    * @access private
+    */
+    var $handler_object_data;
+    /**
+    * User defined data handler method
+    * @var string
+    * @access private
+    */
+    var $handler_method_data;
+    /**
+    * User defined object for handling processing instructions
+    * @var object
+    * @access private
+    */
+    var $handler_object_pi;
+    /**
+    * User defined processing instruction handler method
+    * @var string
+    * @access private
+    */
+    var $handler_method_pi;
+    /**
+    * User defined object for handling JSP/ASP tags
+    * @var object
+    * @access private
+    */
+    var $handler_object_jasp;
+    /**
+    * User defined JSP/ASP handler method
+    * @var string
+    * @access private
+    */
+    var $handler_method_jasp;
+    /**
+    * User defined object for handling XML escapes
+    * @var object
+    * @access private
+    */
+    var $handler_object_escape;
+    /**
+    * User defined XML escape handler method
+    * @var string
+    * @access private
+    */
+    var $handler_method_escape;
+    /**
+    * User defined handler object or NullHandler
+    * @var object
+    * @access private
+    */
+    var $handler_default;
+    /**
+    * Parser options determining parsing behavior
+    * @var array
+    * @access private
+    */
+    var $parser_options = array();
+    /**
+    * XML document being parsed
+    * @var string
+    * @access private
+    */
+    var $rawtext;
+    /**
+    * Position in XML document relative to start (0)
+    * @var int
+    * @access private
+    */
+    var $position;
+    /**
+    * Length of the XML document in characters
+    * @var int
+    * @access private
+    */
+    var $length;
+    /**
+    * Array of state objects
+    * @var array
+    * @access private
+    */
+    var $State = array();
+
+    /**
+    * Constructs XML_HTMLSax_StateParser setting up states
+    * @var XML_HTMLSax instance of user front end class
+    * @access protected
+    */
+    function XML_HTMLSax_StateParser (& $htmlsax) {
+        $this->htmlsax = & $htmlsax;
+        $this->State[XML_HTMLSAX_STATE_START] =& new XML_HTMLSax_StartingState();
+
+        $this->State[XML_HTMLSAX_STATE_CLOSING_TAG] =& new XML_HTMLSax_ClosingTagState();
+        $this->State[XML_HTMLSAX_STATE_TAG] =& new XML_HTMLSax_TagState();
+        $this->State[XML_HTMLSAX_STATE_OPENING_TAG] =& new XML_HTMLSax_OpeningTagState();
+
+        $this->State[XML_HTMLSAX_STATE_PI] =& new XML_HTMLSax_PiState();
+        $this->State[XML_HTMLSAX_STATE_JASP] =& new XML_HTMLSax_JaspState();
+        $this->State[XML_HTMLSAX_STATE_ESCAPE] =& new XML_HTMLSax_EscapeState();
+    }
+
+    /**
+    * Moves the position back one character
+    * @access protected
+    * @return void
+    */
+    function unscanCharacter() {
+        $this->position -= 1;
+    }
+
+    /**
+    * Moves the position forward one character
+    * @access protected
+    * @return void
+    */
+    function ignoreCharacter() {
+        $this->position += 1;
+    }
+
+    /**
+    * Returns the next character from the XML document or void if at end
+    * @access protected
+    * @return mixed
+    */
+    function scanCharacter() {
+        if ($this->position < $this->length) {
+            return $this->rawtext{$this->position++};
+        }
+    }
+
+    /**
+    * Returns a string from the current position to the next occurance
+    * of the supplied string
+    * @param string string to search until
+    * @access protected
+    * @return string
+    */
+    function scanUntilString($string) {
+        $start = $this->position;
+        $this->position = @strpos($this->rawtext, $string, $start);
+        if ($this->position === FALSE) {
+            $this->position = $this->length;
+        }
+        return substr($this->rawtext, $start, $this->position - $start);
+    }
+
+    /**
+    * Returns a string from the current position until the first instance of
+    * one of the characters in the supplied string argument
+    * @param string string to search until
+    * @access protected
+    * @return string
+    * @abstract
+    */
+    function scanUntilCharacters($string) {}
+
+    /**
+    * Moves the position forward past any whitespace characters
+    * @access protected
+    * @return void
+    * @abstract
+    */
+    function ignoreWhitespace() {}
+
+    /**
+    * Begins the parsing operation, setting up any decorators, depending on
+    * parse options invoking _parse() to execute parsing
+    * @param string XML document to parse
+    * @access protected
+    * @return void
+    */
+    function parse($data) {
+        if ($this->parser_options['XML_OPTION_TRIM_DATA_NODES']==1) {
+            $decorator =& new XML_HTMLSax_Trim(
+                $this->handler_object_data,
+                $this->handler_method_data);
+            $this->handler_object_data =& $decorator;
+            $this->handler_method_data = 'trimData';
+        }
+        if ($this->parser_options['XML_OPTION_CASE_FOLDING']==1) {
+            $open_decor =& new XML_HTMLSax_CaseFolding(
+                $this->handler_object_element,
+                $this->handler_method_opening,
+                $this->handler_method_closing);
+            $this->handler_object_element =& $open_decor;
+            $this->handler_method_opening ='foldOpen';
+            $this->handler_method_closing ='foldClose';
+        }
+        if ($this->parser_options['XML_OPTION_LINEFEED_BREAK']==1) {
+            $decorator =& new XML_HTMLSax_Linefeed(
+                $this->handler_object_data,
+                $this->handler_method_data);
+            $this->handler_object_data =& $decorator;
+            $this->handler_method_data = 'breakData';
+        }
+        if ($this->parser_options['XML_OPTION_TAB_BREAK']==1) {
+            $decorator =& new XML_HTMLSax_Tab(
+                $this->handler_object_data,
+                $this->handler_method_data);
+            $this->handler_object_data =& $decorator;
+            $this->handler_method_data = 'breakData';
+        }
+        if ($this->parser_options['XML_OPTION_ENTITIES_UNPARSED']==1) {
+            $decorator =& new XML_HTMLSax_Entities_Unparsed(
+                $this->handler_object_data,
+                $this->handler_method_data);
+            $this->handler_object_data =& $decorator;
+            $this->handler_method_data = 'breakData';
+        }
+        if ($this->parser_options['XML_OPTION_ENTITIES_PARSED']==1) {
+            $decorator =& new XML_HTMLSax_Entities_Parsed(
+                $this->handler_object_data,
+                $this->handler_method_data);
+            $this->handler_object_data =& $decorator;
+            $this->handler_method_data = 'breakData';
+        }
+        $this->rawtext = $data;
+        $this->length = strlen($data);
+        $this->position = 0;
+        $this->_parse();
+    }
+
+    /**
+    * Performs the parsing itself, delegating calls to a specific parser
+    * state
+    * @param constant state object to parse with
+    * @access protected
+    * @return void
+    */
+    function _parse($state = XML_HTMLSAX_STATE_START) {
+        do {
+            $state = $this->State[$state]->parse($this);
+        } while ($state != XML_HTMLSAX_STATE_STOP &&
+                    $this->position < $this->length);
+    }
+}
+
+/**
+* Parser for PHP Versions below 4.3.0. Uses a slower parsing mechanism than
+* the equivalent PHP 4.3.0+  subclass of StateParser
+* @package XML_HTMLSax
+* @access protected
+* @see XML_HTMLSax_StateParser_Gtet430
+*/
+class XML_HTMLSax_StateParser_Lt430 extends XML_HTMLSax_StateParser {
+    /**
+    * Constructs XML_HTMLSax_StateParser_Lt430 defining available
+    * parser options
+    * @var XML_HTMLSax instance of user front end class
+    * @access protected
+    */
+    function XML_HTMLSax_StateParser_Lt430(& $htmlsax) {
+        parent::XML_HTMLSax_StateParser($htmlsax);
+        $this->parser_options['XML_OPTION_TRIM_DATA_NODES'] = 0;
+        $this->parser_options['XML_OPTION_CASE_FOLDING'] = 0;
+        $this->parser_options['XML_OPTION_LINEFEED_BREAK'] = 0;
+        $this->parser_options['XML_OPTION_TAB_BREAK'] = 0;
+        $this->parser_options['XML_OPTION_ENTITIES_PARSED'] = 0;
+        $this->parser_options['XML_OPTION_ENTITIES_UNPARSED'] = 0;
+        $this->parser_options['XML_OPTION_FULL_ESCAPES'] = 0;
+    }
+
+    /**
+    * Returns a string from the current position until the first instance of
+    * one of the characters in the supplied string argument
+    * @param string string to search until
+    * @access protected
+    * @return string
+    */
+    function scanUntilCharacters($string) {
+        $startpos = $this->position;
+        while ($this->position < $this->length && strpos($string, $this->rawtext{$this->position}) === FALSE) {
+            $this->position++;
+        }
+        return substr($this->rawtext, $startpos, $this->position - $startpos);
+    }
+
+    /**
+    * Moves the position forward past any whitespace characters
+    * @access protected
+    * @return void
+    */
+    function ignoreWhitespace() {
+        while ($this->position < $this->length && 
+            strpos(" \n\r\t", $this->rawtext{$this->position}) !== FALSE) {
+            $this->position++;
+        }
+    }
+
+    /**
+    * Begins the parsing operation, setting up the unparsed XML entities
+    * decorator if necessary then delegating further work to parent
+    * @param string XML document to parse
+    * @access protected
+    * @return void
+    */
+    function parse($data) {
+        parent::parse($data);
+    }
+}
+
+/**
+* Parser for PHP Versions equal to or greater than 4.3.0. Uses a faster
+* parsing mechanism than the equivalent PHP < 4.3.0 subclass of StateParser
+* @package XML_HTMLSax
+* @access protected
+* @see XML_HTMLSax_StateParser_Lt430
+*/
+class XML_HTMLSax_StateParser_Gtet430 extends XML_HTMLSax_StateParser {
+    /**
+    * Constructs XML_HTMLSax_StateParser_Gtet430 defining available
+    * parser options
+    * @var XML_HTMLSax instance of user front end class
+    * @access protected
+    */
+    function XML_HTMLSax_StateParser_Gtet430(& $htmlsax) {
+        parent::XML_HTMLSax_StateParser($htmlsax);
+        $this->parser_options['XML_OPTION_TRIM_DATA_NODES'] = 0;
+        $this->parser_options['XML_OPTION_CASE_FOLDING'] = 0;
+        $this->parser_options['XML_OPTION_LINEFEED_BREAK'] = 0;
+        $this->parser_options['XML_OPTION_TAB_BREAK'] = 0;
+        $this->parser_options['XML_OPTION_ENTITIES_PARSED'] = 0;
+        $this->parser_options['XML_OPTION_ENTITIES_UNPARSED'] = 0;
+        $this->parser_options['XML_OPTION_FULL_ESCAPES'] = 0;
+    }
+    /**
+    * Returns a string from the current position until the first instance of
+    * one of the characters in the supplied string argument.
+    * @param string string to search until
+    * @access protected
+    * @return string
+    */
+    function scanUntilCharacters($string) {
+        $startpos = $this->position;
+        $length = strcspn($this->rawtext, $string, $startpos);
+        $this->position += $length;
+        return substr($this->rawtext, $startpos, $length);
+    }
+
+    /**
+    * Moves the position forward past any whitespace characters
+    * @access protected
+    * @return void
+    */
+    function ignoreWhitespace() {
+        $this->position += strspn($this->rawtext, " \n\r\t", $this->position);
+    }
+
+    /**
+    * Begins the parsing operation, setting up the parsed and unparsed
+    * XML entity decorators if necessary then delegating further work
+    * to parent
+    * @param string XML document to parse
+    * @access protected
+    * @return void
+    */
+    function parse($data) {
+        parent::parse($data);
+    }
+}
+
+/**
+* Default NullHandler for methods which were not set by user
+* @package XML_HTMLSax
+* @access protected
+*/
+class XML_HTMLSax_NullHandler {
+    /**
+    * Generic handler method which does nothing
+    * @access protected
+    * @return void
+    */
+    function DoNothing() {
+    }
+}
+
+/**
+* User interface class. All user calls should only be made to this class
+* @package XML_HTMLSax
+* @access public
+*/
+class XML_HTMLSax extends Pear {
+    /**
+    * Instance of concrete subclass of XML_HTMLSax_StateParser
+    * @var XML_HTMLSax_StateParser
+    * @access private
+    */
+    var $state_parser;
+
+    /**
+    * Constructs XML_HTMLSax selecting concrete StateParser subclass
+    * depending on PHP version being used as well as setting the default
+    * NullHandler for all callbacks<br />
+    * <b>Example:</b>
+    * <pre>
+    * $myHandler = & new MyHandler();
+    * $parser = new XML_HTMLSax();
+    * $parser->set_object($myHandler);
+    * $parser->set_option('XML_OPTION_CASE_FOLDING');
+    * $parser->set_element_handler('myOpenHandler','myCloseHandler');
+    * $parser->set_data_handler('myDataHandler');
+    * $parser->parser($xml);
+    * </pre>
+    * @access public
+    */
+    function XML_HTMLSax() {
+        if (version_compare(phpversion(), '4.3', 'ge')) {
+            $this->state_parser =& new XML_HTMLSax_StateParser_Gtet430($this);
+        } else {
+            $this->state_parser =& new XML_HTMLSax_StateParser_Lt430($this);
+        }
+        $nullhandler =& new XML_HTMLSax_NullHandler();
+        $this->set_object($nullhandler);
+        $this->set_element_handler('DoNothing', 'DoNothing');
+        $this->set_data_handler('DoNothing');
+        $this->set_pi_handler('DoNothing');
+        $this->set_jasp_handler('DoNothing');
+        $this->set_escape_handler('DoNothing');
+    }
+
+    /**
+    * Sets the user defined handler object. Returns a PEAR Error
+    * if supplied argument is not an object.
+    * @param object handler object containing SAX callback methods
+    * @access public
+    * @return mixed
+    */
+    function set_object(&$object) {
+        if ( is_object($object) ) {
+            $this->state_parser->handler_default =& $object;
+            return true;
+        } else {
+            return $this->raiseError('XML_HTMLSax::set_object requires '.
+                'an object instance');
+        }
+    }
+
+    /**
+    * Sets a parser option. Returns a PEAR Error if option is invalid<br />
+    * <b>Available options:</b>
+    * <ul>
+    * <li>XML_OPTION_TRIM_DATA_NODES: trim whitespace off the beginning
+    * and end of data passed to the data handler</li>
+    * <li>XML_OPTION_LINEFEED_BREAK: linefeeds result in additional data
+    * handler calls</li>
+    * <li>XML_OPTION_TAB_BREAK: tabs result in additional data handler
+    * calls</li>
+    * <li>XML_OPTION_ENTIES_UNPARSED: XML entities are returned as
+    * seperate data handler calls in unparsed form</li>
+    * <li>XML_OPTION_ENTIES_PARSED: (PHP 4.3.0+ only) XML entities are
+    * returned as seperate data handler calls and are parsed with 
+    * PHP's html_entity_decode() function</li>
+    * </ul>
+    * @param string name of parser option
+    * @param int (optional) 1 to switch on, 0 for off
+    * @access public
+    * @return boolean
+    */
+    function set_option($name, $value=1) {
+        if ( array_key_exists($name,$this->state_parser->parser_options) ) {
+            $this->state_parser->parser_options[$name] = $value;
+            return true;
+        } else {
+            return $this->raiseError('XML_HTMLSax::set_option('.$name.') illegal');
+        }
+    }
+
+    /**
+    * Sets the data handler method which deals with the contents of XML
+    * elements.<br />
+    * The handler method must accept two arguments, the first being an
+    * instance of XML_HTMLSax and the second being the contents of an
+    * XML element e.g.
+    * <pre>
+    * function myDataHander(& $parser,$data){}
+    * </pre>
+    * @param string name of method
+    * @access public
+    * @return void
+    * @see set_object
+    */
+    function set_data_handler($data_method) {
+        $this->state_parser->handler_object_data =& $this->state_parser->handler_default;
+        $this->state_parser->handler_method_data = $data_method;
+    }
+
+    /**
+    * Sets the open and close tag handlers
+    * <br />The open handler method must accept three arguments; the parser,
+    * the tag name and an array of attributes e.g.
+    * <pre>
+    * function myOpenHander(& $parser,$tagname,$attrs=array()){}
+    * </pre>
+    * The close handler method must accept two arguments; the parser and
+    * the tag name e.g.
+    * <pre>
+    * function myCloseHander(& $parser,$tagname){}
+    * </pre>
+    * @param string name of open method
+    * @param string name of close method
+    * @access public
+    * @return void
+    * @see set_object
+    */
+    function set_element_handler($opening_method, $closing_method) {
+        $this->state_parser->handler_object_element =& $this->state_parser->handler_default;
+        $this->state_parser->handler_method_opening = $opening_method;
+        $this->state_parser->handler_method_closing = $closing_method;
+    }
+
+    /**
+    * Sets the processing instruction handler method e.g. for PHP open
+    * and close tags<br />
+    * The handler method must accept three arguments; the parser, the
+    * PI target and data inside the PI
+    * <pre>
+    * function myPIHander(& $parser,$target, $data){}
+    * </pre>
+    * @param string name of method
+    * @access public
+    * @return void
+    * @see set_object
+    */
+    function set_pi_handler($pi_method) {
+        $this->state_parser->handler_object_pi =& $this->state_parser->handler_default;
+        $this->state_parser->handler_method_pi = $pi_method;
+    }
+
+    /**
+    * Sets the XML escape handler method e.g. for comments and doctype
+    * declarations<br />
+    * The handler method must accept two arguments; the parser and the
+    * contents of the escaped section
+    * <pre>
+    * function myEscapeHander(& $parser, $data){}
+    * </pre>
+    * @param string name of method
+    * @access public
+    * @return void
+    * @see set_object
+    */
+    function set_escape_handler($escape_method) {
+        $this->state_parser->handler_object_escape =& $this->state_parser->handler_default;
+        $this->state_parser->handler_method_escape = $escape_method;
+    }
+
+    /**
+    * Sets the JSP/ASP markup handler<br />
+    * The handler method must accept two arguments; the parser and
+    * body of the JASP tag
+    * <pre>
+    * function myJaspHander(& $parser, $data){}
+    * </pre>
+    * @param string name of method
+    * @access public
+    * @return void
+    * @see set_object
+    */
+    function set_jasp_handler ($jasp_method) {
+        $this->state_parser->handler_object_jasp =& $this->state_parser->handler_default;
+        $this->state_parser->handler_method_jasp = $jasp_method;
+    }
+
+    /**
+    * Returns the current string position of the "cursor" inside the XML
+    * document
+    * <br />Intended for use from within a user defined handler called
+    * via the $parser reference e.g.
+    * <pre>
+    * function myDataHandler(& $parser,$data) {
+    *     echo( 'Current position: '.$parser->get_current_position() );
+    * }
+    * </pre>
+    * @access public
+    * @return int
+    * @see get_length
+    */
+    function get_current_position() {
+        return $this->state_parser->position;
+    }
+
+    /**
+    * Returns the string length of the XML document being parsed
+    * @access public
+    * @return int
+    */
+    function get_length() {
+        return $this->state_parser->length;
+    }
+
+    /**
+    * Start parsing some XML
+    * @param string XML document
+    * @access public
+    * @return void
+    */
+    function parse($data) {
+        $this->state_parser->parse($data);
+    }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/cssparser.php b/include/classes/cssparser.php
new file mode 100644 (file)
index 0000000..f2a19b7
--- /dev/null
@@ -0,0 +1,238 @@
+<?php
+class cssparser {
+  var $css;
+  var $html;
+  
+  function cssparser($html = true) {
+    // Register "destructor"
+    register_shutdown_function(array(&$this, "finalize"));
+    $this->html = ($html != false);
+    $this->Clear();
+  }
+  
+  function finalize() {
+    unset($this->css);
+  }
+  
+  function Clear() {
+    unset($this->css);
+    $this->css = array();
+    if($this->html) {
+               /*
+      $this->Add("ADDRESS", "");
+      $this->Add("APPLET", "");
+      $this->Add("AREA", "");
+      $this->Add("A", "text-decoration : underline; color : Blue;");
+      $this->Add("A:visited", "color : Purple;");
+      $this->Add("BASE", "");
+      $this->Add("BASEFONT", "");
+      $this->Add("BIG", "");
+      $this->Add("BLOCKQUOTE", "");
+      $this->Add("BODY", "");
+      $this->Add("BR", "");
+      $this->Add("B", "font-weight: bold;");
+      $this->Add("CAPTION", "");
+      $this->Add("CENTER", "");
+      $this->Add("CITE", "");
+      $this->Add("CODE", "");
+      $this->Add("DD", "");
+      $this->Add("DFN", "");
+      $this->Add("DIR", "");
+      $this->Add("DIV", "");
+      $this->Add("DL", "");
+      $this->Add("DT", "");
+      $this->Add("EM", "");
+      $this->Add("FONT", "");
+      $this->Add("FORM", "");
+      $this->Add("H1", "");
+      $this->Add("H2", "");
+      $this->Add("H3", "");
+      $this->Add("H4", "");
+      $this->Add("H5", "");
+      $this->Add("H6", "");
+      $this->Add("HEAD", "");
+      $this->Add("HR", "");
+      $this->Add("HTML", "");
+      $this->Add("IMG", "");
+      $this->Add("INPUT", "");
+      $this->Add("ISINDEX", "");
+      $this->Add("I", "font-style: italic;");
+      $this->Add("KBD", "");
+      $this->Add("LINK", "");
+      $this->Add("LI", "");
+      $this->Add("MAP", "");
+      $this->Add("MENU", "");
+      $this->Add("META", "");
+      $this->Add("OL", "");
+      $this->Add("OPTION", "");
+      $this->Add("PARAM", "");
+      $this->Add("PRE", "");
+      $this->Add("P", "");
+      $this->Add("SAMP", "");
+      $this->Add("SCRIPT", "");
+      $this->Add("SELECT", "");
+      $this->Add("SMALL", "");
+      $this->Add("STRIKE", "");
+      $this->Add("STRONG", "");
+      $this->Add("STYLE", "");
+      $this->Add("SUB", "");
+      $this->Add("SUP", "");
+      $this->Add("TABLE", "");
+      $this->Add("TD", "");
+      $this->Add("TEXTAREA", "");
+      $this->Add("TH", "");
+      $this->Add("TITLE", "");
+      $this->Add("TR", "");
+      $this->Add("TT", "");
+      $this->Add("UL", "");
+      $this->Add("U", "text-decoration : underline;");
+         */
+      $this->Add("VAR", "");
+
+    }
+  }
+  
+  function SetHTML($html) {
+    $this->html = ($html != false);
+  }
+  
+  function Add($key, $codestr) {
+    $key = strtolower($key);
+    $codestr = strtolower($codestr);
+    if(!isset($this->css[$key])) {
+      $this->css[$key] = array();
+    }
+    $codes = explode(";",$codestr);
+    if(count($codes) > 0) {
+      foreach($codes as $code) {
+        $code = trim($code);
+        list($codekey, $codevalue) = explode(":",$code,2);
+        if(strlen($codekey) > 0) {
+          $this->css[$key][trim($codekey)] = trim($codevalue);
+        }
+      }
+    }
+  }
+  
+  function Get($key, $property) {
+    $key = strtolower($key);
+    $property = strtolower($property);
+    
+    list($tag, $subtag) = explode(":",$key);
+    list($tag, $class) = explode(".",$tag);
+    list($tag, $id) = explode("#",$tag);
+    $result = "";
+    foreach($this->css as $_tag => $value) {
+      list($_tag, $_subtag) = explode(":",$_tag);
+      list($_tag, $_class) = explode(".",$_tag);
+      list($_tag, $_id) = explode("#",$_tag);
+      
+      $tagmatch = (strcmp($tag, $_tag) == 0) | (strlen($_tag) == 0);
+      $subtagmatch = (strcmp($subtag, $_subtag) == 0) | (strlen($_subtag) == 0);
+      $classmatch = (strcmp($class, $_class) == 0) | (strlen($_class) == 0);
+      $idmatch = (strcmp($id, $_id) == 0);
+      
+      if($tagmatch & $subtagmatch & $classmatch & $idmatch) {
+        $temp = $_tag;
+        if((strlen($temp) > 0) & (strlen($_class) > 0)) {
+          $temp .= ".".$_class;
+        } elseif(strlen($temp) == 0) {
+          $temp = ".".$_class;
+        }
+        if((strlen($temp) > 0) & (strlen($_subtag) > 0)) {
+          $temp .= ":".$_subtag;
+        } elseif(strlen($temp) == 0) {
+          $temp = ":".$_subtag;
+        }
+        if(isset($this->css[$temp][$property])) {
+          $result = $this->css[$temp][$property];
+        }
+      }
+    }
+    return $result;
+  }
+  
+  function GetSection($key) {
+    $key = strtolower($key);
+    
+    list($tag, $subtag) = explode(":",$key);
+    list($tag, $class) = explode(".",$tag);
+    list($tag, $id) = explode("#",$tag);
+    $result = array();
+    foreach($this->css as $_tag => $value) {
+      list($_tag, $_subtag) = explode(":",$_tag);
+      list($_tag, $_class) = explode(".",$_tag);
+      list($_tag, $_id) = explode("#",$_tag);
+      
+      $tagmatch = (strcmp($tag, $_tag) == 0) | (strlen($_tag) == 0);
+      $subtagmatch = (strcmp($subtag, $_subtag) == 0) | (strlen($_subtag) == 0);
+      $classmatch = (strcmp($class, $_class) == 0) | (strlen($_class) == 0);
+      $idmatch = (strcmp($id, $_id) == 0);
+      
+      if($tagmatch & $subtagmatch & $classmatch & $idmatch) {
+        $temp = $_tag;
+        if((strlen($temp) > 0) & (strlen($_class) > 0)) {
+          $temp .= ".".$_class;
+        } elseif(strlen($temp) == 0) {
+          $temp = ".".$_class;
+        }
+        if((strlen($temp) > 0) & (strlen($_subtag) > 0)) {
+          $temp .= ":".$_subtag;
+        } elseif(strlen($temp) == 0) {
+          $temp = ":".$_subtag;
+        }
+        foreach($this->css[$temp] as $property => $value) {
+          $result[$property] = $value;
+        }
+      }
+    }
+    return $result;
+  }
+  
+  function ParseStr($str) {
+    $this->Clear();
+    // Remove comments
+    $str = preg_replace("/\/\*(.*)?\*\//Usi", "", $str);
+    // Parse this damn csscode
+    $parts = explode("}",$str);
+    if(count($parts) > 0) {
+      foreach($parts as $part) {
+        list($keystr,$codestr) = explode("{",$part);
+        $keys = explode(",",trim($keystr));
+        if(count($keys) > 0) {
+          foreach($keys as $key) {
+            if(strlen($key) > 0) {
+              $key = str_replace("\n", "", $key);
+              $key = str_replace("\\", "", $key);
+              $this->Add($key, trim($codestr));
+            }
+          }
+        }
+      }
+    }
+    //
+    return (count($this->css) > 0);
+  }
+  
+  function Parse($filename) {
+    $this->Clear();
+    if(file_exists($filename)) {
+      return $this->ParseStr(file_get_contents($filename));
+    } else {
+      return false;
+    }
+  }
+  
+  function GetCSS() {
+    $result = "";
+    foreach($this->css as $key => $values) {
+      $result .= $key." {\n";
+      foreach($values as $key => $value) {
+        $result .= "  $key: $value;\n";
+      }
+      $result .= "}\n\n";
+    }
+    return $result;
+  }
+}
+?>
diff --git a/include/classes/feedcreator.class.php b/include/classes/feedcreator.class.php
new file mode 100644 (file)
index 0000000..69e2854
--- /dev/null
@@ -0,0 +1,1545 @@
+<?php\r
+/***************************************************************************\r
+\r
+FeedCreator class v1.7.2\r
+originally (c) Kai Blankenhorn\r
+www.bitfolge.de\r
+kaib@bitfolge.de\r
+v1.3 work by Scott Reynen (scott@randomchaos.com) and Kai Blankenhorn\r
+v1.5 OPML support by Dirk Clemens\r
+\r
+This library is free software; you can redistribute it and/or\r
+modify it under the terms of the GNU Lesser General Public\r
+License as published by the Free Software Foundation; either\r
+version 2.1 of the License, or (at your option) any later version.\r
+\r
+This library is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+Lesser General Public License for more details.\r
+\r
+You should have received a copy of the GNU Lesser General Public\r
+License along with this library; if not, write to the Free Software\r
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+\r
+****************************************************************************\r
+\r
+\r
+Changelog:\r
+\r
+v1.7.2 10-11-04\r
+       license changed to LGPL\r
+\r
+v1.7.1\r
+       fixed a syntax bug\r
+       fixed left over debug code\r
+\r
+v1.7   07-18-04\r
+       added HTML and JavaScript feeds (configurable via CSS) (thanks to Pascal Van Hecke)\r
+       added HTML descriptions for all feed formats (thanks to Pascal Van Hecke)\r
+       added a switch to select an external stylesheet (thanks to Pascal Van Hecke)\r
+       changed default content-type to application/xml\r
+       added character encoding setting\r
+       fixed numerous smaller bugs (thanks to Sören Fuhrmann of golem.de)\r
+       improved changing ATOM versions handling (thanks to August Trometer)\r
+       improved the UniversalFeedCreator's useCached method (thanks to Sören Fuhrmann of golem.de)\r
+       added charset output in HTTP headers (thanks to Sören Fuhrmann of golem.de)\r
+       added Slashdot namespace to RSS 1.0 (thanks to Sören Fuhrmann of golem.de)\r
+\r
+v1.6   05-10-04\r
+       added stylesheet to RSS 1.0 feeds\r
+       fixed generator comment (thanks Kevin L. Papendick and Tanguy Pruvot)\r
+       fixed RFC822 date bug (thanks Tanguy Pruvot)\r
+       added TimeZone customization for RFC8601 (thanks Tanguy Pruvot)\r
+       fixed Content-type could be empty (thanks Tanguy Pruvot)\r
+       fixed author/creator in RSS1.0 (thanks Tanguy Pruvot)\r
+\r
+v1.6 beta      02-28-04\r
+       added Atom 0.3 support (not all features, though)\r
+       improved OPML 1.0 support (hopefully - added more elements)\r
+       added support for arbitrary additional elements (use with caution)\r
+       code beautification :-)\r
+       considered beta due to some internal changes\r
+\r
+v1.5.1 01-27-04\r
+       fixed some RSS 1.0 glitches (thanks to Stéphane Vanpoperynghe)\r
+       fixed some inconsistencies between documentation and code (thanks to Timothy Martin)\r
+\r
+v1.5   01-06-04\r
+       added support for OPML 1.0\r
+       added more documentation\r
+\r
+v1.4   11-11-03\r
+       optional feed saving and caching\r
+       improved documentation\r
+       minor improvements\r
+\r
+v1.3    10-02-03\r
+       renamed to FeedCreator, as it not only creates RSS anymore\r
+       added support for mbox\r
+       tentative support for echo/necho/atom/pie/???\r
+        \r
+v1.2    07-20-03\r
+       intelligent auto-truncating of RSS 0.91 attributes\r
+       don't create some attributes when they're not set\r
+       documentation improved\r
+       fixed a real and a possible bug with date conversions\r
+       code cleanup\r
+\r
+v1.1    06-29-03\r
+       added images to feeds\r
+       now includes most RSS 0.91 attributes\r
+       added RSS 2.0 feeds\r
+\r
+v1.0    06-24-03\r
+       initial release\r
+\r
+\r
+\r
+***************************************************************************/\r
+\r
+/*** GENERAL USAGE *********************************************************\r
+\r
+include("feedcreator.class.php"); \r
+\r
+$rss = new UniversalFeedCreator(); \r
+$rss->useCached(); // use cached version if age<1 hour\r
+$rss->title = "PHP news"; \r
+$rss->description = "daily news from the PHP scripting world"; \r
+\r
+//optional\r
+$rss->descriptionTruncSize = 500;\r
+$rss->descriptionHtmlSyndicated = true;\r
+\r
+$rss->link = "http://www.dailyphp.net/news"; \r
+$rss->syndicationURL = "http://www.dailyphp.net/".$_SERVER["PHP_SELF"]; \r
+\r
+$image = new FeedImage(); \r
+$image->title = "dailyphp.net logo"; \r
+$image->url = "http://www.dailyphp.net/images/logo.gif"; \r
+$image->link = "http://www.dailyphp.net"; \r
+$image->description = "Feed provided by dailyphp.net. Click to visit."; \r
+\r
+//optional\r
+$image->descriptionTruncSize = 500;\r
+$image->descriptionHtmlSyndicated = true;\r
+\r
+$rss->image = $image; \r
+\r
+// get your news items from somewhere, e.g. your database: \r
+mysql_select_db($dbHost, $dbUser, $dbPass); \r
+$res = mysql_query("SELECT * FROM news ORDER BY newsdate DESC"); \r
+while ($data = mysql_fetch_object($res)) { \r
+    $item = new FeedItem(); \r
+    $item->title = $data->title; \r
+    $item->link = $data->url; \r
+    $item->description = $data->short; \r
+    \r
+    //optional\r
+    item->descriptionTruncSize = 500;\r
+    item->descriptionHtmlSyndicated = true;\r
+\r
+    $item->date = $data->newsdate; \r
+    $item->source = "http://www.dailyphp.net"; \r
+    $item->author = "John Doe"; \r
+     \r
+    $rss->addItem($item); \r
+} \r
+\r
+// valid format strings are: RSS0.91, RSS1.0, RSS2.0, PIE0.1 (deprecated),\r
+// MBOX, OPML, ATOM, ATOM0.3, HTML, JS\r
+echo $rss->saveFeed("RSS1.0", "news/feed.xml");\r
+\r
+\r
+***************************************************************************\r
+*          A little setup                                                 *\r
+**************************************************************************/\r
+\r
+// your local timezone, set to "" to disable or for GMT\r
+define("TIME_ZONE","");\r
+\r
+\r
+/**\r
+ * Version string.\r
+ **/\r
+define("FEEDCREATOR_VERSION", "FeedCreator 1.7.2");\r
+\r
+//Greg Gay\r
+//Added ATutor charset encoding, see line 502\r
+//define("MY_ENCODING" , $myLang->getCharacterSet());\r
+\r
+/**\r
+ * A FeedItem is a part of a FeedCreator feed.\r
+ *\r
+ * @author Kai Blankenhorn <kaib@bitfolge.de>\r
+ * @since 1.3\r
+ */\r
+class FeedItem extends HtmlDescribable {\r
+       /**\r
+        * Mandatory attributes of an item.\r
+        */\r
+       var $title, $description, $link;\r
+       \r
+       /**\r
+        * Optional attributes of an item.\r
+        */\r
+       var $author, $authorEmail, $image, $category, $comments, $guid, $source, $creator;\r
+       \r
+       /**\r
+        * Publishing date of an item. May be in one of the following formats:\r
+        *\r
+        *      RFC 822:\r
+        *      "Mon, 20 Jan 03 18:05:41 +0400"\r
+        *      "20 Jan 03 18:05:41 +0000"\r
+        *\r
+        *      ISO 8601:\r
+        *      "2003-01-20T18:05:41+04:00"\r
+        *\r
+        *      Unix:\r
+        *      1043082341\r
+        */\r
+       var $date;\r
+       \r
+       /**\r
+        * Any additional elements to include as an assiciated array. All $key => $value pairs\r
+        * will be included unencoded in the feed item in the form\r
+        *     <$key>$value</$key>\r
+        * Again: No encoding will be used! This means you can invalidate or enhance the feed\r
+        * if $value contains markup. This may be abused to embed tags not implemented by\r
+        * the FeedCreator class used.\r
+        */\r
+       var $additionalElements = Array();\r
+\r
+       // on hold\r
+       // var $source;\r
+}\r
+\r
+\r
+\r
+/**\r
+ * An FeedImage may be added to a FeedCreator feed.\r
+ * @author Kai Blankenhorn <kaib@bitfolge.de>\r
+ * @since 1.3\r
+ */\r
+class FeedImage extends HtmlDescribable {\r
+       /**\r
+        * Mandatory attributes of an image.\r
+        */\r
+       var $title, $url, $link;\r
+       \r
+       /**\r
+        * Optional attributes of an image.\r
+        */\r
+       var $width, $height, $description;\r
+}\r
+\r
+\r
+\r
+/**\r
+ * An HtmlDescribable is an item within a feed that can have a description that may\r
+ * include HTML markup.\r
+ */\r
+class HtmlDescribable {\r
+       /**\r
+        * Indicates whether the description field should be rendered in HTML.\r
+        */\r
+       var $descriptionHtmlSyndicated;\r
+       \r
+       /**\r
+        * Indicates whether and to how many characters a description should be truncated.\r
+        */\r
+       var $descriptionTruncSize;\r
+       \r
+       /**\r
+        * Returns a formatted description field, depending on descriptionHtmlSyndicated and\r
+        * $descriptionTruncSize properties\r
+        * @return    string    the formatted description  \r
+        */\r
+       function getDescription() {\r
+               $descriptionField = new FeedHtmlField($this->description);\r
+               $descriptionField->syndicateHtml = $this->descriptionHtmlSyndicated;\r
+               $descriptionField->truncSize = $this->descriptionTruncSize;\r
+               return $descriptionField->output();\r
+       }\r
+\r
+}\r
+\r
+\r
+/**\r
+ * An FeedHtmlField describes and generates\r
+ * a feed, item or image html field (probably a description). Output is \r
+ * generated based on $truncSize, $syndicateHtml properties.\r
+ * @author Pascal Van Hecke <feedcreator.class.php@vanhecke.info>\r
+ * @version 1.6\r
+ */\r
+class FeedHtmlField {\r
+       /**\r
+        * Mandatory attributes of a FeedHtmlField.\r
+        */\r
+       var $rawFieldContent;\r
+       \r
+       /**\r
+        * Optional attributes of a FeedHtmlField.\r
+        * \r
+        */\r
+       var $truncSize, $syndicateHtml;\r
+       \r
+       /**\r
+        * Creates a new instance of FeedHtmlField.\r
+        * @param  $string: if given, sets the rawFieldContent property\r
+        */\r
+       function FeedHtmlField($parFieldContent) {\r
+               if ($parFieldContent) {\r
+                       $this->rawFieldContent = $parFieldContent;\r
+               }\r
+       }\r
+               \r
+               \r
+       /**\r
+        * Creates the right output, depending on $truncSize, $syndicateHtml properties.\r
+        * @return string    the formatted field\r
+        */\r
+       function output() {\r
+               // when field available and syndicated in html we assume \r
+               // - valid html in $rawFieldContent and we enclose in CDATA tags\r
+               // - no truncation (truncating risks producing invalid html)\r
+               if (!$this->rawFieldContent) {\r
+                       $result = "";\r
+               }       elseif ($this->syndicateHtml) {\r
+                       $result = "<![CDATA[".$this->rawFieldContent."]]>";\r
+               } else {\r
+                       if ($this->truncSize and is_int($this->truncSize)) {\r
+                               $result = FeedCreator::iTrunc(htmlspecialchars($this->rawFieldContent),$this->truncSize);\r
+                       } else {\r
+                               $result = htmlspecialchars($this->rawFieldContent);\r
+                       }\r
+               }\r
+               return $result;\r
+       }\r
+\r
+}\r
+\r
+\r
+\r
+/**\r
+ * UniversalFeedCreator lets you choose during runtime which\r
+ * format to build.\r
+ * For general usage of a feed class, see the FeedCreator class\r
+ * below or the example above.\r
+ *\r
+ * @since 1.3\r
+ * @author Kai Blankenhorn <kaib@bitfolge.de>\r
+ */\r
+class UniversalFeedCreator extends FeedCreator {\r
+       var $_feed;\r
+       \r
+       function _setFormat($format) {\r
+               switch (strtoupper($format)) {\r
+                       \r
+                       case "2.0":\r
+                               // fall through\r
+                       case "RSS2.0":\r
+                               $this->_feed = new RSSCreator20();\r
+                               break;\r
+                       \r
+                       case "1.0":\r
+                               // fall through\r
+                       case "RSS1.0":\r
+                               $this->_feed = new RSSCreator10();\r
+                               break;\r
+                       \r
+                       case "0.91":\r
+                               // fall through\r
+                       case "RSS0.91":\r
+                               $this->_feed = new RSSCreator091();\r
+                               break;\r
+                       \r
+                       case "PIE0.1":\r
+                               $this->_feed = new PIECreator01();\r
+                               break;\r
+                       \r
+                       case "MBOX":\r
+                               $this->_feed = new MBOXCreator();\r
+                               break;\r
+                       \r
+                       case "OPML":\r
+                               $this->_feed = new OPMLCreator();\r
+                               break;\r
+                               \r
+                       case "ATOM":\r
+                               // fall through: always the latest ATOM version\r
+                               \r
+                       case "ATOM0.3":\r
+                               $this->_feed = new AtomCreator03();\r
+                               break;\r
+                               \r
+                       case "HTML":\r
+                               $this->_feed = new HTMLCreator();\r
+                               break;\r
+                       \r
+                       case "JS":\r
+                               // fall through\r
+                       case "JAVASCRIPT":\r
+                               $this->_feed = new JSCreator();\r
+                               break;\r
+                       \r
+                       default:\r
+                               $this->_feed = new RSSCreator091();\r
+                               break;\r
+               }\r
+        \r
+               $vars = get_object_vars($this);\r
+               foreach ($vars as $key => $value) {\r
+                       // prevent overwriting of properties "contentType", "encoding"; do not copy "_feed" itself\r
+                       if (!in_array($key, array("_feed", "contentType", "encoding"))) {\r
+                               $this->_feed->{$key} = $this->{$key};\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Creates a syndication feed based on the items previously added.\r
+        *\r
+        * @see        FeedCreator::addItem()\r
+        * @param    string    format    format the feed should comply to. Valid values are:\r
+        *                      "PIE0.1", "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM0.3", "HTML", "JS"\r
+        * @return    string    the contents of the feed.\r
+        */\r
+       function createFeed($format = "RSS0.91") {\r
+               $this->_setFormat($format);\r
+               return $this->_feed->createFeed();\r
+       }\r
+       \r
+       \r
+       \r
+       /**\r
+        * Saves this feed as a file on the local disk. After the file is saved, an HTTP redirect\r
+        * header may be sent to redirect the use to the newly created file.\r
+        * @since 1.4\r
+        * \r
+        * @param       string  format  format the feed should comply to. Valid values are:\r
+        *                      "PIE0.1" (deprecated), "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM", "ATOM0.3", "HTML", "JS"\r
+        * @param       string  filename        optional        the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).\r
+        * @param       boolean displayContents optional        send the content of the file or not. If true, the file will be sent in the body of the response.\r
+        */\r
+       function saveFeed($format="RSS0.91", $filename="", $displayContents=true) {\r
+               $this->_setFormat($format);\r
+               $this->_feed->saveFeed($filename, $displayContents);\r
+       }\r
+\r
+\r
+   /**\r
+    * Turns on caching and checks if there is a recent version of this feed in the cache.\r
+    * If there is, an HTTP redirect header is sent.\r
+    * To effectively use caching, you should create the FeedCreator object and call this method\r
+    * before anything else, especially before you do the time consuming task to build the feed\r
+    * (web fetching, for example).\r
+    *\r
+    * @param   string   format   format the feed should comply to. Valid values are:\r
+    *       "PIE0.1" (deprecated), "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM0.3".\r
+    * @param filename   string   optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).\r
+    * @param timeout int      optional the timeout in seconds before a cached version is refreshed (defaults to 3600 = 1 hour)\r
+    */\r
+   function useCached($format="RSS0.91", $filename="", $timeout=3600) {\r
+      $this->_setFormat($format);\r
+      $this->_feed->useCached($filename, $timeout);\r
+   }\r
+\r
+}\r
+\r
+\r
+/**\r
+ * FeedCreator is the abstract base implementation for concrete\r
+ * implementations that implement a specific format of syndication.\r
+ *\r
+ * @abstract\r
+ * @author Kai Blankenhorn <kaib@bitfolge.de>\r
+ * @since 1.4\r
+ */\r
+class FeedCreator extends HtmlDescribable {\r
+\r
+       /**\r
+        * Mandatory attributes of a feed.\r
+        */\r
+       var $title, $description, $link;\r
+       \r
+       //var $my_charset;\r
+       /**\r
+        * Optional attributes of a feed.\r
+        */\r
+       var $syndicationURL, $image, $language, $copyright, $pubDate, $lastBuildDate, $editor, $editorEmail, $webmaster, $category, $docs, $ttl, $rating, $skipHours, $skipDays;\r
+\r
+       /**\r
+       * The url of the external xsl stylesheet used to format the naked rss feed.\r
+       * Ignored in the output when empty.\r
+       */\r
+       var $xslStyleSheet = "";\r
+       \r
+       \r
+       /**\r
+        * @access private\r
+        */\r
+       var $items = Array();\r
+       \r
+       \r
+       /**\r
+        * This feed's MIME content type.\r
+        * @since 1.4\r
+        * @access private\r
+        */\r
+       var $contentType = "application/xml";\r
+       \r
+       \r
+       /**\r
+        * This feed's character encoding.\r
+        * @since 1.6.1\r
+        **/\r
+        //Modified to accommodate ATutor charsets\r
+        //Greg Gay\r
+\r
+       //var $encoding = MY_ENCODING;\r
+       var $encoding =  "utf-8";\r
+       //var $encoding =  "ISO-8859-1";\r
+       \r
+       \r
+       /**\r
+        * Any additional elements to include as an assiciated array. All $key => $value pairs\r
+        * will be included unencoded in the feed in the form\r
+        *     <$key>$value</$key>\r
+        * Again: No encoding will be used! This means you can invalidate or enhance the feed\r
+        * if $value contains markup. This may be abused to embed tags not implemented by\r
+        * the FeedCreator class used.\r
+        */\r
+       var $additionalElements = Array();\r
+   \r
+    \r
+       /**\r
+        * Adds an FeedItem to the feed.\r
+        *\r
+        * @param object FeedItem $item The FeedItem to add to the feed.\r
+        * @access public\r
+        */\r
+       function addItem($item) {\r
+               $this->items[] = $item;\r
+       }\r
+       \r
+       \r
+       /**\r
+        * Truncates a string to a certain length at the most sensible point.\r
+        * First, if there's a '.' character near the end of the string, the string is truncated after this character.\r
+        * If there is no '.', the string is truncated after the last ' ' character.\r
+        * If the string is truncated, " ..." is appended.\r
+        * If the string is already shorter than $length, it is returned unchanged.\r
+        * \r
+        * @static\r
+        * @param string    string A string to be truncated.\r
+        * @param int        length the maximum length the string should be truncated to\r
+        * @return string    the truncated string\r
+        */\r
+       function iTrunc($string, $length) {\r
+               if (strlen($string)<=$length) {\r
+                       return $string;\r
+               }\r
+               \r
+               $pos = strrpos($string,".");\r
+               if ($pos>=$length-4) {\r
+                       $string = substr($string,0,$length-4);\r
+                       $pos = strrpos($string,".");\r
+               }\r
+               if ($pos>=$length*0.4) {\r
+                       return substr($string,0,$pos+1)." ...";\r
+               }\r
+               \r
+               $pos = strrpos($string," ");\r
+               if ($pos>=$length-4) {\r
+                       $string = substr($string,0,$length-4);\r
+                       $pos = strrpos($string," ");\r
+               }\r
+               if ($pos>=$length*0.4) {\r
+                       return substr($string,0,$pos)." ...";\r
+               }\r
+               \r
+               return substr($string,0,$length-4)." ...";\r
+                       \r
+       }\r
+       \r
+       \r
+       /**\r
+        * Creates a comment indicating the generator of this feed.\r
+        * The format of this comment seems to be recognized by\r
+        * Syndic8.com.\r
+        */\r
+       function _createGeneratorComment() {\r
+               return "<!-- generator=\"".FEEDCREATOR_VERSION."\" -->\n";\r
+       }\r
+       \r
+       \r
+       /**\r
+        * Creates a string containing all additional elements specified in\r
+        * $additionalElements.\r
+        * @param       elements        array   an associative array containing key => value pairs\r
+        * @param indentString  string  a string that will be inserted before every generated line\r
+        * @return    string    the XML tags corresponding to $additionalElements\r
+        */\r
+       function _createAdditionalElements($elements, $indentString="") {\r
+               $ae = "";\r
+               if (is_array($elements)) {\r
+                       foreach($elements AS $key => $value) {\r
+                               $ae.= $indentString."<$key>$value</$key>\n";\r
+                       }\r
+               }\r
+               return $ae;\r
+       }\r
+       \r
+       function _createStylesheetReferences() {\r
+               $xml = "";\r
+               if ($this->cssStyleSheet) $xml .= "<?xml-stylesheet href=\"".$this->cssStyleSheet."\" type=\"text/css\"?>\n";\r
+               if ($this->xslStyleSheet) $xml .= "<?xml-stylesheet href=\"".$this->xslStyleSheet."\" type=\"text/xsl\"?>\n";\r
+               return $xml;\r
+       }\r
+       \r
+       \r
+       /**\r
+        * Builds the feed's text.\r
+        * @abstract\r
+        * @return    string    the feed's complete text \r
+        */\r
+       function createFeed() {\r
+       }\r
+       \r
+       /**\r
+        * Generate a filename for the feed cache file. The result will be $_SERVER["PHP_SELF"] with the extension changed to .xml.\r
+        * For example:\r
+        * \r
+        * echo $_SERVER["PHP_SELF"]."\n";\r
+        * echo FeedCreator::_generateFilename();\r
+        * \r
+        * would produce:\r
+        * \r
+        * /rss/latestnews.php\r
+        * latestnews.xml\r
+        *\r
+        * @return string the feed cache filename\r
+        * @since 1.4\r
+        * @access private\r
+        */\r
+       function _generateFilename() {\r
+               $fileInfo = pathinfo($_SERVER["PHP_SELF"]);\r
+               return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".xml";\r
+       }\r
+       \r
+       \r
+       /**\r
+        * @since 1.4\r
+        * @access private\r
+        */\r
+       function _redirect($filename) {\r
+               // attention, heavily-commented-out-area\r
+               \r
+               // maybe use this in addition to file time checking\r
+               //Header("Expires: ".date("r",time()+$this->_timeout));\r
+               \r
+               /* no caching at all, doesn't seem to work as good:\r
+               Header("Cache-Control: no-cache");\r
+               Header("Pragma: no-cache");\r
+               */\r
+               \r
+               // HTTP redirect, some feed readers' simple HTTP implementations don't follow it\r
+               //Header("Location: ".$filename);\r
+\r
+               Header("Content-Type: ".$this->contentType."; charset=".$this->encoding."; filename=".basename($filename));\r
+               Header("Content-Disposition: inline; filename=".basename($filename));\r
+               readfile($filename, "r");\r
+               die();\r
+       }\r
+    \r
+       /**\r
+        * Turns on caching and checks if there is a recent version of this feed in the cache.\r
+        * If there is, an HTTP redirect header is sent.\r
+        * To effectively use caching, you should create the FeedCreator object and call this method\r
+        * before anything else, especially before you do the time consuming task to build the feed\r
+        * (web fetching, for example).\r
+        * @since 1.4\r
+        * @param filename      string  optional        the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).\r
+        * @param timeout       int             optional        the timeout in seconds before a cached version is refreshed (defaults to 3600 = 1 hour)\r
+        */\r
+       function useCached($filename="", $timeout=3600) {\r
+               $this->_timeout = $timeout;\r
+               if ($filename=="") {\r
+                       $filename = $this->_generateFilename();\r
+               }\r
+               if (file_exists($filename) AND (time()-filemtime($filename) < $timeout)) {\r
+                       $this->_redirect($filename);\r
+               }\r
+       }\r
+       \r
+       \r
+       /**\r
+        * Saves this feed as a file on the local disk. After the file is saved, a redirect\r
+        * header may be sent to redirect the user to the newly created file.\r
+        * @since 1.4\r
+        * \r
+        * @param filename      string  optional        the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).\r
+        * @param redirect      boolean optional        send an HTTP redirect header or not. If true, the user will be automatically redirected to the created file.\r
+        */\r
+       function saveFeed($filename="", $displayContents=true) {\r
+               if ($filename=="") {\r
+                       $filename = $this->_generateFilename();\r
+               }\r
+               $feedFile = fopen($filename, "w+");\r
+               if ($feedFile) {\r
+                       fputs($feedFile,$this->createFeed());\r
+                       fclose($feedFile);\r
+                       if ($displayContents) {\r
+                               $this->_redirect($filename);\r
+                       }\r
+               } else {\r
+                       echo "<br /><b>Error creating feed file, please check write permissions.</b><br />";\r
+               }\r
+       }\r
+       \r
+}\r
+\r
+\r
+/**\r
+ * FeedDate is an internal class that stores a date for a feed or feed item.\r
+ * Usually, you won't need to use this.\r
+ */\r
+class FeedDate {\r
+       var $unix;\r
+       \r
+       /**\r
+        * Creates a new instance of FeedDate representing a given date.\r
+        * Accepts RFC 822, ISO 8601 date formats as well as unix time stamps.\r
+        * @param mixed $dateString optional the date this FeedDate will represent. If not specified, the current date and time is used.\r
+        */\r
+       function FeedDate($dateString="") {\r
+               if ($dateString=="") $dateString = date("r");\r
+               \r
+               if (is_integer($dateString)) {\r
+                       $this->unix = $dateString;\r
+                       return;\r
+               }\r
+               if (preg_match("~(?:(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),\\s+)?(\\d{1,2})\\s+([a-zA-Z]{3})\\s+(\\d{4})\\s+(\\d{2}):(\\d{2}):(\\d{2})\\s+(.*)~",$dateString,$matches)) {\r
+                       $months = Array("Jan"=>1,"Feb"=>2,"Mar"=>3,"Apr"=>4,"May"=>5,"Jun"=>6,"Jul"=>7,"Aug"=>8,"Sep"=>9,"Oct"=>10,"Nov"=>11,"Dec"=>12);\r
+                       $this->unix = mktime($matches[4],$matches[5],$matches[6],$months[$matches[2]],$matches[1],$matches[3]);\r
+                       if (substr($matches[7],0,1)=='+' OR substr($matches[7],0,1)=='-') {\r
+                               $tzOffset = (substr($matches[7],0,3) * 60 + substr($matches[7],-2)) * 60;\r
+                       } else {\r
+                               if (strlen($matches[7])==1) {\r
+                                       $oneHour = 3600;\r
+                                       $ord = ord($matches[7]);\r
+                                       if ($ord < ord("M")) {\r
+                                               $tzOffset = (ord("A") - $ord - 1) * $oneHour;\r
+                                       } elseif ($ord >= ord("M") AND $matches[7]!="Z") {\r
+                                               $tzOffset = ($ord - ord("M")) * $oneHour;\r
+                                       } elseif ($matches[7]=="Z") {\r
+                                               $tzOffset = 0;\r
+                                       }\r
+                               }\r
+                               switch ($matches[7]) {\r
+                                       case "UT":\r
+                                       case "GMT":     $tzOffset = 0;\r
+                               }\r
+                       }\r
+                       $this->unix += $tzOffset;\r
+                       return;\r
+               }\r
+               if (preg_match("~(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(.*)~",$dateString,$matches)) {\r
+                       $this->unix = mktime($matches[4],$matches[5],$matches[6],$matches[2],$matches[3],$matches[1]);\r
+                       if (substr($matches[7],0,1)=='+' OR substr($matches[7],0,1)=='-') {\r
+                               $tzOffset = (substr($matches[7],0,3) * 60 + substr($matches[7],-2)) * 60;\r
+                       } else {\r
+                               if ($matches[7]=="Z") {\r
+                                       $tzOffset = 0;\r
+                               }\r
+                       }\r
+                       $this->unix += $tzOffset;\r
+                       return;\r
+               }\r
+               $this->unix = 0;\r
+       }\r
+\r
+       /**\r
+        * Gets the date stored in this FeedDate as an RFC 822 date.\r
+        *\r
+        * @return a date in RFC 822 format\r
+        */\r
+       function rfc822() {\r
+               //return gmdate("r",$this->unix);\r
+               $date = gmdate("D, d M Y H:i:s", $this->unix);\r
+               if (TIME_ZONE!="") $date .= " ".str_replace(":","",TIME_ZONE);\r
+               return $date;\r
+       }\r
+       \r
+       /**\r
+        * Gets the date stored in this FeedDate as an ISO 8601 date.\r
+        *\r
+        * @return a date in ISO 8601 format\r
+        */\r
+       function iso8601() {\r
+               $date = gmdate("Y-m-d\TH:i:sO",$this->unix);\r
+               $date = substr($date,0,22) . ':' . substr($date,-2);\r
+               if (TIME_ZONE!="") $date = str_replace("+00:00",TIME_ZONE,$date);\r
+               return $date;\r
+       }\r
+       \r
+       /**\r
+        * Gets the date stored in this FeedDate as unix time stamp.\r
+        *\r
+        * @return a date as a unix time stamp\r
+        */\r
+       function unix() {\r
+               return $this->unix;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * RSSCreator10 is a FeedCreator that implements RDF Site Summary (RSS) 1.0.\r
+ *\r
+ * @see http://www.purl.org/rss/1.0/\r
+ * @since 1.3\r
+ * @author Kai Blankenhorn <kaib@bitfolge.de>\r
+ */\r
+class RSSCreator10 extends FeedCreator {\r
+\r
+       /**\r
+        * Builds the RSS feed's text. The feed will be compliant to RDF Site Summary (RSS) 1.0.\r
+        * The feed will contain all items previously added in the same order.\r
+        * @return    string    the feed's complete text \r
+        */\r
+       function createFeed() {     \r
+               $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";\r
+               $feed.= $this->_createGeneratorComment();\r
+               if ($this->cssStyleSheet=="") {\r
+                       $cssStyleSheet = "http://www.w3.org/2000/08/w3c-synd/style.css";\r
+               }\r
+               $feed.= $this->_createStylesheetReferences();\r
+               $feed.= "<rdf:RDF\n";\r
+               $feed.= "    xmlns=\"http://purl.org/rss/1.0/\"\n";\r
+               $feed.= "    xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n"; \r
+               $feed.= "    xmlns:slash=\"http://purl.org/rss/1.0/modules/slash/\"\n";\r
+               $feed.= "    xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n";\r
+               $feed.= "    <channel rdf:about=\"".$this->syndicationURL."\">\n";\r
+               $feed.= "        <title>".htmlspecialchars($this->title)."</title>\n";\r
+               $feed.= "        <description>".htmlspecialchars($this->description)."</description>\n";\r
+               $feed.= "        <link>".$this->link."</link>\n";\r
+               if ($this->image!=null) {\r
+                       $feed.= "        <image rdf:resource=\"".$this->image->url."\" />\n";\r
+               }\r
+               $now = new FeedDate();\r
+               $feed.= "       <dc:date>".htmlspecialchars($now->iso8601())."</dc:date>\n";\r
+               $feed.= "        <items>\n";\r
+               $feed.= "            <rdf:Seq>\n";\r
+               for ($i=0;$i<count($this->items);$i++) {\r
+                       $feed.= "                <rdf:li rdf:resource=\"".htmlspecialchars($this->items[$i]->link)."\"/>\n";\r
+               }\r
+               $feed.= "            </rdf:Seq>\n";\r
+               $feed.= "        </items>\n";\r
+               $feed.= "    </channel>\n";\r
+               if ($this->image!=null) {\r
+                       $feed.= "    <image rdf:about=\"".$this->image->url."\">\n";\r
+                       $feed.= "        <title>".$this->image->title."</title>\n";\r
+                       $feed.= "        <link>".$this->image->link."</link>\n";\r
+                       $feed.= "        <url>".$this->image->url."</url>\n";\r
+                       $feed.= "    </image>\n";\r
+               }\r
+               $feed.= $this->_createAdditionalElements($this->additionalElements, "    ");\r
+               \r
+               for ($i=0;$i<count($this->items);$i++) {\r
+                       $feed.= "    <item rdf:about=\"".htmlspecialchars($this->items[$i]->link)."\">\n";\r
+                       //$feed.= "        <dc:type>Posting</dc:type>\n";\r
+                       $feed.= "        <dc:format>text/html</dc:format>\n";\r
+                       if ($this->items[$i]->date!=null) {\r
+                               $itemDate = new FeedDate($this->items[$i]->date);\r
+                               $feed.= "        <dc:date>".htmlspecialchars($itemDate->iso8601())."</dc:date>\n";\r
+                       }\r
+                       if ($this->items[$i]->source!="") {\r
+                               $feed.= "        <dc:source>".htmlspecialchars($this->items[$i]->source)."</dc:source>\n";\r
+                       }\r
+                       if ($this->items[$i]->author!="") {\r
+                               $feed.= "        <dc:creator>".htmlspecialchars($this->items[$i]->author)."</dc:creator>\n";\r
+                       }\r
+                       $feed.= "        <title>".htmlspecialchars(strip_tags(strtr($this->items[$i]->title,"\n\r","  ")))."</title>\n";\r
+                       $feed.= "        <link>".htmlspecialchars($this->items[$i]->link)."</link>\n";\r
+                       $feed.= "        <description>".htmlspecialchars($this->items[$i]->description)."</description>\n";\r
+                       $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, "        ");\r
+                       $feed.= "    </item>\n";\r
+               }\r
+               $feed.= "</rdf:RDF>\n";\r
+               return $feed;\r
+       }\r
+}\r
+\r
+\r
+\r
+/**\r
+ * RSSCreator091 is a FeedCreator that implements RSS 0.91 Spec, revision 3.\r
+ *\r
+ * @see http://my.netscape.com/publish/formats/rss-spec-0.91.html\r
+ * @since 1.3\r
+ * @author Kai Blankenhorn <kaib@bitfolge.de>\r
+ */\r
+class RSSCreator091 extends FeedCreator {\r
+\r
+       /**\r
+        * Stores this RSS feed's version number.\r
+        * @access private\r
+        */\r
+       var $RSSVersion;\r
+\r
+       function RSSCreator091() {\r
+               $this->_setRSSVersion("0.91");\r
+               $this->contentType = "application/rss+xml";\r
+       }\r
+       \r
+       /**\r
+        * Sets this RSS feed's version number.\r
+        * @access private\r
+        */\r
+       function _setRSSVersion($version) {\r
+               $this->RSSVersion = $version;\r
+       }\r
+\r
+       /**\r
+        * Builds the RSS feed's text. The feed will be compliant to RDF Site Summary (RSS) 1.0.\r
+        * The feed will contain all items previously added in the same order.\r
+        * @return    string    the feed's complete text \r
+        */\r
+       function createFeed() {\r
+               $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";\r
+               $feed.= $this->_createGeneratorComment();\r
+               $feed.= $this->_createStylesheetReferences();\r
+               $feed.= "<rss version=\"".$this->RSSVersion."\">\n"; \r
+               $feed.= "    <channel>\n";\r
+               $feed.= "        <title>".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</title>\n";\r
+               $this->descriptionTruncSize = 500;\r
+               $feed.= "        <description>".$this->getDescription()."</description>\n";\r
+               $feed.= "        <link>".$this->link."</link>\n";\r
+               $now = new FeedDate();\r
+               $feed.= "        <lastBuildDate>".htmlspecialchars($now->rfc822())."</lastBuildDate>\n";\r
+               $feed.= "        <generator>".FEEDCREATOR_VERSION."</generator>\n";\r
+\r
+               if ($this->image!=null) {\r
+                       $feed.= "        <image>\n";\r
+                       $feed.= "            <url>".$this->image->url."</url>\n"; \r
+                       $feed.= "            <title>".FeedCreator::iTrunc(htmlspecialchars($this->image->title),100)."</title>\n"; \r
+                       $feed.= "            <link>".$this->image->link."</link>\n";\r
+                       if ($this->image->width!="") {\r
+                               $feed.= "            <width>".$this->image->width."</width>\n";\r
+                       }\r
+                       if ($this->image->height!="") {\r
+                               $feed.= "            <height>".$this->image->height."</height>\n";\r
+                       }\r
+                       if ($this->image->description!="") {\r
+                               $feed.= "            <description>".$this->image->getDescription()."</description>\n";\r
+                       }\r
+                       $feed.= "        </image>\n";\r
+               }\r
+               if ($this->language!="") {\r
+                       $feed.= "        <language>".$this->language."</language>\n";\r
+               }\r
+               if ($this->copyright!="") {\r
+                       $feed.= "        <copyright>".FeedCreator::iTrunc(htmlspecialchars($this->copyright),100)."</copyright>\n";\r
+               }\r
+               if ($this->editor!="") {\r
+                       $feed.= "        <managingEditor>".FeedCreator::iTrunc(htmlspecialchars($this->editor),100)."</managingEditor>\n";\r
+               }\r
+               if ($this->webmaster!="") {\r
+                       $feed.= "        <webMaster>".FeedCreator::iTrunc(htmlspecialchars($this->webmaster),100)."</webMaster>\n";\r
+               }\r
+               if ($this->pubDate!="") {\r
+                       $pubDate = new FeedDate($this->pubDate);\r
+                       $feed.= "        <pubDate>".htmlspecialchars($pubDate->rfc822())."</pubDate>\n";\r
+               }\r
+               if ($this->category!="") {\r
+                       $feed.= "        <category>".htmlspecialchars($this->category)."</category>\n";\r
+               }\r
+               if ($this->docs!="") {\r
+                       $feed.= "        <docs>".FeedCreator::iTrunc(htmlspecialchars($this->docs),500)."</docs>\n";\r
+               }\r
+               if ($this->ttl!="") {\r
+                       $feed.= "        <ttl>".htmlspecialchars($this->ttl)."</ttl>\n";\r
+               }\r
+               if ($this->rating!="") {\r
+                       $feed.= "        <rating>".FeedCreator::iTrunc(htmlspecialchars($this->rating),500)."</rating>\n";\r
+               }\r
+               if ($this->skipHours!="") {\r
+                       $feed.= "        <skipHours>".htmlspecialchars($this->skipHours)."</skipHours>\n";\r
+               }\r
+               if ($this->skipDays!="") {\r
+                       $feed.= "        <skipDays>".htmlspecialchars($this->skipDays)."</skipDays>\n";\r
+               }\r
+               $feed.= $this->_createAdditionalElements($this->additionalElements, "    ");\r
+\r
+               for ($i=0;$i<count($this->items);$i++) {\r
+                       $feed.= "        <item>\n";\r
+                       $feed.= "            <title>".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100)."</title>\n";\r
+                       $feed.= "            <link>".htmlspecialchars($this->items[$i]->link)."</link>\n";\r
+                       $feed.= "            <description>".$this->items[$i]->getDescription()."</description>\n";\r
+                       \r
+                       if ($this->items[$i]->author!="") {\r
+                               $feed.= "            <author>".htmlspecialchars($this->items[$i]->author)."</author>\n";\r
+                       }\r
+                       /*\r
+                       // on hold\r
+                       if ($this->items[$i]->source!="") {\r
+                                       $feed.= "            <source>".htmlspecialchars($this->items[$i]->source)."</source>\n";\r
+                       }\r
+                       */\r
+                       if ($this->items[$i]->category!="") {\r
+                               $feed.= "            <category>".htmlspecialchars($this->items[$i]->category)."</category>\n";\r
+                       }\r
+                       if ($this->items[$i]->comments!="") {\r
+                               $feed.= "            <comments>".htmlspecialchars($this->items[$i]->comments)."</comments>\n";\r
+                       }\r
+                       if ($this->items[$i]->date!="") {\r
+                       $itemDate = new FeedDate($this->items[$i]->date);\r
+                               $feed.= "            <pubDate>".htmlspecialchars($itemDate->rfc822())."</pubDate>\n";\r
+                       }\r
+                       if ($this->items[$i]->guid!="") {\r
+                               $feed.= "            <guid>".htmlspecialchars($this->items[$i]->guid)."</guid>\n";\r
+                       }\r
+                       $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, "        ");\r
+                       $feed.= "        </item>\n";\r
+               }\r
+               $feed.= "    </channel>\n";\r
+               $feed.= "</rss>\n";\r
+               return $feed;\r
+       }\r
+}\r
+\r
+\r
+\r
+/**\r
+ * RSSCreator20 is a FeedCreator that implements RDF Site Summary (RSS) 2.0.\r
+ *\r
+ * @see http://backend.userland.com/rss\r
+ * @since 1.3\r
+ * @author Kai Blankenhorn <kaib@bitfolge.de>\r
+ */\r
+class RSSCreator20 extends RSSCreator091 {\r
+\r
+    function RSSCreator20() {\r
+        parent::_setRSSVersion("2.0");\r
+    }\r
+    \r
+}\r
+\r
+\r
+/**\r
+ * PIECreator01 is a FeedCreator that implements the emerging PIE specification,\r
+ * as in http://intertwingly.net/wiki/pie/Syntax.\r
+ *\r
+ * @deprecated\r
+ * @since 1.3\r
+ * @author Scott Reynen <scott@randomchaos.com> and Kai Blankenhorn <kaib@bitfolge.de>\r
+ */\r
+class PIECreator01 extends FeedCreator {\r
+       \r
+       function PIECreator01() {\r
+               $this->encoding = "utf-8";\r
+       }\r
+    \r
+       function createFeed() {\r
+               $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";\r
+               $feed.= $this->_createStylesheetReferences();\r
+               $feed.= "<feed version=\"0.1\" xmlns=\"http://example.com/newformat#\">\n"; \r
+               $feed.= "    <title>".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</title>\n";\r
+               $this->truncSize = 500;\r
+               $feed.= "    <subtitle>".$this->getDescription()."</subtitle>\n";\r
+               $feed.= "    <link>".$this->link."</link>\n";\r
+               for ($i=0;$i<count($this->items);$i++) {\r
+                       $feed.= "    <entry>\n";\r
+                       $feed.= "        <title>".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100)."</title>\n";\r
+                       $feed.= "        <link>".htmlspecialchars($this->items[$i]->link)."</link>\n";\r
+                       $itemDate = new FeedDate($this->items[$i]->date);\r
+                       $feed.= "        <created>".htmlspecialchars($itemDate->iso8601())."</created>\n";\r
+                       $feed.= "        <issued>".htmlspecialchars($itemDate->iso8601())."</issued>\n";\r
+                       $feed.= "        <modified>".htmlspecialchars($itemDate->iso8601())."</modified>\n";\r
+                       $feed.= "        <id>".htmlspecialchars($this->items[$i]->guid)."</id>\n";\r
+                       if ($this->items[$i]->author!="") {\r
+                               $feed.= "        <author>\n";\r
+                               $feed.= "            <name>".htmlspecialchars($this->items[$i]->author)."</name>\n";\r
+                               if ($this->items[$i]->authorEmail!="") {\r
+                                       $feed.= "            <email>".$this->items[$i]->authorEmail."</email>\n";\r
+                               }\r
+                               $feed.="        </author>\n";\r
+                       }\r
+                       $feed.= "        <content type=\"text/html\" xml:lang=\"en-us\">\n";\r
+                       $feed.= "            <div xmlns=\"http://www.w3.org/1999/xhtml\">".$this->items[$i]->getDescription()."</div>\n";\r
+                       $feed.= "        </content>\n";\r
+                       $feed.= "    </entry>\n";\r
+               }\r
+               $feed.= "</feed>\n";\r
+               return $feed;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * AtomCreator03 is a FeedCreator that implements the atom specification,\r
+ * as in http://www.intertwingly.net/wiki/pie/FrontPage.\r
+ * Please note that just by using AtomCreator03 you won't automatically\r
+ * produce valid atom files. For example, you have to specify either an editor\r
+ * for the feed or an author for every single feed item.\r
+ *\r
+ * Some elements have not been implemented yet. These are (incomplete list):\r
+ * author URL, item author's email and URL, item contents, alternate links, \r
+ * other link content types than text/html. Some of them may be created with\r
+ * AtomCreator03::additionalElements.\r
+ *\r
+ * @see FeedCreator#additionalElements\r
+ * @since 1.6\r
+ * @author Kai Blankenhorn <kaib@bitfolge.de>, Scott Reynen <scott@randomchaos.com>\r
+ */\r
+class AtomCreator03 extends FeedCreator {\r
+\r
+       function AtomCreator03() {\r
+               $this->contentType = "application/atom+xml";\r
+               $this->encoding = "utf-8";\r
+       }\r
+       \r
+       function createFeed() {\r
+               $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";\r
+               $feed.= $this->_createGeneratorComment();\r
+               $feed.= $this->_createStylesheetReferences();\r
+               $feed.= "<feed version=\"0.3\" xmlns=\"http://purl.org/atom/ns#\"";\r
+               if ($this->language!="") {\r
+                       $feed.= " xml:lang=\"".$this->language."\"";\r
+               }\r
+               $feed.= ">\n"; \r
+               $feed.= "    <title>".htmlspecialchars($this->title)."</title>\n";\r
+               $feed.= "    <tagline>".htmlspecialchars($this->description)."</tagline>\n";\r
+               $feed.= "    <link rel=\"alternate\" type=\"text/html\" href=\"".htmlspecialchars($this->link)."\"/>\n";\r
+               $feed.= "    <id>".htmlspecialchars($this->link)."</id>\n";\r
+               $now = new FeedDate();\r
+               $feed.= "    <modified>".htmlspecialchars($now->iso8601())."</modified>\n";\r
+               if ($this->editor!="") {\r
+                       $feed.= "    <author>\n";\r
+                       $feed.= "        <name>".$this->editor."</name>\n";\r
+                       if ($this->editorEmail!="") {\r
+                               $feed.= "        <email>".$this->editorEmail."</email>\n";\r
+                       }\r
+                       $feed.= "    </author>\n";\r
+               }\r
+               $feed.= "    <generator>".FEEDCREATOR_VERSION."</generator>\n";\r
+               $feed.= $this->_createAdditionalElements($this->additionalElements, "    ");\r
+               for ($i=0;$i<count($this->items);$i++) {\r
+                       $feed.= "    <entry>\n";\r
+                       $feed.= "        <title>".htmlspecialchars(strip_tags($this->items[$i]->title))."</title>\n";\r
+                       $feed.= "        <link rel=\"alternate\" type=\"text/html\" href=\"".htmlspecialchars($this->items[$i]->link)."\"/>\n";\r
+                       if ($this->items[$i]->date=="") {\r
+                               $this->items[$i]->date = time();\r
+                       }\r
+                       $itemDate = new FeedDate($this->items[$i]->date);\r
+                       $feed.= "        <created>".htmlspecialchars($itemDate->iso8601())."</created>\n";\r
+                       $feed.= "        <issued>".htmlspecialchars($itemDate->iso8601())."</issued>\n";\r
+                       $feed.= "        <modified>".htmlspecialchars($itemDate->iso8601())."</modified>\n";\r
+                       $feed.= "        <id>".htmlspecialchars($this->items[$i]->link)."</id>\n";\r
+                       $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, "        ");\r
+                       if ($this->items[$i]->author!="") {\r
+                               $feed.= "        <author>\n";\r
+                               $feed.= "            <name>".htmlspecialchars($this->items[$i]->author)."</name>\n";\r
+                               $feed.= "        </author>\n";\r
+                       }\r
+                       if ($this->items[$i]->description!="") {\r
+                               $feed.= "        <summary>".htmlspecialchars($this->items[$i]->description)."</summary>\n";\r
+                       }\r
+                       $feed.= "    </entry>\n";\r
+               }\r
+               $feed.= "</feed>\n";\r
+               return $feed;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * MBOXCreator is a FeedCreator that implements the mbox format\r
+ * as described in http://www.qmail.org/man/man5/mbox.html\r
+ *\r
+ * @since 1.3\r
+ * @author Kai Blankenhorn <kaib@bitfolge.de>\r
+ */\r
+class MBOXCreator extends FeedCreator {\r
+\r
+       function MBOXCreator() {\r
+               $this->contentType = "text/plain";\r
+               $this->encoding = "ISO-8859-15";\r
+       }\r
+    \r
+       function qp_enc($input = "", $line_max = 76) { \r
+               $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); \r
+               $lines = preg_split("/(?:\r\n|\r|\n)/", $input); \r
+               $eol = "\r\n"; \r
+               $escape = "="; \r
+               $output = ""; \r
+               while( list(, $line) = each($lines) ) { \r
+                       //$line = rtrim($line); // remove trailing white space -> no =20\r\n necessary \r
+                       $linlen = strlen($line); \r
+                       $newline = ""; \r
+                       for($i = 0; $i < $linlen; $i++) { \r
+                               $c = substr($line, $i, 1); \r
+                               $dec = ord($c); \r
+                               if ( ($dec == 32) && ($i == ($linlen - 1)) ) { // convert space at eol only \r
+                                       $c = "=20"; \r
+                               } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required \r
+                                       $h2 = floor($dec/16); $h1 = floor($dec%16); \r
+                                       $c = $escape.$hex["$h2"].$hex["$h1"]; \r
+                               } \r
+                               if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted \r
+                                       $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay \r
+                                       $newline = ""; \r
+                               } \r
+                               $newline .= $c; \r
+                       } // end of for \r
+                       $output .= $newline.$eol; \r
+               } \r
+               return trim($output); \r
+       }\r
+       \r
+\r
+       /**\r
+        * Builds the MBOX contents.\r
+        * @return    string    the feed's complete text \r
+        */\r
+       function createFeed() {\r
+               for ($i=0;$i<count($this->items);$i++) {\r
+                       if ($this->items[$i]->author!="") {\r
+                               $from = $this->items[$i]->author;\r
+                       } else {\r
+                               $from = $this->title;\r
+                       }\r
+                       $itemDate = new FeedDate($this->items[$i]->date);\r
+                       $feed.= "From ".strtr(MBOXCreator::qp_enc($from)," ","_")." ".date("D M d H:i:s Y",$itemDate->unix())."\n";\r
+                       $feed.= "Content-Type: text/plain;\n";\r
+                       $feed.= "       charset=\"".$this->encoding."\"\n";\r
+                       $feed.= "Content-Transfer-Encoding: quoted-printable\n";\r
+                       $feed.= "Content-Type: text/plain\n";\r
+                       $feed.= "From: \"".MBOXCreator::qp_enc($from)."\"\n";\r
+                       $feed.= "Date: ".$itemDate->rfc822()."\n";\r
+                       $feed.= "Subject: ".MBOXCreator::qp_enc(FeedCreator::iTrunc($this->items[$i]->title,100))."\n";\r
+                       $feed.= "\n";\r
+                       $body = chunk_split(MBOXCreator::qp_enc($this->items[$i]->description));\r
+                       $feed.= preg_replace("~\nFrom ([^\n]*)(\n?)~","\n>From $1$2\n",$body);\r
+                       $feed.= "\n";\r
+                       $feed.= "\n";\r
+               }\r
+               return $feed;\r
+       }\r
+       \r
+       /**\r
+        * Generate a filename for the feed cache file. Overridden from FeedCreator to prevent XML data types.\r
+        * @return string the feed cache filename\r
+        * @since 1.4\r
+        * @access private\r
+        */\r
+       function _generateFilename() {\r
+               $fileInfo = pathinfo($_SERVER["PHP_SELF"]);\r
+               return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".mbox";\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * OPMLCreator is a FeedCreator that implements OPML 1.0.\r
+ * \r
+ * @see http://opml.scripting.com/spec\r
+ * @author Dirk Clemens, Kai Blankenhorn\r
+ * @since 1.5\r
+ */\r
+class OPMLCreator extends FeedCreator {\r
+\r
+       function OPMLCreator() {\r
+               $this->encoding = "utf-8";\r
+       }\r
+    \r
+       function createFeed() {     \r
+               $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";\r
+               $feed.= $this->_createGeneratorComment();\r
+               $feed.= $this->_createStylesheetReferences();\r
+               $feed.= "<opml xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n";\r
+               $feed.= "    <head>\n";\r
+               $feed.= "        <title>".htmlspecialchars($this->title)."</title>\n";\r
+               if ($this->pubDate!="") {\r
+                       $date = new FeedDate($this->pubDate);\r
+                       $feed.= "         <dateCreated>".$date->rfc822()."</dateCreated>\n";\r
+               }\r
+               if ($this->lastBuildDate!="") {\r
+                       $date = new FeedDate($this->lastBuildDate);\r
+                       $feed.= "         <dateModified>".$date->rfc822()."</dateModified>\n";\r
+               }\r
+               if ($this->editor!="") {\r
+                       $feed.= "         <ownerName>".$this->editor."</ownerName>\n";\r
+               }\r
+               if ($this->editorEmail!="") {\r
+                       $feed.= "         <ownerEmail>".$this->editorEmail."</ownerEmail>\n";\r
+               }\r
+               $feed.= "    </head>\n";\r
+               $feed.= "    <body>\n";\r
+               for ($i=0;$i<count($this->items);$i++) {\r
+                       $feed.= "    <outline type=\"rss\" ";\r
+                       $title = htmlspecialchars(strip_tags(strtr($this->items[$i]->title,"\n\r","  ")));\r
+                       $feed.= " title=\"".$title."\"";\r
+                       $feed.= " text=\"".$title."\"";\r
+                       //$feed.= " description=\"".htmlspecialchars($this->items[$i]->description)."\"";\r
+                       $feed.= " url=\"".htmlspecialchars($this->items[$i]->link)."\"";\r
+                       $feed.= "/>\n";\r
+               }\r
+               $feed.= "    </body>\n";\r
+               $feed.= "</opml>\n";\r
+               return $feed;\r
+       }\r
+}\r
+\r
+\r
+\r
+/**\r
+ * HTMLCreator is a FeedCreator that writes an HTML feed file to a specific \r
+ * location, overriding the createFeed method of the parent FeedCreator.\r
+ * The HTML produced can be included over http by scripting languages, or serve\r
+ * as the source for an IFrame.\r
+ * All output by this class is embedded in <div></div> tags to enable formatting\r
+ * using CSS. \r
+ *\r
+ * @author Pascal Van Hecke\r
+ * @since 1.7\r
+ */\r
+class HTMLCreator extends FeedCreator {\r
+\r
+       var $contentType = "text/html";\r
+       \r
+       /**\r
+        * Contains HTML to be output at the start of the feed's html representation.\r
+        */\r
+       var $header;\r
+       \r
+       /**\r
+        * Contains HTML to be output at the end of the feed's html representation.\r
+        */\r
+       var $footer ;\r
+       \r
+       /**\r
+        * Contains HTML to be output between entries. A separator is only used in \r
+        * case of multiple entries.\r
+        */\r
+       var $separator;\r
+       \r
+       /**\r
+        * Used to prefix the stylenames to make sure they are unique \r
+        * and do not clash with stylenames on the users' page.\r
+        */\r
+       var $stylePrefix;\r
+       \r
+       /**\r
+        * Determines whether the links open in a new window or not.\r
+        */\r
+       var $openInNewWindow = true;\r
+       \r
+       var $imageAlign ="right";\r
+       \r
+       /**\r
+        * In case of very simple output you may want to get rid of the style tags,\r
+        * hence this variable.  There's no equivalent on item level, but of course you can \r
+        * add strings to it while iterating over the items ($this->stylelessOutput .= ...)\r
+        * and when it is non-empty, ONLY the styleless output is printed, the rest is ignored\r
+        * in the function createFeed().\r
+        */\r
+       var $stylelessOutput ="";\r
+\r
+       /**\r
+        * Writes the HTML.\r
+        * @return    string    the scripts's complete text \r
+        */\r
+       function createFeed() {\r
+               // if there is styleless output, use the content of this variable and ignore the rest\r
+               if ($this->stylelessOutput!="") {\r
+                       return $this->stylelessOutput;\r
+               }\r
+               \r
+               //if no stylePrefix is set, generate it yourself depending on the script name\r
+               if ($this->stylePrefix=="") {\r
+                       $this->stylePrefix = str_replace(".", "_", $this->_generateFilename())."_";\r
+               }\r
+\r
+               //set an openInNewWindow_token_to be inserted or not\r
+               if ($this->openInNewWindow) {\r
+                       $targetInsert = " target='_blank'";\r
+               }\r
+               \r
+               // use this array to put the lines in and implode later with "document.write" javascript\r
+               $feedArray = array();\r
+               if ($this->image!=null) {\r
+                       $imageStr = "<a href='".$this->image->link."'".$targetInsert.">".\r
+                                                       "<img src='".$this->image->url."' border='0' alt='".\r
+                                                       FeedCreator::iTrunc(htmlspecialchars($this->image->title),100).\r
+                                                       "' align='".$this->imageAlign."' ";\r
+                       if ($this->image->width) {\r
+                               $imageStr .=" width='".$this->image->width. "' ";\r
+                       }\r
+                       if ($this->image->height) {\r
+                               $imageStr .=" height='".$this->image->height."' ";\r
+                       }\r
+                       $imageStr .="/></a>";\r
+                       $feedArray[] = $imageStr;\r
+               }\r
+               \r
+               if ($this->title) {\r
+                       $feedArray[] = "<div class='".$this->stylePrefix."title'><a href='".$this->link."' ".$targetInsert." class='".$this->stylePrefix."title'>".\r
+                               FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</a></div>";\r
+               }\r
+               if ($this->getDescription()) {\r
+                       $feedArray[] = "<div class='".$this->stylePrefix."description'>".\r
+                               str_replace("]]>", "", str_replace("<![CDATA[", "", $this->getDescription())).\r
+                               "</div>";\r
+               }\r
+               \r
+               if ($this->header) {\r
+                       $feedArray[] = "<div class='".$this->stylePrefix."header'>".$this->header."</div>";\r
+               }\r
+               \r
+               for ($i=0;$i<count($this->items);$i++) {\r
+                       if ($this->separator and $i > 0) {\r
+                               $feedArray[] = "<div class='".$this->stylePrefix."separator'>".$this->separator."</div>";\r
+                       }\r
+                       \r
+                       if ($this->items[$i]->title) {\r
+                               if ($this->items[$i]->link) {\r
+                                       $feedArray[] = \r
+                                               "<div class='".$this->stylePrefix."item_title'><a href='".$this->items[$i]->link."' class='".$this->stylePrefix.\r
+                                               "item_title'".$targetInsert.">".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100).\r
+                                               "</a></div>";\r
+                               } else {\r
+                                       $feedArray[] = \r
+                                               "<div class='".$this->stylePrefix."item_title'>".\r
+                                               FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100).\r
+                                               "</div>";\r
+                               }\r
+                       }\r
+                       if ($this->items[$i]->getDescription()) {\r
+                               $feedArray[] = \r
+                               "<div class='".$this->stylePrefix."item_description'>".\r
+                                       str_replace("]]>", "", str_replace("<![CDATA[", "", $this->items[$i]->getDescription())).\r
+                                       "</div>";\r
+                       }\r
+               }\r
+               if ($this->footer) {\r
+                       $feedArray[] = "<div class='".$this->stylePrefix."footer'>".$this->footer."</div>";\r
+               }\r
+               \r
+               $feed= "".join($feedArray, "\r\n");\r
+               return $feed;\r
+       }\r
+    \r
+       /**\r
+        * Overrrides parent to produce .html extensions\r
+        *\r
+        * @return string the feed cache filename\r
+        * @since 1.4\r
+        * @access private\r
+        */\r
+       function _generateFilename() {\r
+               $fileInfo = pathinfo($_SERVER["PHP_SELF"]);\r
+               return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".html";\r
+       }\r
+}      \r
+\r
+\r
+/**\r
+ * JSCreator is a class that writes a js file to a specific \r
+ * location, overriding the createFeed method of the parent HTMLCreator.\r
+ *\r
+ * @author Pascal Van Hecke\r
+ */\r
+class JSCreator extends HTMLCreator {\r
+       var $contentType = "text/javascript";\r
+       \r
+       /**\r
+        * writes the javascript\r
+        * @return    string    the scripts's complete text \r
+        */\r
+       function createFeed() \r
+       {\r
+               $feed = parent::createFeed();\r
+               $feedArray = explode("\n",$feed);\r
+               \r
+               $jsFeed = "";\r
+               foreach ($feedArray as $value) {\r
+                       $jsFeed .= "document.write('".trim(addslashes($value))."');\n";\r
+               }\r
+               return $jsFeed;\r
+       }\r
+    \r
+       /**\r
+        * Overrrides parent to produce .js extensions\r
+        *\r
+        * @return string the feed cache filename\r
+        * @since 1.4\r
+        * @access private\r
+        */\r
+       function _generateFilename() {\r
+               $fileInfo = pathinfo($_SERVER["PHP_SELF"]);\r
+               return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".js";\r
+       }\r
+       \r
+}      \r
+\r
+\r
+\r
+/*** TEST SCRIPT *********************************************************\r
+\r
+//include("feedcreator.class.php"); \r
+\r
+$rss = new UniversalFeedCreator(); \r
+$rss->useCached(); \r
+$rss->title = "PHP news"; \r
+$rss->description = "daily news from the PHP scripting world"; \r
+\r
+//optional\r
+//$rss->descriptionTruncSize = 500;\r
+//$rss->descriptionHtmlSyndicated = true;\r
+//$rss->xslStyleSheet = "http://feedster.com/rss20.xsl";\r
+\r
+$rss->link = "http://www.dailyphp.net/news"; \r
+$rss->feedURL = "http://www.dailyphp.net/".$PHP_SELF; \r
+\r
+$image = new FeedImage(); \r
+$image->title = "dailyphp.net logo"; \r
+$image->url = "http://www.dailyphp.net/images/logo.gif"; \r
+$image->link = "http://www.dailyphp.net"; \r
+$image->description = "Feed provided by dailyphp.net. Click to visit."; \r
+\r
+//optional\r
+$image->descriptionTruncSize = 500;\r
+$image->descriptionHtmlSyndicated = true;\r
+\r
+$rss->image = $image; \r
+\r
+// get your news items from somewhere, e.g. your database: \r
+//mysql_select_db($dbHost, $dbUser, $dbPass); \r
+//$res = mysql_query("SELECT * FROM news ORDER BY newsdate DESC"); \r
+//while ($data = mysql_fetch_object($res)) { \r
+       $item = new FeedItem(); \r
+       $item->title = "This is an the test title of an item"; \r
+       $item->link = "http://localhost/item/"; \r
+       $item->description = "<b>description in </b><br/>HTML"; \r
+       \r
+       //optional\r
+       //item->descriptionTruncSize = 500;\r
+       $item->descriptionHtmlSyndicated = true;\r
+       \r
+       $item->date = time(); \r
+       $item->source = "http://www.dailyphp.net"; \r
+       $item->author = "John Doe"; \r
+        \r
+       $rss->addItem($item); \r
+//} \r
+\r
+// valid format strings are: RSS0.91, RSS1.0, RSS2.0, PIE0.1, MBOX, OPML, ATOM0.3, HTML, JS\r
+echo $rss->saveFeed("RSS0.91", "feed.xml"); \r
+\r
+\r
+\r
+***************************************************************************/\r
+?>
\ No newline at end of file
diff --git a/include/classes/lastRSS.php b/include/classes/lastRSS.php
new file mode 100644 (file)
index 0000000..b50c540
--- /dev/null
@@ -0,0 +1,226 @@
+<?php\r
+/*\r
+ ======================================================================\r
+ lastRSS 0.9.1\r
\r
+ Simple yet powerfull PHP class to parse RSS files.\r
\r
+ by Vojtech Semecky, webmaster @ webdot . cz\r
\r
+ Latest version, features, manual and examples:\r
+       http://lastrss.webdot.cz/\r
+\r
+ ----------------------------------------------------------------------\r
+ LICENSE\r
+\r
+ This program is free software; you can redistribute it and/or\r
+ modify it under the terms of the GNU General Public License (GPL)\r
+ as published by the Free Software Foundation; either version 2\r
+ of the License, or (at your option) any later version.\r
+\r
+ This program is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ To read the license please visit http://www.gnu.org/copyleft/gpl.html\r
+ ======================================================================\r
+*/\r
+\r
+/**\r
+* lastRSS\r
+* Simple yet powerfull PHP class to parse RSS files.\r
+*/\r
+class lastRSS {\r
+       // -------------------------------------------------------------------\r
+       // Public properties\r
+       // -------------------------------------------------------------------\r
+       var $default_cp = 'UTF-8';\r
+       var $CDATA = 'nochange';\r
+       var $cp = '';\r
+       var $items_limit = 0;\r
+       var $stripHTML = False;\r
+       var $date_format = '';\r
+\r
+       // -------------------------------------------------------------------\r
+       // Private variables\r
+       // -------------------------------------------------------------------\r
+       var $channeltags = array ('title', 'link', 'description', 'language', 'copyright', 'managingEditor', 'webMaster', 'lastBuildDate', 'rating', 'docs');\r
+       var $itemtags = array('title', 'link', 'description', 'author', 'category', 'comments', 'enclosure', 'guid', 'pubDate', 'source');\r
+       var $imagetags = array('title', 'url', 'link', 'width', 'height');\r
+       var $textinputtags = array('title', 'description', 'name', 'link');\r
+\r
+       // -------------------------------------------------------------------\r
+       // Parse RSS file and returns associative array.\r
+       // Get() function modified by Heidi Hazelton\r
+       // -------------------------------------------------------------------\r
+       function Get ($rss_url, $rss_feed_id) {\r
+               \r
+               $output = '';\r
+\r
+               if(!isset($this->num_results)) {\r
+                       $this->num_results = 5;\r
+               }\r
+               if (!isset($this->description)) {\r
+                       $this->description = FALSE;\r
+               }\r
+\r
+               $result = $this->Parse($rss_url);\r
+               if ($result && ($result['items_count'] == 0)) {\r
+                       return null;\r
+               } else if ($result) {\r
+                       $output = "<ul class='rss_feed'>";\r
+                       for ($i=0; $i < min($this->num_results, $result['items_count']) ; $i++) {\r
+                               $output .= "<li><a href='".$result['items'][$i]['link']."' target='_new'>".$result['items'][$i]['title']."</a>";\r
+                               if ($this->description) { $output .= "<br />".$result['items'][$i]['description']; }\r
+                               $output .= "</li>\n";\r
+                       }\r
+                       $output .= "</ul>\n"; \r
+\r
+               } elseif (file_exists($cache_file)) {\r
+                       touch($cache_file);\r
+               } else {\r
+                       //create an empty file\r
+                       if ($f = @fopen($cache_file, 'w')) {\r
+                               fclose($f);\r
+                       }\r
+               }\r
+\r
+               return $output;\r
+       }\r
+       \r
+       // -------------------------------------------------------------------\r
+       // Modification of preg_match(); return trimed field with index 1\r
+       // from 'classic' preg_match() array output\r
+       // -------------------------------------------------------------------\r
+       function my_preg_match ($pattern, $subject) {\r
+               // start regullar expression\r
+               preg_match($pattern, $subject, $out);\r
+\r
+               // if there is some result... process it and return it\r
+               if(isset($out[1])) {\r
+                       // Process CDATA (if present)\r
+                       if ($this->CDATA == 'content') { // Get CDATA content (without CDATA tag)\r
+                               $out[1] = strtr($out[1], array('<![CDATA['=>'', ']]>'=>''));\r
+                       } elseif ($this->CDATA == 'strip') { // Strip CDATA\r
+                               $out[1] = strtr($out[1], array('<![CDATA['=>'', ']]>'=>''));\r
+                       }\r
+\r
+                       // If code page is set convert character encoding to required\r
+                       if ($this->cp != '')\r
+                               //$out[1] = $this->MyConvertEncoding($this->rsscp, $this->cp, $out[1]);\r
+                               $out[1] = iconv($this->rsscp, $this->cp.'//TRANSLIT', $out[1]);\r
+                       // Return result\r
+                       return trim($out[1]);\r
+               } else {\r
+               // if there is NO result, return empty string\r
+                       return '';\r
+               }\r
+       }\r
+\r
+       // -------------------------------------------------------------------\r
+       // Replace HTML entities &something; by real characters\r
+       // -------------------------------------------------------------------\r
+       function unhtmlentities ($string) {\r
+               // Get HTML entities table\r
+               $trans_tbl = get_html_translation_table (HTML_ENTITIES, ENT_QUOTES);\r
+               // Flip keys<==>values\r
+               $trans_tbl = array_flip ($trans_tbl);\r
+               // Add support for &apos; entity (missing in HTML_ENTITIES)\r
+               $trans_tbl += array('&apos;' => "'");\r
+               // Replace entities by values\r
+               return strtr ($string, $trans_tbl);\r
+       }\r
+\r
+       // -------------------------------------------------------------------\r
+       // Parse() is private method used by Get() to load and parse RSS file.\r
+       // Don't use Parse() in your scripts - use Get($rss_file) instead.\r
+       // -------------------------------------------------------------------\r
+       function Parse ($rss_url) {\r
+               // Open and load RSS file\r
+               if ($f = @fopen($rss_url, 'r')) {\r
+                       $rss_content = '';\r
+                       while (!feof($f)) {\r
+                               $rss_content .= fgets($f, 4096);\r
+                       }\r
+                       fclose($f);\r
+\r
+                       // Parse document encoding\r
+                       $result['encoding'] = $this->my_preg_match("'encoding=[\'\"](.*?)[\'\"]'si", $rss_content);\r
+                       // if document codepage is specified, use it\r
+                       if ($result['encoding'] != '')\r
+                               { $this->rsscp = $result['encoding']; } // This is used in my_preg_match()\r
+                       // otherwise use the default codepage\r
+                       else\r
+                               { $this->rsscp = $this->default_cp; } // This is used in my_preg_match()\r
+\r
+                       // Parse CHANNEL info\r
+                       preg_match("'<channel.*?>(.*?)</channel>'si", $rss_content, $out_channel);\r
+                       foreach($this->channeltags as $channeltag)\r
+                       {\r
+                               $temp = $this->my_preg_match("'<$channeltag.*?>(.*?)</$channeltag>'si", $out_channel[1]);\r
+                               if ($temp != '') $result[$channeltag] = $temp; // Set only if not empty\r
+                       }\r
+                       // If date_format is specified and lastBuildDate is valid\r
+                       if ($this->date_format != '' && ($timestamp = strtotime($result['lastBuildDate'])) !==-1) {\r
+                                               // convert lastBuildDate to specified date format\r
+                                               $result['lastBuildDate'] = date($this->date_format, $timestamp);\r
+                       }\r
+\r
+                       // Parse TEXTINPUT info\r
+                       preg_match("'<textinput(|[^>]*[^/])>(.*?)</textinput>'si", $rss_content, $out_textinfo);\r
+                               // This a little strange regexp means:\r
+                               // Look for tag <textinput> with or without any attributes, but skip truncated version <textinput /> (it's not beggining tag)\r
+                       if (isset($out_textinfo[2])) {\r
+                               foreach($this->textinputtags as $textinputtag) {\r
+                                       $temp = $this->my_preg_match("'<$textinputtag.*?>(.*?)</$textinputtag>'si", $out_textinfo[2]);\r
+                                       if ($temp != '') $result['textinput_'.$textinputtag] = $temp; // Set only if not empty\r
+                               }\r
+                       }\r
+                       // Parse IMAGE info\r
+                       preg_match("'<image.*?>(.*?)</image>'si", $rss_content, $out_imageinfo);\r
+                       if (isset($out_imageinfo[1])) {\r
+                               foreach($this->imagetags as $imagetag) {\r
+                                       $temp = $this->my_preg_match("'<$imagetag.*?>(.*?)</$imagetag>'si", $out_imageinfo[1]);\r
+                                       if ($temp != '') $result['image_'.$imagetag] = $temp; // Set only if not empty\r
+                               }\r
+                       }\r
+                       // Parse ITEMS\r
+                       preg_match_all("'<item(| .*?)>(.*?)</item>'si", $rss_content, $items);\r
+                       $rss_items = $items[2];\r
+                       $i = 0;\r
+                       $result['items'] = array(); // create array even if there are no items\r
+                       foreach($rss_items as $rss_item) {\r
+                               // If number of items is lower then limit: Parse one item\r
+                               if ($i < $this->items_limit || $this->items_limit == 0) {\r
+                                       foreach($this->itemtags as $itemtag) {\r
+                                               $temp = $this->my_preg_match("'<$itemtag.*?>(.*?)</$itemtag>'si", $rss_item);\r
+                                               if ($temp != '') $result['items'][$i][$itemtag] = $temp; // Set only if not empty\r
+                                       }\r
+                                       // Strip HTML tags and other bullshit from DESCRIPTION\r
+                                       if ($this->stripHTML && $result['items'][$i]['description'])\r
+                                               $result['items'][$i]['description'] = strip_tags($this->unhtmlentities(strip_tags($result['items'][$i]['description'])));\r
+                                       // Strip HTML tags and other bullshit from TITLE\r
+                                       if ($this->stripHTML && $result['items'][$i]['title'])\r
+                                               $result['items'][$i]['title'] = strip_tags($this->unhtmlentities(strip_tags($result['items'][$i]['title'])));\r
+                                       // If date_format is specified and pubDate is valid\r
+                                       if ($this->date_format != '' && ($timestamp = strtotime($result['items'][$i]['pubDate'])) !==-1) {\r
+                                               // convert pubDate to specified date format\r
+                                               $result['items'][$i]['pubDate'] = date($this->date_format, $timestamp);\r
+                                       }\r
+                                       // Item counter\r
+                                       $i++;\r
+                               }\r
+                       }\r
+\r
+                       $result['items_count'] = $i;\r
+                       return $result;\r
+               }\r
+               else // Error in opening return False\r
+               {\r
+                       return False;\r
+               }\r
+       }\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/include/classes/nusoap.php b/include/classes/nusoap.php
new file mode 100644 (file)
index 0000000..6d984c2
--- /dev/null
@@ -0,0 +1,5467 @@
+<?php
+
+/*
+$Id$
+
+NuSOAP - Web Services Toolkit for PHP
+
+Copyright (c) 2002 NuSphere Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+If you have any questions or comments, please email:
+
+Dietrich Ayala
+dietrich@ganx4.com
+http://dietrich.ganx4.com/nusoap
+
+NuSphere Corporation
+http://www.nusphere.com
+
+*/
+
+/* load classes
+
+// necessary classes
+require_once('class.soapclient.php');
+require_once('class.soap_val.php');
+require_once('class.soap_parser.php');
+require_once('class.soap_fault.php');
+
+// transport classes
+require_once('class.soap_transport_http.php');
+
+// optional add-on classes
+require_once('class.xmlschema.php');
+require_once('class.wsdl.php');
+
+// server class
+require_once('class.soap_server.php');*/
+
+/**
+*
+* nusoap_base
+*
+* @author   Dietrich Ayala <dietrich@ganx4.com>
+* @version  $Id$
+* @access   public
+*/
+class nusoap_base {
+
+       var $title = 'NuSOAP';
+       var $version = '0.6.7';
+       var $revision = '$Revision: 1.1 $';
+       var $error_str = false;
+    var $debug_str = '';
+       // toggles automatic encoding of special characters as entities
+       // (should always be true, I think)
+       var $charencoding = true;
+
+    /**
+       *  set schema version
+       *
+       * @var      XMLSchemaVersion
+       * @access   public
+       */
+       var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
+       
+    /**
+       *  set charset encoding for outgoing messages
+       *
+       * @var      soap_defencoding
+       * @access   public
+       */
+       //var $soap_defencoding = 'UTF-8';
+    var $soap_defencoding = 'ISO-8859-1';
+
+       /**
+       *  load namespace uris into an array of uri => prefix
+       *
+       * @var      namespaces
+       * @access   public
+       */
+       var $namespaces = array(
+               'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
+               'xsd' => 'http://www.w3.org/2001/XMLSchema',
+               'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+               'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/',
+               'si' => 'http://soapinterop.org/xsd');
+       var $usedNamespaces = array();
+
+       /**
+       * load types into typemap array
+       * is this legacy yet?
+       * no, this is used by the xmlschema class to verify type => namespace mappings.
+       * @var      typemap
+       * @access   public
+       */
+       var $typemap = array(
+       'http://www.w3.org/2001/XMLSchema' => array(
+               'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
+               'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
+               'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
+               // derived datatypes
+               'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
+               'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
+               'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
+               'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
+       'http://www.w3.org/1999/XMLSchema' => array(
+               'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
+               'float'=>'double','dateTime'=>'string',
+               'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
+       'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
+       'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
+    'http://xml.apache.org/xml-soap' => array('Map')
+       );
+
+       /**
+       *  entities to convert
+       *
+       * @var      xmlEntities
+       * @access   public
+       */
+       var $xmlEntities = array('quot' => '"','amp' => '&',
+               'lt' => '<','gt' => '>','apos' => "'");
+
+       /**
+       * adds debug data to the class level debug string
+       *
+       * @param    string $string debug data
+       * @access   private
+       */
+       function debug($string){
+               $this->debug_str .= get_class($this).": $string\n";
+       }
+
+       /**
+       * expands entities, e.g. changes '<' to '&lt;'.
+       *
+       * @param        string  $val    The string in which to expand entities.
+       * @access       private
+       */
+       function expandEntities($val) {
+               if ($this->charencoding) {
+               $val = str_replace('&', '&amp;', $val);
+               $val = str_replace("'", '&apos;', $val);
+               $val = str_replace('"', '&quot;', $val);
+               $val = str_replace('<', '&lt;', $val);
+               $val = str_replace('>', '&gt;', $val);
+           }
+           return $val;
+       }
+
+       /**
+       * returns error string if present
+       *
+       * @return   boolean $string error string
+       * @access   public
+       */
+       function getError(){
+               if($this->error_str != ''){
+                       return $this->error_str;
+               }
+               return false;
+       }
+
+       /**
+       * sets error string
+       *
+       * @return   boolean $string error string
+       * @access   private
+       */
+       function setError($str){
+               $this->error_str = $str;
+       }
+
+       /**
+       * detect if array is a simple array or a struct (associative array)
+       *
+       * @param        $val    The PHP array
+       * @return       string  (arraySimple|arrayStruct)
+       * @access       private
+       */
+       function isArraySimpleOrStruct($val) {
+        $keyList = array_keys($val);
+               foreach ($keyList as $keyListValue) {
+                       if (!is_int($keyListValue)) {
+                               return 'arrayStruct';
+                       }
+               }
+               return 'arraySimple';
+       }
+
+       /**
+       * serializes PHP values in accordance w/ section 5. Type information is
+       * not serialized if $use == 'literal'.
+       *
+       * @return       string
+    * @access  public
+       */
+       function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded'){
+       if(is_object($val) && get_class($val) == 'soapval'){
+               return $val->serialize($use);
+        }
+               $this->debug( "in serialize_val: $val, $name, $type, $name_ns, $type_ns, $attributes, $use");
+               // if no name, use item
+               $name = (!$name|| is_numeric($name)) ? 'soapVal' : $name;
+               // if name has ns, add ns prefix to name
+               $xmlns = '';
+        if($name_ns){
+                       $prefix = 'nu'.rand(1000,9999);
+                       $name = $prefix.':'.$name;
+                       $xmlns .= " xmlns:$prefix=\"$name_ns\"";
+               }
+               // if type is prefixed, create type prefix
+               if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
+                       // need to fix this. shouldn't default to xsd if no ns specified
+                   // w/o checking against typemap
+                       $type_prefix = 'xsd';
+               } elseif($type_ns){
+                       $type_prefix = 'ns'.rand(1000,9999);
+                       $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
+               }
+               // serialize attributes if present
+               $atts = '';
+               if($attributes){
+                       foreach($attributes as $k => $v){
+                               $atts .= " $k=\"$v\"";
+                       }
+               }
+        // serialize if an xsd built-in primitive type
+        if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
+               if(is_bool($val) && !$val){
+                       $val = 0;
+                       } else if (is_string($val)) {
+                               $val = $this->expandEntities($val);
+                       }
+                       if ($use == 'literal') {
+                       return "<$name$xmlns>$val</$name>";
+               } else {
+                       return "<$name$xmlns xsi:type=\"xsd:$type\">$val</$name>";
+               }
+        }
+               // detect type and serialize
+               $xml = '';
+               switch(true) {
+                       case ($type == '' && is_null($val)):
+                               if ($use == 'literal') {
+                                       // TODO: depends on nillable
+                                       $xml .= "<$name$xmlns/>";
+                               } else {
+                                       $xml .= "<$name$xmlns xsi:nil=\"true\"/>";
+                               }
+                               break;
+                       case (is_bool($val) || $type == 'boolean'):
+                               if(!$val){
+                               $val = 0;
+                               }
+                               if ($use == 'literal') {
+                                       $xml .= "<$name$xmlns $atts>$val</$name>";
+                               } else {
+                                       $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
+                               }
+                               break;
+                       case (is_int($val) || is_long($val) || $type == 'int'):
+                               if ($use == 'literal') {
+                                       $xml .= "<$name$xmlns $atts>$val</$name>";
+                               } else {
+                                       $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
+                               }
+                               break;
+                       case (is_float($val)|| is_double($val) || $type == 'float'):
+                               if ($use == 'literal') {
+                                       $xml .= "<$name$xmlns $atts>$val</$name>";
+                               } else {
+                                       $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
+                               }
+                               break;
+                       case (is_string($val) || $type == 'string'):
+                               $val = $this->expandEntities($val);
+                               if ($use == 'literal') {
+                                       $xml .= "<$name$xmlns $atts>$val</$name>";
+                               } else {
+                                       $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
+                               }
+                               break;
+                       case is_object($val):
+                               $name = get_class($val);
+                               foreach(get_object_vars($val) as $k => $v){
+                                       $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
+                               }
+                               $xml .= '<'.$name.'>'.$pXml.'</'.$name.'>';
+                               break;
+                       break;
+                       case (is_array($val) || $type):
+                               // detect if struct or array
+                               $valueType = $this->isArraySimpleOrStruct($val);
+                if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){
+                                       $i = 0;
+                                       if(is_array($val) && count($val)> 0){
+                                               foreach($val as $v){
+                               if(is_object($v) && get_class($v) ==  'soapval'){
+                                                               $tt_ns = $v->type_ns;
+                                                               $tt = $v->type;
+                                                       } else {
+                                                               $tt = gettype($v);
+                               }
+                                                       $array_types[$tt] = 1;
+                                                       $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
+                                                       ++$i;
+                                               }
+                                               if(count($array_types) > 1){
+                                                       $array_typename = 'xsd:ur-type';
+                                               } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
+                                                       $array_typename = 'xsd:'.$tt;
+                                               } elseif($tt == 'array' || $tt == 'Array'){
+                                                       $array_typename = 'SOAP-ENC:Array';
+                                               } else {
+                                                       // if type is prefixed, create type prefix
+                                                       if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
+                                                                $array_typename = 'xsd:' . $tt;
+                                                       } elseif ($tt_ns) {
+                                                               $tt_prefix = 'ns' . rand(1000, 9999);
+                                                               $array_typename = "$tt_prefix:$tt";
+                                                               $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
+                                                       } else {
+                                                               $array_typename = $tt;
+                                                       }
+                                               }
+                                               $array_type = $i;
+                                               if ($use == 'literal') {
+                                                       $type_str = '';
+                                               } else if (isset($type) && isset($type_prefix)) {
+                                                       $type_str = " xsi:type=\"$type_prefix:$type\"";
+                                               } else {
+                                                       $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
+                                               }
+                                       // empty array
+                                       } else {
+                                               if ($use == 'literal') {
+                                                       $type_str = '';
+                                               } else if (isset($type) && isset($type_prefix)) {
+                                                       $type_str = " xsi:type=\"$type_prefix:$type\"";
+                                               } else {
+                                                       $type_str = " xsi:type=\"SOAP-ENC:Array\"";
+                                               }
+                                       }
+                                       $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
+                               } else {
+                                       // got a struct
+                                       if(isset($type) && isset($type_prefix)){
+                                               $type_str = " xsi:type=\"$type_prefix:$type\"";
+                                       } else {
+                                               $type_str = '';
+                                       }
+                                       if ($use == 'literal') {
+                                               $xml .= "<$name$xmlns $atts>";
+                                       } else {
+                                               $xml .= "<$name$xmlns$type_str$atts>";
+                                       }
+                                       foreach($val as $k => $v){
+                                               // Apache Map
+                                               if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
+                                                       $xml .= '<item>';
+                                                       $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
+                                                       $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
+                                                       $xml .= '</item>';
+                                               } else {
+                                                       $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
+                                               }
+                                       }
+                                       $xml .= "</$name>";
+                               }
+                               break;
+                       default:
+                               $xml .= 'not detected, got '.gettype($val).' for '.$val;
+                               break;
+               }
+               return $xml;
+       }
+
+    /**
+    * serialize message
+    *
+    * @param string body
+    * @param string headers optional
+    * @param array namespaces optional
+    * @param string style optional (rpc|document)
+    * @param string use optional (encoded|literal)
+    * @return string message
+    * @access public
+    */
+    function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded'){
+    // TODO: add an option to automatically run utf8_encode on $body and $headers
+    // if $this->soap_defencoding is UTF-8.  Not doing this automatically allows
+    // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
+
+       // serialize namespaces
+    $ns_string = '';
+       foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
+               $ns_string .= "  xmlns:$k=\"$v\"";
+       }
+       if($style == 'rpc' && $use == 'encoded') {
+               $ns_string = ' SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"' . $ns_string;
+       }
+
+       // serialize headers
+       if($headers){
+               $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
+       }
+       // serialize envelope
+       return
+       '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
+       '<SOAP-ENV:Envelope'.$ns_string.">".
+       $headers.
+       "<SOAP-ENV:Body>".
+               $body.
+       "</SOAP-ENV:Body>".
+       "</SOAP-ENV:Envelope>";
+    }
+
+    function formatDump($str){
+               $str = htmlspecialchars($str);
+               return nl2br($str);
+    }
+
+       /**
+       * contracts a qualified name
+       *
+       * @param    string $string qname
+       * @return       string contracted qname
+       * @access   private
+       */
+       function contractQname($qname){
+               // get element namespace
+               //$this->xdebug("Contract $qname");
+               if (strrpos($qname, ':')) {
+                       // get unqualified name
+                       $name = substr($qname, strrpos($qname, ':') + 1);
+                       // get ns
+                       $ns = substr($qname, 0, strrpos($qname, ':'));
+                       $p = $this->getPrefixFromNamespace($ns);
+                       if ($p) {
+                               return $p . ':' . $name;
+                       }
+                       return $qname;
+               } else {
+                       return $qname;
+               }
+       }
+
+       /**
+       * expands a qualified name
+       *
+       * @param    string $string qname
+       * @return       string expanded qname
+       * @access   private
+       */
+       function expandQname($qname){
+               // get element prefix
+               if(strpos($qname,':') && !ereg('^http://',$qname)){
+                       // get unqualified name
+                       $name = substr(strstr($qname,':'),1);
+                       // get ns prefix
+                       $prefix = substr($qname,0,strpos($qname,':'));
+                       if(isset($this->namespaces[$prefix])){
+                               return $this->namespaces[$prefix].':'.$name;
+                       } else {
+                               return $qname;
+                       }
+               } else {
+                       return $qname;
+               }
+       }
+
+    /**
+    * returns the local part of a prefixed string
+    * returns the original string, if not prefixed
+    *
+    * @param string
+    * @return string
+    * @access public
+    */
+       function getLocalPart($str){
+               if($sstr = strrchr($str,':')){
+                       // get unqualified name
+                       return substr( $sstr, 1 );
+               } else {
+                       return $str;
+               }
+       }
+
+       /**
+    * returns the prefix part of a prefixed string
+    * returns false, if not prefixed
+    *
+    * @param string
+    * @return mixed
+    * @access public
+    */
+       function getPrefix($str){
+               if($pos = strrpos($str,':')){
+                       // get prefix
+                       return substr($str,0,$pos);
+               }
+               return false;
+       }
+
+       /**
+    * pass it a prefix, it returns a namespace
+       * returns false if no namespace registered with the given prefix
+    *
+    * @param string
+    * @return mixed
+    * @access public
+    */
+       function getNamespaceFromPrefix($prefix){
+               if (isset($this->namespaces[$prefix])) {
+                       return $this->namespaces[$prefix];
+               }
+               //$this->setError("No namespace registered for prefix '$prefix'");
+               return false;
+       }
+
+       /**
+    * returns the prefix for a given namespace (or prefix)
+    * or false if no prefixes registered for the given namespace
+    *
+    * @param string
+    * @return mixed
+    * @access public
+    */
+       function getPrefixFromNamespace($ns) {
+               foreach ($this->namespaces as $p => $n) {
+                       if ($ns == $n || $ns == $p) {
+                           $this->usedNamespaces[$p] = $n;
+                               return $p;
+                       }
+               }
+               return false;
+       }
+
+    function varDump($data) {
+               ob_start();
+               var_dump($data);
+               $ret_val = ob_get_contents();
+               ob_end_clean();
+               return $ret_val;
+       }
+}
+
+// XML Schema Datatype Helper Functions
+
+//xsd:dateTime helpers
+
+/**
+* convert unix timestamp to ISO 8601 compliant date string
+*
+* @param    string $timestamp Unix time stamp
+* @access   public
+*/
+function timestamp_to_iso8601($timestamp,$utc=true){
+       $datestr = date('Y-m-d\TH:i:sO',$timestamp);
+       if($utc){
+               $eregStr =
+               '([0-9]{4})-'.  // centuries & years CCYY-
+               '([0-9]{2})-'.  // months MM-
+               '([0-9]{2})'.   // days DD
+               'T'.                    // separator T
+               '([0-9]{2}):'.  // hours hh:
+               '([0-9]{2}):'.  // minutes mm:
+               '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
+               '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
+
+               if(ereg($eregStr,$datestr,$regs)){
+                       return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
+               }
+               return false;
+       } else {
+               return $datestr;
+       }
+}
+
+/**
+* convert ISO 8601 compliant date string to unix timestamp
+*
+* @param    string $datestr ISO 8601 compliant date string
+* @access   public
+*/
+function iso8601_to_timestamp($datestr){
+       $eregStr =
+       '([0-9]{4})-'.  // centuries & years CCYY-
+       '([0-9]{2})-'.  // months MM-
+       '([0-9]{2})'.   // days DD
+       'T'.                    // separator T
+       '([0-9]{2}):'.  // hours hh:
+       '([0-9]{2}):'.  // minutes mm:
+       '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
+       '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
+       if(ereg($eregStr,$datestr,$regs)){
+               // not utc
+               if($regs[8] != 'Z'){
+                       $op = substr($regs[8],0,1);
+                       $h = substr($regs[8],1,2);
+                       $m = substr($regs[8],strlen($regs[8])-2,2);
+                       if($op == '-'){
+                               $regs[4] = $regs[4] + $h;
+                               $regs[5] = $regs[5] + $m;
+                       } elseif($op == '+'){
+                               $regs[4] = $regs[4] - $h;
+                               $regs[5] = $regs[5] - $m;
+                       }
+               }
+               return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
+       } else {
+               return false;
+       }
+}
+
+function usleepWindows($usec)
+{
+       $start = gettimeofday();
+       
+       do
+       {
+               $stop = gettimeofday();
+               $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
+               + $stop['usec'] - $start['usec'];
+       }
+       while ($timePassed < $usec);
+}
+
+?><?php
+
+
+
+/**
+* soap_fault class, allows for creation of faults
+* mainly used for returning faults from deployed functions
+* in a server instance.
+* @author   Dietrich Ayala <dietrich@ganx4.com>
+* @version  $Id$
+* @access public
+*/
+class soap_fault extends nusoap_base {
+
+       var $faultcode;
+       var $faultactor;
+       var $faultstring;
+       var $faultdetail;
+
+       /**
+       * constructor
+    *
+    * @param string $faultcode (client | server)
+    * @param string $faultactor only used when msg routed between multiple actors
+    * @param string $faultstring human readable error message
+    * @param string $faultdetail
+       */
+       function soap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
+               $this->faultcode = $faultcode;
+               $this->faultactor = $faultactor;
+               $this->faultstring = $faultstring;
+               $this->faultdetail = $faultdetail;
+       }
+
+       /**
+       * serialize a fault
+       *
+       * @access   public
+       */
+       function serialize(){
+               $ns_string = '';
+               foreach($this->namespaces as $k => $v){
+                       $ns_string .= "\n  xmlns:$k=\"$v\"";
+               }
+               $return_msg =
+                       '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
+                       '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
+                               '<SOAP-ENV:Body>'.
+                               '<SOAP-ENV:Fault>'.
+                                       '<faultcode>'.$this->expandEntities($this->faultcode).'</faultcode>'.
+                                       '<faultactor>'.$this->expandEntities($this->faultactor).'</faultactor>'.
+                                       '<faultstring>'.$this->expandEntities($this->faultstring).'</faultstring>'.
+                                       '<detail>'.$this->serialize_val($this->faultdetail).'</detail>'.
+                               '</SOAP-ENV:Fault>'.
+                               '</SOAP-ENV:Body>'.
+                       '</SOAP-ENV:Envelope>';
+               return $return_msg;
+       }
+}
+
+
+
+?><?php
+
+
+
+/**
+* parses an XML Schema, allows access to it's data, other utility methods
+* no validation... yet.
+* very experimental and limited. As is discussed on XML-DEV, I'm one of the people
+* that just doesn't have time to read the spec(s) thoroughly, and just have a couple of trusty
+* tutorials I refer to :)
+*
+* @author   Dietrich Ayala <dietrich@ganx4.com>
+* @version  $Id$
+* @access   public
+*/
+class XMLSchema extends nusoap_base  {
+       
+       // files
+       var $schema = '';
+       var $xml = '';
+       // namespaces
+       var $enclosingNamespaces;
+       // schema info
+       var $schemaInfo = array();
+       var $schemaTargetNamespace = '';
+       // types, elements, attributes defined by the schema
+       var $attributes = array();
+       var $complexTypes = array();
+       var $currentComplexType = false;
+       var $elements = array();
+       var $currentElement = false;
+       var $simpleTypes = array();
+       var $currentSimpleType = false;
+       // imports
+       var $imports = array();
+       // parser vars
+       var $parser;
+       var $position = 0;
+       var $depth = 0;
+       var $depth_array = array();
+       var $message = array();
+       var $defaultNamespace = array();
+    
+       /**
+       * constructor
+       *
+       * @param    string $schema schema document URI
+       * @param    string $xml xml document URI
+       * @param        string $namespaces namespaces defined in enclosing XML
+       * @access   public
+       */
+       function XMLSchema($schema='',$xml='',$namespaces=array()){
+
+               $this->debug('xmlschema class instantiated, inside constructor');
+               // files
+               $this->schema = $schema;
+               $this->xml = $xml;
+
+               // namespaces
+               $this->enclosingNamespaces = $namespaces;
+               $this->namespaces = array_merge($this->namespaces, $namespaces);
+
+               // parse schema file
+               if($schema != ''){
+                       $this->debug('initial schema file: '.$schema);
+                       $this->parseFile($schema, 'schema');
+               }
+
+               // parse xml file
+               if($xml != ''){
+                       $this->debug('initial xml file: '.$xml);
+                       $this->parseFile($xml, 'xml');
+               }
+
+       }
+
+    /**
+    * parse an XML file
+    *
+    * @param string $xml, path/URL to XML file
+    * @param string $type, (schema | xml)
+       * @return boolean
+    * @access public
+    */
+       function parseFile($xml,$type){
+               // parse xml file
+               if($xml != ""){
+                       $xmlStr = @join("",@file($xml));
+                       if($xmlStr == ""){
+                               $msg = 'Error reading XML from '.$xml;
+                               $this->setError($msg);
+                               $this->debug($msg);
+                       return false;
+                       } else {
+                               $this->debug("parsing $xml");
+                               $this->parseString($xmlStr,$type);
+                               $this->debug("done parsing $xml");
+                       return true;
+                       }
+               }
+               return false;
+       }
+
+       /**
+       * parse an XML string
+       *
+       * @param    string $xml path or URL
+    * @param string $type, (schema|xml)
+       * @access   private
+       */
+       function parseString($xml,$type){
+               // parse xml string
+               if($xml != ""){
+
+               // Create an XML parser.
+               $this->parser = xml_parser_create();
+               // Set the options for parsing the XML data.
+               xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
+
+               // Set the object for the parser.
+               xml_set_object($this->parser, $this);
+
+               // Set the element handlers for the parser.
+                       if($type == "schema"){
+                       xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
+                       xml_set_character_data_handler($this->parser,'schemaCharacterData');
+                       } elseif($type == "xml"){
+                               xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
+                       xml_set_character_data_handler($this->parser,'xmlCharacterData');
+                       }
+
+                   // Parse the XML file.
+                   if(!xml_parse($this->parser,$xml,true)){
+                       // Display an error message.
+                               $errstr = sprintf('XML error parsing XML schema on line %d: %s',
+                               xml_get_current_line_number($this->parser),
+                               xml_error_string(xml_get_error_code($this->parser))
+                               );
+                               $this->debug($errstr);
+                               $this->debug("XML payload:\n" . $xml);
+                               $this->setError($errstr);
+               }
+            
+                       xml_parser_free($this->parser);
+               } else{
+                       $this->debug('no xml passed to parseString()!!');
+                       $this->setError('no xml passed to parseString()!!');
+               }
+       }
+
+       /**
+       * start-element handler
+       *
+       * @param    string $parser XML parser object
+       * @param    string $name element name
+       * @param    string $attrs associative array of attributes
+       * @access   private
+       */
+       function schemaStartElement($parser, $name, $attrs) {
+               
+               // position in the total number of elements, starting from 0
+               $pos = $this->position++;
+               $depth = $this->depth++;
+               // set self as current value for this depth
+               $this->depth_array[$depth] = $pos;
+               $this->message[$pos] = array('cdata' => ''); 
+               if ($depth > 0) {
+                       $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
+               } else {
+                       $this->defaultNamespace[$pos] = false;
+               }
+
+               // get element prefix
+               if($prefix = $this->getPrefix($name)){
+                       // get unqualified name
+                       $name = $this->getLocalPart($name);
+               } else {
+               $prefix = '';
+        }
+               
+        // loop thru attributes, expanding, and registering namespace declarations
+        if(count($attrs) > 0){
+               foreach($attrs as $k => $v){
+                // if ns declarations, add to class level array of valid namespaces
+                               if(ereg("^xmlns",$k)){
+                       //$this->xdebug("$k: $v");
+                       //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
+                       if($ns_prefix = substr(strrchr($k,':'),1)){
+                               //$this->xdebug("Add namespace[$ns_prefix] = $v");
+                                               $this->namespaces[$ns_prefix] = $v;
+                                       } else {
+                                               $this->defaultNamespace[$pos] = $v;
+                                               if (! $this->getPrefixFromNamespace($v)) {
+                                                       $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
+                                               }
+                                       }
+                                       if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema'){
+                                               $this->XMLSchemaVersion = $v;
+                                               $this->namespaces['xsi'] = $v.'-instance';
+                                       }
+                               }
+               }
+               foreach($attrs as $k => $v){
+                // expand each attribute
+                $k = strpos($k,':') ? $this->expandQname($k) : $k;
+                $v = strpos($v,':') ? $this->expandQname($v) : $v;
+                       $eAttrs[$k] = $v;
+               }
+               $attrs = $eAttrs;
+        } else {
+               $attrs = array();
+        }
+               // find status, register data
+               switch($name){
+                       case 'all':
+                       case 'choice':
+                       case 'sequence':
+                               //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
+                               $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
+                               if($name == 'all' || $name == 'sequence'){
+                                       $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
+                               }
+                       break;
+                       case 'attribute':
+               //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
+               $this->xdebug("parsing attribute " . $this->varDump($attrs));
+               if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
+                                       $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
+                                       if (!strpos($v, ':')) {
+                                               // no namespace in arrayType attribute value...
+                                               if ($this->defaultNamespace[$pos]) {
+                                                       // ...so use the default
+                                                       $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
+                                               }
+                                       }
+               }
+                if(isset($attrs['name'])){
+                                       $this->attributes[$attrs['name']] = $attrs;
+                                       $aname = $attrs['name'];
+                               } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
+                                       if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
+                               $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
+                       } else {
+                               $aname = '';
+                       }
+                               } elseif(isset($attrs['ref'])){
+                                       $aname = $attrs['ref'];
+                    $this->attributes[$attrs['ref']] = $attrs;
+                               }
+                
+                               if(isset($this->currentComplexType)){
+                                       $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
+                               } elseif(isset($this->currentElement)){
+                                       $this->elements[$this->currentElement]['attrs'][$aname] = $attrs;
+                               }
+                               // arrayType attribute
+                               if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
+                                       $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
+                       $prefix = $this->getPrefix($aname);
+                                       if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
+                                               $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
+                                       } else {
+                                               $v = '';
+                                       }
+                    if(strpos($v,'[,]')){
+                        $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
+                    }
+                    $v = substr($v,0,strpos($v,'[')); // clip the []
+                    if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
+                        $v = $this->XMLSchemaVersion.':'.$v;
+                    }
+                    $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
+                               }
+                       break;
+                       case 'complexType':
+                               if(isset($attrs['name'])){
+                                       $this->xdebug('processing named complexType '.$attrs['name']);
+                                       $this->currentElement = false;
+                                       $this->currentComplexType = $attrs['name'];
+                                       $this->complexTypes[$this->currentComplexType] = $attrs;
+                                       $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
+                                       if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
+                                               $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
+                                       } else {
+                                               $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
+                                       }
+                               }else{
+                                       $this->xdebug('processing unnamed complexType for element '.$this->currentElement);
+                                       $this->currentComplexType = $this->currentElement . '_ContainedType';
+                                       $this->currentElement = false;
+                                       $this->complexTypes[$this->currentComplexType] = $attrs;
+                                       $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
+                                       if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
+                                               $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
+                                       } else {
+                                               $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
+                                       }
+                               }
+                       break;
+                       case 'element':
+                               // elements defined as part of a complex type should
+                               // not really be added to $this->elements, but for some
+                               // reason, they are
+                               if(isset($attrs['type'])){
+                                       $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
+                                       $this->currentElement = $attrs['name'];
+                                       $this->elements[ $attrs['name'] ] = $attrs;
+                                       $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
+                                       if (!isset($this->elements[ $attrs['name'] ]['form'])) {
+                                               $this->elements[ $attrs['name'] ]['form'] = $this->schemaInfo['elementFormDefault'];
+                                       }
+                                       $ename = $attrs['name'];
+                               } elseif(isset($attrs['ref'])){
+                                       $ename = $attrs['ref'];
+                               } else {
+                                       $this->xdebug("processing untyped element ".$attrs['name']);
+                                       $this->currentElement = $attrs['name'];
+                                       $this->elements[ $attrs['name'] ] = $attrs;
+                                       $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
+                                       $this->elements[ $attrs['name'] ]['type'] = $this->schemaTargetNamespace . ':' . $attrs['name'] . '_ContainedType';
+                                       if (!isset($this->elements[ $attrs['name'] ]['form'])) {
+                                               $this->elements[ $attrs['name'] ]['form'] = $this->schemaInfo['elementFormDefault'];
+                                       }
+                               }
+                               if(isset($ename) && $this->currentComplexType){
+                                       $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
+                               }
+                       break;
+                       // we ignore enumeration values
+                       //case 'enumeration':
+                       //break;
+                       case 'import':
+                           if (isset($attrs['schemaLocation'])) {
+                                       //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
+                    $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
+                               } else {
+                                       //$this->xdebug('import namespace ' . $attrs['namespace']);
+                    $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
+                                       if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
+                                               $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
+                                       }
+                               }
+                       break;
+                       case 'restriction':
+                               //$this->xdebug("in restriction for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
+                               if($this->currentElement){
+                                       $this->elements[$this->currentElement]['type'] = $attrs['base'];
+                               } elseif($this->currentSimpleType){
+                                       $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
+                               } elseif($this->currentComplexType){
+                                       $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
+                                       if(strstr($attrs['base'],':') == ':Array'){
+                                               $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
+                                       }
+                               }
+                       break;
+                       case 'schema':
+                               $this->schemaInfo = $attrs;
+                               $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
+                               if (isset($attrs['targetNamespace'])) {
+                                       $this->schemaTargetNamespace = $attrs['targetNamespace'];
+                               }
+                               if (!isset($attrs['elementFormDefault'])) {
+                                       $this->schemaInfo['elementFormDefault'] = 'unqualified';
+                               }
+                       break;
+                       case 'simpleType':
+                               if(isset($attrs['name'])){
+                                       $this->xdebug("processing simpleType for name " . $attrs['name']);
+                                       $this->currentSimpleType = $attrs['name'];
+                                       $this->simpleTypes[ $attrs['name'] ] = $attrs;
+                                       $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
+                                       $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
+                               } else {
+                                       //echo 'not parsing: '.$name;
+                                       //var_dump($attrs);
+                               }
+                       break;
+                       default:
+                               //$this->xdebug("do not have anything to do for element $name");
+               }
+       }
+
+       /**
+       * end-element handler
+       *
+       * @param    string $parser XML parser object
+       * @param    string $name element name
+       * @access   private
+       */
+       function schemaEndElement($parser, $name) {
+               // bring depth down a notch
+               $this->depth--;
+               // position of current element is equal to the last value left in depth_array for my depth
+               if(isset($this->depth_array[$this->depth])){
+               $pos = $this->depth_array[$this->depth];
+        }
+               // move on...
+               if($name == 'complexType'){
+                       $this->currentComplexType = false;
+                       $this->currentElement = false;
+               }
+               if($name == 'element'){
+                       $this->currentElement = false;
+               }
+               if($name == 'simpleType'){
+                       $this->currentSimpleType = false;
+               }
+       }
+
+       /**
+       * element content handler
+       *
+       * @param    string $parser XML parser object
+       * @param    string $data element content
+       * @access   private
+       */
+       function schemaCharacterData($parser, $data){
+               $pos = $this->depth_array[$this->depth - 1];
+               $this->message[$pos]['cdata'] .= $data;
+       }
+
+       /**
+       * serialize the schema
+       *
+       * @access   public
+       */
+       function serializeSchema(){
+
+               $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
+               $xml = '';
+               // imports
+               if (sizeof($this->imports) > 0) {
+                       foreach($this->imports as $ns => $list) {
+                               foreach ($list as $ii) {
+                                       if ($ii['location'] != '') {
+                                               $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
+                                       } else {
+                                               $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
+                                       }
+                               }
+                       } 
+               } 
+               // complex types
+               foreach($this->complexTypes as $typeName => $attrs){
+                       $contentStr = '';
+                       // serialize child elements
+                       if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
+                               foreach($attrs['elements'] as $element => $eParts){
+                                       if(isset($eParts['ref'])){
+                                               $contentStr .= "   <$schemaPrefix:element ref=\"$element\"/>\n";
+                                       } else {
+                                               $contentStr .= "   <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"/>\n";
+                                       }
+                               }
+                       }
+                       // attributes
+                       if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
+                               foreach($attrs['attrs'] as $attr => $aParts){
+                                       $contentStr .= "    <$schemaPrefix:attribute ref=\"".$this->contractQName($aParts['ref']).'"';
+                                       if(isset($aParts['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
+                                               $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
+                                               $contentStr .= ' wsdl:arrayType="'.$this->contractQName($aParts['http://schemas.xmlsoap.org/wsdl/:arrayType']).'"';
+                                       }
+                                       $contentStr .= "/>\n";
+                               }
+                       }
+                       // if restriction
+                       if( isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
+                               $contentStr = "   <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr."   </$schemaPrefix:restriction>\n";
+                       }
+                       // compositor obviates complex/simple content
+                       if(isset($attrs['compositor']) && ($attrs['compositor'] != '')){
+                               $contentStr = "  <$schemaPrefix:$attrs[compositor]>\n".$contentStr."  </$schemaPrefix:$attrs[compositor]>\n";
+                       }
+                       // complex or simple content
+                       elseif((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
+                               $contentStr = "  <$schemaPrefix:complexContent>\n".$contentStr."  </$schemaPrefix:complexContent>\n";
+                       }
+                       // finalize complex type
+                       if($contentStr != ''){
+                               $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
+                       } else {
+                               $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
+                       }
+                       $xml .= $contentStr;
+               }
+               // simple types
+               if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
+                       foreach($this->simpleTypes as $typeName => $attr){
+                               $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n  <restriction base=\"".$this->contractQName($eParts['type'])."\"/>\n </$schemaPrefix:simpleType>";
+                       }
+               }
+               // elements
+               if(isset($this->elements) && count($this->elements) > 0){
+                       foreach($this->elements as $element => $eParts){
+                               $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
+                       }
+               }
+               // attributes
+               if(isset($this->attributes) && count($this->attributes) > 0){
+                       foreach($this->attributes as $attr => $aParts){
+                               $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
+                       }
+               }
+               // finish 'er up
+               $el = "<$schemaPrefix:schema targetNamespace=\"$this->schemaTargetNamespace\"\n";
+               foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
+                       $el .= " xmlns:$nsp=\"$ns\"\n";
+               }
+               $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
+               return $xml;
+       }
+
+       /**
+       * adds debug data to the clas level debug string
+       *
+       * @param    string $string debug data
+       * @access   private
+       */
+       function xdebug($string){
+               $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
+       }
+
+    /**
+    * get the PHP type of a user defined type in the schema
+    * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
+    * returns false if no type exists, or not w/ the given namespace
+    * else returns a string that is either a native php type, or 'struct'
+    *
+    * @param string $type, name of defined type
+    * @param string $ns, namespace of type
+    * @return mixed
+    * @access public
+    */
+       function getPHPType($type,$ns){
+               if(isset($this->typemap[$ns][$type])){
+                       //print "found type '$type' and ns $ns in typemap<br>";
+                       return $this->typemap[$ns][$type];
+               } elseif(isset($this->complexTypes[$type])){
+                       //print "getting type '$type' and ns $ns from complexTypes array<br>";
+                       return $this->complexTypes[$type]['phpType'];
+               }
+               return false;
+       }
+
+       /**
+    * returns an array of information about a given type
+    * returns false if no type exists by the given name
+    *
+       *        typeDef = array(
+       *        'elements' => array(), // refs to elements array
+       *       'restrictionBase' => '',
+       *       'phpType' => '',
+       *       'order' => '(sequence|all)',
+       *       'attrs' => array() // refs to attributes array
+       *       )
+    *
+    * @param string
+    * @return mixed
+    * @access public
+    */
+       function getTypeDef($type){
+               //$this->debug("in getTypeDef for type $type");
+               if(isset($this->complexTypes[$type])){
+                       $this->xdebug("in getTypeDef, found complexType $type");
+                       return $this->complexTypes[$type];
+               } elseif(isset($this->simpleTypes[$type])){
+                       $this->xdebug("in getTypeDef, found simpleType $type");
+                       if (!isset($this->simpleTypes[$type]['phpType'])) {
+                               // get info for type to tack onto the simple type
+                               // TODO: can this ever really apply (i.e. what is a simpleType really?)
+                               $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
+                               $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
+                               $etype = $this->getTypeDef($uqType);
+                               if ($etype) {
+                                       if (isset($etype['phpType'])) {
+                                               $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
+                                       }
+                                       if (isset($etype['elements'])) {
+                                               $this->simpleTypes[$type]['elements'] = $etype['elements'];
+                                       }
+                               }
+                       }
+                       return $this->simpleTypes[$type];
+               } elseif(isset($this->elements[$type])){
+                       $this->xdebug("in getTypeDef, found element $type");
+                       if (!isset($this->elements[$type]['phpType'])) {
+                               // get info for type to tack onto the element
+                               $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
+                               $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
+                               $etype = $this->getTypeDef($uqType);
+                               if ($etype) {
+                                       if (isset($etype['phpType'])) {
+                                               $this->elements[$type]['phpType'] = $etype['phpType'];
+                                       }
+                                       if (isset($etype['elements'])) {
+                                               $this->elements[$type]['elements'] = $etype['elements'];
+                                       }
+                               } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
+                                       $this->elements[$type]['phpType'] = 'scalar';
+                               }
+                       }
+                       return $this->elements[$type];
+               } elseif(isset($this->attributes[$type])){
+                       $this->xdebug("in getTypeDef, found attribute $type");
+                       return $this->attributes[$type];
+               }
+               $this->xdebug("in getTypeDef, did not find $type");
+               return false;
+       }
+
+       /**
+    * returns a sample serialization of a given type, or false if no type by the given name
+    *
+    * @param string $type, name of type
+    * @return mixed
+    * @access public
+    */
+    function serializeTypeDef($type){
+       //print "in sTD() for type $type<br>";
+       if($typeDef = $this->getTypeDef($type)){
+               $str .= '<'.$type;
+           if(is_array($typeDef['attrs'])){
+               foreach($attrs as $attName => $data){
+                   $str .= " $attName=\"{type = ".$data['type']."}\"";
+               }
+           }
+           $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
+           if(count($typeDef['elements']) > 0){
+               $str .= ">";
+               foreach($typeDef['elements'] as $element => $eData){
+                   $str .= $this->serializeTypeDef($element);
+               }
+               $str .= "</$type>";
+           } elseif($typeDef['typeClass'] == 'element') {
+               $str .= "></$type>";
+           } else {
+               $str .= "/>";
+           }
+                       return $str;
+       }
+       return false;
+    }
+
+    /**
+    * returns HTML form elements that allow a user
+    * to enter values for creating an instance of the given type.
+    *
+    * @param string $name, name for type instance
+    * @param string $type, name of type
+    * @return string
+    * @access public
+       */
+       function typeToForm($name,$type){
+               // get typedef
+               if($typeDef = $this->getTypeDef($type)){
+                       // if struct
+                       if($typeDef['phpType'] == 'struct'){
+                               $buffer .= '<table>';
+                               foreach($typeDef['elements'] as $child => $childDef){
+                                       $buffer .= "
+                                       <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
+                                       <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
+                               }
+                               $buffer .= '</table>';
+                       // if array
+                       } elseif($typeDef['phpType'] == 'array'){
+                               $buffer .= '<table>';
+                               for($i=0;$i < 3; $i++){
+                                       $buffer .= "
+                                       <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
+                                       <td><input type='text' name='parameters[".$name."][]'></td></tr>";
+                               }
+                               $buffer .= '</table>';
+                       // if scalar
+                       } else {
+                               $buffer .= "<input type='text' name='parameters[$name]'>";
+                       }
+               } else {
+                       $buffer .= "<input type='text' name='parameters[$name]'>";
+               }
+               return $buffer;
+       }
+       
+       /**
+       * adds a complex type to the schema
+       * 
+       * example: array
+       * 
+       * addType(
+       *       'ArrayOfstring',
+       *       'complexType',
+       *       'array',
+       *       '',
+       *       'SOAP-ENC:Array',
+       *       array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
+       *       'xsd:string'
+       * );
+       * 
+       * example: PHP associative array ( SOAP Struct )
+       * 
+       * addType(
+       *       'SOAPStruct',
+       *       'complexType',
+       *       'struct',
+       *       'all',
+       *       array('myVar'=> array('name'=>'myVar','type'=>'string')
+       * );
+       * 
+       * @param name
+       * @param typeClass (complexType|simpleType|attribute)
+       * @param phpType: currently supported are array and struct (php assoc array)
+       * @param compositor (all|sequence|choice)
+       * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
+       * @param elements = array ( name = array(name=>'',type=>'') )
+       * @param attrs = array(
+       *       array(
+       *               'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
+       *               "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
+       *       )
+       * )
+       * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
+       *
+       */
+       function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
+               $this->complexTypes[$name] = array(
+           'name'              => $name,
+           'typeClass' => $typeClass,
+           'phpType'   => $phpType,
+               'compositor'=> $compositor,
+           'restrictionBase' => $restrictionBase,
+               'elements'      => $elements,
+           'attrs'             => $attrs,
+           'arrayType' => $arrayType
+               );
+               
+               $this->xdebug("addComplexType $name: " . $this->varDump($this->complexTypes[$name]));
+       }
+       
+       /**
+       * adds a simple type to the schema
+       *
+       * @param name
+       * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
+       * @param typeClass (simpleType)
+       * @param phpType: (scalar)
+       * @see xmlschema
+       * 
+       */
+       function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar') {
+               $this->simpleTypes[$name] = array(
+           'name'              => $name,
+           'typeClass' => $typeClass,
+           'phpType'   => $phpType,
+           'type' => $restrictionBase
+               );
+               
+               $this->xdebug("addSimpleType $name: " . $this->varDump($this->simpleTypes[$name]));
+       }
+}
+
+
+
+?><?php
+
+
+
+/**
+* for creating serializable abstractions of native PHP types
+* NOTE: this is only really used when WSDL is not available.
+*
+* @author   Dietrich Ayala <dietrich@ganx4.com>
+* @version  $Id$
+* @access   public
+*/
+class soapval extends nusoap_base {
+       /**
+       * constructor
+       *
+       * @param    string $name optional name
+       * @param    string $type optional type name
+       * @param        mixed $value optional value
+       * @param        string $namespace optional namespace of value
+       * @param        string $type_namespace optional namespace of type
+       * @param        array $attributes associative array of attributes to add to element serialization
+       * @access   public
+       */
+       function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
+               $this->name = $name;
+               $this->value = $value;
+               $this->type = $type;
+               $this->element_ns = $element_ns;
+               $this->type_ns = $type_ns;
+               $this->attributes = $attributes;
+    }
+
+       /**
+       * return serialized value
+       *
+       * @return       string XML data
+       * @access   private
+       */
+       function serialize($use='encoded') {
+               return $this->serialize_val($this->value,$this->name,$this->type,$this->element_ns,$this->type_ns,$this->attributes,$use);
+    }
+
+       /**
+       * decodes a soapval object into a PHP native type
+       *
+       * @param        object $soapval optional SOAPx4 soapval object, else uses self
+       * @return       mixed
+       * @access   public
+       */
+       function decode(){
+               return $this->value;
+       }
+}
+
+
+
+?><?php
+
+
+
+/**
+* transport class for sending/receiving data via HTTP and HTTPS
+* NOTE: PHP must be compiled with the CURL extension for HTTPS support
+*
+* @author   Dietrich Ayala <dietrich@ganx4.com>
+* @version  $Id$
+* @access public
+*/
+class soap_transport_http extends nusoap_base {
+
+       var $url = '';
+       var $uri = '';
+       var $scheme = '';
+       var $host = '';
+       var $port = '';
+       var $path = '';
+       var $request_method = 'POST';
+       var $protocol_version = '1.0';
+       var $encoding = '';
+       var $outgoing_headers = array();
+       var $incoming_headers = array();
+       var $outgoing_payload = '';
+       var $incoming_payload = '';
+       var $useSOAPAction = true;
+       var $persistentConnection = false;
+       var $ch = false;        // cURL handle
+       var $username;
+       var $password;
+       
+       /**
+       * constructor
+       */
+       function soap_transport_http($url){
+               $this->url = $url;
+               
+               $u = parse_url($url);
+               foreach($u as $k => $v){
+                       $this->debug("$k = $v");
+                       $this->$k = $v;
+               }
+               
+               // add any GET params to path
+               if(isset($u['query']) && $u['query'] != ''){
+            $this->path .= '?' . $u['query'];
+               }
+               
+               // set default port
+               if(!isset($u['port'])){
+                       if($u['scheme'] == 'https'){
+                               $this->port = 443;
+                       } else {
+                               $this->port = 80;
+                       }
+               }
+               
+               $this->uri = $this->path;
+               
+               // build headers
+               ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
+               $this->outgoing_headers['User-Agent'] = $this->title.'/'.$this->version.' ('.$rev[1].')';
+               if (!isset($u['port'])) {
+                       $this->outgoing_headers['Host'] = $this->host;
+               } else {
+                       $this->outgoing_headers['Host'] = $this->host.':'.$this->port;
+               }
+               
+               if (isset($u['user']) && $u['user'] != '') {
+                       $this->setCredentials($u['user'], isset($u['pass']) ? $u['pass'] : '');
+               }
+       }
+       
+       function connect($connection_timeout=0,$response_timeout=30){
+               // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
+               // "regular" socket.
+               // TODO: disabled for now because OpenSSL must be *compiled* in (not just
+               //       loaded), and until PHP5 stream_get_wrappers is not available.
+//             if ($this->scheme == 'https') {
+//                     if (version_compare(phpversion(), '4.3.0') >= 0) {
+//                             if (extension_loaded('openssl')) {
+//                                     $this->scheme = 'ssl';
+//                                     $this->debug('Using SSL over OpenSSL');
+//                             }
+//                     }
+//             }
+         if ($this->scheme == 'http' || $this->scheme == 'ssl') {
+               // use persistent connection
+               if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
+                       if (!feof($this->fp)) {
+                               $this->debug('Re-use persistent connection');
+                               return true;
+                       }
+                       fclose($this->fp);
+                       $this->debug('Closed persistent connection at EOF');
+               }
+
+               // munge host if using OpenSSL
+               if ($this->scheme == 'ssl') {
+                       $host = 'ssl://' . $this->host;
+               } else {
+                       $host = $this->host;
+               }
+               $this->debug('calling fsockopen with host ' . $host);
+
+               // open socket
+               if($connection_timeout > 0){
+                       $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);
+               } else {
+                       $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);
+               }
+               
+               // test pointer
+               if(!$this->fp) {
+                       $this->debug('Couldn\'t open socket connection to server '.$this->url.', Error ('.$this->errno.'): '.$this->error_str);
+                       $this->setError('Couldn\'t open socket connection to server: '.$this->url.', Error ('.$this->errno.'): '.$this->error_str);
+                       return false;
+               }
+               
+               // set response timeout
+               socket_set_timeout( $this->fp, $response_timeout);
+
+               $this->debug('socket connected');
+               return true;
+         } else if ($this->scheme == 'https') {
+               if (!extension_loaded('curl')) {
+                       $this->setError('CURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
+                       return false;
+               }
+               $this->debug('connect using https');
+               // init CURL
+               $this->ch = curl_init();
+               // set url
+               $hostURL = ($this->port != '') ? "https://$this->host:$this->port" : "https://$this->host";
+               // add path
+               $hostURL .= $this->path;
+               curl_setopt($this->ch, CURLOPT_URL, $hostURL);
+               // ask for headers in the response output
+               curl_setopt($this->ch, CURLOPT_HEADER, 1);
+               // ask for the response output as the return value
+               curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
+               // encode
+               // We manage this ourselves through headers and encoding
+//             if(function_exists('gzuncompress')){
+//                     curl_setopt($this->ch, CURLOPT_ENCODING, 'deflate');
+//             }
+               // persistent connection
+               if ($this->persistentConnection) {
+                       // The way we send data, we cannot use persistent connections, since
+                       // there will be some "junk" at the end of our request.
+                       //curl_setopt($this->ch, CURL_HTTP_VERSION_1_1, true);
+                       $this->persistentConnection = false;
+                       $this->outgoing_headers['Connection'] = 'close';
+               }
+               // set timeout (NOTE: cURL does not have separate connection and response timeouts)
+               if ($connection_timeout != 0) {
+                       curl_setopt($this->ch, CURLOPT_TIMEOUT, $connection_timeout);
+               }
+
+               // recent versions of cURL turn on peer/host checking by default,
+               // while PHP binaries are not compiled with a default location for the
+               // CA cert bundle, so disable peer/host checking.
+//curl_setopt($this->ch, CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');          
+               curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 0);
+               curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 0);
+
+               /*
+                       TODO: support client certificates (thanks Tobias Boes)
+        curl_setopt($this->ch, CURLOPT_CAINFO, '$pathToPemFiles/rootca.pem');
+        curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 1);
+        curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 1);
+        curl_setopt($this->ch, CURLOPT_SSLCERT, '$pathToPemFiles/mycert.pem');
+        curl_setopt($this->ch, CURLOPT_SSLKEY, '$pathToPemFiles/mykey.pem');
+               */
+               $this->debug('cURL connection set up');
+               return true;
+         } else {
+               $this->setError('Unknown scheme ' . $this->scheme);
+               $this->debug('Unknown scheme ' . $this->scheme);
+               return false;
+         }
+       }
+       
+       /**
+       * send the SOAP message via HTTP
+       *
+       * @param    string $data message data
+       * @param    integer $timeout set connection timeout in seconds
+       * @param        integer $response_timeout set response timeout in seconds
+       * @return       string data
+       * @access   public
+       */
+       function send($data, $timeout=0, $response_timeout=30) {
+               
+               $this->debug('entered send() with data of length: '.strlen($data));
+
+               $this->tryagain = true;
+               $tries = 0;
+               while ($this->tryagain) {
+                       $this->tryagain = false;
+                       if ($tries++ < 2) {
+                               // make connnection
+                               if (!$this->connect($timeout, $response_timeout)){
+                                       return false;
+                               }
+                               
+                               // send request
+                               if (!$this->sendRequest($data)){
+                                       return false;
+                               }
+                               
+                               // get response
+                               $respdata = $this->getResponse();
+                       } else {
+                               $this->setError('Too many tries to get an OK response');
+                       }
+               }               
+               $this->debug('end of send()');
+               return $respdata;
+       }
+
+
+       /**
+       * send the SOAP message via HTTPS 1.0 using CURL
+       *
+       * @param    string $msg message data
+       * @param    integer $timeout set connection timeout in seconds
+       * @param        integer $response_timeout set response timeout in seconds
+       * @return       string data
+       * @access   public
+       */
+       function sendHTTPS($data, $timeout=0, $response_timeout=30) {
+               return $this->send($data, $timeout, $response_timeout);
+       }
+       
+       /**
+       * if authenticating, set user credentials here
+       *
+       * @param    string $username
+       * @param    string $password
+       * @param        string $authtype
+       * @param        array $digestRequest
+       * @access   public
+       */
+       function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array()) {
+               global $_SERVER;
+
+               // cf. RFC 2617
+               if ($authtype == 'basic') {
+                       $this->outgoing_headers['Authorization'] = 'Basic '.base64_encode($username.':'.$password);
+               } elseif ($authtype == 'digest') {
+                       if (isset($digestRequest['nonce'])) {
+                               $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
+                               
+                               // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
+       
+                               // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
+                               $A1 = $username. ':' . $digestRequest['realm'] . ':' . $password;
+       
+                               // H(A1) = MD5(A1)
+                               $HA1 = md5($A1);
+       
+                               // A2 = Method ":" digest-uri-value
+                               $A2 = 'POST:' . $this->uri;
+       
+                               // H(A2)
+                               $HA2 =  md5($A2);
+       
+                               // KD(secret, data) = H(concat(secret, ":", data))
+                               // if qop == auth:
+                               // request-digest  = <"> < KD ( H(A1),     unq(nonce-value)
+                               //                              ":" nc-value
+                               //                              ":" unq(cnonce-value)
+                               //                              ":" unq(qop-value)
+                               //                              ":" H(A2)
+                               //                            ) <">
+                               // if qop is missing,
+                               // request-digest  = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
+       
+                               $unhashedDigest = '';
+                               $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
+                               $cnonce = $nonce;
+                               if ($digestRequest['qop'] != '') {
+                                       $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
+                               } else {
+                                       $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
+                               }
+       
+                               $hashedDigest = md5($unhashedDigest);
+       
+                               $this->outgoing_headers['Authorization'] = 'Digest username="' . $username . '", realm="' . $digestRequest['realm'] . '", nonce="' . $nonce . '", uri="' . $this->uri . '", cnonce="' . $cnonce . '", nc=' . sprintf("%08x", $digestRequest['nc']) . ', qop="' . $digestRequest['qop'] . '", response="' . $hashedDigest . '"';
+                       }
+               }
+               $this->username = $username;
+               $this->password = $password;
+               $this->authtype = $authtype;
+               $this->digestRequest = $digestRequest;
+       }
+       
+       /**
+       * set the soapaction value
+       *
+       * @param    string $soapaction
+       * @access   public
+       */
+       function setSOAPAction($soapaction) {
+               $this->outgoing_headers['SOAPAction'] = '"' . $soapaction . '"';
+       }
+       
+       /**
+       * use http encoding
+       *
+       * @param    string $enc encoding style. supported values: gzip, deflate, or both
+       * @access   public
+       */
+       function setEncoding($enc='gzip, deflate'){
+               $this->protocol_version = '1.1';
+               $this->outgoing_headers['Accept-Encoding'] = $enc;
+               $this->outgoing_headers['Connection'] = 'close';
+               $this->persistentConnection = false;
+               set_magic_quotes_runtime(0);
+               // deprecated
+               $this->encoding = $enc;
+       }
+       
+       /**
+       * set proxy info here
+       *
+       * @param    string $proxyhost
+       * @param    string $proxyport
+       * @param        string $proxyusername
+       * @param        string $proxypassword
+       * @access   public
+       */
+       function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
+               $this->uri = $this->url;
+               $this->host = $proxyhost;
+               $this->port = $proxyport;
+               if ($proxyusername != '' && $proxypassword != '') {
+                       $this->outgoing_headers['Proxy-Authorization'] = ' Basic '.base64_encode($proxyusername.':'.$proxypassword);
+               }
+       }
+       
+       /**
+       * decode a string that is encoded w/ "chunked' transfer encoding
+       * as defined in RFC2068 19.4.6
+       *
+       * @param    string $buffer
+       * @param    string $lb
+       * @returns      string
+       * @access   public
+       */
+       function decodeChunked($buffer, $lb){
+               // length := 0
+               $length = 0;
+               $new = '';
+               
+               // read chunk-size, chunk-extension (if any) and CRLF
+               // get the position of the linebreak
+               $chunkend = strpos($buffer, $lb);
+               if ($chunkend == FALSE) {
+                       $this->debug('no linebreak found in decodeChunked');
+                       return $new;
+               }
+               $temp = substr($buffer,0,$chunkend);
+               $chunk_size = hexdec( trim($temp) );
+               $chunkstart = $chunkend + strlen($lb);
+               // while (chunk-size > 0) {
+               while ($chunk_size > 0) {
+                       $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
+                       $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
+                       
+                       // Just in case we got a broken connection
+                       if ($chunkend == FALSE) {
+                           $chunk = substr($buffer,$chunkstart);
+                               // append chunk-data to entity-body
+                       $new .= $chunk;
+                           $length += strlen($chunk);
+                           break;
+                       }
+                       
+                       // read chunk-data and CRLF
+                       $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
+                       // append chunk-data to entity-body
+                       $new .= $chunk;
+                       // length := length + chunk-size
+                       $length += strlen($chunk);
+                       // read chunk-size and CRLF
+                       $chunkstart = $chunkend + strlen($lb);
+                       
+                       $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
+                       if ($chunkend == FALSE) {
+                               break; //Just in case we got a broken connection
+                       }
+                       $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
+                       $chunk_size = hexdec( trim($temp) );
+                       $chunkstart = $chunkend;
+               }
+               return $new;
+       }
+       
+       /*
+        *      Writes payload, including HTTP headers, to $this->outgoing_payload.
+        */
+       function buildPayload($data) {
+               // add content-length header
+               $this->outgoing_headers['Content-Length'] = strlen($data);
+               
+               // start building outgoing payload:
+               $this->outgoing_payload = "$this->request_method $this->uri HTTP/$this->protocol_version\r\n";
+
+               // loop thru headers, serializing
+               foreach($this->outgoing_headers as $k => $v){
+                       $this->outgoing_payload .= $k.': '.$v."\r\n";
+               }
+               
+               // header/body separator
+               $this->outgoing_payload .= "\r\n";
+               
+               // add data
+               $this->outgoing_payload .= $data;
+       }
+
+       function sendRequest($data){
+               // build payload
+               $this->buildPayload($data);
+
+         if ($this->scheme == 'http' || $this->scheme == 'ssl') {
+               // send payload
+               if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
+                       $this->setError('couldn\'t write message data to socket');
+                       $this->debug('couldn\'t write message data to socket');
+                       return false;
+               }
+               $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
+               return true;
+         } else if ($this->scheme == 'https') {
+               // set payload
+               // TODO: cURL does say this should only be the verb, and in fact it
+               // turns out that the URI and HTTP version are appended to this, which
+               // some servers refuse to work with
+               //curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
+               foreach($this->outgoing_headers as $k => $v){
+                       $curl_headers[] = "$k: $v";
+               }
+               curl_setopt($this->ch, CURLOPT_HTTPHEADER, $curl_headers);
+               if ($this->request_method == "POST") {
+                       curl_setopt($this->ch, CURLOPT_POST, 1);
+                       curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data);
+               } else {
+               }
+               $this->debug('set cURL payload');
+               return true;
+         }
+       }
+       
+       function getResponse(){
+               $this->incoming_payload = '';
+           
+         if ($this->scheme == 'http' || $this->scheme == 'ssl') {
+           // loop until headers have been retrieved
+           $data = '';
+           while (!isset($lb)){
+
+                       // We might EOF during header read.
+                       if(feof($this->fp)) {
+                               $this->incoming_payload = $data;
+                               $this->debug('found no headers before EOF after length ' . strlen($data));
+                               $this->debug("received before EOF:\n" . $data);
+                               $this->setError('server failed to send headers');
+                               return false;
+                       }
+
+                       $data .= fgets($this->fp, 256);
+                       $pos = strpos($data,"\r\n\r\n");
+                       if($pos > 1){
+                               $lb = "\r\n";
+                       } else {
+                               $pos = strpos($data,"\n\n");
+                               if($pos > 1){
+                                       $lb = "\n";
+                               }
+                       }
+                       // remove 100 header
+                       if(isset($lb) && ereg('^HTTP/1.1 100',$data)){
+                               unset($lb);
+                               $data = '';
+                       }//
+               }
+               // store header data
+               $this->incoming_payload .= $data;
+               $this->debug('found end of headers after length ' . strlen($data));
+               // process headers
+               $header_data = trim(substr($data,0,$pos));
+               $header_array = explode($lb,$header_data);
+               foreach($header_array as $header_line){
+                       $arr = explode(':',$header_line, 2);
+                       if(count($arr) > 1){
+                               $header_name = strtolower(trim($arr[0]));
+                               $this->incoming_headers[$header_name] = trim($arr[1]);
+                       } else if (isset($header_name)) {
+                               $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
+                       }
+               }
+               
+               // loop until msg has been received
+               // TODO: handle chunking in this loop to allow persistent connections with chunking
+               $content_length = isset($this->incoming_headers['content-length']) ? $this->incoming_headers['content-length'] : 2147483647;
+               $data = '';
+               $strlen = 0;
+           while (($strlen < $content_length) && (!feof($this->fp))) {
+               $readlen = min(8192, $content_length - $strlen);
+                       $tmp = fread($this->fp, $readlen);
+                       $strlen += strlen($tmp);
+                       $data .= $tmp;
+               }
+               $this->debug('read body of length ' . strlen($data));
+               $this->incoming_payload .= $data;
+               $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
+               
+               // close filepointer
+               if(
+                       //(isset($this->incoming_headers['connection']) && $this->incoming_headers['connection'] == 'close') || 
+                       (! $this->persistentConnection) || feof($this->fp)){
+                       fclose($this->fp);
+                       $this->fp = false;
+                       $this->debug('closed socket');
+               }
+               
+               // connection was closed unexpectedly
+               if($this->incoming_payload == ''){
+                       $this->setError('no response from server');
+                       return false;
+               }
+               
+               // decode transfer-encoding
+               if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
+                       if(!$data = $this->decodeChunked($data, $lb)){
+                               $this->setError('Decoding of chunked data failed');
+                               return false;
+                       }
+                       //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
+                       // set decoded payload
+                       $this->incoming_payload = $header_data.$lb.$lb.$data;
+               }
+               
+         } else if ($this->scheme == 'https') {
+               // send and receive
+               $this->debug('send and receive with cURL');
+               $this->incoming_payload = curl_exec($this->ch);
+               $data = $this->incoming_payload;
+
+        $cErr = curl_error($this->ch);
+               if ($cErr != '') {
+               $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
+                       foreach(curl_getinfo($this->ch) as $k => $v){
+                               $err .= "$k: $v<br>";
+                       }
+                       $this->debug($err);
+                       $this->setError($err);
+                       curl_close($this->ch);
+               return false;
+               } else {
+                       //echo '<pre>';
+                       //var_dump(curl_getinfo($this->ch));
+                       //echo '</pre>';
+               }
+               // close curl
+               $this->debug('No cURL error, closing cURL');
+               curl_close($this->ch);
+               
+               // remove 100 header
+               if (ereg('^HTTP/1.1 100',$data)) {
+                       if ($pos = strpos($data,"\r\n\r\n")) {
+                               $data = ltrim(substr($data,$pos));
+                       } elseif($pos = strpos($data,"\n\n") ) {
+                               $data = ltrim(substr($data,$pos));
+                       }
+               }
+               
+               // separate content from HTTP headers
+               if ($pos = strpos($data,"\r\n\r\n")) {
+                       $lb = "\r\n";
+               } elseif( $pos = strpos($data,"\n\n")) {
+                       $lb = "\n";
+               } else {
+                       $this->debug('no proper separation of headers and document');
+                       $this->setError('no proper separation of headers and document');
+                       return false;
+               }
+               $header_data = trim(substr($data,0,$pos));
+               $header_array = explode($lb,$header_data);
+               $data = ltrim(substr($data,$pos));
+               $this->debug('found proper separation of headers and document');
+               $this->debug('cleaned data, stringlen: '.strlen($data));
+               // clean headers
+               foreach ($header_array as $header_line) {
+                       $arr = explode(':',$header_line,2);
+                       if (count($arr) > 1) {
+                               $this->incoming_headers[strtolower(trim($arr[0]))] = trim($arr[1]);
+                       }
+               }
+         }
+
+               // see if we need to resend the request with http digest authentication
+               if (isset($this->incoming_headers['www-authenticate']) && strstr($header_array[0], '401 Unauthorized')) {
+                       if (substr("Digest ", $this->incoming_headers['www-authenticate'])) {
+                               // remove "Digest " from our elements
+                               $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
+                               
+                               // parse elements into array
+                               $digestElements = explode(', ', $digestString);
+                               while (list($key, $val) = each($digestElements)) {
+                                       $tempElement = explode('=', $val);
+                                       $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
+                               }
+
+                               // should have (at least) qop, realm, nonce
+                               if (isset($digestRequest['nonce'])) {
+                                       $this->debug('found nonce in WWW-Authenticate: ' . $this->incoming_headers['www-authenticate']);
+                                       $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
+                                       $this->tryagain = true;
+                                       return false;
+                               }
+                       }
+                       $this->debug('HTTP authentication failed');
+                       $this->setError('HTTP authentication failed');
+                       return false;
+               }
+               
+               // decode content-encoding
+               if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
+                       if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
+                       // if decoding works, use it. else assume data wasn't gzencoded
+                       if(function_exists('gzuncompress')){
+                                       //$timer->setMarker('starting decoding of gzip/deflated content');
+                                       if($this->incoming_headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)){
+                                       $data = $degzdata;
+                                       } elseif($this->incoming_headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))){    // do our best
+                                               $data = $degzdata;
+                                       } else {
+                                               $this->setError('Errors occurred when trying to decode the data');
+                                       }
+                                       //$timer->setMarker('finished decoding of gzip/deflated content');
+                                       //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
+                                       // set decoded payload
+                                       $this->incoming_payload = $header_data.$lb.$lb.$data;
+                       } else {
+                                       $this->setError('The server sent deflated data. Your php install must have the Zlib extension compiled in to support this.');
+                               }
+                       }
+               }
+               
+               if(strlen($data) == 0){
+                       $this->debug('no data after headers!');
+                       $this->setError('no data present after HTTP headers');
+                       return false;
+               }
+               
+               return $data;
+       }
+
+       function setContentType($type, $charset = false) {
+               $this->outgoing_headers['Content-Type'] = $type . ($charset ? '; charset=' . $charset : '');
+       }
+
+       function usePersistentConnection(){
+               if (isset($this->outgoing_headers['Accept-Encoding'])) {
+                       return false;
+               }
+               $this->protocol_version = '1.1';
+               $this->persistentConnection = true;
+               $this->outgoing_headers['Connection'] = 'Keep-Alive';
+               return true;
+       }
+}
+
+?><?php
+
+
+
+/**
+*
+* soap_server allows the user to create a SOAP server
+* that is capable of receiving messages and returning responses
+*
+* NOTE: WSDL functionality is experimental
+*
+* @author   Dietrich Ayala <dietrich@ganx4.com>
+* @version  $Id$
+* @access   public
+*/
+class nusoap_server extends nusoap_base {
+       var $headers = array();                 // HTTP headers of request
+       var $request = '';                              // HTTP request
+       var $requestHeaders = '';               // SOAP headers from request (incomplete namespace resolution) (text)
+       var $document = '';                             // SOAP body request portion (incomplete namespace resolution) (text)
+       var $requestSOAP = '';                  // SOAP payload for request (text)
+       var $methodURI = '';                    // requested method namespace URI
+       var $methodname = '';                   // name of method requested
+       var $methodparams = array();    // method parameters from request
+       var $xml_encoding = '';                 // character set encoding of incoming (request) messages
+       var $SOAPAction = '';                   // SOAP Action from request
+
+       var $outgoing_headers = array();// HTTP headers of response
+       var $response = '';                             // HTTP response
+       var $responseHeaders = '';              // SOAP headers for response (text)
+       var $responseSOAP = '';                 // SOAP payload for response (text)
+       var $methodreturn = false;              // method return to place in response
+       var $fault = false;                             // SOAP fault for response
+       var $result = 'successful';             // text indication of result (for debugging)
+
+       var $operations = array();              // assoc array of operations => opData
+       var $wsdl = false;                              // wsdl instance
+       var $externalWSDLURL = false;   // URL for WSDL
+       var $debug_flag = false;                // whether to append debug to response as XML comment
+       
+       /**
+       * constructor
+    * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
+       *
+    * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
+       * @access   public
+       */
+       function soap_server($wsdl=false){
+
+               // turn on debugging?
+               global $debug;
+               global $_REQUEST;
+               global $_SERVER;
+               global $HTTP_SERVER_VARS;
+
+               if (isset($debug)) {
+                       $this->debug_flag = $debug;
+               } else if (isset($_REQUEST['debug'])) {
+                       $this->debug_flag = $_REQUEST['debug'];
+               } else if (isset($_SERVER['QUERY_STRING'])) {
+                       $qs = explode('&', $_SERVER['QUERY_STRING']);
+                       foreach ($qs as $v) {
+                               if (substr($v, 0, 6) == 'debug=') {
+                                       $this->debug_flag = substr($v, 6);
+                               }
+                       }
+               } else if (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
+                       $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
+                       foreach ($qs as $v) {
+                               if (substr($v, 0, 6) == 'debug=') {
+                                       $this->debug_flag = substr($v, 6);
+                               }
+                       }
+               }
+
+               // wsdl
+               if($wsdl){
+                       if (is_object($wsdl) && is_a($wsdl, 'wsdl')) {
+                               $this->wsdl = $wsdl;
+                               $this->externalWSDLURL = $this->wsdl->wsdl;
+                               $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
+                       } else {
+                               $this->debug('Create wsdl from ' . $wsdl);
+                               $this->wsdl = new wsdl($wsdl);
+                               $this->externalWSDLURL = $wsdl;
+                       }
+                       $this->debug("wsdl...\n" . $this->wsdl->debug_str);
+                       $this->wsdl->debug_str = '';
+                       if($err = $this->wsdl->getError()){
+                               die('WSDL ERROR: '.$err);
+                       }
+               }
+       }
+
+       /**
+       * processes request and returns response
+       *
+       * @param    string $data usually is the value of $HTTP_RAW_POST_DATA
+       * @access   public
+       */
+       function service($data){
+               global $QUERY_STRING;
+               if(isset($_SERVER['QUERY_STRING'])){
+                       $qs = $_SERVER['QUERY_STRING'];
+               } elseif(isset($GLOBALS['QUERY_STRING'])){
+                       $qs = $GLOBALS['QUERY_STRING'];
+               } elseif(isset($QUERY_STRING) && $QUERY_STRING != ''){
+                       $qs = $QUERY_STRING;
+               }
+
+               if(isset($qs) && ereg('wsdl', $qs) ){
+                       // This is a request for WSDL
+                       if($this->externalWSDLURL){
+              if (strpos($this->externalWSDLURL,"://")!==false) { // assume URL
+                               header('Location: '.$this->externalWSDLURL);
+              } else { // assume file
+                header("Content-Type: text/xml\r\n");
+                $fp = fopen($this->externalWSDLURL, 'r');
+                fpassthru($fp);
+              }
+                       } else {
+                               header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
+                               print $this->wsdl->serialize();
+                       }
+               } elseif($data == '' && $this->wsdl){
+                       // print web interface
+                       print $this->webDescription();
+               } else {
+                       // handle the request
+                       $this->parse_request($data);
+                       if (! $this->fault) {
+                               $this->invoke_method();
+                       }
+                       if (! $this->fault) {
+                               $this->serialize_return();
+                       }
+                       $this->send_response();
+               }
+       }
+
+       /**
+       * parses HTTP request headers.
+       *
+       * The following fields are set by this function (when successful)
+       *
+       * headers
+       * request
+       * xml_encoding
+       * SOAPAction
+       *
+       * @access   private
+       */
+       function parse_http_headers() {
+               global $HTTP_SERVER_VARS;
+               global $_SERVER;
+
+               $this->request = '';
+               if(function_exists('getallheaders')){
+                       $this->headers = getallheaders();
+                       foreach($this->headers as $k=>$v){
+                               $this->request .= "$k: $v\r\n";
+                               $this->debug("$k: $v");
+                       }
+                       // get SOAPAction header
+                       if(isset($this->headers['SOAPAction'])){
+                               $this->SOAPAction = str_replace('"','',$this->headers['SOAPAction']);
+                       }
+                       // get the character encoding of the incoming request
+                       if(strpos($this->headers['Content-Type'],'=')){
+                               $enc = str_replace('"','',substr(strstr($this->headers["Content-Type"],'='),1));
+                               if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
+                                       $this->xml_encoding = strtoupper($enc);
+                               } else {
+                                       $this->xml_encoding = 'US-ASCII';
+                               }
+                       } else {
+                               // should be US-ASCII, but for XML, let's be pragmatic and admit UTF-8 is most common
+                               $this->xml_encoding = 'UTF-8';
+                       }
+               } elseif(isset($_SERVER) && is_array($_SERVER)){
+                       foreach ($_SERVER as $k => $v) {
+                               if (substr($k, 0, 5) == 'HTTP_') {
+                                       $k = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($k, 5)))));
+                               } else {
+                                       $k = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $k))));
+                               }
+                               if ($k == 'Soapaction') {
+                                       // get SOAPAction header
+                                       $k = 'SOAPAction';
+                                       $v = str_replace('"', '', $v);
+                                       $v = str_replace('\\', '', $v);
+                                       $this->SOAPAction = $v;
+                               } else if ($k == 'Content-Type') {
+                                       // get the character encoding of the incoming request
+                                       if (strpos($v, '=')) {
+                                               $enc = substr(strstr($v, '='), 1);
+                                               $enc = str_replace('"', '', $enc);
+                                               $enc = str_replace('\\', '', $enc);
+                                               if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) {
+                                                       $this->xml_encoding = strtoupper($enc);
+                                               } else {
+                                                       $this->xml_encoding = 'US-ASCII';
+                                               }
+                                       } else {
+                                               // should be US-ASCII, but for XML, let's be pragmatic and admit UTF-8 is most common
+                                               $this->xml_encoding = 'UTF-8';
+                                       }
+                               }
+                               $this->headers[$k] = $v;
+                               $this->request .= "$k: $v\r\n";
+                               $this->debug("$k: $v");
+                       }
+               } elseif (is_array($HTTP_SERVER_VARS)) {
+                       foreach ($HTTP_SERVER_VARS as $k => $v) {
+                               if (substr($k, 0, 5) == 'HTTP_') {
+                                       $k = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($k, 5)))));
+                                       if ($k == 'Soapaction') {
+                                               // get SOAPAction header
+                                               $k = 'SOAPAction';
+                                               $v = str_replace('"', '', $v);
+                                               $v = str_replace('\\', '', $v);
+                                               $this->SOAPAction = $v;
+                                       } else if ($k == 'Content-Type') {
+                                               // get the character encoding of the incoming request
+                                               if (strpos($v, '=')) {
+                                                       $enc = substr(strstr($v, '='), 1);
+                                                       $enc = str_replace('"', '', $enc);
+                                                       $enc = str_replace('\\', '', $enc);
+                                                       if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) {
+                                                               $this->xml_encoding = strtoupper($enc);
+                                                       } else {
+                                                               $this->xml_encoding = 'US-ASCII';
+                                                       }
+                                               } else {
+                                                       // should be US-ASCII, but for XML, let's be pragmatic and admit UTF-8 is most common
+                                                       $this->xml_encoding = 'UTF-8';
+                                               }
+                                       }
+                                       $this->headers[$k] = $v;
+                                       $this->request .= "$k: $v\r\n";
+                                       $this->debug("$k: $v");
+                               }
+                       }
+               }
+       }
+
+       /**
+       * parses a request
+       *
+       * The following fields are set by this function (when successful)
+       *
+       * headers
+       * request
+       * xml_encoding
+       * SOAPAction
+       * request
+       * requestSOAP
+       * methodURI
+       * methodname
+       * methodparams
+       * requestHeaders
+       * document
+       *
+       * This sets the fault field on error
+       *
+       * @param    string $data XML string
+       * @access   private
+       */
+       function parse_request($data='') {
+               $this->debug('entering parse_request() on '.date('H:i Y-m-d'));
+               $this->parse_http_headers();
+               $this->debug('got character encoding: '.$this->xml_encoding);
+               // uncompress if necessary
+               if (isset($this->headers['Content-Encoding']) && $this->headers['Content-Encoding'] != '') {
+                       $this->debug('got content encoding: ' . $this->headers['Content-Encoding']);
+                       if ($this->headers['Content-Encoding'] == 'deflate' || $this->headers['Content-Encoding'] == 'gzip') {
+                       // if decoding works, use it. else assume data wasn't gzencoded
+                               if (function_exists('gzuncompress')) {
+                                       if ($this->headers['Content-Encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
+                                               $data = $degzdata;
+                                       } elseif ($this->headers['Content-Encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
+                                               $data = $degzdata;
+                                       } else {
+                                               $this->fault('Server', 'Errors occurred when trying to decode the data');
+                                               return;
+                                       }
+                               } else {
+                                       $this->fault('Server', 'This Server does not support compressed data');
+                                       return;
+                               }
+                       }
+               }
+               $this->request .= "\r\n".$data;
+               $this->requestSOAP = $data;
+               // parse response, get soap parser obj
+               $parser = new soap_parser($data,$this->xml_encoding);
+               // parser debug
+               $this->debug("parser debug: \n".$parser->debug_str);
+               // if fault occurred during message parsing
+               if($err = $parser->getError()){
+                       $this->result = 'fault: error in msg parsing: '.$err;
+                       $this->fault('Server',"error in msg parsing:\n".$err);
+               // else successfully parsed request into soapval object
+               } else {
+                       // get/set methodname
+                       $this->methodURI = $parser->root_struct_namespace;
+                       $this->methodname = $parser->root_struct_name;
+                       $this->debug('method name: '.$this->methodname);
+                       $this->debug('calling parser->get_response()');
+                       $this->methodparams = $parser->get_response();
+                       // get SOAP headers
+                       $this->requestHeaders = $parser->getHeaders();
+            // add document for doclit support
+            $this->document = $parser->document;
+               }
+               $this->debug('leaving parse_request() on '.date('H:i Y-m-d'));
+       }
+
+       /**
+       * invokes a PHP function for the requested SOAP method
+       *
+       * The following fields are set by this function (when successful)
+       *
+       * methodreturn
+       *
+       * Note that the PHP function that is called may also set the following
+       * fields to affect the response sent to the client
+       *
+       * responseHeaders
+       * outgoing_headers
+       *
+       * This sets the fault field on error
+       *
+       * @access   private
+       */
+       function invoke_method() {
+               $this->debug('entering invoke_method');
+               // does method exist?
+               if(!function_exists($this->methodname)){
+                       // "method not found" fault here
+                       $this->debug("method '$this->methodname' not found!");
+                       $this->result = 'fault: method not found';
+                       $this->fault('Server',"method '$this->methodname' not defined in service");
+                       return;
+               }
+               if($this->wsdl){
+                       if(!$this->opData = $this->wsdl->getOperationData($this->methodname)){
+                       //if(
+                       $this->fault('Server',"Operation '$this->methodname' is not defined in the WSDL for this service");
+                               return;
+                   }
+                   $this->debug('opData is ' . $this->varDump($this->opData));
+               }
+               $this->debug("method '$this->methodname' exists");
+               // evaluate message, getting back parameters
+               // verify that request parameters match the method's signature
+               if(! $this->verify_method($this->methodname,$this->methodparams)){
+                       // debug
+                       $this->debug('ERROR: request not verified against method signature');
+                       $this->result = 'fault: request failed validation against method signature';
+                       // return fault
+                       $this->fault('Server',"Operation '$this->methodname' not defined in service.");
+                       return;
+               }
+
+               // if there are parameters to pass
+        $this->debug('params var dump '.$this->varDump($this->methodparams));
+               if($this->methodparams){
+                       $this->debug("calling '$this->methodname' with params");
+                       if (! function_exists('call_user_func_array')) {
+                               $this->debug('calling method using eval()');
+                               $funcCall = $this->methodname.'(';
+                               foreach($this->methodparams as $param) {
+                                       $funcCall .= "\"$param\",";
+                               }
+                               $funcCall = substr($funcCall, 0, -1).')';
+                               $this->debug('function call:<br>'.$funcCall);
+                               @eval("\$this->methodreturn = $funcCall;");
+                       } else {
+                               $this->debug('calling method using call_user_func_array()');
+                               $this->methodreturn = call_user_func_array("$this->methodname",$this->methodparams);
+                       }
+            $this->debug('response var dump'.$this->varDump($this->methodreturn));
+               } else {
+                       // call method w/ no parameters
+                       $this->debug("calling $this->methodname w/ no params");
+                       $m = $this->methodname;
+                       $this->methodreturn = @$m();
+               }
+               $this->debug("leaving invoke_method: called method $this->methodname, received $this->methodreturn of type".gettype($this->methodreturn));
+       }
+
+       /**
+       * serializes the return value from a PHP function into a full SOAP Envelope
+       *
+       * The following fields are set by this function (when successful)
+       *
+       * responseSOAP
+       *
+       * This sets the fault field on error
+       *
+       * @access   private
+       */
+       function serialize_return() {
+               $this->debug("Entering serialize_return");
+               // if we got nothing back. this might be ok (echoVoid)
+               if(isset($this->methodreturn) && ($this->methodreturn != '' || is_bool($this->methodreturn))) {
+                       // if fault
+                       if(get_class($this->methodreturn) == 'soap_fault'){
+                               $this->debug('got a fault object from method');
+                               $this->fault = $this->methodreturn;
+                               return;
+                       // if return val is soapval object
+                       } elseif(get_class($this->methodreturn) == 'soapval'){
+                               $this->debug('got a soapval object from method');
+                               $return_val = $this->methodreturn->serialize();
+                       // returned other
+                       } else {
+                               $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
+                               $this->debug('serializing return value');
+                               if($this->wsdl){
+                                       // weak attempt at supporting multiple output params
+                                       if(sizeof($this->opData['output']['parts']) > 1){
+                                       $opParams = $this->methodreturn;
+                                   } else {
+                                       $opParams = array($this->methodreturn);
+                                   }
+                                   $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
+                                       if($errstr = $this->wsdl->getError()){
+                                               $this->debug('got wsdl error: '.$errstr);
+                                               $this->fault('Server', 'got wsdl error: '.$errstr);
+                                               return;
+                                       }
+                               } else {
+                                   $return_val = $this->serialize_val($this->methodreturn, 'return');
+                               }
+                       }
+                       $this->debug('return val: '.$this->varDump($return_val));
+               } else {
+                       $return_val = '';
+                       $this->debug('got no response from method');
+               }
+               $this->debug('serializing response');
+               if ($this->wsdl) {
+                       if ($this->opData['style'] == 'rpc') {
+                               $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
+                       } else {
+                               $payload = $return_val;
+                       }
+               } else {
+                       $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
+               }
+               $this->result = 'successful';
+               if($this->wsdl){
+                       //if($this->debug_flag){
+               $this->debug("WSDL debug data:\n".$this->wsdl->debug_str);
+            // }
+                       // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
+                       $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style']);
+               } else {
+                       $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
+               }
+               $this->debug("Leaving serialize_return");
+       }
+
+       /**
+       * sends an HTTP response
+       *
+       * The following fields are set by this function (when successful)
+       *
+       * outgoing_headers
+       * response
+       *
+       * @access   private
+       */
+       function send_response() {
+               $this->debug('Enter send_response');
+               if ($this->fault) {
+                       $payload = $this->fault->serialize();
+                       $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
+                       $this->outgoing_headers[] = "Status: 500 Internal Server Error";
+               } else {
+                       $payload = $this->responseSOAP;
+                       // Some combinations of PHP+Web server allow the Status
+                       // to come through as a header.  Since OK is the default
+                       // just do nothing.
+                       // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
+                       // $this->outgoing_headers[] = "Status: 200 OK";
+               }
+        // add debug data if in debug mode
+               if(isset($this->debug_flag) && $this->debug_flag){
+                       while (strpos($this->debug_str, '--')) {
+                               $this->debug_str = str_replace('--', '- -', $this->debug_str);
+                       }
+               $payload .= "<!--\n" . $this->debug_str . "\n-->";
+        }
+               $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
+               ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
+               $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
+               // Let the Web server decide about this
+               //$this->outgoing_headers[] = "Connection: Close\r\n";
+               $this->outgoing_headers[] = "Content-Type: text/xml; charset=$this->soap_defencoding";
+               //begin code to compress payload - by John
+               if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['Accept-Encoding'])) {     
+                  if (strstr($this->headers['Accept-Encoding'], 'deflate')) {
+                               if (function_exists('gzcompress')) {
+                                       if (isset($this->debug_flag) && $this->debug_flag) {
+                                               $payload .= "<!-- Content being deflated -->";
+                                       }
+                                       $this->outgoing_headers[] = "Content-Encoding: deflate";
+                                       $payload = gzcompress($payload);
+                               } else {
+                                       if (isset($this->debug_flag) && $this->debug_flag) {
+                                               $payload .= "<!-- Content will not be deflated: no gzcompress -->";
+                                       }
+                               }
+                  } else if (strstr($this->headers['Accept-Encoding'], 'gzip')) {
+                               if (function_exists('gzencode')) {
+                                       if (isset($this->debug_flag) && $this->debug_flag) {
+                                               $payload .= "<!-- Content being gzipped -->";
+                                       }
+                                       $this->outgoing_headers[] = "Content-Encoding: gzip";
+                                       $payload = gzencode($payload);
+                               } else {
+                                       if (isset($this->debug_flag) && $this->debug_flag) {
+                                               $payload .= "<!-- Content will not be gzipped: no gzencode -->";
+                                       }
+                               }
+                       }
+               }
+               //end code
+               $this->outgoing_headers[] = "Content-Length: ".strlen($payload);
+               reset($this->outgoing_headers);
+               foreach($this->outgoing_headers as $hdr){
+                       header($hdr, false);
+               }
+               $this->response = join("\r\n",$this->outgoing_headers)."\r\n".$payload;
+               print $payload;
+       }
+
+       /**
+       * takes the value that was created by parsing the request
+       * and compares to the method's signature, if available.
+       *
+       * @param        mixed
+       * @return       boolean
+       * @access   private
+       */
+       function verify_method($operation,$request){
+               if(isset($this->wsdl) && is_object($this->wsdl)){
+                       if($this->wsdl->getOperationData($operation)){
+                               return true;
+                       }
+           } elseif(isset($this->operations[$operation])){
+                       return true;
+               }
+               return false;
+       }
+
+       /**
+       * add a method to the dispatch map
+       *
+       * @param    string $methodname
+       * @param    string $in array of input values
+       * @param    string $out array of output values
+       * @access   public
+       */
+       function add_to_map($methodname,$in,$out){
+                       $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
+       }
+
+       /**
+       * register a service with the server
+       *
+       * @param    string $methodname
+       * @param    string $in assoc array of input values: key = param name, value = param type
+       * @param    string $out assoc array of output values: key = param name, value = param type
+       * @param        string $namespace
+       * @param        string $soapaction
+       * @param        string $style optional (rpc|document)
+       * @param        string $use optional (encoded|literal)
+       * @param        string $documentation optional Description to include in WSDL
+       * @access   public
+       */
+       function register($name,$in=false,$out=false,$namespace=false,$soapaction=false,$style=false,$use=false,$documentation=''){
+               if($this->externalWSDLURL){
+                       die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
+               }
+           if(false == $in) {
+               }
+               if(false == $out) {
+               }
+               if(false == $namespace) {
+               }
+               if(false == $soapaction) {
+                       $SERVER_NAME = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : $GLOBALS['SERVER_NAME'];
+                       $SCRIPT_NAME = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : $GLOBALS['SCRIPT_NAME'];
+                       $soapaction = "http://$SERVER_NAME$SCRIPT_NAME/$name";
+               }
+               if(false == $style) {
+                       $style = "rpc";
+               }
+               if(false == $use) {
+                       $use = "encoded";
+               }
+               
+               $this->operations[$name] = array(
+           'name' => $name,
+           'in' => $in,
+           'out' => $out,
+           'namespace' => $namespace,
+           'soapaction' => $soapaction,
+           'style' => $style);
+        if($this->wsdl){
+               $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation);
+           }
+               return true;
+       }
+
+       /**
+       * create a fault. this also acts as a flag to the server that a fault has occured.
+       *
+       * @param        string faultcode
+       * @param        string faultstring
+       * @param        string faultactor
+       * @param        string faultdetail
+       * @access   public
+       */
+       function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
+               $this->fault = new soap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
+       }
+
+    /**
+    * prints html description of services
+    *
+    * @access private
+    */
+    function webDescription(){
+               $b = '
+               <html><head><title>NuSOAP: '.$this->wsdl->serviceName.'</title>
+               <style type="text/css">
+                   body    { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
+                   p       { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
+                   pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
+                   ul      { margin-top: 10px; margin-left: 20px; }
+                   li      { list-style-type: none; margin-top: 10px; color: #000000; }
+                   .content{
+                       margin-left: 0px; padding-bottom: 2em; }
+                   .nav {
+                       padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
+                       margin-top: 10px; margin-left: 0px; color: #000000;
+                       background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
+                   .title {
+                       font-family: arial; font-size: 26px; color: #ffffff;
+                       background-color: #999999; width: 105%; margin-left: 0px;
+                       padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
+                   .hidden {
+                       position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
+                       font-family: arial; overflow: hidden; width: 600;
+                       padding: 20px; font-size: 10px; background-color: #999999;
+                       layer-background-color:#FFFFFF; }
+                   a,a:active  { color: charcoal; font-weight: bold; }
+                   a:visited   { color: #666666; font-weight: bold; }
+                   a:hover     { color: cc3300; font-weight: bold; }
+               </style>
+               <script language="JavaScript" type="text/javascript">
+               <!--
+               // POP-UP CAPTIONS...
+               function lib_bwcheck(){ //Browsercheck (needed)
+                   this.ver=navigator.appVersion
+                   this.agent=navigator.userAgent
+                   this.dom=document.getElementById?1:0
+                   this.opera5=this.agent.indexOf("Opera 5")>-1
+                   this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
+                   this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
+                   this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
+                   this.ie=this.ie4||this.ie5||this.ie6
+                   this.mac=this.agent.indexOf("Mac")>-1
+                   this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
+                   this.ns4=(document.layers && !this.dom)?1:0;
+                   this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
+                   return this
+               }
+               var bw = new lib_bwcheck()
+               //Makes crossbrowser object.
+               function makeObj(obj){
+                   this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
+                   if(!this.evnt) return false
+                   this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
+                   this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
+                   this.writeIt=b_writeIt;
+                   return this
+               }
+               // A unit of measure that will be added when setting the position of a layer.
+               //var px = bw.ns4||window.opera?"":"px";
+               function b_writeIt(text){
+                   if (bw.ns4){this.wref.write(text);this.wref.close()}
+                   else this.wref.innerHTML = text
+               }
+               //Shows the messages
+               var oDesc;
+               function popup(divid){
+                   if(oDesc = new makeObj(divid)){
+                       oDesc.css.visibility = "visible"
+                   }
+               }
+               function popout(){ // Hides message
+                   if(oDesc) oDesc.css.visibility = "hidden"
+               }
+               //-->
+               </script>
+               </head>
+               <body>
+               <div class=content>
+                       <br><br>
+                       <div class=title>'.$this->wsdl->serviceName.'</div>
+                       <div class=nav>
+                               <p>View the <a href="'.(isset($GLOBALS['PHP_SELF']) ? $GLOBALS['PHP_SELF'] : $_SERVER['PHP_SELF']).'?wsdl">WSDL</a> for the service.
+                               Click on an operation name to view it&apos;s details.</p>
+                               <ul>';
+                               foreach($this->wsdl->getOperations() as $op => $data){
+                                   $b .= "<li><a href='#' onclick=\"popup('$op')\">$op</a></li>";
+                                   // create hidden div
+                                   $b .= "<div id='$op' class='hidden'>
+                                   <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
+                                   foreach($data as $donnie => $marie){ // loop through opdata
+                                               if($donnie == 'input' || $donnie == 'output'){ // show input/output data
+                                                   $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
+                                                   foreach($marie as $captain => $tenille){ // loop through data
+                                                               if($captain == 'parts'){ // loop thru parts
+                                                                   $b .= "&nbsp;&nbsp;$captain:<br>";
+                                                       //if(is_array($tenille)){
+                                                                       foreach($tenille as $joanie => $chachi){
+                                                                                       $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
+                                                                       }
+                                                               //}
+                                                               } else {
+                                                                   $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
+                                                               }
+                                                   }
+                                               } else {
+                                                   $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
+                                               }
+                                   }
+                                       $b .= '</div>';
+                               }
+                               $b .= '
+                               <ul>
+                       </div>
+               </div></body></html>';
+               return $b;
+    }
+
+    /**
+    * sets up wsdl object
+    * this acts as a flag to enable internal WSDL generation
+    *
+    * @param string $serviceName, name of the service
+    * @param string $namespace optional tns namespace
+    * @param string $endpoint optional URL of service endpoint
+    * @param string $style optional (rpc|document) WSDL style (also specified by operation)
+    * @param string $transport optional SOAP transport
+    * @param string $schemaTargetNamespace optional targetNamespace for service schema
+    */
+    function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
+    {
+               $SERVER_NAME = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : $GLOBALS['SERVER_NAME'];
+               $SERVER_PORT = isset($_SERVER['SERVER_PORT']) ? $_SERVER['SERVER_PORT'] : $GLOBALS['SERVER_PORT'];
+               if ($SERVER_PORT == 80) {
+                       $SERVER_PORT = '';
+               } else {
+                       $SERVER_PORT = ':' . $SERVER_PORT;
+               }
+               $SCRIPT_NAME = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : $GLOBALS['SCRIPT_NAME'];
+        if(false == $namespace) {
+            $namespace = "http://$SERVER_NAME/soap/$serviceName";
+        }
+        
+        if(false == $endpoint) {
+               if (isset($_SERVER['HTTPS'])) {
+                       $HTTPS = $_SERVER['HTTPS'];
+               } elseif (isset($GLOBALS['HTTPS'])) {
+                       $HTTPS = $GLOBALS['HTTPS'];
+               } else {
+                       $HTTPS = '0';
+               }
+               if ($HTTPS == '1' || $HTTPS == 'on') {
+                       $SCHEME = 'https';
+               } else {
+                       $SCHEME = 'http';
+               }
+            $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
+        }
+        
+        if(false == $schemaTargetNamespace) {
+            $schemaTargetNamespace = $namespace;
+        }
+        
+               $this->wsdl = new wsdl;
+               $this->wsdl->serviceName = $serviceName;
+        $this->wsdl->endpoint = $endpoint;
+               $this->wsdl->namespaces['tns'] = $namespace;
+               $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
+               $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
+               if ($schemaTargetNamespace != $namespace) {
+                       $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
+               }
+        $this->wsdl->schemas[$schemaTargetNamespace][0] = new xmlschema('', '', $this->wsdl->namespaces);
+        $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
+        $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
+        $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
+        $this->wsdl->bindings[$serviceName.'Binding'] = array(
+               'name'=>$serviceName.'Binding',
+            'style'=>$style,
+            'transport'=>$transport,
+            'portType'=>$serviceName.'PortType');
+        $this->wsdl->ports[$serviceName.'Port'] = array(
+               'binding'=>$serviceName.'Binding',
+            'location'=>$endpoint,
+            'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
+    }
+}
+
+
+
+?><?php
+
+
+
+/**
+* parses a WSDL file, allows access to it's data, other utility methods
+* 
+* @author   Dietrich Ayala <dietrich@ganx4.com>
+* @version  $Id$
+* @access public 
+*/
+class wsdl extends nusoap_base {
+       // URL or filename of the root of this WSDL
+    var $wsdl; 
+    // define internal arrays of bindings, ports, operations, messages, etc.
+    var $schemas = array();
+    var $currentSchema;
+    var $message = array();
+    var $complexTypes = array();
+    var $messages = array();
+    var $currentMessage;
+    var $currentOperation;
+    var $portTypes = array();
+    var $currentPortType;
+    var $bindings = array();
+    var $currentBinding;
+    var $ports = array();
+    var $currentPort;
+    var $opData = array();
+    var $status = '';
+    var $documentation = false;
+    var $endpoint = ''; 
+    // array of wsdl docs to import
+    var $import = array(); 
+    // parser vars
+    var $parser;
+    var $position = 0;
+    var $depth = 0;
+    var $depth_array = array();
+       // for getting wsdl
+       var $proxyhost = '';
+    var $proxyport = '';
+       var $proxyusername = '';
+       var $proxypassword = '';
+       var $timeout = 0;
+       var $response_timeout = 30;
+
+    /**
+     * constructor
+     * 
+     * @param string $wsdl WSDL document URL
+        * @param string $proxyhost
+        * @param string $proxyport
+        * @param string $proxyusername
+        * @param string $proxypassword
+        * @param integer $timeout set the connection timeout
+        * @param integer $response_timeout set the response timeout
+     * @access public 
+     */
+    function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30){
+        $this->wsdl = $wsdl;
+        $this->proxyhost = $proxyhost;
+        $this->proxyport = $proxyport;
+               $this->proxyusername = $proxyusername;
+               $this->proxypassword = $proxypassword;
+               $this->timeout = $timeout;
+               $this->response_timeout = $response_timeout;
+        
+        // parse wsdl file
+        if ($wsdl != "") {
+            $this->debug('initial wsdl URL: ' . $wsdl);
+            $this->parseWSDL($wsdl);
+        }
+        // imports
+        // TODO: handle imports more properly, grabbing them in-line and nesting them
+               $imported_urls = array();
+               $imported = 1;
+               while ($imported > 0) {
+                       $imported = 0;
+                       // Schema imports
+                       foreach ($this->schemas as $ns => $list) {
+                               foreach ($list as $xs) {
+                                               $wsdlparts = parse_url($this->wsdl);    // this is bogusly simple!
+                                   foreach ($xs->imports as $ns2 => $list2) {
+                                       for ($ii = 0; $ii < count($list2); $ii++) {
+                                               if (! $list2[$ii]['loaded']) {
+                                                       $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
+                                                       $url = $list2[$ii]['location'];
+                                                                       if ($url != '') {
+                                                                               $urlparts = parse_url($url);
+                                                                               if (!isset($urlparts['host'])) {
+                                                                                       $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . 
+                                                                                                       substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
+                                                                               }
+                                                                               if (! in_array($url, $imported_urls)) {
+                                                                       $this->parseWSDL($url);
+                                                                       $imported++;
+                                                                       $imported_urls[] = $url;
+                                                               }
+                                                                       } else {
+                                                                               $this->debug("Unexpected scenario: empty URL for unloaded import");
+                                                                       }
+                                                               }
+                                                       }
+                                   } 
+                               }
+                       }
+                       // WSDL imports
+                               $wsdlparts = parse_url($this->wsdl);    // this is bogusly simple!
+                   foreach ($this->import as $ns => $list) {
+                       for ($ii = 0; $ii < count($list); $ii++) {
+                               if (! $list[$ii]['loaded']) {
+                                       $this->import[$ns][$ii]['loaded'] = true;
+                                       $url = $list[$ii]['location'];
+                                                       if ($url != '') {
+                                                               $urlparts = parse_url($url);
+                                                               if (!isset($urlparts['host'])) {
+                                                                       $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . 
+                                                                                       substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
+                                                               }
+                                                               if (! in_array($url, $imported_urls)) {
+                                                       $this->parseWSDL($url);
+                                                       $imported++;
+                                                       $imported_urls[] = $url;
+                                               }
+                                                       } else {
+                                                               $this->debug("Unexpected scenario: empty URL for unloaded import");
+                                                       }
+                                               }
+                                       }
+                   } 
+                       }
+        // add new data to operation data
+        foreach($this->bindings as $binding => $bindingData) {
+            if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
+                foreach($bindingData['operations'] as $operation => $data) {
+                    $this->debug('post-parse data gathering for ' . $operation);
+                    $this->bindings[$binding]['operations'][$operation]['input'] = 
+                                               isset($this->bindings[$binding]['operations'][$operation]['input']) ? 
+                                               array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
+                                               $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
+                    $this->bindings[$binding]['operations'][$operation]['output'] = 
+                                               isset($this->bindings[$binding]['operations'][$operation]['output']) ?
+                                               array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
+                                               $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
+                    if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
+                                               $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
+                                       }
+                                       if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
+                               $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
+                    }
+                                       if (isset($bindingData['style'])) {
+                        $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
+                    }
+                    $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
+                    $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
+                    $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
+                } 
+            } 
+        }
+    }
+
+    /**
+     * parses the wsdl document
+     * 
+     * @param string $wsdl path or URL
+     * @access private 
+     */
+    function parseWSDL($wsdl = '')
+    {
+        if ($wsdl == '') {
+            $this->debug('no wsdl passed to parseWSDL()!!');
+            $this->setError('no wsdl passed to parseWSDL()!!');
+            return false;
+        }
+        
+        // parse $wsdl for url format
+        $wsdl_props = parse_url($wsdl);
+
+        if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
+            $this->debug('getting WSDL http(s) URL ' . $wsdl);
+               // get wsdl
+               $tr = new soap_transport_http($wsdl);
+                       $tr->request_method = 'GET';
+                       $tr->useSOAPAction = false;
+                       if($this->proxyhost && $this->proxyport){
+                               $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
+                       }
+                       if (isset($wsdl_props['user'])) {
+                $tr->setCredentials($wsdl_props['user'],$wsdl_props['pass']);
+            }
+                       $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
+                       //$this->debug("WSDL request\n" . $tr->outgoing_payload);
+                       //$this->debug("WSDL response\n" . $tr->incoming_payload);
+                       $this->debug("transport debug data...\n" . $tr->debug_str);
+                       // catch errors
+                       if($err = $tr->getError() ){
+                               $errstr = 'HTTP ERROR: '.$err;
+                               $this->debug($errstr);
+                   $this->setError($errstr);
+                               unset($tr);
+                   return false;
+                       }
+                       unset($tr);
+        } else {
+            // $wsdl is not http(s), so treat it as a file URL or plain file path
+               if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
+                       $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
+               } else {
+                       $path = $wsdl;
+               }
+            $this->debug('getting WSDL file ' . $path);
+            if ($fp = @fopen($path, 'r')) {
+                $wsdl_string = '';
+                while ($data = fread($fp, 32768)) {
+                    $wsdl_string .= $data;
+                } 
+                fclose($fp);
+            } else {
+               $errstr = "Bad path to WSDL file $path";
+               $this->debug($errstr);
+                $this->setError($errstr);
+                return false;
+            } 
+        }
+        // end new code added
+        // Create an XML parser.
+        $this->parser = xml_parser_create(); 
+        // Set the options for parsing the XML data.
+        // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
+        xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); 
+        // Set the object for the parser.
+        xml_set_object($this->parser, $this); 
+        // Set the element handlers for the parser.
+        xml_set_element_handler($this->parser, 'start_element', 'end_element');
+        xml_set_character_data_handler($this->parser, 'character_data');
+        // Parse the XML file.
+        if (!xml_parse($this->parser, $wsdl_string, true)) {
+            // Display an error message.
+            $errstr = sprintf(
+                               'XML error parsing WSDL from %s on line %d: %s',
+                               $wsdl,
+                xml_get_current_line_number($this->parser),
+                xml_error_string(xml_get_error_code($this->parser))
+                );
+            $this->debug($errstr);
+                       $this->debug("XML payload:\n" . $wsdl_string);
+            $this->setError($errstr);
+            return false;
+        } 
+               // free the parser
+        xml_parser_free($this->parser);
+               // catch wsdl parse errors
+               if($this->getError()){
+                       return false;
+               }
+        return true;
+    } 
+
+    /**
+     * start-element handler
+     * 
+     * @param string $parser XML parser object
+     * @param string $name element name
+     * @param string $attrs associative array of attributes
+     * @access private 
+     */
+    function start_element($parser, $name, $attrs)
+    {
+        if ($this->status == 'schema') {
+            $this->currentSchema->schemaStartElement($parser, $name, $attrs);
+            $this->debug_str .= $this->currentSchema->debug_str;
+            $this->currentSchema->debug_str = '';
+        } elseif (ereg('schema$', $name)) {
+            // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
+            $this->status = 'schema';
+            $this->currentSchema = new xmlschema('', '', $this->namespaces);
+            $this->currentSchema->schemaStartElement($parser, $name, $attrs);
+            $this->debug_str .= $this->currentSchema->debug_str;
+            $this->currentSchema->debug_str = '';
+        } else {
+            // position in the total number of elements, starting from 0
+            $pos = $this->position++;
+            $depth = $this->depth++; 
+            // set self as current value for this depth
+            $this->depth_array[$depth] = $pos;
+            $this->message[$pos] = array('cdata' => ''); 
+            // get element prefix
+            if (ereg(':', $name)) {
+                // get ns prefix
+                $prefix = substr($name, 0, strpos($name, ':')); 
+                // get ns
+                $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : ''; 
+                // get unqualified name
+                $name = substr(strstr($name, ':'), 1);
+            } 
+
+            if (count($attrs) > 0) {
+                foreach($attrs as $k => $v) {
+                    // if ns declarations, add to class level array of valid namespaces
+                    if (ereg("^xmlns", $k)) {
+                        if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
+                            $this->namespaces[$ns_prefix] = $v;
+                        } else {
+                            $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
+                        } 
+                        if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema') {
+                            $this->XMLSchemaVersion = $v;
+                            $this->namespaces['xsi'] = $v . '-instance';
+                        } 
+                    } //  
+                    // expand each attribute
+                    $k = strpos($k, ':') ? $this->expandQname($k) : $k;
+                    if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
+                        $v = strpos($v, ':') ? $this->expandQname($v) : $v;
+                    } 
+                    $eAttrs[$k] = $v;
+                } 
+                $attrs = $eAttrs;
+            } else {
+                $attrs = array();
+            } 
+            // find status, register data
+            switch ($this->status) {
+                case 'message':
+                    if ($name == 'part') {
+                       if (isset($attrs['type'])) {
+                                   $this->debug("msg " . $this->currentMessage . ": found part $attrs[name]: " . implode(',', $attrs));
+                                   $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
+                               } 
+                                   if (isset($attrs['element'])) {
+                                       $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'];
+                                   } 
+                               } 
+                               break;
+                           case 'portType':
+                               switch ($name) {
+                                   case 'operation':
+                                       $this->currentPortOperation = $attrs['name'];
+                                       $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
+                                       if (isset($attrs['parameterOrder'])) {
+                                               $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
+                                               } 
+                                               break;
+                                           case 'documentation':
+                                               $this->documentation = true;
+                                               break; 
+                                           // merge input/output data
+                                           default:
+                                               $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
+                                               $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
+                                               break;
+                                       } 
+                               break;
+                               case 'binding':
+                                   switch ($name) {
+                                       case 'binding': 
+                                           // get ns prefix
+                                           if (isset($attrs['style'])) {
+                                           $this->bindings[$this->currentBinding]['prefix'] = $prefix;
+                                               } 
+                                               $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
+                                               break;
+                                               case 'header':
+                                                   $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
+                                                   break;
+                                               case 'operation':
+                                                   if (isset($attrs['soapAction'])) {
+                                                       $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
+                                                   } 
+                                                   if (isset($attrs['style'])) {
+                                                       $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
+                                                   } 
+                                                   if (isset($attrs['name'])) {
+                                                       $this->currentOperation = $attrs['name'];
+                                                       $this->debug("current binding operation: $this->currentOperation");
+                                                       $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
+                                                       $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
+                                                       $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
+                                                   } 
+                                                   break;
+                                               case 'input':
+                                                   $this->opStatus = 'input';
+                                                   break;
+                                               case 'output':
+                                                   $this->opStatus = 'output';
+                                                   break;
+                                               case 'body':
+                                                   if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
+                                                       $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
+                                                   } else {
+                                                       $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
+                                                   } 
+                                                   break;
+                                       } 
+                                       break;
+                               case 'service':
+                                       switch ($name) {
+                                           case 'port':
+                                               $this->currentPort = $attrs['name'];
+                                               $this->debug('current port: ' . $this->currentPort);
+                                               $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
+                                       
+                                               break;
+                                           case 'address':
+                                               $this->ports[$this->currentPort]['location'] = $attrs['location'];
+                                               $this->ports[$this->currentPort]['bindingType'] = $namespace;
+                                               $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
+                                               $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
+                                               break;
+                                       } 
+                                       break;
+                       } 
+               // set status
+               switch ($name) {
+                       case 'import':
+                           if (isset($attrs['location'])) {
+                    $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
+                    $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
+                               } else {
+                    $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
+                                       if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
+                                               $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
+                                       }
+                    $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
+                               }
+                               break;
+                       //wait for schema
+                       //case 'types':
+                       //      $this->status = 'schema';
+                       //      break;
+                       case 'message':
+                               $this->status = 'message';
+                               $this->messages[$attrs['name']] = array();
+                               $this->currentMessage = $attrs['name'];
+                               break;
+                       case 'portType':
+                               $this->status = 'portType';
+                               $this->portTypes[$attrs['name']] = array();
+                               $this->currentPortType = $attrs['name'];
+                               break;
+                       case "binding":
+                               if (isset($attrs['name'])) {
+                               // get binding name
+                                       if (strpos($attrs['name'], ':')) {
+                                       $this->currentBinding = $this->getLocalPart($attrs['name']);
+                                       } else {
+                                       $this->currentBinding = $attrs['name'];
+                                       } 
+                                       $this->status = 'binding';
+                                       $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
+                                       $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
+                               } 
+                               break;
+                       case 'service':
+                               $this->serviceName = $attrs['name'];
+                               $this->status = 'service';
+                               $this->debug('current service: ' . $this->serviceName);
+                               break;
+                       case 'definitions':
+                               foreach ($attrs as $name => $value) {
+                                       $this->wsdl_info[$name] = $value;
+                               } 
+                               break;
+                       } 
+               } 
+       } 
+
+       /**
+       * end-element handler
+       * 
+       * @param string $parser XML parser object
+       * @param string $name element name
+       * @access private 
+       */
+       function end_element($parser, $name){ 
+               // unset schema status
+               if (/*ereg('types$', $name) ||*/ ereg('schema$', $name)) {
+                       $this->status = "";
+                       $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
+               } 
+               if ($this->status == 'schema') {
+                       $this->currentSchema->schemaEndElement($parser, $name);
+               } else {
+                       // bring depth down a notch
+                       $this->depth--;
+               } 
+               // end documentation
+               if ($this->documentation) {
+                       //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
+                       //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
+                       $this->documentation = false;
+               } 
+       } 
+
+       /**
+        * element content handler
+        * 
+        * @param string $parser XML parser object
+        * @param string $data element content
+        * @access private 
+        */
+       function character_data($parser, $data)
+       {
+               $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
+               if (isset($this->message[$pos]['cdata'])) {
+                       $this->message[$pos]['cdata'] .= $data;
+               } 
+               if ($this->documentation) {
+                       $this->documentation .= $data;
+               } 
+       } 
+       
+       function getBindingData($binding)
+       {
+               if (is_array($this->bindings[$binding])) {
+                       return $this->bindings[$binding];
+               } 
+       }
+       
+       /**
+        * returns an assoc array of operation names => operation data
+        * 
+        * @param string $bindingType eg: soap, smtp, dime (only soap is currently supported)
+        * @return array 
+        * @access public 
+        */
+       function getOperations($bindingType = 'soap')
+       {
+               $ops = array();
+               if ($bindingType == 'soap') {
+                       $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
+               }
+               // loop thru ports
+               foreach($this->ports as $port => $portData) {
+                       // binding type of port matches parameter
+                       if ($portData['bindingType'] == $bindingType) {
+                               //$this->debug("getOperations for port $port");
+                               //$this->debug("port data: " . $this->varDump($portData));
+                               //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
+                               // merge bindings
+                               if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
+                                       $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
+                               }
+                       }
+               } 
+               return $ops;
+       } 
+       
+       /**
+        * returns an associative array of data necessary for calling an operation
+        * 
+        * @param string $operation , name of operation
+        * @param string $bindingType , type of binding eg: soap
+        * @return array 
+        * @access public 
+        */
+       function getOperationData($operation, $bindingType = 'soap')
+       {
+               if ($bindingType == 'soap') {
+                       $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
+               }
+               // loop thru ports
+               foreach($this->ports as $port => $portData) {
+                       // binding type of port matches parameter
+                       if ($portData['bindingType'] == $bindingType) {
+                               // get binding
+                               //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
+                               foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
+                                       if ($operation == $bOperation) {
+                                               $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
+                                           return $opData;
+                                       } 
+                               } 
+                       }
+               } 
+       }
+       
+       /**
+    * returns an array of information about a given type
+    * returns false if no type exists by the given name
+    *
+       *        typeDef = array(
+       *        'elements' => array(), // refs to elements array
+       *       'restrictionBase' => '',
+       *       'phpType' => '',
+       *       'order' => '(sequence|all)',
+       *       'attrs' => array() // refs to attributes array
+       *       )
+    *
+    * @param $type string
+    * @param $ns string
+    * @return mixed
+    * @access public
+    * @see xmlschema
+    */
+       function getTypeDef($type, $ns) {
+               if ((! $ns) && isset($this->namespaces['tns'])) {
+                       $ns = $this->namespaces['tns'];
+               }
+               if (isset($this->schemas[$ns])) {
+                       foreach ($this->schemas[$ns] as $xs) {
+                               $t = $xs->getTypeDef($type);
+                               $this->debug_str .= $xs->debug_str;
+                               $xs->debug_str = '';
+                               if ($t) {
+                                       return $t;
+                               }
+                       }
+               }
+               return false;
+       }
+
+       /**
+       * serialize the parsed wsdl
+       * 
+       * @return string , serialization of WSDL
+       * @access public 
+       */
+       function serialize()
+       {
+               $xml = '<?xml version="1.0" encoding="ISO-8859-1"?><definitions';
+               foreach($this->namespaces as $k => $v) {
+                       $xml .= " xmlns:$k=\"$v\"";
+               } 
+               // 10.9.02 - add poulter fix for wsdl and tns declarations
+               if (isset($this->namespaces['wsdl'])) {
+                       $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
+               } 
+               if (isset($this->namespaces['tns'])) {
+                       $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
+               } 
+               $xml .= '>'; 
+               // imports
+               if (sizeof($this->import) > 0) {
+                       foreach($this->import as $ns => $list) {
+                               foreach ($list as $ii) {
+                                       if ($ii['location'] != '') {
+                                               $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
+                                       } else {
+                                               $xml .= '<import namespace="' . $ns . '" />';
+                                       }
+                               }
+                       } 
+               } 
+               // types
+               if (count($this->schemas)>=1) {
+                       $xml .= '<types>';
+                       foreach ($this->schemas as $ns => $list) {
+                               foreach ($list as $xs) {
+                                       $xml .= $xs->serializeSchema();
+                               }
+                       }
+                       $xml .= '</types>';
+               } 
+               // messages
+               if (count($this->messages) >= 1) {
+                       foreach($this->messages as $msgName => $msgParts) {
+                               $xml .= '<message name="' . $msgName . '">';
+                               if(is_array($msgParts)){
+                                       foreach($msgParts as $partName => $partType) {
+                                               // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
+                                               if (strpos($partType, ':')) {
+                                                   $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
+                                               } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
+                                                   // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
+                                                   $typePrefix = 'xsd';
+                                               } else {
+                                                   foreach($this->typemap as $ns => $types) {
+                                                       if (isset($types[$partType])) {
+                                                           $typePrefix = $this->getPrefixFromNamespace($ns);
+                                                       } 
+                                                   } 
+                                                   if (!isset($typePrefix)) {
+                                                       die("$partType has no namespace!");
+                                                   } 
+                                               } 
+                                               $xml .= '<part name="' . $partName . '" type="' . $typePrefix . ':' . $this->getLocalPart($partType) . '" />';
+                                       }
+                               }
+                               $xml .= '</message>';
+                       } 
+               } 
+               // bindings & porttypes
+               if (count($this->bindings) >= 1) {
+                       $binding_xml = '';
+                       $portType_xml = '';
+                       foreach($this->bindings as $bindingName => $attrs) {
+                               $binding_xml .= '<binding name="' . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
+                               $binding_xml .= '<soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
+                               $portType_xml .= '<portType name="' . $attrs['portType'] . '">';
+                               foreach($attrs['operations'] as $opName => $opParts) {
+                                       $binding_xml .= '<operation name="' . $opName . '">';
+                                       $binding_xml .= '<soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $attrs['style'] . '"/>';
+                                       if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
+                                               $enc_style = '" encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
+                                       } else {
+                                               $enc_style = '';
+                                       }
+                                       $binding_xml .= '<input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . $enc_style . '/></input>';
+                                       if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
+                                               $enc_style = '" encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
+                                       } else {
+                                               $enc_style = '';
+                                       }
+                                       $binding_xml .= '<output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . $enc_style . '/></output>';
+                                       $binding_xml .= '</operation>';
+                                       $portType_xml .= '<operation name="' . $opParts['name'] . '"';
+                                       if (isset($opParts['parameterOrder'])) {
+                                           $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
+                                       } 
+                                       $portType_xml .= '>';
+                                       if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
+                                               $portType_xml .= '<documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
+                                       }
+                                       $portType_xml .= '<input message="tns:' . $opParts['input']['message'] . '"/>';
+                                       $portType_xml .= '<output message="tns:' . $opParts['output']['message'] . '"/>';
+                                       $portType_xml .= '</operation>';
+                               } 
+                               $portType_xml .= '</portType>';
+                               $binding_xml .= '</binding>';
+                       } 
+                       $xml .= $portType_xml . $binding_xml;
+               } 
+               // services
+               $xml .= '<service name="' . $this->serviceName . '">';
+               if (count($this->ports) >= 1) {
+                       foreach($this->ports as $pName => $attrs) {
+                               $xml .= '<port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
+                               $xml .= '<soap:address location="' . $attrs['location'] . '"/>';
+                               $xml .= '</port>';
+                       } 
+               } 
+               $xml .= '</service>';
+               return $xml . '</definitions>';
+       } 
+       
+       /**
+        * serialize a PHP value according to a WSDL message definition
+        * 
+        * TODO
+        * - multi-ref serialization
+        * - validate PHP values against type definitions, return errors if invalid
+        * 
+        * @param string $ type name
+        * @param mixed $ param value
+        * @return mixed new param or false if initial value didn't validate
+        */
+       function serializeRPCParameters($operation, $direction, $parameters)
+       {
+               $this->debug('in serializeRPCParameters with operation '.$operation.', direction '.$direction.' and '.count($parameters).' param(s), and xml schema version ' . $this->XMLSchemaVersion); 
+               
+               if ($direction != 'input' && $direction != 'output') {
+                       $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
+                       $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
+                       return false;
+               } 
+               if (!$opData = $this->getOperationData($operation)) {
+                       $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
+                       $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
+                       return false;
+               }
+               $this->debug($this->varDump($opData));
+
+               // Get encoding style for output and set to current
+               $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
+               if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
+                       $encodingStyle = $opData['output']['encodingStyle'];
+                       $enc_style = $encodingStyle;
+               }
+
+               // set input params
+               $xml = '';
+               if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
+                       
+                       $use = $opData[$direction]['use'];
+                       $this->debug("use=$use");
+                       $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
+                       if (is_array($parameters)) {
+                               $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
+                               $this->debug('have ' . $parametersArrayType . ' parameters');
+                               foreach($opData[$direction]['parts'] as $name => $type) {
+                                       $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
+                                       // Track encoding style
+                                       if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
+                                               $encodingStyle = $opData[$direction]['encodingStyle'];                  
+                                               $enc_style = $encodingStyle;
+                                       } else {
+                                               $enc_style = false;
+                                       }
+                                       // NOTE: add error handling here
+                                       // if serializeType returns false, then catch global error and fault
+                                       if ($parametersArrayType == 'arraySimple') {
+                                               $p = array_shift($parameters);
+                                               $this->debug('calling serializeType w/indexed param');
+                                               $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
+                                       } elseif (isset($parameters[$name])) {
+                                               $this->debug('calling serializeType w/named param');
+                                               $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
+                                       } else {
+                                               // TODO: only send nillable
+                                               $this->debug('calling serializeType w/null param');
+                                               $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
+                                       }
+                               }
+                       } else {
+                               $this->debug('no parameters passed.');
+                       }
+               }
+               return $xml;
+       } 
+       
+       /**
+        * serialize a PHP value according to a WSDL message definition
+        * 
+        * TODO
+        * - multi-ref serialization
+        * - validate PHP values against type definitions, return errors if invalid
+        * 
+        * @param string $ type name
+        * @param mixed $ param value
+        * @return mixed new param or false if initial value didn't validate
+        */
+       function serializeParameters($operation, $direction, $parameters)
+       {
+               $this->debug('in serializeParameters with operation '.$operation.', direction '.$direction.' and '.count($parameters).' param(s), and xml schema version ' . $this->XMLSchemaVersion); 
+               
+               if ($direction != 'input' && $direction != 'output') {
+                       $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
+                       $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
+                       return false;
+               } 
+               if (!$opData = $this->getOperationData($operation)) {
+                       $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
+                       $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
+                       return false;
+               }
+               $this->debug($this->varDump($opData));
+               
+               // Get encoding style for output and set to current
+               $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
+               if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
+                       $encodingStyle = $opData['output']['encodingStyle'];
+                       $enc_style = $encodingStyle;
+               }
+               
+               // set input params
+               $xml = '';
+               if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
+                       
+                       $use = $opData[$direction]['use'];
+                       $this->debug("use=$use");
+                       $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
+                       if (is_array($parameters)) {
+                               $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
+                               $this->debug('have ' . $parametersArrayType . ' parameters');
+                               foreach($opData[$direction]['parts'] as $name => $type) {
+                                       $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
+                                       // Track encoding style
+                                       if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
+                                               $encodingStyle = $opData[$direction]['encodingStyle'];                  
+                                               $enc_style = $encodingStyle;
+                                       } else {
+                                               $enc_style = false;
+                                       }
+                                       // NOTE: add error handling here
+                                       // if serializeType returns false, then catch global error and fault
+                                       if ($parametersArrayType == 'arraySimple') {
+                                               $p = array_shift($parameters);
+                                               $this->debug('calling serializeType w/indexed param');
+                                               $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
+                                       } elseif (isset($parameters[$name])) {
+                                               $this->debug('calling serializeType w/named param');
+                                               $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
+                                       } else {
+                                               // TODO: only send nillable
+                                               $this->debug('calling serializeType w/null param');
+                                               $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
+                                       }
+                               }
+                       } else {
+                               $this->debug('no parameters passed.');
+                       }
+               }
+               return $xml;
+       } 
+       
+       /**
+        * serializes a PHP value according a given type definition
+        * 
+        * @param string $name , name of type (part)
+        * @param string $type , type of type, heh (type or element)
+        * @param mixed $value , a native PHP value (parameter value)
+        * @param string $use , use for part (encoded|literal)
+        * @param string $encodingStyle , use to add encoding changes to serialisation
+        * @return string serialization
+        * @access public 
+        */
+       function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false)
+       {
+               $this->debug("in serializeType: $name, $type, $value, $use, $encodingStyle");
+               if($use == 'encoded' && $encodingStyle) {
+                       $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
+               }
+
+               // if a soap_val has been supplied, let its type override the WSDL
+       if (is_object($value) && get_class($value) == 'soapval') {
+               // TODO: get attributes from soapval?
+               if ($value->type_ns) {
+                       $type = $value->type_ns . ':' . $value->type;
+               } else {
+                       $type = $value->type;
+               }
+               $value = $value->value;
+               $forceType = true;
+               $this->debug("in serializeType: soapval overrides type to $type, value to $value");
+        } else {
+               $forceType = false;
+        }
+
+               $xml = '';
+               if (strpos($type, ':')) {
+                       $uqType = substr($type, strrpos($type, ':') + 1);
+                       $ns = substr($type, 0, strrpos($type, ':'));
+                       $this->debug("got a prefixed type: $uqType, $ns");
+                       if ($this->getNamespaceFromPrefix($ns)) {
+                               $ns = $this->getNamespaceFromPrefix($ns);
+                               $this->debug("expanded prefixed type: $uqType, $ns");
+                       }
+
+                       if($ns == $this->XMLSchemaVersion){
+                               
+                               if (is_null($value)) {
+                                       if ($use == 'literal') {
+                                               // TODO: depends on nillable
+                                               return "<$name/>";
+                                       } else {
+                                               return "<$name xsi:nil=\"true\"/>";
+                                       }
+                               }
+                       if ($uqType == 'boolean' && !$value) {
+                                       $value = 'false';
+                               } elseif ($uqType == 'boolean') {
+                                       $value = 'true';
+                               } 
+                               if ($uqType == 'string' && gettype($value) == 'string') {
+                                       $value = $this->expandEntities($value);
+                               } 
+                               // it's a scalar
+                               // TODO: what about null/nil values?
+                               // check type isn't a custom type extending xmlschema namespace
+                               if (!$this->getTypeDef($uqType, $ns)) {
+                                       if ($use == 'literal') {
+                                               if ($forceType) {
+                                                       return "<$name xsi:type=\"" . $this->getPrefixFromNamespace($this->XMLSchemaVersion) . ":$uqType\">$value</$name>";
+                                               } else {
+                                                       return "<$name>$value</$name>";
+                                               }
+                                       } else {
+                                               return "<$name xsi:type=\"" . $this->getPrefixFromNamespace($this->XMLSchemaVersion) . ":$uqType\"$encodingStyle>$value</$name>";
+                                       }
+                               }
+                       } else if ($ns == 'http://xml.apache.org/xml-soap') {
+                               if ($uqType == 'Map') {
+                                       $contents = '';
+                                       foreach($value as $k => $v) {
+                                               $this->debug("serializing map element: key $k, value $v");
+                                               $contents .= '<item>';
+                                               $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
+                                               $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
+                                               $contents .= '</item>';
+                                       }
+                                       if ($use == 'literal') {
+                                               if ($forceType) {
+                                               return "<$name xsi:type=\"" . $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap') . ":$uqType\">$contents</$name>";
+                                               } else {
+                                                       return "<$name>$contents</$name>";
+                                               }
+                                       } else {
+                                               return "<$name xsi:type=\"" . $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap') . ":$uqType\"$encodingStyle>$contents</$name>";
+                                       }
+                               }
+                       }
+               } else {
+                       $this->debug("No namespace for type $type");
+                       $ns = '';
+                       $uqType = $type;
+               }
+               if(!$typeDef = $this->getTypeDef($uqType, $ns)){
+                       $this->setError("$type ($uqType) is not a supported type.");
+                       $this->debug("$type ($uqType) is not a supported type.");
+                       return false;
+               } else {
+                       foreach($typeDef as $k => $v) {
+                               $this->debug("typedef, $k: $v");
+                       }
+               }
+               $phpType = $typeDef['phpType'];
+               $this->debug("serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') ); 
+               // if php type == struct, map value to the <all> element names
+               if ($phpType == 'struct') {
+                       if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
+                               $elementName = $uqType;
+                               if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
+                                       $elementNS = " xmlns=\"$ns\"";
+                               }
+                       } else {
+                               $elementName = $name;
+                               $elementNS = '';
+                       }
+                       if (is_null($value)) {
+                               if ($use == 'literal') {
+                                       // TODO: depends on nillable
+                                       return "<$elementName$elementNS/>";
+                               } else {
+                                       return "<$elementName$elementNS xsi:nil=\"true\"/>";
+                               }
+                       }
+                       if ($use == 'literal') {
+                               if ($forceType) {
+                                       $xml = "<$elementName$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
+                               } else {
+                                       $xml = "<$elementName$elementNS>";
+                               }
+                       } else {
+                               $xml = "<$elementName$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
+                       }
+                       
+                       if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
+                       
+                               // toggle whether all elements are present - ideally should validate against schema
+                               if(count($typeDef['elements']) != count($value)){
+                                       $optionals = true;
+                               }
+                               foreach($typeDef['elements'] as $eName => $attrs) {
+                                       // if user took advantage of a minOccurs=0, then only serialize named parameters
+                                       if(isset($optionals) && !isset($value[$eName])){
+                                               // do nothing
+                                       } else {
+                                               // TODO: if maxOccurs > 1, then allow serialization of an array
+                                               // get value
+                                               if (isset($value[$eName])) {
+                                                   $v = $value[$eName];
+                                               } else {
+                                                   $v = null;
+                                               }
+                                               if (isset($attrs['maxOccurs']) && $attrs['maxOccurs'] == 'unbounded' && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
+                                                       $vv = $v;
+                                                       foreach ($vv as $k => $v) {
+                                                               if (isset($attrs['type'])) {
+                                                                       // serialize schema-defined type
+                                                                   $xml .= $this->serializeType($eName, $attrs['type'], $v, $use, $encodingStyle);
+                                                               } else {
+                                                                       // serialize generic type
+                                                                   $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
+                                                                   $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
+                                                               }
+                                                       }
+                                               } else {
+                                                       if (isset($attrs['type'])) {
+                                                               // serialize schema-defined type
+                                                           $xml .= $this->serializeType($eName, $attrs['type'], $v, $use, $encodingStyle);
+                                                       } else {
+                                                               // serialize generic type
+                                                           $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
+                                                           $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
+                                                       }
+                                               }
+                                       }
+                               } 
+                       } else {
+                               //echo 'got here';
+                       }
+                       $xml .= "</$elementName>";
+               } elseif ($phpType == 'array') {
+                       if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
+                               $elementNS = " xmlns=\"$ns\"";
+                       } else {
+                               $elementNS = '';
+                       }
+                       if (is_null($value)) {
+                               if ($use == 'literal') {
+                                       // TODO: depends on nillable
+                                       return "<$name$elementNS/>";
+                               } else {
+                                       return "<$name$elementNS xsi:nil=\"true\"/>";
+                               }
+                       }
+                       if (isset($typeDef['multidimensional'])) {
+                               $nv = array();
+                               foreach($value as $v) {
+                                       $cols = ',' . sizeof($v);
+                                       $nv = array_merge($nv, $v);
+                               } 
+                               $value = $nv;
+                       } else {
+                               $cols = '';
+                       } 
+                       if (is_array($value) && sizeof($value) >= 1) {
+                               $rows = sizeof($value);
+                               $contents = '';
+                               foreach($value as $k => $v) {
+                                       $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
+                                       //if (strpos($typeDef['arrayType'], ':') ) {
+                                       if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
+                                           $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
+                                       } else {
+                                           $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
+                                       } 
+                               }
+                               $this->debug('contents: '.$this->varDump($contents));
+                       } else {
+                               $rows = 0;
+                               $contents = null;
+                       }
+                       // TODO: for now, an empty value will be serialized as a zero element
+                       // array.  Revisit this when coding the handling of null/nil values.
+                       if ($use == 'literal') {
+                               $xml = "<$name$elementNS>"
+                                       .$contents
+                                       ."</$name>";
+                       } else {
+                               $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
+                                       $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
+                                       .':arrayType="'
+                                       .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
+                                       .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
+                                       .$contents
+                                       ."</$name>";
+                       }
+               } elseif ($phpType == 'scalar') {
+                       if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
+                               $elementNS = " xmlns=\"$ns\"";
+                       } else {
+                               $elementNS = '';
+                       }
+                       if ($use == 'literal') {
+                               if ($forceType) {
+                                       return "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
+                               } else {
+                                       return "<$name$elementNS>$value</$name>";
+                               }
+                       } else {
+                               return "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
+                       }
+               }
+               $this->debug('returning: '.$this->varDump($xml));
+               return $xml;
+       }
+       
+       /**
+       * adds an XML Schema complex type to the WSDL types
+       *
+       * @param name
+       * @param typeClass (complexType|simpleType|attribute)
+       * @param phpType: currently supported are array and struct (php assoc array)
+       * @param compositor (all|sequence|choice)
+       * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
+       * @param elements = array ( name = array(name=>'',type=>'') )
+       * @param attrs = array(
+       *       array(
+       *               'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
+       *               "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
+       *       )
+       * )
+       * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
+       * @see xmlschema
+       * 
+       */
+       function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
+               if (count($elements) > 0) {
+               foreach($elements as $n => $e){
+                   // expand each element
+                   foreach ($e as $k => $v) {
+                           $k = strpos($k,':') ? $this->expandQname($k) : $k;
+                           $v = strpos($v,':') ? $this->expandQname($v) : $v;
+                           $ee[$k] = $v;
+                       }
+                       $eElements[$n] = $ee;
+               }
+               $elements = $eElements;
+               }
+               
+               if (count($attrs) > 0) {
+               foreach($attrs as $n => $a){
+                   // expand each attribute
+                   foreach ($a as $k => $v) {
+                           $k = strpos($k,':') ? $this->expandQname($k) : $k;
+                           $v = strpos($v,':') ? $this->expandQname($v) : $v;
+                           $aa[$k] = $v;
+                       }
+                       $eAttrs[$n] = $aa;
+               }
+               $attrs = $eAttrs;
+               }
+
+               $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
+               $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
+
+               $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
+               $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
+       }
+
+       /**
+       * adds an XML Schema simple type to the WSDL types
+       *
+       * @param name
+       * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
+       * @param typeClass (simpleType)
+       * @param phpType: (scalar)
+       * @see xmlschema
+       * 
+       */
+       function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar') {
+               $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
+
+               $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
+               $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType);
+       }
+
+       /**
+       * register a service with the server
+       * 
+       * @param string $methodname 
+       * @param string $in assoc array of input values: key = param name, value = param type
+       * @param string $out assoc array of output values: key = param name, value = param type
+       * @param string $namespace optional The namespace for the operation
+       * @param string $soapaction optional The soapaction for the operation
+       * @param string $style (rpc|document) optional The style for the operation
+       * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
+       * @param string $documentation optional The description to include in the WSDL
+       * @access public 
+       */
+       function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = ''){
+               if ($style == 'rpc' && $use == 'encoded') {
+                       $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
+               } else {
+                       $encodingStyle = '';
+               } 
+               // get binding
+               $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
+               array(
+               'name' => $name,
+               'binding' => $this->serviceName . 'Binding',
+               'endpoint' => $this->endpoint,
+               'soapAction' => $soapaction,
+               'style' => $style,
+               'input' => array(
+                       'use' => $use,
+                       'namespace' => $namespace,
+                       'encodingStyle' => $encodingStyle,
+                       'message' => $name . 'Request',
+                       'parts' => $in),
+               'output' => array(
+                       'use' => $use,
+                       'namespace' => $namespace,
+                       'encodingStyle' => $encodingStyle,
+                       'message' => $name . 'Response',
+                       'parts' => $out),
+               'namespace' => $namespace,
+               'transport' => 'http://schemas.xmlsoap.org/soap/http',
+               'documentation' => $documentation); 
+               // add portTypes
+               // add messages
+               if($in)
+               {
+                       foreach($in as $pName => $pType)
+                       {
+                               if(strpos($pType,':')) {
+                                       $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
+                               }
+                               $this->messages[$name.'Request'][$pName] = $pType;
+                       }
+               } else {
+            $this->messages[$name.'Request']= '0';
+        }
+               if($out)
+               {
+                       foreach($out as $pName => $pType)
+                       {
+                               if(strpos($pType,':')) {
+                                       $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
+                               }
+                               $this->messages[$name.'Response'][$pName] = $pType;
+                       }
+               } else {
+            $this->messages[$name.'Response']= '0';
+        }
+               return true;
+       } 
+}
+?><?php
+
+
+
+/**
+*
+* soap_parser class parses SOAP XML messages into native PHP values
+*
+* @author   Dietrich Ayala <dietrich@ganx4.com>
+* @version  $Id$
+* @access   public
+*/
+class soap_parser extends nusoap_base {
+
+       var $xml = '';
+       var $xml_encoding = '';
+       var $method = '';
+       var $root_struct = '';
+       var $root_struct_name = '';
+       var $root_struct_namespace = '';
+       var $root_header = '';
+    var $document = '';                        // incoming SOAP body (text)
+       // determines where in the message we are (envelope,header,body,method)
+       var $status = '';
+       var $position = 0;
+       var $depth = 0;
+       var $default_namespace = '';
+       var $namespaces = array();
+       var $message = array();
+    var $parent = '';
+       var $fault = false;
+       var $fault_code = '';
+       var $fault_str = '';
+       var $fault_detail = '';
+       var $depth_array = array();
+       var $debug_flag = true;
+       var $soapresponse = NULL;
+       var $responseHeaders = '';      // incoming SOAP headers (text)
+       var $body_position = 0;
+       // for multiref parsing:
+       // array of id => pos
+       var $ids = array();
+       // array of id => hrefs => pos
+       var $multirefs = array();
+       // toggle for auto-decoding element content
+       var $decode_utf8 = true;
+
+       /**
+       * constructor
+       *
+       * @param    string $xml SOAP message
+       * @param    string $encoding character encoding scheme of message
+       * @param    string $method
+       * @param    string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
+       * @access   public
+       */
+       function soap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
+               $this->xml = $xml;
+               $this->xml_encoding = $encoding;
+               $this->method = $method;
+               $this->decode_utf8 = $decode_utf8;
+
+               // Check whether content has been read.
+               if(!empty($xml)){
+                       $this->debug('Entering soap_parser(), length='.strlen($xml).', encoding='.$encoding);
+                       // Create an XML parser - why not xml_parser_create_ns?
+                       $this->parser = xml_parser_create($this->xml_encoding);
+                       // Set the options for parsing the XML data.
+                       //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
+                       xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
+                       xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
+                       // Set the object for the parser.
+                       xml_set_object($this->parser, $this);
+                       // Set the element handlers for the parser.
+                       xml_set_element_handler($this->parser, 'start_element','end_element');
+                       xml_set_character_data_handler($this->parser,'character_data');
+
+                       // Parse the XML file.
+                       if(!xml_parse($this->parser,$xml,true)){
+                           // Display an error message.
+                           $err = sprintf('XML error parsing SOAP payload on line %d: %s',
+                           xml_get_current_line_number($this->parser),
+                           xml_error_string(xml_get_error_code($this->parser)));
+                               $this->debug($err);
+                               $this->debug("XML payload:\n" . $xml);
+                               $this->setError($err);
+                       } else {
+                               $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
+                               // get final value
+                               $this->soapresponse = $this->message[$this->root_struct]['result'];
+                               // get header value: no, because this is documented as XML string
+//                             if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
+//                                     $this->responseHeaders = $this->message[$this->root_header]['result'];
+//                             }
+                               // resolve hrefs/ids
+                               if(sizeof($this->multirefs) > 0){
+                                       foreach($this->multirefs as $id => $hrefs){
+                                               $this->debug('resolving multirefs for id: '.$id);
+                                               $idVal = $this->buildVal($this->ids[$id]);
+                                               foreach($hrefs as $refPos => $ref){
+                                                       $this->debug('resolving href at pos '.$refPos);
+                                                       $this->multirefs[$id][$refPos] = $idVal;
+                                               }
+                                       }
+                               }
+                       }
+                       xml_parser_free($this->parser);
+               } else {
+                       $this->debug('xml was empty, didn\'t parse!');
+                       $this->setError('xml was empty, didn\'t parse!');
+               }
+       }
+
+       /**
+       * start-element handler
+       *
+       * @param    string $parser XML parser object
+       * @param    string $name element name
+       * @param    string $attrs associative array of attributes
+       * @access   private
+       */
+       function start_element($parser, $name, $attrs) {
+               // position in a total number of elements, starting from 0
+               // update class level pos
+               $pos = $this->position++;
+               // and set mine
+               $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
+               // depth = how many levels removed from root?
+               // set mine as current global depth and increment global depth value
+               $this->message[$pos]['depth'] = $this->depth++;
+
+               // else add self as child to whoever the current parent is
+               if($pos != 0){
+                       $this->message[$this->parent]['children'] .= '|'.$pos;
+               }
+               // set my parent
+               $this->message[$pos]['parent'] = $this->parent;
+               // set self as current parent
+               $this->parent = $pos;
+               // set self as current value for this depth
+               $this->depth_array[$this->depth] = $pos;
+               // get element prefix
+               if(strpos($name,':')){
+                       // get ns prefix
+                       $prefix = substr($name,0,strpos($name,':'));
+                       // get unqualified name
+                       $name = substr(strstr($name,':'),1);
+               }
+               // set status
+               if($name == 'Envelope'){
+                       $this->status = 'envelope';
+               } elseif($name == 'Header'){
+                       $this->root_header = $pos;
+                       $this->status = 'header';
+               } elseif($name == 'Body'){
+                       $this->status = 'body';
+                       $this->body_position = $pos;
+               // set method
+               } elseif($this->status == 'body' && $pos == ($this->body_position+1)){
+                       $this->status = 'method';
+                       $this->root_struct_name = $name;
+                       $this->root_struct = $pos;
+                       $this->message[$pos]['type'] = 'struct';
+                       $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
+               }
+               // set my status
+               $this->message[$pos]['status'] = $this->status;
+               // set name
+               $this->message[$pos]['name'] = htmlspecialchars($name);
+               // set attrs
+               $this->message[$pos]['attrs'] = $attrs;
+
+               // loop through atts, logging ns and type declarations
+        $attstr = '';
+               foreach($attrs as $key => $value){
+               $key_prefix = $this->getPrefix($key);
+                       $key_localpart = $this->getLocalPart($key);
+                       // if ns declarations, add to class level array of valid namespaces
+            if($key_prefix == 'xmlns'){
+                               if(ereg('^http://www.w3.org/[0-9]{4}/XMLSchema$',$value)){
+                                       $this->XMLSchemaVersion = $value;
+                                       $this->namespaces['xsd'] = $this->XMLSchemaVersion;
+                                       $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
+                               }
+                $this->namespaces[$key_localpart] = $value;
+                               // set method namespace
+                               if($name == $this->root_struct_name){
+                                       $this->methodNamespace = $value;
+                               }
+                       // if it's a type declaration, set type
+            } elseif($key_localpart == 'type'){
+               $value_prefix = $this->getPrefix($value);
+                $value_localpart = $this->getLocalPart($value);
+                               $this->message[$pos]['type'] = $value_localpart;
+                               $this->message[$pos]['typePrefix'] = $value_prefix;
+                if(isset($this->namespaces[$value_prefix])){
+                       $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
+                } else if(isset($attrs['xmlns:'.$value_prefix])) {
+                                       $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
+                }
+                               // should do something here with the namespace of specified type?
+                       } elseif($key_localpart == 'arrayType'){
+                               $this->message[$pos]['type'] = 'array';
+                               /* do arrayType ereg here
+                               [1]    arrayTypeValue    ::=    atype asize
+                               [2]    atype    ::=    QName rank*
+                               [3]    rank    ::=    '[' (',')* ']'
+                               [4]    asize    ::=    '[' length~ ']'
+                               [5]    length    ::=    nextDimension* Digit+
+                               [6]    nextDimension    ::=    Digit+ ','
+                               */
+                               $expr = '([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]';
+                               if(ereg($expr,$value,$regs)){
+                                       $this->message[$pos]['typePrefix'] = $regs[1];
+                                       $this->message[$pos]['arrayTypePrefix'] = $regs[1];
+                       if (isset($this->namespaces[$regs[1]])) {
+                               $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
+                       } else if (isset($attrs['xmlns:'.$regs[1]])) {
+                                               $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
+                       }
+                                       $this->message[$pos]['arrayType'] = $regs[2];
+                                       $this->message[$pos]['arraySize'] = $regs[3];
+                                       $this->message[$pos]['arrayCols'] = $regs[4];
+                               }
+                       }
+                       // log id
+                       if($key == 'id'){
+                               $this->ids[$value] = $pos;
+                       }
+                       // root
+                       if($key_localpart == 'root' && $value == 1){
+                               $this->status = 'method';
+                               $this->root_struct_name = $name;
+                               $this->root_struct = $pos;
+                               $this->debug("found root struct $this->root_struct_name, pos $pos");
+                       }
+            // for doclit
+            $attstr .= " $key=\"$value\"";
+               }
+        // get namespace - must be done after namespace atts are processed
+               if(isset($prefix)){
+                       $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
+                       $this->default_namespace = $this->namespaces[$prefix];
+               } else {
+                       $this->message[$pos]['namespace'] = $this->default_namespace;
+               }
+        if($this->status == 'header'){
+               if ($this->root_header != $pos) {
+                       $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
+               }
+        } elseif($this->root_struct_name != ''){
+               $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
+        }
+       }
+
+       /**
+       * end-element handler
+       *
+       * @param    string $parser XML parser object
+       * @param    string $name element name
+       * @access   private
+       */
+       function end_element($parser, $name) {
+               // position of current element is equal to the last value left in depth_array for my depth
+               $pos = $this->depth_array[$this->depth--];
+
+        // get element prefix
+               if(strpos($name,':')){
+                       // get ns prefix
+                       $prefix = substr($name,0,strpos($name,':'));
+                       // get unqualified name
+                       $name = substr(strstr($name,':'),1);
+               }
+               
+               // build to native type
+               if(isset($this->body_position) && $pos > $this->body_position){
+                       // deal w/ multirefs
+                       if(isset($this->message[$pos]['attrs']['href'])){
+                               // get id
+                               $id = substr($this->message[$pos]['attrs']['href'],1);
+                               // add placeholder to href array
+                               $this->multirefs[$id][$pos] = 'placeholder';
+                               // add set a reference to it as the result value
+                               $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
+            // build complex values
+                       } elseif($this->message[$pos]['children'] != ''){
+                       
+                               // if result has already been generated (struct/array
+                               if(!isset($this->message[$pos]['result'])){
+                                       $this->message[$pos]['result'] = $this->buildVal($pos);
+                               }
+                               
+                       // set value of simple type
+                       } else {
+               //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
+               if (isset($this->message[$pos]['type'])) {
+                                       $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
+                               } else {
+                                       $parent = $this->message[$pos]['parent'];
+                                       if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
+                                               $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
+                                       } else {
+                                               $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
+                                       }
+                               }
+
+                               /* add value to parent's result, if parent is struct/array
+                               $parent = $this->message[$pos]['parent'];
+                               if($this->message[$parent]['type'] != 'map'){
+                                       if(strtolower($this->message[$parent]['type']) == 'array'){
+                                               $this->message[$parent]['result'][] = $this->message[$pos]['result'];
+                                       } else {
+                                               $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
+                                       }
+                               }
+                               */
+                       }
+               }
+               
+        // for doclit
+        if($this->status == 'header'){
+               if ($this->root_header != $pos) {
+                       $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
+               }
+        } elseif($pos >= $this->root_struct){
+               $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
+        }
+               // switch status
+               if($pos == $this->root_struct){
+                       $this->status = 'body';
+                       $this->root_struct_namespace = $this->message[$pos]['namespace'];
+               } elseif($name == 'Body'){
+                       $this->status = 'envelope';
+                } elseif($name == 'Header'){
+                       $this->status = 'envelope';
+               } elseif($name == 'Envelope'){
+                       //
+               }
+               // set parent back to my parent
+               $this->parent = $this->message[$pos]['parent'];
+       }
+
+       /**
+       * element content handler
+       *
+       * @param    string $parser XML parser object
+       * @param    string $data element content
+       * @access   private
+       */
+       function character_data($parser, $data){
+               $pos = $this->depth_array[$this->depth];
+               if ($this->xml_encoding=='UTF-8'){
+                       // TODO: add an option to disable this for folks who want
+                       // raw UTF-8 that, e.g., might not map to iso-8859-1
+                       // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
+                       if($this->decode_utf8){
+                               $data = utf8_decode($data);
+                       }
+               }
+        $this->message[$pos]['cdata'] .= $data;
+        // for doclit
+        if($this->status == 'header'){
+               $this->responseHeaders .= $data;
+        } else {
+               $this->document .= $data;
+        }
+       }
+
+       /**
+       * get the parsed message
+       *
+       * @return       mixed
+       * @access   public
+       */
+       function get_response(){
+               return $this->soapresponse;
+       }
+
+       /**
+       * get the parsed headers
+       *
+       * @return       string XML or empty if no headers
+       * @access   public
+       */
+       function getHeaders(){
+           return $this->responseHeaders;
+       }
+
+       /**
+       * decodes entities
+       *
+       * @param    string $text string to translate
+       * @access   private
+       */
+       function decode_entities($text){
+               foreach($this->entities as $entity => $encoded){
+                       $text = str_replace($encoded,$entity,$text);
+               }
+               return $text;
+       }
+
+       /**
+       * decodes simple types into PHP variables
+       *
+       * @param    string $value value to decode
+       * @param    string $type XML type to decode
+       * @param    string $typens XML type namespace to decode
+       * @access   private
+       */
+       function decodeSimple($value, $type, $typens) {
+               // TODO: use the namespace!
+               if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
+                       return (string) $value;
+               }
+               if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
+                       return (int) $value;
+               }
+               if ($type == 'float' || $type == 'double' || $type == 'decimal') {
+                       return (double) $value;
+               }
+               if ($type == 'boolean') {
+                       if (strtolower($value) == 'false' || strtolower($value) == 'f') {
+                               return false;
+                       }
+                       return (boolean) $value;
+               }
+               if ($type == 'base64' || $type == 'base64Binary') {
+                       return base64_decode($value);
+               }
+               // obscure numeric types
+               if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
+                       || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
+                       || $type == 'unsignedInt'
+                       || $type == 'unsignedShort' || $type == 'unsignedByte') {
+                       return (int) $value;
+               }
+               // everything else
+               return (string) $value;
+       }
+
+       /**
+       * builds response structures for compound values (arrays/structs)
+       *
+       * @param    string $pos position in node tree
+       * @access   private
+       */
+       function buildVal($pos){
+               if(!isset($this->message[$pos]['type'])){
+                       $this->message[$pos]['type'] = '';
+               }
+               $this->debug('inside buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
+               // if there are children...
+               if($this->message[$pos]['children'] != ''){
+                       $children = explode('|',$this->message[$pos]['children']);
+                       array_shift($children); // knock off empty
+                       // md array
+                       if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
+               $r=0; // rowcount
+               $c=0; // colcount
+               foreach($children as $child_pos){
+                                       $this->debug("got an MD array element: $r, $c");
+                                       $params[$r][] = $this->message[$child_pos]['result'];
+                                   $c++;
+                                   if($c == $this->message[$pos]['arrayCols']){
+                                       $c = 0;
+                                               $r++;
+                                   }
+                }
+            // array
+                       } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
+                $this->debug('adding array '.$this->message[$pos]['name']);
+                foreach($children as $child_pos){
+                       $params[] = &$this->message[$child_pos]['result'];
+                }
+            // apache Map type: java hashtable
+            } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
+                foreach($children as $child_pos){
+                       $kv = explode("|",$this->message[$child_pos]['children']);
+                       $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
+                }
+            // generic compound type
+            //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
+                   } else {
+                       // Apache Vector type: treat as an array
+                               if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
+                                       $notstruct = 1;
+                               } else {
+                       // is array or struct?
+                       foreach($children as $child_pos){
+                               if(isset($keys) && isset($keys[$this->message[$child_pos]['name']])){
+                                       $notstruct = 1;
+                                       break;
+                               }
+                               $keys[$this->message[$child_pos]['name']] = 1;
+                       }
+                   }
+               //
+               foreach($children as $child_pos){
+                       if(isset($notstruct)){
+                               $params[] = &$this->message[$child_pos]['result'];
+                       } else {
+                               if (isset($params[$this->message[$child_pos]['name']])) {
+                                       // de-serialize repeated element name into an array
+                                       if (!is_array($params[$this->message[$child_pos]['name']])) {
+                                               $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
+                                       }
+                                       $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
+                               } else {
+                                               $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
+                                           }
+                       }
+                }
+                       }
+                       return is_array($params) ? $params : array();
+               } else {
+               $this->debug('no children');
+            if(strpos($this->message[$pos]['cdata'],'&')){
+                       return  strtr($this->message[$pos]['cdata'],array_flip($this->entities));
+            } else {
+               return $this->message[$pos]['cdata'];
+            }
+               }
+       }
+}
+
+
+
+?><?php
+
+
+
+/**
+*
+* nusoapclient higher level class for easy usage.
+*
+* usage:
+*
+* // instantiate client with server info
+* $soapclient = new nusoapclient( string path [ ,boolean wsdl] );
+*
+* // call method, get results
+* echo $soapclient->call( string methodname [ ,array parameters] );
+*
+* // bye bye client
+* unset($soapclient);
+*
+* @author   Dietrich Ayala <dietrich@ganx4.com>
+* @version  $Id$
+* @access   public
+*/
+class nusoapclient extends nusoap_base  {
+
+       var $username = '';
+       var $password = '';
+       var $requestHeaders = false;    // SOAP headers in request (text)
+       var $responseHeaders = '';              // SOAP headers from response (incomplete namespace resolution) (text)
+       var $document = '';                             // SOAP body response portion (incomplete namespace resolution) (text)
+       var $endpoint;
+       var $error_str = false;
+    var $proxyhost = '';
+    var $proxyport = '';
+       var $proxyusername = '';
+       var $proxypassword = '';
+    var $xml_encoding = '';                    // character set encoding of incoming (response) messages
+       var $http_encoding = false;
+       var $timeout = 0;
+       var $response_timeout = 30;
+       var $endpointType = '';
+       var $persistentConnection = false;
+       var $defaultRpcParams = false;
+       var $request = '';                              // HTTP request
+       var $response = '';                             // HTTP response
+       var $responseData = '';                 // SOAP payload of response
+       // toggles whether the parser decodes element content w/ utf8_decode()
+    var $decode_utf8 = true;
+       
+       /**
+       * fault related variables
+       *
+       * @var      fault
+       * @var      faultcode
+       * @var      faultstring
+       * @var      faultdetail
+       * @access   public
+       */
+       var $fault, $faultcode, $faultstring, $faultdetail;
+
+       /**
+       * constructor
+       *
+       * @param    mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
+       * @param    bool $wsdl optional, set to true if using WSDL
+       * @param        int $portName optional portName in WSDL document
+       * @param    string $proxyhost
+       * @param    string $proxyport
+       * @param        string $proxyusername
+       * @param        string $proxypassword
+       * @param        integer $timeout set the connection timeout
+       * @param        integer $response_timeout set the response timeout
+       * @access   public
+       */
+       function nusoapclient($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30){
+               $this->endpoint = $endpoint;
+               $this->proxyhost = $proxyhost;
+               $this->proxyport = $proxyport;
+               $this->proxyusername = $proxyusername;
+               $this->proxypassword = $proxypassword;
+               $this->timeout = $timeout;
+               $this->response_timeout = $response_timeout;
+
+               // make values
+               if($wsdl){
+                       $this->endpointType = 'wsdl';
+                       if (is_object($endpoint) && is_a($endpoint, 'wsdl')) {
+                               $this->wsdl = $endpoint;
+                               $this->endpoint = $this->wsdl->wsdl;
+                               $this->wsdlFile = $this->endpoint;
+                               $this->debug('existing wsdl instance created from ' . $this->endpoint);
+                       } else {
+                               $this->wsdlFile = $this->endpoint;
+                               
+                               // instantiate wsdl object and parse wsdl file
+                               $this->debug('instantiating wsdl class with doc: '.$endpoint);
+                               $this->wsdl =& new wsdl($this->wsdlFile,$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout);
+                       }
+                       $this->debug("wsdl debug...\n".$this->wsdl->debug_str);
+                       $this->wsdl->debug_str = '';
+                       // catch errors
+                       if($errstr = $this->wsdl->getError()){
+                               $this->debug('got wsdl error: '.$errstr);
+                               $this->setError('wsdl error: '.$errstr);
+                       } elseif($this->operations = $this->wsdl->getOperations()){
+                               $this->debug( 'got '.count($this->operations).' operations from wsdl '.$this->wsdlFile);
+                       } else {
+                               $this->debug( 'getOperations returned false');
+                               $this->setError('no operations defined in the WSDL document!');
+                       }
+               }
+       }
+
+       /**
+       * calls method, returns PHP native type
+       *
+       * @param    string $method SOAP server URL or path
+       * @param    array $params For RPC, array of parameters, can be associative or not.
+       *                         For literal, either the stringized XML for the body,
+       *                         or an array of parameters like the RPC case.  The
+       *                         $rpcParams parameter controls this treatment, or
+       *                         the $defaultRpcParams field if $rpcParams is not
+       *                         specified.  IMPORTANT: most services with literal
+       *                         parameters have document style, in which case there
+       *                         is really one parameter, the root of the fragment
+       *                         used in the call, which encloses what programmers
+       *                         normally think of parameters.  A parameter array
+       *                         *must* include the wrapper.
+       * @param        string $namespace optional method namespace (WSDL can override)
+       * @param        string $soapAction optional SOAPAction value (WSDL can override)
+       * @param        boolean $headers optional array of soapval objects for headers
+       * @param        boolean $rpcParams optional treat params as RPC for use="literal"
+       *                   This can be used on a per-call basis to overrider defaultRpcParams.
+       * @param        string  $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
+       * @param        string  $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
+       * @return       mixed
+       * @access   public
+       */
+       function call($operation,$params=array(),$namespace='',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
+               $this->operation = $operation;
+               $this->fault = false;
+               $this->error_str = '';
+               $this->request = '';
+               $this->response = '';
+               $this->responseData = '';
+               $this->faultstring = '';
+               $this->faultcode = '';
+               $this->opData = array();
+               
+               $this->debug("call: $operation, $params, $namespace, $soapAction, $headers, $rpcParams");
+               $this->debug("endpointType: $this->endpointType");
+               if ($headers) {
+                       $this->requestHeaders = $headers;
+               }
+               // if wsdl, get operation data and process parameters
+               if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
+
+                       $this->opData = $opData;
+                       foreach($opData as $key => $value){
+                               $this->debug("$key -> $value");
+                       }
+                       if (isset($opData['soapAction'])) {
+                               $soapAction = $opData['soapAction'];
+                       }
+                       $this->endpoint = $opData['endpoint'];
+                       $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] :     ($namespace != '' ? $namespace : 'http://testuri.org');
+                       $style = $opData['style'];
+                       // add ns to ns array
+                       if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
+                               $this->wsdl->namespaces['nu'] = $namespace;
+            }
+                       // serialize payload
+                       
+                       if($opData['input']['use'] == 'literal') {
+                               if (is_null($rpcParams)) {
+                                       $rpcParams = $this->defaultRpcParams;
+                               }
+                               if ($rpcParams) {
+                                       $this->debug("serializing literal params for operation $operation");
+                                       $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params);
+                                       $defaultNamespace = $this->wsdl->wsdl_info['targetNamespace'];
+                                       //$this->debug($this->varDump($params));
+                               } else {
+                                       // TODO: what?  We want to treat $params as a scalar....
+                                       $this->debug("serializing literal document for operation $operation");
+                                       //$payload = is_array($params) ? array_shift($params) : $params;
+                                       $payload = $this->wsdl->serializeParameters($operation,'input',$params);
+                               }
+                       } else {
+                               $this->debug("serializing encoded params for operation $operation");
+                       
+                               // Partial fix for multiple encoding styles in the same function call
+                               $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
+                               $payload = "<".$this->wsdl->getPrefixFromNamespace($namespace).":$operation";
+                               if(isset($opData['output']['encodingStyle']) && $encodingStyle != $opData['output']['encodingStyle']) {
+                                       $payload .= (' SOAP-ENV:encodingStyle="' . $opData['output']['encodingStyle'] . '"');
+                               }                                                                               
+                               $payload .= ('>' . $this->wsdl->serializeRPCParameters($operation,'input',$params).
+                                                        '</'.$this->wsdl->getPrefixFromNamespace($namespace).":$operation>");
+                       }
+                       $this->debug('payload size: '.strlen($payload));
+                       // serialize envelope
+                       $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$this->wsdl->usedNamespaces,$style);
+                       $this->debug("wsdl debug: \n".$this->wsdl->debug_str);
+                       $this->wsdl->debug_str = '';
+                       if ($errstr = $this->wsdl->getError()) {
+                               $this->debug('got wsdl error: '.$errstr);
+                               $this->setError('wsdl error: '.$errstr);
+                               return false;
+                       }
+               } elseif($this->endpointType == 'wsdl') {
+                       $this->setError( 'operation '.$operation.' not present.');
+                       $this->debug("operation '$operation' not present.");
+                       $this->debug("wsdl debug: \n".$this->wsdl->debug_str);
+                       $this->wsdl->debug_str = '';
+                       return false;
+               // no wsdl
+               } else {
+                       // make message
+            if($namespace == ''){
+               $namespace = 'http://testuri.org';
+                $this->wsdl->namespaces['ns1'] = $namespace;
+            }
+                       // serialize envelope
+                       // note: 
+                       $payload = '';
+                       if(is_array($params)){
+                               foreach($params as $k => $v){
+                                       $payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
+                               }
+                       }
+                       $payload = "<ns1:$operation xmlns:ns1=\"$namespace\">".$payload."</ns1:$operation>";
+                       $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,array(),$style,$use);
+               }
+               $this->debug("endpoint: $this->endpoint, soapAction: $soapAction, namespace: $namespace, style: $style");
+               // send
+               $this->debug('sending msg (len: '.strlen($soapmsg).") w/ soapaction '$soapAction'...");
+               $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
+               if($errstr = $this->getError()){
+                       $this->debug('Error: '.$errstr);
+                       return false;
+               } else {
+                       $this->return = $return;
+                       $this->debug('sent message successfully and got a(n) '.gettype($return).' back');
+                       
+                       // fault?
+                       if(is_array($return) && isset($return['faultcode'])){
+                               $this->debug('got fault');
+                               $this->setError($return['faultcode'].': '.$return['faultstring']);
+                               $this->fault = true;
+                               foreach($return as $k => $v){
+                                       $this->$k = $v;
+                                       $this->debug("$k = $v<br>");
+                               }
+                               return $return;
+                       } else {
+                               // array of return values
+                               if(is_array($return)){
+                                       // multiple 'out' parameters
+                                       if(sizeof($return) > 1){
+                                               return $return;
+                                       }
+                                       // single 'out' parameter
+                                       return array_shift($return);
+                               // nothing returned (ie, echoVoid)
+                               } else {
+                                       return "";
+                               }
+                       }
+               }
+       }
+
+       /**
+       * get available data pertaining to an operation
+       *
+       * @param    string $operation operation name
+       * @return       array array of data pertaining to the operation
+       * @access   public
+       */
+       function getOperationData($operation){
+               if(isset($this->operations[$operation])){
+                       return $this->operations[$operation];
+               }
+               $this->debug("No data for operation: $operation");
+       }
+
+    /**
+    * send the SOAP message
+    *
+    * Note: if the operation has multiple return values
+    * the return value of this method will be an array
+    * of those values.
+    *
+       * @param    string $msg a SOAPx4 soapmsg object
+       * @param    string $soapaction SOAPAction value
+       * @param    integer $timeout set connection timeout in seconds
+       * @param        integer $response_timeout set response timeout in seconds
+       * @return       mixed native PHP types.
+       * @access   private
+       */
+       function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
+               // detect transport
+               switch(true){
+                       // http(s)
+                       case ereg('^http',$this->endpoint):
+                               $this->debug('transporting via HTTP');
+                               if($this->persistentConnection == true && is_object($this->persistentConnection)){
+                                       $http =& $this->persistentConnection;
+                               } else {
+                                       $http = new soap_transport_http($this->endpoint);
+                                       if ($this->persistentConnection) {
+                                               $http->usePersistentConnection();
+                                       }
+                               }
+                               $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
+                               $http->setSOAPAction($soapaction);
+                               if($this->proxyhost && $this->proxyport){
+                                       $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
+                               }
+                if($this->username != '' && $this->password != '') {
+                                       $http->setCredentials($this->username,$this->password);
+                               }
+                               if($this->http_encoding != ''){
+                                       $http->setEncoding($this->http_encoding);
+                               }
+                               $this->debug('sending message, length: '.strlen($msg));
+                               if(ereg('^http:',$this->endpoint)){
+                               //if(strpos($this->endpoint,'http:')){
+                                       $this->responseData = $http->send($msg,$timeout,$response_timeout);
+                               } elseif(ereg('^https',$this->endpoint)){
+                               //} elseif(strpos($this->endpoint,'https:')){
+                                       //if(phpversion() == '4.3.0-dev'){
+                                               //$response = $http->send($msg,$timeout,$response_timeout);
+                               //$this->request = $http->outgoing_payload;
+                                               //$this->response = $http->incoming_payload;
+                                       //} else
+                                       if (extension_loaded('curl')) {
+                                               $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout);
+                                       } else {
+                                               $this->setError('CURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
+                                       }                                                               
+                               } else {
+                                       $this->setError('no http/s in endpoint url');
+                               }
+                               $this->request = $http->outgoing_payload;
+                               $this->response = $http->incoming_payload;
+                               $this->debug("transport debug data...\n".$http->debug_str);
+                               
+                               // save transport object if using persistent connections
+                               if ($this->persistentConnection) {
+                                       $http->debug_str = '';
+                                       if (!is_object($this->persistentConnection)) {
+                                               $this->persistentConnection = $http;
+                                       }
+                               }
+                               
+                               if($err = $http->getError()){
+                                       $this->setError('HTTP Error: '.$err);
+                                       return false;
+                               } elseif($this->getError()){
+                                       return false;
+                               } else {
+                                       $this->debug('got response, length: '. strlen($this->responseData).' type: '.$http->incoming_headers['content-type']);
+                                       return $this->parseResponse($http->incoming_headers, $this->responseData);
+                               }
+                       break;
+                       default:
+                               $this->setError('no transport found, or selected transport is not yet supported!');
+                       return false;
+                       break;
+               }
+       }
+
+       /**
+       * processes SOAP message returned from server
+       *
+       * @param        array   $headers        The HTTP headers
+       * @param        string  $data           unprocessed response data from server
+       * @return       mixed   value of the message, decoded into a PHP type
+       * @access   protected
+       */
+    function parseResponse($headers, $data) {
+               $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
+               if (!strstr($headers['content-type'], 'text/xml')) {
+                       $this->setError('Response not of type text/xml');
+                       return false;
+               }
+               if (strpos($headers['content-type'], '=')) {
+                       $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
+                       $this->debug('Got response encoding: ' . $enc);
+                       if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
+                               $this->xml_encoding = strtoupper($enc);
+                       } else {
+                               $this->xml_encoding = 'US-ASCII';
+                       }
+               } else {
+                       // should be US-ASCII, but for XML, let's be pragmatic and admit UTF-8 is most common
+                       $this->xml_encoding = 'UTF-8';
+               }
+               $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating soap_parser');
+               $parser = new soap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
+               // add parser debug data to our debug
+               $this->debug($parser->debug_str);
+               // if parse errors
+               if($errstr = $parser->getError()){
+                       $this->setError( $errstr);
+                       // destroy the parser object
+                       unset($parser);
+                       return false;
+               } else {
+                       // get SOAP headers
+                       $this->responseHeaders = $parser->getHeaders();
+                       // get decoded message
+                       $return = $parser->get_response();
+            // add document for doclit support
+            $this->document = $parser->document;
+                       // destroy the parser object
+                       unset($parser);
+                       // return decode message
+                       return $return;
+               }
+        }
+
+       /**
+       * set the SOAP headers
+       *
+       * @param        $headers string XML
+       * @access   public
+       */
+       function setHeaders($headers){
+               $this->requestHeaders = $headers;
+       }
+
+       /**
+       * get the response headers
+       *
+       * @return       mixed object SOAPx4 soapval object or empty if no headers
+       * @access   public
+       */
+       function getHeaders(){
+           if($this->responseHeaders != '') {
+                       return $this->responseHeaders;
+           }
+       }
+
+       /**
+       * set proxy info here
+       *
+       * @param    string $proxyhost
+       * @param    string $proxyport
+       * @param        string $proxyusername
+       * @param        string $proxypassword
+       * @access   public
+       */
+       function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
+               $this->proxyhost = $proxyhost;
+               $this->proxyport = $proxyport;
+               $this->proxyusername = $proxyusername;
+               $this->proxypassword = $proxypassword;
+       }
+
+       /**
+       * if authenticating, set user credentials here
+       *
+       * @param    string $username
+       * @param    string $password
+       * @access   public
+       */
+       function setCredentials($username, $password) {
+               $this->username = $username;
+               $this->password = $password;
+       }
+       
+       /**
+       * use HTTP encoding
+       *
+       * @param    string $enc
+       * @access   public
+       */
+       function setHTTPEncoding($enc='gzip, deflate'){
+               $this->http_encoding = $enc;
+       }
+       
+       /**
+       * use HTTP persistent connections if possible
+       *
+       * @access   public
+       */
+       function useHTTPPersistentConnection(){
+               $this->persistentConnection = true;
+       }
+       
+       /**
+       * gets the default RPC parameter setting.
+       * If true, default is that call params are like RPC even for document style.
+       * Each call() can override this value.
+       *
+       * @access public
+       */
+       function getDefaultRpcParams() {
+               return $this->defaultRpcParams;
+       }
+
+       /**
+       * sets the default RPC parameter setting.
+       * If true, default is that call params are like RPC even for document style
+       * Each call() can override this value.
+       *
+       * @param    boolean $rpcParams
+       * @access public
+       */
+       function setDefaultRpcParams($rpcParams) {
+               $this->defaultRpcParams = $rpcParams;
+       }
+       
+       /**
+       * dynamically creates proxy class, allowing user to directly call methods from wsdl
+       *
+       * @return   object soap_proxy object
+       * @access   public
+       */
+       function getProxy(){
+               $evalStr = '';
+               foreach($this->operations as $operation => $opData){
+                       if($operation != ''){
+                               // create param string
+                               $paramStr = '';
+                               if(sizeof($opData['input']['parts']) > 0){
+                                       foreach($opData['input']['parts'] as $name => $type){
+                                               $paramStr .= "\$$name,";
+                                       }
+                                       $paramStr = substr($paramStr,0,strlen($paramStr)-1);
+                               }
+                               $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
+                               $evalStr .= "function $operation ($paramStr){
+                                       // load params into array
+                                       \$params = array($paramStr);
+                                       return \$this->call('$operation',\$params,'".$opData['namespace']."','".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
+                               }";
+                               unset($paramStr);
+                       }
+               }
+               $r = rand();
+               $evalStr = 'class soap_proxy_'.$r.' extends nusoapclient {
+                               '.$evalStr.'
+                       }';
+               //print "proxy class:<pre>$evalStr</pre>";
+               // eval the class
+               eval($evalStr);
+               // instantiate proxy object
+               eval("\$proxy = new soap_proxy_$r('');");
+               // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
+               $proxy->endpointType = 'wsdl';
+               $proxy->wsdlFile = $this->wsdlFile;
+               $proxy->wsdl = $this->wsdl;
+               $proxy->operations = $this->operations;
+               $proxy->defaultRpcParams = $this->defaultRpcParams;
+               // transfer other state
+               $proxy->username = $this->username;
+               $proxy->password = $this->password;
+               $proxy->proxyhost = $this->proxyhost;
+               $proxy->proxyport = $this->proxyport;
+               $proxy->proxyusername = $this->proxyusername;
+               $proxy->proxypassword = $this->proxypassword;
+               $proxy->timeout = $this->timeout;
+               $proxy->response_timeout = $this->response_timeout;
+               $proxy->http_encoding = $this->http_encoding;
+               $proxy->persistentConnection = $this->persistentConnection;
+               return $proxy;
+       }
+
+       /**
+       * gets the HTTP body for the current request.
+       *
+       * @param string $soapmsg The SOAP payload
+       * @return string The HTTP body, which includes the SOAP payload
+       * @access protected
+       */
+       function getHTTPBody($soapmsg) {
+               return $soapmsg;
+       }
+       
+       /**
+       * gets the HTTP content type for the current request.
+       *
+       * Note: getHTTPBody must be called before this.
+       *
+       * @return string the HTTP content type for the current request.
+       * @access protected
+       */
+       function getHTTPContentType() {
+               return 'text/xml';
+       }
+       
+       /**
+       * gets the HTTP content type charset for the current request.
+       * returns false for non-text content types.
+       *
+       * Note: getHTTPBody must be called before this.
+       *
+       * @return string the HTTP content type charset for the current request.
+       * @access protected
+       */
+       function getHTTPContentTypeCharset() {
+               return $this->soap_defencoding;
+       }
+
+       /*
+       * whether or not parser should decode utf8 element content
+    *
+    * @return   always returns true
+    * @access   public
+    */
+    function decodeUTF8($bool){
+               $this->decode_utf8 = $bool;
+               return true;
+    }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/pclzip.lib.php b/include/classes/pclzip.lib.php
new file mode 100644 (file)
index 0000000..d76b235
--- /dev/null
@@ -0,0 +1,5207 @@
+<?php
+// --------------------------------------------------------------------------------
+// PhpConcept Library - Zip Module 2.3
+// --------------------------------------------------------------------------------
+// License GNU/LGPL - Vincent Blavet - November 2004
+// http://www.phpconcept.net
+// --------------------------------------------------------------------------------
+//
+// Presentation :
+//   PclZip is a PHP library that manage ZIP archives.
+//   So far tests show that archives generated by PclZip are readable by
+//   WinZip application and other tools.
+//
+// Description :
+//   See readme.txt and http://www.phpconcept.net
+//
+// Warning :
+//   This library and the associated files are non commercial, non professional
+//   work.
+//   It should not have unexpected results. However if any damage is caused by
+//   this software the author can not be responsible.
+//   The use of this software is at the risk of the user.
+//
+// --------------------------------------------------------------------------------
+// $Id$
+// --------------------------------------------------------------------------------
+
+  // ----- Constants
+  define( 'PCLZIP_READ_BLOCK_SIZE', 2048 );
+  
+  // ----- File list separator
+  // In version 1.x of PclZip, the separator for file list is a space
+  // (which is not a very smart choice, specifically for windows paths !).
+  // A better separator should be a comma (,). This constant gives you the
+  // abilty to change that.
+  // However notice that changing this value, may have impact on existing
+  // scripts, using space separated filenames.
+  // Recommanded values for compatibility with older versions :
+  //define( 'PCLZIP_SEPARATOR', ' ' );
+  // Recommanded values for smart separation of filenames.
+  define( 'PCLZIP_SEPARATOR', ',' );
+
+  // ----- Error configuration
+  // 0 : PclZip Class integrated error handling
+  // 1 : PclError external library error handling. By enabling this
+  //     you must ensure that you have included PclError library.
+  // [2,...] : reserved for futur use
+  define( 'PCLZIP_ERROR_EXTERNAL', 0 );
+
+  // ----- Optional static temporary directory
+  //       By default temporary files are generated in the script current
+  //       path.
+  //       If defined :
+  //       - MUST BE terminated by a '/'.
+  //       - MUST be a valid, already created directory
+  //       Samples :
+  // define( 'PCLZIP_TEMPORARY_DIR', '/temp/' );
+  // define( 'PCLZIP_TEMPORARY_DIR', 'C:/Temp/' );
+  define( 'PCLZIP_TEMPORARY_DIR', '' );
+
+// --------------------------------------------------------------------------------
+// ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED *****
+// --------------------------------------------------------------------------------
+
+  // ----- Global variables
+  $g_pclzip_version = "2.3";
+
+  // ----- Error codes
+  //   -1 : Unable to open file in binary write mode
+  //   -2 : Unable to open file in binary read mode
+  //   -3 : Invalid parameters
+  //   -4 : File does not exist
+  //   -5 : Filename is too long (max. 255)
+  //   -6 : Not a valid zip file
+  //   -7 : Invalid extracted file size
+  //   -8 : Unable to create directory
+  //   -9 : Invalid archive extension
+  //  -10 : Invalid archive format
+  //  -11 : Unable to delete file (unlink)
+  //  -12 : Unable to rename file (rename)
+  //  -13 : Invalid header checksum
+  //  -14 : Invalid archive size
+  define( 'PCLZIP_ERR_USER_ABORTED', 2 );
+  define( 'PCLZIP_ERR_NO_ERROR', 0 );
+  define( 'PCLZIP_ERR_WRITE_OPEN_FAIL', -1 );
+  define( 'PCLZIP_ERR_READ_OPEN_FAIL', -2 );
+  define( 'PCLZIP_ERR_INVALID_PARAMETER', -3 );
+  define( 'PCLZIP_ERR_MISSING_FILE', -4 );
+  define( 'PCLZIP_ERR_FILENAME_TOO_LONG', -5 );
+  define( 'PCLZIP_ERR_INVALID_ZIP', -6 );
+  define( 'PCLZIP_ERR_BAD_EXTRACTED_FILE', -7 );
+  define( 'PCLZIP_ERR_DIR_CREATE_FAIL', -8 );
+  define( 'PCLZIP_ERR_BAD_EXTENSION', -9 );
+  define( 'PCLZIP_ERR_BAD_FORMAT', -10 );
+  define( 'PCLZIP_ERR_DELETE_FILE_FAIL', -11 );
+  define( 'PCLZIP_ERR_RENAME_FILE_FAIL', -12 );
+  define( 'PCLZIP_ERR_BAD_CHECKSUM', -13 );
+  define( 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', -14 );
+  define( 'PCLZIP_ERR_MISSING_OPTION_VALUE', -15 );
+  define( 'PCLZIP_ERR_INVALID_OPTION_VALUE', -16 );
+  define( 'PCLZIP_ERR_ALREADY_A_DIRECTORY', -17 );
+  define( 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', -18 );
+  define( 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION', -19 );
+
+  // ----- Options values
+  define( 'PCLZIP_OPT_PATH', 77001 );
+  define( 'PCLZIP_OPT_ADD_PATH', 77002 );
+  define( 'PCLZIP_OPT_REMOVE_PATH', 77003 );
+  define( 'PCLZIP_OPT_REMOVE_ALL_PATH', 77004 );
+  define( 'PCLZIP_OPT_SET_CHMOD', 77005 );
+  define( 'PCLZIP_OPT_EXTRACT_AS_STRING', 77006 );
+  define( 'PCLZIP_OPT_NO_COMPRESSION', 77007 );
+  define( 'PCLZIP_OPT_BY_NAME', 77008 );
+  define( 'PCLZIP_OPT_BY_INDEX', 77009 );
+  define( 'PCLZIP_OPT_BY_EREG', 77010 );
+  define( 'PCLZIP_OPT_BY_PREG', 77011 );
+  define( 'PCLZIP_OPT_COMMENT', 77012 );
+  define( 'PCLZIP_OPT_ADD_COMMENT', 77013 );
+  define( 'PCLZIP_OPT_PREPEND_COMMENT', 77014 );
+  define( 'PCLZIP_OPT_EXTRACT_IN_OUTPUT', 77015 );
+  define( 'PCLZIP_OPT_REPLACE_NEWER', 77016 );
+  define( 'PCLZIP_OPT_STOP_ON_ERROR', 77017 );
+  // Having big trouble with crypt. Need to multiply 2 long int
+  // which is not correctly supported by PHP ...
+  //define( 'PCLZIP_OPT_CRYPT', 77018 );
+
+  // ----- Call backs values
+  define( 'PCLZIP_CB_PRE_EXTRACT', 78001 );
+  define( 'PCLZIP_CB_POST_EXTRACT', 78002 );
+  define( 'PCLZIP_CB_PRE_ADD', 78003 );
+  define( 'PCLZIP_CB_POST_ADD', 78004 );
+  /* For futur use
+  define( 'PCLZIP_CB_PRE_LIST', 78005 );
+  define( 'PCLZIP_CB_POST_LIST', 78006 );
+  define( 'PCLZIP_CB_PRE_DELETE', 78007 );
+  define( 'PCLZIP_CB_POST_DELETE', 78008 );
+  */
+
+  // --------------------------------------------------------------------------------
+  // Class : PclZip
+  // Description :
+  //   PclZip is the class that represent a Zip archive.
+  //   The public methods allow the manipulation of the archive.
+  // Attributes :
+  //   Attributes must not be accessed directly.
+  // Methods :
+  //   PclZip() : Object creator
+  //   create() : Creates the Zip archive
+  //   listContent() : List the content of the Zip archive
+  //   extract() : Extract the content of the archive
+  //   properties() : List the properties of the archive
+  // --------------------------------------------------------------------------------
+   class PclZip
+  {
+    // ----- Filename of the zip file
+    var $zipname = '';
+
+    // ----- File descriptor of the zip file
+    var $zip_fd = 0;
+
+    // ----- Internal error handling
+    var $error_code = 1;
+    var $error_string = '';
+
+  // --------------------------------------------------------------------------------
+  // Function : PclZip()
+  // Description :
+  //   Creates a PclZip object and set the name of the associated Zip archive
+  //   filename.
+  //   Note that no real action is taken, if the archive does not exist it is not
+  //   created. Use create() for that.
+  // --------------------------------------------------------------------------------
+  function PclZip($p_zipname)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::PclZip', "zipname=$p_zipname");
+
+    // ----- Tests the zlib
+    if (!function_exists('gzopen'))
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 1, "zlib extension seems to be missing");
+      die('Abort '.basename(__FILE__).' : Missing zlib extensions');
+    }
+
+    // ----- Set the attributes
+    $this->zipname = $p_zipname;
+    $this->zip_fd = 0;
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 1);
+    return;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function :
+  //   create($p_filelist, $p_add_dir="", $p_remove_dir="")
+  //   create($p_filelist, $p_option, $p_option_value, ...)
+  // Description :
+  //   This method supports two different synopsis. The first one is historical.
+  //   This method creates a Zip Archive. The Zip file is created in the
+  //   filesystem. The files and directories indicated in $p_filelist
+  //   are added in the archive. See the parameters description for the
+  //   supported format of $p_filelist.
+  //   When a directory is in the list, the directory and its content is added
+  //   in the archive.
+  //   In this synopsis, the function takes an optional variable list of
+  //   options. See bellow the supported options.
+  // Parameters :
+  //   $p_filelist : An array containing file or directory names, or
+  //                 a string containing one filename or one directory name, or
+  //                 a string containing a list of filenames and/or directory
+  //                 names separated by spaces.
+  //   $p_add_dir : A path to add before the real path of the archived file,
+  //                in order to have it memorized in the archive.
+  //   $p_remove_dir : A path to remove from the real path of the file to archive,
+  //                   in order to have a shorter path memorized in the archive.
+  //                   When $p_add_dir and $p_remove_dir are set, $p_remove_dir
+  //                   is removed first, before $p_add_dir is added.
+  // Options :
+  //   PCLZIP_OPT_ADD_PATH :
+  //   PCLZIP_OPT_REMOVE_PATH :
+  //   PCLZIP_OPT_REMOVE_ALL_PATH :
+  //   PCLZIP_OPT_COMMENT :
+  //   PCLZIP_CB_PRE_ADD :
+  //   PCLZIP_CB_POST_ADD :
+  // Return Values :
+  //   0 on failure,
+  //   The list of the added files, with a status of the add action.
+  //   (see PclZip::listContent() for list entry format)
+  // --------------------------------------------------------------------------------
+//  function create($p_filelist, $p_add_dir="", $p_remove_dir="")
+  function create($p_filelist /*, options */)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::create', "filelist='$p_filelist', ...");
+    $v_result=1;
+
+    // ----- Reset the error handler
+    $this->privErrorReset();
+
+    // ----- Set default values
+    $v_options = array();
+    $v_add_path = "";
+    $v_remove_path = "";
+    $v_remove_all_path = false;
+    $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
+
+    // ----- Look for variable options arguments
+    $v_size = func_num_args();
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
+
+    // ----- Look for arguments
+    if ($v_size > 1) {
+      // ----- Get the arguments
+      $v_arg_list = &func_get_args();
+
+      // ----- Remove form the options list the first argument
+      array_shift($v_arg_list);
+      $v_size--;
+
+      // ----- Look for first arg
+      if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options detected");
+
+        // ----- Parse the options
+        $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
+                                            array (PCLZIP_OPT_REMOVE_PATH => 'optional',
+                                                   PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
+                                                   PCLZIP_OPT_ADD_PATH => 'optional',
+                                                   PCLZIP_CB_PRE_ADD => 'optional',
+                                                   PCLZIP_CB_POST_ADD => 'optional',
+                                                   PCLZIP_OPT_NO_COMPRESSION => 'optional',
+                                                   PCLZIP_OPT_COMMENT => 'optional'
+                                                   //, PCLZIP_OPT_CRYPT => 'optional'
+                                                                                                  ));
+        if ($v_result != 1) {
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+          return 0;
+        }
+
+        // ----- Set the arguments
+        if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
+          $v_add_path = $v_options[PCLZIP_OPT_ADD_PATH];
+        }
+        if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
+          $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
+        }
+        if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
+          $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
+        }
+      }
+
+      // ----- Look for 2 args
+      // Here we need to support the first historic synopsis of the
+      // method.
+      else {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
+
+        // ----- Get the first argument
+        $v_add_path = $v_arg_list[0];
+
+        // ----- Look for the optional second argument
+        if ($v_size == 2) {
+          $v_remove_path = $v_arg_list[1];
+        }
+        else if ($v_size > 2) {
+          // ----- Error log
+          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
+                                      "Invalid number / type of arguments");
+
+          // ----- Return
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+          return 0;
+        }
+      }
+    }
+
+    // ----- Trace
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "add_path='$v_add_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_all_path?'true':'false')."'");
+
+    // ----- Look if the $p_filelist is really an array
+    $p_result_list = array();
+    if (is_array($p_filelist))
+    {
+      // ----- Call the create fct
+      $v_result = $this->privCreate($p_filelist, $p_result_list, $v_add_path, $v_remove_path, $v_remove_all_path, $v_options);
+    }
+
+    // ----- Look if the $p_filelist is a string
+    else if (is_string($p_filelist))
+    {
+      // ----- Create a list with the elements from the string
+      $v_list = explode(PCLZIP_SEPARATOR, $p_filelist);
+
+      // ----- Call the create fct
+      $v_result = $this->privCreate($v_list, $p_result_list, $v_add_path, $v_remove_path, $v_remove_all_path, $v_options);
+    }
+
+    // ----- Invalid variable
+    else
+    {
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
+      $v_result = PCLZIP_ERR_INVALID_PARAMETER;
+    }
+
+    if ($v_result != 1)
+    {
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+      return 0;
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_result_list);
+    return $p_result_list;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function :
+  //   add($p_filelist, $p_add_dir="", $p_remove_dir="")
+  //   add($p_filelist, $p_option, $p_option_value, ...)
+  // Description :
+  //   This method supports two synopsis. The first one is historical.
+  //   This methods add the list of files in an existing archive.
+  //   If a file with the same name already exists, it is added at the end of the
+  //   archive, the first one is still present.
+  //   If the archive does not exist, it is created.
+  // Parameters :
+  //   $p_filelist : An array containing file or directory names, or
+  //                 a string containing one filename or one directory name, or
+  //                 a string containing a list of filenames and/or directory
+  //                 names separated by spaces.
+  //   $p_add_dir : A path to add before the real path of the archived file,
+  //                in order to have it memorized in the archive.
+  //   $p_remove_dir : A path to remove from the real path of the file to archive,
+  //                   in order to have a shorter path memorized in the archive.
+  //                   When $p_add_dir and $p_remove_dir are set, $p_remove_dir
+  //                   is removed first, before $p_add_dir is added.
+  // Options :
+  //   PCLZIP_OPT_ADD_PATH :
+  //   PCLZIP_OPT_REMOVE_PATH :
+  //   PCLZIP_OPT_REMOVE_ALL_PATH :
+  //   PCLZIP_OPT_COMMENT :
+  //   PCLZIP_OPT_ADD_COMMENT :
+  //   PCLZIP_OPT_PREPEND_COMMENT :
+  //   PCLZIP_CB_PRE_ADD :
+  //   PCLZIP_CB_POST_ADD :
+  // Return Values :
+  //   0 on failure,
+  //   The list of the added files, with a status of the add action.
+  //   (see PclZip::listContent() for list entry format)
+  // --------------------------------------------------------------------------------
+//  function add($p_filelist, $p_add_dir="", $p_remove_dir="")
+  function add($p_filelist /* options */)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::add', "filelist='$p_filelist', ...");
+    $v_result=1;
+
+    // ----- Reset the error handler
+    $this->privErrorReset();
+
+    // ----- Set default values
+    $v_options = array();
+    $v_add_path = "";
+    $v_remove_path = "";
+    $v_remove_all_path = false;
+    $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
+
+    // ----- Look for variable options arguments
+    $v_size = func_num_args();
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
+
+    // ----- Look for arguments
+    if ($v_size > 1) {
+      // ----- Get the arguments
+      $v_arg_list = &func_get_args();
+
+      // ----- Remove form the options list the first argument
+      array_shift($v_arg_list);
+      $v_size--;
+
+      // ----- Look for first arg
+      if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options detected");
+
+        // ----- Parse the options
+        $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
+                                            array (PCLZIP_OPT_REMOVE_PATH => 'optional',
+                                                   PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
+                                                   PCLZIP_OPT_ADD_PATH => 'optional',
+                                                   PCLZIP_CB_PRE_ADD => 'optional',
+                                                   PCLZIP_CB_POST_ADD => 'optional',
+                                                   PCLZIP_OPT_NO_COMPRESSION => 'optional',
+                                                   PCLZIP_OPT_COMMENT => 'optional',
+                                                   PCLZIP_OPT_ADD_COMMENT => 'optional',
+                                                   PCLZIP_OPT_PREPEND_COMMENT => 'optional'
+                                                   //, PCLZIP_OPT_CRYPT => 'optional'
+                                                                                                  ));
+        if ($v_result != 1) {
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+          return 0;
+        }
+
+        // ----- Set the arguments
+        if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
+          $v_add_path = $v_options[PCLZIP_OPT_ADD_PATH];
+        }
+        if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
+          $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
+        }
+        if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
+          $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
+        }
+      }
+
+      // ----- Look for 2 args
+      // Here we need to support the first historic synopsis of the
+      // method.
+      else {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
+
+        // ----- Get the first argument
+        $v_add_path = $v_arg_list[0];
+
+        // ----- Look for the optional second argument
+        if ($v_size == 2) {
+          $v_remove_path = $v_arg_list[1];
+        }
+        else if ($v_size > 2) {
+          // ----- Error log
+          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
+
+          // ----- Return
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+          return 0;
+        }
+      }
+    }
+
+    // ----- Trace
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "add_path='$v_add_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_all_path?'true':'false')."'");
+
+    // ----- Look if the $p_filelist is really an array
+    $p_result_list = array();
+    if (is_array($p_filelist))
+    {
+      // ----- Call the create fct
+      $v_result = $this->privAdd($p_filelist, $p_result_list, $v_add_path, $v_remove_path, $v_remove_all_path, $v_options);
+    }
+
+    // ----- Look if the $p_filelist is a string
+    else if (is_string($p_filelist))
+    {
+      // ----- Create a list with the elements from the string
+      $v_list = explode(PCLZIP_SEPARATOR, $p_filelist);
+
+      // ----- Call the create fct
+      $v_result = $this->privAdd($v_list, $p_result_list, $v_add_path, $v_remove_path, $v_remove_all_path, $v_options);
+    }
+
+    // ----- Invalid variable
+    else
+    {
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
+      $v_result = PCLZIP_ERR_INVALID_PARAMETER;
+    }
+
+    if ($v_result != 1)
+    {
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+      return 0;
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_result_list);
+    return $p_result_list;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : listContent()
+  // Description :
+  //   This public method, gives the list of the files and directories, with their
+  //   properties.
+  //   The properties of each entries in the list are (used also in other functions) :
+  //     filename : Name of the file. For a create or add action it is the filename
+  //                given by the user. For an extract function it is the filename
+  //                of the extracted file.
+  //     stored_filename : Name of the file / directory stored in the archive.
+  //     size : Size of the stored file.
+  //     compressed_size : Size of the file's data compressed in the archive
+  //                       (without the headers overhead)
+  //     mtime : Last known modification date of the file (UNIX timestamp)
+  //     comment : Comment associated with the file
+  //     folder : true | false
+  //     index : index of the file in the archive
+  //     status : status of the action (depending of the action) :
+  //              Values are :
+  //                ok : OK !
+  //                filtered : the file / dir is not extracted (filtered by user)
+  //                already_a_directory : the file can not be extracted because a
+  //                                      directory with the same name already exists
+  //                write_protected : the file can not be extracted because a file
+  //                                  with the same name already exists and is
+  //                                  write protected
+  //                newer_exist : the file was not extracted because a newer file exists
+  //                path_creation_fail : the file is not extracted because the folder
+  //                                     does not exists and can not be created
+  //                write_error : the file was not extracted because there was a
+  //                              error while writing the file
+  //                read_error : the file was not extracted because there was a error
+  //                             while reading the file
+  //                invalid_header : the file was not extracted because of an archive
+  //                                 format error (bad file header)
+  //   Note that each time a method can continue operating when there
+  //   is an action error on a file, the error is only logged in the file status.
+  // Return Values :
+  //   0 on an unrecoverable failure,
+  //   The list of the files in the archive.
+  // --------------------------------------------------------------------------------
+  function listContent()
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::listContent', "");
+    $v_result=1;
+
+    // ----- Reset the error handler
+    $this->privErrorReset();
+
+    // ----- Check archive
+    if (!$this->privCheckFormat()) {
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+      return(0);
+    }
+
+    // ----- Call the extracting fct
+    $p_list = array();
+    if (($v_result = $this->privList($p_list)) != 1)
+    {
+      unset($p_list);
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
+      return(0);
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
+    return $p_list;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function :
+  //   extract($p_path="./", $p_remove_path="")
+  //   extract([$p_option, $p_option_value, ...])
+  // Description :
+  //   This method supports two synopsis. The first one is historical.
+  //   This method extract all the files / directories from the archive to the
+  //   folder indicated in $p_path.
+  //   If you want to ignore the 'root' part of path of the memorized files
+  //   you can indicate this in the optional $p_remove_path parameter.
+  //   By default, if a newer file with the same name already exists, the
+  //   file is not extracted.
+  //
+  //   If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions
+  //   are used, the path indicated in PCLZIP_OPT_ADD_PATH is append
+  //   at the end of the path value of PCLZIP_OPT_PATH.
+  // Parameters :
+  //   $p_path : Path where the files and directories are to be extracted
+  //   $p_remove_path : First part ('root' part) of the memorized path
+  //                    (if any similar) to remove while extracting.
+  // Options :
+  //   PCLZIP_OPT_PATH :
+  //   PCLZIP_OPT_ADD_PATH :
+  //   PCLZIP_OPT_REMOVE_PATH :
+  //   PCLZIP_OPT_REMOVE_ALL_PATH :
+  //   PCLZIP_CB_PRE_EXTRACT :
+  //   PCLZIP_CB_POST_EXTRACT :
+  // Return Values :
+  //   0 or a negative value on failure,
+  //   The list of the extracted files, with a status of the action.
+  //   (see PclZip::listContent() for list entry format)
+  // --------------------------------------------------------------------------------
+  //function extract($p_path="./", $p_remove_path="")
+  function extract(/* options */)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::extract", "");
+    $v_result=1;
+
+    // ----- Reset the error handler
+    $this->privErrorReset();
+
+    // ----- Check archive
+    if (!$this->privCheckFormat()) {
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+      return(0);
+    }
+
+    // ----- Set default values
+    $v_options = array();
+    $v_path = "./";
+    $v_remove_path = "";
+    $v_remove_all_path = false;
+
+    // ----- Look for variable options arguments
+    $v_size = func_num_args();
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
+
+    // ----- Default values for option
+    $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
+
+    // ----- Look for arguments
+    if ($v_size > 0) {
+      // ----- Get the arguments
+      $v_arg_list = &func_get_args();
+
+      // ----- Look for first arg
+      if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options");
+
+        // ----- Parse the options
+        $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
+                                            array (PCLZIP_OPT_PATH => 'optional',
+                                                   PCLZIP_OPT_REMOVE_PATH => 'optional',
+                                                   PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
+                                                   PCLZIP_OPT_ADD_PATH => 'optional',
+                                                   PCLZIP_CB_PRE_EXTRACT => 'optional',
+                                                   PCLZIP_CB_POST_EXTRACT => 'optional',
+                                                   PCLZIP_OPT_SET_CHMOD => 'optional',
+                                                   PCLZIP_OPT_BY_NAME => 'optional',
+                                                   PCLZIP_OPT_BY_EREG => 'optional',
+                                                   PCLZIP_OPT_BY_PREG => 'optional',
+                                                   PCLZIP_OPT_BY_INDEX => 'optional',
+                                                   PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
+                                                   PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional',
+                                                   PCLZIP_OPT_REPLACE_NEWER => 'optional'
+                                                   ,PCLZIP_OPT_STOP_ON_ERROR => 'optional'
+                                                                                                   ));
+        if ($v_result != 1) {
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+          return 0;
+        }
+
+        // ----- Set the arguments
+        if (isset($v_options[PCLZIP_OPT_PATH])) {
+          $v_path = $v_options[PCLZIP_OPT_PATH];
+        }
+        if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
+          $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
+        }
+        if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
+          $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
+        }
+        if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
+          // ----- Check for '/' in last path char
+          if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
+            $v_path .= '/';
+          }
+          $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
+        }
+      }
+
+      // ----- Look for 2 args
+      // Here we need to support the first historic synopsis of the
+      // method.
+      else {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
+
+        // ----- Get the first argument
+        $v_path = $v_arg_list[0];
+
+        // ----- Look for the optional second argument
+        if ($v_size == 2) {
+          $v_remove_path = $v_arg_list[1];
+        }
+        else if ($v_size > 2) {
+          // ----- Error log
+          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
+
+          // ----- Return
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
+          return 0;
+        }
+      }
+    }
+
+    // ----- Trace
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "path='$v_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_path?'true':'false')."'");
+
+    // ----- Call the extracting fct
+    $p_list = array();
+    $v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path,
+                                            $v_remove_all_path, $v_options);
+    if ($v_result < 1) {
+      unset($p_list);
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
+      return(0);
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
+    return $p_list;
+  }
+  // --------------------------------------------------------------------------------
+
+
+  // --------------------------------------------------------------------------------
+  // Function :
+  //   extractByIndex($p_index, $p_path="./", $p_remove_path="")
+  //   extractByIndex($p_index, [$p_option, $p_option_value, ...])
+  // Description :
+  //   This method supports two synopsis. The first one is historical.
+  //   This method is doing a partial extract of the archive.
+  //   The extracted files or folders are identified by their index in the
+  //   archive (from 0 to n).
+  //   Note that if the index identify a folder, only the folder entry is
+  //   extracted, not all the files included in the archive.
+  // Parameters :
+  //   $p_index : A single index (integer) or a string of indexes of files to
+  //              extract. The form of the string is "0,4-6,8-12" with only numbers
+  //              and '-' for range or ',' to separate ranges. No spaces or ';'
+  //              are allowed.
+  //   $p_path : Path where the files and directories are to be extracted
+  //   $p_remove_path : First part ('root' part) of the memorized path
+  //                    (if any similar) to remove while extracting.
+  // Options :
+  //   PCLZIP_OPT_PATH :
+  //   PCLZIP_OPT_ADD_PATH :
+  //   PCLZIP_OPT_REMOVE_PATH :
+  //   PCLZIP_OPT_REMOVE_ALL_PATH :
+  //   PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and
+  //     not as files.
+  //     The resulting content is in a new field 'content' in the file
+  //     structure.
+  //     This option must be used alone (any other options are ignored).
+  //   PCLZIP_CB_PRE_EXTRACT :
+  //   PCLZIP_CB_POST_EXTRACT :
+  // Return Values :
+  //   0 on failure,
+  //   The list of the extracted files, with a status of the action.
+  //   (see PclZip::listContent() for list entry format)
+  // --------------------------------------------------------------------------------
+  function extractByIndex($p_index /* $options */)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::extractByIndex", "index='$p_index', ...");
+    $v_result=1;
+
+    // ----- Reset the error handler
+    $this->privErrorReset();
+
+    // ----- Check archive
+    if (!$this->privCheckFormat()) {
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+      return(0);
+    }
+
+    // ----- Set default values
+    $v_options = array();
+    $v_path = "./";
+    $v_remove_path = "";
+    $v_remove_all_path = false;
+
+    // ----- Look for variable options arguments
+    $v_size = func_num_args();
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
+
+    // ----- Default values for option
+    $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
+
+    // ----- Look for arguments
+    if ($v_size > 1) {
+      // ----- Get the arguments
+      $v_arg_list = &func_get_args();
+
+      // ----- Remove form the options list the first argument
+      array_shift($v_arg_list);
+      $v_size--;
+
+      // ----- Look for first arg
+      if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options");
+
+        // ----- Parse the options
+        $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
+                                            array (PCLZIP_OPT_PATH => 'optional',
+                                                   PCLZIP_OPT_REMOVE_PATH => 'optional',
+                                                   PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
+                                                   PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
+                                                   PCLZIP_OPT_ADD_PATH => 'optional',
+                                                   PCLZIP_CB_PRE_EXTRACT => 'optional',
+                                                   PCLZIP_CB_POST_EXTRACT => 'optional',
+                                                   PCLZIP_OPT_SET_CHMOD => 'optional',
+                                                   PCLZIP_OPT_REPLACE_NEWER => 'optional'
+                                                   ,PCLZIP_OPT_STOP_ON_ERROR => 'optional'
+                                                                                                  ));
+        if ($v_result != 1) {
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+          return 0;
+        }
+
+        // ----- Set the arguments
+        if (isset($v_options[PCLZIP_OPT_PATH])) {
+          $v_path = $v_options[PCLZIP_OPT_PATH];
+        }
+        if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
+          $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
+        }
+        if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
+          $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
+        }
+        if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
+          // ----- Check for '/' in last path char
+          if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
+            $v_path .= '/';
+          }
+          $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
+        }
+        if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) {
+          $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Option PCLZIP_OPT_EXTRACT_AS_STRING not set.");
+        }
+        else {
+            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Option PCLZIP_OPT_EXTRACT_AS_STRING set.");
+        }
+      }
+
+      // ----- Look for 2 args
+      // Here we need to support the first historic synopsis of the
+      // method.
+      else {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
+
+        // ----- Get the first argument
+        $v_path = $v_arg_list[0];
+
+        // ----- Look for the optional second argument
+        if ($v_size == 2) {
+          $v_remove_path = $v_arg_list[1];
+        }
+        else if ($v_size > 2) {
+          // ----- Error log
+          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
+
+          // ----- Return
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+          return 0;
+        }
+      }
+    }
+
+    // ----- Trace
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "index='$p_index', path='$v_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_path?'true':'false')."'");
+
+    // ----- Trick
+    // Here I want to reuse extractByRule(), so I need to parse the $p_index
+    // with privParseOptions()
+    $v_arg_trick = array (PCLZIP_OPT_BY_INDEX, $p_index);
+    $v_options_trick = array();
+    $v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick,
+                                        array (PCLZIP_OPT_BY_INDEX => 'optional' ));
+    if ($v_result != 1) {
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+        return 0;
+    }
+    $v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX];
+
+    // ----- Call the extracting fct
+    if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) {
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
+        return(0);
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
+    return $p_list;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function :
+  //   delete([$p_option, $p_option_value, ...])
+  // Description :
+  // Parameters :
+  //   None
+  // Options :
+  //   PCLZIP_OPT_BY_INDEX :
+  // Return Values :
+  //   0 on failure,
+  //   The list of the files which are still present in the archive.
+  //   (see PclZip::listContent() for list entry format)
+  // --------------------------------------------------------------------------------
+  function delete(/* options */)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::delete", "");
+    $v_result=1;
+
+    // ----- Reset the error handler
+    $this->privErrorReset();
+
+    // ----- Check archive
+    if (!$this->privCheckFormat()) {
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+      return(0);
+    }
+
+    // ----- Set default values
+    $v_options = array();
+
+    // ----- Look for variable options arguments
+    $v_size = func_num_args();
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
+
+    // ----- Look for no arguments
+    if ($v_size <= 0) {
+        // ----- Error log
+        PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing arguments");
+
+        // ----- Return
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
+        return 0;
+    }
+
+    // ----- Get the arguments
+    $v_arg_list = &func_get_args();
+
+    // ----- Parse the options
+    $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
+                                        array (PCLZIP_OPT_BY_NAME => 'optional',
+                                               PCLZIP_OPT_BY_EREG => 'optional',
+                                               PCLZIP_OPT_BY_PREG => 'optional',
+                                               PCLZIP_OPT_BY_INDEX => 'optional' ));
+    if ($v_result != 1) {
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+        return 0;
+    }
+
+    // ----- Check that at least one rule is set
+    if (   (!isset($v_options[PCLZIP_OPT_BY_NAME]))
+        && (!isset($v_options[PCLZIP_OPT_BY_EREG]))
+        && (!isset($v_options[PCLZIP_OPT_BY_PREG]))
+        && (!isset($v_options[PCLZIP_OPT_BY_INDEX]))) {
+        // ----- Error log
+        PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "At least one filtering rule must be set");
+
+        // ----- Return
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
+        return 0;
+    }
+
+    // ----- Call the delete fct
+    $v_list = array();
+    if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1)
+    {
+      unset($v_list);
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
+      return(0);
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_list);
+    return $v_list;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : deleteByIndex()
+  // Description :
+  //   ***** Deprecated *****
+  //   delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered.
+  // --------------------------------------------------------------------------------
+  function deleteByIndex($p_index)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::deleteByIndex", "index='$p_index'");
+    
+    $p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index);
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
+    return $p_list;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : properties()
+  // Description :
+  //   This method gives the properties of the archive.
+  //   The properties are :
+  //     nb : Number of files in the archive
+  //     comment : Comment associated with the archive file
+  //     status : not_exist, ok
+  // Parameters :
+  //   None
+  // Return Values :
+  //   0 on failure,
+  //   An array with the archive properties.
+  // --------------------------------------------------------------------------------
+  function properties()
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::properties", "");
+
+    // ----- Reset the error handler
+    $this->privErrorReset();
+
+    // ----- Check archive
+    if (!$this->privCheckFormat()) {
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+      return(0);
+    }
+
+    // ----- Default properties
+    $v_prop = array();
+    $v_prop['comment'] = '';
+    $v_prop['nb'] = 0;
+    $v_prop['status'] = 'not_exist';
+
+    // ----- Look if file exists
+    if (@is_file($this->zipname))
+    {
+      // ----- Open the zip file
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+      if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
+      {
+        // ----- Error log
+        PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
+
+        // ----- Return
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), 0);
+        return 0;
+      }
+
+      // ----- Read the central directory informations
+      $v_central_dir = array();
+      if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
+      {
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+        return 0;
+      }
+
+      // ----- Close the zip file
+      $this->privCloseFd();
+
+      // ----- Set the user attributes
+      $v_prop['comment'] = $v_central_dir['comment'];
+      $v_prop['nb'] = $v_central_dir['entries'];
+      $v_prop['status'] = 'ok';
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_prop);
+    return $v_prop;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : duplicate()
+  // Description :
+  //   This method creates an archive by copying the content of an other one. If
+  //   the archive already exist, it is replaced by the new one without any warning.
+  // Parameters :
+  //   $p_archive : The filename of a valid archive, or
+  //                a valid PclZip object.
+  // Return Values :
+  //   1 on success.
+  //   0 or a negative value on error (error code).
+  // --------------------------------------------------------------------------------
+  function duplicate($p_archive)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::duplicate", "");
+    $v_result = 1;
+
+    // ----- Reset the error handler
+    $this->privErrorReset();
+
+    // ----- Look if the $p_archive is a PclZip object
+    if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip'))
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The parameter is valid PclZip object '".$p_archive->zipname."'");
+
+      // ----- Duplicate the archive
+      $v_result = $this->privDuplicate($p_archive->zipname);
+    }
+
+    // ----- Look if the $p_archive is a string (so a filename)
+    else if (is_string($p_archive))
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The parameter is a filename '$p_archive'");
+
+      // ----- Check that $p_archive is a valid zip file
+      // TBC : Should also check the archive format
+      if (!is_file($p_archive)) {
+        // ----- Error log
+        PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'");
+        $v_result = PCLZIP_ERR_MISSING_FILE;
+      }
+      else {
+        // ----- Duplicate the archive
+        $v_result = $this->privDuplicate($p_archive);
+      }
+    }
+
+    // ----- Invalid variable
+    else
+    {
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
+      $v_result = PCLZIP_ERR_INVALID_PARAMETER;
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : merge()
+  // Description :
+  //   This method merge the $p_archive_to_add archive at the end of the current
+  //   one ($this).
+  //   If the archive ($this) does not exist, the merge becomes a duplicate.
+  //   If the $p_archive_to_add archive does not exist, the merge is a success.
+  // Parameters :
+  //   $p_archive_to_add : It can be directly the filename of a valid zip archive,
+  //                       or a PclZip object archive.
+  // Return Values :
+  //   1 on success,
+  //   0 or negative values on error (see below).
+  // --------------------------------------------------------------------------------
+  function merge($p_archive_to_add)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::merge", "");
+    $v_result = 1;
+
+    // ----- Reset the error handler
+    $this->privErrorReset();
+
+    // ----- Check archive
+    if (!$this->privCheckFormat()) {
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+      return(0);
+    }
+
+    // ----- Look if the $p_archive_to_add is a PclZip object
+    if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip'))
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The parameter is valid PclZip object");
+
+      // ----- Merge the archive
+      $v_result = $this->privMerge($p_archive_to_add);
+    }
+
+    // ----- Look if the $p_archive_to_add is a string (so a filename)
+    else if (is_string($p_archive_to_add))
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The parameter is a filename");
+
+      // ----- Create a temporary archive
+      $v_object_archive = new PclZip($p_archive_to_add);
+
+      // ----- Merge the archive
+      $v_result = $this->privMerge($v_object_archive);
+    }
+
+    // ----- Invalid variable
+    else
+    {
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
+      $v_result = PCLZIP_ERR_INVALID_PARAMETER;
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+
+
+  // --------------------------------------------------------------------------------
+  // Function : errorCode()
+  // Description :
+  // Parameters :
+  // --------------------------------------------------------------------------------
+  function errorCode()
+  {
+    if (PCLZIP_ERROR_EXTERNAL == 1) {
+      return(PclErrorCode());
+    }
+    else {
+      return($this->error_code);
+    }
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : errorName()
+  // Description :
+  // Parameters :
+  // --------------------------------------------------------------------------------
+  function errorName($p_with_code=false)
+  {
+    $v_name = array ( PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR',
+                      PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL',
+                      PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL',
+                      PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER',
+                      PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE',
+                      PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG',
+                      PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP',
+                      PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE',
+                      PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL',
+                      PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION',
+                      PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT',
+                      PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL',
+                      PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL',
+                      PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM',
+                      PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP',
+                      PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE',
+                      PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE',
+                      PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION',
+                      PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION' );
+
+    if (isset($v_name[$this->error_code])) {
+      $v_value = $v_name[$this->error_code];
+    }
+    else {
+      $v_value = 'NoName';
+    }
+
+    if ($p_with_code) {
+      return($v_value.' ('.$this->error_code.')');
+    }
+    else {
+      return($v_value);
+    }
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : errorInfo()
+  // Description :
+  // Parameters :
+  // --------------------------------------------------------------------------------
+  function errorInfo($p_full=false)
+  {
+    if (PCLZIP_ERROR_EXTERNAL == 1) {
+      return(PclErrorString());
+    }
+    else {
+      if ($p_full) {
+        return($this->errorName(true)." : ".$this->error_string);
+      }
+      else {
+        return($this->error_string." [code ".$this->error_code."]");
+      }
+    }
+  }
+  // --------------------------------------------------------------------------------
+
+
+// --------------------------------------------------------------------------------
+// ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
+// *****                                                        *****
+// *****       THESES FUNCTIONS MUST NOT BE USED DIRECTLY       *****
+// --------------------------------------------------------------------------------
+
+
+
+  // --------------------------------------------------------------------------------
+  // Function : privCheckFormat()
+  // Description :
+  //   This method check that the archive exists and is a valid zip archive.
+  //   Several level of check exists. (futur)
+  // Parameters :
+  //   $p_level : Level of check. Default 0.
+  //              0 : Check the first bytes (magic codes) (default value))
+  //              1 : 0 + Check the central directory (futur)
+  //              2 : 1 + Check each file header (futur)
+  // Return Values :
+  //   true on success,
+  //   false on error, the error code is set.
+  // --------------------------------------------------------------------------------
+  function privCheckFormat($p_level=0)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCheckFormat", "");
+    $v_result = true;
+
+       // ----- Reset the file system cache
+    clearstatcache();
+
+    // ----- Reset the error handler
+    $this->privErrorReset();
+
+    // ----- Look if the file exits
+    if (!is_file($this->zipname)) {
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'");
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, false, PclZip::errorInfo());
+      return(false);
+    }
+
+    // ----- Check that the file is readeable
+    if (!is_readable($this->zipname)) {
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'");
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, false, PclZip::errorInfo());
+      return(false);
+    }
+
+    // ----- Check the magic code
+    // TBC
+
+    // ----- Check the central header
+    // TBC
+
+    // ----- Check each file header
+    // TBC
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privParseOptions()
+  // Description :
+  //   This internal methods reads the variable list of arguments ($p_options_list,
+  //   $p_size) and generate an array with the options and values ($v_result_list).
+  //   $v_requested_options contains the options that can be present and those that
+  //   must be present.
+  //   $v_requested_options is an array, with the option value as key, and 'optional',
+  //   or 'mandatory' as value.
+  // Parameters :
+  //   See above.
+  // Return Values :
+  //   1 on success.
+  //   0 on failure.
+  // --------------------------------------------------------------------------------
+  function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privParseOptions", "");
+    $v_result=1;
+
+    // ----- Read the options
+    $i=0;
+    while ($i<$p_size) {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Looking for table index $i, option = '".PclZipUtilOptionText($p_options_list[$i])."(".$p_options_list[$i].")'");
+
+      // ----- Check if the option is requested
+      if (!isset($v_requested_options[$p_options_list[$i]])) {
+        // ----- Error log
+        PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method");
+
+        // ----- Return
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+        return PclZip::errorCode();
+      }
+
+      // ----- Look for next option
+      switch ($p_options_list[$i]) {
+        // ----- Look for options that request a path value
+        case PCLZIP_OPT_PATH :
+        case PCLZIP_OPT_REMOVE_PATH :
+        case PCLZIP_OPT_ADD_PATH :
+          // ----- Check the number of parameters
+          if (($i+1) >= $p_size) {
+            // ----- Error log
+            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+            // ----- Return
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+            return PclZip::errorCode();
+          }
+
+          // ----- Get the value
+          $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], false);
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
+          $i++;
+        break;
+
+        // ----- Look for options that request an array of string for value
+        case PCLZIP_OPT_BY_NAME :
+          // ----- Check the number of parameters
+          if (($i+1) >= $p_size) {
+            // ----- Error log
+            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+            // ----- Return
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+            return PclZip::errorCode();
+          }
+
+          // ----- Get the value
+          if (is_string($p_options_list[$i+1])) {
+              $v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1];
+          }
+          else if (is_array($p_options_list[$i+1])) {
+              $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
+          }
+          else {
+            // ----- Error log
+            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+            // ----- Return
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+            return PclZip::errorCode();
+          }
+          ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
+          $i++;
+        break;
+
+        // ----- Look for options that request an EREG or PREG expression
+        case PCLZIP_OPT_BY_EREG :
+        case PCLZIP_OPT_BY_PREG :
+        //case PCLZIP_OPT_CRYPT :
+          // ----- Check the number of parameters
+          if (($i+1) >= $p_size) {
+            // ----- Error log
+            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+            // ----- Return
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+            return PclZip::errorCode();
+          }
+
+          // ----- Get the value
+          if (is_string($p_options_list[$i+1])) {
+              $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
+          }
+          else {
+            // ----- Error log
+            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+            // ----- Return
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+            return PclZip::errorCode();
+          }
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
+          $i++;
+        break;
+
+        // ----- Look for options that takes a string
+        case PCLZIP_OPT_COMMENT :
+        case PCLZIP_OPT_ADD_COMMENT :
+        case PCLZIP_OPT_PREPEND_COMMENT :
+          // ----- Check the number of parameters
+          if (($i+1) >= $p_size) {
+            // ----- Error log
+            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
+                                            "Missing parameter value for option '"
+                                                                .PclZipUtilOptionText($p_options_list[$i])
+                                                                ."'");
+
+            // ----- Return
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+            return PclZip::errorCode();
+          }
+
+          // ----- Get the value
+          if (is_string($p_options_list[$i+1])) {
+              $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
+          }
+          else {
+            // ----- Error log
+            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
+                                            "Wrong parameter value for option '"
+                                                                .PclZipUtilOptionText($p_options_list[$i])
+                                                                ."'");
+
+            // ----- Return
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+            return PclZip::errorCode();
+          }
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
+          $i++;
+        break;
+
+        // ----- Look for options that request an array of index
+        case PCLZIP_OPT_BY_INDEX :
+          // ----- Check the number of parameters
+          if (($i+1) >= $p_size) {
+            // ----- Error log
+            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+            // ----- Return
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+            return PclZip::errorCode();
+          }
+
+          // ----- Get the value
+          $v_work_list = array();
+          if (is_string($p_options_list[$i+1])) {
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is a string '".$p_options_list[$i+1]."'");
+
+              // ----- Remove spaces
+              $p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', '');
+
+              // ----- Parse items
+              $v_work_list = explode(",", $p_options_list[$i+1]);
+          }
+          else if (is_integer($p_options_list[$i+1])) {
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is an integer '".$p_options_list[$i+1]."'");
+              $v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1];
+          }
+          else if (is_array($p_options_list[$i+1])) {
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is an array");
+              $v_work_list = $p_options_list[$i+1];
+          }
+          else {
+            // ----- Error log
+            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+            // ----- Return
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+            return PclZip::errorCode();
+          }
+          
+          // ----- Reduce the index list
+          // each index item in the list must be a couple with a start and
+          // an end value : [0,3], [5-5], [8-10], ...
+          // ----- Check the format of each item
+          $v_sort_flag=false;
+          $v_sort_value=0;
+          for ($j=0; $j<sizeof($v_work_list); $j++) {
+              // ----- Explode the item
+              $v_item_list = explode("-", $v_work_list[$j]);
+              $v_size_item_list = sizeof($v_item_list);
+              
+              // ----- TBC : Here we might check that each item is a
+              // real integer ...
+              
+              // ----- Look for single value
+              if ($v_size_item_list == 1) {
+                  // ----- Set the option value
+                  $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
+                  $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[0];
+              }
+              elseif ($v_size_item_list == 2) {
+                  // ----- Set the option value
+                  $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
+                  $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[1];
+              }
+              else {
+                  // ----- Error log
+                  PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Too many values in index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+                  // ----- Return
+                  //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+                  return PclZip::errorCode();
+              }
+
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extracted index item = [".$v_result_list[$p_options_list[$i]][$j]['start'].",".$v_result_list[$p_options_list[$i]][$j]['end']."]");
+
+              // ----- Look for list sort
+              if ($v_result_list[$p_options_list[$i]][$j]['start'] < $v_sort_value) {
+                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The list should be sorted ...");
+                  $v_sort_flag=true;
+
+                  // ----- TBC : An automatic sort should be writen ...
+                  // ----- Error log
+                  PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Invalid order of index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+                  // ----- Return
+                  //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+                  return PclZip::errorCode();
+              }
+              $v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start'];
+          }
+          
+          // ----- Sort the items
+          if ($v_sort_flag) {
+              // TBC : To Be Completed
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "List sorting is not yet write ...");
+          }
+
+          // ----- Next option
+          $i++;
+        break;
+
+        // ----- Look for options that request no value
+        case PCLZIP_OPT_REMOVE_ALL_PATH :
+        case PCLZIP_OPT_EXTRACT_AS_STRING :
+        case PCLZIP_OPT_NO_COMPRESSION :
+        case PCLZIP_OPT_EXTRACT_IN_OUTPUT :
+        case PCLZIP_OPT_REPLACE_NEWER :
+        case PCLZIP_OPT_STOP_ON_ERROR :
+          $v_result_list[$p_options_list[$i]] = true;
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
+        break;
+
+        // ----- Look for options that request an octal value
+        case PCLZIP_OPT_SET_CHMOD :
+          // ----- Check the number of parameters
+          if (($i+1) >= $p_size) {
+            // ----- Error log
+            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+            // ----- Return
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+            return PclZip::errorCode();
+          }
+
+          // ----- Get the value
+          $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
+          $i++;
+        break;
+
+        // ----- Look for options that request a call-back
+        case PCLZIP_CB_PRE_EXTRACT :
+        case PCLZIP_CB_POST_EXTRACT :
+        case PCLZIP_CB_PRE_ADD :
+        case PCLZIP_CB_POST_ADD :
+        /* for futur use
+        case PCLZIP_CB_PRE_DELETE :
+        case PCLZIP_CB_POST_DELETE :
+        case PCLZIP_CB_PRE_LIST :
+        case PCLZIP_CB_POST_LIST :
+        */
+          // ----- Check the number of parameters
+          if (($i+1) >= $p_size) {
+            // ----- Error log
+            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+            // ----- Return
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+            return PclZip::errorCode();
+          }
+
+          // ----- Get the value
+          $v_function_name = $p_options_list[$i+1];
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "call-back ".PclZipUtilOptionText($p_options_list[$i])." = '".$v_function_name."'");
+
+          // ----- Check that the value is a valid existing function
+          if (!function_exists($v_function_name)) {
+            // ----- Error log
+            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+            // ----- Return
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+            return PclZip::errorCode();
+          }
+
+          // ----- Set the attribute
+          $v_result_list[$p_options_list[$i]] = $v_function_name;
+          $i++;
+        break;
+
+        default :
+          // ----- Error log
+          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
+                                      "Unknown parameter '"
+                                                          .$p_options_list[$i]."'");
+
+          // ----- Return
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+          return PclZip::errorCode();
+      }
+
+      // ----- Next options
+      $i++;
+    }
+
+    // ----- Look for mandatory options
+    if ($v_requested_options !== false) {
+      for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
+        // ----- Look for mandatory option
+        if ($v_requested_options[$key] == 'mandatory') {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Detect a mandatory option : ".PclZipUtilOptionText($key)."(".$key.")");
+          // ----- Look if present
+          if (!isset($v_result_list[$key])) {
+            // ----- Error log
+            PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
+
+            // ----- Return
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+            return PclZip::errorCode();
+          }
+        }
+      }
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privCreate()
+  // Description :
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privCreate($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCreate", "list, result_list, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
+    $v_result=1;
+    $v_list_detail = array();
+
+    // ----- Open the file in write mode
+    if (($v_result = $this->privOpenFd('wb')) != 1)
+    {
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Add the list of files
+    $v_result = $this->privAddList($p_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options);
+
+    // ----- Close
+    $this->privCloseFd();
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privAdd()
+  // Description :
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privAdd($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAdd", "list, result_list, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
+    $v_result=1;
+    $v_list_detail = array();
+
+    // ----- Look if the archive exists or is empty
+    if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0))
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive does not exist, or is empty, create it.");
+
+      // ----- Do a create
+      $v_result = $this->privCreate($p_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options);
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Open the zip file
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+    if (($v_result=$this->privOpenFd('rb')) != 1)
+    {
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Read the central directory informations
+    $v_central_dir = array();
+    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
+    {
+      $this->privCloseFd();
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Go to beginning of File
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
+    @rewind($this->zip_fd);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
+
+    // ----- Creates a temporay file
+    $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
+
+    // ----- Open the temporary file in write mode
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+    if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
+    {
+      $this->privCloseFd();
+
+      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+      return PclZip::errorCode();
+    }
+
+    // ----- Copy the files from the archive to the temporary file
+    // TBC : Here I should better append the file and go back to erase the central dir
+    $v_size = $v_central_dir['offset'];
+    while ($v_size != 0)
+    {
+      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+      $v_buffer = fread($this->zip_fd, $v_read_size);
+      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
+      $v_size -= $v_read_size;
+    }
+
+    // ----- Swap the file descriptor
+    // Here is a trick : I swap the temporary fd with the zip fd, in order to use
+    // the following methods on the temporary fil and not the real archive
+    $v_swap = $this->zip_fd;
+    $this->zip_fd = $v_zip_temp_fd;
+    $v_zip_temp_fd = $v_swap;
+
+    // ----- Add the files
+    $v_header_list = array();
+    if (($v_result = $this->privAddFileList($p_list, $v_header_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options)) != 1)
+    {
+      fclose($v_zip_temp_fd);
+      $this->privCloseFd();
+      @unlink($v_zip_temp_name);
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Store the offset of the central dir
+    $v_offset = @ftell($this->zip_fd);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "New offset of central dir : $v_offset");
+
+    // ----- Copy the block of file headers from the old archive
+    $v_size = $v_central_dir['size'];
+    while ($v_size != 0)
+    {
+      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+      $v_buffer = @fread($v_zip_temp_fd, $v_read_size);
+      @fwrite($this->zip_fd, $v_buffer, $v_read_size);
+      $v_size -= $v_read_size;
+    }
+
+    // ----- Create the Central Dir files header
+    for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++)
+    {
+      // ----- Create the file header
+      if ($v_header_list[$i]['status'] == 'ok') {
+        if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
+          fclose($v_zip_temp_fd);
+          $this->privCloseFd();
+          @unlink($v_zip_temp_name);
+
+          // ----- Return
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+          return $v_result;
+        }
+        $v_count++;
+      }
+
+      // ----- Transform the header to a 'usable' info
+      $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
+    }
+
+    // ----- Zip file comment
+    $v_comment = $v_central_dir['comment'];
+    if (isset($p_options[PCLZIP_OPT_COMMENT])) {
+      $v_comment = $p_options[PCLZIP_OPT_COMMENT];
+    }
+    if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) {
+      $v_comment = $v_comment.$p_options[PCLZIP_OPT_ADD_COMMENT];
+    }
+    if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) {
+      $v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT].$v_comment;
+    }
+
+    // ----- Calculate the size of the central header
+    $v_size = @ftell($this->zip_fd)-$v_offset;
+
+    // ----- Create the central dir footer
+    if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1)
+    {
+      // ----- Reset the file list
+      unset($v_header_list);
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Swap back the file descriptor
+    $v_swap = $this->zip_fd;
+    $this->zip_fd = $v_zip_temp_fd;
+    $v_zip_temp_fd = $v_swap;
+
+    // ----- Close
+    $this->privCloseFd();
+
+    // ----- Close the temporary file
+    @fclose($v_zip_temp_fd);
+
+    // ----- Delete the zip file
+    // TBC : I should test the result ...
+    @unlink($this->zipname);
+
+    // ----- Rename the temporary file
+    // TBC : I should test the result ...
+    //@rename($v_zip_temp_name, $this->zipname);
+    PclZipUtilRename($v_zip_temp_name, $this->zipname);
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privOpenFd()
+  // Description :
+  // Parameters :
+  // --------------------------------------------------------------------------------
+  function privOpenFd($p_mode)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privOpenFd", 'mode='.$p_mode);
+    $v_result=1;
+
+    // ----- Look if already open
+    if ($this->zip_fd != 0)
+    {
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open');
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+      return PclZip::errorCode();
+    }
+
+    // ----- Open the zip file
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Open file in '.$p_mode.' mode');
+    if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0)
+    {
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode');
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+      return PclZip::errorCode();
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privCloseFd()
+  // Description :
+  // Parameters :
+  // --------------------------------------------------------------------------------
+  function privCloseFd()
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCloseFd", "");
+    $v_result=1;
+
+    if ($this->zip_fd != 0)
+      @fclose($this->zip_fd);
+    $this->zip_fd = 0;
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privAddList()
+  // Description :
+  //   $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
+  //   different from the real path of the file. This is usefull if you want to have PclTar
+  //   running in any directory, and memorize relative path from an other directory.
+  // Parameters :
+  //   $p_list : An array containing the file or directory names to add in the tar
+  //   $p_result_list : list of added files with their properties (specially the status field)
+  //   $p_add_dir : Path to add in the filename path archived
+  //   $p_remove_dir : Path to remove in the filename path archived
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddList", "list, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
+    $v_result=1;
+
+    // ----- Add the files
+    $v_header_list = array();
+    if (($v_result = $this->privAddFileList($p_list, $v_header_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options)) != 1)
+    {
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Store the offset of the central dir
+    $v_offset = @ftell($this->zip_fd);
+
+    // ----- Create the Central Dir files header
+    for ($i=0,$v_count=0; $i<sizeof($v_header_list); $i++)
+    {
+      // ----- Create the file header
+      if ($v_header_list[$i]['status'] == 'ok') {
+        if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
+          // ----- Return
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+          return $v_result;
+        }
+        $v_count++;
+      }
+
+      // ----- Transform the header to a 'usable' info
+      $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
+    }
+
+    // ----- Zip file comment
+    $v_comment = '';
+    if (isset($p_options[PCLZIP_OPT_COMMENT])) {
+      $v_comment = $p_options[PCLZIP_OPT_COMMENT];
+    }
+
+    // ----- Calculate the size of the central header
+    $v_size = @ftell($this->zip_fd)-$v_offset;
+
+    // ----- Create the central dir footer
+    if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1)
+    {
+      // ----- Reset the file list
+      unset($v_header_list);
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privAddFileList()
+  // Description :
+  //   $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
+  //   different from the real path of the file. This is usefull if you want to
+  //   run the lib in any directory, and memorize relative path from an other directory.
+  // Parameters :
+  //   $p_list : An array containing the file or directory names to add in the tar
+  //   $p_result_list : list of added files with their properties (specially the status field)
+  //   $p_add_dir : Path to add in the filename path archived
+  //   $p_remove_dir : Path to remove in the filename path archived
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privAddFileList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFileList", "list, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
+    $v_result=1;
+    $v_header = array();
+
+    // ----- Recuperate the current number of elt in list
+    $v_nb = sizeof($p_result_list);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Before add, list have $v_nb elements");
+
+    // ----- Loop on the files
+    for ($j=0; ($j<count($p_list)) && ($v_result==1); $j++)
+    {
+      // ----- Recuperate the filename
+      $p_filename = PclZipUtilTranslateWinPath($p_list[$j], false);
+
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Looking for file [$p_filename]");
+
+      // ----- Skip empty file names
+      if ($p_filename == "")
+      {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Skip empty filename");
+        continue;
+      }
+
+      // ----- Check the filename
+      if (!file_exists($p_filename))
+      {
+        // ----- Error log
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '$p_filename' does not exists");
+        PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '$p_filename' does not exists");
+
+        // ----- Return
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+        return PclZip::errorCode();
+      }
+
+      /* This test is done later
+      // ----- Check the path length
+      if (strlen($p_filename) > 0xFF)
+      {
+        // ----- Error log
+        PclZip::privErrorLog(-5, "File name is too long (max. 255) : '$p_filename'");
+
+        // ----- Return
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+        return PclZip::errorCode();
+      }
+      */
+
+      // ----- Look if it is a file or a dir with no all pathnre move
+      if ((is_file($p_filename)) || ((is_dir($p_filename)) && !$p_remove_all_dir)) {
+        // ----- Add the file
+        if (($v_result = $this->privAddFile($p_filename, $v_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options)) != 1)
+        {
+          // ----- Return status
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+          return $v_result;
+        }
+
+        // ----- Store the file infos
+        $p_result_list[$v_nb++] = $v_header;
+      }
+
+      // ----- Look for directory
+      if (@is_dir($p_filename))
+      {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "$p_filename is a directory");
+
+        // ----- Look for path
+        if ($p_filename != ".")
+          $v_path = $p_filename."/";
+        else
+          $v_path = "";
+
+        // ----- Read the directory for files and sub-directories
+        if ($p_hdir = @opendir($p_filename)) {
+          $p_hitem = @readdir($p_hdir); // '.' directory
+          $p_hitem = @readdir($p_hdir); // '..' directory
+          while (($p_hitem = @readdir($p_hdir)) !== false) {
+            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Looking for $p_hitem in the directory");
+
+            // ----- Look for a file
+            if (is_file($v_path.$p_hitem)) {
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Add the file '".$v_path.$p_hitem."'");
+
+              // ----- Add the file
+              if (($v_result = $this->privAddFile($v_path.$p_hitem, $v_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options)) != 1) {
+                // ----- Return status
+                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+                return $v_result;
+              }
+
+              // ----- Store the file infos
+              $p_result_list[$v_nb++] = $v_header;
+            }
+
+            // ----- Recursive call to privAddFileList()
+            else {
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Add the directory '".$v_path.$p_hitem."'");
+
+              // ----- Need an array as parameter
+              $p_temp_list[0] = $v_path.$p_hitem;
+              $v_result = $this->privAddFileList($p_temp_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options);
+
+              // ----- Update the number of elements of the list
+              $v_nb = sizeof($p_result_list);
+            }
+          }
+        }
+
+        // ----- Free memory for the recursive loop
+        unset($p_temp_list);
+        unset($p_hdir);
+        unset($p_hitem);
+      }
+    }
+
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "After add, list have $v_nb elements");
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privAddFile()
+  // Description :
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privAddFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFile", "filename='$p_filename', add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
+    $v_result=1;
+
+    if ($p_filename == "")
+    {
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+      return PclZip::errorCode();
+    }
+
+    // ----- Calculate the stored filename
+    $v_stored_filename = $p_filename;
+
+    // ----- Look for all path to remove
+    if ($p_remove_all_dir) {
+      $v_stored_filename = basename($p_filename);
+    }
+    // ----- Look for partial path remove
+    else if ($p_remove_dir != "")
+    {
+      if (substr($p_remove_dir, -1) != '/')
+        $p_remove_dir .= "/";
+
+      if ((substr($p_filename, 0, 2) == "./") || (substr($p_remove_dir, 0, 2) == "./"))
+      {
+        if ((substr($p_filename, 0, 2) == "./") && (substr($p_remove_dir, 0, 2) != "./"))
+          $p_remove_dir = "./".$p_remove_dir;
+        if ((substr($p_filename, 0, 2) != "./") && (substr($p_remove_dir, 0, 2) == "./"))
+          $p_remove_dir = substr($p_remove_dir, 2);
+      }
+
+      $v_compare = PclZipUtilPathInclusion($p_remove_dir, $p_filename);
+      if ($v_compare > 0)
+//      if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir)
+      {
+
+        if ($v_compare == 2) {
+          $v_stored_filename = "";
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Path to remove is the current folder");
+        }
+        else {
+          $v_stored_filename = substr($p_filename, strlen($p_remove_dir));
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Remove path '$p_remove_dir' in file '$p_filename' = '$v_stored_filename'");
+        }
+      }
+    }
+    // ----- Look for path to add
+    if ($p_add_dir != "")
+    {
+      if (substr($p_add_dir, -1) == "/")
+        $v_stored_filename = $p_add_dir.$v_stored_filename;
+      else
+        $v_stored_filename = $p_add_dir."/".$v_stored_filename;
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Add path '$p_add_dir' in file '$p_filename' = '$v_stored_filename'");
+    }
+
+    // ----- Filename (reduce the path of stored name)
+    $v_stored_filename = PclZipUtilPathReduction($v_stored_filename);
+
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Filename (reduced) '$v_stored_filename', strlen ".strlen($v_stored_filename));
+
+    // ----- Set the file properties
+    clearstatcache();
+    $p_header['version'] = 20;
+    $p_header['version_extracted'] = 10;
+    $p_header['flag'] = 0;
+    $p_header['compression'] = 0;
+    $p_header['mtime'] = filemtime($p_filename);
+    $p_header['crc'] = 0;
+    $p_header['compressed_size'] = 0;
+    $p_header['size'] = filesize($p_filename);
+    $p_header['filename_len'] = strlen($p_filename);
+    $p_header['extra_len'] = 0;
+    $p_header['comment_len'] = 0;
+    $p_header['disk'] = 0;
+    $p_header['internal'] = 0;
+//    $p_header['external'] = (is_file($p_filename)?0xFE49FFE0:0x41FF0010);
+    $p_header['external'] = (is_file($p_filename)?0x00000000:0x00000010);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Header external extension '".sprintf("0x%X",$p_header['external'])."'");
+    $p_header['offset'] = 0;
+    $p_header['filename'] = $p_filename;
+    $p_header['stored_filename'] = $v_stored_filename;
+    $p_header['extra'] = '';
+    $p_header['comment'] = '';
+    $p_header['status'] = 'ok';
+    $p_header['index'] = -1;
+
+
+    // ----- Look for pre-add callback
+    if (isset($p_options[PCLZIP_CB_PRE_ADD])) {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_ADD]."()') is defined for the extraction");
+
+      // ----- Generate a local information
+      $v_local_header = array();
+      $this->privConvertHeader2FileInfo($p_header, $v_local_header);
+
+      // ----- Call the callback
+      // Here I do not use call_user_func() because I need to send a reference to the
+      // header.
+      eval('$v_result = '.$p_options[PCLZIP_CB_PRE_ADD].'(PCLZIP_CB_PRE_ADD, $v_local_header);');
+      if ($v_result == 0) {
+        // ----- Change the file status
+        $p_header['status'] = "skipped";
+        $v_result = 1;
+      }
+
+      // ----- Update the informations
+      // Only some fields can be modified
+      if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
+        $p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']);
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New stored filename is '".$p_header['stored_filename']."'");
+      }
+    }
+
+    // ----- Look for empty stored filename
+    if ($p_header['stored_filename'] == "") {
+      $p_header['status'] = "filtered";
+    }
+    
+    // ----- Check the path length
+    if (strlen($p_header['stored_filename']) > 0xFF) {
+      $p_header['status'] = 'filename_too_long';
+    }
+
+    // ----- Look if no error, or file not skipped
+    if ($p_header['status'] == 'ok') {
+
+      // ----- Look for a file
+      if (is_file($p_filename))
+      {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "'".$p_filename."' is a file");
+        // ----- Open the source file
+        if (($v_file = @fopen($p_filename, "rb")) == 0) {
+          PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+          return PclZip::errorCode();
+        }
+
+        if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File will not be compressed");
+          // ----- Read the file content
+          $v_content_compressed = @fread($v_file, $p_header['size']);
+
+          // ----- Calculate the CRC
+          $p_header['crc'] = @crc32($v_content_compressed);
+
+          // ----- Set header parameters
+          $p_header['compressed_size'] = $p_header['size'];
+          $p_header['compression'] = 0;
+        }
+        else {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File will be compressed");
+          // ----- Read the file content
+          $v_content = @fread($v_file, $p_header['size']);
+
+          // ----- Calculate the CRC
+          $p_header['crc'] = @crc32($v_content);
+
+          // ----- Compress the file
+          $v_content_compressed = @gzdeflate($v_content);
+
+          // ----- Set header parameters
+          $p_header['compressed_size'] = strlen($v_content_compressed);
+          $p_header['compression'] = 8;
+        }
+        
+        // ----- Look for encryption
+        /*
+        if ((isset($p_options[PCLZIP_OPT_CRYPT]))
+                   && ($p_options[PCLZIP_OPT_CRYPT] != "")) {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File need to be crypted ....");
+          
+          // Should be a random header
+          $v_header = 'xxxxxxxxxxxx';
+             $v_content_compressed = PclZipUtilZipEncrypt($v_content_compressed,
+                                                          $p_header['compressed_size'],
+                                                      $v_header,
+                                                                                                  $p_header['crc'],
+                                                                                                  "test");
+                                                                                                  
+          $p_header['compressed_size'] += 12;
+          $p_header['flag'] = 1;
+          
+          // ----- Add the header to the data
+          $v_content_compressed = $v_header.$v_content_compressed;
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Size after header : ".strlen($v_content_compressed)."");
+        }
+        */
+
+        // ----- Call the header generation
+        if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
+          @fclose($v_file);
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+          return $v_result;
+        }
+
+        // ----- Write the compressed (or not) content
+        $v_binary_data = pack('a'.$p_header['compressed_size'],
+                                     $v_content_compressed);
+        @fwrite($this->zip_fd, $v_binary_data, $p_header['compressed_size']);
+        
+        // ----- Close the file
+        @fclose($v_file);
+      }
+
+      // ----- Look for a directory
+      else {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "'".$p_filename."' is a folder");
+        // ----- Look for directory last '/'
+        if (@substr($p_header['stored_filename'], -1) != '/') {
+          $p_header['stored_filename'] .= '/';
+        }
+
+        // ----- Set the file properties
+        $p_header['size'] = 0;
+        //$p_header['external'] = 0x41FF0010;   // Value for a folder : to be checked
+        $p_header['external'] = 0x00000010;   // Value for a folder : to be checked
+
+        // ----- Call the header generation
+        if (($v_result = $this->privWriteFileHeader($p_header)) != 1)
+        {
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+          return $v_result;
+        }
+      }
+    }
+
+    // ----- Look for pre-add callback
+    if (isset($p_options[PCLZIP_CB_POST_ADD])) {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_ADD]."()') is defined for the extraction");
+
+      // ----- Generate a local information
+      $v_local_header = array();
+      $this->privConvertHeader2FileInfo($p_header, $v_local_header);
+
+      // ----- Call the callback
+      // Here I do not use call_user_func() because I need to send a reference to the
+      // header.
+      eval('$v_result = '.$p_options[PCLZIP_CB_POST_ADD].'(PCLZIP_CB_POST_ADD, $v_local_header);');
+      if ($v_result == 0) {
+        // ----- Ignored
+        $v_result = 1;
+      }
+
+      // ----- Update the informations
+      // Nothing can be modified
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privWriteFileHeader()
+  // Description :
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privWriteFileHeader(&$p_header)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteFileHeader", 'file="'.$p_header['filename'].'", stored as "'.$p_header['stored_filename'].'"');
+    $v_result=1;
+
+    // TBC
+    //for(reset($p_header); $key = key($p_header); next($p_header)) {
+    //  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "header[$key] = ".$p_header[$key]);
+    //}
+
+    // ----- Store the offset position of the file
+    $p_header['offset'] = ftell($this->zip_fd);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, 'File offset of the header :'.$p_header['offset']);
+
+    // ----- Transform UNIX mtime to DOS format mdate/mtime
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
+    $v_date = getdate($p_header['mtime']);
+    $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
+    $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
+
+    // ----- Packed data
+    $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50,
+                             $p_header['version_extracted'], $p_header['flag'],
+                          $p_header['compression'], $v_mtime, $v_mdate,
+                          $p_header['crc'], $p_header['compressed_size'],
+                                                 $p_header['size'],
+                          strlen($p_header['stored_filename']),
+                                                 $p_header['extra_len']);
+
+    // ----- Write the first 148 bytes of the header in the archive
+    fputs($this->zip_fd, $v_binary_data, 30);
+
+    // ----- Write the variable fields
+    if (strlen($p_header['stored_filename']) != 0)
+    {
+      fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
+    }
+    if ($p_header['extra_len'] != 0)
+    {
+      fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privWriteCentralFileHeader()
+  // Description :
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privWriteCentralFileHeader(&$p_header)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteCentralFileHeader", 'file="'.$p_header['filename'].'", stored as "'.$p_header['stored_filename'].'"');
+    $v_result=1;
+
+    // TBC
+    //for(reset($p_header); $key = key($p_header); next($p_header)) {
+    //  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "header[$key] = ".$p_header[$key]);
+    //}
+
+    // ----- Transform UNIX mtime to DOS format mdate/mtime
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
+    $v_date = getdate($p_header['mtime']);
+    $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
+    $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
+
+    // ----- Packed data
+    $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50,
+                             $p_header['version'], $p_header['version_extracted'],
+                          $p_header['flag'], $p_header['compression'],
+                                                 $v_mtime, $v_mdate, $p_header['crc'],
+                          $p_header['compressed_size'], $p_header['size'],
+                          strlen($p_header['stored_filename']),
+                                                 $p_header['extra_len'], $p_header['comment_len'],
+                          $p_header['disk'], $p_header['internal'],
+                                                 $p_header['external'], $p_header['offset']);
+
+    // ----- Write the 42 bytes of the header in the zip file
+    fputs($this->zip_fd, $v_binary_data, 46);
+
+    // ----- Write the variable fields
+    if (strlen($p_header['stored_filename']) != 0)
+    {
+      fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
+    }
+    if ($p_header['extra_len'] != 0)
+    {
+      fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
+    }
+    if ($p_header['comment_len'] != 0)
+    {
+      fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']);
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privWriteCentralHeader()
+  // Description :
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteCentralHeader", 'nb_entries='.$p_nb_entries.', size='.$p_size.', offset='.$p_offset.', comment="'.$p_comment.'"');
+    $v_result=1;
+
+    // ----- Packed data
+    $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries,
+                             $p_nb_entries, $p_size,
+                                                 $p_offset, strlen($p_comment));
+
+    // ----- Write the 22 bytes of the header in the zip file
+    fputs($this->zip_fd, $v_binary_data, 22);
+
+    // ----- Write the variable fields
+    if (strlen($p_comment) != 0)
+    {
+      fputs($this->zip_fd, $p_comment, strlen($p_comment));
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privList()
+  // Description :
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privList(&$p_list)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privList", "list");
+    $v_result=1;
+
+    // ----- Open the zip file
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+    if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
+    {
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+      return PclZip::errorCode();
+    }
+
+    // ----- Read the central directory informations
+    $v_central_dir = array();
+    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Go to beginning of Central Dir
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Offset : ".$v_central_dir['offset']."'");
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
+    @rewind($this->zip_fd);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
+    if (@fseek($this->zip_fd, $v_central_dir['offset']))
+    {
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+      return PclZip::errorCode();
+    }
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
+
+    // ----- Read each entry
+    for ($i=0; $i<$v_central_dir['entries']; $i++)
+    {
+      // ----- Read the file header
+      if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
+      {
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+        return $v_result;
+      }
+      $v_header['index'] = $i;
+
+      // ----- Get the only interesting attributes
+      $this->privConvertHeader2FileInfo($v_header, $p_list[$i]);
+      unset($v_header);
+    }
+
+    // ----- Close the zip file
+    $this->privCloseFd();
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privConvertHeader2FileInfo()
+  // Description :
+  //   This function takes the file informations from the central directory
+  //   entries and extract the interesting parameters that will be given back.
+  //   The resulting file infos are set in the array $p_info
+  //     $p_info['filename'] : Filename with full path. Given by user (add),
+  //                           extracted in the filesystem (extract).
+  //     $p_info['stored_filename'] : Stored filename in the archive.
+  //     $p_info['size'] = Size of the file.
+  //     $p_info['compressed_size'] = Compressed size of the file.
+  //     $p_info['mtime'] = Last modification date of the file.
+  //     $p_info['comment'] = Comment associated with the file.
+  //     $p_info['folder'] = true/false : indicates if the entry is a folder or not.
+  //     $p_info['status'] = status of the action on the file.
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privConvertHeader2FileInfo($p_header, &$p_info)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privConvertHeader2FileInfo", "Filename='".$p_header['filename']."'");
+    $v_result=1;
+
+    // ----- Get the interesting attributes
+    $p_info['filename'] = $p_header['filename'];
+    $p_info['stored_filename'] = $p_header['stored_filename'];
+    $p_info['size'] = $p_header['size'];
+    $p_info['compressed_size'] = $p_header['compressed_size'];
+    $p_info['mtime'] = $p_header['mtime'];
+    $p_info['comment'] = $p_header['comment'];
+    $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010);
+    $p_info['index'] = $p_header['index'];
+    $p_info['status'] = $p_header['status'];
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privExtractByRule()
+  // Description :
+  //   Extract a file or directory depending of rules (by index, by name, ...)
+  // Parameters :
+  //   $p_file_list : An array where will be placed the properties of each
+  //                  extracted file
+  //   $p_path : Path to add while writing the extracted files
+  //   $p_remove_path : Path to remove (from the file memorized path) while writing the
+  //                    extracted files. If the path does not match the file path,
+  //                    the file is extracted with its memorized path.
+  //                    $p_remove_path does not apply to 'list' mode.
+  //                    $p_path and $p_remove_path are commulative.
+  // Return Values :
+  //   1 on success,0 or less on error (see error code list)
+  // --------------------------------------------------------------------------------
+  function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privExtractByRule", "path='$p_path', remove_path='$p_remove_path', remove_all_path='".($p_remove_all_path?'true':'false')."'");
+    $v_result=1;
+
+    // ----- Check the path
+    if (($p_path == "") || ((substr($p_path, 0, 1) != "/") && (substr($p_path, 0, 3) != "../") && (substr($p_path,1,2)!=":/")))
+      $p_path = "./".$p_path;
+
+    // ----- Reduce the path last (and duplicated) '/'
+    if (($p_path != "./") && ($p_path != "/"))
+    {
+      // ----- Look for the path end '/'
+      while (substr($p_path, -1) == "/")
+      {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Destination path [$p_path] ends by '/'");
+        $p_path = substr($p_path, 0, strlen($p_path)-1);
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Modified to [$p_path]");
+      }
+    }
+
+    // ----- Look for path to remove format (should end by /)
+    if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/'))
+    {
+      $p_remove_path .= '/';
+    }
+    $p_remove_path_size = strlen($p_remove_path);
+
+    // ----- Open the zip file
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+    if (($v_result = $this->privOpenFd('rb')) != 1)
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Read the central directory informations
+    $v_central_dir = array();
+    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
+    {
+      // ----- Close the zip file
+      $this->privCloseFd();
+
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Start at beginning of Central Dir
+    $v_pos_entry = $v_central_dir['offset'];
+
+    // ----- Read each entry
+    $j_start = 0;
+    for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Read next file header entry : '$i'");
+
+      // ----- Read next Central dir entry
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Position before rewind : ".ftell($this->zip_fd)."'");
+      @rewind($this->zip_fd);
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Position after rewind : ".ftell($this->zip_fd)."'");
+      if (@fseek($this->zip_fd, $v_pos_entry))
+      {
+        // ----- Close the zip file
+        $this->privCloseFd();
+
+        // ----- Error log
+        PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
+
+        // ----- Return
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+        return PclZip::errorCode();
+      }
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position after fseek : ".ftell($this->zip_fd)."'");
+
+      // ----- Read the file header
+      $v_header = array();
+      if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
+      {
+        // ----- Close the zip file
+        $this->privCloseFd();
+
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+        return $v_result;
+      }
+
+      // ----- Store the index
+      $v_header['index'] = $i;
+
+      // ----- Store the file position
+      $v_pos_entry = ftell($this->zip_fd);
+
+      // ----- Look for the specific extract rules
+      $v_extract = false;
+
+      // ----- Look for extract by name rule
+      if (   (isset($p_options[PCLZIP_OPT_BY_NAME]))
+          && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByName'");
+
+          // ----- Look if the filename is in the list
+          for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_extract); $j++) {
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Compare with file '".$p_options[PCLZIP_OPT_BY_NAME][$j]."'");
+
+              // ----- Look for a directory
+              if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
+                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The searched item is a directory");
+
+                  // ----- Look if the directory is in the filename path
+                  if (   (strlen($v_header['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
+                      && (substr($v_header['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
+                      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The directory is in the file path");
+                      $v_extract = true;
+                  }
+              }
+              // ----- Look for a filename
+              elseif ($v_header['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
+                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The file is the right one.");
+                  $v_extract = true;
+              }
+          }
+      }
+
+      // ----- Look for extract by ereg rule
+      else if (   (isset($p_options[PCLZIP_OPT_BY_EREG]))
+               && ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract by ereg '".$p_options[PCLZIP_OPT_BY_EREG]."'");
+
+          if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) {
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
+              $v_extract = true;
+          }
+      }
+
+      // ----- Look for extract by preg rule
+      else if (   (isset($p_options[PCLZIP_OPT_BY_PREG]))
+               && ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByEreg'");
+
+          if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) {
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
+              $v_extract = true;
+          }
+      }
+
+      // ----- Look for extract by index rule
+      else if (   (isset($p_options[PCLZIP_OPT_BY_INDEX]))
+               && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByIndex'");
+          
+          // ----- Look if the index is in the list
+          for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_extract); $j++) {
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Look if index '$i' is in [".$p_options[PCLZIP_OPT_BY_INDEX][$j]['start'].",".$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']."]");
+
+              if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
+                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as part of an index range");
+                  $v_extract = true;
+              }
+              if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
+                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Do not look this index range for next loop");
+                  $j_start = $j+1;
+              }
+
+              if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
+                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Index range is greater than index, stop loop");
+                  break;
+              }
+          }
+      }
+
+      // ----- Look for no rule, which means extract all the archive
+      else {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with no rule (extract all)");
+          $v_extract = true;
+      }
+
+         // ----- Check compression method
+         if (   ($v_extract)
+             && (   ($v_header['compression'] != 8)
+                     && ($v_header['compression'] != 0))) {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unsupported compression method (".$v_header['compression'].")");
+          $v_header['status'] = 'unsupported_compression';
+
+          // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
+          if (   (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
+                     && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
+
+              PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_COMPRESSION,
+                                              "Filename '".$v_header['stored_filename']."' is "
+                                                          ."compressed by an unsupported compression "
+                                                          ."method (".$v_header['compression'].") ");
+
+              //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+              return PclZip::errorCode();
+                 }
+         }
+         
+         // ----- Check encrypted files
+         if (($v_extract) && (($v_header['flag'] & 1) == 1)) {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unsupported file encryption");
+          $v_header['status'] = 'unsupported_encryption';
+
+          // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
+          if (   (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
+                     && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
+
+              PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION,
+                                              "Unsupported encryption for "
+                                                          ." filename '".$v_header['stored_filename']
+                                                                  ."'");
+
+              //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+              return PclZip::errorCode();
+                 }
+         }
+
+      // ----- Look for real extraction
+      if (($v_extract) && ($v_header['status'] != 'ok')) {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "No need for extract");
+          $v_result = $this->privConvertHeader2FileInfo($v_header,
+                                                       $p_file_list[$v_nb_extracted++]);
+          if ($v_result != 1) {
+              $this->privCloseFd();
+              //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+              return $v_result;
+          }
+
+          $v_extract = false;
+      }
+      
+      // ----- Look for real extraction
+      if ($v_extract)
+      {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file '".$v_header['filename']."', index '$i'");
+
+        // ----- Go to the file position
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
+        @rewind($this->zip_fd);
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
+        if (@fseek($this->zip_fd, $v_header['offset']))
+        {
+          // ----- Close the zip file
+          $this->privCloseFd();
+
+          // ----- Error log
+          PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
+
+          // ----- Return
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+          return PclZip::errorCode();
+        }
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
+
+        // ----- Look for extraction as string
+        if ($p_options[PCLZIP_OPT_EXTRACT_AS_STRING]) {
+
+          // ----- Extracting the file
+          $v_result1 = $this->privExtractFileAsString($v_header, $v_string);
+          if ($v_result1 < 1) {
+            $this->privCloseFd();
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
+            return $v_result1;
+          }
+
+          // ----- Get the only interesting attributes
+          if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1)
+          {
+            // ----- Close the zip file
+            $this->privCloseFd();
+
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+            return $v_result;
+          }
+
+          // ----- Set the file content
+          $p_file_list[$v_nb_extracted]['content'] = $v_string;
+
+          // ----- Next extracted file
+          $v_nb_extracted++;
+          
+          // ----- Look for user callback abort
+          if ($v_result1 == 2) {
+               break;
+          }
+        }
+        // ----- Look for extraction in standard output
+        elseif (   (isset($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT]))
+                       && ($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) {
+          // ----- Extracting the file in standard output
+          $v_result1 = $this->privExtractFileInOutput($v_header, $p_options);
+          if ($v_result1 < 1) {
+            $this->privCloseFd();
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
+            return $v_result1;
+          }
+
+          // ----- Get the only interesting attributes
+          if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) {
+            $this->privCloseFd();
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+            return $v_result;
+          }
+
+          // ----- Look for user callback abort
+          if ($v_result1 == 2) {
+               break;
+          }
+        }
+        // ----- Look for normal extraction
+        else {
+          // ----- Extracting the file
+          $v_result1 = $this->privExtractFile($v_header,
+                                                     $p_path, $p_remove_path,
+                                                                                         $p_remove_all_path,
+                                                                                         $p_options);
+          if ($v_result1 < 1) {
+            $this->privCloseFd();
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
+            return $v_result1;
+          }
+
+          // ----- Get the only interesting attributes
+          if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1)
+          {
+            // ----- Close the zip file
+            $this->privCloseFd();
+
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+            return $v_result;
+          }
+
+          // ----- Look for user callback abort
+          if ($v_result1 == 2) {
+               break;
+          }
+        }
+      }
+    }
+
+    // ----- Close the zip file
+    $this->privCloseFd();
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privExtractFile()
+  // Description :
+  // Parameters :
+  // Return Values :
+  //
+  // 1 : ... ?
+  // PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback
+  // --------------------------------------------------------------------------------
+  function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFile', "path='$p_path', remove_path='$p_remove_path', remove_all_path='".($p_remove_all_path?'true':'false')."'");
+    $v_result=1;
+
+    // ----- Read the file header
+    if (($v_result = $this->privReadFileHeader($v_header)) != 1)
+    {
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'");
+
+    // ----- Check that the file header is coherent with $p_entry info
+    if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
+        // TBC
+    }
+
+    // ----- Look for all path to remove
+    if ($p_remove_all_path == true) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "All path is removed");
+        // ----- Get the basename of the path
+        $p_entry['filename'] = basename($p_entry['filename']);
+    }
+
+    // ----- Look for path to remove
+    else if ($p_remove_path != "")
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Look for some path to remove");
+      if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2)
+      {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The folder is the same as the removed path '".$p_entry['filename']."'");
+
+        // ----- Change the file status
+        $p_entry['status'] = "filtered";
+
+        // ----- Return
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+        return $v_result;
+      }
+
+      $p_remove_path_size = strlen($p_remove_path);
+      if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path)
+      {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found path '$p_remove_path' to remove in file '".$p_entry['filename']."'");
+
+        // ----- Remove the path
+        $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);
+
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Resulting file is '".$p_entry['filename']."'");
+      }
+    }
+
+    // ----- Add the path
+    if ($p_path != '')
+    {
+      $p_entry['filename'] = $p_path."/".$p_entry['filename'];
+    }
+
+    // ----- Look for pre-extract callback
+    if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_EXTRACT]."()') is defined for the extraction");
+
+      // ----- Generate a local information
+      $v_local_header = array();
+      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
+
+      // ----- Call the callback
+      // Here I do not use call_user_func() because I need to send a reference to the
+      // header.
+      eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
+      if ($v_result == 0) {
+        // ----- Change the file status
+        $p_entry['status'] = "skipped";
+        $v_result = 1;
+      }
+      
+      // ----- Look for abort result
+      if ($v_result == 2) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
+        // ----- This status is internal and will be changed in 'skipped'
+        $p_entry['status'] = "aborted";
+       $v_result = PCLZIP_ERR_USER_ABORTED;
+      }
+
+      // ----- Update the informations
+      // Only some fields can be modified
+      $p_entry['filename'] = $v_local_header['filename'];
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New filename is '".$p_entry['filename']."'");
+    }
+
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file (with path) '".$p_entry['filename']."', size '$v_header[size]'");
+
+    // ----- Look if extraction should be done
+    if ($p_entry['status'] == 'ok') {
+
+    // ----- Look for specific actions while the file exist
+    if (file_exists($p_entry['filename']))
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$p_entry['filename']."' already exists");
+
+      // ----- Look if file is a directory
+      if (is_dir($p_entry['filename']))
+      {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is a directory");
+
+        // ----- Change the file status
+        $p_entry['status'] = "already_a_directory";
+        
+        // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
+        // For historical reason first PclZip implementation does not stop
+        // when this kind of error occurs.
+        if (   (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
+                   && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
+            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
+
+            PclZip::privErrorLog(PCLZIP_ERR_ALREADY_A_DIRECTORY,
+                                            "Filename '".$p_entry['filename']."' is "
+                                                                ."already used by an existing directory");
+
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+            return PclZip::errorCode();
+               }
+      }
+      // ----- Look if file is write protected
+      else if (!is_writeable($p_entry['filename']))
+      {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is write protected");
+
+        // ----- Change the file status
+        $p_entry['status'] = "write_protected";
+
+        // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
+        // For historical reason first PclZip implementation does not stop
+        // when this kind of error occurs.
+        if (   (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
+                   && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
+            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
+
+            PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
+                                            "Filename '".$p_entry['filename']."' exists "
+                                                                ."and is write protected");
+
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+            return PclZip::errorCode();
+               }
+      }
+
+      // ----- Look if the extracted file is older
+      else if (filemtime($p_entry['filename']) > $p_entry['mtime'])
+      {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is newer (".date("l dS of F Y h:i:s A", filemtime($p_entry['filename'])).") than the extracted file (".date("l dS of F Y h:i:s A", $p_entry['mtime']).")");
+        // ----- Change the file status
+        if (   (isset($p_options[PCLZIP_OPT_REPLACE_NEWER]))
+                   && ($p_options[PCLZIP_OPT_REPLACE_NEWER]===true)) {
+            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_REPLACE_NEWER is selected, file will be replaced");
+               }
+               else {
+            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File will not be replaced");
+            $p_entry['status'] = "newer_exist";
+
+            // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
+            // For historical reason first PclZip implementation does not stop
+            // when this kind of error occurs.
+            if (   (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
+                       && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
+                //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
+
+                PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
+                                    "Newer version of '".$p_entry['filename']."' exists "
+                                           ."and option PCLZIP_OPT_REPLACE_NEWER is not selected");
+
+                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+                return PclZip::errorCode();
+                   }
+               }
+      }
+      else {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is older than the extrated one - will be replaced by the extracted one (".date("l dS of F Y h:i:s A", filemtime($p_entry['filename'])).") than the extracted file (".date("l dS of F Y h:i:s A", $p_entry['mtime']).")");
+      }
+    }
+
+    // ----- Check the directory availability and create it if necessary
+    else {
+      if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/'))
+        $v_dir_to_check = $p_entry['filename'];
+      else if (!strstr($p_entry['filename'], "/"))
+        $v_dir_to_check = "";
+      else
+        $v_dir_to_check = dirname($p_entry['filename']);
+
+      if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to create path for '".$p_entry['filename']."'");
+
+        // ----- Change the file status
+        $p_entry['status'] = "path_creation_fail";
+
+        // ----- Return
+        ////--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+        //return $v_result;
+        $v_result = 1;
+      }
+    }
+    }
+
+    // ----- Look if extraction should be done
+    if ($p_entry['status'] == 'ok') {
+
+      // ----- Do the extraction (if not a folder)
+      if (!(($p_entry['external']&0x00000010)==0x00000010))
+      {
+        // ----- Look for not compressed file
+        if ($p_entry['compression'] == 0) {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
+
+                 // ----- Opening destination file
+          if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0)
+          {
+            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode");
+
+            // ----- Change the file status
+            $p_entry['status'] = "write_error";
+
+            // ----- Return
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+            return $v_result;
+          }
+
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read '".$p_entry['size']."' bytes");
+
+          // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
+          $v_size = $p_entry['compressed_size'];
+          while ($v_size != 0)
+          {
+            $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
+            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read $v_read_size bytes");
+            $v_buffer = fread($this->zip_fd, $v_read_size);
+            $v_binary_data = pack('a'.$v_read_size, $v_buffer);
+            @fwrite($v_dest_file, $v_binary_data, $v_read_size);
+            $v_size -= $v_read_size;
+          }
+
+          // ----- Closing the destination file
+          fclose($v_dest_file);
+
+          // ----- Change the file mtime
+          touch($p_entry['filename'], $p_entry['mtime']);
+          
+
+        }
+        else {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file (Compression method ".$p_entry['compression'].")");
+          // ----- TBC
+          // Need to be finished
+          if (($p_entry['flag'] & 1) == 1) {
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File is encrypted");
+            /*
+              // ----- Read the encryption header
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read 12 encryption header bytes");
+              $v_encryption_header = @fread($this->zip_fd, 12);
+              
+              // ----- Read the encrypted & compressed file in a buffer
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read '".($p_entry['compressed_size']-12)."' compressed & encrypted bytes");
+              $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']-12);
+              
+              // ----- Decrypt the buffer
+              $this->privDecrypt($v_encryption_header, $v_buffer,
+                                            $p_entry['compressed_size']-12, $p_entry['crc']);
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Buffer is '".$v_buffer."'");
+              */
+          }
+          else {
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read '".$p_entry['compressed_size']."' compressed bytes");
+              // ----- Read the compressed file in a buffer (one shot)
+              $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
+          }
+          
+          // ----- Decompress the file
+          $v_file_content = @gzinflate($v_buffer);
+          unset($v_buffer);
+          if ($v_file_content === FALSE) {
+            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to inflate compressed file");
+
+            // ----- Change the file status
+            // TBC
+            $p_entry['status'] = "error";
+            
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+            return $v_result;
+          }
+          
+          // ----- Opening destination file
+          if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
+            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode");
+
+            // ----- Change the file status
+            $p_entry['status'] = "write_error";
+
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+            return $v_result;
+          }
+
+          // ----- Write the uncompressed data
+          @fwrite($v_dest_file, $v_file_content, $p_entry['size']);
+          unset($v_file_content);
+
+          // ----- Closing the destination file
+          @fclose($v_dest_file);
+
+          // ----- Change the file mtime
+          @touch($p_entry['filename'], $p_entry['mtime']);
+        }
+
+        // ----- Look for chmod option
+        if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "chmod option activated '".$p_options[PCLZIP_OPT_SET_CHMOD]."'");
+
+          // ----- Change the mode of the file
+          @chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]);
+        }
+
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
+      }
+    }
+
+       // ----- Change abort status
+       if ($p_entry['status'] == "aborted") {
+      $p_entry['status'] = "skipped";
+       }
+       
+    // ----- Look for post-extract callback
+    elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_EXTRACT]."()') is defined for the extraction");
+
+      // ----- Generate a local information
+      $v_local_header = array();
+      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
+
+      // ----- Call the callback
+      // Here I do not use call_user_func() because I need to send a reference to the
+      // header.
+      eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
+
+      // ----- Look for abort result
+      if ($v_result == 2) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
+       $v_result = PCLZIP_ERR_USER_ABORTED;
+      }
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privExtractFileInOutput()
+  // Description :
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privExtractFileInOutput(&$p_entry, &$p_options)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFileInOutput', "");
+    $v_result=1;
+
+    // ----- Read the file header
+    if (($v_result = $this->privReadFileHeader($v_header)) != 1) {
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'");
+
+    // ----- Check that the file header is coherent with $p_entry info
+    if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
+        // TBC
+    }
+
+    // ----- Look for pre-extract callback
+    if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_EXTRACT]."()') is defined for the extraction");
+
+      // ----- Generate a local information
+      $v_local_header = array();
+      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
+
+      // ----- Call the callback
+      // Here I do not use call_user_func() because I need to send a reference to the
+      // header.
+      eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
+      if ($v_result == 0) {
+        // ----- Change the file status
+        $p_entry['status'] = "skipped";
+        $v_result = 1;
+      }
+
+      // ----- Look for abort result
+      if ($v_result == 2) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
+        // ----- This status is internal and will be changed in 'skipped'
+        $p_entry['status'] = "aborted";
+       $v_result = PCLZIP_ERR_USER_ABORTED;
+      }
+
+      // ----- Update the informations
+      // Only some fields can be modified
+      $p_entry['filename'] = $v_local_header['filename'];
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New filename is '".$p_entry['filename']."'");
+    }
+
+    // ----- Trace
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file (with path) '".$p_entry['filename']."', size '$v_header[size]'");
+
+    // ----- Look if extraction should be done
+    if ($p_entry['status'] == 'ok') {
+
+      // ----- Do the extraction (if not a folder)
+      if (!(($p_entry['external']&0x00000010)==0x00000010)) {
+        // ----- Look for not compressed file
+        if ($p_entry['compressed_size'] == $p_entry['size']) {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes");
+
+          // ----- Read the file in a buffer (one shot)
+          $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
+
+          // ----- Send the file to the output
+          echo $v_buffer;
+          unset($v_buffer);
+        }
+        else {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file");
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Reading '".$p_entry['size']."' bytes");
+
+          // ----- Read the compressed file in a buffer (one shot)
+          $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
+          
+          // ----- Decompress the file
+          $v_file_content = gzinflate($v_buffer);
+          unset($v_buffer);
+
+          // ----- Send the file to the output
+          echo $v_file_content;
+          unset($v_file_content);
+        }
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
+      }
+    }
+
+       // ----- Change abort status
+       if ($p_entry['status'] == "aborted") {
+      $p_entry['status'] = "skipped";
+       }
+
+    // ----- Look for post-extract callback
+    elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_EXTRACT]."()') is defined for the extraction");
+
+      // ----- Generate a local information
+      $v_local_header = array();
+      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
+
+      // ----- Call the callback
+      // Here I do not use call_user_func() because I need to send a reference to the
+      // header.
+      eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
+
+      // ----- Look for abort result
+      if ($v_result == 2) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
+       $v_result = PCLZIP_ERR_USER_ABORTED;
+      }
+    }
+
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privExtractFileAsString()
+  // Description :
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privExtractFileAsString(&$p_entry, &$p_string)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFileAsString', "p_entry['filename']='".$p_entry['filename']."'");
+    $v_result=1;
+
+    // ----- Read the file header
+    $v_header = array();
+    if (($v_result = $this->privReadFileHeader($v_header)) != 1)
+    {
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'");
+
+    // ----- Check that the file header is coherent with $p_entry info
+    if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
+        // TBC
+    }
+
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file in string (with path) '".$p_entry['filename']."', size '$v_header[size]'");
+
+    // ----- Do the extraction (if not a folder)
+    if (!(($p_entry['external']&0x00000010)==0x00000010))
+    {
+      // ----- Look for not compressed file
+      if ($p_entry['compressed_size'] == $p_entry['size'])
+      {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes");
+
+        // ----- Reading the file
+        $p_string = @fread($this->zip_fd, $p_entry['compressed_size']);
+      }
+      else
+      {
+        // ----- Trace
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file");
+
+        // ----- Reading the file
+        $v_data = @fread($this->zip_fd, $p_entry['compressed_size']);
+        
+        // ----- Decompress the file
+        if (($p_string = @gzinflate($v_data)) === FALSE) {
+            // TBC
+        }
+      }
+
+      // ----- Trace
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
+    }
+    else {
+        // TBC : error : can not extract a folder in a string
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privReadFileHeader()
+  // Description :
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privReadFileHeader(&$p_header)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadFileHeader", "");
+    $v_result=1;
+
+    // ----- Read the 4 bytes signature
+    $v_binary_data = @fread($this->zip_fd, 4);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
+    $v_data = unpack('Vid', $v_binary_data);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
+
+    // ----- Check signature
+    if ($v_data['id'] != 0x04034b50)
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid File header");
+
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+      return PclZip::errorCode();
+    }
+
+    // ----- Read the first 42 bytes of the header
+    $v_binary_data = fread($this->zip_fd, 26);
+
+    // ----- Look for invalid block size
+    if (strlen($v_binary_data) != 26)
+    {
+      $p_header['filename'] = "";
+      $p_header['status'] = "invalid_header";
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid block size : ".strlen($v_binary_data));
+
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+      return PclZip::errorCode();
+    }
+
+    // ----- Extract the values
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Header : '".$v_binary_data."'");
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Header (Hex) : '".bin2hex($v_binary_data)."'");
+    $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);
+
+    // ----- Get filename
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "File name length : ".$v_data['filename_len']);
+    $p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Filename : \''.$p_header['filename'].'\'');
+
+    // ----- Get extra_fields
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extra field length : ".$v_data['extra_len']);
+    if ($v_data['extra_len'] != 0) {
+      $p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']);
+    }
+    else {
+      $p_header['extra'] = '';
+    }
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Extra field : \''.bin2hex($p_header['extra']).'\'');
+
+    // ----- Extract properties
+    $p_header['version_extracted'] = $v_data['version'];
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version need to extract : ('.$p_header['version_extracted'].') \''.($p_header['version_extracted']/10).'.'.($p_header['version_extracted']%10).'\'');
+    $p_header['compression'] = $v_data['compression'];
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compression method : \''.$p_header['compression'].'\'');
+    $p_header['size'] = $v_data['size'];
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size : \''.$p_header['size'].'\'');
+    $p_header['compressed_size'] = $v_data['compressed_size'];
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compressed Size : \''.$p_header['compressed_size'].'\'');
+    $p_header['crc'] = $v_data['crc'];
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'CRC : \''.sprintf("0x%X", $p_header['crc']).'\'');
+    $p_header['flag'] = $v_data['flag'];
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Flag : \''.$p_header['flag'].'\'');
+
+    // ----- Recuperate date in UNIX format
+    $p_header['mdate'] = $v_data['mdate'];
+    $p_header['mtime'] = $v_data['mtime'];
+    if ($p_header['mdate'] && $p_header['mtime'])
+    {
+      // ----- Extract time
+      $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
+      $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
+      $v_seconde = ($p_header['mtime'] & 0x001F)*2;
+
+      // ----- Extract date
+      $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
+      $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
+      $v_day = $p_header['mdate'] & 0x001F;
+
+      // ----- Get UNIX date format
+      $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
+
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
+    }
+    else
+    {
+      $p_header['mtime'] = time();
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date is actual : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
+    }
+
+    // TBC
+    //for(reset($v_data); $key = key($v_data); next($v_data)) {
+    //  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Attribut[$key] = ".$v_data[$key]);
+    //}
+
+    // ----- Set the stored filename
+    $p_header['stored_filename'] = $p_header['filename'];
+
+    // ----- Set the status field
+    $p_header['status'] = "ok";
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privReadCentralFileHeader()
+  // Description :
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privReadCentralFileHeader(&$p_header)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadCentralFileHeader", "");
+    $v_result=1;
+
+    // ----- Read the 4 bytes signature
+    $v_binary_data = @fread($this->zip_fd, 4);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
+    $v_data = unpack('Vid', $v_binary_data);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
+
+    // ----- Check signature
+    if ($v_data['id'] != 0x02014b50)
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid Central Dir File signature");
+
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+      return PclZip::errorCode();
+    }
+
+    // ----- Read the first 42 bytes of the header
+    $v_binary_data = fread($this->zip_fd, 42);
+
+    // ----- Look for invalid block size
+    if (strlen($v_binary_data) != 42)
+    {
+      $p_header['filename'] = "";
+      $p_header['status'] = "invalid_header";
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid block size : ".strlen($v_binary_data));
+
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+      return PclZip::errorCode();
+    }
+
+    // ----- Extract the values
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Header : '".$v_binary_data."'");
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Header (Hex) : '".bin2hex($v_binary_data)."'");
+    $p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data);
+
+    // ----- Get filename
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "File name length : ".$p_header['filename_len']);
+    if ($p_header['filename_len'] != 0)
+      $p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']);
+    else
+      $p_header['filename'] = '';
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Filename : \''.$p_header['filename'].'\'');
+
+    // ----- Get extra
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Extra length : ".$p_header['extra_len']);
+    if ($p_header['extra_len'] != 0)
+      $p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']);
+    else
+      $p_header['extra'] = '';
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Extra : \''.$p_header['extra'].'\'');
+
+    // ----- Get comment
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Comment length : ".$p_header['comment_len']);
+    if ($p_header['comment_len'] != 0)
+      $p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']);
+    else
+      $p_header['comment'] = '';
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Comment : \''.$p_header['comment'].'\'');
+
+    // ----- Extract properties
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version : \''.($p_header['version']/10).'.'.($p_header['version']%10).'\'');
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version need to extract : \''.($p_header['version_extracted']/10).'.'.($p_header['version_extracted']%10).'\'');
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Size : \''.$p_header['size'].'\'');
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Compressed Size : \''.$p_header['compressed_size'].'\'');
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'CRC : \''.sprintf("0x%X", $p_header['crc']).'\'');
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Flag : \''.$p_header['flag'].'\'');
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Offset : \''.$p_header['offset'].'\'');
+
+    // ----- Recuperate date in UNIX format
+    if ($p_header['mdate'] && $p_header['mtime'])
+    {
+      // ----- Extract time
+      $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
+      $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
+      $v_seconde = ($p_header['mtime'] & 0x001F)*2;
+
+      // ----- Extract date
+      $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
+      $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
+      $v_day = $p_header['mdate'] & 0x001F;
+
+      // ----- Get UNIX date format
+      $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
+
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
+    }
+    else
+    {
+      $p_header['mtime'] = time();
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Date is actual : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
+    }
+
+    // ----- Set the stored filename
+    $p_header['stored_filename'] = $p_header['filename'];
+
+    // ----- Set default status to ok
+    $p_header['status'] = 'ok';
+
+    // ----- Look if it is a directory
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Internal (Hex) : '".sprintf("Ox%04X", $p_header['internal'])."'");
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "External (Hex) : '".sprintf("Ox%04X", $p_header['external'])."' (".(($p_header['external']&0x00000010)==0x00000010?'is a folder':'is a file').')');
+    if (substr($p_header['filename'], -1) == '/') {
+      //$p_header['external'] = 0x41FF0010;
+      $p_header['external'] = 0x00000010;
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Force folder external : \''.sprintf("Ox%04X", $p_header['external']).'\'');
+    }
+
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Header of filename : \''.$p_header['filename'].'\'');
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privCheckFileHeaders()
+  // Description :
+  // Parameters :
+  // Return Values :
+  //   1 on success,
+  //   0 on error;
+  // --------------------------------------------------------------------------------
+  function privCheckFileHeaders(&$p_local_header, &$p_central_header)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCheckFileHeaders", "");
+    $v_result=1;
+
+       // ----- Check the static values
+       // TBC
+       if ($p_local_header['filename'] != $p_central_header['filename']) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "filename" : TBC To Be Completed');
+       }
+       if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "version_extracted" : TBC To Be Completed');
+       }
+       if ($p_local_header['flag'] != $p_central_header['flag']) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "flag" : TBC To Be Completed');
+       }
+       if ($p_local_header['compression'] != $p_central_header['compression']) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "compression" : TBC To Be Completed');
+       }
+       if ($p_local_header['mtime'] != $p_central_header['mtime']) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "mtime" : TBC To Be Completed');
+       }
+       if ($p_local_header['filename_len'] != $p_central_header['filename_len']) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "filename_len" : TBC To Be Completed');
+       }
+
+       // ----- Look for flag bit 3
+       if (($p_local_header['flag'] & 8) == 8) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Purpose bit flag bit 3 set !');
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'File size, compression size and crc found in central header');
+        $p_local_header['size'] = $p_central_header['size'];
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size : \''.$p_local_header['size'].'\'');
+        $p_local_header['compressed_size'] = $p_central_header['compressed_size'];
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compressed Size : \''.$p_local_header['compressed_size'].'\'');
+        $p_local_header['crc'] = $p_central_header['crc'];
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'CRC : \''.sprintf("0x%X", $p_local_header['crc']).'\'');
+       }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privReadEndCentralDir()
+  // Description :
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privReadEndCentralDir(&$p_central_dir)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadEndCentralDir", "");
+    $v_result=1;
+
+    // ----- Go to the end of the zip file
+    $v_size = filesize($this->zipname);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Size of the file :$v_size");
+    @fseek($this->zip_fd, $v_size);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position at end of zip file : \''.ftell($this->zip_fd).'\'');
+    if (@ftell($this->zip_fd) != $v_size)
+    {
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\'');
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+      return PclZip::errorCode();
+    }
+
+    // ----- First try : look if this is an archive with no commentaries (most of the time)
+    // in this case the end of central dir is at 22 bytes of the file end
+    $v_found = 0;
+    if ($v_size > 26) {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Look for central dir with no comment');
+      @fseek($this->zip_fd, $v_size-22);
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position after min central position : \''.ftell($this->zip_fd).'\'');
+      if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22))
+      {
+        // ----- Error log
+        PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
+
+        // ----- Return
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+        return PclZip::errorCode();
+      }
+
+      // ----- Read for bytes
+      $v_binary_data = @fread($this->zip_fd, 4);
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
+      $v_data = @unpack('Vid', $v_binary_data);
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
+
+      // ----- Check signature
+      if ($v_data['id'] == 0x06054b50) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found central dir at the default position.");
+        $v_found = 1;
+      }
+
+      $v_pos = ftell($this->zip_fd);
+    }
+
+    // ----- Go back to the maximum possible size of the Central Dir End Record
+    if (!$v_found) {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Start extended search of end central dir');
+      $v_maximum_size = 65557; // 0xFFFF + 22;
+      if ($v_maximum_size > $v_size)
+        $v_maximum_size = $v_size;
+      @fseek($this->zip_fd, $v_size-$v_maximum_size);
+      if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size))
+      {
+        // ----- Error log
+        PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
+
+        // ----- Return
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+        return PclZip::errorCode();
+      }
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position after max central position : \''.ftell($this->zip_fd).'\'');
+
+      // ----- Read byte per byte in order to find the signature
+      $v_pos = ftell($this->zip_fd);
+      $v_bytes = 0x00000000;
+      while ($v_pos < $v_size)
+      {
+        // ----- Read a byte
+        $v_byte = @fread($this->zip_fd, 1);
+
+        // -----  Add the byte
+        $v_bytes = ($v_bytes << 8) | Ord($v_byte);
+
+        // ----- Compare the bytes
+        if ($v_bytes == 0x504b0506)
+        {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Found End Central Dir signature at position : \''.ftell($this->zip_fd).'\'');
+          $v_pos++;
+          break;
+        }
+
+        $v_pos++;
+      }
+
+      // ----- Look if not found end of central dir
+      if ($v_pos == $v_size)
+      {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to find End of Central Dir Record signature");
+
+        // ----- Error log
+        PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature");
+
+        // ----- Return
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+        return PclZip::errorCode();
+      }
+    }
+
+    // ----- Read the first 18 bytes of the header
+    $v_binary_data = fread($this->zip_fd, 18);
+
+    // ----- Look for invalid block size
+    if (strlen($v_binary_data) != 18)
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));
+
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+      return PclZip::errorCode();
+    }
+
+    // ----- Extract the values
+    ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Central Dir Record : '".$v_binary_data."'");
+    ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Central Dir Record (Hex) : '".bin2hex($v_binary_data)."'");
+    $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
+
+    // ----- Check the global size
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Comment length : ".$v_data['comment_size']);
+    if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The central dir is not at the end of the archive. Some trailing bytes exists after the archive.");
+
+         // ----- Removed in release 2.2 see readme file
+         // The check of the file size is a little too strict.
+         // Some bugs where found when a zip is encrypted/decrypted with 'crypt'.
+         // While decrypted, zip has training 0 bytes
+         if (0) {
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT,
+                              'The central dir is not at the end of the archive.'
+                                                  .' Some trailing bytes exists after the archive.');
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+      return PclZip::errorCode();
+         }
+    }
+
+    // ----- Get comment
+    if ($v_data['comment_size'] != 0)
+      $p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']);
+    else
+      $p_central_dir['comment'] = '';
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Comment : \''.$p_central_dir['comment'].'\'');
+
+    $p_central_dir['entries'] = $v_data['entries'];
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Nb of entries : \''.$p_central_dir['entries'].'\'');
+    $p_central_dir['disk_entries'] = $v_data['disk_entries'];
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Nb of entries for this disk : \''.$p_central_dir['disk_entries'].'\'');
+    $p_central_dir['offset'] = $v_data['offset'];
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Offset of Central Dir : \''.$p_central_dir['offset'].'\'');
+    $p_central_dir['size'] = $v_data['size'];
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size of Central Dir : \''.$p_central_dir['size'].'\'');
+    $p_central_dir['disk'] = $v_data['disk'];
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Disk number : \''.$p_central_dir['disk'].'\'');
+    $p_central_dir['disk_start'] = $v_data['disk_start'];
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Start disk number : \''.$p_central_dir['disk_start'].'\'');
+
+    // TBC
+    //for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) {
+    //  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "central_dir[$key] = ".$p_central_dir[$key]);
+    //}
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privDeleteByRule()
+  // Description :
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privDeleteByRule(&$p_result_list, &$p_options)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDeleteByRule", "");
+    $v_result=1;
+    $v_list_detail = array();
+
+    // ----- Open the zip file
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+    if (($v_result=$this->privOpenFd('rb')) != 1)
+    {
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Read the central directory informations
+    $v_central_dir = array();
+    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
+    {
+      $this->privCloseFd();
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Go to beginning of File
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
+    @rewind($this->zip_fd);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
+
+    // ----- Scan all the files
+    // ----- Start at beginning of Central Dir
+    $v_pos_entry = $v_central_dir['offset'];
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
+    @rewind($this->zip_fd);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
+    if (@fseek($this->zip_fd, $v_pos_entry))
+    {
+      // ----- Close the zip file
+      $this->privCloseFd();
+
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+      return PclZip::errorCode();
+    }
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
+
+    // ----- Read each entry
+    $v_header_list = array();
+    $j_start = 0;
+    for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Read next file header entry (index '$i')");
+
+      // ----- Read the file header
+      $v_header_list[$v_nb_extracted] = array();
+      if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1)
+      {
+        // ----- Close the zip file
+        $this->privCloseFd();
+
+        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+        return $v_result;
+      }
+
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename (index '$i') : '".$v_header_list[$v_nb_extracted]['stored_filename']."'");
+
+      // ----- Store the index
+      $v_header_list[$v_nb_extracted]['index'] = $i;
+
+      // ----- Look for the specific extract rules
+      $v_found = false;
+
+      // ----- Look for extract by name rule
+      if (   (isset($p_options[PCLZIP_OPT_BY_NAME]))
+          && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByName'");
+
+          // ----- Look if the filename is in the list
+          for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_found); $j++) {
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Compare with file '".$p_options[PCLZIP_OPT_BY_NAME][$j]."'");
+
+              // ----- Look for a directory
+              if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
+                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The searched item is a directory");
+
+                  // ----- Look if the directory is in the filename path
+                  if (   (strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
+                      && (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
+                      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The directory is in the file path");
+                      $v_found = true;
+                  }
+                  elseif (   (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */
+                          && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
+                      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The entry is the searched directory");
+                      $v_found = true;
+                  }
+              }
+              // ----- Look for a filename
+              elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
+                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The file is the right one.");
+                  $v_found = true;
+              }
+          }
+      }
+
+      // ----- Look for extract by ereg rule
+      else if (   (isset($p_options[PCLZIP_OPT_BY_EREG]))
+               && ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract by ereg '".$p_options[PCLZIP_OPT_BY_EREG]."'");
+
+          if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
+              $v_found = true;
+          }
+      }
+
+      // ----- Look for extract by preg rule
+      else if (   (isset($p_options[PCLZIP_OPT_BY_PREG]))
+               && ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByEreg'");
+
+          if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
+              $v_found = true;
+          }
+      }
+
+      // ----- Look for extract by index rule
+      else if (   (isset($p_options[PCLZIP_OPT_BY_INDEX]))
+               && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
+          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByIndex'");
+
+          // ----- Look if the index is in the list
+          for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_found); $j++) {
+              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Look if index '$i' is in [".$p_options[PCLZIP_OPT_BY_INDEX][$j]['start'].",".$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']."]");
+
+              if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
+                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as part of an index range");
+                  $v_found = true;
+              }
+              if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
+                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Do not look this index range for next loop");
+                  $j_start = $j+1;
+              }
+
+              if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
+                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Index range is greater than index, stop loop");
+                  break;
+              }
+          }
+      }
+
+      // ----- Look for deletion
+      if ($v_found)
+      {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_header_list[$v_nb_extracted]['stored_filename']."', index '$i' need to be deleted");
+        unset($v_header_list[$v_nb_extracted]);
+      }
+      else
+      {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_header_list[$v_nb_extracted]['stored_filename']."', index '$i' will not be deleted");
+        $v_nb_extracted++;
+      }
+    }
+
+    // ----- Look if something need to be deleted
+    if ($v_nb_extracted > 0) {
+
+        // ----- Creates a temporay file
+        $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
+
+        // ----- Creates a temporary zip archive
+        $v_temp_zip = new PclZip($v_zip_temp_name);
+
+        // ----- Open the temporary zip file in write mode
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary write mode");
+        if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) {
+            $this->privCloseFd();
+
+            // ----- Return
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+            return $v_result;
+        }
+
+        // ----- Look which file need to be kept
+        for ($i=0; $i<sizeof($v_header_list); $i++) {
+            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Keep entry index '$i' : '".$v_header_list[$i]['filename']."'");
+
+            // ----- Calculate the position of the header
+            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset='". $v_header_list[$i]['offset']."'");
+            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
+            @rewind($this->zip_fd);
+            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
+            if (@fseek($this->zip_fd,  $v_header_list[$i]['offset'])) {
+                // ----- Close the zip file
+                $this->privCloseFd();
+                $v_temp_zip->privCloseFd();
+                @unlink($v_zip_temp_name);
+
+                // ----- Error log
+                PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
+
+                // ----- Return
+                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+                return PclZip::errorCode();
+            }
+            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
+
+            // ----- Read the file header
+            $v_local_header = array();
+            if (($v_result = $this->privReadFileHeader($v_local_header)) != 1) {
+                // ----- Close the zip file
+                $this->privCloseFd();
+                $v_temp_zip->privCloseFd();
+                @unlink($v_zip_temp_name);
+
+                // ----- Return
+                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+                return $v_result;
+            }
+            
+            // ----- Check that local file header is same as central file header
+            if ($this->privCheckFileHeaders($v_local_header,
+                                                       $v_header_list[$i]) != 1) {
+                // TBC
+            }
+            unset($v_local_header);
+
+            // ----- Write the file header
+            if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) {
+                // ----- Close the zip file
+                $this->privCloseFd();
+                $v_temp_zip->privCloseFd();
+                @unlink($v_zip_temp_name);
+
+                // ----- Return
+                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+                return $v_result;
+            }
+            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset for this file is '".$v_header_list[$i]['offset']."'");
+
+            // ----- Read/write the data block
+            if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) {
+                // ----- Close the zip file
+                $this->privCloseFd();
+                $v_temp_zip->privCloseFd();
+                @unlink($v_zip_temp_name);
+
+                // ----- Return
+                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+                return $v_result;
+            }
+        }
+
+        // ----- Store the offset of the central dir
+        $v_offset = @ftell($v_temp_zip->zip_fd);
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "New offset of central dir : $v_offset");
+
+        // ----- Re-Create the Central Dir files header
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Creates the new central directory");
+        for ($i=0; $i<sizeof($v_header_list); $i++) {
+            // ----- Create the file header
+            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset of file : ".$v_header_list[$i]['offset']);
+            if (($v_result = $v_temp_zip->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
+                $v_temp_zip->privCloseFd();
+                $this->privCloseFd();
+                @unlink($v_zip_temp_name);
+
+                // ----- Return
+                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+                return $v_result;
+            }
+
+            // ----- Transform the header to a 'usable' info
+            $v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
+        }
+
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Creates the central directory footer");
+
+        // ----- Zip file comment
+        $v_comment = '';
+        if (isset($p_options[PCLZIP_OPT_COMMENT])) {
+          $v_comment = $p_options[PCLZIP_OPT_COMMENT];
+        }
+
+        // ----- Calculate the size of the central header
+        $v_size = @ftell($v_temp_zip->zip_fd)-$v_offset;
+
+        // ----- Create the central dir footer
+        if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) {
+            // ----- Reset the file list
+            unset($v_header_list);
+            $v_temp_zip->privCloseFd();
+            $this->privCloseFd();
+            @unlink($v_zip_temp_name);
+
+            // ----- Return
+            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+            return $v_result;
+        }
+
+        // ----- Close
+        $v_temp_zip->privCloseFd();
+        $this->privCloseFd();
+
+        // ----- Delete the zip file
+        // TBC : I should test the result ...
+        @unlink($this->zipname);
+
+        // ----- Rename the temporary file
+        // TBC : I should test the result ...
+        //@rename($v_zip_temp_name, $this->zipname);
+        PclZipUtilRename($v_zip_temp_name, $this->zipname);
+    
+        // ----- Destroy the temporary archive
+        unset($v_temp_zip);
+    }
+    
+    // ----- Remove every files : reset the file
+    else if ($v_central_dir['entries'] != 0) {
+        $this->privCloseFd();
+
+        if (($v_result = $this->privOpenFd('wb')) != 1) {
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+          return $v_result;
+        }
+
+        if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) {
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+          return $v_result;
+        }
+
+        $this->privCloseFd();
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privDirCheck()
+  // Description :
+  //   Check if a directory exists, if not it creates it and all the parents directory
+  //   which may be useful.
+  // Parameters :
+  //   $p_dir : Directory path to check.
+  // Return Values :
+  //    1 : OK
+  //   -1 : Unable to create directory
+  // --------------------------------------------------------------------------------
+  function privDirCheck($p_dir, $p_is_dir=false)
+  {
+    $v_result = 1;
+
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDirCheck", "entry='$p_dir', is_dir='".($p_is_dir?"true":"false")."'");
+
+    // ----- Remove the final '/'
+    if (($p_is_dir) && (substr($p_dir, -1)=='/'))
+    {
+      $p_dir = substr($p_dir, 0, strlen($p_dir)-1);
+    }
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Looking for entry '$p_dir'");
+
+    // ----- Check the directory availability
+    if ((is_dir($p_dir)) || ($p_dir == ""))
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, "'$p_dir' is a directory");
+      return 1;
+    }
+
+    // ----- Extract parent directory
+    $p_parent_dir = dirname($p_dir);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Parent directory is '$p_parent_dir'");
+
+    // ----- Just a check
+    if ($p_parent_dir != $p_dir)
+    {
+      // ----- Look for parent directory
+      if ($p_parent_dir != "")
+      {
+        if (($v_result = $this->privDirCheck($p_parent_dir)) != 1)
+        {
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+          return $v_result;
+        }
+      }
+    }
+
+    // ----- Create the directory
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Create directory '$p_dir'");
+    if (!@mkdir($p_dir, 0777))
+    {
+      // ----- Error log
+      PclZip::privErrorLog(PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'");
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+      return PclZip::errorCode();
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result, "Directory '$p_dir' created");
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privMerge()
+  // Description :
+  //   If $p_archive_to_add does not exist, the function exit with a success result.
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privMerge(&$p_archive_to_add)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privMerge", "archive='".$p_archive_to_add->zipname."'");
+    $v_result=1;
+
+    // ----- Look if the archive_to_add exists
+    if (!is_file($p_archive_to_add->zipname))
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive to add does not exist. End of merge.");
+
+      // ----- Nothing to merge, so merge is a success
+      $v_result = 1;
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Look if the archive exists
+    if (!is_file($this->zipname))
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive does not exist, duplicate the archive_to_add.");
+
+      // ----- Do a duplicate
+      $v_result = $this->privDuplicate($p_archive_to_add->zipname);
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Open the zip file
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+    if (($v_result=$this->privOpenFd('rb')) != 1)
+    {
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Read the central directory informations
+    $v_central_dir = array();
+    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
+    {
+      $this->privCloseFd();
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Go to beginning of File
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in zip : ".ftell($this->zip_fd)."'");
+    @rewind($this->zip_fd);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in zip : ".ftell($this->zip_fd)."'");
+
+    // ----- Open the archive_to_add file
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open archive_to_add in binary read mode");
+    if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1)
+    {
+      $this->privCloseFd();
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Read the central directory informations
+    $v_central_dir_to_add = array();
+    if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1)
+    {
+      $this->privCloseFd();
+      $p_archive_to_add->privCloseFd();
+
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Go to beginning of File
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in archive_to_add : ".ftell($p_archive_to_add->zip_fd)."'");
+    @rewind($p_archive_to_add->zip_fd);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in archive_to_add : ".ftell($p_archive_to_add->zip_fd)."'");
+
+    // ----- Creates a temporay file
+    $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
+
+    // ----- Open the temporary file in write mode
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+    if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
+    {
+      $this->privCloseFd();
+      $p_archive_to_add->privCloseFd();
+
+      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+      return PclZip::errorCode();
+    }
+
+    // ----- Copy the files from the archive to the temporary file
+    // TBC : Here I should better append the file and go back to erase the central dir
+    $v_size = $v_central_dir['offset'];
+    while ($v_size != 0)
+    {
+      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+      $v_buffer = fread($this->zip_fd, $v_read_size);
+      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
+      $v_size -= $v_read_size;
+    }
+
+    // ----- Copy the files from the archive_to_add into the temporary file
+    $v_size = $v_central_dir_to_add['offset'];
+    while ($v_size != 0)
+    {
+      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+      $v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size);
+      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
+      $v_size -= $v_read_size;
+    }
+
+    // ----- Store the offset of the central dir
+    $v_offset = @ftell($v_zip_temp_fd);
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "New offset of central dir : $v_offset");
+
+    // ----- Copy the block of file headers from the old archive
+    $v_size = $v_central_dir['size'];
+    while ($v_size != 0)
+    {
+      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+      $v_buffer = @fread($this->zip_fd, $v_read_size);
+      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
+      $v_size -= $v_read_size;
+    }
+
+    // ----- Copy the block of file headers from the archive_to_add
+    $v_size = $v_central_dir_to_add['size'];
+    while ($v_size != 0)
+    {
+      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+      $v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size);
+      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
+      $v_size -= $v_read_size;
+    }
+
+    // ----- Merge the file comments
+    $v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment'];
+
+    // ----- Calculate the size of the (new) central header
+    $v_size = @ftell($v_zip_temp_fd)-$v_offset;
+
+    // ----- Swap the file descriptor
+    // Here is a trick : I swap the temporary fd with the zip fd, in order to use
+    // the following methods on the temporary fil and not the real archive fd
+    $v_swap = $this->zip_fd;
+    $this->zip_fd = $v_zip_temp_fd;
+    $v_zip_temp_fd = $v_swap;
+
+    // ----- Create the central dir footer
+    if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1)
+    {
+      $this->privCloseFd();
+      $p_archive_to_add->privCloseFd();
+      @fclose($v_zip_temp_fd);
+      $this->zip_fd = null;
+
+      // ----- Reset the file list
+      unset($v_header_list);
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Swap back the file descriptor
+    $v_swap = $this->zip_fd;
+    $this->zip_fd = $v_zip_temp_fd;
+    $v_zip_temp_fd = $v_swap;
+
+    // ----- Close
+    $this->privCloseFd();
+    $p_archive_to_add->privCloseFd();
+
+    // ----- Close the temporary file
+    @fclose($v_zip_temp_fd);
+
+    // ----- Delete the zip file
+    // TBC : I should test the result ...
+    @unlink($this->zipname);
+
+    // ----- Rename the temporary file
+    // TBC : I should test the result ...
+    //@rename($v_zip_temp_name, $this->zipname);
+    PclZipUtilRename($v_zip_temp_name, $this->zipname);
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privDuplicate()
+  // Description :
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privDuplicate($p_archive_filename)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDuplicate", "archive_filename='$p_archive_filename'");
+    $v_result=1;
+
+    // ----- Look if the $p_archive_filename exists
+    if (!is_file($p_archive_filename))
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive to duplicate does not exist. End of duplicate.");
+
+      // ----- Nothing to duplicate, so duplicate is a success.
+      $v_result = 1;
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Open the zip file
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+    if (($v_result=$this->privOpenFd('wb')) != 1)
+    {
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+      return $v_result;
+    }
+
+    // ----- Open the temporary file in write mode
+    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+    if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0)
+    {
+      $this->privCloseFd();
+
+      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode');
+
+      // ----- Return
+      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+      return PclZip::errorCode();
+    }
+
+    // ----- Copy the files from the archive to the temporary file
+    // TBC : Here I should better append the file and go back to erase the central dir
+    $v_size = filesize($p_archive_filename);
+    while ($v_size != 0)
+    {
+      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read $v_read_size bytes");
+      $v_buffer = fread($v_zip_temp_fd, $v_read_size);
+      @fwrite($this->zip_fd, $v_buffer, $v_read_size);
+      $v_size -= $v_read_size;
+    }
+
+    // ----- Close
+    $this->privCloseFd();
+
+    // ----- Close the temporary file
+    @fclose($v_zip_temp_fd);
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privErrorLog()
+  // Description :
+  // Parameters :
+  // --------------------------------------------------------------------------------
+  function privErrorLog($p_error_code=0, $p_error_string='')
+  {
+    if (PCLZIP_ERROR_EXTERNAL == 1) {
+      PclError($p_error_code, $p_error_string);
+    }
+    else {
+      $this->error_code = $p_error_code;
+      $this->error_string = $p_error_string;
+    }
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privErrorReset()
+  // Description :
+  // Parameters :
+  // --------------------------------------------------------------------------------
+  function privErrorReset()
+  {
+    if (PCLZIP_ERROR_EXTERNAL == 1) {
+      PclErrorReset();
+    }
+    else {
+      $this->error_code = 0;
+      $this->error_string = '';
+    }
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : privDecrypt()
+  // Description :
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function privDecrypt($p_encryption_header, &$p_buffer, $p_size, $p_crc)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privDecrypt', "size=".$p_size."");
+    $v_result=1;
+    
+    // ----- To Be Modified ;-)
+    $v_pwd = "test";
+    
+    $p_buffer = PclZipUtilZipDecrypt($p_buffer, $p_size, $p_encryption_header,
+                                        $p_crc, $v_pwd);
+    
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  }
+  // End of class
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : PclZipUtilPathReduction()
+  // Description :
+  // Parameters :
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function PclZipUtilPathReduction($p_dir)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilPathReduction", "dir='$p_dir'");
+    $v_result = "";
+
+    // ----- Look for not empty path
+    if ($p_dir != "")
+    {
+      // ----- Explode path by directory names
+      $v_list = explode("/", $p_dir);
+
+      // ----- Study directories from last to first
+      for ($i=sizeof($v_list)-1; $i>=0; $i--)
+      {
+        // ----- Look for current path
+        if ($v_list[$i] == ".")
+        {
+          // ----- Ignore this directory
+          // Should be the first $i=0, but no check is done
+        }
+        else if ($v_list[$i] == "..")
+        {
+          // ----- Ignore it and ignore the $i-1
+          $i--;
+        }
+        else if (($v_list[$i] == "") && ($i!=(sizeof($v_list)-1)) && ($i!=0))
+        {
+          // ----- Ignore only the double '//' in path,
+          // but not the first and last '/'
+        }
+        else
+        {
+          $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:"");
+        }
+      }
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : PclZipUtilPathInclusion()
+  // Description :
+  //   This function indicates if the path $p_path is under the $p_dir tree. Or,
+  //   said in an other way, if the file or sub-dir $p_path is inside the dir
+  //   $p_dir.
+  //   The function indicates also if the path is exactly the same as the dir.
+  //   This function supports path with duplicated '/' like '//', but does not
+  //   support '.' or '..' statements.
+  // Parameters :
+  // Return Values :
+  //   0 if $p_path is not inside directory $p_dir
+  //   1 if $p_path is inside directory $p_dir
+  //   2 if $p_path is exactly the same as $p_dir
+  // --------------------------------------------------------------------------------
+  function PclZipUtilPathInclusion($p_dir, $p_path)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilPathInclusion", "dir='$p_dir', path='$p_path'");
+    $v_result = 1;
+
+    // ----- Explode dir and path by directory separator
+    $v_list_dir = explode("/", $p_dir);
+    $v_list_dir_size = sizeof($v_list_dir);
+    $v_list_path = explode("/", $p_path);
+    $v_list_path_size = sizeof($v_list_path);
+
+    // ----- Study directories paths
+    $i = 0;
+    $j = 0;
+    while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Working on dir($i)='".$v_list_dir[$i]."' and path($j)='".$v_list_path[$j]."'");
+
+      // ----- Look for empty dir (path reduction)
+      if ($v_list_dir[$i] == '') {
+        $i++;
+        continue;
+      }
+      if ($v_list_path[$j] == '') {
+        $j++;
+        continue;
+      }
+
+      // ----- Compare the items
+      if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != ''))  {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Items ($i,$j) are different");
+        $v_result = 0;
+      }
+
+      // ----- Next items
+      $i++;
+      $j++;
+    }
+
+    // ----- Look if everything seems to be the same
+    if ($v_result) {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Look for tie break");
+      // ----- Skip all the empty items
+      while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++;
+      while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++;
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Looking on dir($i)='".($i < $v_list_dir_size?$v_list_dir[$i]:'')."' and path($j)='".($j < $v_list_path_size?$v_list_path[$j]:'')."'");
+
+      if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
+        // ----- There are exactly the same
+        $v_result = 2;
+      }
+      else if ($i < $v_list_dir_size) {
+        // ----- The path is shorter than the dir
+        $v_result = 0;
+      }
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : PclZipUtilCopyBlock()
+  // Description :
+  // Parameters :
+  //   $p_mode : read/write compression mode
+  //             0 : src & dest normal
+  //             1 : src gzip, dest normal
+  //             2 : src normal, dest gzip
+  //             3 : src & dest gzip
+  // Return Values :
+  // --------------------------------------------------------------------------------
+  function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilCopyBlock", "size=$p_size, mode=$p_mode");
+    $v_result = 1;
+
+    if ($p_mode==0)
+    {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Src offset before read :".(@ftell($p_src)));
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Dest offset before write :".(@ftell($p_dest)));
+      while ($p_size != 0)
+      {
+        $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+        $v_buffer = @fread($p_src, $v_read_size);
+        @fwrite($p_dest, $v_buffer, $v_read_size);
+        $p_size -= $v_read_size;
+      }
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Src offset after read :".(@ftell($p_src)));
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Dest offset after write :".(@ftell($p_dest)));
+    }
+    else if ($p_mode==1)
+    {
+      while ($p_size != 0)
+      {
+        $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+        $v_buffer = @gzread($p_src, $v_read_size);
+        @fwrite($p_dest, $v_buffer, $v_read_size);
+        $p_size -= $v_read_size;
+      }
+    }
+    else if ($p_mode==2)
+    {
+      while ($p_size != 0)
+      {
+        $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+        $v_buffer = @fread($p_src, $v_read_size);
+        @gzwrite($p_dest, $v_buffer, $v_read_size);
+        $p_size -= $v_read_size;
+      }
+    }
+    else if ($p_mode==3)
+    {
+      while ($p_size != 0)
+      {
+        $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+        $v_buffer = @gzread($p_src, $v_read_size);
+        @gzwrite($p_dest, $v_buffer, $v_read_size);
+        $p_size -= $v_read_size;
+      }
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : PclZipUtilRename()
+  // Description :
+  //   This function tries to do a simple rename() function. If it fails, it
+  //   tries to copy the $p_src file in a new $p_dest file and then unlink the
+  //   first one.
+  // Parameters :
+  //   $p_src : Old filename
+  //   $p_dest : New filename
+  // Return Values :
+  //   1 on success, 0 on failure.
+  // --------------------------------------------------------------------------------
+  function PclZipUtilRename($p_src, $p_dest)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilRename", "source=$p_src, destination=$p_dest");
+    $v_result = 1;
+
+    // ----- Try to rename the files
+    if (!@rename($p_src, $p_dest)) {
+      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to rename file, try copy+unlink");
+
+      // ----- Try to copy & unlink the src
+      if (!@copy($p_src, $p_dest)) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to copy file");
+        $v_result = 0;
+      }
+      else if (!@unlink($p_src)) {
+        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to unlink old filename");
+        $v_result = 0;
+      }
+    }
+
+    // ----- Return
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : PclZipUtilOptionText()
+  // Description :
+  //   Translate option value in text. Mainly for debug purpose.
+  // Parameters :
+  //   $p_option : the option value.
+  // Return Values :
+  //   The option text value.
+  // --------------------------------------------------------------------------------
+  function PclZipUtilOptionText($p_option)
+  {
+    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilOptionText", "option='".$p_option."'");
+    
+    $v_list = get_defined_constants();
+    for (reset($v_list); $v_key = key($v_list); next($v_list)) {
+         $v_prefix = substr($v_key, 0, 10);
+         if ((($v_prefix == 'PCLZIP_OPT') || ($v_prefix == 'PCLZIP_CB_'))
+             && ($v_list[$v_key] == $p_option)) {
+          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_key);
+          return $v_key;
+           }
+    }
+    
+    $v_result = 'Unknown';
+
+    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+    return $v_result;
+  }
+  // --------------------------------------------------------------------------------
+
+  // --------------------------------------------------------------------------------
+  // Function : PclZipUtilTranslateWinPath()
+  // Description :
+  //   Translate windows path by replacing '\' by '/' and optionally removing
+  //   drive letter.
+  // Parameters :
+  //   $p_path : path to translate.
+  //   $p_remove_disk_letter : true | false
+  // Return Values :
+  //   The path translated.
+  // --------------------------------------------------------------------------------
+  function PclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter=true)
+  {
+    if (stristr(php_uname(), 'windows')) {
+      // ----- Look for potential disk letter
+      if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) {
+          $p_path = substr($p_path, $v_position+1);
+      }
+      // ----- Change potential windows directory separator
+      if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
+          $p_path = strtr($p_path, '\\', '/');
+      }
+    }
+    return $p_path;
+  }
+  // --------------------------------------------------------------------------------
+
+
+?>
\ No newline at end of file
diff --git a/include/classes/phpmailer/atutormailer.class.php b/include/classes/phpmailer/atutormailer.class.php
new file mode 100644 (file)
index 0000000..d1b6bd3
--- /dev/null
@@ -0,0 +1,144 @@
+<?php
+/************************************************************************/
+/* ATutor                                                               */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton */
+/* http://atutor.ca                                                     */
+/*                                                                      */
+/* 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.                        */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+require(dirname(__FILE__) . '/class.phpmailer.php');
+
+/**
+* ATutorMailer extends PHPMailer and sets all the default values
+* that are common for ATutor.
+* @access  public
+* @see     include/classes/phpmailer/class.phpmailer.php
+* @since   ATutor 1.4.1
+* @author  Joel Kronenberg
+*/
+class ATutorMailer extends PHPMailer {
+
+       /**
+       * The constructor sets whether to use SMTP or Sendmail depending
+       * on the value of MAIL_USE_SMTP defined in the config.inc.php file.
+       * @access  public
+       * @since   ATutor 1.4.1
+       * @author  Joel Kronenberg
+       */
+       function ATutorMailer() {
+               if (MAIL_USE_SMTP) {
+                       $this->IsSMTP(); // set mailer to use SMTP
+                       $this->Host = ini_get('SMTP');  // specify main and backup server
+               } else {
+                       $this->IsSendmail(); // use sendmail
+                       $this->Sendmail = ini_get('sendmail_path');
+               }
+
+               $this->SMTPAuth = false;  // turn on SMTP authentication
+               $this->IsHTML(false);
+
+               // send the email in the current encoding:
+               global $myLang;
+               $this->CharSet = $myLang->getCharacterSet();
+       }
+
+       /**
+       * Appends a custom ATutor footer to all outgoing email then sends the email.
+       * If mail_queue is enabled then instead of sending the mail out right away, it 
+       * places it in the database and waits for the cron to send it using SendQueue().
+       * The mail queue does not support reply-to, or attachments, and converts all BCCs
+       * to regular To emails.
+       * @access  public
+       * @return  boolean      whether or not the mail was sent (or queued) successfully.
+       * @see     parent::send()
+       * @since   ATutor 1.4.1
+       * @author  Joel Kronenberg
+       */
+       function Send() {
+               global $_config;
+
+               // attach the ATutor footer to the body first:
+               $this->Body .=  "\n\n".'----------------------------------------------'."\n";
+               $this->Body .= _AT('sent_via_atutor', AT_BASE_HREF);
+               if ($_SESSION['course_id'] > 0) {
+                       $this->Body .= 'login.php?course='.$_SESSION['course_id'].' | ' . $_SESSION['course_title'];
+               }
+
+               $this->Body .= "\n"._AT('atutor_home').': http://atutor.ca';
+
+               // if this email has been queued then don't send it. instead insert it in the db
+               // for each bcc or to or cc
+               if ($_config['enable_mail_queue'] && !$this->attachment) {
+                       global $db;
+                       for ($i = 0; $i < count($this->to); $i++) {
+                               $this->QueueMail(addslashes($this->to[$i][0]), addslashes($this->to[$i][1]), addslashes($this->From), addslashes($this->FromName), addslashes($this->Subject), addslashes($this->Body));
+                       }
+                       for($i = 0; $i < count($this->cc); $i++) {
+                               $this->QueueMail(addslashes($this->cc[$i][0]), addslashes($this->cc[$i][1]), addslashes($this->From), addslashes($this->FromName), addslashes($this->Subject), addslashes($this->Body));
+                       }
+                       for($i = 0; $i < count($this->bcc); $i++) {
+                               $this->QueueMail(addslashes($this->bcc[$i][0]), addslashes($this->bcc[$i][1]), addslashes($this->From), addslashes($this->FromName), addslashes($this->Subject), addslashes($this->Body));
+                       }
+                       return true;
+               } else {
+                       return parent::Send();
+               }
+       }
+
+       /**
+       * Adds the mail to the queue.
+       * @access private
+       * @return boolean whether the mail was queued successfully.
+       * @since  ATutor 1.5.3
+       * @author Joel Kronenberg
+       */
+       function QueueMail($to_email, $to_name, $from_email, $from_name, $subject, $body) {
+               global $db;
+               $sql = "INSERT INTO ".TABLE_PREFIX."mail_queue VALUES (NULL, '$to_email', '$to_name', '$from_email', '$from_name', '".addslashes($this->CharSet)."', '$subject', '$body')";
+               return mysql_query($sql, $db);
+       }
+
+       /**
+       * Sends all the queued mail. Called by ./admin/cron.php.
+       * @access public
+       * @return void
+       * @since ATutor 1.5.3
+       * @author Joel Kronenberg
+       */
+       function SendQueue() {
+               global $db;
+
+               $mail_ids = '';
+               $sql = "SELECT * FROM ".TABLE_PREFIX."mail_queue";
+               $result = mysql_query($sql, $db);
+               while ($row = mysql_fetch_assoc($result)) {
+                       $this->ClearAllRecipients();
+
+                       $this->AddAddress($row['to_email'], $row['to_name']);
+                       $this->From     = $row['from_email'];
+                       $this->FromName = $row['from_name'];
+                       $this->CharSet  = $row['char_set'];
+                       $this->Subject  = $row['subject'];
+                       $this->Body     = $row['body'];
+
+                       parent::Send();
+
+                       $mail_ids .= $row['mail_id'].',';
+               }
+               if ($mail_ids) {
+                       $mail_ids = substr($mail_ids, 0, -1); // remove the last comma
+                       $sql = "DELETE FROM ".TABLE_PREFIX."mail_queue WHERE mail_id IN ($mail_ids)";
+                       mysql_query($sql, $db);
+               }
+       }
+
+}
+
+?>
diff --git a/include/classes/phpmailer/class.phpmailer.php b/include/classes/phpmailer/class.phpmailer.php
new file mode 100644 (file)
index 0000000..8d955b2
--- /dev/null
@@ -0,0 +1,1499 @@
+<?php\r
+////////////////////////////////////////////////////\r
+// PHPMailer - PHP email class\r
+//\r
+// Class for sending email using either\r
+// sendmail, PHP mail(), or SMTP.  Methods are\r
+// based upon the standard AspEmail(tm) classes.\r
+//\r
+// Copyright (C) 2001 - 2003  Brent R. Matzelle\r
+//\r
+// License: LGPL, see LICENSE\r
+////////////////////////////////////////////////////\r
+\r
+/**\r
+ * PHPMailer - PHP email transport class\r
+ * @package PHPMailer\r
+ * @author Brent R. Matzelle\r
+ * @copyright 2001 - 2003 Brent R. Matzelle\r
+ */\r
+class PHPMailer\r
+{\r
+    /////////////////////////////////////////////////\r
+    // PUBLIC VARIABLES\r
+    /////////////////////////////////////////////////\r
+\r
+    /**\r
+     * Email priority (1 = High, 3 = Normal, 5 = low).\r
+     * @var int\r
+     */\r
+    var $Priority          = 3;\r
+\r
+    /**\r
+     * Sets the CharSet of the message.\r
+     * @var string\r
+     */\r
+    var $CharSet           = "iso-8859-1";\r
+\r
+    /**\r
+     * Sets the Content-type of the message.\r
+     * @var string\r
+     */\r
+    var $ContentType        = "text/plain";\r
+\r
+    /**\r
+     * Sets the Encoding of the message. Options for this are "8bit",\r
+     * "7bit", "binary", "base64", and "quoted-printable".\r
+     * @var string\r
+     */\r
+    var $Encoding          = "8bit";\r
+\r
+    /**\r
+     * Holds the most recent mailer error message.\r
+     * @var string\r
+     */\r
+    var $ErrorInfo         = "";\r
+\r
+    /**\r
+     * Sets the From email address for the message.\r
+     * @var string\r
+     */\r
+    var $From               = "";\r
+\r
+    /**\r
+     * Sets the From name of the message.\r
+     * @var string\r
+     */\r
+    var $FromName           = "";\r
+\r
+    /**\r
+     * Sets the Sender email (Return-Path) of the message.  If not empty,\r
+     * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.\r
+     * @var string\r
+     */\r
+    var $Sender            = "";\r
+\r
+    /**\r
+     * Sets the Subject of the message.\r
+     * @var string\r
+     */\r
+    var $Subject           = "";\r
+\r
+    /**\r
+     * Sets the Body of the message.  This can be either an HTML or text body.\r
+     * If HTML then run IsHTML(true).\r
+     * @var string\r
+     */\r
+    var $Body               = "";\r
+\r
+    /**\r
+     * Sets the text-only body of the message.  This automatically sets the\r
+     * email to multipart/alternative.  This body can be read by mail\r
+     * clients that do not have HTML email capability such as mutt. Clients\r
+     * that can read HTML will view the normal Body.\r
+     * @var string\r
+     */\r
+    var $AltBody           = "";\r
+\r
+    /**\r
+     * Sets word wrapping on the body of the message to a given number of \r
+     * characters.\r
+     * @var int\r
+     */\r
+    var $WordWrap          = 0;\r
+\r
+    /**\r
+     * Method to send mail: ("mail", "sendmail", or "smtp").\r
+     * @var string\r
+     */\r
+    var $Mailer            = "mail";\r
+\r
+    /**\r
+     * Sets the path of the sendmail program.\r
+     * @var string\r
+     */\r
+    var $Sendmail          = "/usr/sbin/sendmail";\r
+    \r
+    /**\r
+     * Path to PHPMailer plugins.  This is now only useful if the SMTP class \r
+     * is in a different directory than the PHP include path.  \r
+     * @var string\r
+     */\r
+    var $PluginDir         = "";\r
+\r
+    /**\r
+     *  Holds PHPMailer version.\r
+     *  @var string\r
+     */\r
+    var $Version           = "1.73";\r
+\r
+    /**\r
+     * Sets the email address that a reading confirmation will be sent.\r
+     * @var string\r
+     */\r
+    var $ConfirmReadingTo  = "";\r
+\r
+    /**\r
+     *  Sets the hostname to use in Message-Id and Received headers\r
+     *  and as default HELO string. If empty, the value returned\r
+     *  by SERVER_NAME is used or 'localhost.localdomain'.\r
+     *  @var string\r
+     */\r
+    var $Hostname          = "";\r
+\r
+    /////////////////////////////////////////////////\r
+    // SMTP VARIABLES\r
+    /////////////////////////////////////////////////\r
+\r
+    /**\r
+     *  Sets the SMTP hosts.  All hosts must be separated by a\r
+     *  semicolon.  You can also specify a different port\r
+     *  for each host by using this format: [hostname:port]\r
+     *  (e.g. "smtp1.example.com:25;smtp2.example.com").\r
+     *  Hosts will be tried in order.\r
+     *  @var string\r
+     */\r
+    var $Host        = "localhost";\r
+\r
+    /**\r
+     *  Sets the default SMTP server port.\r
+     *  @var int\r
+     */\r
+    var $Port        = 25;\r
+\r
+    /**\r
+     *  Sets the SMTP HELO of the message (Default is $Hostname).\r
+     *  @var string\r
+     */\r
+    var $Helo        = "";\r
+\r
+    /**\r
+     *  Sets SMTP authentication. Utilizes the Username and Password variables.\r
+     *  @var bool\r
+     */\r
+    var $SMTPAuth     = false;\r
+\r
+    /**\r
+     *  Sets SMTP username.\r
+     *  @var string\r
+     */\r
+    var $Username     = "";\r
+\r
+    /**\r
+     *  Sets SMTP password.\r
+     *  @var string\r
+     */\r
+    var $Password     = "";\r
+\r
+    /**\r
+     *  Sets the SMTP server timeout in seconds. This function will not \r
+     *  work with the win32 version.\r
+     *  @var int\r
+     */\r
+    var $Timeout      = 10;\r
+\r
+    /**\r
+     *  Sets SMTP class debugging on or off.\r
+     *  @var bool\r
+     */\r
+    var $SMTPDebug    = false;\r
+\r
+    /**\r
+     * Prevents the SMTP connection from being closed after each mail \r
+     * sending.  If this is set to true then to close the connection \r
+     * requires an explicit call to SmtpClose(). \r
+     * @var bool\r
+     */\r
+    var $SMTPKeepAlive = false;\r
+\r
+    /**#@+\r
+     * @access private\r
+     */\r
+    var $smtp            = NULL;\r
+    var $to              = array();\r
+    var $cc              = array();\r
+    var $bcc             = array();\r
+    var $ReplyTo         = array();\r
+    var $attachment      = array();\r
+    var $CustomHeader    = array();\r
+    var $message_type    = "";\r
+    var $boundary        = array();\r
+    var $language        = array();\r
+    var $error_count     = 0;\r
+    var $LE              = "\n";\r
+    /**#@-*/\r
+    \r
+    /////////////////////////////////////////////////\r
+    // VARIABLE METHODS\r
+    /////////////////////////////////////////////////\r
+\r
+    /**\r
+     * Sets message type to HTML.  \r
+     * @param bool $bool\r
+     * @return void\r
+     */\r
+    function IsHTML($bool) {\r
+        if($bool == true)\r
+            $this->ContentType = "text/html";\r
+        else\r
+            $this->ContentType = "text/plain";\r
+    }\r
+\r
+    /**\r
+     * Sets Mailer to send message using SMTP.\r
+     * @return void\r
+     */\r
+    function IsSMTP() {\r
+        $this->Mailer = "smtp";\r
+    }\r
+\r
+    /**\r
+     * Sets Mailer to send message using PHP mail() function.\r
+     * @return void\r
+     */\r
+    function IsMail() {\r
+        $this->Mailer = "mail";\r
+    }\r
+\r
+    /**\r
+     * Sets Mailer to send message using the $Sendmail program.\r
+     * @return void\r
+     */\r
+    function IsSendmail() {\r
+        $this->Mailer = "sendmail";\r
+    }\r
+\r
+    /**\r
+     * Sets Mailer to send message using the qmail MTA. \r
+     * @return void\r
+     */\r
+    function IsQmail() {\r
+        $this->Sendmail = "/var/qmail/bin/sendmail";\r
+        $this->Mailer = "sendmail";\r
+    }\r
+\r
+\r
+    /////////////////////////////////////////////////\r
+    // RECIPIENT METHODS\r
+    /////////////////////////////////////////////////\r
+\r
+    /**\r
+     * Adds a "To" address.  \r
+     * @param string $address\r
+     * @param string $name\r
+     * @return void\r
+     */\r
+    function AddAddress($address, $name = "") {\r
+        $cur = count($this->to);\r
+        $this->to[$cur][0] = trim($address);\r
+        $this->to[$cur][1] = $name;\r
+    }\r
+\r
+    /**\r
+     * Adds a "Cc" address. Note: this function works\r
+     * with the SMTP mailer on win32, not with the "mail"\r
+     * mailer.  \r
+     * @param string $address\r
+     * @param string $name\r
+     * @return void\r
+    */\r
+    function AddCC($address, $name = "") {\r
+        $cur = count($this->cc);\r
+        $this->cc[$cur][0] = trim($address);\r
+        $this->cc[$cur][1] = $name;\r
+    }\r
+\r
+    /**\r
+     * Adds a "Bcc" address. Note: this function works\r
+     * with the SMTP mailer on win32, not with the "mail"\r
+     * mailer.  \r
+     * @param string $address\r
+     * @param string $name\r
+     * @return void\r
+     */\r
+    function AddBCC($address, $name = "") {\r
+        $cur = count($this->bcc);\r
+        $this->bcc[$cur][0] = trim($address);\r
+        $this->bcc[$cur][1] = $name;\r
+    }\r
+\r
+    /**\r
+     * Adds a "Reply-to" address.  \r
+     * @param string $address\r
+     * @param string $name\r
+     * @return void\r
+     */\r
+    function AddReplyTo($address, $name = "") {\r
+        $cur = count($this->ReplyTo);\r
+        $this->ReplyTo[$cur][0] = trim($address);\r
+        $this->ReplyTo[$cur][1] = $name;\r
+    }\r
+\r
+\r
+    /////////////////////////////////////////////////\r
+    // MAIL SENDING METHODS\r
+    /////////////////////////////////////////////////\r
+\r
+    /**\r
+     * Creates message and assigns Mailer. If the message is\r
+     * not sent successfully then it returns false.  Use the ErrorInfo\r
+     * variable to view description of the error.  \r
+     * @return bool\r
+     */\r
+    function Send() {\r
+        $header = "";\r
+        $body = "";\r
+        $result = true;\r
+\r
+        if((count($this->to) + count($this->cc) + count($this->bcc)) < 1)\r
+        {\r
+            $this->SetError($this->Lang("provide_address"));\r
+            return false;\r
+        }\r
+\r
+        // Set whether the message is multipart/alternative\r
+        if(!empty($this->AltBody))\r
+            $this->ContentType = "multipart/alternative";\r
+\r
+        $this->error_count = 0; // reset errors\r
+        $this->SetMessageType();\r
+        $header .= $this->CreateHeader();\r
+        $body = $this->CreateBody();\r
+\r
+        if($body == "") { return false; }\r
+\r
+        // Choose the mailer\r
+        switch($this->Mailer)\r
+        {\r
+            case "sendmail":\r
+                $result = $this->SendmailSend($header, $body);\r
+                break;\r
+            case "mail":\r
+                $result = $this->MailSend($header, $body);\r
+                break;\r
+            case "smtp":\r
+                $result = $this->SmtpSend($header, $body);\r
+                break;\r
+            default:\r
+            $this->SetError($this->Mailer . $this->Lang("mailer_not_supported"));\r
+                $result = false;\r
+                break;\r
+        }\r
+\r
+        return $result;\r
+    }\r
+    \r
+    /**\r
+     * Sends mail using the $Sendmail program.  \r
+     * @access private\r
+     * @return bool\r
+     */\r
+    function SendmailSend($header, $body) {\r
+        if ($this->Sender != "")\r
+            $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));\r
+        else\r
+            $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));\r
+\r
+        if(!@$mail = popen($sendmail, "w"))\r
+        {\r
+            $this->SetError($this->Lang("execute") . $this->Sendmail);\r
+            return false;\r
+        }\r
+\r
+        fputs($mail, $header);\r
+        fputs($mail, $body);\r
+        \r
+        $result = pclose($mail) >> 8 & 0xFF;\r
+        if($result != 0)\r
+        {\r
+            $this->SetError($this->Lang("execute") . $this->Sendmail);\r
+            return false;\r
+        }\r
+\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Sends mail using the PHP mail() function.  \r
+     * @access private\r
+     * @return bool\r
+     */\r
+    function MailSend($header, $body) {\r
+        $to = "";\r
+        for($i = 0; $i < count($this->to); $i++)\r
+        {\r
+            if($i != 0) { $to .= ", "; }\r
+            $to .= $this->to[$i][0];\r
+        }\r
+\r
+        if ($this->Sender != "" && strlen(ini_get("safe_mode"))< 1)\r
+        {\r
+            $old_from = ini_get("sendmail_from");\r
+            ini_set("sendmail_from", $this->Sender);\r
+            $params = sprintf("-oi -f %s", $this->Sender);\r
+            $rt = @mail($to, $this->EncodeHeader($this->Subject), $body, \r
+                        $header, $params);\r
+        }\r
+        else\r
+            $rt = @mail($to, $this->EncodeHeader($this->Subject), $body, $header);\r
+\r
+        if (isset($old_from))\r
+            ini_set("sendmail_from", $old_from);\r
+\r
+        if(!$rt)\r
+        {\r
+            $this->SetError($this->Lang("instantiate"));\r
+            return false;\r
+        }\r
+\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Sends mail via SMTP using PhpSMTP (Author:\r
+     * Chris Ryan).  Returns bool.  Returns false if there is a\r
+     * bad MAIL FROM, RCPT, or DATA input.\r
+     * @access private\r
+     * @return bool\r
+     */\r
+    function SmtpSend($header, $body) {\r
+        include_once($this->PluginDir . "class.smtp.php");\r
+        $error = "";\r
+        $bad_rcpt = array();\r
+\r
+        if(!$this->SmtpConnect())\r
+            return false;\r
+\r
+        $smtp_from = ($this->Sender == "") ? $this->From : $this->Sender;\r
+        if(!$this->smtp->Mail($smtp_from))\r
+        {\r
+            $error = $this->Lang("from_failed") . $smtp_from;\r
+            $this->SetError($error);\r
+            $this->smtp->Reset();\r
+            return false;\r
+        }\r
+\r
+        // Attempt to send attach all recipients\r
+        for($i = 0; $i < count($this->to); $i++)\r
+        {\r
+            if(!$this->smtp->Recipient($this->to[$i][0]))\r
+                $bad_rcpt[] = $this->to[$i][0];\r
+        }\r
+        for($i = 0; $i < count($this->cc); $i++)\r
+        {\r
+            if(!$this->smtp->Recipient($this->cc[$i][0]))\r
+                $bad_rcpt[] = $this->cc[$i][0];\r
+        }\r
+        for($i = 0; $i < count($this->bcc); $i++)\r
+        {\r
+            if(!$this->smtp->Recipient($this->bcc[$i][0]))\r
+                $bad_rcpt[] = $this->bcc[$i][0];\r
+        }\r
+\r
+        if(count($bad_rcpt) > 0) // Create error message\r
+        {\r
+            for($i = 0; $i < count($bad_rcpt); $i++)\r
+            {\r
+                if($i != 0) { $error .= ", "; }\r
+                $error .= $bad_rcpt[$i];\r
+            }\r
+            $error = $this->Lang("recipients_failed") . $error;\r
+            $this->SetError($error);\r
+            $this->smtp->Reset();\r
+            return false;\r
+        }\r
+\r
+        if(!$this->smtp->Data($header . $body))\r
+        {\r
+            $this->SetError($this->Lang("data_not_accepted"));\r
+            $this->smtp->Reset();\r
+            return false;\r
+        }\r
+        if($this->SMTPKeepAlive == true)\r
+            $this->smtp->Reset();\r
+        else\r
+            $this->SmtpClose();\r
+\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Initiates a connection to an SMTP server.  Returns false if the \r
+     * operation failed.\r
+     * @access private\r
+     * @return bool\r
+     */\r
+    function SmtpConnect() {\r
+        if($this->smtp == NULL) { $this->smtp = new SMTP(); }\r
+\r
+        $this->smtp->do_debug = $this->SMTPDebug;\r
+        $hosts = explode(";", $this->Host);\r
+        $index = 0;\r
+        $connection = ($this->smtp->Connected()); \r
+\r
+        // Retry while there is no connection\r
+        while($index < count($hosts) && $connection == false)\r
+        {\r
+            if(strstr($hosts[$index], ":"))\r
+                list($host, $port) = explode(":", $hosts[$index]);\r
+            else\r
+            {\r
+                $host = $hosts[$index];\r
+                $port = $this->Port;\r
+            }\r
+\r
+            if($this->smtp->Connect($host, $port, $this->Timeout))\r
+            {\r
+                if ($this->Helo != '')\r
+                    $this->smtp->Hello($this->Helo);\r
+                else\r
+                    $this->smtp->Hello($this->ServerHostname());\r
+        \r
+                if($this->SMTPAuth)\r
+                {\r
+                    if(!$this->smtp->Authenticate($this->Username, \r
+                                                  $this->Password))\r
+                    {\r
+                        $this->SetError($this->Lang("authenticate"));\r
+                        $this->smtp->Reset();\r
+                        $connection = false;\r
+                    }\r
+                }\r
+                $connection = true;\r
+            }\r
+            $index++;\r
+        }\r
+        if(!$connection)\r
+            $this->SetError($this->Lang("connect_host"));\r
+\r
+        return $connection;\r
+    }\r
+\r
+    /**\r
+     * Closes the active SMTP session if one exists.\r
+     * @return void\r
+     */\r
+    function SmtpClose() {\r
+        if($this->smtp != NULL)\r
+        {\r
+            if($this->smtp->Connected())\r
+            {\r
+                $this->smtp->Quit();\r
+                $this->smtp->Close();\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Sets the language for all class error messages.  Returns false \r
+     * if it cannot load the language file.  The default language type\r
+     * is English.\r
+     * @param string $lang_type Type of language (e.g. Portuguese: "br")\r
+     * @param string $lang_path Path to the language file directory\r
+     * @access public\r
+     * @return bool\r
+     */\r
+    function SetLanguage($lang_type, $lang_path = "language/") {\r
+        if(file_exists($lang_path.'phpmailer.lang-'.$lang_type.'.php'))\r
+            include($lang_path.'phpmailer.lang-'.$lang_type.'.php');\r
+        else if(file_exists($lang_path.'phpmailer.lang-en.php'))\r
+            include($lang_path.'phpmailer.lang-en.php');\r
+        else\r
+        {\r
+            $this->SetError("Could not load language file");\r
+            return false;\r
+        }\r
+        $this->language = $PHPMAILER_LANG;\r
+    \r
+        return true;\r
+    }\r
+\r
+    /////////////////////////////////////////////////\r
+    // MESSAGE CREATION METHODS\r
+    /////////////////////////////////////////////////\r
+\r
+    /**\r
+     * Creates recipient headers.  \r
+     * @access private\r
+     * @return string\r
+     */\r
+    function AddrAppend($type, $addr) {\r
+        $addr_str = $type . ": ";\r
+        $addr_str .= $this->AddrFormat($addr[0]);\r
+        if(count($addr) > 1)\r
+        {\r
+            for($i = 1; $i < count($addr); $i++)\r
+                $addr_str .= ", " . $this->AddrFormat($addr[$i]);\r
+        }\r
+        $addr_str .= $this->LE;\r
+\r
+        return $addr_str;\r
+    }\r
+    \r
+    /**\r
+     * Formats an address correctly. \r
+     * @access private\r
+     * @return string\r
+     */\r
+    function AddrFormat($addr) {\r
+        if(empty($addr[1]))\r
+            $formatted = $addr[0];\r
+        else\r
+        {\r
+            $formatted = $this->EncodeHeader($addr[1], 'phrase') . " <" . \r
+                         $addr[0] . ">";\r
+        }\r
+\r
+        return $formatted;\r
+    }\r
+\r
+    /**\r
+     * Wraps message for use with mailers that do not\r
+     * automatically perform wrapping and for quoted-printable.\r
+     * Original written by philippe.  \r
+     * @access private\r
+     * @return string\r
+     */\r
+    function WrapText($message, $length, $qp_mode = false) {\r
+        $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;\r
+\r
+        $message = $this->FixEOL($message);\r
+        if (substr($message, -1) == $this->LE)\r
+            $message = substr($message, 0, -1);\r
+\r
+        $line = explode($this->LE, $message);\r
+        $message = "";\r
+        for ($i=0 ;$i < count($line); $i++)\r
+        {\r
+          $line_part = explode(" ", $line[$i]);\r
+          $buf = "";\r
+          for ($e = 0; $e<count($line_part); $e++)\r
+          {\r
+              $word = $line_part[$e];\r
+              if ($qp_mode and (strlen($word) > $length))\r
+              {\r
+                $space_left = $length - strlen($buf) - 1;\r
+                if ($e != 0)\r
+                {\r
+                    if ($space_left > 20)\r
+                    {\r
+                        $len = $space_left;\r
+                        if (substr($word, $len - 1, 1) == "=")\r
+                          $len--;\r
+                        elseif (substr($word, $len - 2, 1) == "=")\r
+                          $len -= 2;\r
+                        $part = substr($word, 0, $len);\r
+                        $word = substr($word, $len);\r
+                        $buf .= " " . $part;\r
+                        $message .= $buf . sprintf("=%s", $this->LE);\r
+                    }\r
+                    else\r
+                    {\r
+                        $message .= $buf . $soft_break;\r
+                    }\r
+                    $buf = "";\r
+                }\r
+                while (strlen($word) > 0)\r
+                {\r
+                    $len = $length;\r
+                    if (substr($word, $len - 1, 1) == "=")\r
+                        $len--;\r
+                    elseif (substr($word, $len - 2, 1) == "=")\r
+                        $len -= 2;\r
+                    $part = substr($word, 0, $len);\r
+                    $word = substr($word, $len);\r
+\r
+                    if (strlen($word) > 0)\r
+                        $message .= $part . sprintf("=%s", $this->LE);\r
+                    else\r
+                        $buf = $part;\r
+                }\r
+              }\r
+              else\r
+              {\r
+                $buf_o = $buf;\r
+                $buf .= ($e == 0) ? $word : (" " . $word); \r
+\r
+                if (strlen($buf) > $length and $buf_o != "")\r
+                {\r
+                    $message .= $buf_o . $soft_break;\r
+                    $buf = $word;\r
+                }\r
+              }\r
+          }\r
+          $message .= $buf . $this->LE;\r
+        }\r
+\r
+        return $message;\r
+    }\r
+    \r
+    /**\r
+     * Set the body wrapping.\r
+     * @access private\r
+     * @return void\r
+     */\r
+    function SetWordWrap() {\r
+        if($this->WordWrap < 1)\r
+            return;\r
+            \r
+        switch($this->message_type)\r
+        {\r
+           case "alt":\r
+              // fall through\r
+           case "alt_attachments":\r
+              $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);\r
+              break;\r
+           default:\r
+              $this->Body = $this->WrapText($this->Body, $this->WordWrap);\r
+              break;\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Assembles message header.  \r
+     * @access private\r
+     * @return string\r
+     */\r
+    function CreateHeader() {\r
+        $result = "";\r
+        \r
+        // Set the boundaries\r
+        $uniq_id = md5(uniqid(time()));\r
+        $this->boundary[1] = "b1_" . $uniq_id;\r
+        $this->boundary[2] = "b2_" . $uniq_id;\r
+\r
+        $result .= $this->HeaderLine("Date", $this->RFCDate());\r
+        if($this->Sender == "")\r
+            $result .= $this->HeaderLine("Return-Path", trim($this->From));\r
+        else\r
+            $result .= $this->HeaderLine("Return-Path", trim($this->Sender));\r
+        \r
+        // To be created automatically by mail()\r
+        if($this->Mailer != "mail")\r
+        {\r
+            if(count($this->to) > 0)\r
+                $result .= $this->AddrAppend("To", $this->to);\r
+            else if (count($this->cc) == 0)\r
+                $result .= $this->HeaderLine("To", "undisclosed-recipients:;");\r
+            if(count($this->cc) > 0)\r
+                $result .= $this->AddrAppend("Cc", $this->cc);\r
+        }\r
+\r
+        $from = array();\r
+        $from[0][0] = trim($this->From);\r
+        $from[0][1] = $this->FromName;\r
+        $result .= $this->AddrAppend("From", $from); \r
+\r
+        // sendmail and mail() extract Bcc from the header before sending\r
+        if((($this->Mailer == "sendmail") || ($this->Mailer == "mail")) && (count($this->bcc) > 0))\r
+            $result .= $this->AddrAppend("Bcc", $this->bcc);\r
+\r
+        if(count($this->ReplyTo) > 0)\r
+            $result .= $this->AddrAppend("Reply-to", $this->ReplyTo);\r
+\r
+        // mail() sets the subject itself\r
+        if($this->Mailer != "mail")\r
+            $result .= $this->HeaderLine("Subject", $this->EncodeHeader(trim($this->Subject)));\r
+\r
+        $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);\r
+        $result .= $this->HeaderLine("X-Priority", $this->Priority);\r
+        $result .= $this->HeaderLine("X-Mailer", "PHPMailer [version " . $this->Version . "]");\r
+        \r
+        if($this->ConfirmReadingTo != "")\r
+        {\r
+            $result .= $this->HeaderLine("Disposition-Notification-To", \r
+                       "<" . trim($this->ConfirmReadingTo) . ">");\r
+        }\r
+\r
+        // Add custom headers\r
+        for($index = 0; $index < count($this->CustomHeader); $index++)\r
+        {\r
+            $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), \r
+                       $this->EncodeHeader(trim($this->CustomHeader[$index][1])));\r
+        }\r
+        $result .= $this->HeaderLine("MIME-Version", "1.0");\r
+\r
+        switch($this->message_type)\r
+        {\r
+            case "plain":\r
+                $result .= $this->HeaderLine("Content-Transfer-Encoding", $this->Encoding);\r
+                $result .= sprintf("Content-Type: %s; charset=\"%s\"",\r
+                                    $this->ContentType, $this->CharSet);\r
+                break;\r
+            case "attachments":\r
+                // fall through\r
+            case "alt_attachments":\r
+                if($this->InlineImageExists())\r
+                {\r
+                    $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", \r
+                                    "multipart/related", $this->LE, $this->LE, \r
+                                    $this->boundary[1], $this->LE);\r
+                }\r
+                else\r
+                {\r
+                    $result .= $this->HeaderLine("Content-Type", "multipart/mixed;");\r
+                    $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');\r
+                }\r
+                break;\r
+            case "alt":\r
+                $result .= $this->HeaderLine("Content-Type", "multipart/alternative;");\r
+                $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');\r
+                break;\r
+        }\r
+\r
+        if($this->Mailer != "mail")\r
+            $result .= $this->LE.$this->LE;\r
+\r
+        return $result;\r
+    }\r
+\r
+    /**\r
+     * Assembles the message body.  Returns an empty string on failure.\r
+     * @access private\r
+     * @return string\r
+     */\r
+    function CreateBody() {\r
+        $result = "";\r
+\r
+        $this->SetWordWrap();\r
+\r
+        switch($this->message_type)\r
+        {\r
+            case "alt":\r
+                $result .= $this->GetBoundary($this->boundary[1], "", \r
+                                              "text/plain", "");\r
+                $result .= $this->EncodeString($this->AltBody, $this->Encoding);\r
+                $result .= $this->LE.$this->LE;\r
+                $result .= $this->GetBoundary($this->boundary[1], "", \r
+                                              "text/html", "");\r
+                \r
+                $result .= $this->EncodeString($this->Body, $this->Encoding);\r
+                $result .= $this->LE.$this->LE;\r
+    \r
+                $result .= $this->EndBoundary($this->boundary[1]);\r
+                break;\r
+            case "plain":\r
+                $result .= $this->EncodeString($this->Body, $this->Encoding);\r
+                break;\r
+            case "attachments":\r
+                $result .= $this->GetBoundary($this->boundary[1], "", "", "");\r
+                $result .= $this->EncodeString($this->Body, $this->Encoding);\r
+                $result .= $this->LE;\r
+     \r
+                $result .= $this->AttachAll();\r
+                break;\r
+            case "alt_attachments":\r
+                $result .= sprintf("--%s%s", $this->boundary[1], $this->LE);\r
+                $result .= sprintf("Content-Type: %s;%s" .\r
+                                   "\tboundary=\"%s\"%s",\r
+                                   "multipart/alternative", $this->LE, \r
+                                   $this->boundary[2], $this->LE.$this->LE);\r
+    \r
+                // Create text body\r
+                $result .= $this->GetBoundary($this->boundary[2], "", \r
+                                              "text/plain", "") . $this->LE;\r
+\r
+                $result .= $this->EncodeString($this->AltBody, $this->Encoding);\r
+                $result .= $this->LE.$this->LE;\r
+    \r
+                // Create the HTML body\r
+                $result .= $this->GetBoundary($this->boundary[2], "", \r
+                                              "text/html", "") . $this->LE;\r
+    \r
+                $result .= $this->EncodeString($this->Body, $this->Encoding);\r
+                $result .= $this->LE.$this->LE;\r
+\r
+                $result .= $this->EndBoundary($this->boundary[2]);\r
+                \r
+                $result .= $this->AttachAll();\r
+                break;\r
+        }\r
+        if($this->IsError())\r
+            $result = "";\r
+\r
+        return $result;\r
+    }\r
+\r
+    /**\r
+     * Returns the start of a message boundary.\r
+     * @access private\r
+     */\r
+    function GetBoundary($boundary, $charSet, $contentType, $encoding) {\r
+        $result = "";\r
+        if($charSet == "") { $charSet = $this->CharSet; }\r
+        if($contentType == "") { $contentType = $this->ContentType; }\r
+        if($encoding == "") { $encoding = $this->Encoding; }\r
+\r
+        $result .= $this->TextLine("--" . $boundary);\r
+        $result .= sprintf("Content-Type: %s; charset = \"%s\"", \r
+                            $contentType, $charSet);\r
+        $result .= $this->LE;\r
+        $result .= $this->HeaderLine("Content-Transfer-Encoding", $encoding);\r
+        $result .= $this->LE;\r
+       \r
+        return $result;\r
+    }\r
+    \r
+    /**\r
+     * Returns the end of a message boundary.\r
+     * @access private\r
+     */\r
+    function EndBoundary($boundary) {\r
+        return $this->LE . "--" . $boundary . "--" . $this->LE; \r
+    }\r
+    \r
+    /**\r
+     * Sets the message type.\r
+     * @access private\r
+     * @return void\r
+     */\r
+    function SetMessageType() {\r
+        if(count($this->attachment) < 1 && strlen($this->AltBody) < 1)\r
+            $this->message_type = "plain";\r
+        else\r
+        {\r
+            if(count($this->attachment) > 0)\r
+                $this->message_type = "attachments";\r
+            if(strlen($this->AltBody) > 0 && count($this->attachment) < 1)\r
+                $this->message_type = "alt";\r
+            if(strlen($this->AltBody) > 0 && count($this->attachment) > 0)\r
+                $this->message_type = "alt_attachments";\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Returns a formatted header line.\r
+     * @access private\r
+     * @return string\r
+     */\r
+    function HeaderLine($name, $value) {\r
+        return $name . ": " . $value . $this->LE;\r
+    }\r
+\r
+    /**\r
+     * Returns a formatted mail line.\r
+     * @access private\r
+     * @return string\r
+     */\r
+    function TextLine($value) {\r
+        return $value . $this->LE;\r
+    }\r
+\r
+    /////////////////////////////////////////////////\r
+    // ATTACHMENT METHODS\r
+    /////////////////////////////////////////////////\r
+\r
+    /**\r
+     * Adds an attachment from a path on the filesystem.\r
+     * Returns false if the file could not be found\r
+     * or accessed.\r
+     * @param string $path Path to the attachment.\r
+     * @param string $name Overrides the attachment name.\r
+     * @param string $encoding File encoding (see $Encoding).\r
+     * @param string $type File extension (MIME) type.\r
+     * @return bool\r
+     */\r
+    function AddAttachment($path, $name = "", $encoding = "base64", \r
+                           $type = "application/octet-stream") {\r
+        if(!@is_file($path))\r
+        {\r
+            $this->SetError($this->Lang("file_access") . $path);\r
+            return false;\r
+        }\r
+\r
+        $filename = basename($path);\r
+        if($name == "")\r
+            $name = $filename;\r
+\r
+        $cur = count($this->attachment);\r
+        $this->attachment[$cur][0] = $path;\r
+        $this->attachment[$cur][1] = $filename;\r
+        $this->attachment[$cur][2] = $name;\r
+        $this->attachment[$cur][3] = $encoding;\r
+        $this->attachment[$cur][4] = $type;\r
+        $this->attachment[$cur][5] = false; // isStringAttachment\r
+        $this->attachment[$cur][6] = "attachment";\r
+        $this->attachment[$cur][7] = 0;\r
+\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Attaches all fs, string, and binary attachments to the message.\r
+     * Returns an empty string on failure.\r
+     * @access private\r
+     * @return string\r
+     */\r
+    function AttachAll() {\r
+        // Return text of body\r
+        $mime = array();\r
+\r
+        // Add all attachments\r
+        for($i = 0; $i < count($this->attachment); $i++)\r
+        {\r
+            // Check for string attachment\r
+            $bString = $this->attachment[$i][5];\r
+            if ($bString)\r
+                $string = $this->attachment[$i][0];\r
+            else\r
+                $path = $this->attachment[$i][0];\r
+\r
+            $filename    = $this->attachment[$i][1];\r
+            $name        = $this->attachment[$i][2];\r
+            $encoding    = $this->attachment[$i][3];\r
+            $type        = $this->attachment[$i][4];\r
+            $disposition = $this->attachment[$i][6];\r
+            $cid         = $this->attachment[$i][7];\r
+            \r
+            $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE);\r
+            $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $name, $this->LE);\r
+            $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);\r
+\r
+            if($disposition == "inline")\r
+                $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);\r
+\r
+            $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", \r
+                              $disposition, $name, $this->LE.$this->LE);\r
+\r
+            // Encode as string attachment\r
+            if($bString)\r
+            {\r
+                $mime[] = $this->EncodeString($string, $encoding);\r
+                if($this->IsError()) { return ""; }\r
+                $mime[] = $this->LE.$this->LE;\r
+            }\r
+            else\r
+            {\r
+                $mime[] = $this->EncodeFile($path, $encoding);                \r
+                if($this->IsError()) { return ""; }\r
+                $mime[] = $this->LE.$this->LE;\r
+            }\r
+        }\r
+\r
+        $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE);\r
+\r
+        return join("", $mime);\r
+    }\r
+    \r
+    /**\r
+     * Encodes attachment in requested format.  Returns an\r
+     * empty string on failure.\r
+     * @access private\r
+     * @return string\r
+     */\r
+    function EncodeFile ($path, $encoding = "base64") {\r
+        if(!@$fd = fopen($path, "rb"))\r
+        {\r
+            $this->SetError($this->Lang("file_open") . $path);\r
+            return "";\r
+        }\r
+        $magic_quotes = get_magic_quotes_runtime();\r
+        set_magic_quotes_runtime(0);\r
+        $file_buffer = fread($fd, filesize($path));\r
+        $file_buffer = $this->EncodeString($file_buffer, $encoding);\r
+        fclose($fd);\r
+        set_magic_quotes_runtime($magic_quotes);\r
+\r
+        return $file_buffer;\r
+    }\r
+\r
+    /**\r
+     * Encodes string to requested format. Returns an\r
+     * empty string on failure.\r
+     * @access private\r
+     * @return string\r
+     */\r
+    function EncodeString ($str, $encoding = "base64") {\r
+        $encoded = "";\r
+        switch(strtolower($encoding)) {\r
+          case "base64":\r
+              // chunk_split is found in PHP >= 3.0.6\r
+              $encoded = chunk_split(base64_encode($str), 76, $this->LE);\r
+              break;\r
+          case "7bit":\r
+          case "8bit":\r
+              $encoded = $this->FixEOL($str);\r
+              if (substr($encoded, -(strlen($this->LE))) != $this->LE)\r
+                $encoded .= $this->LE;\r
+              break;\r
+          case "binary":\r
+              $encoded = $str;\r
+              break;\r
+          case "quoted-printable":\r
+              $encoded = $this->EncodeQP($str);\r
+              break;\r
+          default:\r
+              $this->SetError($this->Lang("encoding") . $encoding);\r
+              break;\r
+        }\r
+        return $encoded;\r
+    }\r
+\r
+    /**\r
+     * Encode a header string to best of Q, B, quoted or none.  \r
+     * @access private\r
+     * @return string\r
+     */\r
+    function EncodeHeader ($str, $position = 'text') {\r
+      $x = 0;\r
+      \r
+      switch (strtolower($position)) {\r
+        case 'phrase':\r
+          if (!preg_match('/[\200-\377]/', $str)) {\r
+            // Can't use addslashes as we don't know what value has magic_quotes_sybase.\r
+            $encoded = addcslashes($str, "\0..\37\177\\\"");\r
+\r
+            if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str))\r
+              return ($encoded);\r
+            else\r
+              return ("\"$encoded\"");\r
+          }\r
+          $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);\r
+          break;\r
+        case 'comment':\r
+          $x = preg_match_all('/[()"]/', $str, $matches);\r
+          // Fall-through\r
+        case 'text':\r
+        default:\r
+          $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);\r
+          break;\r
+      }\r
+\r
+      if ($x == 0)\r
+        return ($str);\r
+\r
+      $maxlen = 75 - 7 - strlen($this->CharSet);\r
+      // Try to select the encoding which should produce the shortest output\r
+      if (strlen($str)/3 < $x) {\r
+        $encoding = 'B';\r
+        $encoded = base64_encode($str);\r
+        $maxlen -= $maxlen % 4;\r
+        $encoded = trim(chunk_split($encoded, $maxlen, "\n"));\r
+      } else {\r
+        $encoding = 'Q';\r
+        $encoded = $this->EncodeQ($str, $position);\r
+        $encoded = $this->WrapText($encoded, $maxlen, true);\r
+        $encoded = str_replace("=".$this->LE, "\n", trim($encoded));\r
+      }\r
+\r
+      $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded);\r
+      $encoded = trim(str_replace("\n", $this->LE, $encoded));\r
+      \r
+      return $encoded;\r
+    }\r
+    \r
+    /**\r
+     * Encode string to quoted-printable.  \r
+     * @access private\r
+     * @return string\r
+     */\r
+    function EncodeQP ($str) {\r
+        $encoded = $this->FixEOL($str);\r
+        if (substr($encoded, -(strlen($this->LE))) != $this->LE)\r
+            $encoded .= $this->LE;\r
+\r
+        // Replace every high ascii, control and = characters\r
+        $encoded = preg_replace('/([\000-\010\013\014\016-\037\075\177-\377])/e',\r
+                  "'='.sprintf('%02X', ord('\\1'))", $encoded);\r
+        // Replace every spaces and tabs when it's the last character on a line\r
+        $encoded = preg_replace("/([\011\040])".$this->LE."/e",\r
+                  "'='.sprintf('%02X', ord('\\1')).'".$this->LE."'", $encoded);\r
+\r
+        // Maximum line length of 76 characters before CRLF (74 + space + '=')\r
+        $encoded = $this->WrapText($encoded, 74, true);\r
+\r
+        return $encoded;\r
+    }\r
+\r
+    /**\r
+     * Encode string to q encoding.  \r
+     * @access private\r
+     * @return string\r
+     */\r
+    function EncodeQ ($str, $position = "text") {\r
+        // There should not be any EOL in the string\r
+        $encoded = preg_replace("[\r\n]", "", $str);\r
+\r
+        switch (strtolower($position)) {\r
+          case "phrase":\r
+            $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);\r
+            break;\r
+          case "comment":\r
+            $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);\r
+          case "text":\r
+          default:\r
+            // Replace every high ascii, control =, ? and _ characters\r
+            $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',\r
+                  "'='.sprintf('%02X', ord('\\1'))", $encoded);\r
+            break;\r
+        }\r
+        \r
+        // Replace every spaces to _ (more readable than =20)\r
+        $encoded = str_replace(" ", "_", $encoded);\r
+\r
+        return $encoded;\r
+    }\r
+\r
+    /**\r
+     * Adds a string or binary attachment (non-filesystem) to the list.\r
+     * This method can be used to attach ascii or binary data,\r
+     * such as a BLOB record from a database.\r
+     * @param string $string String attachment data.\r
+     * @param string $filename Name of the attachment.\r
+     * @param string $encoding File encoding (see $Encoding).\r
+     * @param string $type File extension (MIME) type.\r
+     * @return void\r
+     */\r
+    function AddStringAttachment($string, $filename, $encoding = "base64", \r
+                                 $type = "application/octet-stream") {\r
+        // Append to $attachment array\r
+        $cur = count($this->attachment);\r
+        $this->attachment[$cur][0] = $string;\r
+        $this->attachment[$cur][1] = $filename;\r
+        $this->attachment[$cur][2] = $filename;\r
+        $this->attachment[$cur][3] = $encoding;\r
+        $this->attachment[$cur][4] = $type;\r
+        $this->attachment[$cur][5] = true; // isString\r
+        $this->attachment[$cur][6] = "attachment";\r
+        $this->attachment[$cur][7] = 0;\r
+    }\r
+    \r
+    /**\r
+     * Adds an embedded attachment.  This can include images, sounds, and \r
+     * just about any other document.  Make sure to set the $type to an \r
+     * image type.  For JPEG images use "image/jpeg" and for GIF images \r
+     * use "image/gif".\r
+     * @param string $path Path to the attachment.\r
+     * @param string $cid Content ID of the attachment.  Use this to identify \r
+     *        the Id for accessing the image in an HTML form.\r
+     * @param string $name Overrides the attachment name.\r
+     * @param string $encoding File encoding (see $Encoding).\r
+     * @param string $type File extension (MIME) type.  \r
+     * @return bool\r
+     */\r
+    function AddEmbeddedImage($path, $cid, $name = "", $encoding = "base64", \r
+                              $type = "application/octet-stream") {\r
+    \r
+        if(!@is_file($path))\r
+        {\r
+            $this->SetError($this->Lang("file_access") . $path);\r
+            return false;\r
+        }\r
+\r
+        $filename = basename($path);\r
+        if($name == "")\r
+            $name = $filename;\r
+\r
+        // Append to $attachment array\r
+        $cur = count($this->attachment);\r
+        $this->attachment[$cur][0] = $path;\r
+        $this->attachment[$cur][1] = $filename;\r
+        $this->attachment[$cur][2] = $name;\r
+        $this->attachment[$cur][3] = $encoding;\r
+        $this->attachment[$cur][4] = $type;\r
+        $this->attachment[$cur][5] = false; // isStringAttachment\r
+        $this->attachment[$cur][6] = "inline";\r
+        $this->attachment[$cur][7] = $cid;\r
+    \r
+        return true;\r
+    }\r
+    \r
+    /**\r
+     * Returns true if an inline attachment is present.\r
+     * @access private\r
+     * @return bool\r
+     */\r
+    function InlineImageExists() {\r
+        $result = false;\r
+        for($i = 0; $i < count($this->attachment); $i++)\r
+        {\r
+            if($this->attachment[$i][6] == "inline")\r
+            {\r
+                $result = true;\r
+                break;\r
+            }\r
+        }\r
+        \r
+        return $result;\r
+    }\r
+\r
+    /////////////////////////////////////////////////\r
+    // MESSAGE RESET METHODS\r
+    /////////////////////////////////////////////////\r
+\r
+    /**\r
+     * Clears all recipients assigned in the TO array.  Returns void.\r
+     * @return void\r
+     */\r
+    function ClearAddresses() {\r
+        $this->to = array();\r
+    }\r
+\r
+    /**\r
+     * Clears all recipients assigned in the CC array.  Returns void.\r
+     * @return void\r
+     */\r
+    function ClearCCs() {\r
+        $this->cc = array();\r
+    }\r
+\r
+    /**\r
+     * Clears all recipients assigned in the BCC array.  Returns void.\r
+     * @return void\r
+     */\r
+    function ClearBCCs() {\r
+        $this->bcc = array();\r
+    }\r
+\r
+    /**\r
+     * Clears all recipients assigned in the ReplyTo array.  Returns void.\r
+     * @return void\r
+     */\r
+    function ClearReplyTos() {\r
+        $this->ReplyTo = array();\r
+    }\r
+\r
+    /**\r
+     * Clears all recipients assigned in the TO, CC and BCC\r
+     * array.  Returns void.\r
+     * @return void\r
+     */\r
+    function ClearAllRecipients() {\r
+        $this->to = array();\r
+        $this->cc = array();\r
+        $this->bcc = array();\r
+    }\r
+\r
+    /**\r
+     * Clears all previously set filesystem, string, and binary\r
+     * attachments.  Returns void.\r
+     * @return void\r
+     */\r
+    function ClearAttachments() {\r
+        $this->attachment = array();\r
+    }\r
+\r
+    /**\r
+     * Clears all custom headers.  Returns void.\r
+     * @return void\r
+     */\r
+    function ClearCustomHeaders() {\r
+        $this->CustomHeader = array();\r
+    }\r
+\r
+\r
+    /////////////////////////////////////////////////\r
+    // MISCELLANEOUS METHODS\r
+    /////////////////////////////////////////////////\r
+\r
+    /**\r
+     * Adds the error message to the error container.\r
+     * Returns void.\r
+     * @access private\r
+     * @return void\r
+     */\r
+    function SetError($msg) {\r
+        $this->error_count++;\r
+        $this->ErrorInfo = $msg;\r
+    }\r
+\r
+    /**\r
+     * Returns the proper RFC 822 formatted date. \r
+     * @access private\r
+     * @return string\r
+     */\r
+    function RFCDate() {\r
+        $tz = date("Z");\r
+        $tzs = ($tz < 0) ? "-" : "+";\r
+        $tz = abs($tz);\r
+        $tz = ($tz/3600)*100 + ($tz%3600)/60;\r
+        $result = sprintf("%s %s%04d", date("D, j M Y H:i:s"), $tzs, $tz);\r
+\r
+        return $result;\r
+    }\r
+    \r
+    /**\r
+     * Returns the appropriate server variable.  Should work with both \r
+     * PHP 4.1.0+ as well as older versions.  Returns an empty string \r
+     * if nothing is found.\r
+     * @access private\r
+     * @return mixed\r
+     */\r
+    function ServerVar($varName) {\r
+        global $HTTP_SERVER_VARS;\r
+        global $HTTP_ENV_VARS;\r
+\r
+        if(!isset($_SERVER))\r
+        {\r
+            $_SERVER = $HTTP_SERVER_VARS;\r
+            if(!isset($_SERVER["REMOTE_ADDR"]))\r
+                $_SERVER = $HTTP_ENV_VARS; // must be Apache\r
+        }\r
+        \r
+        if(isset($_SERVER[$varName]))\r
+            return $_SERVER[$varName];\r
+        else\r
+            return "";\r
+    }\r
+\r
+    /**\r
+     * Returns the server hostname or 'localhost.localdomain' if unknown.\r
+     * @access private\r
+     * @return string\r
+     */\r
+    function ServerHostname() {\r
+        if ($this->Hostname != "")\r
+            $result = $this->Hostname;\r
+        elseif ($this->ServerVar('SERVER_NAME') != "")\r
+            $result = $this->ServerVar('SERVER_NAME');\r
+        else\r
+            $result = "localhost.localdomain";\r
+\r
+        return $result;\r
+    }\r
+\r
+    /**\r
+     * Returns a message in the appropriate language.\r
+     * @access private\r
+     * @return string\r
+     */\r
+    function Lang($key) {\r
+        if(count($this->language) < 1)\r
+            $this->SetLanguage("en"); // set the default language\r
+    \r
+        if(isset($this->language[$key]))\r
+            return $this->language[$key];\r
+        else\r
+            return "Language string failed to load: " . $key;\r
+    }\r
+    \r
+    /**\r
+     * Returns true if an error occurred.\r
+     * @return bool\r
+     */\r
+    function IsError() {\r
+        return ($this->error_count > 0);\r
+    }\r
+\r
+    /**\r
+     * Changes every end of line from CR or LF to CRLF.  \r
+     * @access private\r
+     * @return string\r
+     */\r
+    function FixEOL($str) {\r
+        $str = str_replace("\r\n", "\n", $str);\r
+        $str = str_replace("\r", "\n", $str);\r
+        $str = str_replace("\n", $this->LE, $str);\r
+        return $str;\r
+    }\r
+\r
+    /**\r
+     * Adds a custom header. \r
+     * @return void\r
+     */\r
+    function AddCustomHeader($custom_header) {\r
+        $this->CustomHeader[] = explode(":", $custom_header, 2);\r
+    }\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/include/classes/phpmailer/class.smtp.php b/include/classes/phpmailer/class.smtp.php
new file mode 100644 (file)
index 0000000..ad0fb52
--- /dev/null
@@ -0,0 +1,1045 @@
+<?php\r
+////////////////////////////////////////////////////\r
+// SMTP - PHP SMTP class\r
+//\r
+// Version 1.02\r
+//\r
+// Define an SMTP class that can be used to connect\r
+// and communicate with any SMTP server. It implements\r
+// all the SMTP functions defined in RFC821 except TURN.\r
+//\r
+// Author: Chris Ryan\r
+//\r
+// License: LGPL, see LICENSE\r
+////////////////////////////////////////////////////\r
+\r
+/**\r
+ * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP\r
+ * commands except TURN which will always return a not implemented\r
+ * error. SMTP also provides some utility methods for sending mail\r
+ * to an SMTP server.\r
+ * @package PHPMailer\r
+ * @author Chris Ryan\r
+ */\r
+class SMTP\r
+{\r
+    /**\r
+     *  SMTP server port\r
+     *  @var int\r
+     */\r
+    var $SMTP_PORT = 25;\r
+    \r
+    /**\r
+     *  SMTP reply line ending\r
+     *  @var string\r
+     */\r
+    var $CRLF = "\r\n";\r
+    \r
+    /**\r
+     *  Sets whether debugging is turned on\r
+     *  @var bool\r
+     */\r
+    var $do_debug;       # the level of debug to perform\r
+\r
+    /**#@+\r
+     * @access private\r
+     */\r
+    var $smtp_conn;      # the socket to the server\r
+    var $error;          # error if any on the last call\r
+    var $helo_rply;      # the reply the server sent to us for HELO\r
+    /**#@-*/\r
+\r
+    /**\r
+     * Initialize the class so that the data is in a known state.\r
+     * @access public\r
+     * @return void\r
+     */\r
+    function SMTP() {\r
+        $this->smtp_conn = 0;\r
+        $this->error = null;\r
+        $this->helo_rply = null;\r
+\r
+        $this->do_debug = 0;\r
+    }\r
+\r
+    /*************************************************************\r
+     *                    CONNECTION FUNCTIONS                  *\r
+     ***********************************************************/\r
+\r
+    /**\r
+     * Connect to the server specified on the port specified.\r
+     * If the port is not specified use the default SMTP_PORT.\r
+     * If tval is specified then a connection will try and be\r
+     * established with the server for that number of seconds.\r
+     * If tval is not specified the default is 30 seconds to\r
+     * try on the connection.\r
+     *\r
+     * SMTP CODE SUCCESS: 220\r
+     * SMTP CODE FAILURE: 421\r
+     * @access public\r
+     * @return bool\r
+     */\r
+    function Connect($host,$port=0,$tval=30) {\r
+        # set the error val to null so there is no confusion\r
+        $this->error = null;\r
+\r
+        # make sure we are __not__ connected\r
+        if($this->connected()) {\r
+            # ok we are connected! what should we do?\r
+            # for now we will just give an error saying we\r
+            # are already connected\r
+            $this->error =\r
+                array("error" => "Already connected to a server");\r
+            return false;\r
+        }\r
+\r
+        if(empty($port)) {\r
+            $port = $this->SMTP_PORT;\r
+        }\r
+\r
+        #connect to the smtp server\r
+        $this->smtp_conn = @fsockopen($host,    # the host of the server\r
+                                     $port,    # the port to use\r
+                                     $errno,   # error number if any\r
+                                     $errstr,  # error message if any\r
+                                     $tval);   # give up after ? secs\r
+        # verify we connected properly\r
+        if(empty($this->smtp_conn)) {\r
+            $this->error = array("error" => "Failed to connect to server",\r
+                                 "errno" => $errno,\r
+                                 "errstr" => $errstr);\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $this->error["error"] .\r
+                         ": $errstr ($errno)" . $this->CRLF;\r
+            }\r
+            return false;\r
+        }\r
+\r
+        # sometimes the SMTP server takes a little longer to respond\r
+        # so we will give it a longer timeout for the first read\r
+        // Windows still does not have support for this timeout function\r
+        if(substr(PHP_OS, 0, 3) != "WIN")\r
+           socket_set_timeout($this->smtp_conn, $tval, 0);\r
+\r
+        # get any announcement stuff\r
+        $announce = $this->get_lines();\r
+\r
+        # set the timeout  of any socket functions at 1/10 of a second\r
+        //if(function_exists("socket_set_timeout"))\r
+        //   socket_set_timeout($this->smtp_conn, 0, 100000);\r
+\r
+        if($this->do_debug >= 2) {\r
+            echo "SMTP -> FROM SERVER:" . $this->CRLF . $announce;\r
+        }\r
+\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Performs SMTP authentication.  Must be run after running the\r
+     * Hello() method.  Returns true if successfully authenticated.\r
+     * @access public\r
+     * @return bool\r
+     */\r
+    function Authenticate($username, $password) {\r
+        // Start authentication\r
+        fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);\r
+\r
+        $rply = $this->get_lines();\r
+        $code = substr($rply,0,3);\r
+\r
+        if($code != 334) {\r
+            $this->error =\r
+                array("error" => "AUTH not accepted from server",\r
+                      "smtp_code" => $code,\r
+                      "smtp_msg" => substr($rply,4));\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $this->error["error"] .\r
+                         ": " . $rply . $this->CRLF;\r
+            }\r
+            return false;\r
+        }\r
+\r
+        // Send encoded username\r
+        fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);\r
+\r
+        $rply = $this->get_lines();\r
+        $code = substr($rply,0,3);\r
+\r
+        if($code != 334) {\r
+            $this->error =\r
+                array("error" => "Username not accepted from server",\r
+                      "smtp_code" => $code,\r
+                      "smtp_msg" => substr($rply,4));\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $this->error["error"] .\r
+                         ": " . $rply . $this->CRLF;\r
+            }\r
+            return false;\r
+        }\r
+\r
+        // Send encoded password\r
+        fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);\r
+\r
+        $rply = $this->get_lines();\r
+        $code = substr($rply,0,3);\r
+\r
+        if($code != 235) {\r
+            $this->error =\r
+                array("error" => "Password not accepted from server",\r
+                      "smtp_code" => $code,\r
+                      "smtp_msg" => substr($rply,4));\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $this->error["error"] .\r
+                         ": " . $rply . $this->CRLF;\r
+            }\r
+            return false;\r
+        }\r
+\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Returns true if connected to a server otherwise false\r
+     * @access private\r
+     * @return bool\r
+     */\r
+    function Connected() {\r
+        if(!empty($this->smtp_conn)) {\r
+            $sock_status = socket_get_status($this->smtp_conn);\r
+            if($sock_status["eof"]) {\r
+                # hmm this is an odd situation... the socket is\r
+                # valid but we aren't connected anymore\r
+                if($this->do_debug >= 1) {\r
+                    echo "SMTP -> NOTICE:" . $this->CRLF .\r
+                         "EOF caught while checking if connected";\r
+                }\r
+                $this->Close();\r
+                return false;\r
+            }\r
+            return true; # everything looks good\r
+        }\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Closes the socket and cleans up the state of the class.\r
+     * It is not considered good to use this function without\r
+     * first trying to use QUIT.\r
+     * @access public\r
+     * @return void\r
+     */\r
+    function Close() {\r
+        $this->error = null; # so there is no confusion\r
+        $this->helo_rply = null;\r
+        if(!empty($this->smtp_conn)) {\r
+            # close the connection and cleanup\r
+            fclose($this->smtp_conn);\r
+            $this->smtp_conn = 0;\r
+        }\r
+    }\r
+\r
+\r
+    /***************************************************************\r
+     *                        SMTP COMMANDS                       *\r
+     *************************************************************/\r
+\r
+    /**\r
+     * Issues a data command and sends the msg_data to the server\r
+     * finializing the mail transaction. $msg_data is the message\r
+     * that is to be send with the headers. Each header needs to be\r
+     * on a single line followed by a <CRLF> with the message headers\r
+     * and the message body being seperated by and additional <CRLF>.\r
+     *\r
+     * Implements rfc 821: DATA <CRLF>\r
+     *\r
+     * SMTP CODE INTERMEDIATE: 354\r
+     *     [data]\r
+     *     <CRLF>.<CRLF>\r
+     *     SMTP CODE SUCCESS: 250\r
+     *     SMTP CODE FAILURE: 552,554,451,452\r
+     * SMTP CODE FAILURE: 451,554\r
+     * SMTP CODE ERROR  : 500,501,503,421\r
+     * @access public\r
+     * @return bool\r
+     */\r
+    function Data($msg_data) {\r
+        $this->error = null; # so no confusion is caused\r
+\r
+        if(!$this->connected()) {\r
+            $this->error = array(\r
+                    "error" => "Called Data() without being connected");\r
+            return false;\r
+        }\r
+\r
+        fputs($this->smtp_conn,"DATA" . $this->CRLF);\r
+\r
+        $rply = $this->get_lines();\r
+        $code = substr($rply,0,3);\r
+\r
+        if($this->do_debug >= 2) {\r
+            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
+        }\r
+\r
+        if($code != 354) {\r
+            $this->error =\r
+                array("error" => "DATA command not accepted from server",\r
+                      "smtp_code" => $code,\r
+                      "smtp_msg" => substr($rply,4));\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $this->error["error"] .\r
+                         ": " . $rply . $this->CRLF;\r
+            }\r
+            return false;\r
+        }\r
+\r
+        # the server is ready to accept data!\r
+        # according to rfc 821 we should not send more than 1000\r
+        # including the CRLF\r
+        # characters on a single line so we will break the data up\r
+        # into lines by \r and/or \n then if needed we will break\r
+        # each of those into smaller lines to fit within the limit.\r
+        # in addition we will be looking for lines that start with\r
+        # a period '.' and append and additional period '.' to that\r
+        # line. NOTE: this does not count towards are limit.\r
+\r
+        # normalize the line breaks so we know the explode works\r
+        $msg_data = str_replace("\r\n","\n",$msg_data);\r
+        $msg_data = str_replace("\r","\n",$msg_data);\r
+        $lines = explode("\n",$msg_data);\r
+\r
+        # we need to find a good way to determine is headers are\r
+        # in the msg_data or if it is a straight msg body\r
+        # currently I'm assuming rfc 822 definitions of msg headers\r
+        # and if the first field of the first line (':' sperated)\r
+        # does not contain a space then it _should_ be a header\r
+        # and we can process all lines before a blank "" line as\r
+        # headers.\r
+        $field = substr($lines[0],0,strpos($lines[0],":"));\r
+        $in_headers = false;\r
+        if(!empty($field) && !strstr($field," ")) {\r
+            $in_headers = true;\r
+        }\r
+\r
+        $max_line_length = 998; # used below; set here for ease in change\r
+\r
+        while(list(,$line) = @each($lines)) {\r
+            $lines_out = null;\r
+            if($line == "" && $in_headers) {\r
+                $in_headers = false;\r
+            }\r
+            # ok we need to break this line up into several\r
+            # smaller lines\r
+            while(strlen($line) > $max_line_length) {\r
+                $pos = strrpos(substr($line,0,$max_line_length)," ");\r
+\r
+                # Patch to fix DOS attack\r
+                if(!$pos) {\r
+                    $pos = $max_line_length - 1;\r
+                }\r
+\r
+                $lines_out[] = substr($line,0,$pos);\r
+                $line = substr($line,$pos + 1);\r
+                # if we are processing headers we need to\r
+                # add a LWSP-char to the front of the new line\r
+                # rfc 822 on long msg headers\r
+                if($in_headers) {\r
+                    $line = "\t" . $line;\r
+                }\r
+            }\r
+            $lines_out[] = $line;\r
+\r
+            # now send the lines to the server\r
+            while(list(,$line_out) = @each($lines_out)) {\r
+                if(strlen($line_out) > 0)\r
+                {\r
+                    if(substr($line_out, 0, 1) == ".") {\r
+                        $line_out = "." . $line_out;\r
+                    }\r
+                }\r
+                fputs($this->smtp_conn,$line_out . $this->CRLF);\r
+            }\r
+        }\r
+\r
+        # ok all the message data has been sent so lets get this\r
+        # over with aleady\r
+        fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);\r
+\r
+        $rply = $this->get_lines();\r
+        $code = substr($rply,0,3);\r
+\r
+        if($this->do_debug >= 2) {\r
+            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
+        }\r
+\r
+        if($code != 250) {\r
+            $this->error =\r
+                array("error" => "DATA not accepted from server",\r
+                      "smtp_code" => $code,\r
+                      "smtp_msg" => substr($rply,4));\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $this->error["error"] .\r
+                         ": " . $rply . $this->CRLF;\r
+            }\r
+            return false;\r
+        }\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Expand takes the name and asks the server to list all the\r
+     * people who are members of the _list_. Expand will return\r
+     * back and array of the result or false if an error occurs.\r
+     * Each value in the array returned has the format of:\r
+     *     [ <full-name> <sp> ] <path>\r
+     * The definition of <path> is defined in rfc 821\r
+     *\r
+     * Implements rfc 821: EXPN <SP> <string> <CRLF>\r
+     *\r
+     * SMTP CODE SUCCESS: 250\r
+     * SMTP CODE FAILURE: 550\r
+     * SMTP CODE ERROR  : 500,501,502,504,421\r
+     * @access public\r
+     * @return string array\r
+     */\r
+    function Expand($name) {\r
+        $this->error = null; # so no confusion is caused\r
+\r
+        if(!$this->connected()) {\r
+            $this->error = array(\r
+                    "error" => "Called Expand() without being connected");\r
+            return false;\r
+        }\r
+\r
+        fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF);\r
+\r
+        $rply = $this->get_lines();\r
+        $code = substr($rply,0,3);\r
+\r
+        if($this->do_debug >= 2) {\r
+            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
+        }\r
+\r
+        if($code != 250) {\r
+            $this->error =\r
+                array("error" => "EXPN not accepted from server",\r
+                      "smtp_code" => $code,\r
+                      "smtp_msg" => substr($rply,4));\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $this->error["error"] .\r
+                         ": " . $rply . $this->CRLF;\r
+            }\r
+            return false;\r
+        }\r
+\r
+        # parse the reply and place in our array to return to user\r
+        $entries = explode($this->CRLF,$rply);\r
+        while(list(,$l) = @each($entries)) {\r
+            $list[] = substr($l,4);\r
+        }\r
+\r
+        return $list;\r
+    }\r
+\r
+    /**\r
+     * Sends the HELO command to the smtp server.\r
+     * This makes sure that we and the server are in\r
+     * the same known state.\r
+     *\r
+     * Implements from rfc 821: HELO <SP> <domain> <CRLF>\r
+     *\r
+     * SMTP CODE SUCCESS: 250\r
+     * SMTP CODE ERROR  : 500, 501, 504, 421\r
+     * @access public\r
+     * @return bool\r
+     */\r
+    function Hello($host="") {\r
+        $this->error = null; # so no confusion is caused\r
+\r
+        if(!$this->connected()) {\r
+            $this->error = array(\r
+                    "error" => "Called Hello() without being connected");\r
+            return false;\r
+        }\r
+\r
+        # if a hostname for the HELO wasn't specified determine\r
+        # a suitable one to send\r
+        if(empty($host)) {\r
+            # we need to determine some sort of appopiate default\r
+            # to send to the server\r
+            $host = "localhost";\r
+        }\r
+\r
+        // Send extended hello first (RFC 2821)\r
+        if(!$this->SendHello("EHLO", $host))\r
+        {\r
+            if(!$this->SendHello("HELO", $host))\r
+                return false;\r
+        }\r
+\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Sends a HELO/EHLO command.\r
+     * @access private\r
+     * @return bool\r
+     */\r
+    function SendHello($hello, $host) {\r
+        fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);\r
+\r
+        $rply = $this->get_lines();\r
+        $code = substr($rply,0,3);\r
+\r
+        if($this->do_debug >= 2) {\r
+            echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply;\r
+        }\r
+\r
+        if($code != 250) {\r
+            $this->error =\r
+                array("error" => $hello . " not accepted from server",\r
+                      "smtp_code" => $code,\r
+                      "smtp_msg" => substr($rply,4));\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $this->error["error"] .\r
+                         ": " . $rply . $this->CRLF;\r
+            }\r
+            return false;\r
+        }\r
+\r
+        $this->helo_rply = $rply;\r
+        \r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Gets help information on the keyword specified. If the keyword\r
+     * is not specified then returns generic help, ussually contianing\r
+     * A list of keywords that help is available on. This function\r
+     * returns the results back to the user. It is up to the user to\r
+     * handle the returned data. If an error occurs then false is\r
+     * returned with $this->error set appropiately.\r
+     *\r
+     * Implements rfc 821: HELP [ <SP> <string> ] <CRLF>\r
+     *\r
+     * SMTP CODE SUCCESS: 211,214\r
+     * SMTP CODE ERROR  : 500,501,502,504,421\r
+     * @access public\r
+     * @return string\r
+     */\r
+    function Help($keyword="") {\r
+        $this->error = null; # to avoid confusion\r
+\r
+        if(!$this->connected()) {\r
+            $this->error = array(\r
+                    "error" => "Called Help() without being connected");\r
+            return false;\r
+        }\r
+\r
+        $extra = "";\r
+        if(!empty($keyword)) {\r
+            $extra = " " . $keyword;\r
+        }\r
+\r
+        fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF);\r
+\r
+        $rply = $this->get_lines();\r
+        $code = substr($rply,0,3);\r
+\r
+        if($this->do_debug >= 2) {\r
+            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
+        }\r
+\r
+        if($code != 211 && $code != 214) {\r
+            $this->error =\r
+                array("error" => "HELP not accepted from server",\r
+                      "smtp_code" => $code,\r
+                      "smtp_msg" => substr($rply,4));\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $this->error["error"] .\r
+                         ": " . $rply . $this->CRLF;\r
+            }\r
+            return false;\r
+        }\r
+\r
+        return $rply;\r
+    }\r
+\r
+    /**\r
+     * Starts a mail transaction from the email address specified in\r
+     * $from. Returns true if successful or false otherwise. If True\r
+     * the mail transaction is started and then one or more Recipient\r
+     * commands may be called followed by a Data command.\r
+     *\r
+     * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>\r
+     *\r
+     * SMTP CODE SUCCESS: 250\r
+     * SMTP CODE SUCCESS: 552,451,452\r
+     * SMTP CODE SUCCESS: 500,501,421\r
+     * @access public\r
+     * @return bool\r
+     */\r
+    function Mail($from) {\r
+        $this->error = null; # so no confusion is caused\r
+\r
+        if(!$this->connected()) {\r
+            $this->error = array(\r
+                    "error" => "Called Mail() without being connected");\r
+            return false;\r
+        }\r
+\r
+        fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $this->CRLF);\r
+\r
+        $rply = $this->get_lines();\r
+        $code = substr($rply,0,3);\r
+\r
+        if($this->do_debug >= 2) {\r
+            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
+        }\r
+\r
+        if($code != 250) {\r
+            $this->error =\r
+                array("error" => "MAIL not accepted from server",\r
+                      "smtp_code" => $code,\r
+                      "smtp_msg" => substr($rply,4));\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $this->error["error"] .\r
+                         ": " . $rply . $this->CRLF;\r
+            }\r
+            return false;\r
+        }\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Sends the command NOOP to the SMTP server.\r
+     *\r
+     * Implements from rfc 821: NOOP <CRLF>\r
+     *\r
+     * SMTP CODE SUCCESS: 250\r
+     * SMTP CODE ERROR  : 500, 421\r
+     * @access public\r
+     * @return bool\r
+     */\r
+    function Noop() {\r
+        $this->error = null; # so no confusion is caused\r
+\r
+        if(!$this->connected()) {\r
+            $this->error = array(\r
+                    "error" => "Called Noop() without being connected");\r
+            return false;\r
+        }\r
+\r
+        fputs($this->smtp_conn,"NOOP" . $this->CRLF);\r
+\r
+        $rply = $this->get_lines();\r
+        $code = substr($rply,0,3);\r
+\r
+        if($this->do_debug >= 2) {\r
+            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
+        }\r
+\r
+        if($code != 250) {\r
+            $this->error =\r
+                array("error" => "NOOP not accepted from server",\r
+                      "smtp_code" => $code,\r
+                      "smtp_msg" => substr($rply,4));\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $this->error["error"] .\r
+                         ": " . $rply . $this->CRLF;\r
+            }\r
+            return false;\r
+        }\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Sends the quit command to the server and then closes the socket\r
+     * if there is no error or the $close_on_error argument is true.\r
+     *\r
+     * Implements from rfc 821: QUIT <CRLF>\r
+     *\r
+     * SMTP CODE SUCCESS: 221\r
+     * SMTP CODE ERROR  : 500\r
+     * @access public\r
+     * @return bool\r
+     */\r
+    function Quit($close_on_error=true) {\r
+        $this->error = null; # so there is no confusion\r
+\r
+        if(!$this->connected()) {\r
+            $this->error = array(\r
+                    "error" => "Called Quit() without being connected");\r
+            return false;\r
+        }\r
+\r
+        # send the quit command to the server\r
+        fputs($this->smtp_conn,"quit" . $this->CRLF);\r
+\r
+        # get any good-bye messages\r
+        $byemsg = $this->get_lines();\r
+\r
+        if($this->do_debug >= 2) {\r
+            echo "SMTP -> FROM SERVER:" . $this->CRLF . $byemsg;\r
+        }\r
+\r
+        $rval = true;\r
+        $e = null;\r
+\r
+        $code = substr($byemsg,0,3);\r
+        if($code != 221) {\r
+            # use e as a tmp var cause Close will overwrite $this->error\r
+            $e = array("error" => "SMTP server rejected quit command",\r
+                       "smtp_code" => $code,\r
+                       "smtp_rply" => substr($byemsg,4));\r
+            $rval = false;\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $e["error"] . ": " .\r
+                         $byemsg . $this->CRLF;\r
+            }\r
+        }\r
+\r
+        if(empty($e) || $close_on_error) {\r
+            $this->Close();\r
+        }\r
+\r
+        return $rval;\r
+    }\r
+\r
+    /**\r
+     * Sends the command RCPT to the SMTP server with the TO: argument of $to.\r
+     * Returns true if the recipient was accepted false if it was rejected.\r
+     *\r
+     * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>\r
+     *\r
+     * SMTP CODE SUCCESS: 250,251\r
+     * SMTP CODE FAILURE: 550,551,552,553,450,451,452\r
+     * SMTP CODE ERROR  : 500,501,503,421\r
+     * @access public\r
+     * @return bool\r
+     */\r
+    function Recipient($to) {\r
+        $this->error = null; # so no confusion is caused\r
+\r
+        if(!$this->connected()) {\r
+            $this->error = array(\r
+                    "error" => "Called Recipient() without being connected");\r
+            return false;\r
+        }\r
+\r
+        fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);\r
+\r
+        $rply = $this->get_lines();\r
+        $code = substr($rply,0,3);\r
+\r
+        if($this->do_debug >= 2) {\r
+            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
+        }\r
+\r
+        if($code != 250 && $code != 251) {\r
+            $this->error =\r
+                array("error" => "RCPT not accepted from server",\r
+                      "smtp_code" => $code,\r
+                      "smtp_msg" => substr($rply,4));\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $this->error["error"] .\r
+                         ": " . $rply . $this->CRLF;\r
+            }\r
+            return false;\r
+        }\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Sends the RSET command to abort and transaction that is\r
+     * currently in progress. Returns true if successful false\r
+     * otherwise.\r
+     *\r
+     * Implements rfc 821: RSET <CRLF>\r
+     *\r
+     * SMTP CODE SUCCESS: 250\r
+     * SMTP CODE ERROR  : 500,501,504,421\r
+     * @access public\r
+     * @return bool\r
+     */\r
+    function Reset() {\r
+        $this->error = null; # so no confusion is caused\r
+\r
+        if(!$this->connected()) {\r
+            $this->error = array(\r
+                    "error" => "Called Reset() without being connected");\r
+            return false;\r
+        }\r
+\r
+        fputs($this->smtp_conn,"RSET" . $this->CRLF);\r
+\r
+        $rply = $this->get_lines();\r
+        $code = substr($rply,0,3);\r
+\r
+        if($this->do_debug >= 2) {\r
+            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
+        }\r
+\r
+        if($code != 250) {\r
+            $this->error =\r
+                array("error" => "RSET failed",\r
+                      "smtp_code" => $code,\r
+                      "smtp_msg" => substr($rply,4));\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $this->error["error"] .\r
+                         ": " . $rply . $this->CRLF;\r
+            }\r
+            return false;\r
+        }\r
+\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Starts a mail transaction from the email address specified in\r
+     * $from. Returns true if successful or false otherwise. If True\r
+     * the mail transaction is started and then one or more Recipient\r
+     * commands may be called followed by a Data command. This command\r
+     * will send the message to the users terminal if they are logged\r
+     * in.\r
+     *\r
+     * Implements rfc 821: SEND <SP> FROM:<reverse-path> <CRLF>\r
+     *\r
+     * SMTP CODE SUCCESS: 250\r
+     * SMTP CODE SUCCESS: 552,451,452\r
+     * SMTP CODE SUCCESS: 500,501,502,421\r
+     * @access public\r
+     * @return bool\r
+     */\r
+    function Send($from) {\r
+        $this->error = null; # so no confusion is caused\r
+\r
+        if(!$this->connected()) {\r
+            $this->error = array(\r
+                    "error" => "Called Send() without being connected");\r
+            return false;\r
+        }\r
+\r
+        fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF);\r
+\r
+        $rply = $this->get_lines();\r
+        $code = substr($rply,0,3);\r
+\r
+        if($this->do_debug >= 2) {\r
+            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
+        }\r
+\r
+        if($code != 250) {\r
+            $this->error =\r
+                array("error" => "SEND not accepted from server",\r
+                      "smtp_code" => $code,\r
+                      "smtp_msg" => substr($rply,4));\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $this->error["error"] .\r
+                         ": " . $rply . $this->CRLF;\r
+            }\r
+            return false;\r
+        }\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Starts a mail transaction from the email address specified in\r
+     * $from. Returns true if successful or false otherwise. If True\r
+     * the mail transaction is started and then one or more Recipient\r
+     * commands may be called followed by a Data command. This command\r
+     * will send the message to the users terminal if they are logged\r
+     * in and send them an email.\r
+     *\r
+     * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>\r
+     *\r
+     * SMTP CODE SUCCESS: 250\r
+     * SMTP CODE SUCCESS: 552,451,452\r
+     * SMTP CODE SUCCESS: 500,501,502,421\r
+     * @access public\r
+     * @return bool\r
+     */\r
+    function SendAndMail($from) {\r
+        $this->error = null; # so no confusion is caused\r
+\r
+        if(!$this->connected()) {\r
+            $this->error = array(\r
+                "error" => "Called SendAndMail() without being connected");\r
+            return false;\r
+        }\r
+\r
+        fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);\r
+\r
+        $rply = $this->get_lines();\r
+        $code = substr($rply,0,3);\r
+\r
+        if($this->do_debug >= 2) {\r
+            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
+        }\r
+\r
+        if($code != 250) {\r
+            $this->error =\r
+                array("error" => "SAML not accepted from server",\r
+                      "smtp_code" => $code,\r
+                      "smtp_msg" => substr($rply,4));\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $this->error["error"] .\r
+                         ": " . $rply . $this->CRLF;\r
+            }\r
+            return false;\r
+        }\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Starts a mail transaction from the email address specified in\r
+     * $from. Returns true if successful or false otherwise. If True\r
+     * the mail transaction is started and then one or more Recipient\r
+     * commands may be called followed by a Data command. This command\r
+     * will send the message to the users terminal if they are logged\r
+     * in or mail it to them if they are not.\r
+     *\r
+     * Implements rfc 821: SOML <SP> FROM:<reverse-path> <CRLF>\r
+     *\r
+     * SMTP CODE SUCCESS: 250\r
+     * SMTP CODE SUCCESS: 552,451,452\r
+     * SMTP CODE SUCCESS: 500,501,502,421\r
+     * @access public\r
+     * @return bool\r
+     */\r
+    function SendOrMail($from) {\r
+        $this->error = null; # so no confusion is caused\r
+\r
+        if(!$this->connected()) {\r
+            $this->error = array(\r
+                "error" => "Called SendOrMail() without being connected");\r
+            return false;\r
+        }\r
+\r
+        fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF);\r
+\r
+        $rply = $this->get_lines();\r
+        $code = substr($rply,0,3);\r
+\r
+        if($this->do_debug >= 2) {\r
+            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
+        }\r
+\r
+        if($code != 250) {\r
+            $this->error =\r
+                array("error" => "SOML not accepted from server",\r
+                      "smtp_code" => $code,\r
+                      "smtp_msg" => substr($rply,4));\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $this->error["error"] .\r
+                         ": " . $rply . $this->CRLF;\r
+            }\r
+            return false;\r
+        }\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * This is an optional command for SMTP that this class does not\r
+     * support. This method is here to make the RFC821 Definition\r
+     * complete for this class and __may__ be implimented in the future\r
+     *\r
+     * Implements from rfc 821: TURN <CRLF>\r
+     *\r
+     * SMTP CODE SUCCESS: 250\r
+     * SMTP CODE FAILURE: 502\r
+     * SMTP CODE ERROR  : 500, 503\r
+     * @access public\r
+     * @return bool\r
+     */\r
+    function Turn() {\r
+        $this->error = array("error" => "This method, TURN, of the SMTP ".\r
+                                        "is not implemented");\r
+        if($this->do_debug >= 1) {\r
+            echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF;\r
+        }\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Verifies that the name is recognized by the server.\r
+     * Returns false if the name could not be verified otherwise\r
+     * the response from the server is returned.\r
+     *\r
+     * Implements rfc 821: VRFY <SP> <string> <CRLF>\r
+     *\r
+     * SMTP CODE SUCCESS: 250,251\r
+     * SMTP CODE FAILURE: 550,551,553\r
+     * SMTP CODE ERROR  : 500,501,502,421\r
+     * @access public\r
+     * @return int\r
+     */\r
+    function Verify($name) {\r
+        $this->error = null; # so no confusion is caused\r
+\r
+        if(!$this->connected()) {\r
+            $this->error = array(\r
+                    "error" => "Called Verify() without being connected");\r
+            return false;\r
+        }\r
+\r
+        fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF);\r
+\r
+        $rply = $this->get_lines();\r
+        $code = substr($rply,0,3);\r
+\r
+        if($this->do_debug >= 2) {\r
+            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
+        }\r
+\r
+        if($code != 250 && $code != 251) {\r
+            $this->error =\r
+                array("error" => "VRFY failed on name '$name'",\r
+                      "smtp_code" => $code,\r
+                      "smtp_msg" => substr($rply,4));\r
+            if($this->do_debug >= 1) {\r
+                echo "SMTP -> ERROR: " . $this->error["error"] .\r
+                         ": " . $rply . $this->CRLF;\r
+            }\r
+            return false;\r
+        }\r
+        return $rply;\r
+    }\r
+\r
+    /*******************************************************************\r
+     *                       INTERNAL FUNCTIONS                       *\r
+     ******************************************************************/\r
+\r
+    /**\r
+     * Read in as many lines as possible\r
+     * either before eof or socket timeout occurs on the operation.\r
+     * With SMTP we can tell if we have more lines to read if the\r
+     * 4th character is '-' symbol. If it is a space then we don't\r
+     * need to read anything else.\r
+     * @access private\r
+     * @return string\r
+     */\r
+    function get_lines() {\r
+        $data = "";\r
+        while($str = fgets($this->smtp_conn,515)) {\r
+            if($this->do_debug >= 4) {\r
+                echo "SMTP -> get_lines(): \$data was \"$data\"" .\r
+                         $this->CRLF;\r
+                echo "SMTP -> get_lines(): \$str is \"$str\"" .\r
+                         $this->CRLF;\r
+            }\r
+            $data .= $str;\r
+            if($this->do_debug >= 4) {\r
+                echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF;\r
+            }\r
+            # if the 4th character is a space then we are done reading\r
+            # so just break the loop\r
+            if(substr($str,3,1) == " ") { break; }\r
+        }\r
+        return $data;\r
+    }\r
+\r
+}\r
+\r
+\r
+ ?>\r
diff --git a/include/classes/phpmailer/phpmailer.lang-en.php b/include/classes/phpmailer/phpmailer.lang-en.php
new file mode 100644 (file)
index 0000000..2f45383
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+/**
+ * PHPMailer language file.  
+ * English Version
+ */
+
+$PHPMAILER_LANG = array();
+
+$PHPMAILER_LANG["provide_address"] = 'You must provide at least one ' .
+                                     'recipient email address.';
+$PHPMAILER_LANG["mailer_not_supported"] = ' mailer is not supported.';
+$PHPMAILER_LANG["execute"] = 'Could not execute: ';
+$PHPMAILER_LANG["instantiate"] = 'Could not instantiate mail function.';
+$PHPMAILER_LANG["authenticate"] = 'SMTP Error: Could not authenticate.';
+$PHPMAILER_LANG["from_failed"] = 'The following From address failed: ';
+$PHPMAILER_LANG["recipients_failed"] = 'SMTP Error: The following ' .
+                                       'recipients failed: ';
+$PHPMAILER_LANG["data_not_accepted"] = 'SMTP Error: Data not accepted.';
+$PHPMAILER_LANG["connect_host"] = 'SMTP Error: Could not connect to SMTP host.';
+$PHPMAILER_LANG["file_access"] = 'Could not access file: ';
+$PHPMAILER_LANG["file_open"] = 'File Error: Could not open file: ';
+$PHPMAILER_LANG["encoding"] = 'Unknown encoding: ';
+?>
diff --git a/include/classes/sqlutility.class.php b/include/classes/sqlutility.class.php
new file mode 100644 (file)
index 0000000..dd4a707
--- /dev/null
@@ -0,0 +1,187 @@
+<?php
+
+
+class SqlUtility
+{
+       /**
+       * Function from phpMyAdmin (http://phpwizard.net/projects/phpMyAdmin/)
+       *
+       * Removes comment and splits large sql files into individual queries
+       *
+       * Last revision: September 23, 2001 - gandon
+       *
+       * @param   array    the splitted sql commands
+       * @param   string   the sql commands
+       * @return  boolean  always true
+       * @access  public
+       */
+       function splitSqlFile(&$ret, $sql)
+       {
+               $sql               = trim($sql);
+               $sql_len           = strlen($sql);
+               $char              = '';
+       $string_start      = '';
+       $in_string         = false;
+
+       for ($i = 0; $i < $sql_len; ++$i) {
+               $char = $sql[$i];
+
+           // We are in a string, check for not escaped end of
+                  // strings except for backquotes that can't be escaped
+           if ($in_string) {
+                       for (;;) {
+                               $i         = strpos($sql, $string_start, $i);
+                                       // No end of string found -> add the current
+                                       // substring to the returned array
+                       if (!$i) {
+                                               $ret[] = $sql;
+                       return true;
+                       }
+                                       // Backquotes or no backslashes before 
+                                       // quotes: it's indeed the end of the 
+                                       // string -> exit the loop
+                       else if ($string_start == '`' || $sql[$i-1] != '\\') {
+                                               $string_start      = '';
+                               $in_string         = false;
+                       break;
+                       }
+                       // one or more Backslashes before the presumed 
+                                       // end of string...
+                       else {
+                                               // first checks for escaped backslashes
+                       $j                     = 2;
+                       $escaped_backslash     = false;
+                                               while ($i-$j > 0 && $sql[$i-$j] == '\\') {
+                                                       $escaped_backslash = !$escaped_backslash;
+                               $j++;
+                       }
+                       // ... if escaped backslashes: it's really the 
+                                               // end of the string -> exit the loop
+                       if ($escaped_backslash) {
+                                                       $string_start  = '';
+                               $in_string     = false;
+                                                       break;
+                       }
+                       // ... else loop
+                       else {
+                                                       $i++;
+                       }
+                       } // end if...elseif...else
+               } // end for
+               } // end if (in string)
+               // We are not in a string, first check for delimiter...
+               else if ($char == ';') {
+                               // if delimiter found, add the parsed part to the returned array
+               $ret[]    = substr($sql, 0, $i);
+               $sql      = ltrim(substr($sql, min($i + 1, $sql_len)));
+                       $sql_len  = strlen($sql);
+               if ($sql_len) {
+                                       $i      = -1;
+               } else {
+                       // The submited statement(s) end(s) here
+                       return true;
+                               }
+               } // end else if (is delimiter)
+               // ... then check for start of a string,...
+               else if (($char == '"') || ($char == '\'') || ($char == '`')) {
+                               $in_string    = true;
+                               $string_start = $char;
+               } // end else if (is start of string)
+
+               // for start of a comment (and remove this comment if found)...
+               else if ($char == '#' || ($char == ' ' && $i > 1 && $sql[$i-2] . $sql[$i-1] == '--')) {
+               // starting position of the comment depends on the comment type
+                       $start_of_comment = (($sql[$i] == '#') ? $i : $i-2);
+               // if no "\n" exits in the remaining string, checks for "\r"
+               // (Mac eol style)
+                       $end_of_comment   = (strpos(' ' . $sql, "\012", $i+2))
+                              ? strpos(' ' . $sql, "\012", $i+2)
+                              : strpos(' ' . $sql, "\015", $i+2);
+                       if (!$end_of_comment) {
+                // no eol found after '#', add the parsed part to the returned
+                // array and exit
+                               $ret[]   = trim(substr($sql, 0, $i-1));
+                               return true;
+                               } else {
+                       $sql     = substr($sql, 0, $start_of_comment) . ltrim(substr($sql, $end_of_comment));
+                       $sql_len = strlen($sql);
+                       $i--;
+               } // end if...else
+               } // end else if (is comment)
+       } // end for
+
+       // add any rest to the returned array
+       if (!empty($sql) && trim($sql) != '') {
+                       $ret[] = $sql;
+       }
+       return true;
+       }
+
+       /**
+        * add a prefix.'_' to all tablenames in a query
+     * 
+     * @param   string  $query  valid MySQL query string
+     * @param   string  $prefix prefix to add to all table names
+        * @return  mixed   FALSE on failure
+        */
+       function prefixQuery($query, $prefix)
+       {
+               $pattern = "/^(INSERT INTO|CREATE TABLE|ALTER TABLE|UPDATE)(\s)+([`]?)([^`\s]+)\\3(\s)+/siU";
+               $pattern2 = "/^(DROP TABLE)(\s)+([`]?)([^`\s]+)\\3(\s)?$/siU";
+               if (preg_match($pattern, $query, $matches) || preg_match($pattern2, $query, $matches)) {
+                       $replace = "\\1 ".$prefix."\\4\\5";
+                       $matches[0] = preg_replace($pattern, $replace, $query);
+                       return $matches;
+               }
+               return false;
+       }
+
+       function queryFromFile($sql_file_path, $table_prefix){
+               global $db, $progress, $errors;
+               
+               $tables = array();
+
+        if (!file_exists($sql_file_path)) {
+            return false;
+        }
+
+        $sql_query = trim(fread(fopen($sql_file_path, 'r'), filesize($sql_file_path)));
+        SqlUtility::splitSqlFile($pieces, $sql_query);
+
+           foreach ($pieces as $piece) {
+               $piece = trim($piece);
+            // [0] contains the prefixed query
+            // [4] contains unprefixed table name
+
+                       if ($table_prefix || ($table_prefix == '')) {
+                   $prefixed_query = SqlUtility::prefixQuery($piece, $table_prefix);
+                       } else {
+                               $prefixed_query = $piece;
+                       }
+       
+                       if ($prefixed_query != false ) {
+                $table = $table_prefix.$prefixed_query[4];
+                if($prefixed_query[1] == 'CREATE TABLE'){
+                    if (mysql_query($prefixed_query[0],$db) !== false) {
+                                               $progress[] = 'Table <b>'.$table . '</b> created successfully.';
+                    } else {
+                                               if (mysql_errno($db) == 1050) {
+                                                       $progress[] = 'Table <b>'.$table . '</b> already exists. Skipping.';
+                                               } else {
+                                                       $errors[] = 'Table <b>' . $table . '</b> creation failed.';
+                                               }
+                    }
+                }
+                elseif($prefixed_query[1] == 'INSERT INTO'){
+                                       mysql_query($prefixed_query[0],$db);
+                }elseif($prefixed_query[1] == 'ALTER TABLE'){
+                    mysql_query($prefixed_query[0],$db);
+                }elseif($prefixed_query[1] == 'DROP TABLE'){
+                    mysql_query($prefixed_query[1] . ' ' .$table,$db);
+                }
+            }
+               }
+        return TRUE;
+    }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/testQuestions.class.php b/include/classes/testQuestions.class.php
new file mode 100644 (file)
index 0000000..85d6066
--- /dev/null
@@ -0,0 +1,864 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+/*
+ * Steps to follow when adding a new question type:
+ *
+ * 1 - Create a class extending AbstractQuestion or extend an 
+ *     existing question class.
+ *     Define $sPrefix and $sNameVar appropriately.
+ *     Implement the following methods, which set template variables:
+ *
+ *        assignQTIVariables()
+ *        assignDisplayResultVariables()
+ *        assignDisplayVariables()
+ *        assignDisplayStatisticsVariables()
+ *     
+ *     And implement mark() which is used for marking the result.
+ *
+ * 2 - Add the new class name to $question_classes in test_question_factory()
+ *
+ * 3 - Add $sNameVar to the language database.
+ *
+ * 4 - Create the following files for creating and editing the question,
+ *     where "{PREFIX}" is the value defined by $sPrefix:
+ *
+ *     /tools/tests/create_question_{PREFIX}.php
+ *     /tools/tests/edit_question_{PREFIX}.php
+ *
+ * 5 - Add those two newly created pages to 
+ *     /mods/_standard/tests/module.php
+ *
+ * 6 - Create the following template files:
+ *
+ *     /themes/default/test_questions/{PREFIX}.tmpl.php
+ *     /themes/default/test_questions/{PREFIX}_qti_2p1.tmpl.php
+ *     /themes/default/test_questions/{PREFIX}_result.tmpl.php
+ *     /themes/default/test_questions/{PREFIX}_stats.tmpl.php
+ *
+ * 7 - Done!
+ **/
+
+class TestQuestions {
+       // returns array of prefix => name, sorted!
+       /*static */function getQuestionPrefixNames() {
+               $question_prefix_names = array(); // prefix => name
+               $questions = TestQuestions::getQuestionClasses();
+               foreach ($questions as $type => $question) {
+                       $o = TestQuestions::getQuestion($type);
+                       $question_prefix_names[$o->getPrefix()] = $o->getName();
+               }
+               asort($question_prefix_names);
+               return $question_prefix_names;
+       }
+
+       /*static */function getQuestionClasses() {
+               /** NOTE: The indices are CONSTANTS. Do NOT change!! **/
+               $question_classes = array(); // type ID => class name
+               $question_classes[1] = 'MultichoiceQuestion';
+               $question_classes[2] = 'TruefalseQuestion';
+               $question_classes[3] = 'LongQuestion';
+               $question_classes[4] = 'LikertQuestion';
+               $question_classes[5] = 'MatchingQuestion';
+               $question_classes[6] = 'OrderingQuestion';
+               $question_classes[7] = 'MultianswerQuestion';
+               $question_classes[8] = 'MatchingddQuestion';
+
+               return $question_classes;
+       }
+
+       /**
+        * Used to create question objects based on $question_type.
+        * A singleton that creates one obj per question since
+        * questions are all stateless.
+        * Returns a reference to the question object.
+        */
+       /*static */function & getQuestion($question_type) {
+               static $objs, $question_classes;
+
+               if (isset($objs[$question_type])) {
+                       return $objs[$question_type];
+               }
+
+               $question_classes = TestQuestions::getQuestionClasses();
+
+               if (isset($question_classes[$question_type])) {
+                       global $savant;
+                       $objs[$question_type] =& new $question_classes[$question_type]($savant);
+               } else {
+                       return FALSE;
+               }
+
+               return $objs[$question_type];
+       }
+}
+
+function test_question_qti_export(/* array */ $question_ids) {
+       require(AT_INCLUDE_PATH.'classes/zipfile.class.php'); // for zipfile
+       require(AT_INCLUDE_PATH.'lib/html_resource_parser.inc.php'); // for get_html_resources()
+       require(AT_INCLUDE_PATH.'classes/XML/XML_HTMLSax/XML_HTMLSax.php');     // for XML_HTMLSax
+
+       global $savant, $db, $system_courses, $languageManager;
+
+       $course_language = $system_courses[$_SESSION['course_id']]['primary_language'];
+       $courseLanguage =& $languageManager->getLanguage($course_language);
+       $course_language_charset = $courseLanguage->getCharacterSet();
+
+       $zipfile = new zipfile();
+       $zipfile->create_dir('resources/'); // for all the dependency files
+       $resources    = array();
+       $dependencies = array();
+
+       asort($question_ids);
+
+       $question_ids_delim = implode(',',$question_ids);
+       $sql = "SELECT * FROM ".TABLE_PREFIX."tests_questions WHERE course_id=$_SESSION[course_id] AND question_id IN($question_ids_delim)";
+       $result = mysql_query($sql, $db);
+
+       while ($row = mysql_fetch_assoc($result)) {
+               $obj = TestQuestions::getQuestion($row['type']);
+               $xml = $obj->exportQTI($row, $course_language_charset);
+               $local_dependencies = array();
+
+               $text_blob = implode(' ', $row);
+               $local_dependencies = get_html_resources($text_blob);
+               $dependencies = array_merge($dependencies, $local_dependencies);
+
+               $resources[] = array('href'         => 'question_'.$row['question_id'].'.xml',
+                                                        'dependencies' => array_keys($local_dependencies));
+
+               $zipfile->add_file($xml, 'question_'.$row['question_id'].'.xml');
+       }
+
+       // add any dependency files:
+       foreach ($dependencies as $resource => $resource_server_path) {
+               $zipfile->add_file(@file_get_contents($resource_server_path), 'resources/' . $resource, filemtime($resource_server_path));
+       }
+
+       // construct the manifest xml
+       $savant->assign('resources', $resources);
+       $savant->assign('dependencies', array_keys($dependencies));
+       $savant->assign('encoding', $course_language_charset);
+       $manifest_xml = $savant->fetch('test_questions/manifest_qti_2p1.tmpl.php');
+
+       $zipfile->add_file($manifest_xml, 'imsmanifest.xml');
+
+       $zipfile->close();
+
+       $filename = str_replace(array(' ', ':'), '_', $_SESSION['course_title'].'-'._AT('question_database').'-'.date('Ymd'));
+       $zipfile->send_file($filename);
+       exit;
+}
+
+/**
+* keeps count of the question number (when displaying the question)
+* need this function because PHP 4 doesn't support static members
+*/
+function TestQuestionCounter($increment = FALSE) {
+       static $count;
+
+       if (!isset($count)) { 
+               $count = 0;
+       }
+       if ($increment) {
+               $count++;
+       }
+
+       return $count;
+}
+
+
+/**
+ * testQuestion
+ *
+ * Note that all PHP 5 OO declarations and signatures are commented out to be
+ * backwards compatible with PHP 4.
+ *
+ */
+/*abstract */ class AbstractTestQuestion  {
+       /**
+       * Savant2 $savant - refrence to the savant obj
+       */
+       /*protected */ var $savant;
+
+       /**
+       * Constructor method.  Initialises variables.
+       */
+       function AbstractTestQuestion(&$savant) { $this->savant =& $savant; }
+
+       /**
+       * Public
+       */
+       /*final public */function seed($salt) {
+               /**
+               * by controlling the seed before calling array_rand() we insure that
+               * we can un-randomize the order for marking.
+               * used with ordering type questions only.
+               */
+               srand($salt + $_SESSION['member_id']);
+       }
+
+       /**
+       * Public
+       */
+       /*final public */function unseed() {
+               // To fix http://www.atutor.ca/atutor/mantis/view.php?id=3167
+               // Disturb the seed for ordering questions after mark to avoid the deterioration  
+               // of the random distribution due to a repeated initialization of the same random seed
+               list($usec, $sec) = explode(" ", microtime());
+               srand((int)($usec*10));
+       }
+
+       /**
+       * Public
+       * Prints the name of this question
+       */
+       /*final public */function printName() { echo $this->getName(); }
+
+       /**
+       * Public
+       * Prints the name of this question
+       */
+       /*final public */function getName() { return _AT($this->sNameVar); }
+
+       /**
+       * Public
+       * Returns the prefix string (used for file names)
+       */
+       /*final public */function getPrefix() { return $this->sPrefix; }
+
+       /**
+       * Display the current question (for taking or previewing a test/question)
+       */
+       /*final public */function display($row, $response = '') {
+               // print the generic question header
+               $this->displayHeader($row['weight']);
+
+               // print the question specific template
+               $this->assignDisplayVariables($row, $response);
+               $this->savant->display('test_questions/' . $this->sPrefix . '.tmpl.php');
+               
+               // print the generic question footer
+               $this->displayFooter();
+       }
+
+       /**
+       * Display the result for the current question
+       */
+       /*final public */function displayResult($row, $answer_row, $editable = FALSE) {
+               // print the generic question header
+               $this->displayHeader($row['weight'], (int) $answer_row['score'], $editable ? $row['question_id'] : FALSE);
+
+               // print the question specific template
+               $this->assignDisplayResultVariables($row, $answer_row);
+               $this->savant->display('test_questions/' . $this->sPrefix . '_result.tmpl.php');
+               
+               // print the generic question footer
+               $this->displayFooter();
+       }
+
+
+       /**
+       * print the question template header
+       */
+       /*final public */function displayResultStatistics($row, $answers) {
+               TestQuestionCounter(TRUE);
+
+               $this->assignDisplayStatisticsVariables($row, $answers);
+               $this->savant->display('test_questions/' . $this->sPrefix . '_stats.tmpl.php');
+       }
+
+       /*final public */function exportQTI($row, $encoding) {
+               $this->savant->assign('encoding', $encoding);
+               $this->assignQTIVariables($row);
+               $xml = $this->savant->fetch('test_questions/'. $this->sPrefix . '_qti_2p1.tmpl.php');
+
+               return $xml;
+       }
+
+       /**
+       * print the question template header
+       */
+       /*final private */function displayHeader($weight, $score = FALSE, $question_id = FALSE) {
+               TestQuestionCounter(TRUE);
+
+               $this->savant->assign('question_id', $question_id);
+               $this->savant->assign('score', $score);
+               $this->savant->assign('weight', $weight);
+               $this->savant->assign('type',   _AT($this->sNameVar));
+               $this->savant->assign('number', TestQuestionCounter());
+               $this->savant->display('test_questions/header.tmpl.php');
+       }
+
+       /**
+       * print the question template footer
+       */
+       /*final private */function displayFooter() {
+               $this->savant->display('test_questions/footer.tmpl.php');
+       }
+
+       /**
+       * return only the non-empty choices from $row.
+       * assumes choices are sequential.
+       */
+       /*protected */function getChoices($row) {
+               $choices = array();
+               for ($i=0; $i < 10; $i++) {
+                       if ($row['choice_'.$i] != '') {
+                               $num_choices++;
+                               $choices[] = $row['choice_'.$i];
+                       } else {
+                               break;
+                       }
+               }
+               return $choices;
+       }
+}
+
+/**
+* orderingQuestion
+*
+*/
+class OrderingQuestion extends AbstractTestQuestion {
+       /*protected */ var $sNameVar = 'test_ordering';
+       /*protected */ var $sPrefix = 'ordering';
+       
+       /*protected */function assignDisplayResultVariables($row, $answer_row) {
+               $answers = explode('|', $answer_row['answer']);
+
+               $num_choices = count($this->getChoices($row));
+
+               $this->savant->assign('base_href', AT_BASE_HREF);
+               $this->savant->assign('num_choices', $num_choices);
+               $this->savant->assign('answers', $answers);
+               $this->savant->assign('row', $row);
+       }
+
+       /*protected */function assignQTIVariables($row) {
+               $choices = $this->getChoices($row);
+               $num_choices = count($choices);
+
+               $this->savant->assign('num_choices', $num_choices);
+               $this->savant->assign('row', $row);
+       }
+
+       /*protected */function assignDisplayVariables($row, $response) {
+               // determine the number of choices this question has
+               // and save those choices to be re-assigned back to $row
+               // in the randomized order.
+               $choices = $this->getChoices($row);
+               $num_choices = count($choices);
+
+               // response from the test_answers table is in the correct order
+               // so, they have to be re-randomized in the same order as the
+               // choices are. this is only possible because of the seed() method.
+               $response = explode('|', $response);
+               $new_response = array();
+
+               // randomize the order of choices and re-assign to $row
+               $this->seed($row['question_id']);
+               $rand = array_rand($choices, $num_choices);
+               for ($i=0; $i < 10; $i++) {
+                       $row['choice_'.$i] = $choices[$rand[$i]];
+                       $new_response[$i]  = $response[$rand[$i]];
+               }
+
+               $this->savant->assign('num_choices', $num_choices);
+               $this->savant->assign('row', $row);
+
+               $this->savant->assign('response', $new_response);
+       }
+
+       /*protected */function assignDisplayStatisticsVariables($row, $answers) {
+               $num_results = 0;               
+               foreach ($answers as $answer) {
+                       $num_results += $answer['count'];
+               }
+
+               $choices = $this->getChoices($row);
+               $num_choices = count($choices);
+
+               $final_answers = array(); // assoc array of # of times that key was used correctly 0, 1, ...  $num -1
+               foreach ($answers as $key => $value) {
+                       $values = explode('|', $key);
+                       // we assume $values is never empty and contains $num number of answers
+                       for ($i=0; $i<=$num_choices; $i++) {
+                               if ($values[$i] == $i) {
+                                       $final_answers[$i] += $answers[$key]['count'];
+                               }
+                       }
+               }
+
+               $this->savant->assign('num_results', $num_results);
+               $this->savant->assign('num_choices', $num_choices);
+               $this->savant->assign('answers', $final_answers);
+               $this->savant->assign('row', $row);
+       }
+
+       /*public */function mark($row) { 
+               $this->seed($row['question_id']);
+               $num_choices = count($_POST['answers'][$row['question_id']]);
+               $answers = range(0, $num_choices-1);
+               $answers = array_rand($answers, $num_choices);
+               
+               // Disturb the seed for ordering questions after mark to avoid the deterioration  
+               // of the random distribution due to a repeated initialization of the same random seed
+               $this->unseed();
+
+               $num_answer_correct = 0;
+
+               $ordered_answers = array();
+
+               for ($i = 0; $i < $num_choices ; $i++) {
+                       $_POST['answers'][$row['question_id']][$i] = intval($_POST['answers'][$row['question_id']][$i]);
+
+                       if ($_POST['answers'][$row['question_id']][$i] == -1) {
+                               // nothing to do. it was left blank
+                       } else if ($_POST['answers'][$row['question_id']][$i] == $answers[$i]) {
+                               $num_answer_correct++;
+                       }
+                       $ordered_answers[$answers[$i]] = $_POST['answers'][$row['question_id']][$i];
+               }
+               ksort($ordered_answers);
+
+               $score = 0;
+
+               // to avoid roundoff errors:
+               if ($num_answer_correct == $num_choices) {
+                       $score = $row['weight'];
+               } else if ($num_answer_correct > 0) {
+                       $score = number_format($row['weight'] / $num_choices * $num_answer_correct, 2);
+                       if ( (float) (int) $score == $score) {
+                               $score = (int) $score; // a whole number with decimals, eg. "2.00"
+                       } else {
+                               $score = trim($score, '0'); // remove trailing zeros, if any, eg. "2.50"
+                       }
+               }
+
+               $_POST['answers'][$row['question_id']] = implode('|', $ordered_answers);
+
+               return $score;
+       }
+}
+
+/**
+* truefalseQuestion
+*
+*/
+class TruefalseQuestion extends AbstracttestQuestion {
+       /*protected */ var $sPrefix = 'truefalse';
+       /*protected */ var $sNameVar   = 'test_tf';
+
+       /*protected */function assignQTIVariables($row) {
+               $this->savant->assign('row', $row);
+       }
+
+       /*protected */function assignDisplayResultVariables($row, $answer_row) {
+
+               $this->savant->assign('base_href', AT_BASE_HREF);
+               $this->savant->assign('answers', $answer_row['answer']);
+               $this->savant->assign('row', $row);
+       }
+
+       /*protected */function assignDisplayVariables($row, $response) {
+               $this->savant->assign('row', $row);
+               $this->savant->assign('response', $response);
+       }
+
+       /*protected */function assignDisplayStatisticsVariables($row, $answers) {
+               $num_results = 0;               
+               foreach ($answers as $answer) {
+                       $num_results += $answer['count'];
+               }
+
+               $this->savant->assign('num_results', $num_results);
+               $this->savant->assign('num_blanks', (int) $answers['-1']['count']);
+               $this->savant->assign('num_true', (int) $answers['1']['count']);
+               $this->savant->assign('num_false', (int) $answers['2']['count']);
+               $this->savant->assign('row', $row);
+       }
+
+       /*public */function mark($row) { 
+               $_POST['answers'][$row['question_id']] = intval($_POST['answers'][$row['question_id']]);
+
+               if ($row['answer_0'] == $_POST['answers'][$row['question_id']]) {
+                       return (int) $row['weight'];
+               } // else:
+               return 0;
+       }
+}
+
+/**
+* likertQuestion
+*
+*/
+class LikertQuestion extends AbstracttestQuestion {
+       /*protected */ var $sPrefix = 'likert';
+       /*protected */ var $sNameVar   = 'test_lk';
+
+       /*protected */function assignQTIVariables($row) {
+               $choices = $this->getChoices($row);
+               $num_choices = count($choices);
+
+               $this->savant->assign('num_choices', $num_choices);
+               $this->savant->assign('row', $row);
+       }
+
+       /*protected */function assignDisplayResultVariables($row, $answer_row) {
+               $this->savant->assign('answer', $answer_row['answer']);
+               $this->savant->assign('row', $row);
+       }
+
+       /*protected */function assignDisplayVariables($row, $response) {
+               $choices = $this->getChoices($row);
+               $num_choices = count($choices);
+
+               $this->savant->assign('num_choices', $num_choices);
+               $this->savant->assign('row', $row);
+
+               if (empty($response)) {
+                       $response = -1;
+               }
+               $this->savant->assign('response', $response);
+       }
+
+       /*protected */function assignDisplayStatisticsVariables($row, $answers) {
+               $num_results = 0;               
+               foreach ($answers as $answer) {
+                       $num_results += $answer['count'];
+               }
+               
+               $choices = $this->getChoices($row);
+               $num_choices = count($choices);
+
+               $sum = 0;
+               for ($i=0; $i<$num_choices; $i++) {
+                       $sum += ($i+1) * $answers[$i]['count'];
+               }
+               $average = round($sum/$num_results, 1);
+
+               $this->savant->assign('num_results', $num_results);
+               $this->savant->assign('average', $average);
+               $this->savant->assign('num_choices', $num_choices);
+               $this->savant->assign('num_blanks', (int) $answers['-1']['count']);
+               $this->savant->assign('answers', $answers);
+               $this->savant->assign('row', $row);
+       }
+
+       /*public */function mark($row) { 
+               $_POST['answers'][$row['question_id']] = intval($_POST['answers'][$row['question_id']]);
+               return 0;
+       }
+}
+
+/**
+* longQuestion
+*
+*/
+class LongQuestion extends AbstracttestQuestion {
+       /*protected */ var $sPrefix = 'long';
+       /*protected */ var $sNameVar = 'test_open';
+
+       /*protected */function assignQTIVariables($row) {
+               $this->savant->assign('row', $row);
+       }
+
+       /*protected */function assignDisplayResultVariables($row, $answer_row) {
+               $this->savant->assign('answer', $answer_row['answer']);
+               $this->savant->assign('row', $row);
+       }
+
+       /*protected */function assignDisplayVariables($row, $response) {
+               $this->savant->assign('row', $row);
+               $this->savant->assign('response', $response);
+       }
+
+       /*protected */function assignDisplayStatisticsVariables($row, $answers) {
+               $num_results = 0;               
+               foreach ($answers as $answer) {
+                       $num_results += $answer['count'];
+               }
+               
+               $this->savant->assign('num_results', $num_results);
+               $this->savant->assign('num_blanks', (int) $answers['']['count']);
+               $this->savant->assign('answers', $answers);
+               $this->savant->assign('row', $row);
+       }
+
+       /*public */function mark($row) { 
+               global $addslashes;
+               $_POST['answers'][$row['question_id']] = $addslashes($_POST['answers'][$row['question_id']]);
+               return 0;
+       }
+}
+
+/**
+* matchingQuestion
+*
+*/
+class MatchingQuestion extends AbstracttestQuestion {
+       /*protected */ var $sPrefix = 'matching';
+       /*protected */ var $sNameVar   = 'test_matching';
+
+       /*protected */function assignQTIVariables($row) {
+               $choices = $this->getChoices($row);
+               $num_choices = count($choices);
+
+               $num_options = 0;
+               for ($i=0; $i < 10; $i++) {
+                       if ($row['option_'. $i] != '') {
+                               $num_options++;
+                       }
+               }
+
+               $this->savant->assign('num_choices', $num_choices);
+               $this->savant->assign('num_options', $num_options);
+               $this->savant->assign('row', $row);
+       }
+
+       /*protected */function assignDisplayResultVariables($row, $answer_row) {
+               $num_options = 0;
+               for ($i=0; $i < 10; $i++) {
+                       if ($row['option_'. $i] != '') {
+                               $num_options++;
+                       }
+               }
+
+               $answer_row['answer'] = explode('|', $answer_row['answer']);
+
+               global $_letters;
+
+               $this->savant->assign('base_href', AT_BASE_HREF);
+               $this->savant->assign('answers', $answer_row['answer']);
+               $this->savant->assign('letters', $_letters);
+               $this->savant->assign('num_options', $num_options);
+               $this->savant->assign('row', $row);
+       }
+
+       /*protected */function assignDisplayVariables($row, $response) {
+               $choices = $this->getChoices($row);
+               $num_choices = count($choices);
+
+               if (empty($response)) {
+                       $response = array_fill(0, $num_choices, -1);
+               } else {
+                       $response = explode('|', $response);
+               }
+
+               $num_options = 0;
+               for ($i=0; $i < 10; $i++) {
+                       if ($row['option_'. $i] != '') {
+                               $num_options++;
+                       }
+               }
+
+               global $_letters;
+
+               $this->savant->assign('num_choices', $num_choices);
+               $this->savant->assign('base_href', AT_BASE_HREF);
+               $this->savant->assign('letters', $_letters);
+               $this->savant->assign('num_options', $num_options);
+               $this->savant->assign('row', $row);
+
+               $this->savant->assign('response', $response);
+       }
+
+       /*protected */function assignDisplayStatisticsVariables($row, $answers) {
+               $choices = $this->getChoices($row);
+               $num_choices = count($choices);
+
+               $num_results = 0;
+               foreach ($answers as $answer) {
+                       $num_results += $answer['count'];
+               }
+                                       
+               foreach ($answers as $key => $value) {
+                       $values = explode('|', $key);
+                       if (count($values) > 1) {
+                               for ($i=0; $i<count($values); $i++) {
+                                       $answers[$values[$i]]['count']++;
+                               }
+                       }
+               }
+
+               $this->savant->assign('num_choices', $num_choices);
+               $this->savant->assign('num_results', $num_results);
+               $this->savant->assign('answers', $answers);
+               $this->savant->assign('row', $row);
+       }
+
+       /*public */function mark($row) { 
+               $num_choices = count($_POST['answers'][$row['question_id']]);
+               $num_answer_correct = 0;
+               foreach ($_POST['answers'][$row['question_id']] as $item_id => $response) {
+                       if ($row['answer_' . $item_id] == $response) {
+                               $num_answer_correct++;
+                       }
+                       $_POST['answers'][$row['question_id']][$item_id] = intval($_POST['answers'][$row['question_id']][$item_id]);
+               }
+
+               $score = 0;
+               // to avoid roundoff errors:
+               if ($num_answer_correct == $num_choices) {
+                       $score = $row['weight'];
+               } else if ($num_answer_correct > 0) {
+                       $score = number_format($row['weight'] / $num_choices * $num_answer_correct, 2);
+                       if ( (float) (int) $score == $score) {
+                               $score = (int) $score; // a whole number with decimals, eg. "2.00"
+                       } else {
+                               $score = trim($score, '0'); // remove trailing zeros, if any
+                       }
+               }
+
+               $_POST['answers'][$row['question_id']] = implode('|', $_POST['answers'][$row['question_id']]);
+
+               return $score;
+       }
+}
+
+/**
+* matchingddQuestion
+*
+*/
+class MatchingddQuestion extends MatchingQuestion {
+       /*protected */ var $sPrefix = 'matchingdd';
+       /*protected */ var $sNameVar   = 'test_matchingdd';
+}
+
+/**
+* multichoiceQuestion
+*
+*/
+class MultichoiceQuestion extends AbstracttestQuestion {
+       /*protected */ var $sPrefix = 'multichoice';
+       /*protected */var $sNameVar = 'test_mc';
+
+       /*protected */function assignQTIVariables($row) {
+               $choices = $this->getChoices($row);
+               $num_choices = count($choices);
+
+               $this->savant->assign('num_choices', $num_choices);
+               $this->savant->assign('row', $row);
+       }
+
+       /*protected */function assignDisplayResultVariables($row, $answer_row) {
+               if (strpos($answer_row['answer'], '|') !== false) {
+                       $answer_row['answer'] = explode('|', $answer_row['answer']);
+               } else {
+                       $answer_row['answer'] = array($answer_row['answer']);
+               }
+
+               $this->savant->assign('base_href', AT_BASE_HREF);
+               $this->savant->assign('answers', $answer_row['answer']);
+               $this->savant->assign('row', $row);
+       }
+
+       /*protected */function assignDisplayVariables($row, $response) {
+               $choices = $this->getChoices($row);
+               $num_choices = count($choices);
+
+               if ($response == '') {
+                       $response = -1;
+               }
+               $response = explode('|', $response);
+               $this->savant->assign('response', $response);
+
+               $this->savant->assign('num_choices', $num_choices);
+               $this->savant->assign('row', $row);
+       }
+
+       /*protected */function assignDisplayStatisticsVariables($row, $answers) {
+               $choices = $this->getChoices($row);
+               $num_choices = count($choices);
+
+               $num_results = 0;
+               foreach ($answers as $answer) {
+                       $num_results += $answer['count'];
+               }
+                                       
+               foreach ($answers as $key => $value) {
+                       $values = explode('|', $key);
+                       if (count($values) > 1) {
+                               for ($i=0; $i<count($values); $i++) {
+                                       $answers[$values[$i]]['count']++;
+                               }
+                       }
+               }
+
+               $this->savant->assign('num_choices', $num_choices);
+               $this->savant->assign('num_results', $num_results);
+               $this->savant->assign('num_blanks', (int) $answers['-1']['count']);
+               $this->savant->assign('answers', $answers);
+               $this->savant->assign('row', $row);
+       }
+
+       /*public */function mark($row) { 
+               $_POST['answers'][$row['question_id']] = intval($_POST['answers'][$row['question_id']]);
+               if ($row['answer_' . $_POST['answers'][$row['question_id']]]) {
+                       $score = $row['weight'];
+               } else if ($_POST['answers'][$row['question_id']] == -1) {
+                       $has_answer = 0;
+                       for($i=0; $i<10; $i++) {
+                               $has_answer += $row['answer_'.$i];
+                       }
+                       if (!$has_answer && $row['weight']) {
+                               // If MC has no answer and user answered "leave blank"
+                               $score = $row['weight'];
+                       }
+               }
+               return $score;
+       }
+}
+
+/**
+* multianswerQuestion
+*
+*/
+class MultianswerQuestion extends MultichoiceQuestion {
+       /*protected */ var $sPrefix  = 'multianswer';
+       /*protected */ var $sNameVar = 'test_ma';
+
+       /*public */function mark($row) { 
+               $num_correct = array_sum(array_slice($row, 3));
+
+               if (is_array($_POST['answers'][$row['question_id']]) && count($_POST['answers'][$row['question_id']]) > 1) {
+                       if (($i = array_search('-1', $_POST['answers'][$row['question_id']])) !== FALSE) {
+                               unset($_POST['answers'][$row['question_id']][$i]);
+                       }
+                       $num_answer_correct = 0;
+                       foreach ($_POST['answers'][$row['question_id']] as $item_id => $answer) {
+                               if ($row['answer_' . $answer]) {
+                                       // correct answer
+                                       $num_answer_correct++;
+                               } else {
+                                       // wrong answer
+                                       $num_answer_correct--;
+                               }
+                               $_POST['answers'][$row['question_id']][$item_id] = intval($_POST['answers'][$row['question_id']][$item_id]);
+                       }
+                       if ($num_answer_correct == $num_correct) {
+                               $score = $row['weight'];
+                       } else {
+                               $score = 0;
+                       }
+                       $_POST['answers'][$row['question_id']] = implode('|', $_POST['answers'][$row['question_id']]);
+               } else {
+                       // no answer given
+                       $_POST['answers'][$row['question_id']] = '-1'; // left blank
+                       $score = 0;
+               }
+               return $score;
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/classes/vcard.php b/include/classes/vcard.php
new file mode 100644 (file)
index 0000000..7a205b0
--- /dev/null
@@ -0,0 +1,158 @@
+<?php
+/***************************************************************************
+
+PHP vCard class v2.0
+(c) Kai Blankenhorn
+www.bitfolge.de/en
+kaib@bitfolge.de
+
+
+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.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+***************************************************************************/
+
+
+function encode($string) {
+       return escape(quoted_printable_encode($string));
+}
+
+function escape($string) {
+       return str_replace(";","\;",$string);
+}
+
+// taken from PHP documentation comments
+function quoted_printable_encode($input, $line_max = 76) {
+       $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
+       $lines = preg_split("/(?:\r\n|\r|\n)/", $input);
+       $eol = "\r\n";
+       $linebreak = "=0D=0A";
+       $escape = "=";
+       $output = "";
+
+       for ($j=0;$j<count($lines);$j++) {
+               $line = $lines[$j];
+               $linlen = strlen($line);
+               $newline = "";
+               for($i = 0; $i < $linlen; $i++) {
+                       $c = substr($line, $i, 1);
+                       $dec = ord($c);
+                       if ( ($dec == 32) && ($i == ($linlen - 1)) ) { // convert space at eol only
+                               $c = "=20"; 
+                       } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
+                               $h2 = floor($dec/16); $h1 = floor($dec%16); 
+                               $c = $escape.$hex["$h2"].$hex["$h1"]; 
+                       }
+                       if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
+                               $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay
+                               $newline = "    ";
+                       }
+                       $newline .= $c;
+               } // end of for
+               $output .= $newline;
+               if ($j<count($lines)-1) $output .= $linebreak;
+       }
+       return trim($output);
+}
+
+class vCard {
+       var $properties;
+       var $filename;
+       
+       function setPhoneNumber($number, $type="") {
+       // type may be PREF | WORK | HOME | VOICE | FAX | MSG | CELL | PAGER | BBS | CAR | MODEM | ISDN | VIDEO or any senseful combination, e.g. "PREF;WORK;VOICE"
+               $key = "TEL";
+               if ($type!="") $key .= ";".$type;
+               $key.= ";ENCODING=QUOTED-PRINTABLE";
+               $this->properties[$key] = quoted_printable_encode($number);
+       }
+       
+       // UNTESTED !!!
+       function setPhoto($type, $photo) { // $type = "GIF" | "JPEG"
+               $this->properties["PHOTO;TYPE=$type;ENCODING=BASE64"] = base64_encode($photo);
+       }
+       
+       function setFormattedName($name) {
+               $this->properties["FN"] = quoted_printable_encode($name);
+       }
+       
+       function setName($family="", $first="", $additional="", $prefix="", $suffix="") {
+               $this->properties["N"] = "$family;$first;$additional;$prefix;$suffix";
+               $this->filename = "$first%20$family.vcf";
+               if ($this->properties["FN"]=="") $this->setFormattedName(trim("$prefix $first $additional $family $suffix"));
+       }
+       
+       function setBirthday($date) { // $date format is YYYY-MM-DD
+               $this->properties["BDAY"] = $date;
+       }
+       
+       function setAddress($postoffice="", $extended="", $street="", $city="", $region="", $zip="", $country="", $type="HOME;POSTAL") {
+       // $type may be DOM | INTL | POSTAL | PARCEL | HOME | WORK or any combination of these: e.g. "WORK;PARCEL;POSTAL"
+               $key = "ADR";
+               if ($type!="") $key.= ";$type";
+               $key.= ";ENCODING=QUOTED-PRINTABLE";
+               $this->properties[$key] = encode($name).";".encode($extended).";".encode($street).";".encode($city).";".encode($region).";".encode($zip).";".encode($country);
+               
+               if ($this->properties["LABEL;$type;ENCODING=QUOTED-PRINTABLE"] == "") {
+                       //$this->setLabel($postoffice, $extended, $street, $city, $region, $zip, $country, $type);
+               }
+       }
+       
+       function setLabel($postoffice="", $extended="", $street="", $city="", $region="", $zip="", $country="", $type="HOME;POSTAL") {
+               $label = "";
+               if ($postoffice!="") $label.= "$postoffice\r\n";
+               if ($extended!="") $label.= "$extended\r\n";
+               if ($street!="") $label.= "$street\r\n";
+               if ($zip!="") $label.= "$zip ";
+               if ($city!="") $label.= "$city\r\n";
+               if ($region!="") $label.= "$region\r\n";
+               if ($country!="") $country.= "$country\r\n";
+               
+               $this->properties["LABEL;$type;ENCODING=QUOTED-PRINTABLE"] = quoted_printable_encode($label);
+       }
+       
+       function setEmail($address) {
+               $this->properties["EMAIL;INTERNET"] = $address;
+       }
+       
+       function setNote($note) {
+               $this->properties["NOTE;ENCODING=QUOTED-PRINTABLE"] = quoted_printable_encode($note);
+       }
+       
+       function setURL($url, $type="") {
+       // $type may be WORK | HOME
+               $key = "URL";
+               if ($type!="") $key.= ";$type";
+               $this->properties[$key] = $url;
+       }
+       
+       function getVCard() {
+               $text = "BEGIN:VCARD\r\n";
+               $text.= "VERSION:2.1\r\n";
+               foreach($this->properties as $key => $value) {
+                       $text.= "$key:$value\r\n";
+               }
+               $text.= "REV:".date("Y-m-d")."T".date("H:i:s")."Z\r\n";
+               //$text.= "MAILER:PHP vCard class by Kai Blankenhorn\r\n";
+               $text.= "END:VCARD\r\n";
+               return $text;
+       }
+       
+       function getFileName() {
+               return $this->filename;
+       }
+}
+
+
+?>
\ No newline at end of file
diff --git a/include/classes/zipfile.class.php b/include/classes/zipfile.class.php
new file mode 100644 (file)
index 0000000..401ab78
--- /dev/null
@@ -0,0 +1,368 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+
+/**
+* Class for creating and accessing an archive zip file
+* @access      public
+* @link                http://www.pkware.com/products/enterprise/white_papers/appnote.html     for the specs
+* @author      Joel Kronenberg
+*/
+class zipfile {
+
+       /**
+       * string $files_data - stores file information like the header and description 
+       * @access  public 
+       */
+       var $files_data;
+
+       /**
+       * string $central_directory_headers - headers necessary for including file in central record
+       * @access  public 
+       */
+       var $central_directory_headers; 
+
+       /**
+       * int $num_entries - a counter for the number of entries in the archive
+       * @access  public 
+       */
+       var $num_entries = 0;
+
+       /**
+       * string $zip_file - complete contents of file
+       * @access  public 
+       */
+       var $zip_file;
+
+       /**
+       * boolean $is_closed - flag set to true if file is closed, false if still open
+       * @access  private
+       */
+       var $is_closed; 
+
+
+       /**
+       * Constructor method.  Initialises variables.
+       * @access       public
+       * @author       Joel Kronenberg
+       */
+       function zipfile() {
+               $this->files_data = '';
+               $this->central_directory_headers = '';
+               $this->num_entries = 0;
+               $this->is_closed = false;
+       }
+
+       /**
+       * Public interface for adding a dir and its contents recursively to zip file
+       * @access  public
+       * @param   string $dir                          the real system directory that contains the files to add to the zip              
+       * @param   string $zip_prefix_dir       the zip dir where the contents of $dir will be put in
+       * @param   string $pre_pend_dir         used during the recursion to keep track of the path, default=''
+       * @see     $_base_path                          in include/vitals.inc.php
+       * @see     priv_add_dir()                       in include/classes/zipfile.class.php
+       * @see     add_file()                           in include/classes/zipfile.class.php
+       * @author  Joel Kronenberg
+       */
+       function add_dir($dir, $zip_prefix_dir, $pre_pend_dir='') {
+               if (!($dh = @opendir($dir.$pre_pend_dir))) {
+                       echo 'cant open dir: '.$dir.$pre_pend_dir;
+                       exit;
+               }
+
+               while (($file = readdir($dh)) !== false) {
+                       /* skip directories */
+                       if ($file == '.' || $file == '..') {
+                               continue;
+                       }
+                       /* skip potential harmful files/directories */
+                       if ( (strpos($file, '..') !== false) || (strpos($file, '/') !== false)) {
+                               continue;
+                       }
+
+                       $file_info = stat( $dir . $pre_pend_dir . $file );
+
+                       if (is_dir( $dir . $pre_pend_dir . $file )) {
+                               /* create this dir in the zip */
+                               $this->priv_add_dir( $zip_prefix_dir . $pre_pend_dir . $file . '/',
+                                                                        $file_info['mtime'] );
+
+                               /* continue recursion, going down this dir */
+                               $this->add_dir( $dir,
+                                                               $zip_prefix_dir,
+                                                               $pre_pend_dir . $file . '/' );
+
+                       } else {
+                               /* add this file to the zip */
+                               $this-> add_file( file_get_contents($dir . $pre_pend_dir . $file),
+                                                                 $zip_prefix_dir . $pre_pend_dir . $file,
+                                                                 $file_info['mtime'] );
+                       }
+               }
+               closedir($dh);
+       }
+
+       /**
+       * Adding a dir to the archive 
+       * @access  private
+       * @param   string $name                         directory name
+       * @param   string $timestamp            time, default=''
+       * @author  Joel Kronenberg
+       */
+    function priv_add_dir($name, $timestamp = '') {   
+        $name = str_replace("\\", "/", $name);   
+               $old_offset = strlen($this->files_data);
+
+        $local_file_header  = "\x50\x4b\x03\x04";                                                                                              // local file header signature 4 bytes (0x04034b50) 
+        $local_file_header .= "\x0a\x00";    // ver needed to extract                                                  // version needed to extract 2 bytes
+        $local_file_header .= "\x00\x00";    // gen purpose bit flag                                                   // general purpose bit flag 2 bytes
+        $local_file_header .= "\x00\x00";    // compression method                                                             // compression method 2 bytes
+        $local_file_header .= "\x00\x00\x00\x00"; // last mod time and date                                    // last mod file time 2 bytes & last mod file date 2 bytes 
+        $local_file_header .= pack("V",0); // crc32                                                                                    // crc-32 4 bytes
+        $local_file_header .= pack("V",0); //compressed filesize                                                               // compressed size 4 bytes 
+        $local_file_header .= pack("V",0); //uncompressed filesize                                                             // uncompressed size 4 bytes
+        $local_file_header .= pack("v", strlen($name) ); //length of pathname                                  // file name length 2 bytes 
+        $local_file_header .= pack("v", 0 ); //extra field length                                                              // extra field length 2 bytes           
+        $local_file_header .= $name;                                                                                                                   // file name (variable size)  & extra field (variable size)
+        // end of "local file header" segment 
+
+        // no "file data" segment for path 
+
+        // add this entry to array 
+        $this->files_data .= $local_file_header;
+
+        // ext. file attributes mirrors MS-DOS directory attr byte, detailed 
+        // at http://support.microsoft.com/support/kb/articles/Q125/0/19.asp 
+
+               if ($timestamp) {
+                       $v_date = getdate($timestamp);
+               } else {
+                       $v_date = getdate();
+               }
+               $time = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
+               $date = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
+
+        // now add to central record 
+        $central_directory = "\x50\x4b\x01\x02";                                                                                       // central file header signature 4 bytes (0x02014b50)
+        $central_directory .="\x14\x00";    // version made by                                                         // version made by 2 bytes
+        $central_directory .="\x14\x00";    // version needed to extract                                       // version needed to extract 2 bytes
+        $central_directory .="\x00\x00";    // gen purpose bit flag                                                    // general purpose bit flag 2 bytes
+        $central_directory .="\x00\x00";    // compression method                                                      // compression method 2 bytes
+               $central_directory .= pack("v",$time); // time                                                                          // last mod file time 2 bytes
+        $central_directory .= pack("v",$date); // date                                                                         // last mod file date 2 bytes
+        $central_directory .= pack("V", 0); // crc32                                                                           // crc-32 4 bytes
+        $central_directory .= pack("V", 0); // compressed filesize                                                     // compressed size 4 bytes
+        $central_directory .= pack("V", 0); // uncompressed filesize                                           // uncompressed size 4 bytes
+        $central_directory .= pack("v", strlen($name) ); //length of filename                          // file name length 2 bytes
+        $central_directory .= pack("v", 0); // extra field length                                                      // extra field length 2 bytes
+        $central_directory .= pack("v", 0); // file comment length                                                     // file comment length 2 bytes 
+        $central_directory .= pack("v", 0); // disk number start                                                       // disk number start 2 bytes
+        $central_directory .= pack("v", 0); // internal file attributes                                                // internal file attributes 2 bytes
+        $central_directory .= pack("V", 16+32); //external file attributes  - 'directory' 'archive' bit set // external file attributes 4 bytes
+        $central_directory .= pack("V", $old_offset); //relative offset of local header // relative offset of local header 4 bytes
+        $central_directory .= $name;                                                                                                           // file name (variable size)
+
+       $this->central_directory_headers .= $central_directory;
+
+               $this->num_entries++;
+    } 
+       
+       /**
+       * Public interface to create a directory in the archive.
+       * @access  public
+       * @param   string $name                         directory name
+       * @param   string $timestamp            time of creation, default=''
+       * @see     $_base_path                          in include/vitals.inc.php
+       * @see     priv_add_dir()                       in include/zipfile.class.php
+       * @author  Joel Kronenberg
+       */
+       function create_dir($name, $timestamp='') {
+               $name = trim($name);
+
+               if (substr($name, -1) != '/') {
+                       /* add the trailing slash */
+                       $name .= '/';
+               }
+
+               $this->priv_add_dir($name, $timestamp = '');
+       }
+
+       /**
+       * Adds a file to the archive.
+       * @access  public
+       * @param   string $file_data            file contents
+       * @param   string $name                         name of file in archive (add path if your want)
+       * @param   string $timestamp            time of creation, default=''
+       * @see     $_base_path                          in include/vitals.inc.php
+       * @see     priv_add_dir()                       in include/zipfile.class.php
+       * @author  Joel Kronenberg
+       */
+    function add_file($file_data, $name, $timestamp = '') {
+        $name = str_replace("\\", "/", $name);   
+        $crc = crc32($file_data);
+        $uncompressed_size = strlen($file_data);
+               $file_data = substr(gzcompress($file_data, 9), 2, -4);
+        $compressed_size = strlen($file_data);
+               $old_offset = strlen($this->files_data);
+
+               /* local file header */
+        $local_file_header = "\x50\x4b\x03\x04";                                                               // local file header signature 4 bytes (0x04034b50) 
+        $local_file_header .= "\x14\x00";    // ver needed to extract                  // version needed to extract 2 bytes 
+        $local_file_header .= "\x00\x00";    // gen purpose bit flag                   // general purpose bit flag 2 bytes 
+        $local_file_header .= "\x08\x00";    // compression method                             // compression method 2 bytes 
+        $local_file_header .= "\x00\x00\x00\x00"; // last mod time and date    // last mod file time 2 bytes & last mod file date 2 bytes 
+        $local_file_header .= pack("V",$crc); // crc32                                                 // crc-32 4 bytes 
+        $local_file_header .= pack("V",$compressed_size); //compressed filesize                        // compressed size 4 bytes 
+        $local_file_header .= pack("V",$uncompressed_size); //uncompressed filesize            // uncompressed size 4 bytes 
+        $local_file_header .= pack("v", strlen($name) ); //length of filename  // file name length 2 bytes 
+        $local_file_header .= "\x00\x00"; //extra field length                         // extra field length 2 bytes 
+        $local_file_header .= $name;                                                                                   // file name (variable size)  & extra field (variable size) 
+               /* end of local file header */
+          
+               $this->files_data .= $local_file_header . $file_data; // . $data_descriptor;;
+
+               /* create the central directory */
+               $central_directory = '';
+               if ($timestamp) {
+                       $v_date = getdate($timestamp);
+               } else {
+                       $v_date = getdate();
+               }
+               $time = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
+               $date = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
+
+        // now add to central directory record 
+        $central_directory = "\x50\x4b\x01\x02";                                                                                       // central file header signature 4 bytes (0x02014b50)
+        $central_directory .="\x14\x00";    // version made by                                                         // version made by 2 bytes 
+        $central_directory .="\x14\x00";    // version needed to extract                                       // version needed to extract 2 bytes 
+        $central_directory .="\x00\x00";    // gen purpose bit flag                                                    // general purpose bit flag 2 bytes 
+        $central_directory .="\x08\x00";    // compression method                                                      // compression method 2 bytes         
+        $central_directory .= pack("v",$time); // time                                                                         // last mod file time 2 bytes 
+               $central_directory .= pack("v",$date); // date                                                                          // last mod file date 2 bytes 
+               $central_directory .= pack("V",$crc); // crc32                                                                          // crc-32 4 bytes 
+        $central_directory .= pack("V",$compressed_size); //compressed filesize                                                // compressed size 4 bytes 
+        $central_directory .= pack("V",$uncompressed_size); //uncompressed filesize                                    // uncompressed size 4 bytes 
+        $central_directory .= pack("v", strlen($name) ); //length of filename                          // file name length 2 bytes 
+        $central_directory .= "\x00\x00"; //extra field length                                                 // extra field length 2 bytes 
+        $central_directory .= "\x00\x00"; //file comment length                                                        // file comment length 2 bytes 
+        $central_directory .= "\x00\x00"; //disk number start                                                  // disk number start 2 bytes 
+        $central_directory .= "\x00\x00"; //internal file attributes                                           // internal file attributes 2 bytes 
+        $central_directory .= pack("V", 32); //external file attributes - 'archive' bit set // external file attributes 4 bytes 
+               $central_directory .= pack("V", $old_offset);
+
+        $central_directory .= $name;                                                                                                           // file name (variable size)
+
+               $this->central_directory_headers .= $central_directory;
+       
+               $this->num_entries++;
+    } 
+
+       /**
+       * Closes archive, sets $is_closed to true
+       * @access  public
+       * @param   none
+       * @author  Joel Kronenberg
+       */
+       function close() {
+               $this->files_data .= $this->central_directory_headers . "\x50\x4b\x05\x06\x00\x00\x00\x00" .   
+            pack("v", $this->num_entries).     // total # of entries "on this disk" 
+            pack("v", $this->num_entries).     // total # of entries overall 
+            pack("V", strlen($this->central_directory_headers)).             // size of central dir 
+            pack("V", strlen($this->files_data)).                 // offset to start of central dir 
+            "\x00\x00"; 
+
+               unset($this->central_directory_headers);
+               unset($this->num_entries);
+
+               $this->zip_file =& $this->files_data;
+               $this->is_closed = true;
+       }
+
+    /**
+       * Gets size of new archive
+       * Only call this after calling close() - will return false if the zip wasn't close()d yet
+       * @access  public
+       * @return  int  size of file
+       * @author  Joel Kronenberg
+       */
+       function get_size() {
+               if (!$this->is_closed) {
+                       return false;
+               }
+               return strlen($this->zip_file);
+       }
+
+
+    /**
+       * Returns binary file
+       * @access       public
+       * @see          get_size()              in include/classes/zipfile.class.php
+       * @author  Joel Kronenberg
+       */      
+       function get_file() {
+               if (!$this->is_closed) {
+                       $this->close();
+               }
+               return $this->zip_file;
+    }
+
+       /**
+       * Writes the file to disk.
+       * Similar to get_file(), but instead of returning the file, it saves it to disk.
+       * @access  public
+       * @author  Joel Kronenberg
+       * @param  $file The full path and file name of the destination file.
+       */
+       function write_file($file) {
+               if (!$this->is_closed) {
+                       $this->close();
+               }
+               if (function_exists('file_put_contents')) {
+                       file_put_contents($file, $this->zip_file);
+               } else {
+                       $fp = fopen($file, 'wb+');
+                       fwrite($fp, $this->zip_file);
+                       fclose($fp);
+               }
+       }
+
+
+    /**
+       * Outputs the file - sends headers to browser to force download
+       * Only call this after calling close() - will return false if the zip wasn't close()d yet
+       * @access       public
+       * @see          get_size()              in include/classes/zipfile.class.php
+       * @author  Joel Kronenberg
+       */
+       function send_file($file_name) {
+               if (!$this->is_closed) {
+                       $this->close();
+               }
+               $file_name = str_replace(array('"', '<', '>', '|', '?', '*', ':', '/', '\\'), '', $file_name);
+
+               header('Content-Type: application/x-zip');
+               header('Content-transfer-encoding: binary'); 
+               header('Content-Disposition: attachment; filename="'.htmlspecialchars($file_name).'.zip"');
+               header('Expires: 0');
+               header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+               header('Pragma: public');
+               header('Content-Length: '.$this->get_size());
+
+               echo $this->get_file();
+
+               exit;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/include/footer.inc.php b/include/footer.inc.php
new file mode 100644 (file)
index 0000000..65df878
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+global $next_prev_links;
+global $_base_path, $_my_uri;
+global $_stacks, $db;
+global $system_courses;
+
+$side_menu = array();
+$stack_files = array();
+
+if (isset($_SESSION['course_id']) && $_SESSION['course_id'] > 0) {
+       $savant->assign('my_uri', $_my_uri);
+
+       $savant->assign('right_menu_open', TRUE);
+       $savant->assign('popup_help', 'MAIN_MENU');
+       $savant->assign('menu_url', '<a name="menu"></a>');
+       $savant->assign('close_menu_url', htmlspecialchars($_my_uri).'disable=PREF_MAIN_MENU');
+       $savant->assign('close_menus', _AT('close_menus'));
+
+       //copyright can be found in include/html/copyright.inc.php
+
+       $side_menu = explode('|', $system_courses[$_SESSION['course_id']]['side_menu']);
+
+       foreach ($side_menu as $side) {
+               if (isset($_stacks[$side])) {
+                       $stack_files[] = $_stacks[$side]['file'];
+               }
+       }
+}
+
+$theme_img  = $_base_path . 'themes/'. $_SESSION['prefs']['PREF_THEME'] . '/images/';
+$savant->assign('img', $theme_img);
+
+if (isset($err)) {
+       $err->showErrors(); // print all the errors caught on this page
+}
+$savant->assign('side_menu', $stack_files);
+
+// this js is indep of the theme used:
+?>
+<script language="javascript" type="text/javascript">
+//<!--
+var selected;
+function rowselect(obj) {
+       obj.className = 'selected';
+       if (selected && selected != obj.id)
+               document.getElementById(selected).className = '';
+       selected = obj.id;
+}
+function rowselectbox(obj, checked, handler) {
+       var functionDemo = new Function(handler + ";");
+       functionDemo();
+
+       if (checked)
+               obj.className = 'selected';
+       else
+               obj.className = '';
+}
+//-->
+</script>
+<?php
+
+if ($framed || $popup) {
+       $savant->display('include/fm_footer.tmpl.php');
+} else {
+       $savant->display('include/footer.tmpl.php');
+}
+
+//Harris Timer
+  $mtime = microtime(); 
+  $mtime = explode(" ", $mtime); 
+  $mtime = $mtime[1] + $mtime[0]; 
+  $endtime = $mtime; 
+  $totaltime = ($endtime - $starttime); 
+  debug ($totaltime. ' seconds.', "TIME USED"); 
+//Harris Timer Ends
+
+if (defined('AT_DEVEL') && AT_DEVEL) {
+       debug(TABLE_PREFIX, 'TABLE_PREFIX');
+       debug(DB_NAME, 'DB_NAME');
+       debug(VERSION, 'VERSION');
+       debug($_SESSION);
+}
+
+?>
\ No newline at end of file
diff --git a/include/header.inc.php b/include/header.inc.php
new file mode 100644 (file)
index 0000000..35405ca
--- /dev/null
@@ -0,0 +1,264 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+header('Cache-Control: private, pre-check=0, post-check=0, max-age=0');
+
+//Harris Timer
+  $mtime = microtime(); 
+  $mtime = explode(' ', $mtime); 
+  $mtime = $mtime[1] + $mtime[0]; 
+  $starttime = $mtime; 
+//Harris Timer Ends
+
+global $myLang;
+global $savant;
+global $onload;
+global $content_base_href, $course_base_href;
+global $_base_path;
+global $cid;
+global $contentManager;
+global $db;
+global $_pages;
+global $_stacks;
+global $framed, $popup;
+global $_custom_css;
+global $_custom_head;
+global $substr, $strlen;
+
+require(AT_INCLUDE_PATH . 'lib/menu_pages.php');
+$savant->assign('lang_code', $_SESSION['lang']);
+$savant->assign('lang_charset', $myLang->getCharacterSet());
+$savant->assign('base_path', $_base_path);
+$savant->assign('base_tmpl_path', $_SERVER['HTTP_HOST']);
+$savant->assign('theme', $_SESSION['prefs']['PREF_THEME']);
+$savant->assign('current_date', AT_date(_AT('announcement_date_format')));
+
+$theme_img  = $_base_path . 'themes/'. $_SESSION['prefs']['PREF_THEME'] . '/images/';
+$savant->assign('img', $theme_img);
+
+$_tmp_base_href = AT_BASE_HREF;
+if (isset($course_base_href) || isset($content_base_href)) {
+       $_tmp_base_href .= $course_base_href;
+       if ($content_base_href) {
+               $_tmp_base_href .= $content_base_href;
+       }
+}
+
+$savant->assign('content_base_href', $_tmp_base_href);
+$savant->assign('base_href', AT_BASE_HREF);
+
+//Handle pretty url pages
+if ((($_config['course_dir_name'] + $_config['pretty_url']) > 0) && ($temp = strpos($_SERVER['PHP_SELF'], AT_PRETTY_URL_HANDLER)) > 0){
+       $current_page = $pretty_current_page; //this is set in AT_PRETTY_URL_HANDLER
+}
+
+if ($myLang->isRTL()) {
+       $savant->assign('rtl_css', '<link rel="stylesheet" href="'.$_base_path.'themes/'.$_SESSION['prefs']['PREF_THEME'].'/rtl.css" type="text/css" />');
+} else {
+       $savant->assign('rtl_css', '');
+}
+
+$custom_head = '';
+if (isset($_custom_css)) {
+       $custom_head = '<link rel="stylesheet" href="'.$_custom_css.'" type="text/css" />';
+}
+
+if (isset($_custom_head)) {
+       $custom_head .= '
+' . $_custom_head;
+}
+
+$savant->assign('custom_css', $custom_head);
+
+if ($onload && ($_SESSION['prefs']['PREF_FORM_FOCUS'] || ($substr($onload, -8) != 'focus();'))) {
+       $savant->assign('onload', $onload);
+}
+
+if (isset($_SESSION['valid_user']) && $_SESSION['valid_user'] === true) {
+       if (!empty($_SESSION['member_id'])) {
+               $savant->assign('user_name', get_display_name($_SESSION['member_id']));
+       } else {
+               $savant->assign('user_name', $_SESSION['login']);
+       }
+} else {
+       $savant->assign('user_name', _AT('guest'));
+}
+
+if (!isset($_pages[$current_page])) {
+       global $msg;
+       $msg->addError('PAGE_NOT_FOUND'); // probably the wrong error
+       header('location: '.AT_BASE_HREF.'index.php');
+       exit;
+}
+
+$_top_level_pages        = get_main_navigation($current_page);
+
+$_current_top_level_page = get_current_main_page($current_page);
+
+if (empty($_top_level_pages)) {
+       if (!$_SESSION['member_id'] && !$_SESSION['course_id']) {
+               $_top_level_pages = get_main_navigation($_pages[AT_NAV_PUBLIC][0]);
+       } else if ($_SESSION['course_id'] < 0) {
+               $_top_level_pages = get_main_navigation($_pages[AT_NAV_ADMIN][0]);
+       } else if (!$_SESSION['course_id']) {
+               $_top_level_pages = get_main_navigation($_pages[AT_NAV_START][0]);
+       } else {
+               $_top_level_pages = get_main_navigation($_pages[AT_NAV_COURSE][0]);
+       }
+}
+$_sub_level_pages        = get_sub_navigation($current_page);
+
+$_current_sub_level_page = get_current_sub_navigation_page($current_page);
+
+$_path = get_path($current_page);
+
+unset($_path[0]);
+if (isset($_path[2]['url'], $_sub_level_pages[0]['url']) && $_path[2]['url'] == $_sub_level_pages[0]['url']) {
+       $back_to_page = $_path[3];
+} else if (isset($_path[1]['url'], $_sub_level_pages[0]['url']) && $_path[1]['url'] == $_sub_level_pages[0]['url']) {
+       $back_to_page = isset($_path[2]) ? $_path[2] : null;
+} else if (isset($_path[1])) {
+       $back_to_page = $_path[1];
+}
+
+if (isset($_SESSION['course_id']) && $_SESSION['course_id'] > 0) {
+       $_path[] = array('url' => $_base_path . url_rewrite('index.php'), 'title' => $_SESSION['course_title']);
+} else if (isset($_SESSION['course_id']) && $_SESSION['course_id'] < 0) {
+       $_path[] = array('url' => $_base_path . 'admin/index.php', 'title' => _AT('administration'));
+}
+
+if (isset($_SESSION['member_id']) && $_SESSION['member_id']) {
+       $_path[] = array('url' => $_base_path . 'bounce.php?course=0', 'title' => _AT('my_start_page'));
+} else if (!isset($_SESSION['course_id']) || !$_SESSION['course_id']) {
+       $_path[] = array('url' => $_base_path . 'login.php', 'title' => SITE_NAME);
+}
+
+$_path = array_reverse($_path);
+if (isset($_pages[$current_page]['title'])) {
+       $_page_title = $_pages[$current_page]['title'];
+} else {
+       $_page_title = _AT($_pages[$current_page]['title_var']);
+}
+
+
+
+/* calculate the section_title: */
+if (isset($_SESSION['course_id']) && $_SESSION['course_id'] > 0) {
+       //Truncate course title if it's > 45.
+       $section_title = validate_length($_SESSION['course_title'], 45, VALIDATE_LENGTH_FOR_DISPLAY);
+       // If there is an icon, display it on the header
+       $sql = 'SELECT icon FROM '.TABLE_PREFIX.'courses WHERE course_id='.$_SESSION['course_id'];
+       $result =  mysql_query($sql, $db);
+       $row = mysql_fetch_assoc($result);
+       if (!empty($row['icon'])){
+               //Check if this is a custom icon, if so, use get_course_icon.php to get it
+               //Otherwise, simply link it from the images/
+               $custom_icon_path = AT_CONTENT_DIR.$_SESSION['course_id']."/custom_icons/";
+               if (file_exists($custom_icon_path.$row['icon'])) {
+                       if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+                               $course_icon = $_base_path.'get_course_icon.php/?id='.$_SESSION['course_id'];
+                       } else {
+                               $course_icon = $_base_path.'content/' . $_SESSION['course_id'] . '/';
+                       }
+               } else {
+                       $course_icon = $_base_path.'images/courses/'.$row['icon'];
+               }
+               $savant->assign('icon', $course_icon);
+       }
+} else if (!isset($_SESSION['valid_user']) || !$_SESSION['valid_user']) {
+       $section_title = SITE_NAME;
+       if (defined('HOME_URL') && HOME_URL) {
+               $_top_level_pages[] = array('url' => HOME_URL, 'title' => _AT('home'));
+       }
+} else if ($_SESSION['course_id'] < 0) {
+       $section_title = _AT('administration');
+} else if (!$_SESSION['course_id']) {
+       $section_title = _AT('my_start_page');
+}
+$savant->assign('current_top_level_page', $_current_top_level_page);
+$savant->assign('sub_level_pages', $_sub_level_pages);
+$savant->assign('current_sub_level_page', $_current_sub_level_page);
+
+$savant->assign('path', $_path);
+$savant->assign('back_to_page', isset($back_to_page) ? $back_to_page : null);
+$savant->assign('page_title', $_page_title);
+$savant->assign('top_level_pages', $_top_level_pages);
+$savant->assign('section_title', $section_title);
+
+if (isset($_pages[$current_page]['guide'])) {
+       $savant->assign('guide', AT_GUIDES_PATH . $_pages[$current_page]['guide']);
+}
+
+$myLang->sendContentTypeHeader();
+
+if (isset($_SESSION['course_id']) && $_SESSION['course_id'] > -1) {
+
+       /* the list of our courses: */
+       /* used for the courses drop down */
+       global $system_courses;
+       if ($_SESSION['valid_user']) {
+               $sql    = "SELECT E.course_id FROM ".TABLE_PREFIX."course_enrollment E WHERE E.member_id=$_SESSION[member_id] AND E.approved<>'n'";
+               $result = @mysql_query($sql, $db);
+
+               $nav_courses = array(); /* the list of courses we're enrolled in or own */
+               while ($row = @mysql_fetch_assoc($result)) {
+                       //Truncate course title if it's > 45.
+                       $nav_courses[$row['course_id']] = validate_length($system_courses[$row['course_id']]['title'], 45, VALIDATE_LENGTH_FOR_DISPLAY);
+               }
+
+               natcasesort($nav_courses);
+               reset($nav_courses);
+               $savant->assign('nav_courses',    $nav_courses);
+       }
+
+       if (($_SESSION['course_id'] > 0) && isset($_SESSION['prefs']['PREF_JUMP_REDIRECT']) && $_SESSION['prefs']['PREF_JUMP_REDIRECT']) {
+               $savant->assign('rel_url', $_rel_url);
+       } else {
+               $savant->assign('rel_url', '');
+       }
+
+       /* course specific elements: */
+       /* != 'public' special case for the about.php page, which is available from a course but hides the content menu */
+       $sequence_links = array();
+       if ($_SESSION['course_id'] > 0) {
+               $sequence_links = $contentManager->generateSequenceCrumbs($cid);
+               $savant->assign('sequence_links', $sequence_links);
+       }
+
+       //side menu array
+       if ($_SESSION['course_id'] > 0) {
+               $side_menu = array();
+               $side_menu = explode('|', $system_courses[$_SESSION['course_id']]['side_menu']);
+               $side_menu = array_intersect($side_menu, $_stacks);
+               $savant->assign('side_menu', $side_menu);
+       }
+}
+
+/* Register our Errorhandler on everypage */
+//require_once(AT_INCLUDE_PATH . 'classes/ErrorHandler/ErrorHandler.class.php');
+//$err =& new ErrorHandler();
+
+// if filemanager is a inside a popup or a frame
+// i don't like this code. i don't know were these two variables are coming from
+// anyone can add ?framed=1 to a URL to alter the behaviour.
+if ((isset($_REQUEST['framed']) && $_REQUEST['framed']) || (isset($_REQUEST['popup']) && $_REQUEST['popup'])) {
+       $savant->assign('framed', 1);
+       $savant->assign('popup', 1);
+       $savant->display('include/fm_header.tmpl.php');
+} else {
+       $savant->display('include/header.tmpl.php');
+}
+?>
diff --git a/include/html/announcements.inc.php b/include/html/announcements.inc.php
new file mode 100644 (file)
index 0000000..66534fd
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+       require_once(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+       /* help for content pages */
+
+       if (FALSE && defined('AT_SHOW_TEST_BOX') && AT_SHOW_TEST_BOX) {
+               // print new available tests
+               
+               $sql    = "SELECT T.test_id, T.title FROM ".TABLE_PREFIX."tests T WHERE T.course_id=$_SESSION[course_id] AND T.start_date<=NOW() AND T.end_date>= NOW() ORDER BY T.start_date, T.title";
+               $result = mysql_query($sql, $db);
+               $num_tests = mysql_num_rows($result);
+               $tests = '';
+               while (($row = mysql_fetch_assoc($result)) && authenticate_test($row['test_id'])) {
+                       $tests .= '<a href="'.$_base_path.'tools/take_test.php?tid='.$row['test_id'].'">'.$row['title'].'</a><br />';
+               } 
+
+               if ($tests) { ?>
+                               <table border="0" cellspacing="0" cellpadding="0" align="center">
+                               <tr>
+                                       <td class="test-box"><small><a href="<?php echo AT_BASE_HREF; ?>tools/my_tests.php?g=32"><?php echo _AT('curren_tests_surveys'); ?></a></small></td>
+                               </tr>
+                               <tr>
+                                       <td class="dropdown"><?php echo $tests; ?></td>
+                               </tr>
+                               </table><br />
+               <?php 
+               }
+       }
+
+/* the "home" links: */
+$home_links = get_home_navigation();
+$savant->assign('home_links', $home_links);
+
+
+/* the news announcements: */
+$news = array();
+$num_pages = 1;
+$page = intval($_GET['p']);
+if (!$page) {
+       $page = 1;
+}      
+
+$sql   = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."news WHERE course_id=$_SESSION[course_id]";
+$result = mysql_query($sql, $db);
+
+if ($row = mysql_fetch_assoc($result)) {       
+       $num_results = $row['cnt'];
+       $results_per_page = NUM_ANNOUNCEMENTS;
+       $num_pages = ceil($num_results / $results_per_page);
+
+       $count = (($page-1) * $results_per_page) + 1;
+
+       $offset = ($page-1)*$results_per_page;
+
+       $sql = "SELECT N.* FROM ".TABLE_PREFIX."news N WHERE N.course_id=$_SESSION[course_id] ORDER BY date DESC LIMIT $offset, $results_per_page";
+       
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_assoc($result)) {
+               /* this can't be cached because it called _AT */
+
+               $news[$row['news_id']] = array(
+                                               'date'          => AT_date(     _AT('announcement_date_format'), 
+                                                                                               $row['date'], 
+                                                                                               AT_DATE_MYSQL_DATETIME),
+                                               'title'         => AT_print($row['title'], 'news.title'),
+                                               'body'          => AT_print($row['body'], 'news.body', $row['formatting']));
+       }
+}
+
+$savant->assign('announcements', $news);
+$savant->assign('num_pages', $num_pages);
+$savant->assign('current_page', $page);
+$savant->display('index.tmpl.php');
+
+?>
\ No newline at end of file
diff --git a/include/html/auto_enroll_courses.inc.php b/include/html/auto_enroll_courses.inc.php
new file mode 100644 (file)
index 0000000..6fb0045
--- /dev/null
@@ -0,0 +1,101 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id: auto_enroll_courses.php 7208 2008-01-09 16:07:24Z cindy $\r
+\r
+// Note: MUST set variables $member_id before calling this page.\r
+\r
+// auto enroll into courses that link with en_id\r
+if (isset($_REQUEST["en_id"]) && $_REQUEST["en_id"] <> "")\r
+{\r
+\r
+       $associate_string = $_REQUEST["en_id"];\r
+       \r
+       $sql_courses = "SELECT aec.course_id\r
+                         FROM " . TABLE_PREFIX."auto_enroll a, " . \r
+                                  TABLE_PREFIX."auto_enroll_courses aec \r
+                        where a.associate_string='".$associate_string ."'\r
+                          and a.auto_enroll_id = aec.auto_enroll_id";\r
+\r
+       $result_courses = mysql_query($sql_courses, $db) or die(mysql_error());\r
+       \r
+       if (mysql_num_rows($result_courses) > 0)  $_SESSION['enroll'] = AT_ENROLL_YES;\r
+       \r
+       while ($row_courses = mysql_fetch_assoc($result_courses))\r
+       {\r
+               $course = $row_courses["course_id"];\r
+               \r
+               $sql    = "SELECT access, member_id FROM ".TABLE_PREFIX."courses WHERE course_id=$course";\r
+               $result = mysql_query($sql, $db);\r
+               $course_info = mysql_fetch_assoc($result);\r
+               \r
+               if ($course_info['access'] == 'private') \r
+               {\r
+                       $sql    = "INSERT INTO ".TABLE_PREFIX."course_enrollment VALUES ($member_id, $course, 'n', 0, '"._AT('student')."', 0)";\r
+                       $result = mysql_query($sql, $db);\r
+       \r
+                       // send the email - if needed\r
+                       if ($system_courses[$course]['notify'] == 1) {\r
+                               $mail_list = array();   //initialize an array to store all the pending emails\r
+       \r
+                               //Get the list of students with enrollment privilege\r
+                               $module =& $moduleFactory->getModule('_core/enrolment');\r
+                               $sql    = "SELECT email, first_name, last_name, privileges FROM ".TABLE_PREFIX."members m INNER JOIN ".TABLE_PREFIX."course_enrollment ce ON m.member_id=ce.member_id WHERE ce.privileges > 0 AND ce.course_id=$course";\r
+                               $result = mysql_query($sql, $db);\r
+                               while ($row     = mysql_fetch_assoc($result))\r
+                               {\r
+                                       if (query_bit($row['privileges'], $module->getPrivilege()))\r
+                                       {\r
+                                               unset($row['privileges']);      //we don't need the privilege to flow around\r
+                                               $mail_list[] = $row;\r
+                                       }\r
+                               }\r
+                               \r
+                               //Get instructor information\r
+                               $ins_id = $system_courses[$course]['member_id'];\r
+                               $sql    = "SELECT email, first_name, last_name FROM ".TABLE_PREFIX."members WHERE member_id=$ins_id";\r
+                               $result = mysql_query($sql, $db);\r
+                               $row    = mysql_fetch_assoc($result);\r
+                               $mail_list[] = $row;\r
+       \r
+                               //Send email notification to both assistants with privileges & Instructor\r
+                               foreach ($mail_list as $row)\r
+                               {\r
+                                       $to_email = $row['email'];\r
+                                       $tmp_message  = $row['first_name']  .' ' . $row['last_name']."\n\n";\r
+                                       $tmp_message .= _AT('enrol_messagenew', $system_courses[$course]['title'], AT_BASE_HREF );\r
+                                       if ($to_email != '') {\r
+                                               require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');\r
+       \r
+                                               $mail = new ATutorMailer;\r
+                                               $mail->From     = $_config['contact_email'];\r
+                                               $mail->FromName = $_config['site_name'];\r
+                                               $mail->AddAddress($to_email);\r
+                                               $mail->Subject = _AT('enrol_message3');\r
+                                               $mail->Body    = $tmp_message;\r
+       \r
+                                               if (!$mail->Send()) \r
+                                               {\r
+                                                  $msg->addError('SENDING_ERROR');\r
+                                               }\r
+                                               unset($mail);\r
+                                       }\r
+                               }\r
+                       }\r
+               } else {\r
+                       $sql    = "INSERT INTO ".TABLE_PREFIX."course_enrollment VALUES ($member_id, $course, 'y', 0, '"._AT('student')."', 0)";\r
+                       $result = mysql_query($sql, $db);\r
+               }\r
+       }\r
+       \r
+}\r
+?>
\ No newline at end of file
diff --git a/include/html/auto_enroll_list_courses.inc.php b/include/html/auto_enroll_list_courses.inc.php
new file mode 100644 (file)
index 0000000..22c0b69
--- /dev/null
@@ -0,0 +1,85 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id: auto_enroll_list_courses.php 7208 2008-01-09 16:07:24Z cindy $\r
+\r
+// Lists all courses to auto enroll\r
+if (isset($_REQUEST["en_id"]) && $_REQUEST["en_id"] <> "")\r
+{\r
+       $associate_string = $_REQUEST["en_id"];\r
+       \r
+       $cats   = array();\r
+       $cats[0] = _AT('cats_uncategorized');\r
+       \r
+       $sql = "SELECT cat_id, cat_name FROM ".TABLE_PREFIX."course_cats";\r
+       $result = mysql_query($sql,$db);\r
+       while($row = mysql_fetch_array($result)) {\r
+               $cats[$row['cat_id']] = $row['cat_name'];\r
+       }\r
+       \r
+       $sql_courses = "SELECT aec.auto_enroll_courses_id auto_enroll_courses_id, \r
+                              aec.course_id,\r
+                              c.cat_id,\r
+                              c.title title\r
+                         FROM " . TABLE_PREFIX."auto_enroll a, " . \r
+                                  TABLE_PREFIX."auto_enroll_courses aec, " . \r
+                                  TABLE_PREFIX ."courses c\r
+                        where a.associate_string='".$associate_string ."'\r
+                          and a.auto_enroll_id = aec.auto_enroll_id\r
+                          and aec.course_id = c.course_id";\r
+\r
+       $result_courses = mysql_query($sql_courses, $db) or die(mysql_error());\r
+       \r
+       if (mysql_num_rows($result_courses) > 0)\r
+       {\r
+?>\r
+\r
+<fieldset>\r
+       <legend>Courses to Auto Enroll</legend>\r
+               <?php echo $table_title; ?>\r
+       \r
+       <div class="row">\r
+               <table summary="" class="data" rules="cols" align="left" style="width: 100%;">\r
+               \r
+               <thead>\r
+               <tr>\r
+                       <th scope="col"><?php echo _AT('title'); ?></th>\r
+                       <th scope="col"><?php echo _AT('category'); ?></th>\r
+               </tr>\r
+               </thead>\r
+\r
+               <tbody>\r
+<?php\r
+       if ($row_courses = mysql_fetch_assoc($result_courses)): \r
+               do {\r
+               ?>\r
+                       <tr>\r
+                               <td><label for="m<?php echo $row_courses['auto_enroll_courses_id']; ?>"><?php echo $row_courses['title']; ?></label></td>\r
+                               <td><?php echo $cats[$row_courses['cat_id']]; ?></td>\r
+                       </tr>\r
+               <?php } while ($row_courses = mysql_fetch_assoc($result_courses)); ?>\r
+       <?php else: ?>\r
+                       <tr>\r
+                               <td colspan="3"><?php echo _AT('none_found'); ?></td>\r
+                       </tr>\r
+       <?php endif; ?>\r
+               </tbody>\r
+               </table>\r
+       </div>\r
+       </legend>\r
+</fieldset>\r
+\r
+       <?php\r
+       }\r
+\r
+}\r
+?>\r
diff --git a/include/html/browse.inc.php b/include/html/browse.inc.php
new file mode 100644 (file)
index 0000000..b448fa1
--- /dev/null
@@ -0,0 +1,193 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+require(AT_INCLUDE_PATH.'lib/admin_categories.inc.php');
+
+$cats  = array();
+$cats[0] = _AT('cats_uncategorized');
+
+$sql = "SELECT cat_id, cat_name FROM ".TABLE_PREFIX."course_cats";
+$result = mysql_query($sql,$db);
+while($row = mysql_fetch_array($result)) {
+       $cats[$row['cat_id']] = $row['cat_name'];
+}
+
+if ($_GET['reset_filter']) { unset($_GET); }
+
+$page_string = '';
+
+if (isset($_GET['access']) && in_array($_GET['access'], array('public','private','protected'))) {
+       $page_string .= SEP.'access='.$_GET['access'];
+       $sql_access = "='{$_GET['access']}'";
+} else {
+       $sql_access     = '<>-1';
+       $_GET['access'] = '';
+}
+
+if (isset($_GET['category']) && ($_GET['category'] > -1)) {
+       $_GET['category'] = intval($_GET['category']);
+       $page_string .= SEP.'category='.$_GET['category'];
+       $sql_category = '='.$_GET['category'];
+} else {
+       $sql_category     = '<>-1';
+       $_GET['category'] = -1; // all (because 0 = uncategorized)
+}
+
+if (isset($_GET['include']) && $_GET['include'] == 'one') {
+       $checked_include_one = ' checked="checked"';
+       $page_string .= SEP.'include=one';
+} else {
+       $_GET['include'] = 'all';
+       $checked_include_all = ' checked="checked"';
+       $page_string .= SEP.'include=all';
+}
+
+if (!empty($_GET['search'])) {
+       $page_string .= SEP.'search='.urlencode($stripslashes($_GET['search']));
+       $search = $addslashes($_GET['search']);
+       $search = explode(' ', $search);
+
+       if ($_GET['include'] == 'all') {
+               $predicate = 'AND ';
+       } else {
+               $predicate = 'OR ';
+       }
+
+       $sql_search = '';
+       foreach ($search as $term) {
+               $term = trim($term);
+               $term = str_replace(array('%','_'), array('\%', '\_'), $term);
+               if ($term) {
+                       $term = '%'.$term.'%';
+                       $sql_search .= "((title LIKE '$term') OR (description LIKE '$term')) $predicate";
+               }
+       }
+       $sql_search = '('.substr($sql_search, 0, -strlen($predicate)).')';
+} else {
+       $sql_search = '1';
+}
+
+$sql   = "SELECT COUNT(course_id) AS cnt FROM ".TABLE_PREFIX."courses WHERE access $sql_access AND cat_id $sql_category AND $sql_search AND hide=0";
+$result = mysql_query($sql, $db);
+$row = mysql_fetch_assoc($result);
+$num_results = $row['cnt'];
+
+$sql   = "SELECT * FROM ".TABLE_PREFIX."courses WHERE access $sql_access AND cat_id $sql_category AND $sql_search AND hide=0 ORDER BY title";
+$courses_result = mysql_query($sql, $db);
+
+// get the categories <select>, if there are any.
+// we need ob_start/ob_clean, because select_categories() outputs directly.
+// we do this so that if there are no categories, then the option doesn't appear.
+ob_start();
+select_categories(get_categories(), 0, $_GET['category'], false);
+$categories_select = ob_get_contents();
+ob_clean();
+
+$has_categories = false;
+if ($categories_select != '<option value="0"></option>') {
+       $has_categories = true;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+<fieldset class="group_form"><legend class="group_form"><?php echo _AT('filter'); ?></legend>
+       <form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+               <div class="input-form">
+                       <div class="row">
+                               <h3><?php echo _AT('results_found', $num_results); ?></h3>
+                       </div>
+                       <div class="row">
+                               <?php echo _AT('access'); ?><br />
+                               <input type="radio" name="access" value="private" id="s1" <?php if ($_GET['access'] == 'private') { echo 'checked="checked"'; } ?> /><label for="s1"><?php echo _AT('private'); ?></label> 
+
+                               <input type="radio" name="access" value="protected" id="s2" <?php if ($_GET['access'] == 'protected') { echo 'checked="checked"'; } ?> /><label for="s2"><?php echo _AT('protected'); ?></label>
+
+                               <input type="radio" name="access" value="public" id="s3" <?php if ($_GET['access'] == 'public') { echo 'checked="checked"'; } ?> /><label for="s3"><?php echo _AT('public'); ?></label>
+
+                               <input type="radio" name="access" value="" id="s" <?php if ($_GET['access'] == '') { echo 'checked="checked"'; } ?> /><label for="s"><?php echo _AT('all'); ?></label>
+                       </div>
+
+               <?php if ($has_categories): ?>
+                       <div class="row">
+                               <label for="category"><?php echo _AT('category'); ?></label><br/>
+                               <select name="category" id="category">
+                                       <option value="-1">- - - <?php echo _AT('cats_all'); ?> - - -</option>
+                                       <option value="0" <?php if ($_GET['category'] == 0) { echo 'selected="selected"'; } ?>>- - - <?php echo _AT('cats_uncategorized'); ?> - - -</option>
+                                       <?php echo $categories_select; ?>
+                               </select>
+                       </div>
+               <?php endif; ?>
+
+                       <div class="row">
+                               <label for="search"><?php echo _AT('search'); ?> (<?php echo _AT('title').', '._AT('description'); ?>)</label><br />
+
+                               <input type="text" name="search" id="search" size="40" value="<?php echo htmlspecialchars($_GET['search']); ?>" />
+                               <br/>
+                               <?php echo _AT('search_match'); ?>:
+                               <input type="radio" name="include" value="all" id="match_all" <?php echo $checked_include_all; ?> /><label for="match_all"><?php echo _AT('search_all_words'); ?></label> 
+                               <input type="radio" name="include" value="one" id="match_one" <?php echo $checked_include_one; ?> /><label for="match_one"><?php echo _AT('search_any_word'); ?></label>
+                       </div>
+
+                       <div class="row buttons">
+                               <input type="submit" name="filter" value="<?php echo _AT('filter'); ?>"/>
+                               <input type="submit" name="reset_filter" value="<?php echo _AT('reset_filter'); ?>"/>
+                       </div>
+               </div>
+       </form>
+</fieldset>
+       <ul style=" padding: 0px; margin: 0px">
+       <?php while ($row = mysql_fetch_assoc($courses_result)): ?>
+               <li style="list-style: none; width: 80%">
+                       <dl class="browse-course">
+                               <dt>
+                                       <?php if ($row['icon']) { // if a course icon is available, display it here.  
+                                               $style_for_title = 'style="height: 79px;"'; 
+
+                                               //Check if this is a custom icon, if so, use get_course_icon.php to get it
+                                               //Otherwise, simply link it from the images/
+                                               $path = AT_CONTENT_DIR.$row['course_id']."/custom_icons/";
+                               if (file_exists($path.$row['icon'])) {
+                                                       if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+                                                               $course_icon = 'get_course_icon.php/?id='.$row['course_id'];
+                                                       } else {
+                                                               $course_icon = 'content/' . $row['course_id'] . '/';
+                                                       }
+                                               } else {
+                                                       $course_icon = 'images/courses/'.$row['icon'];
+                                               }
+                                       ?>
+                                               <a href="<?php echo url_rewrite('bounce.php?course='.$row['course_id'], true); ?>"><img src="<?php echo $course_icon; ?>" class="headicon" alt="" /></a>        
+                                       <?php } ?>
+                               </dt>
+                               <dd><h3 <?php echo $style_for_title; ?>><a href="<?php echo url_rewrite('bounce.php?course='.$row['course_id'], true); ?>"><?php echo $row['title']; ?></a></h3></dd>
+                               
+                       <?php if ($row['description']): ?>
+                               <dt><?php echo _AT('description'); ?></dt>
+                               <dd><?php echo nl2br($row['description']); ?>&nbsp;</dd>
+                       <?php endif; ?>
+
+                       <?php if ($has_categories): ?>
+                               <dt><?php echo _AT('category'); ?></dt>
+                               <dd><a href="<?php echo $_SERVER['PHP_SELF'].'?'.$page_string.SEP; ?>category=<?php echo $row['cat_id']; ?>"><?php echo $cats[$row['cat_id']]; ?></a>&nbsp;</dd>
+                       <?php endif; ?>
+                               
+                               <dt><?php echo _AT('instructor'); ?></dt>
+                               <dd><a href="<?php echo AT_BASE_HREF; ?>contact_instructor.php?id=<?php echo $row['course_id']; ?>"><?php echo get_display_name($row['member_id']); ?></a></dd>
+
+                               <dt><?php echo _AT('access'); ?></dt>
+                               <dd><?php echo _AT($row['access']); ?></dd>
+                       </dl>
+               </li>
+       <?php endwhile; ?>
+       </ul>
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/include/html/code_picker.inc.php b/include/html/code_picker.inc.php
new file mode 100644 (file)
index 0000000..cb768c3
--- /dev/null
@@ -0,0 +1,78 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+?>
+<table border="0" cellspacing="0" cellpadding="0" width="100%">
+<tr>
+       <td colspan="2"><small><?php echo _AT('click_code'); ?></small></td>
+</tr>
+<tr>
+       <td align="right"><small><b><?php echo _AT('emoticons'); ?>:</b></small></td>
+       <td><small><?php
+               echo '<a href="javascript:smilie(\':)\')" title=":)">'.smile_replace(':)').'</a> ';
+               echo '<a href="javascript:smilie(\';)\')" title=";)">'.smile_replace(';)').'</a> ';
+               echo '<a href="javascript:smilie(\':(\')" title=":(">'.smile_replace(':(').'</a> ';
+               echo '<a href="javascript:smilie(\'::ohwell::\')" title=":\\">'.smile_replace('::ohwell::').'</a> ';
+
+               echo '<a href="javascript:smilie(\':P\')" title=":P">'.smile_replace(':P').'</a> ';
+               echo '<a href="javascript:smilie(\'::angry::\')" title="::angry::">'.smile_replace('::angry::').'</a> ';
+
+               echo '<a href="javascript:smilie(\'::evil::\')" title="::evil::">'.smile_replace('::evil::').'</a> ';
+               echo '<a href="javascript:smilie(\'::lol::\')" title="::lol::">'.smile_replace('::lol::').'</a> ';
+               echo '<a href="javascript:smilie(\'::confused::\')" title="::confused::">'.smile_replace('::confused::').'</a> ';
+               echo '<a href="javascript:smilie(\'::crazy::\')" title="::crazy::">'.smile_replace('::crazy::').'</a> ';
+
+               echo '<a href="javascript:smilie(\'::tired::\')" title="::tired::">'.smile_replace('::tired::').'</a> ';
+               echo '<a href="javascript:smilie(\'::muah::\')" title="::muah::">'.smile_replace('::muah::').'</a>';
+       ?></small></td>
+</tr>
+<tr>
+       <td align="right"><small><b><?php echo _AT('codes'); ?>:</b></small></td>
+       <td><small><a href="javascript:smilie('[b] [/b]')" title="[b] [/b]"><?php echo _AT('bold'); ?></a>,
+       <a href="javascript:smilie('[i] [/i]')" title="[i] [/i]"><?php echo _AT('italic'); ?></a>,
+       <a href="javascript:smilie('[u] [/u]')" title="[u] [/u]"><?php echo _AT('underline'); ?></a>,
+       <a href="javascript:smilie('[center] [/center]')" title="[center] [/center]"><?php echo _AT('center'); ?></a>,
+       <a href="javascript:smilie('[quote] [/quote]')" title="[quote] [/quote]"><?php echo _AT('quote'); ?></a>,
+       <a href="javascript:smilie('http://')" title="http://"><?php echo _AT('link'); ?></a>,
+       <a href="javascript:smilie('[image|alt text][/image]')" title="[image|alt text][/image]"><?php echo _AT('image'); ?></a>,
+       <a href="javascript:smilie('[media][/media]')" title="[media] [/media]"><?php echo _AT('media'); ?></a><?php
+       if (isset($current_tab)) {
+               echo ', <a href="javascript:smilie(\' [?][/?]\')" title="[?][/?]">',_AT('add_term'), '</a>';
+               echo '<a href="javascript:smilie(\' [code][/code]\')" title="[code][/code]" onclick="document.form.formatting.html.checked=true;">',_AT('add_code'), '</a>';
+       } ?></small></td>
+</tr>
+<tr>
+       <td align="right"><small><b><?php echo _AT('colors'); ?>:</b></small></td>
+       <td><table border="0" cellspacing="2" cellpadding="0" summary="">
+       <tr>
+               <td bgcolor="blue"><a href="javascript:smilie('[blue] [/blue]')" title="[blue] [/blue]"><img src="<?php echo $_base_path; ?>images/clr.gif" alt="<?php echo _AT('blue'); ?>" height="15" width="15" border="0" /></a></td>
+               <td bgcolor="red"><a href="javascript:smilie('[red] [/red]')" title="[red] [/red]"><img src="<?php echo $_base_path; ?>images/clr.gif" alt="<?php echo _AT('red'); ?>" height="15" width="15" border="0" /></a></td>
+               <td bgcolor="green"><a href="javascript:smilie('[green] [/green]')" title="[green] [/green]"><img src="<?php echo $_base_path; ?>images/clr.gif" alt="<?php echo _AT('green'); ?>" height="15" width="15" border="0" /></a></td>
+               <td bgcolor="orange"><a href="javascript:smilie('[orange] [/orange]')" title="[orange] [/orange]"><img src="<?php echo $_base_path; ?>images/clr.gif" alt="<?php echo _AT('orange'); ?>" height="15" width="15" border="0" /></a></td>
+               <td bgcolor="purple"><a href="javascript:smilie('[purple] [/purple]')" title="[purple] [/purple]"><img src="<?php echo $_base_path; ?>images/clr.gif" alt="<?php echo _AT('purple'); ?>" height="15" width="15" border="0" /></a></td>
+               <td bgcolor="gray"><a href="javascript:smilie('[gray] [/gray]')" title="[gray] [/gray]"><img src="<?php echo $_base_path; ?>images/clr.gif" alt="<?php echo _AT('gray'); ?>" height="15" width="15" border="0" /></a></td>
+       </tr>
+       </table></td>
+</tr>
+</table>
+       <script type="text/javascript">
+       //<!--
+       function smilie(thesmilie) {
+               // inserts smilie text
+               document.form.body.value += thesmilie+" ";
+               document.form.body.focus();
+       }
+
+       //-->
+       </script>
\ No newline at end of file
diff --git a/include/html/copyright.inc.php b/include/html/copyright.inc.php
new file mode 100644 (file)
index 0000000..1d158c9
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+global $_base_path;
+global $system_courses;
+
+?>
+<div align="center"><?php
+
+       if (($_SESSION['course_id'] > 0) && $system_courses[$_SESSION['course_id']]['copyright'] != '') {       
+               echo '<small>' . AT_print($system_courses[$_SESSION['course_id']]['copyright'], 'courses.copyright') . '</small><br />';
+       }
+
+       /****************************************************************************************/
+       /* VERY IMPORTANT
+          IN KEEPING WITH THE TERMS OF THE ATUTOR LICENCE AGREEMENT (GNU GPL), THE FOLLOWING
+          COPYRIGHT LINES MAY NOT BE ALTERED IN ANY WAY.
+       */
+?>
+       <small><?php echo _AT('copyright').'. '; echo '<a href="'.$_base_path.'about.php">'._AT('about_atutor').'</a>.'; ?><br />
+       <span id="howto"><?php echo _AT('general_help', AT_GUIDES_PATH.'index_list.php?lang='.$_SESSION['lang']); ?></span></small>
+</div>
\ No newline at end of file
diff --git a/include/html/course_icon.inc.php b/include/html/course_icon.inc.php
new file mode 100644 (file)
index 0000000..9469674
--- /dev/null
@@ -0,0 +1,52 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id: course_icon.inc.php 7603 2008-06-11 14:59:33Z hwong $\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+\r
+// check if GD is installed\r
+if (!extension_loaded('gd')) {\r
+       $msg->addInfo('FEATURE_NOT_AVAILABLE');\r
+}else{\r
+\r
+       $gd_info = gd_info();\r
+       $supported_images = array();\r
+\r
+       if ($gd_info['GIF Create Support']) {\r
+               $supported_images[] = 'gif';\r
+       }\r
+       if ($gd_info['JPG Support']) {\r
+               $supported_images[] = 'jpg';\r
+       }\r
+       if ($gd_info['PNG Support']) {\r
+               $supported_images[] = 'png';\r
+       }\r
+       \r
+       if (!$supported_images) {\r
+               $msg->addInfo('FEATURE_NOT_AVAILABLE');\r
+       }\r
+}\r
+?>\r
+<input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $_config['prof_pic_max_file_size']; ?>" />\r
+\r
+    <div style="float:right;width:40%;">\r
+               <h3 style="padding-top:0;"><?php echo _AT('upload_icon'); ?></h3>\r
+               <?php\r
+                       if(!extension_loaded('gd')){\r
+                               $msg->printInfos();\r
+                       }else{\r
+\r
+               ?>\r
+               <input type="file"  name="customicon" id="customicon" /> (<?php echo implode(', ', $supported_images); ?>)\r
+               <?php } ?>\r
+       </div>\r
diff --git a/include/html/course_properties.inc.php b/include/html/course_properties.inc.php
new file mode 100644 (file)
index 0000000..1953e1e
--- /dev/null
@@ -0,0 +1,681 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+require_once(AT_INCLUDE_PATH.'lib/filemanager.inc.php');
+require_once(AT_INCLUDE_PATH.'lib/admin_categories.inc.php');
+require_once(AT_INCLUDE_PATH.'lib/tinymce.inc.php');
+//require_once(AT_INCLUDE_PATH.'lib/course_icon.inc.php');
+
+$_GET['show_courses'] = $addslashes(intval($_GET['show_courses']));
+$_GET['current_cat'] = $addslashes(intval($_GET['current_cat']));
+
+if (!isset($_REQUEST['setvisual']) && !isset($_REQUEST['settext'])) {
+       if ($_SESSION['prefs']['PREF_CONTENT_EDITOR'] == 1) {
+               $_POST['formatting'] = 1;
+               $_REQUEST['settext'] = 0;
+               $_REQUEST['setvisual'] = 0;
+
+       } else if ($_SESSION['prefs']['PREF_CONTENT_EDITOR'] == 2) {
+               $_POST['formatting'] = 1;
+               $_POST['settext'] = 0;
+               $_POST['setvisual'] = 1;
+
+       } else { // else if == 0
+               $_POST['formatting'] = 0;
+               $_REQUEST['settext'] = 0;
+               $_REQUEST['setvisual'] = 0;
+       }
+}
+
+if (($_POST['setvisual'] && !$_POST['settext']) || $_GET['setvisual']) {
+       load_editor('banner');
+}
+
+if (!isset($isadmin, $course, $db)) {
+       return; 
+}
+
+if (isset($_POST['form_course'])) {
+
+       $row['course_id']                       = $_POST['course'];
+       $row['title']                           = $_POST['title'];
+       $row['primary_language']        = $_POST['primary_language'];
+       $row['member_id']                       = $_POST['member_id'];
+       $row['description']                     = $_POST['description'];
+       $row['course_dir_name']         = $_POST['course_dir_name'];
+       $row['cat_id']                          = $_POST['cat_id'];
+       $row['content_packaging']       = $_POST['content_packaging'];
+
+       $row['access']                          = $_POST['access'];
+       $row['notify']                          = $_POST['notify'];
+
+       $row['max_quota']                       = $_POST['max_quota'];
+       $row['max_file_size']           = $_POST['max_file_size'];
+
+       $row['created_date']            = date('Y-m-d H:i:s');
+       $row['primary_language']    = $_POST['pri_lang'];
+       $row['rss']                 = $_POST['rss'];
+
+       $row['copyright']                       = $_POST['copyright'];
+       $row['icon']                            = $_POST['icon'];
+       $row['banner']              = stripcslashes($_POST['banner']);
+
+       if (intval($_POST['release_date'])) {
+               $day_release    = intval($_POST['day_release']);
+               $month_release  = intval($_POST['month_release']);
+               $year_release   = intval($_POST['year_release']);
+               $hour_release   = intval($_POST['hour_release']);
+               $min_release    = intval($_POST['min_release']);
+
+               if (strlen($month_release) == 1){
+                       $month_release = "0$month_release";
+               }
+               if (strlen($day_release) == 1){
+                       $day_release = "0$day_release";
+               }
+               if (strlen($hour_release) == 1){
+                       $hour_release = "0$hour_release";
+               }
+               if (strlen($min_release) == 1){
+                       $min_release = "0$min_release";
+               }
+               $row['release_date'] = "$year_release-$month_release-$day_release $hour_release:$min_release:00";
+       } else {
+               $row['release_date'] = 0;
+       }
+
+       if (intval($_POST['end_date'])) {
+               $day_end        = intval($_POST['day_end']);
+               $month_end      = intval($_POST['month_end']);
+               $year_end       = intval($_POST['year_end']);
+               $hour_end       = intval($_POST['hour_end']);
+               $min_end        = intval($_POST['min_end']);
+
+               if (strlen($month_end) == 1){
+                       $month_end = "0$month_end";
+               }
+               if (strlen($day_end) == 1){
+                       $day_end = "0$day_end";
+               }
+               if (strlen($hour_end) == 1){
+                       $hour_end = "0$hour_end";
+               }
+               if (strlen($min_end) == 1){
+                       $min_end = "0$min_end";
+               }
+               $row['end_date'] = "$year_end-$month_end-$day_end $hour_end:$min_end:00";
+       } else {
+               $row['end_date'] = 0;
+       }
+
+} else if ($course) {
+       $sql    = "SELECT *, DATE_FORMAT(release_date, '%Y-%m-%d %H:%i:00') AS release_date, DATE_FORMAT(end_date, '%Y-%m-%d %H:%i:00') AS end_date  FROM ".TABLE_PREFIX."courses WHERE course_id=$course";
+       $result = mysql_query($sql, $db);
+       if (!($row      = mysql_fetch_assoc($result))) {
+               echo _AT('no_course_found');
+               return;
+       }
+
+} else {
+       //new course defaults
+       $row['content_packaging']       = 'top';
+       $row['access']                          = 'protected';
+       $row['notify']                          = '';
+       $row['hide']                            = '';
+
+       $row['max_quota']                       = AT_COURSESIZE_DEFAULT;
+       $row['max_file_size']           = AT_FILESIZE_DEFAULT;
+
+       $row['primary_language']        = $_SESSION['lang'];
+       $row['created_date']            = date('Y-m-d H:i:s');
+       $row['rss']                 = 0; // default to off
+       $row['release_date']            = '0';
+       $row['end_date']            = '0';
+}
+/*
+if (($_POST['setvisual'] || $_POST['settext']) && !$_POST['submit']){
+       $anchor =  "#banner";
+} */
+
+?>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF'];  ?>" name="course_form" enctype="multipart/form-data">
+       <input type="hidden" name="form_course" value="true" />
+       <input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $_config['prof_pic_max_file_size']; ?>" />
+       <input type="hidden" name="course" value="<?php echo $course; ?>" />
+       <input type="hidden" name="old_access" value="<?php echo $row['access']; ?>" />
+       <input type="hidden" name="created_date" value="<?php echo $row['created_date']; ?>" />
+       <input type="hidden" name="show_courses" value="<?php echo $_GET['show_courses']; ?>" />
+       <input type="hidden" name="current_cat" value="<?php echo $_GET['current_cat']; ?>" />
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('properties'); ?></legend>
+<?php if ($isadmin): ?>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="inst"><?php echo  _AT('instructor'); ?></label><br />
+                       <?php 
+                       $sql = "SELECT member_id, login FROM ".TABLE_PREFIX."members WHERE status=".AT_STATUS_INSTRUCTOR;
+                       $result = mysql_query($sql, $db);
+                       
+                       if ($instructor_row = mysql_fetch_assoc($result)) {
+                               echo '<select name="instructor" id="inst">';
+                               do {
+                                       if ($instructor_row['member_id'] == $row['member_id']) {
+                                               echo '<option value="'.$instructor_row['member_id'].'" selected="selected">'.$instructor_row['login'].'</option>';
+                                       } else {
+                                               echo '<option value="'.$instructor_row['member_id'].'">'.$instructor_row['login'].'</option>';
+                                       }
+                               } while($instructor_row = mysql_fetch_assoc($result));
+                               echo '</select>';
+                       } else {
+                               echo '<span id="inst">'._AT('none_found').'</span>';
+                       }
+                       ?>
+       </div>
+<?php endif; ?>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php echo _AT('title'); ?></label><br />
+               <input type="text" id="title" name="title" size="40" value="<?php echo htmlspecialchars($row['title']); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="pri_lang"><?php  echo _AT('primary_language'); ?></label><br />
+               <?php $languageManager->printDropdown($row['primary_language'], 'pri_lang', 'pri_lang'); ?>
+       </div>
+
+       <div class="row">
+               <label for="description"><?php echo _AT('description'); ?></label><br />
+               <textarea id="description" cols="45" rows="2" name="description"><?php echo $row['description']; ?></textarea>
+       </div>
+
+       <?php if ($_config['course_dir_name']): ?>
+       <div class="row">
+               <label for="course_dir_name"><?php echo _AT('course_dir_name'); ?></label><br />
+               <input type="text" id="course_dir_name" name="course_dir_name" size="40" value="<?php echo htmlspecialchars($row['course_dir_name']); ?>" />
+       </div>
+       <?php endif; ?>
+
+       <?php $categories = get_categories(); ?>
+       <?php if (is_array($categories)): ?>
+               <div class="row">
+               <label for="cat"><?php echo _AT('category'); ?></label><br />
+                       <select name="category_parent" id="cat">
+                               <option value="0">&nbsp;&nbsp;&nbsp;[&nbsp;&nbsp;<?php echo _AT('cats_uncategorized'); ?>&nbsp;&nbsp;]&nbsp;&nbsp;&nbsp;</option>
+                               <?php select_categories($categories, 0, $row['cat_id'], false); ?>
+
+                       </select>
+               </div>
+       <?php endif; ?>
+
+       <div class="row">
+               <?php  echo _AT('export_content'); ?><br />
+               <?php
+                       switch ($row['content_packaging']) {
+                               case 'none':
+                                               $none = ' checked="checked"';
+                                               break;
+
+                               case 'top':
+                                               $top     = ' checked="checked"';
+                                               break;
+
+                               case 'all':
+                                               $all    = ' checked="checked"';
+                                               break;
+                       }
+                       ?>
+               <label><input type="radio" name="content_packaging" value="none" id="none" <?php echo $none; ?> /><?php echo _AT('content_packaging_none'); ?></label><br />
+               <label><input type="radio" name="content_packaging" value="top" id="ctop"  <?php echo $top; ?> /><?php  echo _AT('content_packaging_top'); ?></label><br />
+               <label><input type="radio" name="content_packaging" value="all" id="all" <?php echo $all; ?> /><?php  echo _AT('content_packaging_all'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('syndicate_announcements'); ?><br />
+               <?php
+                               $rss_no = $rss_yes = '';
+
+                               if ($row['rss']) {
+                                       $rss_yes = ' checked="checked"';
+                               } else {
+                                       $rss_no = ' checked="checked"';
+                               }
+               ?>
+               <label><input type="radio" name="rss" value="1" id="rss_y" <?php echo $rss_yes; ?> /><?php echo _AT('enable_syndicate'); ?></label><br />
+               <label><input type="radio" name="rss" value="0" id="rss_n"  <?php echo $rss_no; ?> /><?php  echo _AT('disable_syndicate'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('access'); ?><br />
+               <?php
+                               switch ($row['access']) {
+                                       case 'public':
+                                                       $pub = ' checked="checked"';
+                                                       $disable = 'disabled="disabled"'; // disable the nofity box
+                                                       break;
+
+                                       case 'protected':
+                                                       $prot    = ' checked="checked"';
+                                                       $disable = 'disabled="disabled"'; // disable the nofity box
+                                                       break;
+
+                                       case 'private':
+                                                       $priv   = ' checked="checked"';
+                                                       break;
+                               }
+
+                               if ($row['notify']) {
+                                       $notify = ' checked="checked"';
+                               }
+
+                               if ($row['hide']) {
+                                       $hide = ' checked="checked"';
+                               }
+               ?>
+               <input type="radio" name="access" value="public" id="pub" onclick="disableNotify();" <?php echo $pub; ?> /><label for="pub"><strong> <?php echo  _AT('public'); ?>: </strong></label><?php echo  _AT('about_public'); ?><br /><br />
+
+               <input type="radio" name="access" value="protected" id="prot" onclick="disableNotify();" <?php echo $prot; ?> /><label for="prot"><strong><?php echo  _AT('protected'); ?>:</strong></label> <?php echo _AT('about_protected'); ?><br /><br />
+
+               <input type="radio" name="access" value="private" id="priv" onclick="enableNotify();" <?php echo $priv; ?> /><label for="priv"><strong><?php echo  _AT('private'); ?>:</strong></label> <?php echo  _AT('about_private'); ?><br />
+               <input type="checkbox" name="notify" id="notify" value="1" <?php
+                       echo $disable;
+                       echo $notify; ?> /><label for="notify"><?php echo  _AT('email_approvals'); ?></label>
+               <br />
+               <input type="checkbox" name="hide" id="hide" value="1" <?php
+               echo $disable;
+               echo $hide; ?> /><label for="hide"><?php echo  _AT('hide_course'); ?></label>.
+       </div>
+
+       <div class="row">
+               <?php echo _AT('release_date'); ?><br />
+               <?php
+                       $rel_no = $rel_yes = '';
+
+                       if (intval($row['release_date'])) {
+                               $rel_yes = ' checked="checked"';
+
+                               $today_day   = substr($row['release_date'], 8, 2);
+                               $today_mon   = substr($row['release_date'], 5, 2);
+                               $today_year  = substr($row['release_date'], 0, 4);
+
+                               $today_hour  = substr($row['release_date'], 11, 2);
+                               $today_min   = substr($row['release_date'], 14, 2);
+                       } else {
+                               $rel_no = ' checked="checked"'; 
+                               $today_year  = date('Y');
+                       }
+
+               ?>
+
+               <input type="radio" name="release_date" value="0" id="release_now" <?php echo $rel_no; ?> /> <label for="release_now"><?php echo _AT('available_immediately'); ?></label><br />
+
+
+               <input type="radio" name="release_date" value="1" id="release_later" <?php echo $rel_yes; ?> /> <label for="release_later"><?php echo _AT('release_on'); ?></label> 
+               <?php
+                       $name = '_release';
+                       require(AT_INCLUDE_PATH.'html/release_date.inc.php');
+               ?>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('end_date'); ?><br />
+               <?php
+                       $end_no = $end_yes = '';
+
+                       if (intval($row['end_date'])) {
+                               $end_yes = ' checked="checked"';
+
+                               $today_day   = substr($row['end_date'], 8, 2);
+                               $today_mon   = substr($row['end_date'], 5, 2);
+                               $today_year  = substr($row['end_date'], 0, 4);
+
+                               $today_hour  = substr($row['end_date'], 11, 2);
+                               $today_min   = substr($row['end_date'], 14, 2);
+                       } else {
+                               $end_no = ' checked="checked"'; 
+                               $today_year  = date('Y')+1;
+                       }
+
+               ?>
+
+               <input type="radio" name="end_date" value="0" id="end_now" <?php echo $end_no; ?> /> <label for="end_now"><?php echo _AT('no_end_date'); ?></label><br />
+
+               <input type="radio" name="end_date" value="1" id="end_later" <?php echo $end_yes; ?> /> <label for="end_later"><?php echo _AT('end_on'); ?></label> 
+               <?php
+                       $name = '_end';
+                       require(AT_INCLUDE_PATH.'html/release_date.inc.php');
+               ?>
+       </div>
+
+       <div class="row">
+               <?php
+                       if (($_POST['setvisual'] && !$_POST['settext']) || $_GET['setvisual']){
+                               echo '<input type="hidden" name="setvisual" value="'.$_POST['setvisual'].'" />';
+                               echo '<input type="submit" name="settext" value="'._AT('switch_text').'" />';
+                       } else {
+                               echo '<input type="submit" name="setvisual" value="'._AT('switch_visual').'" />';
+                       }
+               ?>
+       </div>
+       <div class="row">
+
+               <label for="banner"><?php echo _AT('banner'); ?></label><br />
+               <textarea id="banner" cols="45" rows="15" name="banner"><?php echo $row['banner']; ?></textarea>
+       </div>
+
+<?php if (!$course) : ?>
+       <div class="row">
+               <label for="initial_content"><?php echo _AT('initial_content'); ?></label><br />
+               <select name="initial_content" id="initial_content" size="5">
+                       <option value="0"><?php echo _AT('empty'); ?></option>
+                       <option value="1" selected="selected"><?php echo _AT('create_basic'); ?></option>
+                       <?php 
+                       $Backup =& new Backup($db);
+
+                       if ($isadmin) {
+                               $sql    = "SELECT course_id, title FROM ".TABLE_PREFIX."courses ORDER BY title";
+                       } else {
+                               $sql    = "SELECT course_id, title FROM ".TABLE_PREFIX."courses WHERE member_id=$_SESSION[member_id] ORDER BY title";
+                       }
+
+                       $result = mysql_query($sql, $db);
+
+                       if ($course_row = mysql_fetch_assoc($result)) {
+                               do {
+                                       $Backup->setCourseID($course_row['course_id']);
+                                       $list = $Backup->getAvailableList();
+
+                                       if (!empty($list)) { 
+                                               echo '<optgroup label="'. _AT('restore').': '.$course_row['title'].'">';
+                                               foreach ($list as $list_item) {
+                                                       echo '<option value="'.$list_item['backup_id'].'_'.$list_item['course_id'].'">'.$list_item['file_name'].' - '.get_human_size($list_item['file_size']).'</option>';
+                                               }
+                                               echo '</optgroup>';
+                                       }
+                               } while ($course_row = mysql_fetch_assoc($result));
+                       }
+                       ?>
+                       </select>
+       </div>
+<?php endif; // !$course_id ?>
+
+<?php if ($isadmin) : ?>
+       <div class="row">
+               <?php  echo _AT('course_quota'); ?><br />
+               <?php 
+                       if ($row['max_quota'] == AT_COURSESIZE_UNLIMITED) { 
+                               $c_unlim = ' checked="checked" ';
+                               $c_oth2 = ' disabled="disabled" ';
+                       } elseif ($row['max_quota'] == AT_COURSESIZE_DEFAULT) {
+                               $c_def = ' checked="checked" ';
+                               $c_oth2 = ' disabled="disabled" ';
+                       } else {
+                               $c_oth = ' checked="checked" ';
+                               $c_oth2 = '';
+                       }
+
+                       if ($course > 0) {
+                               $course_size = dirsize(AT_CONTENT_DIR . $course.'/');
+                       } else {
+                               $course_size = 0;
+                       }
+
+                       if ($course) {
+                               echo _AT('current_course_size') .': '.get_human_size($course_size).'<br />'; 
+                       }
+               ?>
+
+               <input type="radio" id="c_default" name="quota" value="<?php echo AT_COURSESIZE_DEFAULT; ?>" onclick="disableOther();" <?php echo $c_def;?> /><label for="c_default"> <?php echo _AT('default') . ' ('.get_human_size($MaxCourseSize).')'; ?></label> <br />
+               <input type="radio" id="c_unlim" name="quota" value="<?php echo AT_COURSESIZE_UNLIMITED; ?>" onclick="disableOther();" <?php echo $c_unlim;?>/><label for="c_unlim"> <?php echo _AT('unlimited'); ?></label> <br />
+               <input type="radio" id="c_other" name="quota" value="2" onclick="enableOther();" <?php echo $c_oth;?>/><label for="c_other"> <?php echo _AT('other'); ?> </label> - 
+               <input type="text" id="quota_entered" name="quota_entered" <?php echo $c_oth2?> value="<?php if ($row['max_quota']!=AT_COURSESIZE_UNLIMITED && $row['max_quota']!=AT_COURSESIZE_DEFAULT) { echo bytes_to_megabytes($row['max_quota']); } ?>" size="4" /> <?php echo _AT('mb'); ?>
+       </div>
+
+       <div class="row">
+               <?php  echo _AT('max_file_size'); ?><br />
+               <?php 
+                       $max_allowed = megabytes_to_bytes(substr(ini_get('upload_max_filesize'), 0, -1));
+
+                       if ($row['max_file_size'] == AT_FILESIZE_DEFAULT) { 
+                               $f_def = ' checked="checked" ';
+                               $f_oth2 = ' disabled="disabled" ';
+                       } elseif ($row['max_file_size'] == AT_FILESIZE_SYSTEM_MAX) {
+                               $f_max = ' checked="checked" ';
+                               $f_oth2 = ' disabled="disabled" ';
+                       } else {
+                               $f_oth = ' checked="checked" ';
+                               $f_oth2 = '';
+                       }
+               ?>
+               <input type="radio" id="f_default" name="filesize" value="<?php echo AT_FILESIZE_DEFAULT; ?>" onclick="disableOther2();" <?php echo $f_def;?> /><label for="f_default"> <?php echo _AT('default') . ' ('.get_human_size($MaxFileSize).')'; ?></label> <br />
+               <input type="radio" id="f_maxallowed" name="filesize" value="<?php echo AT_FILESIZE_SYSTEM_MAX; ?>" onclick="disableOther2();" <?php echo $f_max;?>/><label for="f_maxallowed"> <?php echo _AT('max_file_size_system') . ' ('.get_human_size($max_allowed).')'; ?></label> <br />
+               <input type="radio" id="f_other" name="filesize" value="2" onclick="enableOther2();" <?php echo $f_oth;?>/><label for="f_other"> <?php echo _AT('other'); ?> </label> - 
+               <input type="text" id="filesize_entered" name="filesize_entered" <?php echo $f_oth2?> value="<?php if ($row['max_file_size']!=AT_FILESIZE_DEFAULT && $row['max_file_size']!=AT_FILESIZE_SYSTEM_MAX) { echo bytes_to_megabytes($row['max_file_size']); } ?>" size="4" /> <?php echo _AT('mb'); ?>
+       </div>
+
+<?php else: ?>
+       <input type="hidden" name="quota" value="<?php echo $row['max_quota']; ?>" />
+       <input type="hidden" name="filesize" value="<?php echo $row['max_file_size']; ?>" />
+       <input type="hidden" name="tracking" value="<?php echo $row['tracking']; ?>" />
+<?php endif; ?>
+
+       <div class="row">
+               <label for="copyright"><?php echo _AT('course_copyright'); ?></label><br />
+               <textarea name="copyright" rows="2" cols="65" id="copyright"><?php echo $row['copyright']; ?></textarea>
+       </div>
+       <div class="row">
+               <?php 
+            if ($row['icon'] != ''): 
+                $path = AT_CONTENT_DIR.$row['course_id']."/custom_icons/";
+                if (file_exists($path.$row['icon'])) {
+                    if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+                        $_base_href = 'get_course_icon.php/?id='.$row['course_id'];
+                    } else {
+                        $_base_href = 'content/' . $row['course_id'] . '/';
+                    }
+                } else {
+                    $_base_href = "images/courses/";
+                                            //$_base_href = 'get_course_icon.php/?id='.$row['course_id'];
+                }
+
+            $force_get = (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) ? true : false;
+            echo "<input type='hidden' name='boolForce' id='boolForce' value='$force_get' />";
+        
+       //include(AT_INCLUDE_PATH.'html/course_icon.inc.php');
+        
+        
+        ?>
+               <img id="i0" src="<?php echo $_base_href.$row['icon']; ?>" alt="<?php echo $row['icon']; ?>" border="1" height="79" width="79"  style="float: left; margin: 2px;" />
+
+               <?php else: ?>
+                       <img id="i0" src="images/clr.gif" alt="" style="float: left; margin: 2px;" border="1" height="79" width="79"  />
+                       <input type='hidden' name='boolForce' id='boolForce' value='' />
+               <?php endif; ?>
+               <div style="width:40%; float:left;">
+               <label for="icons"><?php echo _AT('icon'); ?></label><br />
+               <select name="icon" id="icons" onchange="SelectImg()">
+                       <option value=""><?php echo _AT('no_icon'); ?></option>
+            <?php // ------------- custom course icons
+                $path = AT_CONTENT_DIR.$row['course_id']."/custom_icons/";
+                $boolCustom = false;
+                $optCount = 0;
+
+                if (is_dir($path)) {
+                    $boolCustom = true;  // true if custom icons are uploaded, otherwise false
+                    
+                    /*$files = scandir($path);  //SCANDIR STOPS ATUTOR WHEN RUN AS INSTRUCTOR, BUT NOT AS ADMIN. WHY? -Gorzan */
+                    
+                    /* PHP 4 REPLACEMENT FOR SCANDIR */
+                                       $dh  = opendir($path);
+                                       while (false !== ($filename = readdir($dh))) {
+                                               $files[] = $filename;
+                                       }
+
+                                       /*END PHP 4 REPLACEMENT FOR SCANDIR*/
+                    echo "<optgroup label='Custom Icons'>";
+                    foreach($files as $val) {
+                                               $file_ext = substr(strtolower($val), -3);
+                        if ($file_ext == "jpg" || $file_ext == "png" || $file_ext == "gif") {
+                            $optCount++;
+                            echo "<option value='".$val."'";
+                            if ($val == $row['icon']) {
+                                echo 'selected="selected"';
+                            }
+                            echo ">".$val."</option>";
+                        }
+                    }
+                    echo "</optgroup>";
+                }
+                
+            ?>
+                       <?php // ------------- other icons
+
+                               $course_imgs = array();
+                               if ($dir = opendir('../images/courses/')) {
+                                       while (false !== ($file = readdir($dir)) ) {
+                                               if( ($file == '.') || ($file == '..')) { 
+                                                       continue;
+                                               }
+                                               $course_imgs[] = $file;
+                                       }               
+                                       closedir($dir); 
+                               }
+                               sort($course_imgs);
+                if ($boolCustom == true) {
+                    echo "<optgroup label='Other Icons'>";
+                }
+                               foreach ($course_imgs as $file) {
+                                       echo '<option value="' . $file . '" ';
+                                       if ($file == $row['icon']) { 
+                                               echo 'selected="selected"'; 
+                                       }
+                                       echo ' >' . $file . '</option>';        
+                               }
+                if ($boolCustom == true) {
+                    echo "</optgroup>";
+                }
+                       ?>
+               </select><?php echo "&nbsp;&nbsp;&nbsp; "._AT('or'); ?>
+       </div>
+            <!-- div class="row" style="float:right;width:40%;">
+            <?php echo _AT('upload_icon'); ?><br />
+                <input type="file" name="customicon" id="customicon" value="<?php echo $_POST['customicon']; ?>"/><br />
+                <small><?php echo _AT('upload_icon_text'); ?></small>
+            </div -->
+
+        <?php  require_once(AT_INCLUDE_PATH.'html/course_icon.inc.php'); ?>
+
+        <br style="clear: left;" />
+
+       </div>
+
+    <div style="clear: both;"></div>
+
+    
+
+       <div class="buttons">
+               <?php
+            echo "<input type='hidden' name='custOptCount' id='custOptCount' value='".$optCount."' />";
+            echo "<input type='hidden' name='courseId' id='courseId' value='".$row['course_id']."' />";
+               ?>
+
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" /> 
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel');?>" />
+       </div>
+    </fieldset>
+</div>
+
+</form>
+<?php
+
+if ($_POST['customicon']) {
+    echo "<script language='javascript' type='text/javascript'>document.getElementById('uploadform').focus();</script>";
+}
+?>
+
+<script language="javascript" type="text/javascript">
+<!--
+function enableNotify() {
+       document.course_form.notify.disabled = false;
+       document.course_form.hide.disabled = false;
+}
+
+function disableNotify() {
+       document.course_form.notify.disabled = true;
+       document.course_form.hide.disabled = true;
+}
+
+function enableOther()         { document.course_form.quota_entered.disabled = false; }
+function disableOther()                { document.course_form.quota_entered.disabled = true; }
+function enableOther2()                { document.course_form.filesize_entered.disabled = false; }
+function disableOther2()       { document.course_form.filesize_entered.disabled = true; }
+
+function enableRelease() { 
+       document.course_form.day_release.disabled = false; 
+       document.course_form.month_release.disabled = false; 
+       document.course_form.year_release.disabled = false; 
+       document.course_form.hour_release.disabled = false; 
+       document.course_form.min_release.disabled = false; 
+}
+function disableRelease() { 
+       document.course_form.day_release.disabled = true; 
+       document.course_form.month_release.disabled = true; 
+       document.course_form.year_release.disabled = true; 
+       document.course_form.hour_release.disabled = true; 
+       document.course_form.min_release.disabled = true; 
+}
+
+function SelectImg() {
+    // UPDATED by Martin Turlej - for custom course icon
+
+    var boolForce = document.getElementById('boolForce').value;
+       if (document.course_form.icon.options[document.course_form.icon.selectedIndex].value == "") {
+               document.getElementById('i0').src = "images/clr.gif";
+               document.getElementById('i0').alt = "";
+       } else {
+        var iconIndx = document.course_form.icon.selectedIndex;
+        var custIndx = document.getElementById('custOptCount').value;
+        var courseId = document.getElementById('courseId').value;
+
+        // if icon is part of custom icons choose corresponding directory
+        if (iconIndx <= custIndx && boolForce != '') {                 
+            var dir = (boolForce == 1) ? "get_course_icon.php/?id="+courseId : "/content/"+courseId+"/custom_icons/";
+        } else {
+            var dir = "images/courses/";
+        }
+
+               document.getElementById('i0').src = dir + document.course_form.icon.options[iconIndx].value;
+               document.getElementById('i0').alt = document.course_form.icon.options[iconIndx].value;
+       }
+}
+
+function toggleFrm(id) {
+    if (document.getElementById(id).style.display == "none") {
+               //show
+               document.getElementById(id).style.display='';   
+
+               if (id == "c_folder") {
+                       document.form0.new_folder_name.focus();
+               } else if (id == "upload") {
+                       document.form0.file.focus();
+               }
+
+       } else {
+               //hide
+               document.getElementById(id).style.display='none';
+       }
+}
+// -->
+</script>
\ No newline at end of file
diff --git a/include/html/dropdowns/glossary.inc.php b/include/html/dropdowns/glossary.inc.php
new file mode 100644 (file)
index 0000000..e95e0b2
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: glossary.inc.php 5252 2005-08-09 16:39:26Z heidi $
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+global $contentManager;
+global $_base_path;
+global $savant;
+global $glossary;
+global $strlen, $substr, $strtolower;
+
+ob_start(); 
+$result = false;
+if (isset($_GET['cid'])) {
+       $result = $contentManager->getContentPage($_GET['cid']);
+}
+if ($result && ($row = mysql_fetch_array($result))) {
+       $matches = find_terms($row['text']);
+       $matches = $matches[0];
+       $words = str_replace(array('[?]', '[/?]'), '', $matches);
+       $words = str_replace("\n", ' ', $words);
+
+       //case-insensitive, unique array of words
+       for($i=0;$i<count($words);$i++) {
+               $words[$i] = $strtolower($words[$i]);
+       }
+       $words = array_unique($words);
+
+       if (count($words) > 0) {
+               $count = 0;
+
+               $glossary_key_lower = array_change_key_case($glossary);
+
+               foreach ($words as $k => $v) {
+                       $original_v = $v;
+                       $v = $strtolower(urlencode($v));        //array_change_key_case change everything to lowercase, including encoding. 
+
+                       if (isset($glossary_key_lower[$v]) && $glossary_key_lower[$v] != '') {
+
+                               $v_formatted = urldecode(array_search($glossary_key_lower[$v], $glossary));
+
+                               $def = AT_print($glossary_key_lower[$v], 'glossary.definition');
+
+                               $count++;
+                               //echo '&#176; <a href="'.$_base_path.'glossary/index.php?g_cid='.$_SESSION['s_cid'].SEP.'w='.$v.'" title="'.$original_v.'">'.$v_formatted.'</a>';
+
+                               echo '<a href="'.$_base_path.'glossary/index.php?g_cid='.$_SESSION['s_cid'].SEP.'w='.urlencode($original_v).'#term" onmouseover="return overlib(\''.$def.'\', CAPTION, \''.addslashes($v_formatted).'\', AUTOSTATUS);" onmouseout="return nd();" onfocus="return overlib(\''.$def.'\', CAPTION, \''.addslashes($v_formatted).'\', AUTOSTATUS);" onblur="return nd();">';
+                               if ($strlen($original_v) > 26 ) {
+                                       $v_formatted = $substr($v_formatted, 0, 26-4).'...';
+                               }
+                               echo AT_print($v_formatted, 'glossary.word').'</a>';
+                               echo '<br />';
+                       }
+               }
+
+               if ($count == 0) {
+                       /* there are defn's, but they're not defined in the glossary */
+                       echo '<em>'._AT('no_terms_found').'</em>';
+               }
+       } else {
+               /* there are no glossary terms on this page */
+               echo '<em>'._AT('no_terms_found').'</em>';
+       }
+} else {
+       /* there are no glossary terms in the system for this course or error */
+       echo '<em>'._AT('na').'</em>';
+}
+
+$savant->assign('dropdown_contents', ob_get_contents());
+ob_end_clean();
+
+$savant->assign('title', _AT('glossary'));
+$savant->display('include/box.tmpl.php');
+?>
diff --git a/include/html/dropdowns/menu_menu.inc.php b/include/html/dropdowns/menu_menu.inc.php
new file mode 100644 (file)
index 0000000..505f326
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+global $_base_path;
+global $savant;
+global $contentManager;
+
+ob_start();
+
+echo '<div style="white-space:nowrap;">';
+
+echo '<a href="'.$_base_path.'index.php">'._AT('home').'</a><br />';
+
+/* @See classes/ContentManager.class.php       */
+$contentManager->printMainMenu();
+
+echo '</div>';
+
+$savant->assign('dropdown_contents', ob_get_contents());
+ob_end_clean();
+$savant->assign('title', _AT('content_navigation'));
+$savant->display('include/box.tmpl.php');
+?>
\ No newline at end of file
diff --git a/include/html/dropdowns/poll.inc.php b/include/html/dropdowns/poll.inc.php
new file mode 100644 (file)
index 0000000..262db33
--- /dev/null
@@ -0,0 +1,101 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+global $_base_path, $include_all, $include_one;
+global $savant;
+global $db;
+
+if (isset($_POST['poll_submit'], $_POST['choice'])) {
+       $poll_id = intval($_POST['poll_id']);
+
+       $sql = "INSERT INTO ".TABLE_PREFIX."polls_members VALUES($poll_id, $_SESSION[member_id])";
+       if ($result = mysql_query($sql, $db)) {
+               $n = intval($_POST['choice']);
+
+               $sql = "UPDATE ".TABLE_PREFIX."polls SET count$n=count$n+1, total=total+1 WHERE poll_id=$poll_id AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $db);
+       }
+}
+
+ob_start(); 
+
+if (!isset($include_all, $include_one)) {
+       $include_one = ' checked="checked"';
+}
+
+$sql = "SELECT * FROM ".TABLE_PREFIX."polls WHERE course_id=$_SESSION[course_id] ORDER BY created_date DESC LIMIT 1";
+$result = mysql_query($sql, $db);
+
+if ($row = mysql_fetch_assoc($result)) {
+       echo '<table width="100%">';
+
+       if (!authenticate(AT_PRIV_POLLS, AT_PRIV_RETURN)) {
+               $sql = "SELECT * FROM ".TABLE_PREFIX."polls_members WHERE poll_id=$row[poll_id] AND member_id=$_SESSION[member_id]";
+               $result = mysql_query($sql, $db);
+       }
+       if (authenticate(AT_PRIV_POLLS, AT_PRIV_RETURN) || ($my_row = mysql_fetch_assoc($result))) {
+               echo '<tr>';
+               echo '<td valign="top" class="dropdown-heading" align="left"><strong>' . AT_print($row['question'], 'polls.question') . '</strong>';
+               echo '</td></tr>';
+
+               // we already voted
+               for ($i=1; $i<= AT_NUM_POLL_CHOICES; $i++) {
+                       if ($row['choice' . $i]) {
+                               if ($row['total']) {
+                                       $width = round($row['count' . $i] / $row['total'] * 110);
+                               } else {
+                                       $width = 0;
+                               }
+
+                               echo '<tr>';
+                               echo '<td valign="top" class="dropdown"  align="left">';
+                               echo '<small>' . AT_print($row['choice' . $i], 'polls.choice') . '</small><br />';
+                               echo '<img src="'.$_base_path . 'images/blue.gif" height="5" width="'.$width.'" alt="" /> '.$row['count' . $i];
+                               echo '</td></tr>';
+                       }
+               }
+       } else {
+               // show the form to vote
+               echo '<tr>';
+               echo '<td valign="top" class="dropdown" align="left"><strong>' . AT_print($row['question'], 'polls.question') . '</strong>';
+               echo '<form method="post" action="'.htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES).'"><input type="hidden" name="poll_id" value="'.$row['poll_id'].'" />';
+               echo '<table width="100%" border="0" cellspacing="0" cellpadding="0" summary="">';
+               for ($i=1; $i<= AT_NUM_POLL_CHOICES; $i++) {
+                       if ($row['choice' . $i]) {
+                               echo '<tr>';
+                               echo '<td valign="top" align="left">';
+                               echo '<small><input type="radio" name="choice" value="'.$i.'" id="c'.$i.'" /><label for="c'.$i.'">' . AT_print($row['choice' . $i], 'polls.choice') . '</label></small></td></tr>';
+                       }
+               }
+
+               echo '<tr>';
+               echo '<td valign="top" align="center"><input type="submit" name="poll_submit" value="'._AT('submit').'" class="button" />';
+               echo '<br /><small>'._AT('vote_to_see_results').'</small>';
+               echo '</td></tr>';
+
+               echo '</table></form></td></tr>';
+       }
+       echo '</table>';
+
+} else {
+       echo '<em>'._AT('none_found').'</em><br />';
+}
+
+$savant->assign('dropdown_contents', ob_get_contents());
+ob_end_clean();
+
+$savant->assign('title', _AT('polls'));
+$savant->display('include/box.tmpl.php');
+?>
\ No newline at end of file
diff --git a/include/html/dropdowns/posts.inc.php b/include/html/dropdowns/posts.inc.php
new file mode 100644 (file)
index 0000000..7a284ed
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: posts.inc.php 4812 2005-06-07 19:52:15Z joel $
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+global $db;
+global $_base_path;
+global $savant;
+
+//Number of posts to display
+$post_limit = 5;
+       
+ob_start();
+
+$forum_list = get_group_concat('forums_courses', 'forum_id', "course_id={$_SESSION['course_id']}");
+if ($forum_list != 0) {
+       $sql = "SELECT subject, post_id, forum_id, member_id FROM ".TABLE_PREFIX."forums_threads WHERE parent_id=0 AND forum_id IN ($forum_list) ORDER BY last_comment DESC LIMIT $post_limit";
+       $result = mysql_query($sql, $db);
+
+       if (mysql_num_rows($result) > 0) {
+               while ($row = mysql_fetch_assoc($result)) {
+                       echo '&#176; <a href="' . $_base_path.url_rewrite('forum/view.php?fid=' . $row['forum_id'] . SEP . 'pid=' . $row['post_id']) . '" title="' . $row['subject'] . ': ' . htmlspecialchars(get_display_name($row['member_id'])) . '">' . AT_print(validate_length($row['subject'], 20, VALIDATE_LENGTH_FOR_DISPLAY), 'forums_threads.subject') . '</a><br />';
+               }
+       } else {
+               echo '<em>'._AT('none_found').'</em>';
+       }
+} else {
+       echo '<em>'._AT('none_found').'</em>';
+}
+
+$savant->assign('dropdown_contents', ob_get_contents());
+ob_end_clean();
+
+$savant->assign('title', _AT('forum_posts'));
+$savant->display('include/box.tmpl.php');
+?>
\ No newline at end of file
diff --git a/include/html/dropdowns/related_topics.inc.php b/include/html/dropdowns/related_topics.inc.php
new file mode 100644 (file)
index 0000000..cc0cce1
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+global $contentManager;
+global $_base_path, $path;
+global $savant;
+
+ob_start();
+$related = $contentManager->getRelatedContent($_SESSION['s_cid']);
+
+if (count($related) == 0) {
+       echo '<em>'._AT('none_found').'</em>';
+} else {
+       for ($i=0; $i < count($related); $i++) {
+               echo '&#176; <a href="'.$_base_path.'content.php?cid='.$related[$i].'">';
+               echo $contentManager->_menu_info[$related[$i]]['title'];
+               echo '</a>';
+               echo '<br />';
+       }
+}
+$_my_uri = isset($_my_uri) ? $_my_uri : '';
+
+$savant->assign('dropdown_contents', ob_get_contents());
+ob_end_clean();
+$savant->assign('close_url', htmlspecialchars($_my_uri).'disable=PREF_RELATED'.SEP.'menu_jump=3');
+$savant->assign('dropdown_close', _AT('close_related_topics'));
+
+$savant->assign('title', _AT('related_topics'));
+$savant->display('include/box.tmpl.php');
+?>
\ No newline at end of file
diff --git a/include/html/dropdowns/search.inc.php b/include/html/dropdowns/search.inc.php
new file mode 100644 (file)
index 0000000..270c31b
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+global $_base_path, $include_all, $include_one, $stripslashes;
+global $savant;
+
+ob_start(); 
+
+if (!isset($include_all, $include_one)) {
+       $include_one = ' checked="checked"';
+}
+if (!isset($_GET['words'])) {
+       $_GET['words'] = '';
+} else {
+       $_GET['words'] = stripslashes(htmlspecialchars($_GET['words']));
+}
+?>
+
+<form action="<?php echo $_base_path; ?>search.php#search_results" method="get" name="searchform">
+<input type="hidden" name="search" value="1" />
+<input type="hidden" name="find_in" value="this" />
+<input type="hidden" name="display_as" value="pages" />
+<label for="words" style="display:none;"><?php echo _AT('search'); ?></label>
+<input type="text" name="words" class="formfield" size="20" id="words" value="<?php echo $_GET['words']; ?>" /><br />
+<fieldset>
+<legend style="display:none;"><?php echo _AT('search'); ?></legend>
+<small>
+       <?php echo _AT('search_match'); ?>:<br />
+       <input type="radio" name="include" value="all" id="all2"<?php echo $include_all; ?> /><label for="all2"><?php echo _AT('search_all_words'); ?></label><br />
+
+       <input type="radio" name="include" value="one" id="one2"<?php echo $include_one; ?> /><label for="one2"><?php echo _AT('search_any_word'); ?></label><br />
+</small>
+</fieldset>
+<input type="submit" name="submit" value="<?php echo _AT('search'); ?>" class="button" />
+</form>
+
+<?php
+$savant->assign('dropdown_contents', ob_get_contents());
+ob_end_clean();
+
+$savant->assign('title', _AT('search'));
+
+$savant->display('include/box.tmpl.php');
+?>
\ No newline at end of file
diff --git a/include/html/dropdowns/users_online.inc.php b/include/html/dropdowns/users_online.inc.php
new file mode 100644 (file)
index 0000000..e085ea5
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+global $db;
+global $_base_path;
+global $savant;
+global $system_courses;
+
+ob_start(); 
+
+$sql   = "SELECT * FROM ".TABLE_PREFIX."users_online WHERE course_id=$_SESSION[course_id] AND expiry>".time()." ORDER BY login";
+$result        = mysql_query($sql, $db);
+if ($row = mysql_fetch_assoc($result)) {
+       echo '<ul style="padding: 0px; list-style: none;">';
+       do {
+               $type = 'class="user"';
+               if ($system_courses[$_SESSION['course_id']]['member_id'] == $row['member_id']) {
+                       $type = 'class="user instructor" title="'._AT('instructor').'"';
+               }
+               echo '<li style="padding: 3px 0px;"><a href="'.$_base_path.'profile.php?id='.$row['member_id'].'" '.$type.'>'.AT_print($row['login'], 'members.login').'</a></li>';
+       } while ($row = mysql_fetch_assoc($result));
+       echo '</ul>';
+} else {
+       echo '<em>'._AT('none_found').'</em><br />';
+}
+
+echo '<em>'._AT('guests_not_listed').'</em>';
+
+$savant->assign('dropdown_contents', ob_get_contents());
+ob_end_clean();
+$savant->assign('title', _AT('users_online'));
+$savant->display('include/box.tmpl.php');
+?>
\ No newline at end of file
diff --git a/include/html/editor_tabs/accessibility.inc.php b/include/html/editor_tabs/accessibility.inc.php
new file mode 100644 (file)
index 0000000..67d2fe3
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+//make decisions
+if ($_POST['desc_submit']) {
+       //get list of decisions 
+       $desc_query = '';
+       if (is_array($_POST['d'])) {
+               for($i=0; $i<count($_POST['d']); $i++) {
+                       $desc_query .= '&'.$i.'='.$_POST['d'][$i];
+               }
+
+               $checker_url = AT_ACHECKER_URL. 'decisions;'
+                                       .'jsessionid='.$_POST['sessionid']
+                                       .'?file='.urlencode($_POST['pg_url'])
+                                       .'&output=chunk'
+                                       .'&name='.urlencode(get_display_name($_SESSION['member_id']))
+                                       .'&email='.urlencode(AT_BASE_HREF)
+                                       .$desc_query;
+
+               if (@file_get_contents($checker_url) === false) {
+                       $msg->addInfo('DECISION_NOT_SAVED');
+               }
+
+       } else {
+               $msg->addInfo('DECISION_NOT_SAVED');
+       }
+} else if (isset($_POST['reverse'])) {
+       list($achecker_id, $achecker_element, $achecker_identifier) = explode('_', key($_POST['reverse']), 3);
+
+       $reverse_url = AT_ACHECKER_URL . 'decisions;'
+                                       .'jsessionid='.$_POST['sessionid']
+                                       .'?file='.urlencode($_POST['pg_url'])
+                                       .'&lang=eng'
+                                       .'&reverse=true'
+                                       .$achecker_element
+                                       .$achecker_identifier
+                                       .'&checkid='.$achecker_id;
+
+
+
+       if (@file_get_contents($reverse_url) === false) {
+               $msg->addInfo('DECISION_NOT_REVERSED');
+       } else {
+               $msg->addInfo('DECISION_REVERSED');
+       }
+}
+
+?>
+       <div class="row">
+               <?php                                   
+                       echo '<input type="hidden" name="body_text" value="'.htmlspecialchars(stripslashes($_POST['body_text'])).'" />';
+
+                       if (!$cid) {
+                               $msg->printInfos('SAVE_CONTENT');
+
+                               echo '</div>';
+
+                               return;
+                       }
+
+               $msg->printInfos();
+               if ($_POST['body_text'] != '') {
+                       //save temp file
+                       $_POST['content_path'] = $content_row['content_path'];
+                       write_temp_file();
+
+                       $pg_url = AT_BASE_HREF.'get_acheck.php/'.$_POST['cid'] . '.html';
+
+                       $checker_url = AT_ACHECKER_URL.'Checkacc?file='.urlencode($pg_url)
+                                                       . '&guide=wcag-2-0-aa&output=chunk&line=5'
+                                                       . '&vurl=' . urlencode(AT_BASE_HREF . 'editor/view_item.php');
+
+                       $report = @file_get_contents($checker_url);
+
+                       if ($report == 1) {
+                               $msg->printErrors('INVALID_URL');
+                       } else if ($report === false) {
+                               $msg->printInfos('SERVICE_UNAVAILABLE');
+                       } else {
+                               echo '<input type="hidden" name="pg_url" value="'.$pg_url.'" />';
+                               echo $report;   
+
+                               echo '<p>'._AT('access_credit').'</p>';
+                       }
+                       //delete file
+                       @unlink(AT_CONTENT_DIR . $_POST['cid'] . '.html');
+               
+               } else {
+                       $msg->printInfos('NO_PAGE_CONTENT');
+               } 
+
+       ?>
+       </div>
\ No newline at end of file
diff --git a/include/html/editor_tabs/content_code_picker.inc.php b/include/html/editor_tabs/content_code_picker.inc.php
new file mode 100644 (file)
index 0000000..40c945f
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+?>
+<?php echo _AT('click_code'); ?>
+<table border="0" cellspacing="0" cellpadding="0" width="100%">
+<?php
+       if (isset($current_tab)) {
+                       echo '<tr><td align="right"><small><strong>'._AT('codes').': </strong></small></td><td><small>';
+                       echo '<a href="javascript:smilie(\'[?] [/?]\')" title="[?][/?]">',_AT('add_term'), '</a> ';
+                       echo '<a href="javascript:smilie(\'[code] [/code]\')" title="[code][/code]">'._AT('add_code').'</a>';
+                       echo '</small></td></tr>';
+       } ?>
+<tr>
+       <td align="right"><small><b><?php echo _AT('colors'); ?>:</b></small></td>
+       <td><table border="0" cellspacing="2" cellpadding="0" summary="">
+       <tr>
+               <td bgcolor="blue"><a href="javascript:smilie('[blue]', '[/blue]')" title="[blue] [/blue]"><img src="<?php echo $_base_path; ?>images/clr.gif" alt="<?php echo _AT('blue'); ?>" height="15" width="15" border="0" /></a></td>
+               <td bgcolor="red"><a href="javascript:smilie('[red]', '[/red]')" title="[red] [/red]"><img src="<?php echo $_base_path; ?>images/clr.gif" alt="<?php echo _AT('red'); ?>" height="15" width="15" border="0" /></a></td>
+               <td bgcolor="green"><a href="javascript:smilie('[green]', '[/green]')" title="[green] [/green]"><img src="<?php echo $_base_path; ?>images/clr.gif" alt="<?php echo _AT('green'); ?>" height="15" width="15" border="0" /></a></td>
+               <td bgcolor="orange"><a href="javascript:smilie('[orange]', '[/orange]')" title="[orange] [/orange]"><img src="<?php echo $_base_path; ?>images/clr.gif" alt="<?php echo _AT('orange'); ?>" height="15" width="15" border="0" /></a></td>
+               <td bgcolor="purple"><a href="javascript:smilie('[purple]', '[/purple]')" title="[purple] [/purple]"><img src="<?php echo $_base_path; ?>images/clr.gif" alt="<?php echo _AT('purple'); ?>" height="15" width="15" border="0" /></a></td>
+               <td bgcolor="gray"><a href="javascript:smilie('[gray]', '[/gray]')" title="[gray] [/gray]"><img src="<?php echo $_base_path; ?>images/clr.gif" alt="<?php echo _AT('gray'); ?>" height="15" width="15" border="0" /></a></td>
+       </tr>
+       </table></td>
+</tr>
+</table>
+
+<?php if ($_POST['setvisual'] && !$_POST['settext']): ?>
+       <script type="text/javascript">
+       //<!--
+       function smilie(thesmilie, extra) {
+               if (!extra) {
+                       tinyMCE.execCommand("mceInsertContent", false, thesmilie);
+               } else {
+                       tinyMCE.execCommand("mceInsertContent", false, thesmilie + extra);
+               }
+       }
+       //--></script>
+<?php else: ?>
+       <script type="text/javascript">
+       //<!--
+       function smilie(thesmilie, extra) {
+               if (!extra) {
+                       document.form.body_text.value += thesmilie+" ";
+                       document.form.body_text.focus();
+               } else {
+                       document.form.body_text.value += thesmilie+extra+" ";
+                       document.form.body_text.focus();
+               }
+
+       }
+       //--></script>
+<?php endif; ?>
\ No newline at end of file
diff --git a/include/html/editor_tabs/edit.inc.php b/include/html/editor_tabs/edit.inc.php
new file mode 100644 (file)
index 0000000..dc6187c
--- /dev/null
@@ -0,0 +1,166 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+?>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="ctitle"><?php echo _AT('title');  ?></label><br />
+               <input type="text" name="title" size="70" class="formfield" value="<?php echo ContentManager::cleanOutput($_POST['title']); ?>" id="ctitle" />
+       </div>
+       
+       <?php
+               if ($content_row['content_path']) {
+                       echo '  <div class="row">'._AT('packaged_in').'<br />'.$content_row['content_path'].'</div>';
+               }
+       ?>
+
+       <div class="row">
+               <label for="head"><?php echo _AT('customized_head');  ?></label>
+               <input type="button" name="edithead" value="<?php echo _AT('edit'); ?>" onClick="switch_head_editor()" /><br />
+               <small>&middot; <?php echo _AT('customized_head_note'); ?></small>
+       </div>
+
+<?php 
+if (trim($_POST['head']) == '<br />') {
+       $_POST['head'] = '';
+}
+if ($do_check) {
+       $_POST['head'] = $stripslashes($_POST['head']);
+}
+?>
+
+       <div class="row">
+               <div id="headDiv" style="display:none">
+                       <input type="checkbox" name="use_customized_head" value="1" <?php if ($_POST['use_customized_head']) { echo 'checked="checked"'; } ?> />
+                       <label for="head"><?php echo _AT('use_customized_head'); ?></label><br />
+                       <textarea name="head" id="head" cols="" rows="10"><?php echo htmlspecialchars($_POST['head']); ?></textarea>    
+               </div>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('formatting'); ?><br />
+
+               <input type="radio" name="formatting" value="0" id="text" <?php if ($_POST['formatting'] == 0) { echo 'checked="checked"'; } ?> onclick="javascript: document.form.setvisualbutton.disabled=true;" />
+               <label for="text"><?php echo _AT('plain_text'); ?></label>
+
+               , <input type="radio" name="formatting" value="1" id="html" <?php if ($_POST['formatting'] == 1 || $_POST['setvisual']) { echo 'checked="checked"'; } ?> onclick="javascript: document.form.setvisualbutton.disabled=false;"/>
+               <label for="html"><?php echo _AT('html'); ?></label>
+
+               <input type="hidden" name="displayhead" value="<?php if ($_POST['displayhead']==1 || $_REQUEST['displayhead']==1 || $_GET['displayhead']==1) echo '1'; else echo '0'; ?>" />
+               <input type="hidden" name="setvisual" value="<?php if ($_POST['setvisual']==1 || $_REQUEST['setvisual']==1 || $_GET['setvisual']==1) echo '1'; else echo '0'; ?>" />
+               <input type="hidden" name="settext" value="<?php if ($_POST['settext']==1 || $_REQUEST['settext']==1 || $_GET['settext']==1) echo '1'; else echo '0'; ?>" />
+               <input type="button" name="setvisualbutton" value="<?php echo _AT('switch_visual'); ?>" onClick="switch_body_editor()" />
+
+               <script type="text/javascript" language="javascript">
+               //<!--
+                       document.write(" <a href=\"#\" onclick=\"window.open('<?php echo AT_BASE_HREF; ?>tools/filemanager/index.php?framed=1<?php echo SEP; ?>popup=1<?php echo SEP; ?>cp=<?php echo $content_row['content_path']; ?>','newWin1','menubar=0,scrollbars=1,resizable=1,width=640,height=490'); return false;\"><?php echo _AT('open_file_manager'); ?> </a>");
+               //-->
+               </script>
+               <noscript>
+                       <a href="<?php echo AT_BASE_HREF; ?>tools/filemanager/index.php?framed=1"><?php echo _AT('open_file_manager'); ?></a>
+               </noscript>                     
+       </div>
+       <div class="row">
+               <label for="body_text"><?php echo _AT('body');  ?></label><br />
+
+<?php 
+
+// kludge #1548
+if (trim($_POST['body_text']) == '<br />') {
+       $_POST['body_text'] = '';
+}
+if ($do_check) {
+       $_POST['body_text'] = $stripslashes($_POST['body_text']);
+}
+
+?>
+               <textarea name="body_text" id="body_text" cols="" rows="20"><?php echo htmlspecialchars($_POST['body_text']); ?></textarea>     
+       </div>
+       
+       <div class="row">
+               <?php require(AT_INCLUDE_PATH.'html/editor_tabs/content_code_picker.inc.php'); ?>
+       </div>
+
+       <div class="row">
+               <strong><?php echo _AT('or'); ?></strong> <?php echo _AT('paste_file'); ?><br />
+               <input type="file" name="uploadedfile" class="formfield" size="20" /> <input type="submit" name="submit_file" value="<?php echo _AT('upload'); ?>" /><br />
+               <small class="spacer">&middot;<?php echo _AT('html_only'); ?><br />
+               &middot;<?php echo _AT('edit_after_upload'); ?></small>
+       </div>
+
+       <script type="text/javascript" language="javascript">
+       //<!--
+       function on_load()
+       {
+               if (document.getElementById("text").checked)
+                       document.form.setvisualbutton.disabled = true;
+                       
+               if (document.form.displayhead.value==1)
+               {
+                       document.getElementById("headDiv").style.display = '';
+                       document.form.edithead.value = "<?php echo _AT('hide'); ?>"
+               }
+                       
+               if (document.form.setvisual.value==1)
+               {
+                       tinyMCE.execCommand('mceAddControl', false, 'body_text');
+                       document.form.formatting[0].disabled = "disabled";
+                       document.form.setvisualbutton.value = "<?php echo _AT('switch_text'); ?>";
+               }
+               else
+               {
+                       document.form.setvisualbutton.value = "<?php echo _AT('switch_visual'); ?>";
+               }
+       }
+       
+       // show/hide "cusomized head" editor
+       function switch_head_editor()
+       {
+               if (document.form.edithead.value=="<?php echo _AT('edit'); ?>")
+               {
+                       document.form.edithead.value = "<?php echo _AT('hide'); ?>"
+                       document.getElementById("headDiv").style.display = "";
+                       document.form.displayhead.value=1;
+               }
+               else
+               {
+                       document.form.edithead.value = "<?php echo _AT('edit'); ?>"
+                       document.getElementById("headDiv").style.display = "none";
+                       document.form.displayhead.value=0;
+               }
+       }
+       
+       // switch between text, visual editor for "body text"
+       function switch_body_editor()
+       {
+               if (document.form.setvisualbutton.value=="<?php echo _AT('switch_visual'); ?>")
+               {
+                       tinyMCE.execCommand('mceAddControl', false, 'body_text');
+                       document.form.setvisual.value=1;
+                       document.form.settext.value=0;
+                       document.form.formatting[0].disabled = "disabled";
+                       document.form.setvisualbutton.value = "<?php echo _AT('switch_text'); ?>";
+               }
+               else
+               {
+                       tinyMCE.execCommand('mceRemoveControl', false, 'body_text');
+                       document.form.setvisual.value=0;
+                       document.form.settext.value=1;
+                       document.form.formatting[0].disabled = "";
+                       document.form.setvisualbutton.value = "<?php echo _AT('switch_visual'); ?>";
+               }
+       }
+       //-->
+       </script>
diff --git a/include/html/editor_tabs/glossary.inc.php b/include/html/editor_tabs/glossary.inc.php
new file mode 100644 (file)
index 0000000..e5becf4
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+
+?>
+
+<div class="row"><?php
+       if ($num_terms == 0) {
+               echo _AT('no_terms_found');
+       }
+
+       $num_glossary = count($glossary_ids);
+
+       for ($i=0; $i<$num_terms; $i++) {
+               for ($j=0;$j<$i;$j++) {
+                       if ($strtolower($word[$j]) == $strtolower($word[$i])) {
+                               /* skip multiple occurances of the same word: */
+                               continue 2;
+                       }
+               }
+
+               ?><table cellspacing="1" cellpadding="0" border="0" class="bodyline" summary="" align="center">
+               <tr>
+                       <td align="right" class="row1"><strong><?php 
+                               $key = in_array_cin($word[$i], $glossary_ids);
+
+                               if ($key === false) {
+                                       echo '<em>'._AT('new').'</em> ';
+                                       $current_word = $word[$i];
+                                       $current_defn = $_POST['glossary_defs'][$word[$i]];
+                               } else {
+                                       $current_word = $glossary_ids[$key];
+                                       if (!$_POST['glossary_defs'][$word[$i]]) {
+                                               $current_defn = $glossary[$glossary_ids[$key]];
+                                       } else {
+                                               $current_defn = $_POST['glossary_defs'][$word[$i]];
+                                       }
+                               }
+
+                               echo _AT('glossary_term'); ?>:</strong></td>
+                       <td class="row1"><?php echo AT_print(urldecode($current_word), 'glossary.word'); ?></td>
+               </tr>
+               <?php if ($strlen(urldecode($current_word)) > 60): ?>
+               <tr>
+                       <td>&nbsp;</td>
+                       <td><em><?php echo _AT('glossary_term_limit'); ?></em></td>
+               </tr>
+               <?php else: ?>
+               <tr>
+                       <td valign="top" align="right" class="row1"><label for="body<?php echo $i; ?>"><strong><?php echo _AT('glossary_definition');  ?>:</strong></label></td>
+                       <td class="row1">
+                               <textarea name="glossary_defs[<?php echo $word[$i]; ?>]" class="formfield" cols="55" rows="4" id="body<?php echo $i; ?>"><?php 
+                                       echo ContentManager::cleanOutput($current_defn); 
+               
+               ?></textarea></td>
+               </tr>
+               <tr>
+                       <td valign="top" align="right" class="row1"><label for="r<?php echo $i; ?>"><strong><?php echo _AT('glossary_related');  ?>:</strong></label></td>
+                       <td class="row1"><?php
+
+                               if ($num_glossary > 1) {
+                                       echo '<select name="related_term['.$word[$i].']" id="r'.$i.'">';
+                                       echo '<option value="0"></option>';
+                                       foreach ($glossary_ids as $id => $term) {
+                                               if ($term == $word[$i]) {
+                                                       continue;
+                                               }
+                                               echo '<option value="'.$id.'"';
+                                               if ($_POST['related_term'][$word[$i]] == $id) {
+                                                       echo ' selected="selected"';
+                                               }
+                                               echo '>'.urldecode($term).'</option>';
+                                       }
+                                       echo '</select>';
+                               } else {
+                                       echo _AT('none_available');
+                               }
+
+                               ?></td>
+               </tr>
+               <?php endif; ?>
+               </table><br />
+       <?php } ?>
+               
+       </div>
\ No newline at end of file
diff --git a/include/html/editor_tabs/preview.inc.php b/include/html/editor_tabs/preview.inc.php
new file mode 100644 (file)
index 0000000..5fb69fa
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+?>
+       <div class="row"><?php 
+       
+               echo '<h2>'.AT_print($stripslashes($_POST['title']), 'content.title').'</h2>';
+
+               if ($_POST['body_text']) {
+                       echo format_content($stripslashes($_POST['body_text']), $_POST['formatting'], $_POST['glossary_defs']);
+               } else { 
+                       global $msg;
+               
+                       $msg->printInfos('NO_PAGE_CONTENT');
+       
+               } ?>            
+       </div>
diff --git a/include/html/editor_tabs/properties.inc.php b/include/html/editor_tabs/properties.inc.php
new file mode 100644 (file)
index 0000000..eb628f4
--- /dev/null
@@ -0,0 +1,130 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+?>
+       <div class="row">
+               <?php echo _AT('release_date');  ?><br />
+               <?php if ($_POST['day']) { ?>
+                       <?php
+                               $today_day   = $_POST['day'];
+                               $today_mon   = $_POST['month'];
+                               $today_year  = $_POST['year'];
+
+                               $today_hour  = $_POST['hour'];
+                               $today_min   = $_POST['min'];           
+               }?>
+               <?php require(AT_INCLUDE_PATH.'html/release_date.inc.php');     ?>
+               <?php echo _AT('applies_to_all_sub_pages'); ?>
+       </div>
+
+       <div class="row">
+               <label for="keys"><?php echo _AT('keywords'); ?></label><br />
+               <textarea name="keywords" class="formfield" cols="73" rows="2" id="keys"><?php echo ContentManager::cleanOutput($_POST['keywords']); ?></textarea>
+       </div>
+
+       <div class="row">
+               <input type="hidden" name="button_1" value="-1" />
+               <?php
+                       if ($contentManager->getNumSections() > (1 - (bool)(!$cid))) {
+                               echo '<p>' 
+                                       , _AT('editor_properties_instructions', 
+                                               '<img src="'.$_base_path.'images/after.gif" alt="'._AT('after_topic', '').'" title="'._AT('after_topic', '').'" />', 
+                                               '<img src="'.$_base_path.'images/before.gif" alt="'._AT('before_topic', '').'" title="'._AT('before_topic', '').'" />',
+                                               '<img src="'.$_base_path.'images/child_of.gif" alt="'._AT('child_of', '').'" title="'._AT('child_of', '').'"  />')
+                                       , '</p>';
+
+                               echo '<p>' , _AT('editor_properties_insturctions_related') , '</p>';
+                       }
+
+                       $old_pid = $_POST['pid'];
+                       $old_ordering = $_POST['ordering'];
+
+                       if (isset($_POST['move'])) {
+                               $arr = explode('_', key($_POST['move']), 2);
+                               $new_pid = $_POST['new_pid'] = $arr[0];
+                               $new_ordering = $_POST['new_ordering'] = $arr[1];
+                       } else {
+                               $new_pid = $_POST['new_pid'];
+                               $new_ordering = $_POST['new_ordering'];
+                       }
+
+                       echo '<input type="hidden" name="new_ordering" value="'.$new_ordering.'" />';
+                       echo '<input type="hidden" name="new_pid" value="'.$new_pid.'" />';
+
+                       ?><br />
+                       <table border="0">
+                       <tr>
+                               <th colspan="2"><?php echo _AT('move'); ?></th>
+                               <th><?php echo _AT('related_topics'); ?></th>
+                       </tr>
+                       <tr>
+                               <td>&nbsp;</td>
+                               <td>&nbsp;</td>
+                               <td><?php echo _AT('home'); ?></td>
+                       </tr>
+                       <?php
+
+                               $content_menu = $contentManager->_menu;
+                               if ($cid == 0) {
+                                       $old_ordering = count($contentManager->getContent($pid))+1;
+                                       $old_pid = 0;
+
+                                       $current = array('content_id' => -1,
+                                                                       'ordering' => $old_ordering,
+                                                                       'title' => $_POST['title']);
+
+                                       $content_menu[$old_pid][] = $current;
+                               }
+
+                               if (($old_pid != $new_pid) || ($old_ordering != $new_ordering) || ($cid == 0)) {
+
+                                       $children = $content_menu[$old_pid];
+
+                                       $children_current = array($children[$old_ordering-1]);
+                                       unset($content_menu[$old_pid][$old_ordering-1]);
+
+                                       if ($old_pid != $new_pid) {
+                                               $num_children = count($content_menu[$old_pid]);
+                                               $i = 1;
+                                               foreach($content_menu[$old_pid] as $id => $child) {
+                                                       $content_menu[$old_pid][$id]['ordering'] = $i;
+                                                       $i++;
+                                               }
+                                       }
+
+                                       $children = $content_menu[$new_pid];
+                                       if (!isset($children)) {
+                                               $children = array();
+                                       }
+                               
+                                       $children_above = array_slice($children, 0, $new_ordering-1);
+
+                                       $children_below = array_slice($children, $new_ordering-1);
+
+                                       $content_menu[$new_pid] = array_merge($children_above, $children_current, $children_below);
+
+                                       $i=1;
+                                       foreach($content_menu[$new_pid] as $id => $child) {
+                                               $content_menu[$new_pid][$id]['ordering'] = $i;
+                                               $i++;
+                                       }
+                       
+                               }
+
+                               $contentManager->printMoveMenu($content_menu, 0, 0, '', array());
+
+               ?></table>
+       </div>
\ No newline at end of file
diff --git a/include/html/enroll_edit.inc.php b/include/html/enroll_edit.inc.php
new file mode 100644 (file)
index 0000000..9e1f454
--- /dev/null
@@ -0,0 +1,328 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: enroll_edit.php 6662 2006-11-20 15:52:49Z joel $
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+/**
+* Generates the list of login ids of the selected user
+* @access  private
+* @param   string $member_ids  the list of members to be checked
+* @return  string                              The list of login IDs
+* @author  Shozub Qureshi
+*/
+function get_usernames ($member_ids) {
+       global $db;
+
+       $sql    = "SELECT login FROM ".TABLE_PREFIX."members WHERE `member_id` IN ($member_ids)";
+
+       $result = mysql_query($sql, $db);
+
+       while ($row = mysql_fetch_assoc($result)) {
+               $str .= '<li>' . $row['login'] . '</li>';
+       }
+       return $str;
+}
+
+/**
+* Checks if any of the selected users have non-zero roles or privileges
+* @access  private
+* @param   string $member_ids  the list of members to be checked
+* @return  int                                 whether the role/priv is empty or not (0 = if empty, 1 = if ok)
+* @author  Shozub Qureshi
+*/
+function check_roles ($member_ids) {
+       global $db;
+
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."course_enrollment WHERE `member_id` IN ($member_ids)";
+       $result = mysql_query($sql, $db);
+
+       while ($row = mysql_fetch_assoc($result)) {
+               if ($row['role'] != 'Student' || $row['privileges'] != 0) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+/**
+* Removes students from course enrollement
+* @access  private
+* @param   array $list                 the IDs of the members to be removed
+* @author  Shozub Qureshi
+*/
+/*
+// no longer used. Unenroll does this job AND removes groups too.
+function remove ($list) {
+       global $db;
+
+       $members = '(member_id='.$list[0].')';
+       for ($i=1; $i < count($list); $i++) {
+               $members .= ' OR (member_id='.$list[$i].')';
+       }
+       $sql    = "DELETE FROM ".TABLE_PREFIX."course_enrollment WHERE course_id = $_SESSION[course_id] AND ($members)";        
+       $result = mysql_query($sql, $db);
+}*/
+
+/**
+* Unenrolls students from course enrollement
+* @access  private
+* @param   array $list                 the IDs of the members to be removed
+* @author  Shozub Qureshi
+*/
+function unenroll ($list) {
+       global $db, $system_courses, $course_id;
+       $members = implode(',', $list);
+
+       if ($members) {
+               $members = addslashes($members);
+
+               $sql    = "DELETE FROM ".TABLE_PREFIX."course_enrollment WHERE course_id=$course_id AND member_id IN ($members)";
+               $result = mysql_query($sql, $db);
+
+               $sql    = "DELETE FROM ".TABLE_PREFIX."groups_members WHERE member_id IN ($members)";
+               $result = mysql_query($sql, $db);
+               // $groupModule->unenroll(course_id, user_id);
+               // $forumModule->unenroll(course_id, user_id);
+       }
+}
+
+/**
+* Enrolls students into course enrollement
+* @access  private
+* @param   array $list                 the IDs of the members to be added
+* @author  Shozub Qureshi
+*/
+function enroll ($list) {
+       global $db, $msg, $_config, $course_id, $owner;
+       require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+
+       $num_list = count($list);
+       $members = '(member_id='.$list[0].')';
+       for ($i=0; $i < $num_list; $i++)        {
+               $id = intval($list[$i]);
+               $members .= ' OR (member_id='.$id.')';
+               $sql = "INSERT INTO ".TABLE_PREFIX."course_enrollment VALUES ($id, $course_id, 'y', 0, '', 0)";
+               $result = mysql_query($sql, $db);
+               if (mysql_affected_rows($db) != 1) {
+                       $sql = "UPDATE ".TABLE_PREFIX."course_enrollment SET approved='y' WHERE course_id=$course_id AND member_id=$id";
+                       $result = mysql_query($sql, $db);
+               }
+       }
+
+       //get First_name, Last_name of course Instructor
+       $sql_from    = "SELECT first_name, last_name, email FROM ".TABLE_PREFIX."members WHERE member_id = $owner";
+       $result_from = mysql_query($sql_from, $db);
+       $row_from    = mysql_fetch_assoc($result_from);
+
+       $email_from_name  = $row_from['first_name'] . ' ' . $row_from['last_name'];
+       $email_from = $row_from['email'];
+
+       //get email addresses of users:
+       $sql_to    = "SELECT email FROM ".TABLE_PREFIX."members WHERE ($members)";
+       $result_to = mysql_query($sql_to, $db);
+
+       while ($row_to = mysql_fetch_assoc($result_to)) {
+               // send email here.
+               $login_link = AT_BASE_HREF . 'login.php?course=' . $course_id;
+               $subject = SITE_NAME.': '._AT('enrol_message_subject');
+               $body = SITE_NAME.': '._AT('enrol_message_approved', $_SESSION['course_title'], $login_link)."\n\n";
+
+               $mail = new ATutorMailer;
+               $mail->From     = $_config['contact_email'];
+               $mail->FromName = $_config['site_name'];
+               $mail->AddAddress($row_to['email']);
+               $mail->Subject  = $subject;
+               $mail->Body     = $body;
+                       
+               if (!$mail->Send()) {
+                       $msg->addError('SENDING_ERROR');
+               }
+
+               unset($mail);
+       }
+}
+
+
+function group ($list, $gid) {
+       global $db,$msg;
+       $sql = "REPLACE INTO ".TABLE_PREFIX."groups_members VALUES ";
+       $gid=intval($gid);
+       for ($i=0; $i < count($list); $i++)     {
+               $student_id = intval($list[$i]);
+               $sql .= "($gid, $student_id),";
+       }
+       $sql = substr($sql, 0, -1);
+       mysql_query($sql, $db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: index.php');
+       exit;
+}
+
+function group_remove ($ids, $gid) {
+       global $db,$msg;
+       $gid=intval($gid);
+
+       $ids=implode(',', $ids);
+
+       if ($ids) {
+               $sql = "DELETE FROM ".TABLE_PREFIX."groups_members WHERE group_id=$gid AND member_id IN ($ids)";
+               mysql_query($sql, $db);
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       }
+
+       header('Location: index.php');
+       exit;
+}
+
+/**
+* Marks a student as an alumni of the course (not enrolled, but can view course material and participate in forums)
+* @access  private
+* @param   array $list                 the IDs of the members to be alumni
+* @author  Heidi Hazelton
+*/
+function alumni ($list) {
+       global $db, $course_id;
+       $members = '(member_id='.$list[0].')';
+       for ($i=1; $i < count($list); $i++)     {
+               $members .= ' OR (member_id='.$list[$i].')';
+       }
+       
+       $sql    = "UPDATE ".TABLE_PREFIX."course_enrollment SET approved = 'a' WHERE course_id=$course_id AND ($members)";
+       $result = mysql_query($sql, $db);
+}
+
+
+//course_owner
+$owner = $system_courses[$course_id]['member_id'];
+
+if (isset($_POST['submit_no'])) {
+       //if user decides to forgo option
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php?current_tab='.$_POST['curr_tab'].SEP.'course_id='.$course_id);
+       exit;
+} /*
+// No longer used. Unenroll does the same job and removes from groups too.
+else if (isset($_POST['submit_yes']) && $_POST['func'] =='remove' ) {
+       //Remove student from list (unenrolls automatically)
+
+       //you cannot remove anyone unless you are the course owner
+       authenticate(AT_PRIV_ADMIN);
+
+       //echo 'atleast this worked';
+       remove($_POST['id']);
+
+       $msg->addFeedback('MEMBERS_REMOVED');
+       header('Location: index.php?current_tab=4');
+       exit;
+}*/
+else if (isset($_POST['submit_yes']) && $_POST['func'] =='unenroll' ) {
+       //Unenroll student from course
+       unenroll($_POST['id']);
+
+//     $msg->addFeedback('MEMBERS_UNENROLLED');
+       $msg->addFeedback('MEMBERS_REMOVED');
+       header('Location: index.php?current_tab=4'.SEP.'course_id='.$course_id);
+       exit;
+} else if (isset($_POST['submit_yes']) && $_POST['func'] =='enroll' ) {
+       //Enroll student in course
+       enroll($_POST['id']);
+
+       $msg->addFeedback('MEMBERS_ENROLLED');
+       header('Location: index.php?current_tab=0'.SEP.'course_id='.$course_id);
+       exit;
+} else if (isset($_POST['submit_yes']) && $_POST['func'] =='alumni' ) {
+       //Mark student as course alumnus
+       alumni($_POST['id']);
+       
+       $msg->addFeedback('MEMBERS_ALUMNI');
+       header('Location: index.php?current_tab=2'.SEP.'course_id='.$course_id);
+       exit;
+} else if (isset($_POST['submit_yes']) && $_POST['func'] =='group' ) {
+       //Mark student as a member of the group
+       group($_POST['id'],$_POST['gid']);
+       
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: index.php?current_tab='.$_POST['current_tab'].SEP.'course_id='.$course_id);
+       exit;
+} else if (isset($_POST['submit_yes']) && $_POST['func'] =='group_remove' ) {
+       // Remove student as a member of the group
+       group_remove($_POST['id'],$_POST['gid']);
+       
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: index.php?current_tab='.$_POST['current_tab'].SEP.'course_id='.$course_id);
+       exit;
+}
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+//Store id's into a hidden element for use by functions
+$j = 0;
+while ($_GET['id'.$j]) {
+       $_GET['id'.$j] = abs($_GET['id'.$j]);
+       if ($_GET['id'.$j] == $owner) {
+               //do nothing
+       } else {
+               $hidden_vars['id['.$j.']'] = $_GET['id'.$j];
+               $member_ids .= $_GET['id'.$j].', ';
+       }       
+       $j++;
+}
+$member_ids = substr($member_ids, 0, -2);
+
+$hidden_vars['func']     = $_GET['func'];
+$hidden_vars['current_tab'] = $_GET['current_tab'];
+$hidden_vars['gid']             = abs($_GET['gid']);
+$hidden_vars['course_id'] = $course_id;
+//get usernames of users about to be edited
+$str = get_usernames($member_ids);
+
+//Print appropriate confirm msg for action
+if ($_GET['func'] == 'remove') {
+       $confirm = array('REMOVE_STUDENT',   $str);
+       $msg->addConfirm($confirm, $hidden_vars);
+} else if ($_GET['func'] == 'enroll') {
+       $confirm = array('ENROLL_STUDENT',   $str);
+       $msg->addconfirm($confirm, $hidden_vars);
+} else if ($_GET['func'] == 'unenroll') {
+       if (check_roles($member_ids) == 1) {
+               $confirm = array('UNENROLL_PRIV', $str);
+               $msg->addConfirm($confirm, $hidden_vars);
+       } else {
+               $confirm = array('UNENROLL_STUDENT', $str);
+               $msg->addConfirm($confirm, $hidden_vars);
+       }
+} else if ($_GET['func'] == 'alumni') {
+       $confirm = array('ALUMNI',   $str);
+       $msg->addConfirm($confirm, $hidden_vars);
+} else if ($_GET['func'] == 'group') {
+       $sql = "SELECT title FROM ".TABLE_PREFIX."groups WHERE group_id=".$hidden_vars['gid'];
+       $result = mysql_query($sql, $db);
+       $row = mysql_fetch_assoc($result);
+
+       $confirm = array('STUDENT_GROUP', $row['title'], $str);
+       $msg->addConfirm($confirm, $hidden_vars);
+} else if ($_GET['func'] == 'group_remove') {
+       $sql = "SELECT title FROM ".TABLE_PREFIX."groups WHERE group_id=".$hidden_vars['gid'];
+       $result = mysql_query($sql, $db);
+       $row = mysql_fetch_assoc($result);
+
+       $confirm = array('STUDENT_REMOVE_GROUP', $row['title'], $str);
+       $msg->addConfirm($confirm, $hidden_vars);
+}
+               
+$msg->printConfirm();
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+
+?>
\ No newline at end of file
diff --git a/include/html/enroll_tab_functions.inc.php b/include/html/enroll_tab_functions.inc.php
new file mode 100644 (file)
index 0000000..de97531
--- /dev/null
@@ -0,0 +1,132 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+$db;\r
+\r
+/**\r
+* Generates the tabs for the enroll admin page\r
+* @access  private\r
+* @return  string                              The tabs for the enroll_admin page\r
+* @author  Shozub Qureshi\r
+*/\r
+function get_tabs() {\r
+       //these are the _AT(x) variable names and their include file\r
+       /* tabs[tab_id] = array(tab_name, file_name,                accesskey) */\r
+       $tabs[0] = array('enrolled',   'enroll_admin.php', 'e');\r
+       $tabs[1] = array('unenrolled', 'enroll_admin.php', 'u');\r
+       //$tabs[2] = array('assistants', 'enroll_admin.php', 'a');\r
+       $tabs[2] = array('alumni',         'enroll_admin.php', 'a');\r
+\r
+       return $tabs;\r
+}\r
+\r
+/**\r
+* Generates the html for the enrollment tables\r
+* @access  private\r
+* @param   string $condition   the condition to be imposed in the sql query (approved = y/n/a)\r
+* @param   string $col                 the column to be sorted\r
+* @param   string $order               the sorting order (DESC or ASC)\r
+* @param   int $unenr                  is one if the unenrolled list is being generated\r
+* @author  Shozub Qureshi\r
+* @author  Joel Kronenberg\r
+*/\r
+function generate_table($condition, $col, $order, $unenr, $filter) {\r
+       global $db;\r
+\r
+       if ($filter['role'] == -1) {\r
+               $condition .= ' AND CE.privileges<>0';\r
+       }\r
+       if ($filter['group'] > 0) {\r
+               $sql = "SELECT member_id FROM ".TABLE_PREFIX."groups_members WHERE group_id=".$filter['group'];\r
+               $result = mysql_query($sql, $db);\r
+               while ($row = mysql_fetch_assoc($result)) {\r
+                       $members_list .= ',' . $row['member_id'];\r
+               }\r
+               $condition .= ' AND CE.member_id IN (0'.$members_list.')';\r
+       }\r
+       if (isset($filter['status'])) {\r
+               $condition .= ' AND M.status='.$filter['status'];\r
+       }\r
+\r
+       //output list of enrolled students\r
+       $sql    =  "SELECT CE.member_id, CE.role, M.login, M.first_name, M.last_name, M.email, M.status \r
+                               FROM ".TABLE_PREFIX."course_enrollment CE, ".TABLE_PREFIX."members M \r
+                               WHERE CE.course_id=$_SESSION[course_id] AND CE.member_id=M.member_id AND ($condition) \r
+                               ORDER BY $col $order";\r
+       $result = mysql_query($sql, $db);\r
+       echo '<tbody>';\r
+       //if table is empty display message\r
+       if (mysql_num_rows($result) == 0) {\r
+               echo '<tr><td colspan="6">'._AT('none_found').'</td></tr>';\r
+       } else {\r
+               while ($row  = mysql_fetch_assoc($result)) {\r
+                       echo '<tr onmousedown="document.selectform[\'m' . $row['member_id'] . '\'].checked = !document.selectform[\'m' . $row['member_id'] . '\'].checked;">';\r
+                       echo '<td>';\r
+\r
+                       $act = "";\r
+                       if ($row['member_id'] == $_SESSION['member_id']) {\r
+                               $act = 'disabled="disabled"';   \r
+                       } \r
+                       \r
+                       echo '<input type="checkbox" name="id[]" value="'.$row['member_id'].'" id="m'.$row['member_id'].'" ' . $act . ' onmouseup="this.checked=!this.checked" title="'.AT_print($row['login'], 'members.login').'" />';\r
+                       echo AT_print($row['login'], 'members.login') . '</td>';\r
+                       echo '<td>' . AT_print($row['first_name'], 'members.name') . '</td>';\r
+                       echo '<td>' . AT_print($row['last_name'], 'members.name')  . '</td>';\r
+                       echo '<td>' . AT_print($row['email'], 'members.email') . '</td>';\r
+                       \r
+                       //if role not already assigned, assign role to be student\r
+                       //and we are not vieiwing list of unenrolled students\r
+                       echo '<td>';\r
+                       if ($row['status'] == AT_STATUS_DISABLED) {\r
+                               echo _AT('disabled');\r
+                       } else if ($row['status'] == AT_STATUS_UNCONFIRMED) {\r
+                               echo _AT('unconfirmed');\r
+                       } else if ($row['role'] == '' && $unenr != 1) {\r
+                               echo _AT('Student');\r
+                       } else if ($unenr == 1) {\r
+                               echo _AT('na');\r
+                       } else {\r
+                               echo AT_print($row['role'], 'members.role');\r
+                       }\r
+                       echo '</td>';\r
+\r
+                       echo '</tr>';\r
+               }               \r
+       }\r
+       echo '</tbody>';\r
+}\r
+\r
+/**\r
+* Generates the html for the SORTED enrollment tables\r
+* @access  private\r
+* @param   int $curr_tab       the current tab (enrolled, unenrolled or alumni)\r
+* @author  Shozub Qureshi\r
+*/\r
+function display_columns ($curr_tab) {\r
+       global $orders;\r
+       global $order;\r
+?>\r
+       <th scope="col"><input type="checkbox" value="<?php echo _AT('select_all'); ?>" id="all" title="<?php echo _AT('select_all'); ?>" name="selectall" onclick="CheckAll();" /> <a href="tools/enrollment/index.php?<?php echo $orders[$order]; ?>=login<?php echo SEP;?>current_tab=<?php echo $curr_tab; ?>"><?php echo _AT('login_name'); ?></a></th>\r
+\r
+       <th scope="col"><a href="tools/enrollment/index.php?<?php echo $orders[$order]; ?>=first_name<?php echo SEP;?>current_tab=<?php echo $curr_tab; ?>"><?php echo _AT('first_name'); ?></a></th>\r
+\r
+       <th scope="col"><a href="tools/enrollment/index.php?<?php echo $orders[$order]; ?>=last_name<?php echo SEP;?>current_tab=<?php echo $curr_tab; ?>"><?php echo _AT('last_name'); ?></a></th>\r
+\r
+       <th scope="col"><a href="tools/enrollment/index.php?<?php echo $orders[$order]; ?>=email<?php echo SEP;?>current_tab=<?php echo $curr_tab; ?>"><?php echo _AT('email'); ?></a></th>\r
+\r
+       <th scope="col"><a href="tools/enrollment/index.php?<?php echo $orders[$order]; ?>=role<?php echo SEP;?>current_tab=<?php echo $curr_tab; ?>"><?php echo _AT('role').'/'._AT('status'); ?></a></th>\r
+<?php  \r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/include/html/enrollment.inc.php b/include/html/enrollment.inc.php
new file mode 100644 (file)
index 0000000..c971582
--- /dev/null
@@ -0,0 +1,420 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+if (isset($_POST['enroll'])) {
+       if (!$_POST['id'])      {
+               $msg->addError('NO_STUDENT_SELECTED');
+               $_GET['tab'] = $_POST['tab'];
+       } else {
+               $i=0;
+               foreach ($_POST['id'] as $elem) {
+                       $text .= 'id'.$i.'='.$elem.SEP;
+                       $i++;
+               }
+               header('Location: enroll_edit.php?'.$text.'func=enroll'.SEP.'tab=0'.SEP.'course_id='.$course_id);
+               exit;
+       }
+} else if (isset($_POST['unenroll'])) {
+       // different from a plain delete. This removes from groups as well.
+       if (!$_POST['id'])      {
+               $msg->addError('NO_STUDENT_SELECTED');
+               $_GET['tab'] = $_POST['tab'];
+       } else {
+               $i=0;
+               foreach ($_POST['id'] as $elem) {
+                       $text .= 'id'.$i.'='.$elem.SEP;
+                       $i++;
+               }
+               header('Location: enroll_edit.php?'.$text.'func=unenroll'.SEP.'tab=1'.SEP.'course_id='.$course_id);
+               exit;   
+       }
+} else if (isset($_POST['role'])) {
+       if (!$_POST['id'])      {
+               $msg->addError('NO_STUDENT_SELECTED');
+               $_GET['tab'] = $_POST['tab'];
+       } else {
+               $i=0;
+               foreach ($_POST['id'] as $elem) {
+                       $text .= 'mid'.$i.'='.$elem.SEP;
+                       $i++;
+               }
+               header('Location: privileges.php?'.$text.SEP.'course_id='.$course_id);
+               exit;
+       }
+} else if (isset($_POST['alumni'])) {
+       if (!$_POST['id'])      {
+               $msg->addError('NO_STUDENT_SELECTED');
+               $_GET['tab'] = $_POST['tab'];
+       } else {
+               $i=0;
+               foreach ($_POST['id'] as $elem) {
+                       $text .= 'id'.$i.'='.$elem.SEP;
+                       $i++;
+               }
+               header('Location: enroll_edit.php?'.$text.'func=alumni'.SEP.'tab=2'.SEP.'course_id='.$course_id);
+               exit;
+       }
+}
+
+//filter stuff:
+
+if ($_GET['reset_filter']) {
+       unset($_GET);
+}
+
+$filter=array();
+
+if (isset($_GET['role']) && ($_GET['role'] != '')) {
+       $filter['role'] = intval($_GET['role']);
+} 
+
+if (isset($_GET['status']) && ($_GET['status'] != '')) {
+       $filter['status'] = intval($_GET['status']);
+} 
+
+if (isset($_GET['group']) && ($_GET['group'] != '')) {
+       $filter['group'] = intval($_GET['group']);
+} 
+
+require(AT_INCLUDE_PATH.'html/enroll_tab_functions.inc.php');
+$tabs = get_tabs();    
+$num_tabs = count($tabs);
+
+for ($i=0; $i < $num_tabs; $i++) {
+       if (isset($_POST['button_'.$i]) && ($_POST['button_'.$i] != -1)) { 
+               $current_tab = $i;
+               $_POST['current_tab'] = $i;
+               break;
+       }
+}
+
+//get present tab if specified
+if ($_GET['current_tab']) {
+       $current_tab = $_GET['current_tab'];
+       $_POST['current_tab'] = $_GET['current_tab'];
+}
+
+$orders = array('asc' => 'desc', 'desc' => 'asc');
+$cols   = array('login' => 1, 'first_name' => 1, 'second_name' => 1, 'last_name' => 1, 'email' => 1);
+
+if (isset($_GET['asc'])) {
+       $order = 'asc';
+       $col   = isset($cols[$_GET['asc']]) ? $_GET['asc'] : 'login';
+} else if (isset($_GET['desc'])) {
+       $order = 'desc';
+       $col   = isset($cols[$_GET['desc']]) ? $_GET['desc'] : 'login';
+} else {
+       // no order set
+       $order = 'asc';
+       $col   = 'login';
+}
+$view_select = intval($_POST['view_select']);
+
+// the possible tabs. order matters.
+$tabs = array('enrolled', 'assistants', 'alumni', 'pending_enrollment', 'not_enrolled');
+
+$num_tabs = count($tabs);
+if (isset($_REQUEST['tab'])) {
+       $current_tab = intval($_REQUEST['tab']);
+}
+
+if (!isset($current_tab)) {
+       $current_tab = 0;
+}
+
+if (isset($_GET['match']) && $_GET['match'] == 'one') {
+       $checked_match_one = ' checked="checked"';
+       $page_string .= SEP.'match=one';
+} else {
+       $_GET['match'] = 'all';
+       $checked_match_all = ' checked="checked"';
+       $page_string .= SEP.'match=all';
+}
+
+if (admin_authenticate(AT_ADMIN_PRIV_ENROLLMENT, TRUE)) {
+       $page_string .= SEP.'course_id='.$course_id;
+}
+
+if ($_GET['search']) {
+       $page_string .= SEP.'search='.urlencode($_GET['search']);
+       $search = $addslashes($_GET['search']);
+       $search = explode(' ', $search);
+
+       if ($_GET['match'] == 'all') {
+               $predicate = 'AND ';
+       } else {
+               $predicate = 'OR ';
+       }
+
+       $sql = '';
+       foreach ($search as $term) {
+               $term = trim($term);
+               $term = str_replace(array('%','_'), array('\%', '\_'), $term);
+               if ($term) {
+                       $term = '%'.$term.'%';
+                       $sql .= "((M.first_name LIKE '$term') OR (M.second_name LIKE '$term') OR (M.last_name LIKE '$term') OR (M.email LIKE '$term') OR (M.login LIKE '$term')) $predicate";
+               }
+       }
+       $sql = '('.substr($sql, 0, -strlen($predicate)).')';
+       $search = $sql;
+} else {
+       $search = '1';
+}
+
+$instructor_id = $system_courses[$course_id]['member_id'];
+// retrieve all the members of this course (used later to get all those who aren't in this course)
+$course_enrollment = get_group_concat('course_enrollment', 'member_id', "course_id=$course_id AND member_id<>$instructor_id");
+$course_enrollment .= ','.$instructor_id;
+
+$tab_counts     = array();
+$tab_sql_counts = array();
+$tab_sql_counts[0] = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."course_enrollment CE INNER JOIN ".TABLE_PREFIX."members M USING (member_id) WHERE CE.course_id=$course_id 
+                                               AND CE.approved='y' AND M.member_id<>$instructor_id AND CE.privileges=0 AND $search";
+$tab_sql_counts[1] = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."course_enrollment CE INNER JOIN ".TABLE_PREFIX."members M USING (member_id) WHERE CE.course_id=$course_id 
+                                               AND CE.approved='y' AND CE.privileges>0 AND $search";
+$tab_sql_counts[2] = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."course_enrollment CE INNER JOIN ".TABLE_PREFIX."members M USING (member_id) WHERE CE.course_id=$course_id 
+                                               AND approved='a' AND $search";
+$tab_sql_counts[3] = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."course_enrollment CE INNER JOIN ".TABLE_PREFIX."members M USING (member_id) WHERE CE.course_id=$course_id
+                                               AND approved='n' AND $search";
+$tab_sql_counts[4] = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."members M WHERE M.status>1 AND M.member_id NOT IN ($course_enrollment) AND $search";
+
+foreach ($tab_sql_counts as $tab => $sql) {
+       if ($tab == 3 && $system_courses[$course_id]['access'] != 'private') {
+               $tab_counts[$tab] = 0;
+       } else {
+               $result = mysql_query($sql);
+               $row    = mysql_fetch_assoc($result);
+               $tab_counts[$tab] = $row['cnt'];
+       }
+}
+
+
+if ($current_tab == 0) {
+       // enrolled
+       $sql    =  "SELECT CE.member_id, CE.privileges, CE.approved, M.login, M.first_name, M.second_name, M.last_name, M.email 
+                               FROM ".TABLE_PREFIX."course_enrollment CE INNER JOIN ".TABLE_PREFIX."members M USING (member_id)
+                               WHERE CE.course_id=$course_id AND approved='y' AND M.member_id<>$instructor_id AND CE.privileges=0 AND $search
+                               ORDER BY $col $order";
+} else if ($current_tab == 1) {
+       // assistants
+       $sql    =  "SELECT CE.member_id, CE.approved, CE.privileges, M.login, M.first_name, M.second_name, M.last_name, M.email 
+                               FROM ".TABLE_PREFIX."course_enrollment CE INNER JOIN ".TABLE_PREFIX."members M USING (member_id)
+                               WHERE CE.course_id=$course_id AND CE.approved='y' AND CE.privileges>0 AND $search
+                               ORDER BY $col $order";
+
+} else if ($current_tab == 3) {
+       // pending
+       if ($system_courses[$course_id]['access'] == 'private') {
+               $sql    =  "SELECT CE.member_id, CE.approved, CE.privileges, M.login, M.first_name, M.second_name, M.last_name, M.email 
+                               FROM ".TABLE_PREFIX."course_enrollment CE INNER JOIN ".TABLE_PREFIX."members M USING (member_id)
+                               WHERE CE.course_id=$course_id AND approved='n' AND $search
+                               ORDER BY $col $order";
+       } else {
+               // not sure what this is about
+//             $sql_cnt = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."members WHERE 0";
+               $sql = "SELECT login FROM ".TABLE_PREFIX."members WHERE 0";
+       }
+} else if ($current_tab == 2) {
+       // alumni
+       $sql    =  "SELECT CE.member_id, CE.approved, CE.privileges, M.login, M.first_name, M.second_name, M.last_name, M.email 
+                               FROM ".TABLE_PREFIX."course_enrollment CE INNER JOIN ".TABLE_PREFIX."members M USING (member_id)
+                               WHERE CE.course_id=$course_id AND approved='a' AND $search
+                               ORDER BY $col $order";
+} else { // current_tab == 4
+
+//     $sql_cnt=  "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."members M WHERE M.status>1 AND M.member_id NOT IN ($course_enrollment) AND $search";
+       
+       $sql    =  "SELECT M.member_id, M.login, M.first_name, M.second_name, M.last_name, M.email FROM ".TABLE_PREFIX."members M WHERE M.member_id NOT IN ($course_enrollment) AND M.status>1 AND $search ORDER BY $col $order";
+}
+
+$results_per_page = 50;
+
+$num_pages = max(ceil($tab_counts[$current_tab] / $results_per_page), 1);
+$page = intval($_GET['p']);
+if (!$page) {
+       $page = 1;
+}      
+$count  = (($page-1) * $results_per_page) + 1;
+$offset = ($page-1)*$results_per_page;
+$sql .= " LIMIT $offset, $results_per_page";
+
+$enrollment_result = mysql_query($sql, $db);
+$page_string_w_tab = $page_string . SEP . 'tab='.$current_tab;
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+       <input type="hidden" name="tab" value="<?php echo $current_tab; ?>"/>
+       <input type="hidden" name="course_id" value="<?php echo $course_id; ?>"/>
+       <div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('search'); ?></legend>
+               <?php if (admin_authenticate(AT_ADMIN_PRIV_ENROLLMENT, TRUE)): ?>
+                       <div class="row">
+                               <label for="course"><?php echo _AT('course'); ?></label><br/>
+                               <select name="course_id" id="course">
+                               <?php
+                               $sql = "SELECT course_id, title FROM ".TABLE_PREFIX."courses ORDER BY title";
+                               $result = mysql_query($sql, $db);
+                               while ($courses_row = mysql_fetch_assoc($result)) {
+                                       if ($courses_row['course_id'] == $course_id) {
+                                               echo '<option value="'.$courses_row['course_id'].'" selected="selected">'.validate_length($courses_row['title'], 45,VALIDATE_LENGTH_FOR_DISPLAY).'</option>';
+                                       } else {
+                                               echo '<option value="'.$courses_row['course_id'].'">'.validate_length($courses_row['title'],45,VALIDATE_LENGTH_FOR_DISPLAY).'</option>';
+                                       }
+                               }
+                               ?></select>
+                       </div>
+               <?php endif; ?>
+
+               <div class="row">
+                       <label for="search"><?php echo _AT('search'); ?> (<?php echo _AT('login_name').', '._AT('first_name').', '._AT('second_name').', '._AT('last_name') .', '._AT('email'); ?>)</label><br />
+                       <input type="text" name="search" id="search" size="40" value="<?php echo htmlspecialchars($_GET['search']); ?>" />
+                       <br/>
+                       <?php echo _AT('search_match'); ?>:
+                       <input type="radio" name="match" value="all" id="match_all" <?php echo $checked_match_all; ?> /><label for="match_all"><?php echo _AT('search_all_words'); ?></label> <input type="radio" name="match" value="one" id="match_one" <?php echo $checked_match_one; ?> /><label for="match_one"><?php echo _AT('search_any_word'); ?></label>
+               </div>
+
+               <div class="row buttons">
+                       <input type="submit" name="filter" value="<?php echo _AT('filter'); ?>" />
+                       <input type="submit" name="reset_filter" value="<?php echo _AT('reset_filter'); ?>" />
+               </div>
+       </fieldset>
+       </div>
+</form>
+
+<?php print_paginator($page, $tab_counts[$current_tab], $page_string_w_tab . SEP . $order .'='. $col, $results_per_page); ?>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="selectform">
+<input type="hidden" name="tab" value="<?php echo $current_tab; ?>" />
+<input type="hidden" name="course_id" value="<?php echo $course_id; ?>"/>
+<div style="width: 95%; margin-right: auto; margin-left: auto;">
+<ul id="navlist">
+       <?php for ($i = 0; $i< $num_tabs; $i++): ?>
+               <?php if ($current_tab == $i): ?>
+                       <li><a href="<?php echo $_SERVER['PHP_SELF']; ?>?tab=<?php echo $i.$page_string; ?>" class="active"><strong><?php echo _AT($tabs[$i]); ?> - <?php echo $tab_counts[$i]; ?></strong></a></li>
+               <?php else: ?>
+                       <li><a href="<?php echo $_SERVER['PHP_SELF']; ?>?tab=<?php echo $i.$page_string; ?>"><?php echo _AT($tabs[$i]); ?> - <?php echo $tab_counts[$i]; ?></a></li>
+               <?php endif; ?>
+       <?php endfor; ?>
+</ul>
+</div>
+
+<table class="data" style="width:95%;" summary="" rules="cols">
+<colgroup>
+       <?php if ($col == 'login'): ?>
+               <col />
+               <col class="sort" />
+               <col span="4" />
+       <?php elseif($col == 'first_name'): ?>
+               <col span="2" />
+               <col class="sort" />
+               <col span="3" />
+       <?php elseif($col == 'second_name'): ?>
+               <col span="3" />
+               <col class="sort" />
+               <col span="2" />
+       <?php elseif($col == 'last_name'): ?>
+               <col span="4" />
+               <col class="sort" />
+               <col />
+       <?php elseif($col == 'email'): ?>
+               <col span="5" />
+               <col class="sort" />
+       <?php endif; ?>
+</colgroup>
+<thead>
+<tr>
+       <th scope="col" align="left"><input type="checkbox" value="<?php echo _AT('select_all'); ?>" id="all" title="<?php echo _AT('select_all'); ?>" name="selectall" onclick="CheckAll();" /></th>
+
+       <th scope="col"><a href="<?php echo $_SERVER['PHP_SELF']; ?>?<?php echo $orders[$order]; ?>=login<?php echo $page_string_w_tab;?>"><?php echo _AT('login_name'); ?></a></th>
+
+       <th scope="col"><a href="<?php echo $_SERVER['PHP_SELF']; ?>?<?php echo $orders[$order]; ?>=first_name<?php echo $page_string_w_tab;?>"><?php echo _AT('first_name'); ?></a></th>
+
+       <th scope="col"><a href="<?php echo $_SERVER['PHP_SELF']; ?>?<?php echo $orders[$order]; ?>=second_name<?php echo $page_string_w_tab;?>"><?php echo _AT('second_name'); ?></a></th>
+
+       <th scope="col"><a href="<?php echo $_SERVER['PHP_SELF']; ?>?<?php echo $orders[$order]; ?>=last_name<?php echo $page_string_w_tab;?>"><?php echo _AT('last_name'); ?></a></th>
+
+       <th scope="col"><a href="<?php echo $_SERVER['PHP_SELF']; ?>?<?php echo $orders[$order]; ?>=email<?php echo $page_string_w_tab;?>"><?php echo _AT('email'); ?></a></th>
+</tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="6">
+               <?php if ($current_tab == 0): ?>
+                       <input type="submit" name="role"     value="<?php echo _AT('privileges');  ?>" /> 
+                       <input type="submit" name="unenroll" value="<?php echo _AT('remove');    ?>" /> 
+                       <input type="submit" name="alumni"   value="<?php echo _AT('mark_alumni'); ?>" />
+               <?php elseif ($current_tab == 1): ?>
+                       <input type="submit" name="role" value="<?php echo _AT('privileges'); ?>" /> 
+                       <input type="submit" name="unenroll" value="<?php echo _AT('remove'); ?>" /> 
+
+               <?php elseif ($current_tab == 2): ?>
+                       <input type="submit" name="enroll"   value="<?php echo _AT('enroll'); ?>" /> 
+                       <input type="submit" name="unenroll" value="<?php echo _AT('remove'); ?>" />
+               
+               <?php elseif ($current_tab == 3): ?>
+                       <input type="submit" name="enroll" value="<?php echo _AT('enroll'); ?>" /> 
+                       <input type="submit" name="unenroll" value="<?php echo _AT('remove'); ?>" />
+
+               <?php elseif ($current_tab == 4): ?>
+                       <input type="submit" name="enroll"   value="<?php echo _AT('enroll'); ?>" /> 
+
+               <?php endif; ?></td>
+</tr>
+</tfoot>
+<tbody>
+<?php if ($tab_counts[$current_tab]): ?>
+       <?php while ($row = mysql_fetch_assoc($enrollment_result)): ?>
+               <tr onmousedown="document.selectform['m<?php echo $row['member_id']; ?>'].checked = !document.selectform['m<?php echo $row['member_id']; ?>'].checked; togglerowhighlight(this, 'm<?php echo $row['member_id']; ?>');" id="rm<?php echo $row['member_id']; ?>">
+                       <td><input type="checkbox" name="id[]" value="<?php echo $row['member_id']; ?>" id="m<?php echo $row['member_id']; ?>" onmouseup="this.checked=!this.checked" title="<?php echo AT_print($row['login'], 'members.login'); ?>" /></td>
+                       <td><?php echo AT_print($row['login'], 'members.login'); ?></td>
+                       <td><?php echo AT_print($row['first_name'], 'members.name'); ?></td>
+                       <td><?php echo AT_print($row['second_name'], 'members.name'); ?></td>
+                       <td><?php echo AT_print($row['last_name'], 'members.name'); ?></td>
+                       <td><?php echo AT_print($row['email'], 'members.email'); ?></td>
+               </tr>
+       <?php endwhile; ?>
+<?php else: ?>
+       <tr>
+               <td colspan="6"><?php echo _AT('none_found'); ?></td>
+       </tr>
+<?php endif; ?>
+</tbody>
+</table>
+</form>
+
+<script language="JavaScript" type="text/javascript">
+//<!--
+function CheckAll() {
+       for (var i=0;i<document.selectform.elements.length;i++) {
+               var e = document.selectform.elements[i];
+               if ((e.name == 'id[]') && (e.type=='checkbox')) {
+                       e.checked = document.selectform.selectall.checked;
+                       togglerowhighlight(document.getElementById("r" + e.id), e.id);
+               }
+       }
+}
+
+function togglerowhighlight(obj, boxid) {
+       if (document.getElementById(boxid).checked) {
+               obj.className = 'selected';
+       } else {
+               obj.className = '';
+       }
+}
+//-->
+</script>
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/include/html/filemanager_display.inc.php b/include/html/filemanager_display.inc.php
new file mode 100644 (file)
index 0000000..8f6f768
--- /dev/null
@@ -0,0 +1,399 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id: filemanager.php 5078 2005-07-06 14:16:53Z joel $
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+function get_file_extension($file_name) {
+       $ext = pathinfo($file_name);
+       return $ext['extension'];
+}
+
+function get_file_type_icon($file_name) {
+       static $mime;
+
+       $ext = get_file_extension($file_name);
+
+       if (!isset($mime)) {
+               require(AT_INCLUDE_PATH .'lib/mime.inc.php');
+       }
+
+       if (isset($mime[$ext]) && $mime[$ext][1]) {
+               return $mime[$ext][1];
+       }
+       return 'generic';
+}
+
+function get_relative_path($src, $dest) {
+       if ($src == '') {
+               $path = $dest;
+       } else if (substr($dest, 0, strlen($src)) == $src) {
+               $path = substr($dest, strlen($src) + 1);
+       } else {
+               $path = '../' . $dest;
+       }
+
+       return $path;
+}
+
+// get the course total in Bytes 
+$course_total = dirsize($current_path);
+
+$framed = intval($_GET['framed']);
+$popup = intval($_GET['popup']);
+
+if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+       $get_file = 'get.php/';
+} else {
+       $get_file = 'content/' . $_SESSION['course_id'] . '/';
+}
+
+echo '<p>'._AT('current_path').' ';
+
+if ($pathext != '') {
+       echo '<a href="'.$_SERVER['PHP_SELF'].'?popup=' . $popup . SEP . 'framed=' . $framed.'">'._AT('home').'</a> ';
+}
+else {
+       echo _AT('home');
+}
+
+if ($pathext == '') {
+       $pathext = urlencode($_POST['pathext']);
+}
+
+if ($pathext != '') {
+       $bits = explode('/', $pathext);
+
+       foreach ($bits as $bit) {
+               if ($bit != '') {
+                       $bit_path .= $bit . '/';
+                       echo ' / ';
+
+                       if ($bit_path == $pathext) {
+                               echo $bit;
+                       } else {
+                               echo '<a href="'.$_SERVER['PHP_SELF'].'?pathext=' . urlencode($bit_path) . SEP . 'popup=' . $popup . SEP . 'framed=' . $framed . '">' . $bit . '</a>';
+                       }
+               }
+       }
+       $bit_path = "";
+       $bit = "";
+}
+echo '</p>';
+
+if ($popup == TRUE) {
+       $totalcol = 6;
+} else {
+       $totalcol = 5;
+}
+$labelcol = 3;
+
+if (TRUE || $framed != TRUE) {
+       if ($_GET['overwrite'] != '') {
+               // get file name, out of the full path
+               $path_parts = pathinfo($current_path.$_GET['overwrite']);
+
+               if (!file_exists($path_parts['dirname'].'/'.$pathext.$path_parts['basename'])
+                       || !file_exists($path_parts['dirname'].'/'.$pathext.substr($path_parts['basename'], 5))) {
+                       /* source and/or destination does not exist */
+                       $msg->addErrors('CANNOT_OVERWRITE_FILE');
+               } else {
+                       @unlink($path_parts['dirname'].'/'.$pathext.substr($path_parts['basename'], 5));
+                       $result = @rename($path_parts['dirname'].'/'.$pathext.$path_parts['basename'], $path_parts['dirname'].'/'.$pathext.substr($path_parts['basename'], 5));
+
+                       if ($result) {
+                               $msg->addFeedback('FILE_OVERWRITE');
+                       } else {
+                               $msg->addErrors('CANNOT_OVERWRITE_FILE');
+                       }
+               }
+       }
+       // filemanager listing table
+       // make new directory 
+       echo '<fieldset class="group_form"><legend class="group_form">'._AT('add').'</legend>';
+       echo '<table cellspacing="1" cellpadding="0" border="0" summary="" align="center">';
+       echo '<tr><td colspan="2">';
+       echo '<form name="form1" method="post" action="'.$_SERVER['PHP_SELF'].'?pathext='.urlencode($pathext).SEP. 'popup='.$popup.'">';
+       if( $MakeDirOn ) {
+               if ($depth < $MaxDirDepth) {
+                       echo '<input type="text" name="dirname" size="20" /> ';
+                       echo '<input type="hidden" name="mkdir_value" value="true" /> ';
+                       echo '<input type="submit" name="mkdir" value="'._AT('create_folder').'" class="button" />';
+                       echo '&nbsp;<small class="spacer">'._AT('keep_it_short').'';
+               } else {
+                       echo _AT('depth_reached');
+               }
+       }
+       echo '<input type="hidden" name="pathext" value="'.$pathext.'" />';
+       echo '</form></td></tr>';
+
+       $my_MaxCourseSize = $system_courses[$_SESSION['course_id']]['max_quota'];
+
+       // upload file 
+       if (($my_MaxCourseSize == AT_COURSESIZE_UNLIMITED) 
+               || (($my_MaxCourseSize == AT_COURSESIZE_DEFAULT) && ($course_total < $MaxCourseSize))
+               || ($my_MaxCourseSize-$course_total > 0)) {
+               echo '<tr><td  colspan="1">';
+               echo '<form onsubmit="openWindow(\''.AT_BASE_HREF.'tools/prog.php\');" name="form1" method="post" action="tools/filemanager/upload.php?popup='.$popup.'" enctype="multipart/form-data">';
+               echo '<input type="hidden" name="MAX_FILE_SIZE" value="'.$my_MaxFileSize.'" />';
+               echo '<input type="file" name="uploadedfile" class="formfield" size="20" />';
+               echo '<input type="submit" name="submit" value="'._AT('upload').'" class="button" />';
+               echo '<input type="hidden" name="pathext" value="'.$pathext.'" />  ';
+               echo _AT('or'); 
+               echo ' <a href="tools/filemanager/new.php?pathext=' . urlencode($pathext) . SEP . 'framed=' . $framed . SEP . 'popup=' . $popup . '">' . _AT('file_manager_new') . '</a>';
+
+               if ($popup == TRUE) {
+                       echo '<input type="hidden" name="popup" value="1" />';
+               }
+               echo '</form>';
+               echo '</td></tr></table></fieldset>';
+
+       } else {
+               echo '</table>';
+               echo '</fieldset>';
+               $msg->printInfos('OVER_QUOTA');
+       }
+       echo '<br />';
+}
+// Directory and File listing 
+
+echo '<form name="checkform" action="'.$_SERVER['PHP_SELF'].'?pathext='.urlencode($pathext).SEP.'popup='.$popup .SEP. 'framed='.$framed.'" method="post">';
+echo '<input type="hidden" name="pathext" value ="'.$pathext.'" />';
+?>
+<table class="data static" summary="" border="0" rules="groups" style="width: 90%">
+<thead>
+<tr>
+       <th scope="col"><input type="checkbox" name="checkall" onclick="Checkall(checkform);" id="selectall" title="<?php echo _AT('select_all'); ?>" /></th>
+       <th>&nbsp;</th>
+       <th scope="col"><?php echo _AT('name');   ?></th>
+       <th scope="col"><?php echo _AT('date');   ?></th>
+       <th scope="col"><?php echo _AT('size');   ?></th>
+</tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="5"><input type="submit" name="rename" value="<?php echo _AT('rename'); ?>" /> 
+               <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /> 
+               <input type="submit" name="move"   value="<?php echo _AT('move'); ?>" /></td>
+</tr>
+<tr>
+       <td colspan="4" align="right"><strong><?php echo _AT('directory_total'); ?>:</strong></td>
+       <td align="right">&nbsp;<strong><?php echo get_human_size(dirsize($current_path.$pathext.$file.'/')); ?></strong>&nbsp;</td>
+</tr>
+<tr>
+       <td colspan="4" align="right"><strong><?php echo _AT('course_total'); ?>:</strong></td>
+       <td align="right">&nbsp;<strong><?php echo get_human_size($course_total); ?></strong>&nbsp;</td>
+</tr>
+<tr>
+       <td colspan="4" align="right"><strong><?php echo _AT('course_available'); ?>:</strong></td>
+       <td align="right"><strong><?php
+               if ($my_MaxCourseSize == AT_COURSESIZE_UNLIMITED) {
+                       echo _AT('unlimited');
+               } else if ($my_MaxCourseSize == AT_COURSESIZE_DEFAULT) {
+                       echo get_human_size($MaxCourseSize-$course_total);
+               } else {
+                       echo get_human_size($my_MaxCourseSize-$course_total);
+               } ?></strong>&nbsp;</td>
+</tr>
+</tfoot>
+<?php if($pathext) : ?>
+       <tr>
+               <td colspan="5"><a href="<?php echo $_SERVER['PHP_SELF'].'?back=1'.SEP.'pathext='.$pathext.SEP. 'popup=' . $popup .SEP. 'framed=' . $framed .SEP.'cp='.$_GET['cp']; ?>"><img src="images/arrowicon.gif" border="0" height="11" width="10" alt="" /> <?php echo _AT('back'); ?></a></td>
+       </tr>
+<?php endif; ?>
+<?php
+$totalBytes = 0;
+
+// loop through folder to get files and directory listing
+while (false !== ($file = readdir($dir)) ) {
+
+       // if the name is not a directory 
+       if( ($file == '.') || ($file == '..') ) {
+               continue;
+       }
+
+       // get some info about the file
+       $filedata = stat($current_path.$pathext.$file);
+       $path_parts = pathinfo($file);
+       $ext = strtolower($path_parts['extension']);
+
+       $is_dir = false;
+
+       // if it is a directory change the file name to a directory link 
+       if(is_dir($current_path.$pathext.$file)) {
+               $size = dirsize($current_path.$pathext.$file.'/');
+               $totalBytes += $size;
+               $filename = '<a href="'.$_SERVER['PHP_SELF'].'?pathext='.urlencode($pathext.$file.'/'). SEP . 'popup=' . $popup . SEP . 'framed='. $framed . SEP.'cp='.$_GET['cp'].'">'.$file.'</a>';
+               $fileicon = '&nbsp;';
+               $fileicon .= '<img src="images/folder.gif" alt="'._AT('folder').':'.$file.'" height="18" width="20" class="img-size-fm1" />';
+               $fileicon .= '&nbsp;';
+               if(!$MakeDirOn) {
+                       $deletelink = '';
+               }
+
+               $is_dir = true;
+       } else if ($ext == 'zip') {
+
+               $totalBytes += $filedata[7];
+               $filename = $file;
+               $fileicon = '&nbsp;<img src="images/icon-zip.gif" alt="'._AT('zip_archive').':'.$file.'" height="16" width="16" border="0" class="img-size-fm2" />&nbsp;';
+
+       } else {
+               $totalBytes += $filedata[7];
+               $filename = $file;
+               $fileicon = '&nbsp;<img src="images/file_types/'.get_file_type_icon($filename).'.gif" height="16" width="16" alt="" title="" class="img-size-fm2" />&nbsp;';
+       } 
+       $file1 = strtolower($file);
+       // create listing for dirctor or file
+       if ($is_dir) {
+               
+               $dirs[$file1] .= '<tr><td  align="center" width="0%">';
+               $dirs[$file1] .= '<input type="checkbox" id="'.$file.'" value="'.$file.'" name="check[]"/></td>';
+               $dirs[$file1] .= '<td  align="center"><label for="'.$file.'" >'.$fileicon.'</label></td>';
+               $dirs[$file1] .= '<td >&nbsp;';
+               $dirs[$file1] .= $filename.'</td>';
+
+               $dirs[$file1] .= '<td  align="right">&nbsp;';
+               $dirs[$file1] .= AT_date(_AT('filemanager_date_format'), $filedata[10], AT_DATE_UNIX_TIMESTAMP);
+               $dirs[$file1] .= '&nbsp;</td>';
+
+               $dirs[$file1] .= '<td  align="right">';
+               $dirs[$file1] .= get_human_size($size).'</td>';
+               
+       } else {
+               $files[$file1] .= '<tr> <td  align="center">';
+               $files[$file1] .= '<input type="checkbox" id="'.$file.'" value="'.$file.'" name="check[]"/> </td>';
+               $files[$file1] .= '<td  align="center"><label for="'.$file.'">'.$fileicon.'</label></td>';
+               $files[$file1] .= '<td >&nbsp;';
+
+               if ($framed) {
+                       $files[$file1] .= '<a href="'.$get_file.$pathext.urlencode($filename).'">'.$filename.'</a>';
+               } else {
+                       $files[$file1] .= '<a href="tools/filemanager/preview.php?file='.$pathext.$filename.SEP.'pathext='.urlencode($pathext).SEP.'popup='.$popup.'">'.$filename.'</a>';
+               }
+
+               if ($ext == 'zip') {
+                       $files[$file1] .= ' <a href="tools/filemanager/zip.php?pathext=' . urlencode($pathext) . SEP . 'file=' . urlencode($file) . SEP . 'popup=' . $popup . SEP . 'framed=' . $framed .'">';
+                       $files[$file1] .= '<img src="images/archive.gif" border="0" alt="'._AT('extract_archive').'" title="'._AT('extract_archive').'"height="16" width="11" class="img-size-fm3" />';
+                       $files[$file1] .= '</a>';
+               }
+
+               if (in_array($ext, $editable_file_types)) {
+                       $files[$file1] .= ' <a href="tools/filemanager/edit.php?pathext=' . urlencode($pathext) . SEP . 'popup=' . $popup . SEP . 'framed=' . $framed . SEP . 'file=' . $file . '">';
+                       $files[$file1] .= '<img src="images/edit.gif" border="0" alt="'._AT('extract_archive').'" title="'._AT('edit').'" height="15" width="18" class="img-size-fm4" />';
+                       $files[$file1] .= '</a>';
+               }
+
+               $files[$file1] .= '&nbsp;</td>';
+
+               $files[$file1] .= '<td  align="right" style="white-space:nowrap">';
+
+               if ($popup == TRUE) {
+                       $files[$file1] .= '<input class="button" type="button" name="insert" value="' ._AT('insert') . '" onclick="javascript:insertFile(\'' . $file . '\', \'' . get_relative_path($_GET['cp'], $pathext) . '\', \'' . $ext . '\');" />&nbsp;';
+               }
+
+               $files[$file1] .= AT_date(_AT('filemanager_date_format'), $filedata[10], AT_DATE_UNIX_TIMESTAMP);
+               $files[$file1] .= '&nbsp;</td>';
+               
+               $files[$file1] .= '<td  align="right" style="white-space:nowrap">';
+               $files[$file1] .= get_human_size($filedata[7]).'</td>';
+       }
+} // end while
+
+// sort listing and output directories
+if (is_array($dirs)) {
+       ksort($dirs, SORT_STRING);
+       foreach($dirs as $x => $y) {
+               echo $y;
+       }
+}
+
+//sort listing and output files
+if (is_array($files)) {
+       ksort($files, SORT_STRING);
+       foreach($files as $x => $y) {
+               echo $y;
+       }
+}
+
+
+echo '</table></form>';
+?>
+
+<script type="text/javascript">
+//<!--
+function insertFile(fileName, pathTo, ext) { 
+
+       // pathTo + fileName should be relative to current path (specified by the Content Package Path)
+
+       if (ext == "gif" || ext == "jpg" || ext == "jpeg" || ext == "png") {
+               var info = "<?php echo _AT('alternate_text'); ?>";
+               var html = '<img src="' + pathTo+fileName + '" border="0" alt="' + info + '" />';
+
+               if (window.opener.document.form.setvisual.value == 1) {
+                       if (window.parent.tinyMCE)
+                               window.parent.tinyMCE.execCommand('mceInsertContent', false, html);
+
+                       if (window.opener.tinyMCE)
+                               window.opener.tinyMCE.execCommand('mceInsertContent', false, html);
+               } else {
+                       insertAtCursor(window.opener.document.form.body_text, html);
+               }
+       } else if (ext == "mpg" || ext == "avi" || ext == "wmv" || ext == "mov" || ext == "swf" || ext == "mp3" || ext == "wav" || ext == "ogg" || ext == "mid") {
+               var html = '[media]'+ pathTo + fileName + '[/media]';
+               if (window.opener.document.form.setvisual.value == 1) {
+                       if (window.parent.tinyMCE)
+                               window.parent.tinyMCE.execCommand('mceInsertContent', false, html);
+
+                       if (window.opener.tinyMCE)
+                               window.opener.tinyMCE.execCommand('mceInsertContent', false, html);
+               } else {
+                       insertAtCursor(window.opener.document.form.body_text, html);
+               }
+       } else {
+               var info = "<?php echo _AT('put_link'); ?>";
+               var html = '<a href="' + pathTo+fileName + '">' + info + '</a>';
+
+               if (window.opener.document.form.setvisual.value == 1) {
+                       if (window.parent.tinyMCE)
+                               window.parent.tinyMCE.execCommand('mceInsertContent', false, html);
+
+                       if (window.opener.tinyMCE)
+                               window.opener.tinyMCE.execCommand('mceInsertContent', false, html);
+               } else {
+                       insertAtCursor(window.opener.document.form.body_text, html);
+               }
+       }
+}
+function insertAtCursor(myField, myValue) {
+       //IE support
+       if (window.opener.document.selection) {
+               myField.focus();
+               sel = window.opener.document.selection.createRange();
+               sel.text = myValue;
+       }
+       //MOZILLA/NETSCAPE support
+       else if (myField.selectionStart || myField.selectionStart == '0') {
+               var startPos = myField.selectionStart;
+               var endPos = myField.selectionEnd;
+               myField.value = myField.value.substring(0, startPos)
+               + myValue
+               + myField.value.substring(endPos, myField.value.length);
+               myField.focus();
+       } else {
+               myField.value += myValue;
+               myField.focus();
+       }
+}
+//-->
+</script>
\ No newline at end of file
diff --git a/include/html/forum.inc.php b/include/html/forum.inc.php
new file mode 100644 (file)
index 0000000..9e01793
--- /dev/null
@@ -0,0 +1,195 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+$sql   = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."forums_threads WHERE parent_id=0 AND forum_id=$fid";
+$result        = mysql_query($sql, $db);
+$num_threads = mysql_fetch_assoc($result);
+$num_threads = $num_threads['cnt'];
+
+$num_per_page = 10;
+if (!$_GET['page']) {
+       $page = 1;
+} else {
+       $page = intval($_GET['page']);
+}
+$start = ($page-1)*$num_per_page;
+$num_pages = ceil($num_threads/$num_per_page);
+$page_string = SEP.'fid='. $fid;
+
+$orders = array('asc' => 'desc', 'desc' => 'asc');
+$cols   = array('subject' => 1, 'num_comments' => 1, 'last_comment' => 1);
+
+if (isset($_GET['asc'])) {
+       $order = 'asc';
+       $col   = isset($cols[$_GET['asc']]) ? $_GET['asc'] : 'last_comment';
+} else if (isset($_GET['desc'])) {
+       $order = 'desc';
+       $col   = isset($cols[$_GET['desc']]) ? $_GET['desc'] : 'last_comment';
+} else {
+       // no order set
+       $order = 'desc';
+       $col   = 'last_comment';
+}
+
+$sql   = "SELECT *, last_comment + 0 AS stamp, DATE_FORMAT(last_comment, '%Y-%m-%d %H-%i:%s') AS last_comment FROM ".TABLE_PREFIX."forums_threads WHERE parent_id=0 AND forum_id=$fid AND member_id>0 ORDER BY sticky DESC, $col $order LIMIT $start,$num_per_page";
+$result        = mysql_query($sql, $db);
+
+if (!($row = mysql_fetch_assoc($result))) {
+       $msg->printInfos('NO_POSTS_FOUND');
+       return;
+}
+?>
+<table class="data static" summary="" rules="rows">
+<colgroup>
+       <?php if ($col == 'subject'): ?>
+               <col class="sort" />
+               <col span="4" />
+       <?php elseif($col == 'num_comments'): ?>
+               <col  />
+               <col class="sort" />
+               <col span="3" />
+       <?php elseif($col == 'last_comment'): ?>
+               <col span="3" />
+               <col class="sort" />
+               <col />
+       <?php endif; ?>
+</colgroup>
+<thead>
+<tr>
+       <th scope="col"><a href="<?php echo url_rewrite($_SERVER['PHP_SELF']."?$orders[$order]=subject$page_string"); ?>"><?php echo _AT('topic'); ?></a></th>
+       <th scope="col"><a href="<?php echo url_rewrite($_SERVER['PHP_SELF']."?$orders[$order]=num_comments$page_string"); ?>"><?php echo _AT('replies'); ?></a></th>
+       <th scope="col"><?php echo _AT('started_by'); ?></th>
+       <th scope="col"><a href="<?php echo url_rewrite($_SERVER['PHP_SELF']."?$orders[$order]=last_comment$page_string"); ?>"><?php echo _AT('last_comment'); ?></a></th>
+<?php
+       $colspan = 4;
+       if (authenticate(AT_PRIV_FORUMS, AT_PRIV_RETURN)) {
+               echo '<th class="cat">&nbsp;</th>';
+               $colspan++;
+       }
+
+       echo '</tr>';
+       echo '</thead>';
+       echo '<tfoot>';
+       echo '<tr>';
+       echo '<td style="background-image: none" colspan="'.$colspan.'" align="right">'._AT('page').': ';
+
+       for ($i=1; $i<=$num_pages; $i++) {
+               if ($i == $page) {
+                       echo $i;
+               } else {
+                       echo '<a href="'.url_rewrite($_SERVER['PHP_SELF'].'?fid='.$fid.SEP.'page='.$i).'">'.$i.'</a>';
+               }
+
+               if ($i<$num_pages){
+                       echo ' <span class="spacer">|</span> ';
+               }
+       }
+       
+       echo '</td>';
+       echo '</tr>';
+       echo '</tfoot>';
+       echo '<tbody>';
+
+       $current_thread = $row['thread_id'];
+       do {
+               /* crop the subject, if needed */
+               $full_subject = $row['subject'];        //save a copy before croping
+               if ($strlen($row['subject']) > 28) {
+                       $row['subject'] = $substr($row['subject'], 0, 25).'...';
+               }
+               $row['subject'] = AT_print($row['subject'], 'forums_threads.subject');
+               echo '<tr>';
+               echo '<td>';
+
+               if ($_SESSION['valid_user']) {
+                       if ($row['stamp'] > $last_accessed[$row['post_id']]['last_accessed']) {
+                               echo '<i style="color: green; font-weight: bold; font-size: .7em;" title="'._AT('new_thread').'">'._AT('new').'</i> ';
+                       }
+               }
+
+               if ($row['num_comments'] > 10) {
+                       echo '<em style="color: red; font-weight: bold; font-size: .7em;" title="'._AT('hot_thread').'">'._AT('hot').'</em> ';
+               }
+
+               if ($row['locked'] != 0) {
+                       echo '<img src="images/topic_lock.gif" alt="'._AT('thread_locked').'" class="menuimage3" title="'._AT('thread_locked').'" /> ';
+               }
+               
+               if ($row['sticky'] != 0) {
+                       echo '<img src="images/forum/topic_stick.gif" alt="'._AT('sticky_thread').'" class="menuimage3"  title="'._AT('sticky_thread').'" /> ';
+               }
+               
+               if ($row['locked'] != 1) {
+                               echo '<a href="'.url_rewrite('forum/view.php?fid='.$fid.SEP.'pid='.$row['post_id']).'" title="'.$full_subject.'">'.$row['subject'].'</a>';
+
+                       if ($row['locked'] == 2) {
+                               echo ' <i class="spacer">('._AT('post_lock').')</i>';
+                       }
+               } else {
+                       echo $row['subject'].' <i class="spacer">('._AT('read_lock').')</i>';
+               }
+
+               /* print page numbers */
+               $num_pages_2 = ceil(($row['num_comments']+1)/$num_per_page);
+
+               if ($num_pages_2 > 1) {
+                       echo ' <small class="spacer">( Page: ';
+                       for ($i=2; $i<=$num_pages_2; $i++) {
+                               echo '<a href="'.url_rewrite('forum/view.php?fid='.$fid.SEP.'pid='.$row['post_id'].SEP.'page='.$i).'" title="'.$full_subject.'">'.$i.'</a>';
+
+                               if ($i<$num_pages_2){
+                                       echo ' | ';
+                               }
+                       }
+                       echo ' )</small> ';
+               }
+               if ($_SESSION['enroll'] && !$row['locked']) {
+                       if (isset($last_accessed[$row['post_id']]) && $last_accessed[$row['post_id']]['subscribe']){
+                               echo  ' <br /><small><a href="forum/subscribe.php?us=1'.SEP.'pid='.$row['post_id'].SEP.'fid='.$fid.SEP.'t=1">('._AT('unsubscribe1').')</a></small>';
+                       } else {
+                               echo  ' <br /><small><a href="forum/subscribe.php?pid='.$row['post_id'].SEP.'fid='.$fid.SEP.'t=1">('._AT('subscribe1').')</a></small>';
+                       }
+               }
+               echo '</td>';
+
+               echo '<td width="10%" align="center">'.$row['num_comments'].'</td>';
+
+               echo '<td width="10%"><a href="'.AT_BASE_HREF.'profile.php?id='.$row['member_id'].'">'.get_display_name($row['member_id']).'</a></td>';
+
+               echo '<td width="20%" align="right" nowrap="nowrap">';
+               echo AT_date(_AT('forum_date_format'), $row['last_comment'], AT_DATE_MYSQL_DATETIME);
+               echo '</td>';
+
+               if (authenticate(AT_PRIV_FORUMS, AT_PRIV_RETURN)) {
+                       echo '<td nowrap="nowrap">';
+                       echo ' <a href="forum/stick.php?fid='.$fid.SEP.'pid='.$row['post_id'].'"><img src="images/forum/sticky.gif" border="0" alt="'._AT('sticky_thread').'" title="'._AT('sticky_thread').'" /></a> ';
+
+                       if ($row['locked'] != 0) {
+                               echo '<a href="forum/lock_thread.php?fid='.$fid.SEP.'pid='.$row['post_id'].SEP.'unlock='.$row['locked'].'"><img src="images/unlock.gif" border="0"  alt="'._AT('unlock_thread').'" title="'._AT('unlock_thread').'"/></a>';
+                       } else {
+                               echo '<a href="forum/lock_thread.php?fid='.$fid.SEP.'pid='.$row['post_id'].'"><img src="images/lock.gif" border="0" alt="'._AT('lock_thread').'"   title="'._AT('lock_thread').'"/></a>';
+                       }
+                       echo ' <a href="forum/move_thread.php?fid='.$fid.SEP.'pid='.$row['post_id'].SEP.'ppid=0"><img src="images/forum/move.gif" border="0" alt="'._AT('move_thread').'" title="'._AT('move_thread').'"/></a>';
+
+                       echo ' <a href="forum/delete_thread.php?fid='.$fid.SEP.'pid='.$row['post_id'].SEP.'ppid=0"><img src="images/icon_delete.gif" border="0" alt="'._AT('delete_thread').'" title="'._AT('delete_thread').'"/></a>';
+                       
+                       echo '</td>';
+               }
+               echo '</tr>';
+
+       } while ($row = mysql_fetch_assoc($result));
+       echo '</tbody>';
+       echo '</table>';
+
+?>
\ No newline at end of file
diff --git a/include/html/frameset/footer.inc.php b/include/html/frameset/footer.inc.php
new file mode 100644 (file)
index 0000000..691287b
--- /dev/null
@@ -0,0 +1,2 @@
+</body>
+</html>
\ No newline at end of file
diff --git a/include/html/frameset/header.inc.php b/include/html/frameset/header.inc.php
new file mode 100644 (file)
index 0000000..a755ba2
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+?><!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="<?php echo $myLang->getCode(); ?>" lang="<?php echo $myLang->getCharacterSet(); ?>">
+<head>
+       <title>ATutor - <?php echo $_SESSION['course_title'];
+       if ($cid != 0) {
+               $myPath = $path;
+               $num_path = count($myPath);
+               for ($i =0; $i<$num_path; $i++) {
+                       echo ' - ';
+                       echo $myPath[$i]['title'];
+               }
+       } else if (is_array($_section) ) {
+               $num_sections = count($_section);
+               for($i = 0; $i < $num_sections; $i++) {
+                       echo ' - ';
+                       echo $_section[$i][0];
+               }
+       }
+       ?></title>
+       <base href="<?php echo AT_BASE_HREF; ?>" />
+       <link rel="stylesheet" href="<?php echo $_base_path; ?>themes/<?php echo $_SESSION['prefs']['PREF_THEME']; ?>/styles.css" type="text/css" />
+       <link rel="stylesheet" href="<?php echo $_base_path.'themes/'.$_SESSION['prefs']['PREF_THEME']; ?>/forms.css" type="text/css" />
+       <?php
+               
+               if ($myLang->isRTL()) {
+                       echo '<link rel="stylesheet" href="'.$_base_path.'rtl.css" type="text/css" />'."\n";
+               }
+       ?>
+       <meta http-equiv="Content-Type" content="text/html; <?php echo $myLang->getCharacterSet(); ?>" />
+</head>
+<body bgcolor="#FFFFFF">
+<div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>
+<script language="JavaScript" src="overlib.js" type="text/javascript"><!-- overLIB (c) Erik Bosrup --></script>
\ No newline at end of file
diff --git a/include/html/languages.inc.php b/include/html/languages.inc.php
new file mode 100644 (file)
index 0000000..c9f818b
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+global $languageManager, $_my_uri;
+
+if($languageManager->getNumLanguages() < 2){
+       return;
+}
+?>
+<div align="center" id="language" style="clear: left"><br /><?php
+
+       if ($languageManager->getNumLanguages() > 5) {
+               echo '<form method="get" action="'.htmlspecialchars($_my_uri, ENT_QUOTES).'">';
+               echo '<label for="lang" style="display:none;">'._AT('translate_to').' </label>';
+               $languageManager->printDropdown($_SESSION['lang'], 'lang', 'lang');
+               echo ' <input type="submit" name="submit_language" class="button" value="'._AT('translate').'" />';
+               echo '</form>';
+       } else {
+               echo '<small><label for="lang">'._AT('translate_to').' </label></small>';
+               $languageManager->printList($_SESSION['lang'], 'lang', 'lang', htmlspecialchars($_my_uri));
+       }
+?></div>
\ No newline at end of file
diff --git a/include/html/new_thread.inc.php b/include/html/new_thread.inc.php
new file mode 100644 (file)
index 0000000..d55bbe5
--- /dev/null
@@ -0,0 +1,100 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+if (!$_SESSION['valid_user']) {
+       $msg->printInfos('LOGIN_TO_POST');
+       return;
+}
+
+$msg->printErrors();
+
+if ($_POST['submit']) {
+       $subject        = $_POST['subject'];
+       $body           = $_POST['body'];
+       $parent_id      = $_POST['parent_id'];
+       $parent_name    = $_POST['parent_name'];
+       //post reply is set when there is an error occuring.
+       if ($_POST['reply']!=''){
+               $saved_post['body'] = $_POST['replytext'];
+       }
+} else if ($_GET['reply'] != '') {
+       $subject = $saved_post['subject'];
+
+       if (substr($subject, 0, 3) != 'Re:') {
+               $subject = 'Re: '.$subject;
+       }
+}
+
+?>
+<a name="post"></a>
+<form action="forum/new_thread.php" method="post" name="form">
+<input name="parent_id" type="hidden" value="<?php echo $parent_id; ?>" />
+<input name="fid" type="hidden" value="<?php echo $fid; ?>" />
+<input name="reply" type="hidden" value="<?php echo $_REQUEST['reply']; ?>" />
+<input name="page" type="hidden" value="<?php echo $_GET['page']; ?>" />
+<input name="parent_name" type="hidden" value="<?php echo urlencode($parent_name); ?>" />
+
+<a name="post"></a>
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('post_message'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="subject"><?php echo _AT('subject'); ?></label><br />
+               <input type="text" maxlength="80" name="subject" size="36" value="<?php echo stripslashes(htmlspecialchars($subject)); ?>" id="subject" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="body"><?php echo _AT('body'); ?></label><br />
+               <textarea cols="45" name="body" rows="10" id="body"><?php echo $body; ?></textarea>
+
+               <small class="spacer"><br />&middot; <?php echo _AT('forum_links'); ?><br />
+               &middot; <?php echo _AT('forum_email_links'); ?><br />
+               &middot; <?php echo _AT('forum_html_disabled'); ?></small>
+       </div>
+
+       <?php if ($_REQUEST['reply']): ?>
+               <div class="row">
+                       <label for="body"><?php echo _AT('forum_reply_to'); ?></label><br />
+                       <textarea cols="45" name="replytext" rows="5"><?php echo $saved_post['body']; ?></textarea>
+               </div>
+
+       <?php endif; ?>
+
+       <div class="row">       
+               <a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#jumpcodes" title="<?php echo _AT('jump_codes'); ?>"><img src="images/clr.gif" height="1" width="1" alt="<?php echo _AT('jump_codes'); ?>" border="0" /></a><?php require(AT_INCLUDE_PATH.'html/code_picker.inc.php'); ?>
+
+               <a name="jumpcodes"></a>
+       </div>
+
+       <?php if (!$subscribed): ?>
+               <div class="row">
+                       <input type="checkbox" name="subscribe" value="1" id="sub" />
+                       <label for="sub"><?php echo _AT('thread_subscribe'); ?></label>
+               </div>
+       <?php else: ?>
+               <div class="row">
+                       <?php echo _AT('thread_already_subscribed'); ?>
+               </div>
+       <?php endif; ?>
+</fieldset>
+       <div class="row buttons">
+               <input name="submit" accesskey="s" type="submit" value=" <?php echo _AT('post'); ?>" />
+               <?php if ($new_thread == TRUE) : ?>
+                       <input name="cancel" type="submit" value="<?php echo _AT('cancel'); ?>" />
+               <?php endif; ?>
+       </div>
+</div>
+</form>
\ No newline at end of file
diff --git a/include/html/privileges.inc.php b/include/html/privileges.inc.php
new file mode 100644 (file)
index 0000000..e65ce38
--- /dev/null
@@ -0,0 +1,160 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: enroll_edit.php 6662 2006-11-20 15:52:49Z joel $
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+$num_cols = 2;
+
+//if user wants to cancel action
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php?course_id='.$course_id);
+       exit;
+} else if (isset($_POST['submit'])) {
+
+       //update privileges     
+       $mid   = $_POST['dmid'];
+       $privs = $_POST['privs'];
+       $role  = $_POST['role'];
+
+       //loop through selected users to perform update
+       $i=0;
+       while ($mid[$i]) { 
+               change_privs(intval($mid[$i]), $privs[$i]);
+               $i++;
+       }
+
+       $msg->addFeedback('PRIVS_CHANGED');
+       header('Location: index.php?tab=1'.SEP.'course_id='.$course_id);
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
+<input type="hidden" name="course_id" value="<?php echo $course_id; ?>"/>
+<div class="input-form">
+<?php
+       //Store id's into a hidden element for use by functions
+       $j = 0;
+       while ($_GET['mid'.$j]) {
+               echo '<input type="hidden" name="dmid[]" value="'.$_GET['mid'.$j].'" />';               
+               $j++;
+       }
+
+       //loop through all the students
+for ($k = 0; $k < $j; $k++) {
+       $mem_id = intval($_GET['mid'.$k]);
+
+       //NO!!! extra check to ensure that user doesnt send in instructor for change privs
+       $sql = "SELECT CE.privileges, M.login FROM ".TABLE_PREFIX."course_enrollment CE INNER JOIN ".TABLE_PREFIX."members M USING (member_id) WHERE M.member_id=$mem_id AND CE.course_id=$course_id AND CE.approved='y'";
+
+       $result = mysql_query($sql, $db);
+       $student_row = mysql_fetch_assoc($result);
+?>
+       <div class="row">
+               <h3><?php echo $student_row['login']; ?></h3>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('privileges'); ?><br />
+                       <table width="100%" border="0" cellspacing="5" cellpadding="0" summary="">
+                       <tr>
+                       <?php           
+                       $count =0;
+                       $student_row['privileges'] = intval($student_row['privileges']);
+                       $module_list = $moduleFactory->getModules(AT_MODULE_STATUS_ENABLED, 0, TRUE);
+                       $keys = array_keys($module_list);
+                       foreach ($keys as $module_name) {
+                               $module =& $module_list[$module_name];
+                               if (!($module->getPrivilege() > 1)) {
+                                       continue;
+                               }
+                               $count++;
+                               echo '<td><label><input type="checkbox" name="privs['.$k.'][]" value="'.$module->getPrivilege().'" ';
+
+                               if (query_bit($student_row['privileges'], $module->getPrivilege())) { 
+                                       echo 'checked="checked"';
+                               } 
+
+                               echo ' />'.$module->getName().'</label></td>';
+
+                               if (!($count % $num_cols)) {
+                                       echo '</tr><tr>';
+                               }
+                       }
+                       if ($count % $num_cols) {
+                               echo '<td colspan="'.($num_cols-($count % $num_cols)).'">&nbsp;</td>';
+                       } else {
+                               echo '<td colspan="'.$num_cols.'">&nbsp;</td>';
+                       }
+                       ?>
+                       </tr>
+                       </table>
+               </div>
+<?php 
+       }//end for
+?>
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save');  ?>" accesskey="s" /> 
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel');  ?>" />
+       </div>
+</div>
+</form>
+
+<?php 
+
+/**
+* Updates the Role & Priviliges of users
+* @access  private
+* @param   int $member                 The member_id of the user whose values are to be updated
+* @param   int $privs                  value of the privileges of the user
+* @author  Joel Kronenberg
+*/
+function change_privs ($member, $privs) {
+       global $db, $course_id;
+
+       //calculate privileges
+       $privilege = 0;
+       if (!(empty($privs))) {
+               foreach ($privs as $priv) {     
+                       $privilege += intval($priv);
+               }       
+       }
+
+       /*
+       * if we're making a student a GROUP TA then we have to remove them
+       * from all the groups they may belong to. 
+       */
+       if (query_bit($privilege, AT_PRIV_GROUPS)) {
+               $group_list = implode(',', $_SESSION['groups']);
+               if ($group_list) {
+                       $sql = "DELETE FROM ".TABLE_PREFIX."groups_members WHERE group_id IN ($group_list) AND member_id=$member";
+                       $result = mysql_query($sql,$db);
+               }
+       }
+
+       $sql = "UPDATE ".TABLE_PREFIX."course_enrollment SET `privileges`=$privilege WHERE member_id=$member AND course_id=$course_id AND `approved`='y'";
+       $result = mysql_query($sql,$db);
+
+
+       //print error or confirm change
+       if (!$result) {
+               $msg->printErrors('DB_NOT_UPDATED');
+               exit;
+       }
+}
+
+require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/include/html/profile_picture.inc.php b/include/html/profile_picture.inc.php
new file mode 100644 (file)
index 0000000..ff4e267
--- /dev/null
@@ -0,0 +1,176 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+function resize_image($src, $dest, $src_h, $src_w, $dest_h, $dest_w, $type) {\r
+       $thumbnail_img = imagecreatetruecolor($dest_w, $dest_h);\r
+\r
+       if ($type == 'gif') {\r
+               $source = imagecreatefromgif($src);\r
+       } else if ($type == 'jpg') {\r
+               $source = imagecreatefromjpeg($src);\r
+       } else {\r
+               $source = imagecreatefrompng($src);\r
+       }\r
+       \r
+       imagecopyresampled($thumbnail_img, $source, 0, 0, 0, 0, $dest_w, $dest_h, $src_w, $src_h);\r
+\r
+       if ($type == 'gif') {\r
+               imagegif($thumbnail_img, $dest);\r
+       } else if ($type == 'jpg') {\r
+               imagejpeg($thumbnail_img, $dest, 75);\r
+       } else {\r
+               imagepng($thumbnail_img, $dest, 7);\r
+       }\r
+}\r
+\r
+// check if GD is installed\r
+if (!extension_loaded('gd')) {\r
+       require(AT_INCLUDE_PATH.'header.inc.php');\r
+       $msg->printInfos('FEATURE_NOT_AVAILABLE');\r
+       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+\r
+$gd_info = gd_info();\r
+$supported_images = array();\r
+if ($gd_info['GIF Create Support']) {\r
+       $supported_images[] = 'gif';\r
+}\r
+if ($gd_info['JPG Support']) {\r
+       $supported_images[] = 'jpg';\r
+}\r
+if ($gd_info['PNG Support']) {\r
+       $supported_images[] = 'png';\r
+}\r
+\r
+if (!$supported_images) {\r
+       require(AT_INCLUDE_PATH.'header.inc.php');\r
+       $msg->printInfos('FEATURE_NOT_AVAILABLE');\r
+       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id);\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       if (isset($_POST['delete']) && !$_FILES['file']['size']) {\r
+               profile_image_delete($member_id);\r
+\r
+               $msg->addFeedback('PROFILE_UPDATED');\r
+\r
+               header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id);\r
+               exit;\r
+       } else if ($_FILES['file']['error'] == UPLOAD_ERR_FORM_SIZE) {\r
+               $msg->addError(array('FILE_MAX_SIZE', $_config['prof_pic_max_file_size'] . ' ' . _AT('bytes')));\r
+               header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id);\r
+               exit;\r
+       } else if (!$_FILES['file']['size']) {\r
+               header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id);\r
+               exit;\r
+       }\r
+\r
+       // check if this is a supported file type\r
+       $filename   = $stripslashes($_FILES['file']['name']);\r
+       $path_parts = pathinfo($filename);\r
+       $extension  = strtolower($path_parts['extension']);\r
+       $image_attributes = getimagesize($_FILES['file']['tmp_name']);\r
+\r
+       if ($extension == 'jpeg') {\r
+               $extension = 'jpg';\r
+       }\r
+\r
+       if (!in_array($extension, $supported_images)) {\r
+               $msg->addError(array('FILE_ILLEGAL', $extension));\r
+               header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id);\r
+               exit;\r
+       } else if ($image_attributes[2] > IMAGETYPE_PNG) {\r
+               $msg->addError(array('FILE_ILLEGAL', $extension));\r
+               header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id);\r
+               exit;\r
+       }\r
+\r
+       // make sure under max file size\r
+       if ($_FILES['file']['size'] > $_config['prof_pic_max_file_size']) {\r
+               $msg->addError('FILE_MAX_SIZE');\r
+               header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id);\r
+               exit;\r
+       }\r
+\r
+       // delete the old images (if any)\r
+       profile_image_delete($member_id);\r
+\r
+       $new_filename   = $member_id . '.' . $extension;\r
+       $original_img  = AT_CONTENT_DIR.'profile_pictures/originals/'. $new_filename;\r
+       $thumbnail_img = AT_CONTENT_DIR.'profile_pictures/thumbs/'. $new_filename;\r
+\r
+       // save original\r
+       if (!move_uploaded_file($_FILES['file']['tmp_name'], $original_img)) {\r
+               $msg->addError('CANNOT_OVERWRITE_FILE');\r
+               header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id);\r
+               exit;\r
+       }\r
+\r
+       // resize the original and save it at $thumbnail_file\r
+       $width  = $image_attributes[0];\r
+       $height = $image_attributes[1];\r
+\r
+       if ($width > $height && $width>100) {\r
+               $thumbnail_height = intval(100 * $height / $width);\r
+               $thumbnail_width  = 100;\r
+\r
+               resize_image($original_img, $thumbnail_img, $height, $width, $thumbnail_height, $thumbnail_width, $extension);\r
+       } else if ($width <= $height && $height > 100) {\r
+               $thumbnail_height= 100;\r
+               $thumbnail_width = intval(100 * $width / $height);\r
+               resize_image($original_img, $thumbnail_img, $height, $width, $thumbnail_height, $thumbnail_width, $extension);\r
+       } else {\r
+               // no resizing, just copy the image.\r
+               // it's too small to resize.\r
+               copy($original_img, $thumbnail_img);\r
+       }\r
+\r
+       $msg->addFeedback('PROFILE_UPDATED');\r
+\r
+       header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id);\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+?>\r
+\r
+<form method="post" enctype="multipart/form-data" action="<?php echo $_SERVER['PHP_SELF']; ?>?member_id=<?php echo $member_id; ?>" name="form">\r
+<input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $_config['prof_pic_max_file_size']; ?>" />\r
+<div class="input-form">\r
+<?php if (profile_image_exists($member_id)): ?>\r
+       <div class="row">\r
+               <a href="get_profile_img.php?id=<?php echo $member_id.SEP.'size=o'; ?>"><img src="get_profile_img.php?id=<?php echo $member_id; ?>" alt="" /></a>\r
+               <input type="checkbox" name="delete" value="1" id="del"/><label for="del"><?php echo _AT('delete'); ?></label>\r
+       </div>\r
+<?php endif; ?>\r
+       <div class="row">\r
+               <h3><?php echo _AT('upload_new_picture'); ?></h3>\r
+               <input type="file" name="file" /> (<?php echo implode(', ', $supported_images); ?>)</div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/include/html/release_date.inc.php b/include/html/release_date.inc.php
new file mode 100644 (file)
index 0000000..d15f493
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+$month_names = $month_name_con['en'];
+
+               echo '<select name="day'.$name.'">';
+               for ($i = 1; $i <= 31; $i++) {
+                       echo '<option value="'.$i.'"';
+                       if ($i == $today_day) {
+                               echo ' selected="selected"';
+                       }
+                       echo '>';
+                       echo $i.'</option>';
+               }
+               echo '</select>';
+
+               echo '<select name="month'.$name.'">';
+               for ($i = 1; $i <= 12; $i++) {
+                       echo '<option value="'.$i.'"';
+                       if ($i == $today_mon) {
+                               echo ' selected="selected"';
+                       }
+                       echo '>';
+                       echo AT_date('%F', $i, AT_DATE_INDEX_VALUE);
+                       echo '</option>';
+               }
+               echo '</select>';
+
+               echo '<select name="year'.$name.'">';
+               for ($i = min($today_year-1, date('Y')-1); $i <= $today_year+3; $i++) {
+                       echo '<option value="'.$i.'"';
+                       if ($i == $today_year) {
+                               echo ' selected="selected"';
+                       }
+                       echo '>';
+                       echo $i.'</option>';
+               }
+               echo '</select> ';
+
+               echo _AT('at').'  <select name="hour'.$name.'">';
+               for ($i = 0; $i <= 23; $i++) {
+                       echo '<option value="'.$i.'"';
+                       if ($i == $today_hour) {
+                               echo ' selected="selected"';
+                       }
+                       echo '>';
+                       echo $i.'</option>';
+               }
+               echo '</select>:';
+       
+               echo '<select name="min'.$name.'">';
+               for ($i = 0; $i <= 59; $i+=5) {
+                       echo '<option value="'.$i.'"';
+                       if ($i == $today_min) {
+                               echo ' selected="selected"';
+                       }
+                       echo '>';
+                       echo $i.'</option>';
+               }
+               echo '</select><small class="spacer"> '._AT('hours_24').'</small>';
+?>
\ No newline at end of file
diff --git a/include/html/search.inc.php b/include/html/search.inc.php
new file mode 100644 (file)
index 0000000..6ef7283
--- /dev/null
@@ -0,0 +1,310 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                      */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg & Boon-Hau Teh */\r
+/* Adaptive Technology Resource Centre / University of Toronto          */\r
+/* http://atutor.ca                                                                                                    */\r
+/*                                                                      */\r
+/* This program is free software. You can redistribute it and/or        */\r
+/* modify it under the terms of the GNU General Public License          */\r
+/* as published by the Free Software Foundation.                                       */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+// NOTE! please see include/lib/search.inc.php NOTE!\r
+\r
+/* some error checking can go here: */\r
+\r
+if (isset($_GET['search'])) {\r
+       $_GET['words'] = stripslashes($addslashes($_GET['words']));\r
+       $_GET['words'] = str_replace(array('"', '\''), '', $_GET['words']);\r
+       if ($_GET['include'] == 'all') {\r
+               $checked_include_all = ' checked="checked"';\r
+       } else {\r
+               $_GET['include'] = 'one';\r
+               // 'one'\r
+               $checked_include_one = ' checked="checked"';\r
+       }\r
+\r
+       if ($_GET['find_in'] == 'this') {\r
+               $checked_find_in_course = ' checked="checked"';\r
+       } else if ($_GET['find_in'] == 'my') {\r
+               $checked_find_in_my_courses = ' checked="checked"';\r
+       } else {\r
+               $_GET['find_in'] = 'all';\r
+               // 'all'\r
+               $checked_find_in_all_courses = ' checked="checked"';\r
+       }\r
+\r
+       if ($_GET['display_as'] == 'pages') {\r
+               $checked_display_as_pages = ' checked="checked"';\r
+       } else if ($_GET['display_as'] == 'courses') {\r
+               $checked_display_as_courses = ' checked="checked"';\r
+       } else {\r
+               $_GET['display_as'] = 'summaries';\r
+               // 'summaries'\r
+               $checked_display_as_summaries = ' checked="checked"';\r
+       }\r
+\r
+} else {\r
+       // default values:\r
+       $checked_include_all      = ' checked="checked"';\r
+\r
+       if ($_SESSION['course_id'] > 0) {\r
+               $checked_find_in_course   = ' checked="checked"';\r
+               $checked_display_as_pages = ' checked="checked"';\r
+       } else if ($_SESSION['valid_user']) {\r
+               $checked_find_in_my_courses = ' checked="checked"';\r
+               $checked_display_as_courses = ' checked="checked"';\r
+       } else {\r
+               $checked_find_in_all_courses  = ' checked="checked"';\r
+               $checked_display_as_summaries = ' checked="checked"';\r
+       }\r
+}\r
+if (isset($_GET['search']) && !$_GET['words']) {\r
+       $msg->printErrors('SEARCH_TERM_REQUIRED');\r
+       $_GET = array();\r
+}\r
+\r
+?>\r
+\r
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>#search_results" name="form">\r
+<input type="hidden" name="search" value="1" />\r
+<div class="input-form">\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="keywords"><?php echo _AT('search_words'); ?></label><br />\r
+               <input type="text" name="words" size="30" id="keywords" value="<?php echo $_GET['words']; ?>" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <?php echo _AT('search_match'); ?><br />\r
+               <input type="radio" name="include" value="all" id="all" <?php echo $checked_include_all; ?> /><label for="all"><?php echo _AT('search_all_words'); ?></label><br />\r
+               <input type="radio" name="include" value="one" id="one" <?php echo $checked_include_one; ?> /><label for="one"><?php echo _AT('search_any_word'); ?></label>\r
+       </div>\r
+       \r
+       <div class="row">\r
+               <?php echo _AT('find_results_in'); ?><br />\r
+                               <?php if ($_SESSION['course_id'] > 0) : ?>\r
+                                       <input type="radio" name="find_in" value="this" id="f1" <?php echo $checked_find_in_course; ?> /><label for="f1"><?php echo _AT('this_course_only'); ?></label><br />\r
+                               <?php endif; ?>\r
+\r
+                               <?php if ($_SESSION['valid_user'] && ($_SESSION['course_id'] > -1)) : ?>\r
+                                       <input type="radio" name="find_in" value="my" id="f2" <?php echo $checked_find_in_my_courses; ?> /><label for="f2"><?php echo _AT('my_enrolled_courses'); ?></label><br />\r
+                               <?php endif; ?>\r
+\r
+                               <input type="radio" name="find_in" value="all" id="f3" <?php echo $checked_find_in_all_courses; ?> /><label for="f3"><?php echo _AT('all_available_courses'); ?></label>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <?php echo _AT('display'); ?><br />\r
+               <input type="radio" name="display_as" value="pages" id="d1" <?php echo $checked_display_as_pages; ?> /><label for="d1"><?php echo _AT('as_individual_content'); ?></label><br />\r
+\r
+               <input type="radio" name="display_as" value="courses" id="d2" <?php echo $checked_display_as_courses; ?> /><label for="d2"><?php echo _AT('grouped_by_course'); ?></label><br />\r
+\r
+               <input type="radio" name="display_as" value="summaries" id="d3" <?php echo $checked_display_as_summaries; ?> /><label for="d3"><?php echo _AT('course_summaries'); ?></label><br /><br />\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="search" value="<?php echo _AT('search'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php\r
+\r
+/* search results go down here: */\r
+if (isset($_GET['search']) && isset($_GET['words'])) {\r
+       $search_results   = array(); // the content search results\r
+       $search_totals    = array(); // total score per course\r
+       $num_found        = 0;       // total results found\r
+       $total_score      = 0;       // total score (temporary per course)\r
+       $results_per_page = 10;      // number of results per page\r
+       $highlight_system_courses = $system_courses;\r
+\r
+       if ($_GET['include'] == 'all') {\r
+               $predicate = 'AND';\r
+       } else {\r
+               $predicate = 'OR';\r
+       }\r
+\r
+       if (($_GET['find_in'] == 'this') && ($_SESSION['course_id'] > 0)) {\r
+               if ($_GET['display_as'] == 'pages') {\r
+                       $search_results = get_search_result($_GET['words'], $predicate, $_SESSION['course_id'], $num_found, $total_score);\r
+               } else { // 'courses' or 'summaries' :\r
+                       $search_results[$_SESSION['course_id']] = get_search_result($_GET['words'], $predicate, $_SESSION['course_id'], $num_found, $total_score);\r
+                       $search_totals[$_SESSION['course_id']]  = $total_score;\r
+               }\r
+       } else {\r
+               if ($_GET['find_in'] == 'my') {\r
+                       $my_courses = get_my_courses($_SESSION['member_id']);\r
+               } else { // $_GET['find_in'] == 'all' (or other). always safe to perform.\r
+                       $my_courses = get_all_courses($_SESSION['member_id']);\r
+               }\r
+               foreach ($my_courses as $tmp_course_id) {\r
+                       if ($_GET['display_as'] == 'pages') {\r
+                               // merge all the content results together\r
+                               $search_results = array_merge($search_results, get_search_result($_GET['words'], $predicate, $tmp_course_id, $num_found, $total_score));\r
+                       } else {\r
+                               // group by Course\r
+                               $total_score = 0;\r
+                               $search_results[$tmp_course_id] = get_search_result($_GET['words'], $predicate, $tmp_course_id, $num_found, $total_score);\r
+                               if ($total_score) {\r
+                                       $search_totals[$tmp_course_id]  = $total_score;\r
+                               } // else: no content found in this course.\r
+                       }\r
+               }\r
+       }\r
+\r
+       if ($_GET['display_as'] == 'summaries') {\r
+               $num_found = count($search_totals);\r
+       }\r
+\r
+       echo '<a name="search_results"></a><h3>'.$num_found.' '._AT('search_results').'</h3>';\r
+\r
+       if (!$num_found) {\r
+               $msg->printInfos('NO_SEARCH_RESULTS');\r
+               require(AT_INCLUDE_PATH.'footer.inc.php');\r
+               exit;\r
+       } else if (!$num_found && count($search_totals)) {\r
+               // meaning: no pages were found, just courses:\r
+               $num_found = count($search_totals);\r
+       }\r
+\r
+       $num_pages = ceil($num_found / $results_per_page);\r
+                       \r
+       $page = intval($_GET['p']);\r
+       if (!$page) {\r
+               $page = 1;\r
+       }\r
+                       \r
+       $count = (($page-1) * $results_per_page) + 1;\r
+\r
+       $pages_text = '<div class="paging">';\r
+       $pages_text .= '<ul>';\r
+       for ($i=1; $i<=$num_pages; $i++) {\r
+               $pages_text .= '<li>';\r
+               if ($i == $page) {\r
+                       $pages_text .= '<a class="current" href="'.$_SERVER['PHP_SELF'].'?search=1'.SEP.'words='.urlencode($_GET['words']).SEP.'include='.$_GET['include'].SEP.'find_in='.$_GET['find_in'].SEP.'display_as='.$_GET['display_as'].SEP.'p='.$i.'#search_results"><em>'.$i.'</em></a>';\r
+               } else {\r
+                       $pages_text .= '<a href="'.$_SERVER['PHP_SELF'].'?search=1'.SEP.'words='.urlencode($_GET['words']).SEP.'include='.$_GET['include'].SEP.'find_in='.$_GET['find_in'].SEP.'display_as='.$_GET['display_as'].SEP.'p='.$i.'#search_results">'.$i.'</a>';\r
+               }\r
+               $pages_text .= '</li>';\r
+       }\r
+       $pages_text .= '</ul>';\r
+       $pages_text .= '</div>';\r
+\r
+       echo $pages_text;\r
+\r
+       if ($_GET['display_as'] == 'pages') {\r
+               uasort($search_results, 'score_cmp');\r
+\r
+               $search_results = array_slice($search_results, ($page-1)*$results_per_page, $results_per_page);\r
+\r
+               echo '<div class="results">';\r
+               print_search_pages($search_results);\r
+               echo '</div>'."\n";\r
+       } else {\r
+               arsort($search_totals);\r
+               reset($search_totals);\r
+\r
+               $skipped        = 0; // number that have been skipped\r
+               $printed_so_far = 0; // number printed on this page\r
+\r
+               foreach ($search_totals as $tmp_course_id => $score) {\r
+                       $total_here = 0;\r
+                       if ($printed_so_far == $results_per_page) {\r
+                               break;\r
+                       }\r
+                       \r
+                       $increment_count = false;\r
+                       if (count($search_results[$tmp_course_id]) && ($_GET['display_as'] == 'courses')) {\r
+                               uasort($search_results[$tmp_course_id], 'score_cmp');\r
+                               reset($search_results[$tmp_course_id]);\r
+\r
+                               $num_available = count($search_results[$tmp_course_id]); // total number available for this course\r
+               \r
+                               if ($printed_so_far == $results_per_page) {\r
+                                       break;\r
+                               }\r
+\r
+                               if ($skipped < $count) {\r
+                                       // this course is being truncated\r
+                                       // implies that it's at the start of the page\r
+                                       $start = ($page -1) * $results_per_page - $skipped;\r
+\r
+                                       $total_here = count($search_results[$tmp_course_id]);\r
+\r
+                                       $search_results[$tmp_course_id] = array_slice($search_results[$tmp_course_id], $start, $results_per_page - $printed_so_far);\r
+\r
+                                       $num_printing = count($search_results[$tmp_course_id]);\r
+\r
+                                       $printed_so_far += $num_printing;\r
+                                       $skipped += ($num_available - $num_printing);\r
+\r
+                                       if ($num_printing == 0) {\r
+                                               continue;\r
+                                       }\r
+                                       $increment_count = true;\r
+                               }\r
+                       } else {\r
+                               if ($printed_so_far == $results_per_page) {\r
+                                       break;\r
+                               }\r
+\r
+                               $total_here = count($search_results[$tmp_course_id]);\r
+                               if (($total_here == 0) || ($_GET['display_as'] == 'summaries')) {\r
+                                       if ($skipped < ($page-1) * $results_per_page) {\r
+                                               $skipped++;\r
+                                               continue;\r
+                                       }\r
+                                       $printed_so_far ++;\r
+                                       $increment_count = true;\r
+                               } else {\r
+                                       $printed_so_far += $total_here;\r
+                               }\r
+                       }\r
+                       echo '<h5 class="search-results"> '._AT('results_from', '<a href="bounce.php?course='.$tmp_course_id.'">'.$highlight_system_courses[$tmp_course_id]['title'] .'</a>').' - '._AT('pages_found', $total_here) . '</h5>';\r
+\r
+\r
+                       echo '<p class="search-description">';\r
+                       if ($highlight_system_courses[$tmp_course_id]['description']) {\r
+                               echo $highlight_system_courses[$tmp_course_id]['description'];\r
+                       } else {\r
+                               echo '<em>'._AT('no_description').'</em>';\r
+                       }\r
+\r
+                       echo '<br /><small class="search-info">[<strong>'._AT('Access').':</strong> ';\r
+\r
+                       switch ($highlight_system_courses[$tmp_course_id]['access']){\r
+                               case 'public':\r
+                                       echo _AT('public');\r
+                                       break;\r
+                               case 'protected':\r
+                                       echo _AT('protected');\r
+                                       break;\r
+                               case 'private':\r
+                                       echo _AT('private');\r
+                                       break;\r
+                       }\r
+                       $language =& $languageManager->getLanguage($highlight_system_courses[$tmp_course_id]['primary_language']);\r
+\r
+                       echo '. <strong>'._AT('primary_language').':</strong> ' . $language->getTranslatedName();\r
+                       \r
+                       echo ']</small>';\r
+\r
+                       echo '</p>';\r
+\r
+                       if ($_GET['display_as'] != 'summaries') {\r
+                               echo '<div class="results">';\r
+                               print_search_pages($search_results[$tmp_course_id]);\r
+                               echo '</div>';\r
+                       }                       \r
+               \r
+               }\r
+       }\r
+\r
+       echo $pages_text;       \r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/include/html/tests_questions.inc.php b/include/html/tests_questions.inc.php
new file mode 100644 (file)
index 0000000..0074399
--- /dev/null
@@ -0,0 +1,167 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                      */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg & Boon-Hau Teh */\r
+/* Adaptive Technology Resource Centre / University of Toronto          */\r
+/* http://atutor.ca                                                                                                    */\r
+/*                                                                      */\r
+/* This program is free software. You can redistribute it and/or        */\r
+/* modify it under the terms of the GNU General Public License          */\r
+/* as published by the Free Software Foundation.                                       */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+if (isset($_GET['reset_filter'])) {\r
+       unset($_GET['category_id']);\r
+}\r
+if (!isset($_GET['category_id'])) {\r
+       // Suppress warnings\r
+       $_GET['category_id'] = -1;\r
+}\r
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');\r
+?>\r
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+       <input type="hidden" name="tid" value="<?php echo $tid; ?>" />\r
+       <div class="input-form">\r
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('category'); ?></legend>\r
+               <div class="row">\r
+                       <label for="cats"><?php echo _AT('category'); ?></label><br />\r
+                       <select name="category_id" id="cats">\r
+                               <option value="-1"><?php echo _AT('cats_all'); ?></option>\r
+                               <?php print_question_cats($_GET['category_id']); ?>\r
+                       </select>\r
+               </div>\r
+               <div class="row buttons">\r
+                       <input type="submit" name="filter" value="<?php echo _AT('filter'); ?>" />\r
+                       <input type="submit" name="reset_filter" value="<?php echo _AT('reset_filter'); ?>" />\r
+               </div>\r
+               </fieldset>\r
+       </div>\r
+</form>\r
+<?php\r
+\r
+$cats = array();\r
+if ($_GET['category_id'] >= 0) {\r
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."tests_questions_categories WHERE course_id=$_SESSION[course_id] AND category_id=$_GET[category_id] ORDER BY title";\r
+} else {\r
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."tests_questions_categories WHERE course_id=$_SESSION[course_id] ORDER BY title";\r
+}\r
+\r
+$result        = mysql_query($sql, $db);\r
+if ($_GET['category_id'] <= 0) {\r
+       $cats[] = array('title' => _AT('cats_uncategorized'), 'category_id' => 0);\r
+}\r
+\r
+while ($row = mysql_fetch_assoc($result)) {\r
+       $cats[] = $row;\r
+}\r
+\r
+       $cols = 3;\r
+?>\r
+<?php if ($tid): ?>\r
+       <form method="post" action="tools/tests/add_test_questions_confirm.php" name="form">\r
+<?php else: ?>\r
+       <form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">\r
+<?php endif; ?>\r
+<table class="data" summary="" rules="cols">\r
+<thead>\r
+<tr>\r
+       <th scope="col">&nbsp;</th>\r
+       <th scope="col"><?php echo _AT('question'); ?></th>\r
+       <th scope="col"><?php echo _AT('type'); ?></th>\r
+</tr>\r
+</thead>\r
+<tfoot>\r
+<?php if ($tid): ?>\r
+       <tr>\r
+               <td colspan="3">\r
+                       <input type="hidden" name="tid" value="<?php echo $tid; ?>" />\r
+                       <input type="submit" name="submit" value="<?php echo _AT('add_to_test_survey'); ?>" accesskey="s" />\r
+                       <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+               </td>\r
+       </tr>\r
+<?php else: ?>\r
+       <tr>\r
+               <td colspan="3">\r
+                       <input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> \r
+                       <input type="submit" name="preview" value="<?php echo _AT('preview'); ?>" />\r
+                       <input type="submit" name="export" value="<?php echo _AT('export'); ?>" />\r
+                       <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" />\r
+               </td>\r
+       </tr>\r
+<?php endif; ?>\r
+</tfoot>\r
+<tbody>\r
+<?php\r
+\r
+$question_flag = FALSE;\r
+\r
+//output categories\r
+foreach ($cats as $cat) {\r
+       //ouput questions\r
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."tests_questions WHERE course_id=$_SESSION[course_id] AND category_id=".$cat['category_id']." ORDER BY question";\r
+       $result = mysql_query($sql, $db);\r
+       if ($row = mysql_fetch_assoc($result)) {\r
+               $question_flag = TRUE;\r
+               echo '<tr>';\r
+               echo '<th colspan="'.$cols.'">';\r
+\r
+               echo '<input type="checkbox" name="cat'.$cat['category_id'].'" id="cat'.$cat['category_id'].'" onclick="javascript:selectCat('.$cat['category_id'].', this);" /><label for="cat'.$cat['category_id'].'">'.$cat['title'].'</label>';\r
+               echo '</th>';\r
+               echo '</tr>';\r
+\r
+               do {\r
+                       echo '<tr onmousedown="document.form[\'q' . $row['question_id'] . '\'].checked = !document.form[\'q' . $row['question_id'] . '\'].checked; togglerowhighlight(this, \'q'.$row['question_id'].'\');" id="rq'.$row['question_id'].'">';\r
+                       echo '<td>';\r
+                       echo '<input type="checkbox" value="'.$row['question_id'].'|'.$row['type'].'" name="questions['.$cat['category_id'].'][]" id="q'.$row['question_id'].'" onmouseup="this.checked=!this.checked" /></td>';\r
+                       echo '<td>';\r
+                       if ($strlen($row['question']) > 45) {\r
+                               echo AT_print($substr(htmlentities($row['question']), 0, 43), 'tests_questions.question') . '&hellip;';\r
+                       } else {\r
+                               echo AT_print(htmlentities($row['question']), 'tests_questions.question');\r
+                       }\r
+\r
+                       echo '</td>';\r
+                       echo '<td>';\r
+                       $o = TestQuestions::getQuestion($row['type']);\r
+                       $o->printName();\r
+                                       \r
+                       echo '</td>';\r
+                       \r
+                       echo '</tr>';\r
+\r
+               } while ($row = mysql_fetch_assoc($result));\r
+       } \r
+}  \r
+if (!$question_flag) {\r
+       echo '<tr><td colspan="'.$cols.'">'._AT('none_found').'</td></tr>';\r
+}\r
+?>\r
+</tbody>\r
+</table>\r
+</form>\r
+\r
+<script language="javascript" type="text/javascript">\r
+// <!--\r
+       function selectCat(catID, cat) {\r
+               for (var i=0;i<document.form.elements.length;i++) {\r
+                       var e = document.form.elements[i];\r
+                       if ((e.name == 'questions[' + catID + '][]') && (e.type=='checkbox')) {\r
+                               e.checked = cat.checked;\r
+                               togglerowhighlight(document.getElementById("r" + e.id), e.id);\r
+                       }\r
+               }\r
+       }\r
+       \r
+function togglerowhighlight(obj, boxid) {\r
+       if (document.getElementById(boxid).checked) {\r
+               obj.className = 'selected';\r
+       } else {\r
+               obj.className = '';\r
+       }\r
+}\r
+// -->\r
+</script>\r
diff --git a/include/ims/adlcp_rootv1p2.xsd b/include/ims/adlcp_rootv1p2.xsd
new file mode 100644 (file)
index 0000000..f930690
--- /dev/null
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+<!-- filename=adlcp_rootv1p2.xsd -->
+<!-- Conforms to w3c http://www.w3.org/TR/xmlschema-1/ 2000-10-24-->
+
+<xsd:schema xmlns="http://www.adlnet.org/xsd/adlcp_rootv1p2"
+            targetNamespace="http://www.adlnet.org/xsd/adlcp_rootv1p2"
+            xmlns:xml="http://www.w3.org/XML/1998/namespace"
+            xmlns:imscp="http://www.imsproject.org/xsd/imscp_rootv1p1p2"
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            elementFormDefault="unqualified"
+            version="ADL Version 1.2">
+
+        <xsd:import namespace="http://www.imsproject.org/xsd/imscp_rootv1p1p2"
+         schemaLocation="imscp_rootv1p1p2.xsd"/>
+
+        <xsd:element name="location" type="locationType"/>
+        <xsd:element name="prerequisites" type="prerequisitesType"/>
+        <xsd:element name="maxtimeallowed" type="maxtimeallowedType"/>
+        <xsd:element name="timelimitaction" type="timelimitactionType"/>
+        <xsd:element name="datafromlms" type="datafromlmsType"/>
+        <xsd:element name="masteryscore" type="masteryscoreType"/>
+
+
+        <xsd:element name="schema" type="newSchemaType"/>
+        <xsd:simpleType name="newSchemaType">
+                <xsd:restriction base="imscp:schemaType">
+                        <xsd:enumeration value="ADL SCORM"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+
+        <xsd:element name="schemaversion" type="newSchemaversionType"/>
+        <xsd:simpleType name="newSchemaversionType">
+                <xsd:restriction base="imscp:schemaversionType">
+                        <xsd:enumeration value="1.2"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+
+
+        <xsd:attribute name="scormtype">
+            <xsd:simpleType>
+                <xsd:restriction base="xsd:string">
+                   <xsd:enumeration value="asset"/>
+                   <xsd:enumeration value="sco"/>
+                </xsd:restriction>
+            </xsd:simpleType>
+        </xsd:attribute>
+
+        <xsd:simpleType name="locationType">
+                <xsd:restriction base="xsd:string">
+                        <xsd:maxLength value="2000"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+
+
+        <xsd:complexType name="prerequisitesType">
+           <xsd:simpleContent>
+              <xsd:extension base="prerequisiteStringType">
+                  <xsd:attributeGroup ref="attr.prerequisitetype"/>
+              </xsd:extension>
+           </xsd:simpleContent>
+        </xsd:complexType>
+
+        <xsd:attributeGroup name="attr.prerequisitetype">
+                <xsd:attribute name="type" use="required">
+                        <xsd:simpleType>
+                                <xsd:restriction base="xsd:string">
+                                   <xsd:enumeration value="aicc_script"/>
+                                </xsd:restriction>
+                        </xsd:simpleType>
+                </xsd:attribute>
+        </xsd:attributeGroup>
+
+        <xsd:simpleType name="maxtimeallowedType">
+                <xsd:restriction base="xsd:string">
+                        <xsd:maxLength value="13"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+
+        <xsd:simpleType name="timelimitactionType">
+                <xsd:restriction base="stringType">
+                        <xsd:enumeration value="exit,no message"/>
+                        <xsd:enumeration value="exit,message"/>
+                        <xsd:enumeration value="continue,no message"/>
+                        <xsd:enumeration value="continue,message"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+
+        <xsd:simpleType name="datafromlmsType">
+                <xsd:restriction base="xsd:string">
+                        <xsd:maxLength value="255"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+
+        <xsd:simpleType name="masteryscoreType">
+                <xsd:restriction base="xsd:string">
+                        <xsd:maxLength value="200"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+
+        <xsd:simpleType name="stringType">
+                <xsd:restriction base="xsd:string"/>
+        </xsd:simpleType>
+        
+        <xsd:simpleType name="prerequisiteStringType">
+                <xsd:restriction base="xsd:string">
+                   <xsd:maxLength value="200"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+
+</xsd:schema>
diff --git a/include/ims/footer.html b/include/ims/footer.html
new file mode 100644 (file)
index 0000000..44ea970
--- /dev/null
@@ -0,0 +1,17 @@
+<!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>
+       <link rel="stylesheet" type="text/css" href="ims.css" />
+       <title>About this Content Package</title>
+       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+</head>
+<body class="footerbody"> 
+<table>
+<tr>
+       <td valign="middle" align="left"><a href="http://www.atutor.ca" target="_blank"><img src="logo.gif" border="0" alt="ATutor.ca - opens in a new window" width="84" height="29" align="left" title="ATutor.ca - opens in a new window" /></a></td>
+       <td><span class="footer"><small>For general help with using the ATutor system see the official <a href="http://help.atutor.ca/" title="ATutor Handbook - opens in a new window" target="_blank">ATutor <em>Handbook</em> </a>.</small></span></td>
+</tr>
+</table>
+</body>
+</html>
\ No newline at end of file
diff --git a/include/ims/ims.css b/include/ims/ims.css
new file mode 100644 (file)
index 0000000..972d82d
--- /dev/null
@@ -0,0 +1,40 @@
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+/* $Id$                        */
+
+/* header */
+body.headerbody { font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #EFEFEF;}
+h3 { font-family: Verdana, Arial, Helvetica, sans-serif; color: #384F89; }
+
+/* table of contents */
+ul { 
+       font-family: Verdana, Arial, Helvetica, sans-serif; 
+       color: gray;
+       font-size: small;
+}
+ul a { color:#384F89; }
+ul a:hover { text-decoration:none; }
+ul a:visited { color:black; }
+
+li {
+       margin-left: -10px;
+}
+
+/* body */
+body.contentbody { font-family: Verdana, Arial, Helvetica, sans-serif;}
+
+/* footer */
+body.footerbody { font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #384F89; margin-top: 0px;}
+body.footerbody a { font-family: Verdana, Arial, Helvetica, sans-serif; color: white; }
+body.footerbody a:hover { font-family: Verdana, Arial, Helvetica, sans-serif; text-decoration:none; }
+.footer { font-family: Verdana, Arial, Helvetica, sans-serif; color: white; }
+
diff --git a/include/ims/ims_template.inc.php b/include/ims/ims_template.inc.php
new file mode 100644 (file)
index 0000000..9ba407e
--- /dev/null
@@ -0,0 +1,441 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+// This function gets files from html tag @import
+function get_import_files($text)
+{
+       $text = strtolower($text);
+       $tag = '@import';
+       $files = array();
+       
+       while (stripos($text, $tag) > 0)
+       {
+               $start_pos      = strpos($text, $tag);
+               if ($start_pos !== false) 
+               {
+                       $text = substr($text, $start_pos);
+                       $start_pos = strlen($tag);
+                       $len = stripos($text, ';') - strlen($tag);
+                       
+                       $file = substr(trim($text), $start_pos, $len);
+                       
+                       // remove these characters from file name: url, (, ), ", '
+                       $file = trim(preg_replace('/(\'|\"|url|\(|\))/', '', $file));
+                       
+                       // strip processed tag
+                       $text = substr($text, $start_pos);
+                       array_push($files, $file);
+               }
+       
+       }
+       
+       return $files;
+}
+       
+function print_organizations($parent_id,
+                                                        &$_menu, 
+                                                        $depth, 
+                                                        $path='',
+                                                        $children,
+                                                        &$string) {
+       
+       global $html_content_template, $default_html_style, $zipfile, $resources, $ims_template_xml, $parser, $my_files;
+       global $used_glossary_terms, $course_id, $course_language_charset, $course_language_code;
+       static $paths, $zipped_files;
+       global $glossary;
+
+       $space  = '    ';
+       $prefix = '                    ';
+
+       if ($depth == 0) {
+               $string .= '<ul>';
+       }
+       $top_level = $_menu[$parent_id];
+       if (!is_array($paths)) {
+               $paths = array();
+       }
+       if (!is_array($zipped_files)) {
+               $zipped_files = array();
+       }
+       if ( is_array($top_level) ) {
+               $counter = 1;
+               $num_items = count($top_level);
+               foreach ($top_level as $garbage => $content) {
+
+                       $link = '';
+                               
+                       if ($content['content_path']) {
+                               $content['content_path'] .= '/';
+                       }
+
+                       $link = $prevfix.'<item identifier="MANIFEST01_ITEM'.$content['content_id'].'" identifierref="MANIFEST01_RESOURCE'.$content['content_id'].'" parameters="">'."\n";
+                       $html_link = '<a href="resources/'.$content['content_path'].$content['content_id'].'.html" target="body">'.$content['title'].'</a>';
+                       
+                       /* save the content as HTML files */
+                       /* @See: include/lib/format_content.inc.php */
+                       $content['text'] = str_replace('CONTENT_DIR/', '', $content['text']);
+
+                       /* get all the glossary terms used */
+                       $terms = find_terms($content['text']);
+                       if (is_array($terms)) {
+                               foreach ($terms[2] as $term) {
+                                       $used_glossary_terms[] = $term;
+                               }
+                       }
+
+                       /* calculate how deep this page is: */
+                       $path = '../';
+                       if ($content['content_path']) {
+                               $depth = substr_count($content['content_path'], '/');
+
+                               $path .= str_repeat('../', $depth);
+                       }
+                       $content['text'] = format_content($content['text'], $content['formatting'], $glossary, $path);
+
+                       /* add HTML header and footers to the files */
+                       
+                       /* use default style if <style> is not in imported html head */
+                       $head = '';
+                       if ($content['use_customized_head'])
+                       {
+                               if (stripos($content['head'], '<style') > 0)
+                               {
+                                       $head = $content['head'];
+                               }
+                               else
+                               {
+                                       if (strlen($content['head']) > 0)  
+                                               $head = $content['head'] . $default_html_style;
+                                       else 
+                                               $head = $default_html_style;
+                               }
+                       }
+
+                       $content['text'] = str_replace( array('{TITLE}',        '{CONTENT}', '{KEYWORDS}', '{COURSE_PRIMARY_LANGUAGE_CHARSET}', '{COURSE_PRIMARY_LANGUAGE_CODE}', '{HEAD}'),
+                                                                       array($content['title'],        $content['text'], $content['keywords'], $course_language_charset, $course_language_code, $head),
+                                                                       $html_content_template);
+
+                       /* duplicate the paths in the content_path field in the zip file */
+                       if ($content['content_path']) {
+                               if (!in_array($content['content_path'], $paths)) {
+                                       $zipfile->create_dir('resources/'.$content['content_path'], time());
+                                       $paths[] = $content['content_path'];
+                               }
+                       }
+
+                       $zipfile->add_file($content['text'], 'resources/'.$content['content_path'].$content['content_id'].'.html', $content['u_ts']);
+                       $content['title'] = htmlspecialchars($content['title']);
+
+                       /* add the resource dependancies */
+                       $my_files = array();
+                       $content_files = "\n";
+                       $parser->parse($content['text']);
+
+                       /* handle @import */
+                       $import_files = get_import_files($content['text']);
+                       
+                       if (count($import_files) > 0) $my_files = array_merge($my_files, $import_files);
+                       
+                       foreach ($my_files as $file) {
+                               /* filter out full urls */
+                               $url_parts = @parse_url($file);
+                               if (isset($url_parts['scheme'])) {
+                                       continue;
+                               }
+
+                               /* file should be relative to content. let's double check */
+                               if ((substr($file, 0, 1) == '/')) {
+                                       continue;
+                               }
+
+                               $file_path = realpath(AT_CONTENT_DIR . $course_id . '/' . $content['content_path'] . $file);
+
+                               /* check if this file exists in the content dir, if not don't include it */
+                               if (file_exists($file_path) &&  is_file($file_path) && !in_array($file_path, $zipped_files)) {
+                                       $zipped_files[] = $file_path;
+                                       $dir = substr(dirname($file_path), strlen(AT_CONTENT_DIR . $course_id));
+
+                                       if (!in_array($dir, $paths) && $dir) {
+                                               $dir = str_replace('\\', '/', substr($dir, 1));
+                                               $zipfile->create_dir('resources/' . $dir, time());
+                                               
+                                               $paths[] = $dir;
+                                       }
+
+                                       $file_info = stat( $file_path );
+                                       $zipfile->add_file(@file_get_contents($file_path), 'resources/' . $content['content_path'] . $file, $file_info['mtime']);
+
+                                       $content_files .= str_replace('{FILE}', $content['content_path'] . $file, $ims_template_xml['file']);
+                               }
+                       }
+
+                       /******************************/
+                       $resources .= str_replace(      array('{CONTENT_ID}', '{PATH}', '{FILES}'),
+                                                                               array($content['content_id'], $content['content_path'], $content_files),
+                                                                               $ims_template_xml['resource']);
+
+
+                       for ($i=0; $i<$depth; $i++) {
+                               $link .= $space;
+                       }
+                       
+                       $title = $prefix.$space.'<title>'.$content['title'].'</title>';
+
+                       if ( is_array($_menu[$content['content_id']]) ) {
+                               /* has children */
+
+                               $html_link = '<li>'.$html_link.'<ul>';
+                               for ($i=0; $i<$depth; $i++) {
+                                       if ($children[$i] == 1) {
+                                               echo $space;
+                                               //$html_link = $space.$html_link;
+                                       } else {
+                                               echo $space;
+                                               //$html_link = $space.$html_link;
+                                       }
+                               }
+
+                       } else {
+                               /* doesn't have children */
+
+                               $html_link = '<li>'.$html_link.'</li>';
+                               if ($counter == $num_items) {
+                                       for ($i=0; $i<$depth; $i++) {
+                                               if ($children[$i] == 1) {
+                                                       echo $space;
+                                                       //$html_link = $space.$html_link;
+                                               } else {
+                                                       echo $space;
+                                                       //$html_link = $space.$html_link;
+                                               }
+                                       }
+                               } else {
+                                       for ($i=0; $i<$depth; $i++) {
+                                               echo $space;
+                                               //$html_link = $space.$html_link;
+                                       }
+                               }
+                               $title = $space.$title;
+                       }
+
+                       echo $prefix.$link;
+                       echo $title;
+                       echo "\n";
+
+                       $string .= $html_link."\n";
+
+                       $depth ++;
+                       print_organizations($content['content_id'],
+                                                               $_menu, 
+                                                               $depth, 
+                                                               $path.$counter.'.', 
+                                                               $children,
+                                                               $string);
+                       $depth--;
+
+                       $counter++;
+                       for ($i=0; $i<$depth; $i++) {
+                               echo $space;
+                       }
+                       echo $prefix.'</item>';
+                       echo "\n";
+               }
+               $string .= '</ul>';
+               if ($depth > 0) {
+                       $string .= '</li>';
+               }
+
+       }
+}
+
+
+
+$ims_template_xml['header'] = '<?xml version="1.0" encoding="{COURSE_PRIMARY_LANGUAGE_CHARSET}"?>
+<!--This is an ATutor SCORM 1.2 Content Package document-->
+<!--Created from the ATutor Content Package Generator - http://www.atutor.ca-->
+<manifest xmlns="http://www.imsproject.org/xsd/imscp_rootv1p1p2" xmlns:imsmd="http://www.imsglobal.org/xsd/imsmd_rootv1p2p1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:adlcp="http://www.adlnet.org/xsd/adlcp_rootv1p2" identifier="MANIFEST-'.md5(time()).'" xsi:schemaLocation="http://www.imsproject.org/xsd/imscp_rootv1p1p2 imscp_rootv1p1p2.xsd http://www.imsglobal.org/xsd/imsmd_rootv1p2p1 imsmd_rootv1p2p1.xsd http://www.adlnet.org/xsd/adlcp_rootv1p2 adlcp_rootv1p2.xsd">
+       <metadata>
+               <schema>ADL SCORM</schema> 
+           <schemaversion>1.2</schemaversion>
+               <imsmd:lom>
+                 <imsmd:general>
+                       <imsmd:title>
+                         <imsmd:langstring xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}">{COURSE_TITLE}</imsmd:langstring>
+                       </imsmd:title>
+                       <imsmd:description>
+                         <imsmd:langstring xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}">{COURSE_DESCRIPTION}</imsmd:langstring>
+                       </imsmd:description>
+                 </imsmd:general>
+                 <imsmd:lifecycle>
+                       <imsmd:contribute>
+                         <imsmd:role>
+                           <imsmd:source>
+                             <imsmd:langstring xml:lang="x-none">LOMv1.0</imsmd:langstring> 
+                           </imsmd:source>
+                           <imsmd:value>
+                             <imsmd:langstring xml:lang="x-none">Author</imsmd:langstring> 
+                           </imsmd:value>
+                         </imsmd:role>
+                         <imsmd:centity>
+                           <imsmd:vcard>{VCARD}</imsmd:vcard> 
+                         </imsmd:centity>
+                       </imsmd:contribute>
+                 </imsmd:lifecycle>
+                 <imsmd:educational>
+                       <imsmd:learningresourcetype>
+                         <imsmd:source>
+                               <imsmd:langstring xml:lang="x-none">ATutor</imsmd:langstring>
+                         </imsmd:source>
+                         <imsmd:value>
+                               <imsmd:langstring xml:lang="x-none">Content Module</imsmd:langstring>
+                         </imsmd:value>
+                       </imsmd:learningresourcetype>
+                 </imsmd:educational>
+                 <imsmd:rights>
+                 </imsmd:rights>
+               </imsmd:lom>
+       </metadata>
+';
+
+$ims_template_xml['resource'] = '              <resource identifier="MANIFEST01_RESOURCE{CONTENT_ID}" type="webcontent" href="resources/{PATH}{CONTENT_ID}.html"  adlcp:scormtype="asset">
+                       <metadata/>
+                       <file href="resources/{PATH}{CONTENT_ID}.html"/>{FILES}
+               </resource>
+'."\n";
+
+$ims_template_xml['file'] = '                  <file href="resources/{FILE}"/>'."\n";
+
+$ims_template_xml['final'] = '
+       <organizations default="MANIFEST01_ORG1">
+               <organization identifier="MANIFEST01_ORG1" structure="hierarchical">
+                       <title>{COURSE_TITLE}</title>
+{ORGANIZATIONS}
+               </organization>
+       </organizations>
+       <resources>
+{RESOURCES}
+       </resources>
+</manifest>';
+
+$html_template = '<!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="{COURSE_PRIMARY_LANGUAGE_CODE}" lang="{COURSE_PRIMARY_LANGUAGE_CODE}">
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset={COURSE_PRIMARY_LANGUAGE_CHARSET}" />
+       <style type="text/css">
+       body { font-family: Verdana, Arial, Helvetica, sans-serif;}
+       a.at-term {     font-style: italic; }
+       </style>
+       <title>{TITLE}</title>
+       <meta name="Generator" content="ATutor">
+       <meta name="Keywords" content="{KEYWORDS}">
+</head>
+<body>{CONTENT}</body>
+</html>';
+
+$html_content_template = '<!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="{COURSE_PRIMARY_LANGUAGE_CODE}" lang="{COURSE_PRIMARY_LANGUAGE_CODE}">
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset={COURSE_PRIMARY_LANGUAGE_CHARSET}" />
+       {HEAD}
+       <title>{TITLE}</title>
+       <meta name="Generator" content="ATutor">
+       <meta name="Keywords" content="{KEYWORDS}">
+</head>
+<body>{CONTENT}</body>
+</html>';
+
+$default_html_style = '        <style type="text/css">
+       body { font-family: Verdana, Arial, Helvetica, sans-serif;}
+       a.at-term {     font-style: italic; }
+       </style>';
+       
+//output this as header.html
+$html_mainheader = '<!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="{COURSE_PRIMARY_LANGUAGE_CODE}" lang="{COURSE_PRIMARY_LANGUAGE_CODE}">
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset={COURSE_PRIMARY_LANGUAGE_CHARSET}" />
+       <link rel="stylesheet" type="text/css" href="ims.css"/>
+       <title>{COURSE_TITLE}</title>
+</head>
+<body class="headerbody"><h3>{COURSE_TITLE}</h3></body></html>';
+
+
+$html_toc = '<!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="{COURSE_PRIMARY_LANGUAGE_CODE}" lang="{COURSE_PRIMARY_LANGUAGE_CODE}">
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset={COURSE_PRIMARY_LANGUAGE_CHARSET}" />
+       <link rel="stylesheet" type="text/css" href="ims.css" />
+       <title></title>
+</head>
+<body>{TOC}</body></html>';
+
+// index.html
+$html_frame = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
+   "http://www.w3.org/TR/html4/frameset.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}" lang="{COURSE_PRIMARY_LANGUAGE_CODE}">
+       <meta http-equiv="Content-Type" content="text/html; charset={COURSE_PRIMARY_LANGUAGE_CHARSET}" />
+       <title>{COURSE_TITLE}</title>
+</head>
+<frameset rows="50,*,50">
+<frame src="header.html" name="header" title="header" scrolling="no">
+       <frameset cols="25%, *" frameborder="1" framespacing="3">
+               <frame frameborder="2" marginwidth="0" marginheight="0" src="toc.html" name="frame" title="TOC">
+               <frame frameborder="2" src="resources/{PATH}{FIRST_ID}.html" name="body" title="{COURSE_TITLE}">
+       </frameset>
+<frame src="footer.html" name="footer" title="footer" scrolling="no">
+       <noframes>
+               <h1>{COURSE_TITLE}</h1>
+      <p><a href="toc.html">Table of Contents</a> | <a href="footer.html">About</a><br />
+         </p>
+  </noframes>
+</frameset>
+</html>';
+
+
+
+$glossary_xml = '<?xml version="1.0" encoding="{COURSE_PRIMARY_LANGUAGE_CHARSET}"?>
+<!--This is an ATutor Glossary terms document-->
+<!--Created from the ATutor Content Package Generator - http://www.atutor.ca-->
+
+<!DOCTYPE glossary [
+   <!ELEMENT item (term, definition)>
+   <!ELEMENT term (#PCDATA)>
+   <!ELEMENT definition (#PCDATA)>
+]>
+
+<glossary>
+      {GLOSSARY_TERMS}
+</glossary>
+';
+
+$glossary_term_xml = ' <item>
+               <term>{TERM}</term>
+               <definition>{DEFINITION}</definition>
+       </item>';
+
+$glossary_body_html = '<h2>Glossary</h2>
+       <ul>
+{BODY}
+</ul>';
+
+$glossary_term_html = '        <li><a name="{ENCODED_TERM}"></a><strong>{TERM}</strong><br />
+               {DEFINITION}<br /><br /></li>';
+
+?>
\ No newline at end of file
diff --git a/include/ims/ims_xml.xsd b/include/ims/ims_xml.xsd
new file mode 100644 (file)
index 0000000..dbb4ddc
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- filename=ims_xml.xsd -->
+<xsd:schema targetNamespace="http://www.w3.org/XML/1998/namespace" xmlns="http://www.w3.org/XML/1998/namespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified">
+       <!-- 2001-02-22 edited by Thomas Wason IMS Global Learning Consortium, Inc. -->
+       <xsd:annotation>
+               <xsd:documentation>In namespace-aware XML processors, the &quot;xml&quot; prefix is bound to the namespace name http://www.w3.org/XML/1998/namespace.</xsd:documentation>
+               <xsd:documentation>Do not reference this file in XML instances</xsd:documentation>
+       </xsd:annotation>
+       <xsd:attribute name="lang" type="xsd:language">
+               <xsd:annotation>
+                       <xsd:documentation>Refers to universal  XML 1.0 lang attribute</xsd:documentation>
+               </xsd:annotation>
+       </xsd:attribute>
+       <xsd:attribute name="base" type="xsd:anyURI">
+               <xsd:annotation>
+                       <xsd:documentation>Refers to XML Base: http://www.w3.org/TR/xmlbase</xsd:documentation>
+               </xsd:annotation>
+       </xsd:attribute>
+       <xsd:attribute name="link" type="xsd:anyURI"/>
+</xsd:schema>
diff --git a/include/ims/imscp_rootv1p1p2.xsd b/include/ims/imscp_rootv1p1p2.xsd
new file mode 100644 (file)
index 0000000..911a7f8
--- /dev/null
@@ -0,0 +1,345 @@
+<?xml version="1.0"?>
+
+<!-- edited with XML Spy v3.5 (http://www.xmlspy.com) by Thomas Wason (private) -->
+<!-- filename=ims_cp_rootv1p1p2.xsd -->
+<!-- Copyright (2) 2001 IMS Global Learning Consortium, Inc. -->
+<!-- edited by Thomas Wason  -->
+<!-- Conforms to w3c http://www.w3.org/TR/xmlschema-1/ 2000-10-24-->
+
+<xsd:schema xmlns="http://www.imsproject.org/xsd/imscp_rootv1p1p2" 
+            targetNamespace="http://www.imsproject.org/xsd/imscp_rootv1p1p2" 
+            xmlns:xml="http://www.w3.org/XML/1998/namespace" 
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
+            elementFormDefault="unqualified" version="IMS CP 1.1.2">
+
+   <!-- ******************** -->
+   <!-- ** Change History ** -->
+   <!-- ******************** -->
+   <xsd:annotation>
+      <xsd:documentation xml:lang="en">DRAFT XSD for IMS Content Packaging version 1.1 DRAFT</xsd:documentation>
+      <xsd:documentation> Copyright (c) 2001 IMS GLC, Inc. </xsd:documentation>
+      <xsd:documentation>2000-04-21, Adjustments by T.D. Wason from CP 1.0.</xsd:documentation>
+      <xsd:documentation>2001-02-22, T.D.Wason: Modify for 2000-10-24 XML-Schema version.  Modified to support extension.</xsd:documentation>
+      <xsd:documentation>2001-03-12, T.D.Wason: Change filename, target and meta-data namespaces and meta-data fielname.  Add meta-data to itemType, fileType and organizationType.</xsd:documentation>
+      <xsd:documentation>Do not define namespaces for xml in XML instances generated from this xsd.</xsd:documentation>
+      <xsd:documentation>Imports IMS meta-data xsd, lower case element names.         </xsd:documentation>
+      <xsd:documentation>This XSD provides a reference to the IMS meta-data root element as imsmd:record</xsd:documentation>
+      <xsd:documentation>If the IMS meta-data is to be used in the XML instance then the instance must define an IMS meta-data prefix with a namespace.  The meta-data targetNamespace should be used.  </xsd:documentation>
+      <xsd:documentation>2001-03-20, Thor Anderson: Remove manifestref, change resourceref back to identifierref, change manifest back to contained by manifest. --Tom Wason: manifest may contain _none_ or more manifests.</xsd:documentation>
+      <xsd:documentation>2001-04-13 Tom Wason: corrected attirbute name structure.  Was misnamed type.  </xsd:documentation>
+      <xsd:documentation>2001-05-14 Schawn Thropp: Made all complexType extensible with the group.any</xsd:documentation>
+      <xsd:documentation>Added the anyAttribute to all complexTypes. Changed the href attribute on the fileType and resourceType to xsd:string</xsd:documentation>
+      <xsd:documentation>Changed the maxLength of the href, identifierref, parameters, structure attributes to match the Information model.</xsd:documentation>
+      <xsd:documentation>2001-07-25 Schawn Thropp: Changed the namespace for the Schema of Schemas to the 5/2/2001 W3C XML Schema</xsd:documentation> 
+      <xsd:documentation>Recommendation. attributeGroup attr.imsmd deleted, was not used anywhere.  Any attribute declarations that have</xsd:documentation>
+      <xsd:documentation>use = "default" changed to use="optional" - attr.structure.req.</xsd:documentation>
+      <xsd:documentation>Any attribute declarations that have value="somevalue" changed to default="somevalue",</xsd:documentation>
+      <xsd:documentation>attr.structure.req (hierarchical).  Removed references to IMS MD Version 1.1.</xsd:documentation>
+      <xsd:documentation>Modified attribute group "attr.resourcetype.req" to change use from optional</xsd:documentation>
+      <xsd:documentation>to required to match the information model.  As a result the default value also needed to be removed</xsd:documentation> 
+      <xsd:documentation>Name change for XSD.  Changed to match version of CP Spec                                           </xsd:documentation> 
+   </xsd:annotation>
+
+   <xsd:annotation>
+      <xsd:documentation>Inclusions and Imports</xsd:documentation>
+   </xsd:annotation>
+
+   <xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="ims_xml.xsd"/>
+
+   <xsd:annotation>
+      <xsd:documentation>Attribute Declarations</xsd:documentation>
+   </xsd:annotation>
+
+   <!-- **************************** -->
+   <!-- ** Attribute Declarations ** -->
+   <!-- **************************** -->
+   <xsd:attributeGroup name="attr.base">
+      <xsd:attribute ref="xml:base" use="optional"/>
+   </xsd:attributeGroup>
+
+   <xsd:attributeGroup name="attr.default">
+      <xsd:attribute name="default" type="xsd:IDREF" use="optional"/>
+   </xsd:attributeGroup>
+
+   <xsd:attributeGroup name="attr.href">
+      <xsd:attribute name="href" use="optional">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:anyURI">
+               <xsd:maxLength value="2000"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup>
+
+   <xsd:attributeGroup name="attr.href.req">
+      <xsd:attribute name="href" use="required">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:anyURI">
+               <xsd:maxLength value="2000"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup> 
+
+   <xsd:attributeGroup name="attr.identifier.req">
+      <xsd:attribute name="identifier" type="xsd:ID" use="required"/>
+   </xsd:attributeGroup>
+
+   <xsd:attributeGroup name="attr.identifier">
+      <xsd:attribute name="identifier" type="xsd:ID" use="optional"/>
+   </xsd:attributeGroup>
+
+   <xsd:attributeGroup name="attr.isvisible">
+      <xsd:attribute name="isvisible" type="xsd:boolean" use="optional"/>
+   </xsd:attributeGroup>
+   
+   <xsd:attributeGroup name="attr.parameters">
+      <xsd:attribute name="parameters" use="optional">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:string">
+               <xsd:maxLength value="1000"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup>
+   
+   <xsd:attributeGroup name="attr.identifierref">
+      <xsd:attribute name="identifierref" use="optional">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:string">
+               <xsd:maxLength value="2000"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup>
+   
+   <xsd:attributeGroup name="attr.identifierref.req">
+      <xsd:attribute name="identifierref" use="required">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:string">
+               <xsd:maxLength value="2000"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup>
+                
+   <xsd:attributeGroup name="attr.resourcetype.req">
+      <xsd:attribute name="type" use="required">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:string">
+               <xsd:maxLength value="1000"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup>
+
+   <xsd:attributeGroup name="attr.structure.req">
+      <xsd:attribute name="structure" use="optional" default="hierarchical">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:string">
+               <xsd:maxLength value="200"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup>
+
+   <xsd:attributeGroup name="attr.version">
+      <xsd:attribute name="version" use="optional">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:string">
+               <xsd:maxLength value="20"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup>
+
+   <xsd:annotation>
+       <xsd:documentation>element groups</xsd:documentation>
+   </xsd:annotation>
+
+   <xsd:group name="grp.any">
+      <xsd:annotation>
+         <xsd:documentation>Any namespaced element from any namespace may be included within an &quot;any&quot; element.  The namespace for the imported element must be defined in the instance, and the schema must be imported.  </xsd:documentation>
+      </xsd:annotation>
+      <xsd:sequence>
+         <xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:group>
+
+   <!-- ************************** -->
+   <!-- ** Element Declarations ** -->
+   <!-- ************************** -->
+
+   <xsd:element name="dependency" type="dependencyType"/>
+   <xsd:element name="file" type="fileType"/>
+   <xsd:element name="item" type="itemType"/>
+   <xsd:element name="manifest" type="manifestType"/>
+   <xsd:element name="metadata" type="metadataType"/>
+   <xsd:element name="organization" type="organizationType"/>
+   <xsd:element name="organizations" type="organizationsType"/>
+   <xsd:element name="resource" type="resourceType"/>
+   <xsd:element name="resources" type="resourcesType"/>
+   <xsd:element name="schema" type="schemaType"/>
+   <xsd:element name="schemaversion" type="schemaversionType"/>
+   <xsd:element name="title" type="titleType"/>
+
+   <!-- ******************* -->
+   <!-- ** Complex Types ** -->
+   <!-- ******************* -->
+
+   <!-- **************** -->
+   <!-- ** dependency ** -->
+   <!-- **************** -->
+   <xsd:complexType name="dependencyType">
+      <xsd:sequence>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+      <xsd:attributeGroup ref="attr.identifierref.req"/>
+      <xsd:anyAttribute namespace="##other" processContents="strict"/>
+   </xsd:complexType>
+   
+   <!-- ********** -->
+   <!-- ** file ** -->
+   <!-- ********** -->
+   <xsd:complexType name="fileType">
+      <xsd:sequence>
+         <xsd:element ref="metadata" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+      <xsd:attributeGroup ref="attr.href.req"/>
+      <xsd:anyAttribute namespace="##other" processContents="strict"/>
+   </xsd:complexType>
+   
+   <!-- ********** -->
+   <!-- ** item ** -->
+   <!-- ********** -->
+   <xsd:complexType name="itemType">
+      <xsd:sequence>
+         <xsd:element ref="title" minOccurs="0"/>
+         <xsd:element ref="item" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="metadata" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+      <xsd:attributeGroup ref="attr.identifier.req"/>
+      <xsd:attributeGroup ref="attr.identifierref"/>
+      <xsd:attributeGroup ref="attr.isvisible"/>
+      <xsd:attributeGroup ref="attr.parameters"/>
+      <xsd:anyAttribute namespace="##other" processContents="strict"/>
+   </xsd:complexType>
+   
+   <!-- ************** -->
+   <!-- ** manifest ** -->
+   <!-- ************** -->
+   <xsd:complexType name="manifestType">
+      <xsd:sequence>
+         <xsd:element ref="metadata" minOccurs="0"/>
+         <xsd:element ref="organizations"/>
+         <xsd:element ref="resources"/>
+         <xsd:element ref="manifest" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+      <xsd:attributeGroup ref="attr.identifier.req"/>
+      <xsd:attributeGroup ref="attr.version"/>
+      <xsd:attribute ref="xml:base"/>
+      <xsd:anyAttribute namespace="##other" processContents="strict"/>
+   </xsd:complexType>
+   
+   <!-- ************** -->
+   <!-- ** metadata ** -->
+   <!-- ************** -->
+   <xsd:complexType name="metadataType">
+      <xsd:sequence>
+         <xsd:element ref="schema" minOccurs="0"/>
+         <xsd:element ref="schemaversion" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <!-- ******************* -->
+   <!-- ** organizations ** -->
+   <!-- ******************* -->
+   <xsd:complexType name="organizationsType">
+      <xsd:sequence>
+         <xsd:element ref="organization" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+      <xsd:attributeGroup ref="attr.default"/>
+      <xsd:anyAttribute namespace="##other" processContents="strict"/>
+   </xsd:complexType>
+   
+   <!-- ****************** -->
+   <!-- ** organization ** -->
+   <!-- ****************** -->
+   <xsd:complexType name="organizationType">
+      <xsd:sequence>
+         <xsd:element ref="title" minOccurs="0"/>
+         <xsd:element ref="item" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="metadata" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+      <xsd:attributeGroup ref="attr.identifier.req"/>
+      <xsd:attributeGroup ref="attr.structure.req"/>
+      <xsd:anyAttribute namespace="##other" processContents="strict"/>
+   </xsd:complexType>
+   
+   <!-- *************** -->
+   <!-- ** resources ** -->
+   <!-- *************** -->
+   <xsd:complexType name="resourcesType">
+      <xsd:sequence>
+          <xsd:element ref="resource" minOccurs="0" maxOccurs="unbounded"/>
+          <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+      <xsd:attributeGroup ref="attr.base"/>
+      <xsd:anyAttribute namespace="##other" processContents="strict"/>
+   </xsd:complexType>
+   
+   <!-- ************** -->
+   <!-- ** resource ** -->
+   <!-- ************** -->
+   <xsd:complexType name="resourceType">
+      <xsd:sequence>
+         <xsd:element ref="metadata" minOccurs="0"/>
+         <xsd:element ref="file" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="dependency" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+      <xsd:attributeGroup ref="attr.identifier.req"/>
+      <xsd:attributeGroup ref="attr.resourcetype.req"/>
+      <xsd:attributeGroup ref="attr.base"/>
+      <xsd:attributeGroup ref="attr.href"/>
+      <xsd:anyAttribute namespace="##other" processContents="strict"/>
+   </xsd:complexType>
+
+   <!-- ****************** -->
+   <!-- ** Simple Types ** -->
+   <!-- ****************** -->
+
+   <!-- ************ -->
+   <!-- ** schema ** -->
+   <!-- ************ -->
+   <xsd:simpleType name="schemaType">
+      <xsd:restriction base="xsd:string">
+         <xsd:maxLength value="100"/>
+      </xsd:restriction>
+   </xsd:simpleType>
+   
+   <!-- ******************* -->
+   <!-- ** schemaversion ** -->
+   <!-- ******************* -->
+   <xsd:simpleType name="schemaversionType">
+      <xsd:restriction base="xsd:string">
+         <xsd:maxLength value="20"/>
+      </xsd:restriction>
+   </xsd:simpleType>
+   
+   <!-- *********** -->
+   <!-- ** title ** -->
+   <!-- *********** -->
+   <xsd:simpleType name="titleType">
+      <xsd:restriction base="xsd:string">
+         <xsd:maxLength value="200"/>
+      </xsd:restriction>
+   </xsd:simpleType>
+
+</xsd:schema>
diff --git a/include/ims/imsmd_rootv1p2p1.xsd b/include/ims/imsmd_rootv1p2p1.xsd
new file mode 100644 (file)
index 0000000..99bb356
--- /dev/null
@@ -0,0 +1,573 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- edited by Thomas Wason  -->
+<xsd:schema targetNamespace="http://www.imsglobal.org/xsd/imsmd_rootv1p2p1" 
+            xmlns:xml="http://www.w3.org/XML/1998/namespace" 
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
+            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+            xmlns="http://www.imsglobal.org/xsd/imsmd_rootv1p2p1" 
+            elementFormDefault="qualified" 
+            version="1.2:1.1 IMS:MD1.2">
+
+   <xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="ims_xml.xsd"/> 
+
+   <!-- ******************** -->
+   <!-- ** Change History ** -->
+   <!-- ******************** -->
+   <xsd:annotation>
+      <xsd:documentation>2001-04-26 T.D.Wason. IMS meta-data 1.2 XML-Schema.                                  </xsd:documentation>
+      <xsd:documentation>2001-06-07 S.E.Thropp. Changed the multiplicity on all elements to match the         </xsd:documentation>
+      <xsd:documentation>Final 1.2 Binding Specification.                                                     </xsd:documentation>
+      <xsd:documentation>Changed all elements that use the langstringType to a multiplicy of 1 or more        </xsd:documentation>
+      <xsd:documentation>Changed centity in the contribute element to have a multiplicity of 0 or more.       </xsd:documentation>
+      <xsd:documentation>Changed the requirement element to have a multiplicity of 0 or more.                 </xsd:documentation>
+      <xsd:documentation> 2001-07-25 Schawn Thropp.  Updates to bring the XSD up to speed with the W3C        </xsd:documentation>
+      <xsd:documentation> XML Schema Recommendation.  The following changes were made: Change the             </xsd:documentation>
+      <xsd:documentation> namespace to reference the 5/2/2001 W3C XML Schema Recommendation,the base          </xsd:documentation>
+      <xsd:documentation> type for the durtimeType, simpleType, was changed from timeDuration to duration.    </xsd:documentation>              
+      <xsd:documentation> Any attribute declarations that have use="default" had to change to use="optional"  </xsd:documentation>
+      <xsd:documentation> - attr.type.  Any attribute declarations that have value ="somevalue" had to change </xsd:documentation>
+      <xsd:documentation> to default = "somevalue" - attr.type (URI)                                          </xsd:documentation>
+      <xsd:documentation> 2001-09-04 Schawn Thropp                                                            </xsd:documentation>
+      <xsd:documentation> Changed the targetNamespace and namespace of schema to reflect version change       </xsd:documentation>
+   </xsd:annotation>
+
+   <!-- *************************** -->
+   <!-- ** Attribute Declaration ** -->
+   <!-- *************************** -->
+
+   <xsd:attributeGroup name="attr.type">
+      <xsd:attribute name="type" use="optional" default="URI">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:string">
+               <xsd:enumeration value="URI"/>
+               <xsd:enumeration value="TEXT"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup>
+
+   <xsd:group name="grp.any">
+      <xsd:annotation>
+         <xsd:documentation>Any namespaced element from any namespace may be used for an &quot;any&quot; element.  The namespace for the imported element must be defined in the instance, and the schema must be imported.  </xsd:documentation>
+      </xsd:annotation>
+      <xsd:sequence>
+         <xsd:any namespace="##any" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:group>
+
+   <!-- ************************* -->
+   <!-- ** Element Declaration ** -->
+   <!-- ************************* -->
+
+   <xsd:element name="aggregationlevel" type="aggregationlevelType"/>
+   <xsd:element name="annotation" type="annotationType"/>
+   <xsd:element name="catalogentry" type="catalogentryType"/>
+   <xsd:element name="catalog" type="catalogType"/>
+   <xsd:element name="centity" type="centityType"/>
+   <xsd:element name="classification" type="classificationType"/>
+   <xsd:element name="context" type="contextType"/>
+   <xsd:element name="contribute" type="contributeType"/>
+   <xsd:element name="copyrightandotherrestrictions" type="copyrightandotherrestrictionsType"/>
+   <xsd:element name="cost" type="costType"/>
+   <xsd:element name="coverage" type="coverageType"/>
+   <xsd:element name="date" type="dateType"/>
+   <xsd:element name="datetime" type="datetimeType"/>
+   <xsd:element name="description" type="descriptionType"/>
+   <xsd:element name="difficulty" type="difficultyType"/>
+   <xsd:element name="educational" type="educationalType"/>
+   <xsd:element name="entry" type="entryType"/>
+   <xsd:element name="format" type="formatType"/>
+   <xsd:element name="general" type="generalType"/>
+   <xsd:element name="identifier" type="xsd:string"/>
+   <xsd:element name="intendedenduserrole" type="intendedenduserroleType"/>
+   <xsd:element name="interactivitylevel" type="interactivitylevelType"/>
+   <xsd:element name="interactivitytype" type="interactivitytypeType"/>
+   <xsd:element name="keyword" type="keywordType"/>
+   <xsd:element name="kind" type="kindType"/>
+   <xsd:element name="langstring" type="langstringType"/>
+   <xsd:element name="language" type="xsd:string"/>
+   <xsd:element name="learningresourcetype" type="learningresourcetypeType"/>
+   <xsd:element name="lifecycle" type="lifecycleType"/>
+   <xsd:element name="location" type="locationType"/>
+   <xsd:element name="lom" type="lomType"/>
+   <xsd:element name="maximumversion" type="minimumversionType"/>
+   <xsd:element name="metadatascheme" type="metadataschemeType"/>
+   <xsd:element name="metametadata" type="metametadataType"/>
+   <xsd:element name="minimumversion" type="maximumversionType"/>
+   <xsd:element name="name" type="nameType"/>
+   <xsd:element name="purpose" type="purposeType"/>
+   <xsd:element name="relation" type="relationType"/>
+   <xsd:element name="requirement" type="requirementType"/>
+   <xsd:element name="resource" type="resourceType"/>
+   <xsd:element name="rights" type="rightsType"/>
+   <xsd:element name="role" type="roleType"/>
+   <xsd:element name="semanticdensity" type="semanticdensityType"/>
+   <xsd:element name="size" type="sizeType"/>
+   <xsd:element name="source" type="sourceType"/>
+   <xsd:element name="status" type="statusType"/>
+   <xsd:element name="structure" type="structureType"/>
+   <xsd:element name="taxon" type="taxonType"/>
+   <xsd:element name="taxonpath" type="taxonpathType"/>
+   <xsd:element name="technical" type="technicalType"/>
+   <xsd:element name="title" type="titleType"/>
+   <xsd:element name="type" type="typeType"/>
+   <xsd:element name="typicalagerange" type="typicalagerangeType"/>
+   <xsd:element name="typicallearningtime" type="typicallearningtimeType"/>
+   <xsd:element name="value" type="valueType"/>
+   <xsd:element name="person" type="personType"/>
+   <xsd:element name="vcard" type="xsd:string"/>
+   <xsd:element name="version" type="versionType"/>
+   <xsd:element name="installationremarks" type="installationremarksType"/>
+   <xsd:element name="otherplatformrequirements" type="otherplatformrequirementsType"/>
+   <xsd:element name="duration" type="durationType"/>
+   <xsd:element name="id" type="idType"/>
+
+   <!-- ******************* -->
+   <!-- ** Complex Types ** -->
+   <!-- ******************* -->
+
+   <xsd:complexType name="aggregationlevelType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="annotationType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="person" minOccurs="0"/>
+         <xsd:element ref="date" minOccurs="0"/>
+         <xsd:element ref="description" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="catalogentryType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="catalog"/>
+         <xsd:element ref="entry"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="centityType">
+      <xsd:sequence>
+         <xsd:element ref="vcard"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="classificationType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="purpose" minOccurs="0"/>
+         <xsd:element ref="taxonpath" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="description" minOccurs="0"/>
+         <xsd:element ref="keyword" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="contextType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="contributeType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="role"/>
+         <xsd:element ref="centity" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="date" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="copyrightandotherrestrictionsType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="costType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="coverageType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="dateType">
+      <xsd:sequence>
+         <xsd:element ref="datetime" minOccurs="0"/>
+         <xsd:element ref="description" minOccurs="0"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="descriptionType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="difficultyType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="durationType">
+      <xsd:sequence>
+         <xsd:element ref="datetime" minOccurs="0"/>
+         <xsd:element ref="description" minOccurs="0"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="educationalType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="interactivitytype" minOccurs="0"/>
+         <xsd:element ref="learningresourcetype" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="interactivitylevel" minOccurs="0"/>
+         <xsd:element ref="semanticdensity" minOccurs="0"/>
+         <xsd:element ref="intendedenduserrole" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="context" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="typicalagerange" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="difficulty" minOccurs="0"/>
+         <xsd:element ref="typicallearningtime" minOccurs="0"/>
+         <xsd:element ref="description" minOccurs="0"/>
+         <xsd:element ref="language" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="entryType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="generalType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="identifier" minOccurs="0"/>
+         <xsd:element ref="title" minOccurs="0"/>
+         <xsd:element ref="catalogentry" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="language" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="description" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="keyword" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="coverage" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="structure" minOccurs="0"/>
+         <xsd:element ref="aggregationlevel" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="installationremarksType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="intendedenduserroleType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="interactivitylevelType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="interactivitytypeType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="keywordType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="kindType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="langstringType">
+      <xsd:simpleContent>
+         <xsd:extension base="xsd:string">
+            <xsd:attribute ref="xml:lang"/>
+         </xsd:extension>
+      </xsd:simpleContent>
+   </xsd:complexType>
+   
+   <xsd:complexType name="learningresourcetypeType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="lifecycleType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="version" minOccurs="0"/>
+         <xsd:element ref="status" minOccurs="0"/>
+         <xsd:element ref="contribute" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="locationType">
+      <xsd:simpleContent>
+         <xsd:extension base="xsd:string">
+            <xsd:attributeGroup ref="attr.type"/>
+         </xsd:extension>
+      </xsd:simpleContent>
+   </xsd:complexType>
+   
+   <xsd:complexType name="lomType">
+      <xsd:sequence>
+         <xsd:element ref="general" minOccurs="0"/>
+         <xsd:element ref="lifecycle" minOccurs="0"/>
+         <xsd:element ref="metametadata" minOccurs="0"/>
+         <xsd:element ref="technical" minOccurs="0"/>
+         <xsd:element ref="educational" minOccurs="0"/>
+         <xsd:element ref="rights" minOccurs="0"/>
+         <xsd:element ref="relation" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="annotation" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="classification" minOccurs="0" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="metametadataType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="identifier" minOccurs="0"/>
+         <xsd:element ref="catalogentry" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="contribute" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="metadatascheme" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="language" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="nameType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="otherplatformrequirementsType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="personType">
+      <xsd:sequence>
+         <xsd:element ref="vcard"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="purposeType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="relationType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="kind" minOccurs="0"/>
+         <xsd:element ref="resource" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="requirementType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="type" minOccurs="0"/>
+         <xsd:element ref="name" minOccurs="0"/>
+         <xsd:element ref="minimumversion" minOccurs="0"/>
+         <xsd:element ref="maximumversion" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="resourceType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="identifier" minOccurs="0"/>
+         <xsd:element ref="description" minOccurs="0"/>
+         <xsd:element ref="catalogentry" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="rightsType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="cost" minOccurs="0"/>
+         <xsd:element ref="copyrightandotherrestrictions" minOccurs="0"/>
+         <xsd:element ref="description" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="roleType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="semanticdensityType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="sourceType">
+      <xsd:sequence>
+         <xsd:element ref="langstring"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="statusType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="stringType">
+      <xsd:simpleContent>
+         <xsd:extension base="xsd:string">
+            <xsd:attribute ref="xml:lang"/>
+         </xsd:extension>
+      </xsd:simpleContent>
+   </xsd:complexType>
+   
+   <xsd:complexType name="structureType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="taxonpathType">
+      <xsd:sequence>
+         <xsd:element ref="source" minOccurs="0"/>
+         <xsd:element ref="taxon" minOccurs="0" maxOccurs="1"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="taxonType">
+      <xsd:sequence>
+         <xsd:element ref="id" minOccurs="0"/>
+         <xsd:element ref="entry" minOccurs="0"/>
+         <xsd:element ref="taxon" minOccurs="0" maxOccurs="1"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="technicalType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="format" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="size" minOccurs="0"/>
+         <xsd:element ref="location" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="requirement" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="installationremarks" minOccurs="0"/>
+         <xsd:element ref="otherplatformrequirements" minOccurs="0"/>
+         <xsd:element ref="duration" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="titleType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="typeType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="typicalagerangeType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="typicallearningtimeType">
+      <xsd:sequence>
+         <xsd:element ref="datetime" minOccurs="0"/>
+         <xsd:element ref="description" minOccurs="0"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="valueType">
+      <xsd:sequence>
+         <xsd:element ref="langstring"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="versionType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <!-- ****************** -->
+   <!-- ** Simple Types ** -->
+   <!-- ****************** -->
+   
+   <xsd:simpleType name="formatType">
+      <xsd:restriction base="xsd:string"/>
+   </xsd:simpleType>
+   
+   <xsd:simpleType name="sizeType">
+      <xsd:restriction base="xsd:int"/>
+   </xsd:simpleType>
+   
+   <xsd:simpleType name="datetimeType">
+      <xsd:restriction base="xsd:string"/>
+   </xsd:simpleType>
+   
+   <xsd:simpleType name="idType">
+      <xsd:restriction base="xsd:string"/>
+   </xsd:simpleType>
+   
+   <xsd:simpleType name="metadataschemeType">
+      <xsd:restriction base="xsd:string"/>
+   </xsd:simpleType>
+   
+   <xsd:simpleType name="catalogType">
+      <xsd:restriction base="xsd:string"/>
+   </xsd:simpleType>
+   
+   <xsd:simpleType name="minimumversionType">
+      <xsd:restriction base="xsd:string"/>
+   </xsd:simpleType>
+   
+   <xsd:simpleType name="maximumversionType">
+      <xsd:restriction base="xsd:string"/>
+   </xsd:simpleType>
+
+</xsd:schema>
diff --git a/include/index.html b/include/index.html
new file mode 100644 (file)
index 0000000..bbd0b35
--- /dev/null
@@ -0,0 +1 @@
+this is a blank page
\ No newline at end of file
diff --git a/include/lib/admin_categories.inc.php b/include/lib/admin_categories.inc.php
new file mode 100644 (file)
index 0000000..115b984
--- /dev/null
@@ -0,0 +1,150 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+/* prints out the given $categories as an HTML list */
+/* $categories: categories given, where the key is the cat_id */
+/* $cat_id: the current category id */
+function print_categories($categories, $cat_id) {
+       if ($cat_id == 0) {
+               echo '<ul>';
+               foreach($categories[0] as $child_cat_id) {
+                       print_categories($categories, $child_cat_id);
+               }
+               echo '</ul>';
+       } else {
+               echo '<li>';
+               if ($cat_id == $_REQUEST['cat_id']) {
+                       echo '<strong>'.$categories[$cat_id]['cat_name'].'</strong>';
+               } else if ($cat_id == $_REQUEST['pcat_id']) {
+                       echo '<a href="'.$_SERVER['PHP_SELF'].'?cat_id='.$cat_id.'"><b>'.$categories[$cat_id]['cat_name'].'</b></a>';
+               } else {
+                       echo '<a href="'.$_SERVER['PHP_SELF'].'?cat_id='.$cat_id.'">'.$categories[$cat_id]['cat_name'].'</a>';
+               }
+               echo ' <small class="spacer">('.$categories[$cat_id]['num_courses'].' ';
+               if ($categories[$cat_id]['num_courses'] == 1) {
+                       echo _AT('course');
+               } else {
+                       echo _AT('courses');
+               }
+               
+               echo ')</small>';
+               if (is_array($categories[$cat_id]['children'])) {
+                       echo '<ul>';
+                       foreach($categories[$cat_id]['children'] as $child_cat_id) {
+                               print_categories($categories, $child_cat_id);
+                       }
+                       echo '</ul>';
+               }
+               echo '</li>';
+       }
+}
+
+/* generates a <select> of the given $categories */
+/* $cat_id: the current cat id to start the traversal */
+/* $current_cat_id: the current category id, will be set to "selected" if $exclude is false o/w the parent will be selected */
+/* $exclude: whether or not the children of $current_cat_id should be excluded or not. */
+/* $depth: just keeps track of how deep the $cat_id is */
+function select_categories($categories, $cat_id, $current_cat_id, $exclude, $depth=0) {
+       if ($cat_id == 0 && is_array($categories[0])) {
+               foreach($categories[0] as $child_cat_id) {
+                       select_categories($categories, $child_cat_id, $current_cat_id, $exclude);
+               }
+       } else {
+               if ($exclude && ($cat_id == $current_cat_id)) {
+                       return;
+               }
+               echo '<option value="'.$cat_id.'"';
+
+               if ($exclude && is_array($categories[$cat_id]['children']) && in_array($current_cat_id, $categories[$cat_id]['children'])) {
+                       echo ' selected="selected"';
+               } else if (!$exclude && ($cat_id == $current_cat_id)) {
+                       echo ' selected="selected"';
+               }
+               echo '>';
+               echo str_repeat("&nbsp;", $depth*4);
+               echo validate_length($categories[$cat_id]['cat_name'], 45, VALIDATE_LENGTH_FOR_DISPLAY).'</option>';
+
+               if (is_array($categories[$cat_id]['children'])) {
+                       foreach($categories[$cat_id]['children'] as $child_cat_id) {
+                               select_categories($categories, $child_cat_id, $current_cat_id, $exclude, $depth+1);
+                       }
+               }
+       }
+}
+
+function get_categories() {
+       global $db;
+
+       $categories = array();
+
+       /* get all the categories: */
+       /* $categories[category_id] = array(cat_name, cat_parent, num_courses, [array(children)]) */
+       $sql = "SELECT * FROM ".TABLE_PREFIX."course_cats ORDER BY cat_parent, cat_name";
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_assoc($result)) {
+               $categories[$row['cat_id']]['cat_name']    = $row['cat_name'];
+               $categories[$row['cat_id']]['cat_parent']  = $row['cat_parent'];
+               $categories[$row['cat_id']]['num_courses'] = 0;
+               $categories[$row['cat_id']]['theme']       = $row['theme'];
+
+               if ($row['cat_parent'] >0) {
+                       $categories[$row['cat_parent']]['children'][] = $row['cat_id'];
+               } else {
+                       $categories[0][] = $row['cat_id'];
+               }
+       }
+       return $categories;
+}
+
+/* assigns the 'num_courses' field in the $categories array */
+/* returns the number of uncategorized courses */
+function assign_categories_course_count(&$categories) {
+       global $db;
+
+       $num_uncategorized = 0;
+
+       $sql = "SELECT cat_id, COUNT(*) AS cnt FROM ".TABLE_PREFIX."courses GROUP BY cat_id";
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_assoc($result)) {
+               if ($row['cat_id'] == 0) {
+                       $num_uncategorized = $row['cnt'];
+               } else {
+                       $categories[$row['cat_id']]['num_courses'] = $row['cnt'];
+               }
+       }
+
+       return $num_uncategorized;
+}
+
+/* applies $theme to all the sub-categories recursively. */
+/* returns an array of all the subcategories */
+function recursive_get_subcategories($category_parent_id) {
+       static $categories;
+       if (!isset($categories)) {
+               $categories = get_categories();
+       }
+
+       $children = array();
+       if (isset($categories[$category_parent_id]['children']) && is_array($categories[$category_parent_id]['children'])) {
+               $children = $categories[$category_parent_id]['children'];
+               foreach ($categories[$category_parent_id]['children'] as $category_child_id) {
+                       if ($category_child_id) {
+                               $children =  array_merge($children, recursive_get_subcategories($category_child_id));
+                       }
+               }
+       }
+       return $children;
+}
+
+?>
\ No newline at end of file
diff --git a/include/lib/chat.inc.php b/include/lib/chat.inc.php
new file mode 100644 (file)
index 0000000..f870194
--- /dev/null
@@ -0,0 +1,555 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+function getAdminSettings() {
+       if (!file_exists(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings')) {
+               return 0;
+       }
+
+       $admin = array();
+
+       $file_prefs = file(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings');
+       foreach ($file_prefs as $pref) {
+               $pref = explode('=', $pref, 2);
+               $admin[$pref[0]] = trim($pref[1]);
+       }
+
+    if ($admin['returnT'] && $admin['returnL']) {
+        $admin['returnLink'] = '<a href="'.$admin['returnL'].'">'.$admin['returnT'].'</a>';
+    } else {
+        $admin['returnLink'] = '';
+    }
+
+       return $admin;
+}
+
+require('chat_defaults.inc.php');
+$admin = getAdminSettings();
+if ($admin === 0) {
+       $admin = defaultAdminSettings();
+}
+
+function postMessage($chatID, $message, &$topMsgNum, &$bottomMsgNum) {
+       global $admin;
+
+       $topMsgNum++;
+       if (!is_dir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/msgs')) {
+               @mkdir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/msgs');
+       }
+       $fp = @fopen(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/msgs/'.$topMsgNum.'.message', 'w+');
+       if (!$fp) {
+               // error
+               return 0;
+       }
+
+       flock($fp, LOCK_EX);
+       if (!@fwrite($fp, $chatID."\n".$message."\n")) {
+               return 0;
+       }
+       flock($fp, LOCK_UN);
+       fclose($fp);
+       chmod(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/msgs/'.$topMsgNum.'.message', 0600);
+
+       /* the transcript: */
+    if ($admin['produceTran'] > 0) {
+               global $myPrefs;
+               $message = htmlspecialchars($message);
+        $colourT = getChatIDColour($chatID,  'whiteBlack');
+        printToTran('<tr><td valign="top"><span style="color: '.$colourT.';">'.stripslashes($chatID).'</span></td><td><span style="color: '.$colourT.';">'.stripslashes($message).'</span></td></tr>');
+    }
+}
+
+function printToTran($message) {
+       global $admin;
+       $fp = fopen(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/tran/'.$admin['tranFile'], 'a');
+       if ($fp) {
+               fwrite($fp, $message."\n");
+       }else{
+               echo "nope";
+               exit;
+       }
+       @fclose($fp);
+}
+
+function howManyMessages(&$topMsgNum, &$bottomMsgNum) {
+    $topMsgNum = 0;
+    $bottomMsgNum = 0;
+       
+       if ($dir = @opendir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/msgs/')) {
+               while (($file = readdir($dir)) !== false) {
+                       if (($file == '..') || ($file == '.')) {
+                               continue;
+                       }
+                       $tempNum = substr($file, 0, -strlen('.message'));
+                       if ($tempNum > $topMsgNum) {
+                               $topMsgNum = $tempNum;
+                       }
+                       if (($tempNum < $bottomMsgNum) || ($bottomMsgNum == 0)) {
+                               $bottomMsgNum = $tempNum;
+                       }
+               }  
+               closedir($dir);
+       }
+}
+
+
+
+function getChatIDColour($chatID, $colours) {
+    $refNumT1 = strlen($chatID);
+    $char2T = substr($chatID, -1);
+    $refNumT2 = letterToNumber($char2T);
+       $char3T = substr($chatID, -2, 1);
+    $refNumT3 = letterToNumber($char3T);
+       $colourStr = '#';
+
+       if (($colours == 'blackYellow')
+                       || ($colours == 'blueWhite')
+                       || ($colours == 'blackWhite'))
+       {
+               if ($refNumT1%3 == 0) { 
+                       $colourStr .= 'ff';
+               } else if ($refNumT1%3 == 1) { 
+                       $colourStr .= 'cc';
+               } else { 
+                       $colourStr .= '99';
+               }
+
+               if ($refNumT2%3 == 0) { 
+                       $colourStr .= 'ff';
+               } else if ($refNumT2%3 == 1) { 
+                       $colourStr .= 'cc';
+               } else { 
+                       $colourStr .= '99'; 
+               }
+
+               if ($refNumT3%3 == 0) { 
+                       $colourStr .= 'ff';
+               } else if ($refNumT3%3 == 1) { 
+                       $colourStr .= 'cc';
+               } else { 
+                  $colourStr .= '99';
+               }
+       } else {
+               if ($refNumT1%3 == 0) { 
+                       $colourStr .= '00';
+               } else if ($refNumT1%3 == 1) { 
+                       $colourStr .= '33';
+               } else { 
+                       $colourStr .= '66';
+               }
+               if ($refNumT2%3 == 0) { 
+                       $colourStr .= '00';
+               } else if ($refNumT2%3 == 1) { 
+                       $colourStr .= '33';
+               } else { 
+                       $colourStr .= '66'; 
+               }
+               if ($refNumT3%3 == 0) { 
+                       $colourStr .= '00';
+               } else if ($refNumT3%3 == 1) {
+                       $colourStr .= '33';
+               } else { 
+                       $colourStr .= '66';
+               }
+    }
+    return $colourStr;
+}
+
+function letterToNumber($letter) {
+       $letter = strtolower($letter);
+
+    if ($letter == '0') { return 0; }
+    if ($letter == '1') { return 1; }
+    if ($letter == '2') { return 2; }
+    if ($letter == '3') { return 3; }
+    if ($letter == '4') { return 4; }
+    if ($letter == '5') { return 5; }
+    if ($letter == '6') { return 6; }
+    if ($letter == '7') { return 7; }
+    if ($letter == '8') { return 8; }
+    if ($letter == '9') { return 9; }
+    if ($letter == 'b') { return 10; }
+    if ($letter == 'c') { return 11; }
+    if ($letter == 'd') { return 12; }
+    if ($letter == 'e') { return 13; }
+    if ($letter == 'f') { return 14; }
+    if ($letter == 'g') { return 15; }
+    if ($letter == 'h') { return 16; }
+    if ($letter == 'i') { return 17; }
+    if ($letter == 'j') { return 18; }
+    if ($letter == 'k') { return 19; }
+    if ($letter == 'l') { return 20; }
+    if ($letter == 'm') { return 21; }
+    if ($letter == 'n') { return 22; }
+    if ($letter == 'o') { return 23; }
+    if ($letter == 'p') { return 24; }
+    if ($letter == 'q') { return 25; }
+    if ($letter == 'r') { return 26; }
+    if ($letter == 's') { return 27; }
+    if ($letter == 't') { return 28; }
+    if ($letter == 'u') { return 30; }
+    if ($letter == 'v') { return 31; }
+    if ($letter == 'w') { return 32; }
+    if ($letter == 'x') { return 33; }
+    if ($letter == 'y') { return 34; }
+    if ($letter == 'z') { return 35; }
+
+    return 36;
+}
+
+
+function printStylesheet($prefs) {
+    $h3SizeT = $prefs['fontSize'] + 4;
+    $h4SizeT = $prefs['fontSize'] + 2;
+
+       print "<style type=\"text/css\"><!--
+    BODY { margin: 5; }
+    TD { font-family: $prefs[fontFace]; font-size: $prefs[fontSize]; }
+    LI { font-family: $prefs[fontFace]; font-size: $prefs[fontSize]; }
+    UL { margin-left: 40; margin-right: 40; margin-top: 5; margin-bottom: 5; }
+    H3 { font-size: $h3SizeT; margin: 0; font-family: $prefs[fontFace]; }
+    H4 { font-size: $h4SizeT; margin: 0; font-family: $prefs[fontFace]; }
+    B { font-size: $h4SizeT; }
+    A { font-size: $prefs[fontSize]; font-weight: bold; color: $prefs[front]; text-decoration: underline; }
+    A:hover { font-size: $prefs[fontSize]; font-weight: bold; background-color: $prefs[darkBack]; text-decoration: underline; }
+    P { margin-left: 0; margin-right: 0; margin-top: 0; margin-bottom: 10; padding-left: 20; padding-right: 20; padding-top: 5; padding-bottom: 10; font-family: $prefs[fontFamily]; font-size: $prefs[fontSize]; }
+    P.light { background-color: $prefs[lightBack]; font-family: $prefs[fontFace]; font-size: $prefs[fontSize]; }
+    FORM { margin-left: 0; margin-right: 0; margin-top: 10; margin-bottom: 10; }
+    --></style>\n";
+}
+
+function getLastAccessed($chatID) {
+       $tempPrefs = getPrefs($chatID, false);
+       return $tempPrefs['lastAccessed'];
+}
+
+function &defaultAdminSettings() {
+       $admin = array();
+
+    //$admin['cgiURL'] = 'http://dev.atutor.ca/chat/';
+    //$admin['htmlDir'] = '/usr/webserver/content/snow/chat/';
+    //$admin['htmlURL'] = 'http://dev.atutor.ca/discussions/achat/';
+    $admin['msgLifeSpan']              = 1800;         /* 30 min  */
+    $admin['chatIDLifeSpan']   = 2678400;      /* 1 month */
+    $admin['chatSessionLifeSpan'] = 3600;      /* 1 hour  */
+    //$admin['chatName'] = 'Accessible Chat';
+    //$admin['chatIDListFlag'] = 0;
+   // $admin['returnL'] = 'http://dev.atutor.ca';
+    //$admin['returnT'] = 'Return to the ATRC';
+    //$admin['adminPass'] = 'temppass';
+
+       return $admin;
+}
+/*
+function getAdminSettings() {
+       if (!file_exists('admin.settings')) {
+               return 0;
+       }
+
+       $admin = array();
+
+       $file_prefs = file('admin.settings');
+       foreach ($file_prefs as $pref) {
+               $pref = explode('=', $pref, 2);
+               $admin[$pref[0]] = trim($pref[1]);
+       }
+
+    if ($admin['returnT'] && $admin['returnL']) {
+        $admin['returnLink'] = '<a href="'.$admin['returnL'].'">'.$admin['returnT'].'</a>';
+    } else {
+        $admin['returnLink'] = '';
+    }
+
+       return $admin;
+}
+*/
+function resetLastAccessed($chatID) {
+       $tempPrefs = getPrefs($chatID);
+       $tempPrefs['lastAccessed'] = 0;
+       writePrefs($tempPrefs, $chatID);
+
+       /*
+    open(LA,">$cgiDIR"."users/$tempChatID.la") || &printError("resetLastAccessed","$!");
+    flock(LA,2);
+    print LA "0\n";
+    close(LA);
+    chmod (0666, "$cgiDIR"."users/$tempChatID.la");
+       */
+}
+
+
+
+function cleanUp() {
+       global $admin;
+    $msgLifeSpan                       = $admin['msgLifeSpan'];
+    $chatSessionLifeSpan       = $admin['chatSessionLifeSpan'];
+    $chatIDLifeSpan                    = $admin['chatIDLifeSpan'];
+
+       $now = time();
+
+       if (!$msgLifeSpan || !$chatSessionLifeSpan || !$chatIDLifeSpan) {
+        echo 'Nope, something missing: '.$msgLifeSpan.', '.$chatSessionLifeSpan.', '.$chatIDLifeSpan.'<br />';
+    } else {
+               /* Clean up messages */
+               if ($dir = @opendir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/msgs/')) {
+                       while (($file = readdir($dir)) !== false) {
+                               if (substr($file, -strlen('.message')) == '.message') {
+                                       $info = @stat(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/msgs/'.$file);
+                                       if ($now - $info['mtime'] > $msgLifeSpan) {
+                                               unlink(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/msgs/'.$file);
+                                       }
+                               }
+                       }
+               }
+
+               /* Clean up inactive users (doesn't delete the users, just logs them out) */
+               if ($dir = @opendir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/users/')) {
+                       while (($file = readdir($dir)) !== false) {
+                               if (substr($file, -strlen('.prefs')) == '.prefs') {
+                                       $chatName = substr($file, 0, -strlen('.prefs'));
+                                       $la     = getLastAccessed($chatName);
+                                       if ($now - $la > $chatSessionLifeSpan && $la > 0) {
+                                               postMessage('system',
+                                                       'User '.$chatName.' has been logged out due to inactivity.',
+                                                       $topMsgNum,
+                                                       $bottomMsgNum);
+                                               resetLastAccessed($chatName);
+
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+
+/* @See ./history.php */
+function getLower20Bound($topNum, $bottomMsgNum) {
+    for ($i = $topNum; ($i-$bottomMsgNum)%20 !=0; $i--) { ; }
+    return $i;
+}
+
+
+function showMessage($msgNum, &$prefs) {
+       if (file_exists(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/msgs/'.$msgNum.'.message')) {
+               $msg = file(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/msgs/'.$msgNum.'.message');
+
+               $sender = trim($msg[0]);
+               $msg = stripslashes(htmlspecialchars(trim($msg[1])));
+        $colour = getChatIDColour($sender, $prefs['colours']);
+       
+        if ($msgNum > $prefs['lastRead']) {
+            echo '<tr><td width="75" class="row1" align="right"><b><span style="color: '.$colour.';">'.stripslashes($sender).'</span></b>:</td><td class="row1"><b><span style="color: '.$colour.';">'.$msg.'</span></b></td></tr>';
+        } else {
+            echo '<tr><td width="75" class="row1" align="right"><span style="color: '.$colour.';">'.stripslashes($sender).'</span>:</td><td class="row1"><span style="color: '.$colour.';">'.$msg.'</span></td></tr>';
+        }
+       }
+
+}
+
+
+/* @See ./filterHistory.php */
+function showMessageFiltered($msgNum, &$prefs, $chatID) {
+    if (file_exists(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/msgs/'.$msgNum.'.message')) {
+               $msg = file(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/msgs/'.$msgNum.'.message');
+
+               $sender = trim($msg[0]);
+               $msg = trim($msg[1]);
+
+        if ($sender == $chatID) {
+               $colour = getChatIDColour($sender, $prefs['colours']);
+                       
+                       if ($msgNum > $prefs['lastRead']) {
+                echo '<tr><td width="75" class="row1" align="right"><b><span style="color: '.$colour.';">'.stripslashes($sender).' : </span></b></td><td class="row1"><b><span style="color: '.$colour.';">'.stripslashes($msg).'</span></b></td></tr>';
+            } else {
+                echo '<tr><td width="75" class="row1" align="right"><span style="color: '.$colour.';">'.stripslashes($sender).' : </span></td><td class="row1"><span style="color: '.$colour.';">'.stripslashes($msg).'</span></td></tr>';
+            }
+        }
+    }
+}
+
+/* @See ./prefs.php */
+function getAndWriteFormPrefs(&$prefs) {
+    if (isset($_POST['fontSize'])) { 
+               $prefs['fontSize'] = $_POST['fontSize'];
+       }
+
+    if (isset($_POST['fontFace'])) { 
+               $prefs['fontFace'] = $_POST['fontFace'];
+       }
+
+    if (isset($_POST['colours'])) { 
+               $prefs['colours'] = $_POST['colours'];
+       }
+
+    if (isset($_POST['navigationAidFlag'])) {
+               $prefs['navigationAidFlag'] = $_POST['navigationAidFlag'];
+       }
+
+    if (isset($_POST['newestFirstFlag'])) { 
+               $prefs['newestFirstFlag'] = $_POST['newestFirstFlag'];
+       }
+
+    if (isset($_POST['onlyNewFlag'])) { 
+               $prefs['onlyNewFlag'] = $_POST['onlyNewFlag'];
+       }
+
+    if (isset($_POST['bingFlag'])) { 
+               $prefs['bingFlag'] = $_POST['bingFlag'];
+       }
+
+    if (isset($_POST['refresh'])) { 
+               $prefs['refresh'] = $_POST['refresh'];
+       }
+
+       writePrefs($prefs, $_SESSION['login']);
+}
+
+
+/* @See ./admin.php */
+function writeAdminSettings(&$admin) {
+       if (file_exists(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings')) {
+               chmod(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings', 0755);
+       }
+
+       $fp = @fopen(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings', 'w+');
+       if (!$fp) {
+               // error
+               return 0;
+       }
+
+       $settings = '';
+       foreach ($admin as $prefKey => $prefValue) {
+               $settings .= $prefKey.'='.$prefValue."\n";
+       }
+
+       flock($fp, LOCK_EX);
+       if (!@fwrite($fp, $settings)) {
+               return 0;
+       }
+       flock($fp, LOCK_UN);
+       chmod(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings', 0600);
+
+       return 1;
+}
+
+function clearOutOldChatPrefs() {
+    /* Clear out old user names */
+       $now = time();
+       $return = '';
+       if ($dir = @opendir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/users/')) {
+               while (($file = readdir($dir)) !== false) {
+                       if (substr($file, -strlen('.prefs')) == '.prefs') {
+                               $chatName = substr($file, 0, -strlen('.prefs'));
+                               $la     = @stat(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/users/'.$file);
+                               $la = $la['mtime'];
+
+                               if ($admin['chatIDLifeSpan'] && ($now - $la > $admin['chatIDLifeSpan'])) {
+                                       $return .= 'Automated Clean Up: Deleting old Chat ID '.$chatName.'<br />';
+                                       deleteUser($chatName);
+                               }
+                       }
+               }
+       }
+
+       return $return;
+}
+
+function deleteUser($chatName) {
+    @unlink(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/users/'.$chatName.'.prefs');
+
+       /* the bing file */
+    @unlink ('bings/'.$chatName.'.html');
+}
+
+
+function makeBingFile($chatName) {
+       global $myPrefs, $admin;
+
+    if (($myPrefs['refresh'] == 'manual' && $myPrefs['bingFlag'] > 0)) {
+
+       $bing = '<html><script language="vbscript">
+               option explicit
+               Dim IntervalID
+               Dim count
+               count = 0
+
+               sub loaded
+
+                   IntervalID = Window.setInterval("askServer",5000)
+               end sub
+
+               sub changedF2
+                   askServer
+               end sub
+
+               sub askServer
+                   Dim objAsp, theFile
+                   set objAsp = CreateObject("Microsoft.XMLHTTP")
+                   objAsp.open "GET", "'.$admin[cgiURL].'bing.php?uselessVar=" + CStr(count) + "&chatID='.$chatName.'", false
+                   objAsp.send()
+                   theFile = objAsp.responsetext
+                   if InStr(theFile,"yes") > 0 then
+                       Player.URL = "chime.wav"
+                   else
+                   end if
+                   count = count + 1
+                   document.f1.f2.value = CStr(count) + theFile
+                   objAsp = 3
+                   theFile = ""
+               end sub
+
+               </script>
+               <body onLoad="loaded" language="vbscript">
+               <form name=f1><input type=text name=f2 length="200" /></form>
+               <OBJECT ID="Player" height="0" width="0" CLASSID="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6"></OBJECT>
+               </body>
+               </html>';    
+
+    } else if ($myPrefs['refresh'] == 'manual' && $myPrefs['bingFlag'] > 0) {
+        print "<html>
+        <body bgcolor=\"$myPrefs[back]\">
+        <applet code='MachineThatGoesBing.class' width='1' height='1'>
+        <param name='chatID' value='$chatName' />
+        <param name='url' value='chime.wav' />
+        </applet></body></html>\n";
+    }
+
+       $fp = @fopen('bings/'.$chatName.'.html', 'w+');
+       if ($fp) {
+               flock($fp, LOCK_EX);
+               if (@fwrite($fp, $bing)) {
+                       flock($fp, LOCK_UN);
+               }
+       }
+       @fclose($fp);
+}
+
+
+function securityCheck($uniqueID) {
+       global $myPrefs;
+
+    if ($myPrefs['uniqueID'] == $uniqueID) {
+        return true;
+    }
+    return false;
+}
+
+function printError($err1, $err2) {
+    print "An error has occured. Please <a href='./login.php' target='_top'>login again</a><br />\n";
+    print "$err1 <br />\n";
+    print "$err2 <br />\n";
+       exit;
+}
+
+?>
diff --git a/include/lib/chat_defaults.inc.php b/include/lib/chat_defaults.inc.php
new file mode 100644 (file)
index 0000000..d18ef3f
--- /dev/null
@@ -0,0 +1,169 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+/*function authenticate() {
+       $num_args = func_num_args();
+       $args     = func_get_args();
+
+       for ($i=0; $i < $num_args; $i++) {
+               if ($_SESSION['status'] == $args[$i]) {
+                       return true;
+               }
+       }
+
+       //Header('Location: /sign_in.php');
+       //return false;
+}*/
+function loadDefaultPrefs() {
+       $prefs = array();
+
+    $prefs['colours']          = 'beigeBlack';
+    $prefs['back']                     = 'beige';
+    $prefs['lightBack']                = '#ddeecc';
+    $prefs['darkBack']         = '#bbccaa';
+    $prefs['front']                    = 'black';
+    $prefs['fontSize']         = 12;
+    $prefs['fontFace']         = 'arial';
+    $prefs['idColour']         = 'black';
+    $prefs['bingFlag']         = 0;
+    $prefs['onlyNewFlag']      = 0;
+    $prefs['newestFirstFlag']  = 1;
+    $prefs['navigationAidFlag'] = 0;
+    $prefs['refresh']          = 20;
+    $prefs['lastRead']         = 0;
+    $prefs['lastChecked']      = 0;
+    $prefs['lastAccessed']     = time();
+       // password
+       // uniqueID
+
+       if ($myPrefs['colours'] == 'beigeBlack') {
+        $myPrefs['back'] = 'beige';
+        $myPrefs['front'] = 'black';
+        $myPrefs['lightBack'] = '#ddeecc';
+        $myPrefs['darkBack'] = '#bbccaa';
+    } else if ($myPrefs['colours'] == 'whiteBlack') {
+        $myPrefs['back'] = 'white';
+        $myPrefs['front'] = 'black';
+        $myPrefs['lightBack'] = '#ddeecc';
+        $myPrefs['darkBack'] = '#bbccaa';
+    } else if ($myPrefs['colours'] == 'whiteBlue') {
+        $myPrefs['back'] = 'white';
+        $myPrefs['front'] = '000066';
+        $myPrefs['lightBack'] = '#ffddcc';
+        $myPrefs['darkBack'] = '#ddbbaa';
+    } else if ($myPrefs['colours'] == 'blackYellow') {
+        $myPrefs['back'] = 'black';
+        $myPrefs['front'] = 'yellow';
+        $myPrefs['lightBack'] = '#333333';
+        $myPrefs['darkBack'] = '#666666';
+    } else if ($myPrefs['colours'] == 'blackWhite') {
+        $myPrefs['back'] = 'black';
+        $myPrefs['front'] = 'white';
+        $myPrefs['lightBack'] = '#333333';
+        $myPrefs['darkBack'] = '#666666';
+    } else { /* blueWhite */
+        $myPrefs['back'] = '#000033';
+        $myPrefs['front'] = 'white';
+        $myPrefs['lightBack'] = '#000066';
+        $myPrefs['darkBack'] = '#333366';    
+    }
+
+       return $prefs;
+}
+
+function &getPrefs($chatID, $update = true) {
+
+       if (!file_exists(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/users/'.$chatID.'.prefs')) {
+               return loadDefaultPrefs();
+       }
+       $myPrefs = array();
+       $file_prefs = file(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/users/'.$chatID.'.prefs');
+       foreach ($file_prefs as $pref) {
+               $pref = explode('=', $pref, 2);
+               $myPrefs[$pref[0]] = trim($pref[1]);
+       }
+
+       if ($update) {
+               $myPrefs['lastAccessed'] = time();
+       }
+
+       if ($myPrefs['colours'] == 'beigeBlack') {
+        $myPrefs['back'] = 'beige';
+        $myPrefs['front'] = 'black';
+        $myPrefs['lightBack'] = '#ddeecc';
+        $myPrefs['darkBack'] = '#bbccaa';
+    } else if ($myPrefs['colours'] == 'whiteBlack') {
+        $myPrefs['back'] = 'white';
+        $myPrefs['front'] = 'black';
+        $myPrefs['lightBack'] = '#ddeecc';
+        $myPrefs['darkBack'] = '#bbccaa';
+    } else if ($myPrefs['colours'] == 'whiteBlue') {
+        $myPrefs['back'] = 'white';
+        $myPrefs['front'] = '000066';
+        $myPrefs['lightBack'] = '#ffddcc';
+        $myPrefs['darkBack'] = '#ddbbaa';
+    } else if ($myPrefs['colours'] == 'blackYellow') {
+        $myPrefs['back'] = 'black';
+        $myPrefs['front'] = 'yellow';
+        $myPrefs['lightBack'] = '#333333';
+        $myPrefs['darkBack'] = '#666666';
+    } else if ($myPrefs['colours'] == 'blackWhite') {
+        $myPrefs['back'] = 'black';
+        $myPrefs['front'] = 'white';
+        $myPrefs['lightBack'] = '#333333';
+        $myPrefs['darkBack'] = '#666666';
+    } else { /* blueWhite */
+        $myPrefs['back'] = '#000033';
+        $myPrefs['front'] = 'white';
+        $myPrefs['lightBack'] = '#000066';
+        $myPrefs['darkBack'] = '#333366';    
+    }
+
+       return ($myPrefs);
+}
+
+function writePrefs($myPrefs, $chatID) {
+       if (empty($myPrefs)) {
+               return 0;
+       }
+
+       if (!is_dir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/users')) {
+               mkdir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/users');
+       }
+
+       if (file_exists(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/users/'.$chatID.'.prefs')) {
+               chmod(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/users/'.$chatID.'.prefs', 0755);
+       }
+       $fp = @fopen(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/users/'.$chatID.'.prefs', 'w+');
+       if (!$fp) {
+               // error
+               exit;
+               return 0;
+       }
+
+       $prefs = '';
+       foreach ($myPrefs as $prefKey => $prefValue) {
+               $prefs .= $prefKey.'='.$prefValue."\n";
+       }
+
+       flock($fp, LOCK_EX);
+       if (!@fwrite($fp, $prefs)) {
+               return 0;
+       }
+       flock($fp, LOCK_UN);
+       chmod(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/users/'.$chatID.'.prefs', 0600);
+
+       return 1;
+}
+
+?>
diff --git a/include/lib/constants.inc.php b/include/lib/constants.inc.php
new file mode 100644 (file)
index 0000000..4a22cf1
--- /dev/null
@@ -0,0 +1,348 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+/***************
+ * constants
+ ******/
+
+/* config variables. if they're not in the db then it uses the installation default values: */
+$_config_defaults = array();
+$_config_defaults['contact_email']             = '';
+$_config_defaults['email_notification']        = 1; // enabled
+$_config_defaults['allow_instructor_requests'] = 1; // enabled
+$_config_defaults['auto_approve_instructors']  = 0; // disabled
+$_config_defaults['max_file_size']             = 1048576;  // 1MB
+$_config_defaults['max_course_size']           = 10485760; // 10 MB
+$_config_defaults['max_course_float']          = 2097152;  // 2MB
+$_config_defaults['illegal_extentions']        = 'exe|asp|php|php3|bat|cgi|pl|com|vbs|reg|pcd|pif|scr|bas|inf|vb|vbe|wsc|wsf|wsh';
+$_config_defaults['site_name']                 = '';
+$_config_defaults['home_url']                  = ''; // empty means disabled
+$_config_defaults['default_language']          = 'en';
+$_config_defaults['cache_dir']                 = ''; // empty means disabled
+$_config_defaults['enable_category_themes']    = 0; // disabled
+$_config_defaults['course_backups']            = 5; // number of backups
+$_config_defaults['email_confirmation']        = 0; // disabled
+$_config_defaults['master_list']               = 0; // disabled
+$_config_defaults['user_notes']                = 0; // disabled - whether to enable the user contributed handbook notes
+$_config_defaults['theme_categories']          = 0; // disabled
+$_config_defaults['main_defaults']                = 'forum/list.php|glossary/index.php|file_storage/index.php';
+$_config_defaults['home_defaults']             = 'forum/list.php|file_storage/index.php|glossary/index.php|chat/index.php|tile.php|faq/index.php|links/index.php|tools/my_tests.php|sitemap.php|export.php|my_stats.php|polls/index.php|directory.php|groups.php|reading_list/index.php|blogs/index.php';
+$_config_defaults['side_defaults']             = 'menu_menu|related_topics|users_online|glossary|search|poll|posts';
+$_config_defaults['pref_defaults']                        = 'a:4:{s:10:"PREF";s:7:"default";s:14:"PREF_NUMBERING";i:1;s:18:"PREF_JUMP_REDIRECT";i:1;s:15:"PREF_FORM_FOCUS";i:1;}';
+$_config_defaults['pref_inbox_notify']            = 0; // disabled
+$_config_defaults['check_version']                = 0; // disabled
+$_config_defaults['fs_versioning']             = 1; // enabled - file storage version control
+$_config_defaults['last_cron']                 = 0; // cron has to be enabled manually
+$_config_defaults['enable_mail_queue']         = 0; // mail queue can only be enabled if cron is running
+$_config_defaults['auto_install_languages']    = 0; // auto install languages can only be enabled if cron is running
+$_config_defaults['display_name_format']       = 1; // 0-5, see (array) display_name_formats
+$_config_defaults['time_zone']                 = ''; // empty means disabled or not supported
+$_config_defaults['prof_pic_max_file_size']       = 819200; // max size of an uploaded profile pic, in bytes. default 800 KB
+$_config_defaults['sent_msgs_ttl']             = 120; // number of days till saved sent inbox msgs are deleted
+$_config_defaults['mysql_group_concat_max_len'] = null; // null = check, 0 = disabled/unsupported, (non-zero is the actual mysql value)
+$_config_defaults['latex_server']              = 'http://www.forkosh.dreamhost.com/mimetex.cgi?'; // the full URL to an external LaTeX parser
+$_config_defaults['gtype']                                        = 0; //Defaulted to be original google search, @author Harris
+$_config_defaults['pretty_url']                                   = 0; //pretty url, disabled
+$_config_defaults['course_dir_name']              = 0; //course dir name (course slug), disabled
+$_config_defaults['apache_mod_rewrite']                   = 0; //apache mod_rewrite extension, disabled by default.
+$_config = $_config_defaults;
+
+
+/* display name formats
+ * L = login name
+ * F = first name
+ * S = second name
+ * T = last name */
+$display_name_formats = array();
+$display_name_formats[0] = 'display_name_format_l';
+$display_name_formats[1] = 'display_name_format_fst';
+$display_name_formats[2] = 'display_name_format_fstl';
+$display_name_formats[3] = 'display_name_format_fl';
+$display_name_formats[4] = 'display_name_format_lf';
+$display_name_formats[5] = 'display_name_format_lfst';
+
+
+/* the atutor.ca language translation server: */
+define('AT_LANG_DB_HOST', 'atutorsvn.atrc.utoronto.ca');
+define('AT_LANG_DB_USER', 'read_dev_lang');
+define('AT_LANG_DB_PASS', 'read_dev_lang');
+
+/* links */
+define('LINK_CAT_COURSE',      1);
+define('LINK_CAT_GROUP',       2);
+define('LINK_CAT_SELF',                3);
+
+define('LINK_CAT_AUTH_NONE',   0);
+define('LINK_CAT_AUTH_ALL',            1);
+define('LINK_CAT_AUTH_COURSE',  2);
+define('LINK_CAT_AUTH_GROUP',  3);
+
+/* drafting room constants */
+define('WORKSPACE_COURSE',     1); // aka Course Files
+define('WORKSPACE_PERSONAL',   2); // aka My Files
+define('WORKSPACE_ASSIGNMENT', 3);
+define('WORKSPACE_GROUP',      4);
+define('WORKSPACE_SYSTEM',     5);
+define('WORKSPACE_PATH_DEPTH', 1); // how deep the directories should be
+define('WORKSPACE_FILE_PATH',  AT_CONTENT_DIR . 'file_storage/');
+
+/* how many related topics can be listed */
+define('NUM_RELATED_TOPICS', 5);
+
+/* how many days until the password reminder link expires */
+define('AT_PASSWORD_REMINDER_EXPIRY', 2);
+
+/* taking a test an unlimited # of times */
+define('AT_TESTS_TAKE_UNLIMITED', 0);
+
+/* how many announcements listed */
+define('NUM_ANNOUNCEMENTS', 10);
+
+/* how long cache objects can persist  */
+/* in seconds. should be low initially, but doesn't really matter. */
+/* in practice should be 0 (ie. INF)    */
+define('CACHE_TIME_OUT',       60);
+
+/* member status field options */
+define('AT_STATUS_DISABLED',    0);
+define('AT_STATUS_UNCONFIRMED', 1);
+define('AT_STATUS_STUDENT',     2);
+define('AT_STATUS_INSTRUCTOR',  3);
+
+/* $_pages sections */
+define('AT_NAV_PUBLIC', 'AT_NAV_PUBLIC');
+define('AT_NAV_START',  'AT_NAV_START');
+define('AT_NAV_COURSE', 'AT_NAV_COURSE');
+define('AT_NAV_HOME',   'AT_NAV_HOME');
+define('AT_NAV_ADMIN',  'AT_NAV_ADMIN');
+
+/* user permissions */
+
+/* $_privs[priv number] = array(String name, Boolean pen, Boolean tools) */
+define('AT_PRIV_RETURN',               true);
+define('AT_PRIV_NONE',                 0);
+
+define('AT_PRIV_ADMIN',                        1);
+
+/* admin privs: */
+define('AT_ADMIN_PRIV_NONE',        0);
+define('AT_ADMIN_PRIV_ADMIN',       1);
+
+/* admin log (type of operations) */
+define('AT_ADMIN_LOG_UPDATE',  1);
+define('AT_ADMIN_LOG_DELETE',  2);
+define('AT_ADMIN_LOG_INSERT',  3);
+define('AT_ADMIN_LOG_REPLACE', 4);
+define('AT_ADMIN_LOG_OTHER',   5); //for non-db operations
+
+if (strpos(@ini_get('arg_separator.input'), ';') !== false) {
+       define('SEP', ';');
+} else {
+       define('SEP', '&');
+}
+
+/* the URL to the AChecker server of choice. must include trailing slash. */
+define('AT_ACHECKER_URL', 'http://checker.atrc.utoronto.ca/servlet/');
+
+if (!isset($_SERVER['REQUEST_URI'])) {
+       $REQUEST_URI = $_SERVER['SCRIPT_NAME'];
+       if ($_SERVER['QUERY_STRING'] != '') {
+               $REQUEST_URI .= '?'.$_SERVER['QUERY_STRING'];
+       }
+       $_SERVER['REQUEST_URI'] = $REQUEST_URI;
+}
+
+/* get the base url    */
+if (isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) == 'on')) {
+       $server_protocol = 'https://';
+} else {
+       $server_protocol = 'http://';
+}
+
+/* Handles pretty url - @author Harris */
+define('AT_PRETTY_URL_HANDLER',                'go.php');      
+define('AT_PRETTY_URL_NOT_HEADER',     false);
+define('AT_PRETTY_URL_IS_HEADER',      true);
+
+$dir_deep       = substr_count(AT_INCLUDE_PATH, '..');
+$url_parts      = explode('/', $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
+$_base_href     = array_slice($url_parts, 0, count($url_parts) - $dir_deep-1);
+$_base_href     = $server_protocol . implode('/', $_base_href).'/';
+
+if (($temp = strpos($_base_href, AT_PRETTY_URL_HANDLER)) > 0){
+       $endpos = $temp;
+} else {
+       $endpos = strlen($_base_href); 
+
+}
+$_base_href     = substr($_base_href, 0, $endpos);
+$_base_path  = substr($_base_href, strlen($server_protocol . $_SERVER['HTTP_HOST']));
+
+define('AT_BASE_HREF', $_base_href);
+
+/* relative uri */
+$_rel_url = '/'.implode('/', array_slice($url_parts, count($url_parts) - $dir_deep-1));
+
+/* where the gudes are (could be a full URL if needed): */
+define('AT_GUIDES_PATH', $_base_path . 'documentation/');
+
+define('AT_BACKUP_DIR', AT_CONTENT_DIR . 'backups/'); // where the backups get stored
+
+define('VERSION',              '1.6.1');
+define('ONLINE_UPDATE', 3); /* update the user expiry every 3 min */
+
+/* valid date format_types:                                            */
+/* @see ./include/lib/date_functions.inc.php   */
+define('AT_DATE_MYSQL_DATETIME',               1); /* YYYY-MM-DD HH:MM:SS      */
+define('AT_DATE_MYSQL_TIMESTAMP_14',   2); /* YYYYMMDDHHMMSS           */
+define('AT_DATE_UNIX_TIMESTAMP',               3); /* seconds since epoch      */
+define('AT_DATE_INDEX_VALUE',                  4); /* index to the date arrays */
+
+define('AT_ROLE_STUDENT',                              0);
+define('AT_ROLE_INSTRUCTOR',                   1);
+
+define('AT_KBYTE_SIZE',                         1024);
+
+define('AT_COURSESIZE_UNLIMITED',         -1); 
+define('AT_COURSESIZE_DEFAULT',                   -2);  /* can be changed in config.inc.php */
+define('AT_FILESIZE_DEFAULT',             -3);  /* this too */
+define('AT_FILESIZE_SYSTEM_MAX',          -4);
+$editable_file_types = array('txt', 'html', 'htm', 'xml', 'css', 'asc', 'csv', 'sql');
+
+/* how many poll choices are available: */
+define('AT_NUM_POLL_CHOICES',   7);
+
+/* ways of releasing a test */
+define('AT_RELEASE_NEVER',                0); // do not release 
+define('AT_RELEASE_IMMEDIATE',    1); // release after submitted
+define('AT_RELEASE_MARKED',               2); // release after all q's marked
+
+/* QPROP = question property: */
+define('AT_TESTS_QPROP_WORD',       1);
+define('AT_TESTS_QPROP_SENTENCE',   2);
+define('AT_TESTS_QPROP_PARAGRAPH',  3);
+define('AT_TESTS_QPROP_PAGE',       4);
+define('AT_TESTS_QPROP_ALIGN_VERT',    5); // align question options vertically
+define('AT_TESTS_QPROP_ALIGN_HORT',    6); // align question options horizontally
+
+/* enrollment types for $_SESSION['enroll'] */
+define('AT_ENROLL_NO',                 0);
+define('AT_ENROLL_YES',                        1);
+define('AT_ENROLL_ALUMNUS',            2);
+
+// constants for reading list module
+define ('RL_TYPE_BOOK', 1);
+define ('RL_TYPE_URL',  2);
+define ('RL_TYPE_HANDOUT', 3);
+define ('RL_TYPE_AV', 4);
+define ('RL_TYPE_FILE', 5);
+
+$_rl_types = array ();
+$_rl_types[RL_TYPE_BOOK]       = 'rl_book';
+$_rl_types[RL_TYPE_URL]                = 'rl_url';
+$_rl_types[RL_TYPE_HANDOUT]    = 'rl_handout';
+$_rl_types[RL_TYPE_AV]         = 'rl_av';
+$_rl_types[RL_TYPE_FILE]       = 'rl_file';
+
+/* control how user inputs get formatted on output: */
+/* note: v131 not all formatting options are available on each section. */
+
+define('AT_FORMAT_NONE',             0); /* LEQ to ~AT_FORMAT_ALL */
+define('AT_FORMAT_EMOTICONS',     1);
+define('AT_FORMAT_LINKS',         2);
+define('AT_FORMAT_IMAGES',        4);
+define('AT_FORMAT_HTML',          8);
+define('AT_FORMAT_GLOSSARY',     16);
+define('AT_FORMAT_ATCODES',      32);
+define('AT_FORMAT_CONTENT_DIR', 64); /* remove CONTENT_DIR */
+define('AT_FORMAT_QUOTES',      128); /* remove double quotes (does this get used?) */
+define('AT_FORMAT_ALL',       AT_FORMAT_EMOTICONS 
+                                                          + AT_FORMAT_LINKS 
+                                                      + AT_FORMAT_IMAGES 
+                                                      + AT_FORMAT_HTML 
+                                                      + AT_FORMAT_GLOSSARY 
+                                                          + AT_FORMAT_ATCODES
+                                                          + AT_FORMAT_CONTENT_DIR);
+
+$_field_formatting = array();
+
+$_field_formatting['content.keywords']                 = AT_FORMAT_NONE;
+$_field_formatting['content.title']                            = AT_FORMAT_ALL & ~AT_FORMAT_HTML | AT_FORMAT_QUOTES;
+$_field_formatting['content.text']                             = AT_FORMAT_ALL;
+
+$_field_formatting['course_cats.cat_name']             = AT_FORMAT_NONE;
+
+$_field_formatting['courses.*']                                    = AT_FORMAT_ALL & ~AT_FORMAT_EMOTICONS & ~AT_FORMAT_ATCODES & ~AT_FORMAT_LINKS & ~AT_FORMAT_IMAGES;
+
+$_field_formatting['forums.title']                             = AT_FORMAT_NONE;
+$_field_formatting['forums.description']               = AT_FORMAT_ALL;
+
+$_field_formatting['forums_threads.subject']   = AT_FORMAT_ALL & ~AT_FORMAT_HTML;
+$_field_formatting['forums_threads.body']              = AT_FORMAT_ALL & ~AT_FORMAT_HTML;
+
+$_field_formatting['glossary.word']                            = AT_FORMAT_NONE;
+$_field_formatting['glossary.definition']              = AT_FORMAT_ALL & ~AT_FORMAT_HTML;
+
+$_field_formatting['instructor_approvals.notes']= AT_FORMAT_NONE;
+
+$_field_formatting['members.*']                 = AT_FORMAT_NONE; /* wildcards are okay */
+
+$_field_formatting['messages.subject']                 = AT_FORMAT_EMOTICONS + AT_FORMAT_IMAGES;
+$_field_formatting['messages.body']                            = AT_FORMAT_EMOTICONS + AT_FORMAT_LINKS + AT_FORMAT_IMAGES + AT_FORMAT_ATCODES;
+
+$_field_formatting['news.title']                               = AT_FORMAT_EMOTICONS | AT_FORMAT_LINKS & ~AT_FORMAT_HTML;
+$_field_formatting['news.body']                                        = AT_FORMAT_ALL;
+
+$_field_formatting['resource_categories.CatName']= AT_FORMAT_NONE;
+$_field_formatting['resource_categories.Url']  = AT_FORMAT_NONE;
+$_field_formatting['resource_links.LinkName']  = AT_FORMAT_NONE;
+$_field_formatting['resource_links.Description']= AT_FORMAT_NONE;
+$_field_formatting['resource_links.SubmitName']= AT_FORMAT_NONE;
+
+$_field_formatting['tests.title']                              = AT_FORMAT_ALL;
+$_field_formatting['tests.instructions']               = AT_FORMAT_ALL;
+
+$_field_formatting['themes.title']                             = AT_FORMAT_NONE;
+
+$_field_formatting['tests_answers.answer']             = AT_FORMAT_NONE;
+$_field_formatting['tests_answers.notes']              = AT_FORMAT_ALL;
+$_field_formatting['tests_questions.*']                        = AT_FORMAT_ALL;
+
+$_field_formatting['tests_questions_categories.title'] = AT_FORMAT_NONE;
+
+$_field_formatting['polls.*']            = AT_FORMAT_ALL;
+
+$_field_formatting['blog_posts.body']       = AT_FORMAT_ALL & ~AT_FORMAT_HTML;
+$_field_formatting['blog_posts.title']      = AT_FORMAT_NONE;
+
+$_field_formatting['blog_posts_comments.comment'] = AT_FORMAT_ALL & ~AT_FORMAT_HTML;
+
+$_field_formatting['courses.banner'] = AT_FORMAT_ALL;
+
+if (isset($_GET['cid'])) {
+       $cid = intval($_GET['cid']);
+} else if (isset($_POST['cid'])) {
+       $cid = intval($_POST['cid']);
+}
+
+
+/* google type constants - @author Harris */
+define('GOOGLE_TYPE_SOAP',             0);             //The original soap search with key generated before Dec 2005.
+define('GOOGLE_TYPE_AJAX',             1);             //The new AJAX search by google
+
+/* flags for validate_length in vitals. - @author Harris*/
+define('VALIDATE_LENGTH_FOR_DISPLAY',  1);     
+?>
diff --git a/include/lib/course.inc.php b/include/lib/course.inc.php
new file mode 100644 (file)
index 0000000..e2b7543
--- /dev/null
@@ -0,0 +1,431 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+/**
+ * To resize course_icon images
+ * @param      uploaded image source path 
+ * @param      uploaded image path to be saved as
+ * @param      uploaded image's height
+ * @param      uploaded image width
+ * @param      save file with this height
+ * @param      save file with this width
+ * @param      file extension type
+ * @return     true if successful, false otherwise
+ */
+function resize_image($src, $dest, $src_h, $src_w, $dest_h, $dest_w, $type) {
+       $thumbnail_img = imagecreatetruecolor($dest_w, $dest_h);
+       if ($type == 'gif') {
+               $source = imagecreatefromgif($src);
+       } else if ($type == 'jpg') {
+               $source = imagecreatefromjpeg($src);
+       } else {
+               $source = imagecreatefrompng($src);
+       }
+       
+       $result = imagecopyresampled($thumbnail_img, $source, 0, 0, 0, 0, $dest_w, $dest_h, $src_w, $src_h);
+
+       if ($type == 'gif') {
+               $result &= imagegif($thumbnail_img, $dest);
+       } else if ($type == 'jpg') {
+               $result &= imagejpeg($thumbnail_img, $dest, 75);
+       } else {
+               $result &= imagepng($thumbnail_img, $dest, 7);
+       }
+       return $result;
+}
+
+function add_update_course($_POST, $isadmin = FALSE) {
+       require(AT_INCLUDE_PATH.'lib/filemanager.inc.php');
+
+       global $addslashes;
+       global $db;
+       global $system_courses;
+       global $MaxCourseSize;
+       global $msg;
+       global $_config;
+       global $_config_defaults;
+       global $stripslashes;
+
+       $Backup =& new Backup($db);
+       $missing_fields = array();
+
+       if ($_POST['title'] == '') {
+               $missing_fields[] = _AT('title');
+       } 
+       if (!$_POST['instructor']) {
+               $missing_fields[] = _AT('instructor');
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       $_POST['access']                  = $addslashes($_POST['access']);
+       $_POST['title']                   = $addslashes($_POST['title']);
+       $_POST['description']     = $addslashes($_POST['description']);
+       $_POST['hide']                    = $addslashes($_POST['hide']);
+       $_POST['pri_lang']                = $addslashes($_POST['pri_lang']);
+       $_POST['created_date']    = $addslashes($_POST['created_date']);
+       $_POST['copyright']               = $addslashes($_POST['copyright']);
+       $_POST['icon']                    = $addslashes($_POST['icon']);
+       $_POST['banner']                  = $addslashes($_POST['banner']);
+       $_POST['course_dir_name'] = $addslashes($_POST['course_dir_name']);
+
+       $_POST['course']        = intval($_POST['course']);
+       $_POST['notify']        = intval($_POST['notify']);
+       $_POST['hide']          = intval($_POST['hide']);
+       $_POST['instructor']= intval($_POST['instructor']);
+       $_POST['category_parent']       = intval($_POST['category_parent']);
+       $_POST['rss']       = intval($_POST['rss']);
+
+       // Course directory name (aka course slug)
+       if ($_POST['course_dir_name'] != ''){
+               //validate the course_dir_name, allow only alphanumeric, dash, underscore.
+               if (preg_match('/^[\w][\w\d\-\_]+$/', $_POST['course_dir_name'])==0){
+                       $msg->addError('COURSE_DIR_NAME_INVALID');
+               }
+
+               //check if the course_dir_name is already being used
+               $sql = 'SELECT COUNT(course_id) as cnt FROM '.TABLE_PREFIX."courses WHERE course_id!=$_POST[course] AND course_dir_name='$_POST[course_dir_name]'";
+               $result = mysql_query($sql);
+               $num_of_dir = mysql_fetch_assoc($result);
+               if (intval($num_of_dir['cnt']) > 0){
+                       $msg->addError('COURSE_DIR_NAME_IN_USE');
+               }               
+       }
+
+       // Custom icon
+       if ($_FILES['customicon']['name'] != ''){
+               // Use custom icon instead if it exists
+               $_POST['icon']    = $addslashes($_FILES['customicon']['name']);
+       } 
+       if ($_FILES['customicon']['error'] == UPLOAD_ERR_FORM_SIZE){
+               // Check if filesize is too large for a POST
+               $msg->addError(array('FILE_MAX_SIZE', $_config['prof_pic_max_file_size'] . ' ' . _AT('bytes')));
+       }
+       if ($_POST['release_date']) {
+               $day_release    = intval($_POST['day_release']);
+               $month_release  = intval($_POST['month_release']);
+               $year_release   = intval($_POST['year_release']);
+               $hour_release   = intval($_POST['hour_release']);
+               $min_release    = intval($_POST['min_release']);
+
+               if (!checkdate($month_release, $day_release, $year_release)) { //or date is in the past
+                       $msg->addError('RELEASE_DATE_INVALID');
+               }
+
+               if (strlen($month_release) == 1){
+                       $month_release = "0$month_release";
+               }
+               if (strlen($day_release) == 1){
+                       $day_release = "0$day_release";
+               }
+               if (strlen($hour_release) == 1){
+                       $hour_release = "0$hour_release";
+               }
+               if (strlen($min_release) == 1){
+                       $min_release = "0$min_release";
+               }
+               $release_date = "$year_release-$month_release-$day_release $hour_release:$min_release:00";
+       } else {
+               $release_date = "0000-00-00 00:00:00";
+       }
+
+       if ($_POST['end_date']) {
+               $day_end        = intval($_POST['day_end']);
+               $month_end      = intval($_POST['month_end']);
+               $year_end       = intval($_POST['year_end']);
+               $hour_end       = intval($_POST['hour_end']);
+               $min_end        = intval($_POST['min_end']);
+
+               if (!checkdate($month_end, $day_end, $year_end)) { //or date is in the past
+                       $msg->addError('END_DATE_INVALID');
+               }
+
+               if (strlen($month_end) == 1){
+                       $month_end = "0$month_end";
+               }
+               if (strlen($day_end) == 1){
+                       $day_end = "0$day_end";
+               }
+               if (strlen($hour_end) == 1){
+                       $hour_end = "0$hour_end";
+               }
+               if (strlen($min_end) == 1){
+                       $min_end = "0$min_end";
+               }
+               $end_date = "$year_end-$month_end-$day_end $hour_end:$min_end:00";
+       } else {
+               $end_date = "0000-00-00 00:00:00";
+       }
+
+       $initial_content_info = explode('_', $_POST['initial_content'], 2);
+       //admin
+       $course_quotas = '';
+       if ($isadmin) {
+               $instructor             = $_POST['instructor'];
+               $quota                  = intval($_POST['quota']);
+               $quota_entered  = intval($_POST['quota_entered']);
+               $filesize               = intval($_POST['filesize']);
+               $filesize_entered= intval($_POST['filesize_entered']);
+
+               //if they checked 'other', set quota=entered value, if it is empty or negative, set to default (-2)
+               if ($quota == '2') {
+                       if ($quota_entered=='' || empty($quota_entered) || $quota_entered<0 ) {
+                               $quota = AT_COURSESIZE_DEFAULT;                         
+                       } else {
+                               $quota = floatval($quota_entered);
+                               $quota = megabytes_to_bytes($quota);
+                       }
+               }
+
+               //if they checked 'other', set filesize=entered value, if it is empty or negative, set to default 
+               if ($filesize=='2') {
+                       if ($filesize_entered=='' || empty($filesize_entered) || $filesize_entered<0 ) {
+                               $filesize = AT_FILESIZE_DEFAULT;
+                               $msg->addFeedback('COURSE_DEFAULT_FSIZE');
+                       } else {
+                               $filesize = floatval($filesize_entered);
+                               $filesize = megabytes_to_bytes($filesize);
+                       }
+               }
+
+               $course_quotas  =  "max_quota='$quota', max_file_size='$filesize',";
+
+       } else {
+               $instructor = $_SESSION['member_id'];
+               if (!$_POST['course'])  {
+                       $course_quotas    =  "max_quota=".AT_COURSESIZE_DEFAULT.", max_file_size=".AT_FILESIZE_DEFAULT.",";
+                       $row = $Backup->getRow($initial_content_info[0], $initial_content_info[1]);
+
+                       if ((count($initial_content_info) == 2) 
+                               && ($system_courses[$initial_content_info[1]]['member_id'] == $_SESSION['member_id'])) {
+                               
+                                       if ($MaxCourseSize < $row['contents']['file_manager']) {
+                                               $msg->addError('RESTORE_TOO_BIG');      
+                                       }
+                       } else {
+                               $initial_content_info = intval($_POST['initial_content']);
+                       }
+
+               } else {
+                       unset($initial_content_info);
+                       $course_quotas  =  "max_quota='{$system_courses[$_POST[course]][max_quota]}', max_file_size='{$system_courses[$_POST[course]][max_file_size]}',";
+               }
+       }
+
+       if ($msg->containsErrors()) {
+               return FALSE;
+       }
+
+       //display defaults
+       if (!$_POST['course']) {
+               $menu_defaults = ",home_links='$_config[home_defaults]', main_links='$_config[main_defaults]', side_menu='$_config[side_defaults]'";
+       } else {
+               $menu_defaults = ',home_links=\''.$system_courses[$_POST['course']]['home_links'].'\', main_links=\''.$system_courses[$_POST['course']]['main_links'].'\', side_menu=\''.$system_courses[$_POST['course']]['side_menu'].'\'';
+       }
+
+       $sql    = "REPLACE INTO ".TABLE_PREFIX."courses SET course_id=$_POST[course], member_id='$_POST[instructor]', access='$_POST[access]', title='$_POST[title]', description='$_POST[description]', course_dir_name='$_POST[course_dir_name]', cat_id='$_POST[category_parent]', content_packaging='$_POST[content_packaging]', notify=$_POST[notify], hide=$_POST[hide], $course_quotas primary_language='$_POST[pri_lang]', created_date='$_POST[created_date]', rss=$_POST[rss], copyright='$_POST[copyright]', icon='$_POST[icon]', banner='$_POST[banner]', release_date='$release_date', end_date='$end_date' $menu_defaults";
+
+       $result = mysql_query($sql, $db);
+       if (!$result) {
+               echo mysql_error($db);
+               echo 'DB Error';
+               exit;
+       }
+       $_SESSION['is_admin'] = 1;
+       $new_course_id = $_SESSION['course_id'] = mysql_insert_id($db);
+       if ($isadmin) {
+               write_to_log(AT_ADMIN_LOG_REPLACE, 'courses', mysql_affected_rows($db), $sql);
+       }
+
+       if ($isadmin) {
+               //get current instructor and unenroll from course if different from POST instructor     
+               $old_instructor = $system_courses[$_POST['course']]['member_id'];
+               
+               if ($old_instructor != $_POST['instructor']) {
+                       //remove old from course enrollment
+                       $sql = "DELETE FROM ".TABLE_PREFIX."course_enrollment WHERE course_id=".$_POST['course']." AND member_id=".$old_instructor;
+                       $result = mysql_query($sql, $db);
+                       write_to_log(AT_ADMIN_LOG_DELETE, 'course_enrollment', mysql_affected_rows($db), $sql);
+               } 
+       }
+
+       //enroll new instructor
+       $sql = "INSERT INTO ".TABLE_PREFIX."course_enrollment VALUES ($_POST[instructor], $new_course_id, 'y', 0, '"._AT('instructor')."', 0)";
+       $result = mysql_query($sql, $db);
+       if ($isadmin) {
+               write_to_log(AT_ADMIN_LOG_REPLACE, 'course_enrollment', mysql_affected_rows($db), $sql);
+       }
+
+       // create the course content directory
+       $path = AT_CONTENT_DIR . $new_course_id . '/';
+       @mkdir($path, 0700);
+       @copy(AT_CONTENT_DIR . 'index.html', AT_CONTENT_DIR . $new_course_id . '/index.html');
+
+       // create the course backup directory
+       $path = AT_BACKUP_DIR . $new_course_id . '/';
+       @mkdir($path, 0700);
+       @copy(AT_CONTENT_DIR . 'index.html', AT_BACKUP_DIR . $new_course_id . '/index.html');
+
+       /* insert some default content: */
+
+       if (!$_POST['course_id'] && ($_POST['initial_content'] == '1')) {
+               $contentManager = new ContentManager($db, $new_course_id);
+               $contentManager->initContent( );
+
+               $cid = $contentManager->addContent($new_course_id, 0, 1,_AT('welcome_to_atutor'),
+                                                                                       addslashes(_AT('this_is_content')),
+                                                                                       '', '', 1, date('Y-m-d H:00:00'));
+
+               $announcement = _AT('default_announcement');
+               
+               $sql    = "INSERT INTO ".TABLE_PREFIX."news VALUES (NULL, $new_course_id, $instructor, NOW(), 1, '"._AT('welcome_to_atutor')."', '$announcement')";
+               $result = mysql_query($sql,$db);
+               
+               if ($isadmin) {
+                       write_to_log(AT_ADMIN_LOG_INSERT, 'news', mysql_affected_rows($db), $sql);
+               }
+
+               /**
+                * removed - #3098
+               // create forum for Welcome Course
+               $sql    = "INSERT INTO ".TABLE_PREFIX."forums VALUES (NULL, '"._AT('forum_general_discussion')."', '', 0, 0, NOW())";
+               $result = mysql_query($sql,$db);
+
+               if ($isadmin) {
+                       write_to_log(AT_ADMIN_LOG_INSERT, 'forums', mysql_affected_rows($db), $sql);
+               }
+
+               $sql = "INSERT INTO ".TABLE_PREFIX."forums_courses VALUES (LAST_INSERT_ID(), $new_course_id)";
+               $result = mysql_query($sql,$db);
+
+               if ($isadmin) {
+                       write_to_log(AT_ADMIN_LOG_INSERT, 'forums_courses', mysql_affected_rows($db), $sql);
+               }
+               ***/
+
+       } else if (!$_POST['course'] && (count($initial_content_info) == 2)){
+
+               $Backup->setCourseID($new_course_id);
+               $Backup->restore($material = TRUE, 'append', $initial_content_info[0], $initial_content_info[1]);
+       }
+       // custom icon, have to be after directory is created
+//     $_FILES['customicon'] = $_POST['customicon'];   //copy to $_FILES.
+       if($_FILES['customicon']['tmp_name'] != ''){
+        $_POST['comments'] = trim($_POST['comments']);
+
+        $owner_id = $_SESSION['course_id'];
+        $owner_type = "1";
+        if ($_FILES['customicon']['error'] == UPLOAD_ERR_INI_SIZE) {
+            $msg->addError(array('FILE_TOO_BIG', get_human_size(megabytes_to_bytes(substr(ini_get('upload_max_filesize'), 0, -1)))));
+        } else if (!isset($_FILES['customicon']['name']) || ($_FILES['customicon']['error'] == UPLOAD_ERR_NO_FILE) || ($_FILES['customicon']['size'] == 0)) {
+            $msg->addError('FILE_NOT_SELECTED');
+
+        } else if ($_FILES['customicon']['error'] || !is_uploaded_file($_FILES['customicon']['tmp_name'])) {
+            $msg->addError('FILE_NOT_SAVED');
+        }
+        
+        if (!$msg->containsErrors()) {
+            $_POST['description'] = $addslashes(trim($_POST['description']));
+            $_FILES['customicon']['name'] = addslashes($_FILES['customicon']['name']);
+
+            if ($_POST['comments']) {
+                $num_comments = 1;
+            } else {
+                $num_comments = 0;
+            }
+            
+            $path = AT_CONTENT_DIR.$owner_id."/custom_icons/";
+               
+            if (!is_dir($path)) {
+                @mkdir($path);
+            }
+                       
+                       // if we can upload custom course icon, it means GD is enabled, no need to check extension again.
+                       $gd_info = gd_info();
+                       $supported_images = array();
+                       if ($gd_info['GIF Create Support']) {
+                               $supported_images[] = 'gif';
+                       }
+                       if ($gd_info['JPG Support']) {
+                               $supported_images[] = 'jpg';
+                       }
+                       if ($gd_info['PNG Support']) {
+                               $supported_images[] = 'png';
+                       }
+
+                       // check if this is a supported file type
+                       $filename   = $stripslashes($_FILES['customicon']['name']);
+                       $path_parts = pathinfo($filename);
+                       $extension  = strtolower($path_parts['extension']);
+                       $image_attributes = getimagesize($_FILES['customicon']['tmp_name']);
+
+                       if ($extension == 'jpeg') {
+                               $extension = 'jpg';
+                       }
+
+                       // resize the original but don't backup a copy.
+                       $width  = $image_attributes[0];
+                       $height = $image_attributes[1];
+                       $original_img   = $_FILES['customicon']['tmp_name'];
+                       $thumbnail_img  = $path . $_FILES['customicon']['name'];
+
+                       if ($width > $height && $width>79) {
+                               $thumbnail_height = intval(79 * $height / $width);
+                               $thumbnail_width  = 79;
+                               if (!resize_image($original_img, $thumbnail_img, $height, $width, $thumbnail_height, $thumbnail_width, $extension)){
+                                       $msg->addError('FILE_NOT_SAVED');
+                               }
+                       } else if ($width <= $height && $height > 79) {
+                               $thumbnail_height= 100;
+                               $thumbnail_width = intval(100 * $width / $height);
+                               if (!resize_image($original_img, $thumbnail_img, $height, $width, $thumbnail_height, $thumbnail_width, $extension)){
+                                       $msg->addError('FILE_NOT_SAVED');
+                               }
+                       } else {
+                               // no resizing, just copy the image.
+                               // it's too small to resize.
+                               copy($original_img, $thumbnail_img);
+                       }
+
+        } else {
+            $msg->addError('FILE_NOT_SAVED');
+            
+        }
+        //header('Location: index.php'.$owner_arg_prefix.'folder='.$parent_folder_id);
+        //exit;
+    }
+    //----------------------------------------
+
+       /* delete the RSS feeds just in case: */
+       if (file_exists(AT_CONTENT_DIR . 'feeds/' . $new_course_id . '/RSS1.0.xml')) {
+               @unlink(AT_CONTENT_DIR . 'feeds/' . $_POST['course'] . '/RSS1.0.xml');
+       }
+       if (file_exists(AT_CONTENT_DIR . 'feeds/' . $new_course_id . '/RSS2.0.xml')) {
+               @unlink(AT_CONTENT_DIR . 'feeds/' . $new_course_id . '/RSS2.0.xml');
+       }
+
+       if ($isadmin) {
+               $_SESSION['course_id'] = -1;
+       }
+
+       $_SESSION['course_title'] = $stripslashes($_POST['title']);
+       return $new_course_id;
+}
+
+?>
diff --git a/include/lib/delete_course.inc.php b/include/lib/delete_course.inc.php
new file mode 100644 (file)
index 0000000..f87a202
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay,Joel Kronenberg & Heidi Hazelton        */
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+
+function delete_course($course, $material) {
+       global $db, $moduleFactory;
+
+       $delete_groups = FALSE; // whether or not to delete the groups as well
+
+       $groups = array();
+
+       //unset s_cid var
+       if ($material === TRUE) {
+               unset($_SESSION['s_cid']);
+               $delete_groups = TRUE;
+               // get a list of groups in an array to send to module::delete()
+               // get groups
+               $sql    = "SELECT G.group_id FROM ".TABLE_PREFIX."groups G INNER JOIN ".TABLE_PREFIX."groups_types T USING (type_id) WHERE T.course_id=$course";
+               $result = mysql_query($sql, $db);
+               while ($group_row = mysql_fetch_assoc($result)) {
+                       $groups[] = $group_row['group_id'];
+               }
+       }
+
+       $module_list = $moduleFactory->getModules(AT_MODULE_STATUS_ENABLED | AT_MODULE_STATUS_DISABLED);
+       $keys = array_keys($module_list);
+
+       //loop through mods and call delete function
+       foreach ($keys as $module_name) {
+               if ($module_name == '_core/groups') {
+                       continue;
+               }
+               if ($module_name == '_core/enrolment') {
+                       continue;
+               }
+               $module =& $module_list[$module_name];
+
+               if (($material === TRUE) || isset($material[$module_name])) {
+                       $module->delete($course, $groups);
+               }
+       }
+
+       // groups and enrollment must be deleted last because that info is used by other modules
+
+       if (($material === TRUE) || isset($material['_core/groups'])) {
+               $module =& $moduleFactory->getModule('_core/groups');
+               $module->delete($course, $groups);
+       }
+       if (($material === TRUE) || isset($material['_core/enrolment'])) {
+               $module =& $moduleFactory->getModule('_core/enrolment');
+               $module->delete($course, $groups);
+       }
+
+       if ($material === TRUE) {
+               // delete actual course
+               $sql = "DELETE FROM ".TABLE_PREFIX."courses WHERE course_id=$course";
+               $result = mysql_query($sql, $db);
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/lib/editor_tab_functions.inc.php b/include/lib/editor_tab_functions.inc.php
new file mode 100644 (file)
index 0000000..b0297cf
--- /dev/null
@@ -0,0 +1,412 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+
+function in_array_cin($strItem, $arItems)
+{
+   foreach ($arItems as $key => $strValue)
+   {
+       if (strtoupper($strItem) == strtoupper($strValue))
+       {
+                  return $key;
+       }
+   }
+   return false;
+} 
+
+
+function get_tabs() {
+       //these are the _AT(x) variable names and their include file
+       /* tabs[tab_id] = array(tab_name, file_name,                accesskey) */
+       $tabs[0] = array('content',       'edit.inc.php',          'n');
+       $tabs[1] = array('properties',    'properties.inc.php',    'p');
+       $tabs[2] = array('glossary_terms','glossary.inc.php',      'g');
+       $tabs[3] = array('preview',       'preview.inc.php',       'r');
+       $tabs[4] = array('accessibility', 'accessibility.inc.php', 'a');        
+
+       return $tabs;
+}
+
+
+function output_tabs($current_tab, $changes) {
+       global $_base_path;
+       $tabs = get_tabs();
+       $num_tabs = count($tabs);
+?>
+       <table class="etabbed-table" border="0" cellpadding="0" cellspacing="0" width="95%">
+       <tr>            
+               <?php 
+               for ($i=0; $i < $num_tabs; $i++): 
+                       if ($current_tab == $i):?>
+                               <td class="selected">
+                                       <?php if ($changes[$i]): ?>
+                                               <img src="<?php echo $_base_path; ?>images/changes_bullet.gif" alt="<?php echo _AT('usaved_changes_made'); ?>" height="12" width="15" />
+                                       <?php endif; ?>
+                                       <?php echo _AT($tabs[$i][0]); ?>
+                               </td>
+                               <td class="tab-spacer">&nbsp;</td>
+                       <?php else: ?>
+                               <td class="tab">
+                                       <?php if ($changes[$i]): ?>
+                                               <img src="<?php echo $_base_path; ?>images/changes_bullet.gif" alt="<?php echo _AT('usaved_changes_made'); ?>" height="12" width="15" />
+                                       <?php endif; ?>
+
+                                       <?php echo '<input type="submit" name="button_'.$i.'" value="'._AT($tabs[$i][0]).'" title="'._AT($tabs[$i][0]).' - alt '.$tabs[$i][2].'" class="buttontab" accesskey="'.$tabs[$i][2].'" onmouseover="this.style.cursor=\'pointer\';" '.$clickEvent.' />'; ?>
+                               </td>
+                               <td class="tab-spacer">&nbsp;</td>
+                       <?php endif; ?>
+               <?php endfor; ?>
+               <td >&nbsp;</td>
+       </tr>
+       </table>
+<?php }
+
+// save all changes to the DB
+function save_changes($redir) {
+       global $contentManager, $db, $addslashes, $msg;
+
+       $_POST['pid']   = intval($_POST['pid']);
+       $_POST['cid']   = intval($_POST['cid']);
+
+       $_POST['title'] = trim($_POST['title']);
+       $_POST['head']  = trim($_POST['head']);
+       $_POST['use_customized_head']   = isset($_POST['use_customized_head'])?$_POST['use_customized_head']:0;
+       $_POST['body_text']     = trim($_POST['body_text']);
+       $_POST['formatting'] = intval($_POST['formatting']);
+       $_POST['keywords']      = trim($_POST['keywords']);
+       $_POST['new_ordering']  = intval($_POST['new_ordering']);
+       if ($_POST['setvisual']) { $_POST['setvisual'] = 1; }
+
+       if (!($release_date = generate_release_date())) {
+               $msg->addError('BAD_DATE');
+       }
+
+       if ($_POST['title'] == '') {
+               $msg->addError(array('EMPTY_FIELDS', _AT('title')));
+       }
+               
+       if (!$msg->containsErrors()) {
+
+               $_POST['title']     = $addslashes($_POST['title']);
+               $_POST['body_text'] = $addslashes($_POST['body_text']);
+               $_POST['head']  = $addslashes($_POST['head']);
+               $_POST['keywords']  = $addslashes($_POST['keywords']);
+               $_POST['keywords']  = $addslashes($_POST['keywords']);
+
+               if ($_POST['cid']) {
+                       /* editing an existing page */
+                       $err = $contentManager->editContent($_POST['cid'], $_POST['title'], $_POST['body_text'], $_POST['keywords'], $_POST['new_ordering'], $_POST['related'], $_POST['formatting'], $_POST['new_pid'], $release_date, $_POST['head'], $_POST['use_customized_head']);
+
+                       unset($_POST['move']);
+                       unset($_POST['new_ordering']);
+                       $cid = $_POST['cid'];
+               } else {
+                       /* insert new */
+                       
+                       $cid = $contentManager->addContent($_SESSION['course_id'],
+                                                                                                 $_POST['new_pid'],
+                                                                                                 $_POST['new_ordering'],
+                                                                                                 $_POST['title'],
+                                                                                                 $_POST['body_text'],
+                                                                                                 $_POST['keywords'],
+                                                                                                 $_POST['related'],
+                                                                                                 $_POST['formatting'],
+                                                                                                 $release_date,
+                                                                                                 $_POST['head'],
+                                                                                                 $_POST['use_customized_head']);
+                       $_POST['cid']    = $cid;
+                       $_REQUEST['cid'] = $cid;
+               }
+       }
+
+       //debug($_POST['glossary_defs']);
+       /* insert glossary terms */
+       if (is_array($_POST['glossary_defs']) && ($num_terms = count($_POST['glossary_defs']))) {
+               global $glossary, $glossary_ids, $msg;
+
+               foreach($_POST['glossary_defs'] as $w => $d) {
+                       $old_w = $w;
+                       $key = in_array_cin($w, $glossary_ids);
+                       $w = urldecode($w);
+
+                       if (($key !== false) && (($glossary[$old_w] != $d) || isset($_POST['related_term'][$old_w])) ) {
+                               $w = addslashes($w);
+                               $related_id = intval($_POST['related_term'][$old_w]);
+                               $sql = "UPDATE ".TABLE_PREFIX."glossary SET definition='$d', related_word_id=$related_id WHERE word_id=$key AND course_id=$_SESSION[course_id]";
+                               $result = mysql_query($sql, $db);
+                               $glossary[$old_w] = $d;
+                       } else if ($key === false && ($d != '')) {
+                               $w = addslashes($w);
+                               $related_id = intval($_POST['related_term'][$old_w]);
+                               $sql = "INSERT INTO ".TABLE_PREFIX."glossary VALUES (NULL, $_SESSION[course_id], '$w', '$d', $related_id)";
+
+                               //debug($sql);
+                               $result = mysql_query($sql, $db);
+                               $glossary[$old_w] = $d;
+                       }
+               }
+       }
+
+
+       if (!$msg->containsErrors() && $redir) {
+               $_SESSION['save_n_close'] = $_POST['save_n_close'];
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: '.basename($_SERVER['PHP_SELF']).'?cid='.$cid.SEP.'close='.$addslashes($_POST['save_n_close']).SEP.'tab='.$addslashes($_POST['current_tab']).SEP.'setvisual='.$addslashes($_POST['setvisual']).SEP.'displayhead='.$addslashes($_POST['displayhead']));
+               exit;
+       } else {
+               return;
+       }
+}
+
+function generate_release_date($now = false) {
+       if ($now) {
+               $day  = date('d');
+               $month= date('m');
+               $year = date('Y');
+               $hour = date('H');
+               $min  = 0;
+       } else {
+               $day    = intval($_POST['day']);
+               $month  = intval($_POST['month']);
+               $year   = intval($_POST['year']);
+               $hour   = intval($_POST['hour']);
+               $min    = intval($_POST['minute']);
+       }
+
+       if (!checkdate($month, $day, $year)) {
+               return false;
+       }
+
+       if (strlen($month) == 1){
+               $month = "0$month";
+       }
+       if (strlen($day) == 1){
+               $day = "0$day";
+       }
+       if (strlen($hour) == 1){
+               $hour = "0$hour";
+       }
+       if (strlen($min) == 1){
+               $min = "0$min";
+       }
+       $release_date = "$year-$month-$day $hour:$min:00";
+       
+       return $release_date;
+}
+
+function check_for_changes($row) {
+       global $contentManager, $cid, $glossary, $glossary_ids_related, $addslashes;
+
+       $changes = array();
+
+       if ($row && strcmp(trim($addslashes($_POST['title'])), addslashes($row['title']))) {
+               $changes[0] = true;
+       } else if (!$row && $_POST['title']) {
+               $changes[0] = true;
+       }
+
+       if ($row && strcmp($addslashes(trim($_POST['head'])), trim(addslashes($row['head'])))) {
+               $changes[0] = true;
+       } else if (!$row && $_POST['head']) {
+               $changes[0] = true;
+       }
+
+       if ($row && strcmp($addslashes(trim($_POST['body_text'])), trim(addslashes($row['text'])))) {
+               $changes[0] = true;
+       } else if (!$row && $_POST['body_text']) {
+               $changes[0] = true;
+       }
+
+       /* use customized head: */
+       if ($row && isset($_POST['use_customized_head']) && ($_POST['use_customized_head'] != $row['use_customized_head'])) {
+               $changes[0] = true;
+       }
+
+       /* formatting: */
+       if ($row && strcmp(trim($_POST['formatting']), $row['formatting'])) {
+               $changes[0] = true;
+       } else if (!$row && $_POST['formatting']) {
+               $changes[0] = true;
+       }
+
+       /* release date: */
+       if ($row && strcmp(substr(generate_release_date(), 0, -2), substr($row['release_date'], 0, -2))) {
+               /* the substr was added because sometimes the release_date in the db has the seconds field set, which we dont use */
+               /* so it would show a difference, even though it should actually be the same, so we ignore the seconds with the -2 */
+               /* the seconds gets added if the course was created during the installation process. */
+               $changes[1] = true;
+       } else if (!$row && strcmp(generate_release_date(), generate_release_date(true))) {
+               $changes[1] = true;
+       }
+
+       /* related content: */
+       $row_related = $contentManager->getRelatedContent($cid);
+
+       if (is_array($_POST['related']) && is_array($row_related)) {
+               $sum = array_sum(array_diff($_POST['related'], $row_related));
+               $sum += array_sum(array_diff($row_related, $_POST['related']));
+               if ($sum > 0) {
+                       $changes[1] = true;
+               }
+       } else if (!is_array($_POST['related']) && !empty($row_related)) {
+               $changes[1] = true;
+       }
+
+       /* ordering */
+       if ($cid && isset($_POST['move']) && ($_POST['move'] != -1) && ($_POST['move'] != $row['content_parent_id'])) {
+               $changes[1] = true;
+       }
+
+       if ($cid && (($_POST['new_ordering'] != $_POST['ordering']) || ($_POST['new_pid'] != $_POST['pid']))) {
+               $changes[1] = true;
+       }
+
+       /* keywords */
+       if ($row && strcmp(trim($_POST['keywords']), $row['keywords'])) {
+               $changes[1] = true;
+       }  else if (!$row && $_POST['keywords']) {
+               $changes[1] = true;
+       }
+
+
+       /* glossary */
+       if (is_array($_POST['glossary_defs'])) {
+               global $glossary_ids;
+               foreach ($_POST['glossary_defs'] as $w => $d) {
+
+                       $key = in_array_cin($w, $glossary_ids);
+                       if ($key === false) {
+                               /* new term */
+                               $changes[2] = true;
+                               break;
+                       } else if ($cid && ($d &&($d != $glossary[$glossary_ids[$key]]))) {
+                               /* changed term */
+                               $changes[2] = true;
+                               break;
+                       }
+               }
+
+               if (is_array($_POST['related_term'])) {
+                       foreach($_POST['related_term'] as $term => $r_id) {
+                               if ($glossary_ids_related[$term] != $r_id) {
+                                       $changes[2] = true;
+                                       break;
+                               }
+                       }
+               }
+       }
+       
+       return $changes;
+}
+
+function paste_from_file() {
+       global $msg;
+       if ($_FILES['uploadedfile']['name'] == '')      {
+               $msg->addError('FILE_NOT_SELECTED');
+               return;
+       }
+       if ($_FILES['uploadedfile']['name']
+               && (($_FILES['uploadedfile']['type'] == 'text/plain')
+                       || ($_FILES['uploadedfile']['type'] == 'text/html')) )
+               {
+
+               $path_parts = pathinfo($_FILES['uploadedfile']['name']);
+               $ext = strtolower($path_parts['extension']);
+
+               if (in_array($ext, array('html', 'htm'))) {
+                       $_POST['body_text'] = file_get_contents($_FILES['uploadedfile']['tmp_name']);
+
+                       /* get the <title></title> of this page                         */
+
+                       $start_pos      = strpos(strtolower($_POST['body_text']), '<title>');
+                       $end_pos        = strpos(strtolower($_POST['body_text']), '</title>');
+
+                       if (($start_pos !== false) && ($end_pos !== false)) {
+                               $start_pos += strlen('<title>');
+                               $_POST['title'] = trim(substr($_POST['body_text'], $start_pos, $end_pos-$start_pos));
+                       }
+                       unset($start_pos);
+                       unset($end_pos);
+
+                       $_POST['head'] = get_html_head_by_tag($_POST['body_text'], array("link", "style", "script")); 
+                       if (strlen(trim($_POST['head'])) > 0)   
+                               $_POST['use_customized_head'] = 1;
+                       else
+                               $_POST['use_customized_head'] = 0;
+                       
+                       $_POST['body_text'] = get_html_body($_POST['body_text']); 
+
+                       $msg->addFeedback('FILE_PASTED');
+               } else if ($ext == 'txt') {
+                       $_POST['body_text'] = file_get_contents($_FILES['uploadedfile']['tmp_name']);
+                       $msg->addFeedback('FILE_PASTED');
+
+               }
+       } else {
+               $msg->addError('BAD_FILE_TYPE');
+       }
+
+       return;
+}
+
+//for accessibility checker
+function write_temp_file() {
+       global $_POST, $msg;
+
+       if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+               $content_base = 'get.php/';
+       } else {
+               $content_base = 'content/' . $_SESSION['course_id'] . '/';
+       }
+
+       if ($_POST['content_path']) {
+               $content_base .= $_POST['content_path'] . '/';
+       }
+
+       $file_name = $_POST['cid'].'.html';
+
+       if ($handle = fopen(AT_CONTENT_DIR . $file_name, 'wb+')) {
+               $temp_content = '<h2>'.AT_print(stripslashes($_POST['title']), 'content.title').'</h2>';
+
+               if ($_POST['body_text'] != '') {
+                       $temp_content .= format_content(stripslashes($_POST['body_text']), $_POST['formatting'], $_POST['glossary_defs']);
+               }
+               $temp_title = $_POST['title'];
+
+               $html_template = '<!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>
+                       <base href="{BASE_HREF}" />
+                       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+                       <title>{TITLE}</title>
+                       <meta name="Generator" content="ATutor accessibility checker file - can be deleted">
+               </head>
+               <body>{CONTENT}</body>
+               </html>';
+
+               $page_html = str_replace(       array('{BASE_HREF}', '{TITLE}', '{CONTENT}'),
+                                                                       array($content_base, $temp_title, $temp_content),
+                                                                       $html_template);
+               
+               if (!@fwrite($handle, $page_html)) {
+                       $msg->addError('FILE_NOT_SAVED');       
+          }
+       } else {
+               $msg->addError('FILE_NOT_SAVED');
+       }
+       $msg->printErrors();
+}
+?>
\ No newline at end of file
diff --git a/include/lib/enroll.inc.php b/include/lib/enroll.inc.php
new file mode 100644 (file)
index 0000000..0700b80
--- /dev/null
@@ -0,0 +1,261 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+function checkUserInfo($record) {\r
+       global $db, $addslashes;\r
+       static $email_list;\r
+\r
+       if (empty($record['remove'])) {\r
+               $record['remove'] = FALSE;                      \r
+       }\r
+\r
+       //error flags for this record\r
+       $record['err_email'] = FALSE;\r
+       $record['err_uname'] = FALSE;\r
+       $record['exists']    = FALSE;\r
+\r
+       $record['email'] = trim($record['email']);\r
+\r
+       /* email check */\r
+       if ($record['email'] == '') {\r
+               $record['err_email'] = _AT('import_err_email_missing');\r
+       } else if (!eregi("^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$", $record['email'])) {\r
+               $record['err_email'] = _AT('import_err_email_invalid');\r
+       } else if (isset($email_list[$record['email']])) {\r
+               $record['err_email'] = _AT('import_err_email_exists');\r
+       } else {\r
+               $record['email'] = $addslashes($record['email']);\r
+\r
+               $sql="SELECT * FROM ".TABLE_PREFIX."members WHERE email LIKE '$record[email]'";\r
+               $result = mysql_query($sql,$db);\r
+               if (mysql_num_rows($result) != 0) {\r
+                       $row = mysql_fetch_assoc($result);\r
+                       $record['exists'] = _AT('import_err_email_exists');\r
+                       $record['fname']  = $row['first_name']; \r
+                       $record['lname']  = $row['last_name'];\r
+                       $record['email']  = $row['email'];\r
+                       $record['uname']  = $row['login'];\r
+                       $record['status'] = $row['status'];\r
+               } else {\r
+                       // it's good, add it to the list\r
+                       $email_list[$record['email']] = true;\r
+               }\r
+       }\r
+\r
+       /* username check */\r
+       if (empty($record['uname'])) {\r
+               $record['uname'] = stripslashes (strtolower (substr ($record['fname'], 0, 1).$_POST['sep_choice'].$record['lname']));\r
+       }               \r
+\r
+       $record['uname'] = preg_replace("{[^a-zA-Z0-9._-]}","", trim($record['uname']));\r
+\r
+       if (!(eregi("^[a-zA-Z0-9._-]([a-zA-Z0-9._-])*$", $record['uname']))) {\r
+               $record['err_uname'] = _AT('import_err_username_invalid');\r
+       } \r
+\r
+       if (isset($record['status']) && $record['status'] == AT_STATUS_DISABLED) {\r
+               $record['err_disabled'] = true;\r
+       } else {\r
+               $record['err_disabled'] = false;\r
+       }\r
+\r
+       $record['uname'] = $addslashes($record['uname']);\r
+       $record['fname'] = $addslashes($record['fname']);\r
+       $record['lname'] = $addslashes($record['lname']);\r
+\r
+       $sql = "SELECT member_id FROM ".TABLE_PREFIX."members WHERE login='$record[uname]'";\r
+       $result = mysql_query($sql,$db);\r
+       if ((mysql_num_rows($result) != 0) && !$record['exists']) {\r
+               $record['err_uname'] = _AT('import_err_username_exists');\r
+       } else {\r
+               $result = mysql_query("SELECT * FROM ".TABLE_PREFIX."admins WHERE login='$record[uname]'",$db);\r
+               if (mysql_num_rows($result) != 0) {\r
+                       $record['err_uname'] = _AT('import_err_username_exists');\r
+               }\r
+       }       \r
+\r
+       $sql = "SELECT member_id FROM ".TABLE_PREFIX."members WHERE first_name='$record[fname]' AND last_name='$record[lname]' LIMIT 1";\r
+       $result = mysql_query($sql,$db);\r
+       if ((mysql_num_rows($result) != 0) && !$record['exists']) {\r
+               $record['err_uname'] = _AT('import_err_full_name_exists');\r
+       }\r
+\r
+       /* removed record? */\r
+       if ($record['remove']) {\r
+               //unset errors \r
+               $record['err_email'] = '';\r
+               $record['err_uname'] = '';\r
+               $record['err_disabled'] = '';\r
+       }\r
+\r
+       $record['fname'] = htmlspecialchars(stripslashes(trim($record['fname'])));\r
+       $record['lname'] = htmlspecialchars(stripslashes(trim($record['lname'])));\r
+       $record['email'] = htmlspecialchars(stripslashes(trim($record['email'])));\r
+       $record['uname'] = htmlspecialchars(stripslashes(trim($record['uname'])));\r
+\r
+       return $record;\r
+}\r
+\r
+function add_users($user_list, $enroll, $course) {\r
+       global $db;\r
+       global $msg;\r
+       global $_config;\r
+       global $addslashes;\r
+\r
+       require_once(AT_INCLUDE_PATH.'classes/phpmailer/atutormailer.class.php');\r
+\r
+       if (defined('AT_EMAIL_CONFIRMATION') && AT_EMAIL_CONFIRMATION) {\r
+               $status = AT_STATUS_UNCONFIRMED;\r
+       } else {\r
+               $status = AT_STATUS_STUDENT;\r
+       }\r
+\r
+\r
+       foreach ($user_list as $student) {\r
+               if (!$student['remove'])  {\r
+                               $student['uname'] = $addslashes($student['uname']);\r
+                               $student['email'] = $addslashes($student['email']);\r
+                               $student['fname'] = $addslashes($student['fname']);\r
+                               $student['lname'] = $addslashes($student['lname']);\r
+\r
+                       if (!$student['exists']) {\r
+                               $sql = "INSERT INTO ".TABLE_PREFIX."members \r
+                                             (login,\r
+                                              password,\r
+                                              email,\r
+                                              first_name,\r
+                                              last_name,\r
+                                              gender,\r
+                                              status,\r
+                                              preferences,\r
+                                              creation_date,\r
+                                              language,\r
+                                              inbox_notify,\r
+                                              private_email)\r
+                                             VALUES \r
+                                             ('$student[uname]',\r
+                                              '". sha1($student[uname]). "',\r
+                                              '$student[email]',\r
+                                              '$student[fname]',\r
+                                              '$student[lname]',\r
+                                              'n', \r
+                                              $status, \r
+                                              '$_config[pref_defaults]', \r
+                                              NOW(),\r
+                                              '$_config[default_language]', \r
+                                              $_config[pref_inbox_notify], \r
+                                              1)";\r
+\r
+                               $result = mysql_query($sql, $db);\r
+                               if (mysql_affected_rows($db) == 1) {\r
+                                       $m_id = mysql_insert_id($db);\r
+\r
+                                       $student['exists'] = _AT('import_err_email_exists');\r
+\r
+                                       $sql = "INSERT INTO ".TABLE_PREFIX."course_enrollment (member_id, course_id, approved, last_cid) VALUES ($m_id, $course, '$enroll', 0)";\r
+\r
+                                       if ($result = mysql_query($sql,$db)) {\r
+                                               $enrolled_list .= '<li>' . $student['uname'] . '</li>';\r
+\r
+                                               if (defined('AT_EMAIL_CONFIRMATION') && AT_EMAIL_CONFIRMATION) {\r
+\r
+                                                       $sql    = "SELECT email, creation_date FROM ".TABLE_PREFIX."members WHERE member_id=$m_id";\r
+                                                       $result = mysql_query($sql, $db);\r
+                                                       $row    = mysql_fetch_assoc($result);\r
+                                                       $code   = substr(md5($row['email'] . $row['creation_date'] . $m_id), 0, 10);\r
+\r
+                                                       // send email here.\r
+                                                       $confirmation_link = AT_BASE_HREF . 'confirm.php?id='.$m_id.SEP.'m='.$code;\r
+                       \r
+                                                       $subject = $_config['site_name'].': '._AT('email_confirmation_subject');\r
+                                                       $body = _AT(array('new_account_enroll_confirm', $_SESSION['course_title'], $confirmation_link))."\n\n";\r
+                                               } else {\r
+                                                       $subject = $_config['site_name'].': '._AT('account_information');\r
+                                                       $body = _AT(array('new_account_enroll',AT_BASE_HREF, $_SESSION['course_title']))."\n\n";\r
+                                               }\r
+                                               \r
+                                               //$body .= SITE_NAME.': '._AT('account_information')."\n";\r
+                                               $body .= _AT('web_site') .' : '.AT_BASE_HREF."\n";\r
+                                               $body .= _AT('login_name') .' : '.$student['uname'] . "\n";\r
+                                               $body .= _AT('password') .' : '.$student['uname'] . "\n";\r
+\r
+                                               $mail = new ATutorMailer;\r
+                                               $mail->From     = $_config['contact_email'];\r
+                                               $mail->AddAddress($student['email']);\r
+                                               $mail->Subject = $subject;\r
+                                               $mail->Body    = $body;\r
+                                               $mail->Send();\r
+\r
+                                               unset($mail);\r
+                                       } else {\r
+                                               $already_enrolled .= '<li>' . $student['uname'] . '</li>';\r
+                                       }\r
+                               } else {\r
+                                       //$msg->addError('LIST_IMPORT_FAILED'); \r
+                               }\r
+                       } else if (! $student['err_disabled']) {\r
+                               $sql = "SELECT member_id FROM ".TABLE_PREFIX."members WHERE email='$student[email]'";\r
+                               $result = mysql_query($sql, $db);\r
+                               if ($row = mysql_fetch_assoc($result)) {\r
+                               \r
+                                       $m_id = $row['member_id'];\r
+\r
+                                       $sql = "INSERT INTO ".TABLE_PREFIX."course_enrollment (member_id, course_id, approved, last_cid, role) VALUES ($m_id, $course, '$enroll', 0, '$role')";\r
+\r
+                                       if($result = mysql_query($sql,$db)) {\r
+                                               $enrolled_list .= '<li>' . $student['uname'] . '</li>';\r
+                                       } else {\r
+                                               $sql = "REPLACE INTO ".TABLE_PREFIX."course_enrollment (member_id, course_id, approved, last_cid, role) VALUES ($m_id, $course, '$enroll', 0, '$role')";\r
+                                               $result = mysql_query($sql,$db);\r
+                                               $enrolled_list .= '<li>' . $student['uname'] . '</li>';\r
+                                       }\r
+                               $subject = $_config['site_name'].': '._AT('email_confirmation_subject');\r
+                               $body = _AT(array('enrol_message_approved',$_SESSION['course_title'],AT_BASE_HREF))."\n\n";\r
+                               $body .= _AT('web_site') .' : '.AT_BASE_HREF."\n";\r
+                               $body .= _AT('login_name') .' : '.$student['uname'] . "\n";\r
+                               $mail = new ATutorMailer;\r
+                               $mail->From     = $_config['contact_email'];\r
+                               $mail->AddAddress($student['email']);\r
+                               $mail->Subject = $subject;\r
+                               $mail->Body    = $body;\r
+                               $mail->Send();\r
+\r
+                               unset($mail);\r
+\r
+\r
+                               }\r
+\r
+\r
+\r
+\r
+                       } else if ($student['err_disabled']) {\r
+                               $not_enrolled_list .= '<li>' . $student['uname'] . '</li>';\r
+                       }\r
+               }\r
+       }\r
+       if ($already_enrolled) {\r
+               $feedback = array('ALREADY_ENROLLED', $already_enrolled);\r
+               $msg->addFeedback($feedback);\r
+       }\r
+       if ($enrolled_list) {\r
+               $feedback = array('ENROLLED', $enrolled_list);\r
+               $msg->addFeedback($feedback);\r
+       }\r
+       if ($not_enrolled_list) {\r
+               $feedback = array('NOT_ENROLLED', $not_enrolled_list);\r
+               $msg->addFeedback($feedback);\r
+       }\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/include/lib/file_storage.inc.php b/include/lib/file_storage.inc.php
new file mode 100644 (file)
index 0000000..722a305
--- /dev/null
@@ -0,0 +1,563 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+/**\r
+ * Additional constants are found in /include/lib/constants.inc.php (for the work spaces)\r
+ *\r
+ * The File Storage was designed to allow for unlimited workspace, although only four right now.\r
+ *\r
+ * All the functions are namespaced with fs_ (for File Storage not File System).\r
+ *\r
+ * These two variables are used throughout.\r
+ * $owner_type is used to define the workspace type. Also appears as $ot in _GET.\r
+ * $owner_id is the ID of the particular workspace type. Also appears as $oid in _GET.\r
+ * \r
+ **/\r
+\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+define('WORKSPACE_AUTH_NONE',  0);\r
+define('WORKSPACE_AUTH_READ',  1);\r
+define('WORKSPACE_AUTH_WRITE', 2); \r
+define('WORKSPACE_AUTH_RW',    3); // to save time\r
+\r
+/**\r
+ * given an owner_type and owner_id\r
+ * returns false if user cannot read or write to this workspace\r
+ * returns WORKSPACE_AUTH_READ if the user can read\r
+ * returns WORKSPACE_AUTH_WRITE if the user can write\r
+ */\r
+function fs_authenticate($owner_type, $owner_id) {\r
+       if (($owner_type == WORKSPACE_PERSONAL) && $_SESSION['member_id'] && $_SESSION['enroll'] && ($owner_id == $_SESSION['member_id'])) {\r
+\r
+               return WORKSPACE_AUTH_RW;\r
+\r
+       } else if ($owner_type == WORKSPACE_ASSIGNMENT && authenticate(AT_PRIV_ASSIGNMENTS, AT_PRIV_RETURN)) {\r
+               // instructors have read only access to assignments\r
+\r
+               return WORKSPACE_AUTH_READ;\r
+       \r
+       } else if ($owner_type == WORKSPACE_GROUP) {\r
+               if (isset($_SESSION['groups'][$owner_id])) {\r
+                       global $db;\r
+                       $sql = "SELECT * FROM ".TABLE_PREFIX."file_storage_groups WHERE group_id=$owner_id";\r
+                       $result = mysql_query($sql, $db);\r
+                       if (mysql_fetch_assoc($result)) {\r
+                               return WORKSPACE_AUTH_RW;\r
+                       }\r
+               }\r
+\r
+       } else if ($owner_type == WORKSPACE_COURSE) {\r
+               if (($owner_id == $_SESSION['course_id']) && authenticate(AT_PRIV_FILE_STORAGE, AT_PRIV_RETURN)) {\r
+                       return WORKSPACE_AUTH_RW;\r
+               } else if ($owner_id == $_SESSION['course_id']) {\r
+                       return WORKSPACE_AUTH_READ;\r
+               }\r
+       }\r
+       /* else if ($owner_type == WORKSPACE_SYSTEM) {\r
+               if (admin_authenticate(AT_ADMIN_PRIV_FILE_STORAGE, TRUE)) {\r
+                       return WORKSPACE_AUTH_RW;\r
+               } // else\r
+               return WORKSPACE_AUTH_READ; // everyone can read the System File Space\r
+       } */\r
+\r
+       return WORKSPACE_AUTH_NONE;\r
+}\r
+\r
+/**\r
+ * returns the localised name of the specified workspace\r
+ */\r
+function fs_get_workspace($owner_type, $owner_id) {\r
+       if ($owner_type == WORKSPACE_PERSONAL) {\r
+               return _AT('my_files');\r
+\r
+       } else if ($owner_type == WORKSPACE_COURSE) {\r
+               return _AT('course_files');\r
+\r
+       } else if ($owner_type == WORKSPACE_GROUP) {\r
+               global $db;\r
+               $sql = "SELECT title FROM ".TABLE_PREFIX."groups WHERE group_id=$owner_id";\r
+               $result = mysql_query($sql, $db);\r
+               $row    = mysql_fetch_assoc($result);\r
+               return $row['title'];\r
+\r
+       } else if ($owner_type == WORKSPACE_ASSIGNMENT) {\r
+               $row    = fs_get_assignment($owner_id);\r
+               return ($row ? $row['title'] : false);\r
+       } /*\r
+               else if ($owner_type == WORKSPACE_SYSTEM) {\r
+               return _AT('system_files');\r
+     }\r
+       */\r
+}\r
+\r
+/**\r
+ * returns the assignment row specified by $assignment_id\r
+ * false if not found.\r
+ */\r
+function fs_get_assignment($assignment_id) {\r
+       global $db;\r
+       $sql = "SELECT assignment_id, title, assign_to, date_due, date_cutoff, UNIX_TIMESTAMP(date_cutoff) AS u_date_cutoff, multi_submit FROM ".TABLE_PREFIX."assignments WHERE assignment_id=$assignment_id AND course_id=$_SESSION[course_id]";\r
+       $result = mysql_query($sql, $db);\r
+       $row    = mysql_fetch_assoc($result);\r
+       return $row;\r
+}\r
+\r
+/**\r
+ * retrieve folder(s) specified by $folder_id\r
+ * $folder_id the ID of the single folder, or array of IDs\r
+ * if $folder_id is an array then returns an array of folder rows\r
+ * if $folder_id is an int then returns the single row array\r
+ *\r
+ * This function does not authenticate the $folder_id for the assignment.\r
+ *\r
+ * Note: This function checks if the $owner_type is an Assignment.\r
+ *\r
+ */\r
+function fs_get_folder_by_id($folder_id, $owner_type, $owner_id) {\r
+       global $db;\r
+\r
+       $rows = array();\r
+\r
+       if ($owner_type == WORKSPACE_ASSIGNMENT) {\r
+               // get the folder row from the assignments table\r
+\r
+               $sql = "SELECT assign_to FROM ".TABLE_PREFIX."assignments WHERE assignment_id=$owner_id AND course_id=$_SESSION[course_id]";\r
+               $result = mysql_query($sql, $db);\r
+               $row  = mysql_fetch_assoc($result);\r
+               if ($row['assign_to']) {\r
+                       $sql = "SELECT title FROM ".TABLE_PREFIX."groups WHERE group_id=$folder_id";\r
+                       $result = mysql_query($sql, $db);\r
+                       $row = mysql_fetch_assoc($result);\r
+\r
+                       $rows = array('title' => $row['title'], 'folder_id' => $folder_id);\r
+               } else {\r
+                       $rows = array('title' => get_display_name($folder_id), 'folder_id' => $folder_id);\r
+               }\r
+       } else {\r
+               if (is_array($folder_id)) {\r
+                       $folder_id_list = implode(',', $folder_id);\r
+\r
+                       $sql = "SELECT folder_id, title, parent_folder_id FROM ".TABLE_PREFIX."folders WHERE folder_id IN ($folder_id_list) AND owner_type=$owner_type AND owner_id=$owner_id ORDER BY title";\r
+                       $result = mysql_query($sql, $db);\r
+                       while ($row = mysql_fetch_assoc($result)) {\r
+                               $rows[] = $row;\r
+                       }\r
+\r
+               } else {\r
+                       $sql = "SELECT folder_id, title, parent_folder_id FROM ".TABLE_PREFIX."folders WHERE folder_id=$folder_id AND owner_type=$owner_type AND owner_id=$owner_id";\r
+                       $result = mysql_query($sql, $db);\r
+                       $rows = mysql_fetch_assoc($result);\r
+               }\r
+       }\r
+       return $rows;\r
+}\r
+\r
+/**\r
+ * retrieve folder(s) specified by $parent_folder_id\r
+ *\r
+ * Note: This function checks if the $owner_type is an Assignment.\r
+ *\r
+ */\r
+function fs_get_folder_by_pid($parent_folder_id, $owner_type, $owner_id) {\r
+       global $db;\r
+\r
+       $rows = array();\r
+       if ($owner_type == WORKSPACE_ASSIGNMENT) {\r
+               // get the folder row from the assignments table\r
+               // does not currently support sub-folders for assignments\r
+               if ($parent_folder_id == 0) {\r
+                       $sql = "SELECT assign_to FROM ".TABLE_PREFIX."assignments WHERE assignment_id=$owner_id AND course_id=$_SESSION[course_id]";\r
+                       $result = mysql_query($sql, $db);\r
+                       $row  = mysql_fetch_assoc($result);\r
+                       if ($row['assign_to']) {\r
+                               $sql = "SELECT G.group_id AS folder_id, G.title FROM ".TABLE_PREFIX."groups G INNER JOIN ".TABLE_PREFIX."file_storage_groups FS USING (group_id) WHERE G.type_id=$row[assign_to] ORDER BY G.title";\r
+                       } else {\r
+                               global $system_courses;\r
+\r
+                               $sql = "SELECT E.member_id AS folder_id, M.login AS title FROM ".TABLE_PREFIX."course_enrollment E INNER JOIN ".TABLE_PREFIX."members M USING (member_id) WHERE E.course_id=$_SESSION[course_id] AND E.approved='y' AND E.privileges & ".AT_PRIV_GROUPS." = 0 AND E.member_id<>{$system_courses[$_SESSION[course_id]][member_id]} ORDER BY M.login";\r
+                       }\r
+                       $result = mysql_query($sql, $db);\r
+\r
+                       while ($row = mysql_fetch_assoc($result)) {\r
+                               $rows[] = $row;\r
+                       }\r
+               }\r
+       } else {\r
+               $sql = "SELECT folder_id, title FROM ".TABLE_PREFIX."folders WHERE parent_folder_id=$parent_folder_id AND owner_type=$owner_type AND owner_id=$owner_id ORDER BY title";\r
+               $result = mysql_query($sql, $db);\r
+               while ($row = mysql_fetch_assoc($result)) {\r
+                       $rows[] = $row; \r
+               }\r
+       }\r
+       return $rows;\r
+}\r
+\r
+/**\r
+ * outputs the folders as a  list.\r
+ *\r
+ * $current_folder_id the current folder id, used for pre-selecting the radio button\r
+ * $parent_folder_id the folder id to display children of\r
+ * $folders the array of folders returned from get_folders()\r
+ * $disable whether or not the radio button is available\r
+ */\r
+function fs_print_folders($current_folder_id, $parent_folder_id, &$folders, $disable = FALSE) {\r
+       if (!isset($folders[$parent_folder_id])) {\r
+               return;\r
+       }\r
+\r
+       echo '<ul>';\r
+       foreach ($folders[$parent_folder_id] as $folder_id => $folder_info) {\r
+               echo '<li class="folders">';\r
+               \r
+               echo '<input type="radio" name="new_folder" value="'.$folder_id.'" id="f'.$folder_id.'"';\r
+               if ($_GET['folders'] && in_array($folder_id, $_GET['folders'])) {\r
+                       $disable = TRUE;\r
+               }\r
+               if ($folder_id == $current_folder_id) {\r
+                       echo ' checked="checked"';\r
+               }\r
+               if ($disable) {\r
+                       echo ' disabled="disabled"';\r
+               }\r
+               echo '/><label for="f'.$folder_id.'">'.htmlspecialchars($folder_info['title']);\r
+               if ($folder_id == $current_folder_id) {\r
+                       echo ' '._AT('current_location');\r
+               }\r
+               echo '</label>';\r
+               \r
+               fs_print_folders($current_folder_id, $folder_id, $folders, $disable);\r
+               if ($_GET['folders'] && in_array($folder_id, $_GET['folders'])) {\r
+                       $disable = FALSE;\r
+               }\r
+               echo '</li>';\r
+       }\r
+       echo '</ul>';\r
+}\r
+\r
+/**\r
+ * returns an array of all the revisions for the given file_id\r
+ *\r
+ * $file_id ID of a file in a revision sequence. can be any revision, does not have to be the latest.\r
+ * This function is recursive and uses fs_get_revisions_down_recursive() and fs_get_revisions_recurisve() below.\r
+ */\r
+function fs_get_revisions($file_id, $owner_type, $owner_id) {\r
+       global $db;\r
+\r
+       $sql = "SELECT * FROM ".TABLE_PREFIX."files WHERE file_id=$file_id AND owner_type=$owner_type AND owner_id=$owner_id";\r
+       $result = mysql_query($sql, $db);\r
+       if ($row = mysql_fetch_assoc($result)) {\r
+               return array_merge(array_reverse(fs_get_revisions_down_recursive($row['parent_file_id'])), array($row), fs_get_revisions_recursive($file_id));\r
+       }\r
+       return array();\r
+}\r
+\r
+/**\r
+ * recursively retrieves all the revisions of the file.\r
+ * recurses DOWN the revisions path.\r
+ * PRIVATE! use fs_get_revisions() above.\r
+ */\r
+function fs_get_revisions_down_recursive($file_id) {\r
+       global $db;\r
+\r
+       if ($file_id == 0) {\r
+               return array();\r
+       }\r
+\r
+       $sql = "SELECT * FROM ".TABLE_PREFIX."files WHERE file_id=$file_id";\r
+       $result = mysql_query($sql, $db);\r
+       $row = mysql_fetch_assoc($result);\r
+\r
+       if (!$row) {\r
+               return array();\r
+       } else if (!$row['parent_file_id']) {\r
+               return array($row);\r
+       }\r
+\r
+       return array_merge(array($row), fs_get_revisions_down_recursive($row['parent_file_id']));\r
+}\r
+\r
+/**\r
+ * recursively retrieves all the revisions of the file.\r
+ * recurses UP the revisions path.\r
+ * PRIVATE! use fs_get_revisions() above.\r
+ */\r
+function fs_get_revisions_recursive($file_id) {\r
+       global $db;\r
+\r
+       if ($file_id == 0) {\r
+               return array();\r
+       }\r
+\r
+       $sql = "SELECT * FROM ".TABLE_PREFIX."files WHERE parent_file_id=$file_id";\r
+       $result = mysql_query($sql, $db);\r
+       $row = mysql_fetch_assoc($result);\r
+\r
+       if (!$row) {\r
+               return array();\r
+       }\r
+\r
+       return array_merge(array($row), fs_get_revisions_recursive($row['file_id']));\r
+}\r
+\r
+/**\r
+ * returns the full path based on $file_id with trailing slash.\r
+ *\r
+ * Ex. if file_id is 2345 and WORKSPACE_PATH_DEPTH is set to 3 then\r
+ * the path returned will be WORKSPACE_FILE_PATH.'5/4/3/'\r
+ *\r
+ * If the path does not exist within the WORKSPACE_FILE_PATH then attempts\r
+ * to create it.\r
+ */\r
+function fs_get_file_path($file_id) {\r
+       $end_part = substr($file_id, -WORKSPACE_PATH_DEPTH);\r
+       $path = WORKSPACE_FILE_PATH;\r
+       $dirs = max(-WORKSPACE_PATH_DEPTH, -strlen($file_id));\r
+       $id_threshold = pow(10,WORKSPACE_PATH_DEPTH); // only check for the dir before reaching this value.\r
+    for ($i = -1; $i >= $dirs; $i--) {\r
+               $path .= substr($file_id, $i, 1) . DIRECTORY_SEPARATOR;\r
+               if ($file_id <= $id_threshold) {\r
+                       if (!is_dir($path)) {\r
+                               @mkdir($path);\r
+                       }\r
+               }\r
+       }\r
+\r
+       return $path;\r
+}\r
+\r
+/**\r
+ * delete a given file, its revisions, and comments.\r
+ *\r
+ * $file_id the ID of the file to delete. can be any ID within a revision sequence.\r
+ */\r
+function fs_delete_file($file_id, $owner_type, $owner_id) {\r
+       global $db;\r
+       $revisions = fs_get_revisions($file_id, $owner_type, $owner_id);\r
+       foreach ($revisions as $file) {\r
+               $sql = "DELETE FROM ".TABLE_PREFIX."files WHERE file_id=$file[file_id] AND owner_type=$owner_type AND owner_id=$owner_id";\r
+               mysql_query($sql, $db);\r
+\r
+               if (mysql_affected_rows($db) == 1) {\r
+                       $sql = "DELETE FROM ".TABLE_PREFIX."files_comments WHERE file_id=$file[file_id]";\r
+                       mysql_query($sql, $db);\r
+\r
+                       $path = fs_get_file_path($file['file_id']);\r
+                       if (file_exists($path . $file['file_id'])) {\r
+                               @unlink($path . $file['file_id']);\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+/**\r
+ * returns only the extension part of the specified file name\r
+ *\r
+ * $file_name the full name of the file.\r
+ */\r
+function fs_get_file_extension($file_name) {\r
+       $ext = pathinfo($file_name);\r
+       return $ext['extension'];\r
+}\r
+\r
+/**\r
+ * returns the image name (w/o the ".gif" ending) of the icon to use\r
+ * for the given file name.\r
+ * if no icon is specified (by mime.inc.php) then returns "generic"\r
+ */\r
+function fs_get_file_type_icon($file_name) {\r
+       global $mime;\r
+       if (!isset($mime)) {\r
+               require(AT_INCLUDE_PATH.'lib/mime.inc.php');\r
+       }\r
+       $ext = fs_get_file_extension($file_name);\r
+\r
+       if (isset($mime[$ext]) && $mime[$ext][1]) {\r
+               return $mime[$ext][1];\r
+       }\r
+       return 'generic';\r
+}\r
+\r
+/**\r
+ * deletes the folder, its sub-folders and associated files.\r
+ *\r
+ * $folder_id the ID of the folder to delete, recursively, with content.\r
+ */\r
+function fs_delete_folder($folder_id, $owner_type, $owner_id) {\r
+       if (!$folder_id) { return; }\r
+\r
+       global $db;\r
+\r
+       $rows = fs_get_folder_by_pid($folder_id, $owner_type, $owner_id);\r
+       foreach ($rows as $row) {\r
+               fs_delete_folder($row['folder_id'], $owner_type, $owner_id);\r
+       }\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."folders WHERE folder_id=$folder_id AND owner_type=$owner_type AND owner_id=$owner_id";\r
+       mysql_query($sql, $db);\r
+\r
+       // delete this file's folders (we only select the latest versions because\r
+       // the delete_file() function takes care of the revisions for us\r
+       $sql = "SELECT file_id FROM ".TABLE_PREFIX."files WHERE folder_id=$folder_id AND parent_file_id=0 AND owner_type=$owner_type AND owner_id=$owner_id";\r
+       $result = mysql_query($sql, $db);\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               fs_delete_file($row['file_id'], $owner_type, $owner_id);\r
+       }\r
+}\r
+\r
+/**\r
+ * archives a folder into a specified zip handler.\r
+ *\r
+ * $folder_id the ID of the folder to archive recursively, with content.\r
+ * $zipfile reference to the zipFile object.\r
+ * $path the absolute path to the current folder.\r
+ */\r
+function fs_download_folder($folder_id, &$zipfile, $owner_type, $owner_id, $path = '') {\r
+       global $db;\r
+\r
+       $parent_row = fs_get_folder_by_id($folder_id, $owner_type, $owner_id);\r
+       //$sql = "SELECT title FROM ".TABLE_PREFIX."folders WHERE folder_id=$folder_id AND owner_type=$owner_type AND owner_id=$owner_id";\r
+       //$result = mysql_query($sql, $db);\r
+       if ($parent_row) {\r
+               $zipfile->create_dir($path . $parent_row['title']);\r
+       }\r
+\r
+       $sql = "SELECT file_id, file_name, UNIX_TIMESTAMP(date) AS date FROM ".TABLE_PREFIX."files WHERE folder_id=$folder_id AND parent_file_id=0 AND owner_type=$owner_type AND owner_id=$owner_id";\r
+       $result = mysql_query($sql, $db);\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               $file_path = fs_get_file_path($row['file_id']) . $row['file_id'];\r
+\r
+               $zipfile->add_file(file_get_contents($file_path), $path . $parent_row['title'] .'/' . $row['file_name'], $row['date']);\r
+       }\r
+\r
+       $rows = fs_get_folder_by_pid($folder_id, $owner_type, $owner_id);\r
+       foreach ($rows as $row) {\r
+               fs_download_folder($row['folder_id'], $zipfile, $owner_type, $owner_id, $path . $parent_row['title'] . '/');\r
+       }\r
+}\r
+\r
+/**\r
+ * returns the full path to the current folder\r
+ *\r
+ * $folder_id the current folder\r
+ * $workspace the owner_type of this folder\r
+ * $owner_id the ID of the owner.\r
+ */\r
+function fs_get_folder_path($folder_id, $owner_type, $owner_id) {\r
+       $folder_path = fs_get_folder_path_recursive($folder_id, $owner_type, $owner_id);\r
+\r
+       return array_reverse($folder_path);\r
+}\r
+\r
+/**\r
+ * recursively return the path to the current folder\r
+ * PRIVATE! do not call directly, use get_folder_path() above.\r
+ */\r
+function fs_get_folder_path_recursive($folder_id, $owner_type, $owner_id) {\r
+       global $db;\r
+\r
+       if ($folder_id == 0) {\r
+               return array();\r
+       }\r
+\r
+       $row = fs_get_folder_by_id($folder_id, $owner_type, $owner_id);\r
+\r
+       return array_merge(array($row), fs_get_folder_path_recursive($row['parent_folder_id'], $owner_type, $owner_id));\r
+}\r
+\r
+/**\r
+ * deletes all the files, folders, comments, revisions, etc.. in the specified workspace.\r
+ */\r
+function fs_delete_workspace($owner_type, $owner_id) {\r
+       global $db;\r
+\r
+       $sql = "SELECT folder_id, owner_type, owner_id FROM ".TABLE_PREFIX."folders WHERE owner_type=$owner_type AND owner_id=$owner_id AND parent_folder_id=0";\r
+       $result = mysql_query($sql, $db);\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               fs_delete_folder($row['folder_id'], $row['owner_type'], $row['owner_id']);\r
+       }\r
+\r
+       $sql = "SELECT file_id, owner_type, owner_id FROM ".TABLE_PREFIX."files WHERE owner_type=$owner_type AND owner_id=$owner_id";\r
+       $result = mysql_query($sql, $db);\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               fs_delete_file($row['file_id'], $row['owner_type'], $row['owner_id']);\r
+       }\r
+}\r
+\r
+/**\r
+ * copies a file to another workspace.\r
+ * currently only used for submitting assignments.\r
+ **/\r
+function fs_copy_file($file_id, $src_owner_type, $src_owner_id, $dest_owner_type, $dest_owner_id, $dest_folder_id) {\r
+       global $db;\r
+\r
+       $sql = "SELECT file_name, file_size, description FROM ".TABLE_PREFIX."files WHERE file_id=$file_id AND owner_type=$src_owner_type AND owner_id=$src_owner_id";\r
+       $result = mysql_query($sql, $db);\r
+       if (!$row = mysql_fetch_assoc($result)) {\r
+               return false;\r
+       }\r
+       $sql = "INSERT INTO ".TABLE_PREFIX."files VALUES (NULL, $dest_owner_type, $dest_owner_id, $_SESSION[member_id], $dest_folder_id, 0, NOW(), 0, 0, '$row[file_name]', '$row[file_size]', '$row[description]')";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $id = mysql_insert_id($db);\r
+\r
+       $src_file  = fs_get_file_path($file_id) . $file_id;\r
+       $dest_file = fs_get_file_path($id) . $id;\r
+       copy($src_file, $dest_file);\r
+}\r
+\r
+/**\r
+ * used with usort() to sort the revisions array returned from fs_get_revisions()\r
+ * $col is a valid array key to sort by\r
+ * $order is either 'asc' or 'desc'\r
+ */\r
+function fs_revisions_sort_compare($a, $b) {\r
+       global $col, $order;\r
+\r
+       if ($order == 'asc') {\r
+               return strcasecmp($a[$col], $b[$col]);\r
+       }\r
+       return strcasecmp($b[$col], $a[$col]);\r
+}\r
+\r
+/**\r
+ * copies a directory to another workspace.\r
+ * not currently used anywhere.\r
+ */\r
+/***\r
+function fs_copy_folder($folder_id, $src_owner_type, $src_owner_id, $dest_owner_type, $dest_owner_id, $dest_parent_folder_id) {\r
+       global $db;\r
+\r
+       $folder = fs_get_folder_by_id($folder_id, $src_owner_type, $src_owner_id);\r
+       if (!$folder) {\r
+               return false;\r
+       }\r
+\r
+       $sql = "INSERT INTO ".TABLE_PREFIX."folders VALUES (0, $dest_parent_folder_id, $dest_owner_type, $dest_owner_id, '$folder[title]')";\r
+       $result = mysql_query($sql, $db);\r
+       $id = mysql_insert_id($db);\r
+\r
+       $sql = "SELECT file_id FROM ".TABLE_PREFIX."files WHERE folder_id=$folder_id AND owner_type=$src_owner_type AND owner_id=$src_owner_id";\r
+       $result = mysql_query($sql, $db);\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               fs_copy_file($row['file_id'], $src_owner_type, $src_owner_id, $dest_owner_type, $dest_owner_id, $id);\r
+       }\r
+\r
+       $folders = fs_get_folder_by_pid($folder_id, $src_owner_type, $src_owner_id);\r
+       foreach ($folders as $folder) {\r
+               fs_copy_folder($folder['folder_id'], $src_owner_type, $src_owner_id, $dest_owner_type, $dest_owner_id, $id);\r
+       }\r
+}\r
+*/\r
+?>
\ No newline at end of file
diff --git a/include/lib/filemanager.inc.php b/include/lib/filemanager.inc.php
new file mode 100644 (file)
index 0000000..57a830b
--- /dev/null
@@ -0,0 +1,401 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+/**
+* Allows the copying of entire directories.
+* @access  public
+* @param   string $source              the source directory
+* @param   string $dest                        the destination directory
+* @return  boolean                             whether the copy was successful or not
+* @link           http://www.php.net/copy
+* @author  www at w8c dot com
+*/
+function copys($source,$dest)
+{
+       if (!is_dir($source)) {
+               return false;
+       }
+       if (!is_dir($dest))     {
+               mkdir($dest);
+       }
+       
+       $h=@dir($source);
+       while (@($entry=$h->read()) !== false) {
+               if (($entry == '.') || ($entry == '..')) {
+                       continue;
+               }
+
+               if (is_dir("$source/$entry") && $dest!=="$source/$entry") {
+                       copys("$source/$entry", "$dest/$entry");
+               } else {
+                       @copy("$source/$entry", "$dest/$entry");
+               }
+       }
+       $h->close();
+       return true;
+} 
+
+/**
+* Enables deletion of directory if not empty
+* @access  public
+* @param   string $dir         the directory to delete
+* @return  boolean                     whether the deletion was successful
+* @author  Joel Kronenberg
+*/
+function clr_dir($dir) {
+       if(!$opendir = @opendir($dir)) {
+               return false;
+       }
+       
+       while(($readdir=readdir($opendir)) !== false) {
+               if (($readdir !== '..') && ($readdir !== '.')) {
+                       $readdir = trim($readdir);
+
+                       clearstatcache(); /* especially needed for Windows machines: */
+
+                       if (is_file($dir.'/'.$readdir)) {
+                               if(!@unlink($dir.'/'.$readdir)) {
+                                       return false;
+                               }
+                       } else if (is_dir($dir.'/'.$readdir)) {
+                               /* calls itself to clear subdirectories */
+                               if(!clr_dir($dir.'/'.$readdir)) {
+                                       return false;
+                               }
+                       }
+               }
+       } /* end while */
+
+       @closedir($opendir);
+       
+       if(!@rmdir($dir)) {
+               return false;
+       }
+       return true;
+}
+
+/**
+* Calculate the size in Bytes of a directory recursively.
+* @access  public
+* @param   string $dir         the directory to traverse
+* @return  int                         the total size in Bytes of the directory
+* @author  Joel Kronenberg
+*/
+function dirsize($dir) {
+       if (is_dir($dir)) {
+               $dh = @opendir($dir);
+       }
+       if (!$dh) {
+               return -1;
+       }
+       $size = 0;
+       while (($file = readdir($dh)) !== false) {
+
+               if ($file != '.' && $file != '..') {
+                       $path = $dir.$file;
+                       if (is_dir($path)) {
+                               $size += dirsize($path.'/');
+                       } elseif (is_file($path)) {
+                               $size += filesize($path);
+                       }
+               }
+               
+       }
+       closedir($dh);
+       return $size;
+}
+
+/**
+* This function gets used by PclZip when extracting a zip archive.
+* @access  private
+* @return  int                         whether or not to include the file
+* @author  Joel Kronenberg
+*/
+       function preExtractCallBack($p_event, &$p_header) {
+               global $translated_file_names;
+
+               if ($p_header['folder'] == 1) {
+                       return 1;
+               }
+
+               if ($translated_file_names[$p_header['index']] == '') {
+                       return 0;
+               }
+
+               if ($translated_file_names[$p_header['index']]) {
+                       $p_header['filename'] = substr($p_header['filename'], 0, -strlen($p_header['stored_filename']));
+                       $p_header['filename'] .= $translated_file_names[$p_header['index']];
+               }
+               return 1;
+       }
+
+/**
+* This function gets used by PclZip when creating a zip archive.
+* @access  private
+* @return  int                         whether or not to include the file
+* @author  Joel Kronenberg
+*/
+       function preImportCallBack($p_event, &$p_header) {
+               global $IllegalExtentions;
+
+               if ($p_header['folder'] == 1) {
+                       return 1;
+               }
+
+               $path_parts = pathinfo($p_header['filename']);
+               $ext = $path_parts['extension'];
+
+               if (in_array($ext, $IllegalExtentions)) {
+                       return 0;
+               }
+
+               return 1;
+       }
+
+
+/* prints the <options> out of $cats which is an array of course categories where */
+/* $cats[parent_cat_id][] = $row */
+function print_course_cats($parent_cat_id, &$cats, $cat_row, $depth=0) {
+       $my_cats = $cats[$parent_cat_id];
+       if (!is_array($my_cats)) {
+               return;
+       }
+       foreach ($my_cats as $cat) {
+
+               echo '<option value="'.$cat['cat_id'].'"';
+               if($cat['cat_id'] == $cat_row){
+                       echo  ' selected="selected"';
+               }
+               echo '>';
+               echo str_pad('', $depth, '-');
+               echo $cat['cat_name'].'</option>'."\n";
+
+               print_course_cats($cat['cat_id'], $cats,  $cat_row, $depth+1);
+       }
+}
+
+// returns the most appropriate representation of Bytes in MB, KB, or B
+function get_human_size($num_bytes) {
+       $abs_num_bytes = abs($num_bytes);
+
+       if ($abs_num_bytes >= AT_KBYTE_SIZE * AT_KBYTE_SIZE) {
+               return round(bytes_to_megabytes($num_bytes), 2) .' '. _AT('mb');
+       } else if ($abs_num_bytes >= AT_KBYTE_SIZE) {
+               return round(bytes_to_kilobytes($num_bytes), 2) .' '._AT('kb') ;
+       }
+       // else:
+
+       return $num_bytes . ' '._AT('bt');
+}
+
+/**
+* Returns the MB representation of inputed bytes
+* @access  public
+* @param   int $num_bytes      the input bytes to convert
+* @return  int                         MB representation of $num_bytes
+* @author  Heidi Hazelton
+*/
+function bytes_to_megabytes($num_bytes) {
+       return $num_bytes/AT_KBYTE_SIZE/AT_KBYTE_SIZE;
+}
+
+/**
+* Returns the Byte representation of inputed MB
+* @access  public
+* @param   int $num_bytes      the input MB to convert
+* @return  int                         the Bytes representation of $num_bytes
+* @author  Heidi Hazelton
+*/
+function megabytes_to_bytes($num_bytes) {
+       return $num_bytes*AT_KBYTE_SIZE*AT_KBYTE_SIZE;
+}
+
+/**
+* Returns the KB representation of inputed Bytes
+* @access  public
+* @param   int $num_bytes      the input Bytes to convert
+* @return  int                         the KB representation of $num_bytes
+* @author  Heidi Hazelton
+*/
+function bytes_to_kilobytes($num_bytes) {
+       return $num_bytes/AT_KBYTE_SIZE;
+}
+
+/**
+* Returns the Bytes representation of inputed KBytes
+* @access  public
+* @param   int $num_bytes      the input KBytes to convert
+* @return  int                         the KBytes representation of $num_bytes
+* @author  Heidi Hazelton
+*/
+function kilobytes_to_bytes($num_bytes) {
+       return $num_bytes*AT_KBYTE_SIZE;
+}
+
+/**
+* Outputs the directories associated with a course in the form of <option> elements.
+* @access public
+* @param  string $cur_dir  the current directory to include in the options.
+* @author Norma Thompson
+*/
+function output_dirs($current_path,$cur_dir,$indent) {
+       // open the cur_dir
+       if ($dir = opendir($current_path.$cur_dir)) {
+
+               // recursively call output_dirs() for all directories in this directory
+               while (false !== ($file = readdir($dir)) ) {
+
+                       //if the name is not a directory 
+                       if( ($file == '.') || ($file == '..') ) {
+                               continue;
+                       }
+
+                       // if it is a directory call function
+                       if(is_dir($current_path.$cur_dir.$file)) {
+                               $ldir = explode('/',$cur_dir.$file);
+                               $count = count($ldir);
+                               $label = $ldir[$count-1];
+                               
+                               $dir_option .= '<option value="'.$cur_dir.$file.'/" >'.$indent.$label.'</option>';
+
+                               $dir_option .= output_dirs($current_path,$cur_dir.$file.'/',$indent.'--');
+                       }
+                       
+               } // end while  
+               
+               closedir($dir); 
+       }
+       return $dir_option;
+}
+
+function display_tree($current_path, $cur_dir, $pathext, $ignore_children = false) {
+       // open the cur_dir
+       static $list_array;
+       if (!isset($list_array)) {
+               $list_array = explode(',', $_GET['list']);
+       }
+       if ($dir = opendir($current_path . $cur_dir)) {
+
+               // recursively call output_dirs() for all directories in this directory
+               while (false !== ($file = readdir($dir)) ) {
+
+                       //if the name is not a directory 
+                       if( ($file == '.') || ($file == '..') ) {
+                               continue;
+                       }
+
+                       // if it is a directory call function
+                       if (is_dir($current_path . $cur_dir . $file)) {
+
+                               //$ldir = explode('/',$cur_dir.$file);
+                               //$count = count($ldir);
+                               //$label = $ldir[$count-1];
+
+                               $check = '';
+                               $here  = '';
+                               if ($cur_dir . $file == substr($pathext, 0, -1)) {
+                                       $check = 'checked="checked"';
+                                       $here = ' ' . _AT('current_location');
+                               } else if (($cur_dir == $pathext) && in_array($file, $list_array)) {
+                                       $ignore_children = true;
+                               }
+
+                               if ($ignore_children) {
+                                       $check = 'disabled="disabled"';
+                                       $class = ' disabled';
+                               }
+
+                               $dir_option .= '<ul><li class="folders'.$class.'">';
+                               $dir_option .= '<label><input type="radio" name="dir_name" value="'.$cur_dir.$file.'" '.$check. '/>'. $file . $here. '</label>';
+                               $dir_option .= ''.display_tree($current_path,$cur_dir.$file.'/', $pathext, $ignore_children).'';
+                               $dir_option .= '</li></ul>';
+
+                               if (($cur_dir == $pathext) && in_array($file, $list_array)) {
+                                       $ignore_children = false;
+                                       $class = '';
+                               }
+                       }
+
+                       
+               } // end while  
+               
+               closedir($dir); 
+       }
+       return $dir_option;
+}
+
+function course_realpath($file) {
+       if (!$_SESSION['course_id']) {
+               return FALSE;
+       }
+       
+       $course_path = AT_CONTENT_DIR . $_SESSION['course_id'];
+       
+       $path_parts = pathinfo($file);
+       
+       $dir_name   = $path_parts['dirname'];
+       $file_name  = $path_parts['basename'];
+       $ext_name   = $path_parts['extension'];
+
+       //1. determine the real path of the file/directory
+       if (is_dir($dir_name.DIRECTORY_SEPARATOR.$file_name) && $ext_name == '') {
+               //if directory ws passed through (moving file to diff directory)
+               $real = realpath($dir_name . DIRECTORY_SEPARATOR . $file_name);
+       } else {
+               //if file was passed through or no existant direcotry was passed through (rename/creating dir)
+               $real = realpath($dir_name);
+       }
+
+       //2. and whether its in the course content directory
+       if (substr($real, 0, strlen($course_path)) != $course_path) {
+               return FALSE;
+       }
+
+       //3. check if extensions are legal
+
+       //4. Otherwise return the real path of the file
+       return $real;
+}
+
+/**
+* Returns canonicalized absolute pathname to a file/directory in the content directory
+* @access public
+* @param  string $file the relative path to the file or directory
+* @return  string      the full path to the file or directory, FALSE if it does not exist in our content directory.
+*/
+function course_realpath_NEW_VERSION($file) {
+       if (!$_SESSION['course_id']) {
+               return FALSE;
+       }
+       
+       $course_path = AT_CONTENT_DIR . $_SESSION['course_id'];
+
+       // determine the real path of the file/directory
+       $real = realpath($course_path . DIRECTORY_SEPARATOR . $file);
+       
+       if (!file_exists($real)) {
+               // the file or directory does not exist
+               return FALSE;
+
+       } else if (substr($real, 0, strlen($course_path)) != $course_path) {
+               // the file or directory is not in the content path
+               return FALSE;
+
+       } else {
+               // Otherwise return the real path of the file
+               return $real;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/include/lib/forums.inc.php b/include/lib/forums.inc.php
new file mode 100644 (file)
index 0000000..23cf111
--- /dev/null
@@ -0,0 +1,284 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+/**
+* Returns an array of (shared and non-shared) forums belonging to the given course
+* @access  public
+* @param   integer $course             id of the course
+* @return  string array                        each row is a forum 
+* @see     $db                                 in include/vitals.inc.php
+* @see     is_shared_forum()
+* @author  Heidi Hazelton
+* @author  Joel Kronenberg
+*/
+function get_forums($course) {
+       global $db;
+
+       if ($course) {
+               $sql    = "SELECT F.*, DATE_FORMAT(F.last_post, '%Y-%m-%d %H-%i:%s') AS last_post FROM ".TABLE_PREFIX."forums_courses FC INNER JOIN ".TABLE_PREFIX."forums F USING (forum_id) WHERE FC.course_id=$course GROUP BY FC.forum_id ORDER BY F.title";
+       } else {
+               $sql    = "SELECT F.*, FC.course_id, DATE_FORMAT(F.last_post, '%Y-%m-%d %H-%i:%s') AS last_post FROM ".TABLE_PREFIX."forums_courses FC INNER JOIN ".TABLE_PREFIX."forums F USING (forum_id) GROUP BY FC.forum_id ORDER BY F.title";
+       }
+
+       // 'nonshared' forums are always listed first:
+       $forums['nonshared'] = array();
+       $forums['shared']    = array();
+       $forums['group']     = array();
+
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_assoc($result)) {
+               // for each forum, check if it's shared or not:
+
+               if (is_shared_forum($row['forum_id'])) {
+                       $forums['shared'][] = $row;
+               } else {
+                       $forums['nonshared'][] = $row;
+               }
+       }
+               
+       // retrieve the group forums:
+
+       if (!$_SESSION['groups']) {
+               return $forums;
+       }
+
+       $groups =  implode(',',$_SESSION['groups']);
+
+       $sql = "SELECT F.*, G.group_id FROM ".TABLE_PREFIX."forums_groups G INNER JOIN ".TABLE_PREFIX."forums F USING (forum_id) WHERE G.group_id IN ($groups) ORDER BY F.title";
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_assoc($result)) {
+               $row['title'] = get_group_title($row['group_id']);
+               $forums['group'][] = $row;
+       }
+
+       return $forums; 
+}
+
+/**
+* Returns true/false whether or not this forum is shared.
+* @access  public
+* @param   integer $forum_id   id of the forum
+* @return  boolean                             true if this forum is shared, false otherwise
+* @see     $db                                 in include/vitals.inc.php
+* @author  Joel Kronenberg
+*/
+function is_shared_forum($forum_id) {
+       global $db;
+
+       $sql = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."forums_courses WHERE forum_id=$forum_id";
+       $result = mysql_query($sql, $db);
+       $row = mysql_fetch_assoc($result);
+
+       if ($row['cnt'] > 1) {
+               return TRUE;
+       } // else:
+       
+       return FALSE;
+}
+
+
+/**
+* Returns forum information for given forum_id 
+* @access  public
+* @param   integer $forum_id   id of the forum
+* @param   integer $course             id of the course (for non-admins)
+* @return  string array                        each row is a forum 
+* @see     $db                                 in include/vitals.inc.php
+* @author  Heidi Hazelton
+*/
+function get_forum($forum_id, $course = '') {
+       global $db;
+
+       if (!empty($course)) {
+               $sql    = "SELECT * FROM ".TABLE_PREFIX."forums_courses fc, ".TABLE_PREFIX."forums f WHERE (fc.course_id=$course OR fc.course_id=0) AND fc.forum_id=f.forum_id and fc.forum_id=$forum_id ORDER BY title";
+               $result = mysql_query($sql, $db);
+               $forum = mysql_fetch_assoc($result);
+       } else if (empty($course)) {    //only admins should be retrieving forums w/o a course!  add this check
+               $sql = "SELECT * FROM ".TABLE_PREFIX."forums WHERE forum_id=$forum_id";
+               $result = mysql_query($sql, $db);
+               $forum = mysql_fetch_assoc($result);
+       } else {
+
+               return;
+       }
+
+       return $forum;  
+}
+
+/**
+* Checks to see if signed in member is allowed to view the forum page
+* @access  public
+* @param   integer $forum_id   id of the forum
+* @return  boolean                             view (true) or not view (false)
+* @see     $db                                 in include/vitals.inc.php
+* @author  Heidi Hazelton
+*/
+function valid_forum_user($forum_id) {
+       global $db;
+
+       $sql    = "SELECT forum_id FROM ".TABLE_PREFIX."forums_courses WHERE (course_id=$_SESSION[course_id] OR course_id=0) AND forum_id=$forum_id";
+       $result = mysql_query($sql, $db);
+       $row = mysql_fetch_assoc($result);
+
+       if (empty($row)) {
+               // not a course forum, let's check group:
+               if (!empty($_SESSION['groups'])){
+                       $groups = implode(',', $_SESSION['groups']);
+                       $sql    = "SELECT forum_id FROM ".TABLE_PREFIX."forums_groups WHERE group_id IN ($groups) AND forum_id=$forum_id";
+                       $result = mysql_query($sql, $db);
+                       if ($row = mysql_fetch_assoc($result)) {
+                               return TRUE;
+                       }
+               }
+
+               return FALSE;
+       }
+
+       return TRUE;    
+}
+
+/**
+* Adds a forum
+* @access  public
+* @param   array $_POST                        add-forum form variables
+* @see     $db                                 in include/vitals.inc.php
+* @see     $addslashes                 in include/vitals.inc.php
+* @author  Heidi Hazelton
+*/
+function add_forum($_POST) {
+       global $db;
+       global $addslashes;
+
+       $_POST['title'] = $addslashes($_POST['title']);
+       $_POST['body']  = $addslashes($_POST['body']);
+       $_POST['edit']  = intval($_POST['edit']);
+
+       $sql    = "INSERT INTO ".TABLE_PREFIX."forums VALUES (NULL,'$_POST[title]', '$_POST[body]', 0, 0, NOW(), $_POST[edit])";
+       $result = mysql_query($sql,$db);
+
+       $sql    = "INSERT INTO ".TABLE_PREFIX."forums_courses VALUES (LAST_INSERT_ID(),  $_SESSION[course_id])";
+       $result = mysql_query($sql,$db);
+
+       return;
+}
+
+/**
+* Edits a forum
+* @access  public
+* @param   array $_POST                        add-forum form variables
+* @see     $db                                 in include/vitals.inc.php
+* @see     $addslashes                 in include/vitals.inc.php
+* @author  Heidi Hazelton
+*/
+function edit_forum($_POST) {
+       global $db;
+       global $addslashes;
+
+       $_POST['title']  = $addslashes($_POST['title']);
+       $_POST['body']   = $addslashes($_POST['body']);
+
+       $_POST['fid']    = intval($_POST['fid']);
+       $_POST['edit']    = intval($_POST['edit']);
+
+       $sql    = "UPDATE ".TABLE_PREFIX."forums SET title='$_POST[title]', description='$_POST[body]', last_post=last_post, mins_to_edit=$_POST[edit] WHERE forum_id=$_POST[fid]";
+       $result = mysql_query($sql,$db);
+
+       return;
+}
+
+/**
+* Deletes a forum (checks if its shared).
+* Assumes the forum is not shared.
+* Assumes the user has the priv to delete this forum.
+* @access  public
+* @param   array $_POST                        add-forum form variables
+* @see     $db                                 in include/vitals.inc.php
+* @see     $addslashes                 in include/vitals.inc.php
+* @author  Heidi Hazelton
+*/
+function delete_forum($forum_id) {
+       global $db;
+
+       $sql    = "SELECT post_id FROM ".TABLE_PREFIX."forums_threads WHERE forum_id=$forum_id";
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_array($result)) {
+               $sql     = "DELETE FROM ".TABLE_PREFIX."forums_accessed WHERE post_id=$row[post_id]";
+               $result2 = mysql_query($sql, $db);
+       }
+
+       $sql    = "DELETE FROM ".TABLE_PREFIX."forums_subscriptions WHERE forum_id=$forum_id";
+       $result = mysql_query($sql, $db);
+
+       $sql    = "DELETE FROM ".TABLE_PREFIX."forums_threads WHERE forum_id=$forum_id";
+       $result = mysql_query($sql, $db);
+
+       $sql = "DELETE FROM ".TABLE_PREFIX."forums_courses WHERE forum_id=$forum_id";
+       $result = mysql_query($sql, $db);
+
+       $sql    = "DELETE FROM ".TABLE_PREFIX."forums WHERE forum_id=$forum_id";
+       $result = mysql_query($sql, $db);
+       
+       $sql = "OPTIMIZE TABLE ".TABLE_PREFIX."forums_threads";
+       $result = mysql_query($sql, $db);
+
+}
+
+function print_entry($row) {
+       global $page,$system_courses, $forum_info;
+       static $counter;
+       $counter++;
+
+       $reply_link = '<a href="forum/view.php?fid='.$row['forum_id'].SEP.'pid=';
+       if ($row['parent_id'] == 0) {
+               $reply_link .= $row['post_id'];
+       } else {
+               $reply_link .= $row['parent_id'];
+       }
+       $reply_link .= SEP.'reply='.$row['post_id'].SEP.'page='.$page.'#post" >'._AT('reply').'</a>';
+
+?>
+
+       <li class="<?php if ($counter %2) { echo 'odd'; } else { echo 'even'; } ?>">
+               <a name="<?php echo $row['post_id']; ?>"></a>
+               <div class="forum-post-author">
+                       <a href="profile.php?id=<?php echo $row['member_id']; ?>" class="title"><?php echo htmlspecialchars(get_display_name($row['member_id'])); ?></a><br />
+                       <?php print_profile_img($row['member_id']); ?>
+               </div>
+
+               <div class="forum-post-content">
+                       <h3><?php echo AT_Print(htmlspecialchars($row['subject'], ENT_COMPAT, "UTF-8"), 'forums_threads.subject'); ?></h3>
+                       <div>
+                               <div class="forum-post-ctrl">
+                                       <?php if (authenticate(AT_PRIV_FORUMS, AT_PRIV_RETURN)): ?>
+                                               <?php echo $reply_link; ?> | <a href="editor/edit_post.php?fid=<?php echo $row['forum_id'].SEP.'pid='.$row['post_id']; ?>"><?php echo _AT('edit'); ?></a> | <a href="forum/delete_thread.php?fid=<?php echo $row['forum_id'].SEP.'pid='.$row['post_id'].SEP.'ppid='.$row['parent_id'].SEP; ?>nest=1"><?php echo _AT('delete'); ?></a>
+                                       <?php elseif (($row['member_id'] == $_SESSION['member_id']) && (($row['udate'] + $forum_info['mins_to_edit'] * 60) > time())): ?>
+                                               <?php echo $reply_link; ?> | <a href="editor/edit_post.php?fid=<?php echo $row['forum_id'].SEP.'pid='.$row['post_id']; ?>"><?php echo _AT('edit'); ?></a> <span>(<?php echo _AT('edit_for_minutes', round((($row['udate'] + $forum_info['mins_to_edit'] * 60) - time())/60)); ?>)</span>
+                                       <?php elseif ($_SESSION['valid_user']): ?>
+                                               <?php echo $reply_link; ?>
+                                       <?php endif; ?>
+                               </div>
+                               <p class="date">&nbsp;&nbsp;<?php echo AT_date(_AT('forum_date_format'), $row['date'], AT_DATE_MYSQL_DATETIME); ?></p>
+
+                       </div>
+
+                       <div class="body">
+                               <p><?php echo AT_print(htmlspecialchars($row['body'], ENT_COMPAT, "UTF-8"), 'forums_threads.body'); ?></p>
+                       </div>
+               </div>
+       </li>
+<?php
+}
+?>
\ No newline at end of file
diff --git a/include/lib/html_resource_parser.inc.php b/include/lib/html_resource_parser.inc.php
new file mode 100644 (file)
index 0000000..4a7cda6
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+
+function get_html_resources($text) {
+       $resources = array();
+
+       $handler =& new XML_HTMLSax_Handler();
+
+       $parser =& new XML_HTMLSax();
+       $parser->set_object($handler);
+       $parser->set_element_handler('openHandler','closeHandler');
+
+       $parser->parse($text);
+
+       foreach ($handler->resources as $resource) {
+               $url_parts = @parse_url($resource);
+
+               if (isset($url_parts['scheme'])) {
+                       // we don't want full urls
+                       continue;
+               }
+
+               if ((substr($resource, 0, 1) == '/')) {
+                       // we don't want absolute urls
+                       continue;
+               }
+
+               // make sure this resource exists in this course's content directory:
+               $resource_server_path = realpath(AT_CONTENT_DIR . $_SESSION['course_id']. '/' . $resource);
+               if (file_exists($resource_server_path) && is_file($resource_server_path)) {
+                       $resources[$resource] = $resource_server_path;
+               }
+       }
+
+       return $resources;
+}
+
+/*
+       the following resources are to be identified:
+       even if some of these can't be images, they can still be files in the content dir.
+       theoretically the only urls we wouldn't deal with would be for a <!DOCTYPE and <form>
+
+       img             => src
+       a               => href                         // ignore if href doesn't exist (ie. <a name>)
+       object  => data | classid       // probably only want data
+       applet  => classid | archive                    // whatever these two are should double check to see if it's a valid file (not a dir)
+       link    => href
+       script  => src
+       form    => action
+       input   => src
+       iframe  => src
+*/
+class XML_HTMLSax_Handler {
+       var $elements = array(  'img'    => 'src',
+                                                       'a'              => 'href',                             
+                                                       'object' =>  array('data',    'classid'),
+                                                       'applet' =>  array('classid', 'archive'),
+                                                       'link'   => 'href',
+                                                       'script' => 'src',
+                                                       'form'   => 'action',
+                                                       'input'  => 'src',
+                                                       'iframe' => 'src',
+                                                       'embed'  => 'src',
+                                                       'param'  => 'value');
+       var $resources = array();
+
+    function XML_HTMLSax_Handler() { 
+               $this->resources = array();
+       }
+
+    function openHandler(& $parser,$name,$attrs) {
+               $name = strtolower($name);
+               $attrs = array_change_key_case($attrs, CASE_LOWER);
+
+               /* check if this attribute specifies the files in different ways: (ie. java) */
+               if (is_array($this->elements[$name])) {
+                       $items = $this->elements[$name];
+
+                       foreach ($items as $item) {
+                               if ($attrs[$item] != '') {
+                                       /* some attributes allow a listing of files to include seperated by commas (ie. applet->archive). */
+                                       if (strpos($attrs[$item], ',') !== false) {
+                                               $files = explode(',', $attrs[$item]);
+                                               foreach ($files as $file) {
+                                                       $this->resources[] = trim($file);
+                                               }
+                                       } else {
+                                               $this->resources[] = $attrs[$item];
+                                       }
+                               }
+                       }
+               } else if (isset($this->elements[$name]) && ($attrs[$this->elements[$name]] != '')) {
+                       /* we know exactly which attribute contains the reference to the file. */
+                       $this->resources[] = $attrs[$this->elements[$name]];
+               }
+    }
+    function closeHandler(& $parser,$name) { }
+}
+?>
\ No newline at end of file
diff --git a/include/lib/likert_presets.inc.php b/include/lib/likert_presets.inc.php
new file mode 100644 (file)
index 0000000..161de17
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+
+$_likert_preset = array();
+
+$_likert_preset[] = array(_AT('lk_always'),_AT('lk_very_frequently'),_AT('lk_occasionally'),_AT('lk_rarely'),_AT('lk_very_rarely'),_AT('lk_never'));
+
+$_likert_preset[] = array(_AT('lk_excellent'),_AT('lk_very_good'),_AT('lk_good'),_AT('lk_fair'),_AT('lk_poor'),_AT('lk_very_poor'));
+
+$_likert_preset[] = array(_AT('lk_strongly_agree'),_AT('lk_agree'),_AT('lk_undecided'),_AT('lk_disagree'),_AT('lk_strongly_disagree'));
+
+$_likert_preset[] = array(_AT('lk_very_important'),_AT('lk_important'),_AT('lk_mod_important'),_AT('lk_little_importance'),_AT('lk_unimportant'));
+
+
+?>
\ No newline at end of file
diff --git a/include/lib/links.inc.php b/include/lib/links.inc.php
new file mode 100644 (file)
index 0000000..85bd361
--- /dev/null
@@ -0,0 +1,229 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+\r
+\r
+/**\r
+ * given an owner_type and owner_id\r
+ * returns false if user cannot manage link of owner_type\r
+ * returns true if they can\r
+ */\r
+function links_authenticate($owner_type, $owner_id) {\r
+       global $db;\r
+\r
+       if (empty($owner_type) || empty($owner_id)) {\r
+               return false;\r
+       }\r
+\r
+       //if admin or TA w/ right privs, can manage all links\r
+       //if ($_SESSION['is_admin'] || $_SESSION['privileges'] > 0) {\r
+       if (authenticate(AT_PRIV_GROUPS+AT_PRIV_LINKS, true)) {\r
+               return true;\r
+       }\r
+\r
+       if ($owner_type == LINK_CAT_GROUP) {\r
+               //check if member of group\r
+               if ($_SESSION['valid_user'] && isset($_SESSION['groups'])) {                    \r
+                       $sql="SELECT * FROM ".TABLE_PREFIX."groups_members WHERE group_id=".$owner_id." AND member_id=".$_SESSION['member_id'];\r
+                       $result = mysql_query($sql, $db);\r
+                       if ($row = mysql_fetch_assoc($result)) {\r
+                               return true;\r
+                       }\r
+               } \r
+       } \r
+\r
+       return false;\r
+}\r
+\r
+/* return true if user is able to manage group or course links */\r
+function manage_links() {\r
+       global $db;\r
+\r
+       if (authenticate(AT_PRIV_GROUPS, true) && authenticate(AT_PRIV_LINKS, true)) { //course and group links\r
+               return LINK_CAT_AUTH_ALL;\r
+       } else if (authenticate(AT_PRIV_GROUPS, true)) { //all group links\r
+               return LINK_CAT_AUTH_GROUP;\r
+       } else if (authenticate(AT_PRIV_LINKS, true)) { //course links\r
+               return LINK_CAT_AUTH_COURSE;\r
+       } else if (!empty($_SESSION['groups'])) { //particular group links\r
+               //find a group that uses links\r
+               foreach ($_SESSION['groups'] as $group_id) {\r
+                       $sql = "SELECT modules FROM ".TABLE_PREFIX."groups WHERE group_id=$group_id";\r
+                       $result = mysql_query($sql, $db);\r
+\r
+                       $row = mysql_fetch_assoc($result);\r
+                       $mods = explode('|', $row['modules']);\r
+\r
+                       if (in_array("_standard/links", $mods)) {\r
+                               return LINK_CAT_AUTH_GROUP;\r
+                       }\r
+               }\r
+\r
+               return FALSE;\r
+       }\r
+\r
+       return LINK_CAT_AUTH_NONE;\r
+}\r
+\r
+\r
+//if manage, then it's getting categories for only those that should see them\r
+//if list, then filter out the uneditable group cats from the manage list (otherwise it's a dropdown of cats)\r
+function get_link_categories($manage=false, $list=false) {\r
+       global $db, $_base_path;\r
+       $categories = array();\r
+\r
+       /* get all the categories: */\r
+       /* $categories[category_id] = array(cat_name, cat_parent, num_courses, [array(children)]) */\r
+\r
+       if ($_SESSION['groups']) {\r
+               $groups = implode(',', $_SESSION['groups']);\r
+       } else {\r
+               // not in any groups\r
+               $groups = 0;\r
+       }\r
+\r
+       //if suggest a link page\r
+       if ($_SERVER['PHP_SELF'] == $_base_path.'links/add.php') {\r
+               $sql = "SELECT * FROM ".TABLE_PREFIX."links_categories WHERE (owner_id=$_SESSION[course_id] AND owner_type=".LINK_CAT_COURSE.") ORDER BY parent_id, name";\r
+       } else if ($manage) {\r
+               $sql = "SELECT * FROM ".TABLE_PREFIX."links_categories WHERE ";\r
+               if ( authenticate(AT_PRIV_GROUPS, true) && authenticate(AT_PRIV_COURSE, true) ) { \r
+                       if ($list) {\r
+                               $sql .= "(owner_id=$_SESSION[course_id] AND owner_type=".LINK_CAT_COURSE.") OR (owner_id IN ($groups) AND owner_type=".LINK_CAT_GROUP." AND name<>'')";\r
+                       } else {\r
+                               $sql .= "(owner_id=$_SESSION[course_id] AND owner_type=".LINK_CAT_COURSE.") OR (owner_id IN ($groups) AND owner_type=".LINK_CAT_GROUP.")";\r
+                       }\r
+\r
+               } else if ( authenticate(AT_PRIV_LINKS, true) ) {\r
+                       $sql .= "(owner_id=$_SESSION[course_id] AND owner_type=".LINK_CAT_COURSE.")";\r
+                       if (!empty($groups)) {\r
+                               $sql .= " OR (owner_id IN ($groups) AND owner_type=".LINK_CAT_GROUP.")";                        \r
+                       }\r
+               } else if ( authenticate(AT_PRIV_GROUPS, true) || !empty($groups) ) { \r
+                       if ($list) {\r
+                               $sql .= "(owner_id IN ($groups) AND owner_type=".LINK_CAT_GROUP." AND name<>'')";\r
+                       } else {\r
+                               $sql .= "(owner_id IN ($groups) AND owner_type=".LINK_CAT_GROUP.")";\r
+                       }\r
+               }       \r
+               $sql .= " ORDER BY parent_id, name";\r
+       } else {\r
+               if (!empty($groups)) {\r
+                       $sql = "SELECT * FROM ".TABLE_PREFIX."links_categories WHERE (owner_id=$_SESSION[course_id] AND owner_type=".LINK_CAT_COURSE.") OR (owner_id IN ($groups) AND owner_type=".LINK_CAT_GROUP.") ORDER BY parent_id, name";\r
+               } else {\r
+                       $sql = "SELECT * FROM ".TABLE_PREFIX."links_categories WHERE (owner_id=$_SESSION[course_id] AND owner_type=".LINK_CAT_COURSE.") ORDER BY parent_id, name";\r
+               }\r
+       }\r
+       $result = mysql_query($sql, $db);\r
+\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               //if group, get name\r
+               if (empty($row['name'])) {\r
+                       $row['name'] = get_group_name($row['owner_id']);\r
+                       $categories[$row['cat_id']]['group'] = 1;\r
+               }\r
+\r
+               $categories[$row['cat_id']]['cat_name']    = $row['name'];\r
+               $categories[$row['cat_id']]['cat_parent']  = $row['parent_id'];\r
+\r
+               if ($row['parent_id'] > 0) {\r
+                       $categories[$row['parent_id']]['children'][] = $row['cat_id'];\r
+               } else {\r
+                       $categories[0][] = $row['cat_id'];\r
+               }\r
+       }\r
+\r
+       return $categories;\r
+}\r
+\r
+function select_link_categories($categories, $cat_id, $current_cat_id, $exclude, $depth=0, $owner=FALSE) {\r
+       global $db; \r
+\r
+       if ($cat_id == 0 && is_array($categories[0])) {\r
+               foreach($categories[0] as $child_cat_id) {\r
+                       select_link_categories($categories, $child_cat_id, $current_cat_id, $depth, 0, $owner);\r
+               }\r
+       } else {\r
+               $sql = "SELECT name, owner_type, owner_id FROM ".TABLE_PREFIX."links_categories WHERE cat_id=$cat_id";\r
+               $result = mysql_query($sql, $db);\r
+               $row = mysql_fetch_assoc($result);\r
+\r
+               if ($exclude && ($cat_id == $current_cat_id)) {\r
+                       return;\r
+               }\r
+\r
+               if ($owner) {\r
+                       echo '<option value="'.$cat_id.'-'.$row['owner_type'].'-'.$row['owner_id'].'"';\r
+               } else  {\r
+                       echo '<option value="'.$cat_id.'"';\r
+               }\r
+       \r
+               if ($exclude && is_array($categories[$cat_id]['children']) && in_array($current_cat_id, $categories[$cat_id]['children'])) {\r
+                       echo ' selected="selected"';\r
+               } else if (!$exclude && ($cat_id == $current_cat_id)) {\r
+                       echo ' selected="selected"';\r
+               }\r
+               echo '>';\r
+               echo str_repeat("&nbsp;", $depth*4);\r
+               echo $categories[$cat_id]['cat_name'].'</option>';\r
+\r
+               if (is_array($categories[$cat_id]['children'])) {\r
+                       foreach($categories[$cat_id]['children'] as $child_cat_id) {\r
+                               select_link_categories($categories, $child_cat_id, $current_cat_id, $exclude, $depth+1, $owner);\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+/**\r
+ Given a $cat_id, return IDs of all children of that ID as a comma seperated \r
+ string.\r
+ */\r
+function get_child_categories ($cat_id, $categories) {\r
+    if (!isset ($categories)) {\r
+        $categories = get_link_categories();\r
+    }\r
+    \r
+    $category = $categories[$cat_id];\r
+    $children_string = "";\r
+    if (is_array($categories[$cat_id]['children'])){\r
+        foreach ($categories[$cat_id]['children'] as $child) {\r
+            $children_string = $child.",";\r
+        }\r
+    }\r
+    return $children_string;\r
+}\r
+\r
+function get_group_name($owner_id) {\r
+       global $db;\r
+\r
+       if (!$owner_id) {\r
+               return false;\r
+       }\r
+\r
+       $sql = "SELECT title FROM ".TABLE_PREFIX."groups WHERE group_id=".$owner_id;\r
+       $result = mysql_query($sql, $db);\r
+       $row = mysql_fetch_assoc($result);\r
+       return $row['title'];\r
+}\r
+\r
+function get_cat_info($cat_id) {\r
+       global $db;\r
+\r
+       $sql = "SELECT * FROM ".TABLE_PREFIX."links_categories WHERE cat_id=".$cat_id;\r
+       $result = mysql_query($sql, $db);\r
+       $row = mysql_fetch_assoc($result);\r
+\r
+       return $row;\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/include/lib/menu_pages.php b/include/lib/menu_pages.php
new file mode 100644 (file)
index 0000000..337d0fe
--- /dev/null
@@ -0,0 +1,409 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+/*
+       5 sections: public, my_start_page, course, admin, home
+*/
+if (isset($_pages[AT_NAV_ADMIN])) {
+       array_unshift($_pages[AT_NAV_ADMIN], 'admin/index.php', 'admin/modules/index.php');
+}
+
+$_pages[AT_NAV_PUBLIC] = array_merge(array('login.php', 'registration.php', 'browse.php'), (isset($_pages[AT_NAV_PUBLIC]) ? $_pages[AT_NAV_PUBLIC] : array()));
+$_pages[AT_NAV_START]  = array_merge(array('users/index.php',  'users/profile.php', 'users/preferences.php'), (array) $_pages[AT_NAV_START]);
+$_pages[AT_NAV_COURSE] = array('index.php');
+$_pages[AT_NAV_HOME]   = array();
+
+if (isset($_SESSION['course_id']) && $_SESSION['course_id'] > 0) {
+       $main_links = $home_links = $side_menu = array();
+
+       if ($system_courses[$_SESSION['course_id']]['main_links']) {
+               $main_links = explode('|', $system_courses[$_SESSION['course_id']]['main_links']);
+               foreach ($main_links as $link) {
+                       if (isset($_pages[$link])) {
+                               $_pages[$link]['parent'] = AT_NAV_COURSE;
+                       }
+               }
+               $_pages[AT_NAV_COURSE] = array_merge($_pages[AT_NAV_COURSE], $main_links);
+       }
+
+       if ($system_courses[$_SESSION['course_id']]['home_links']) {
+               $home_links = explode('|', $system_courses[$_SESSION['course_id']]['home_links']);
+               foreach ($home_links as $link) {
+                       if (isset($_pages[$link])) {
+                               $_pages[AT_NAV_HOME][] = $link;
+                       }
+               }
+       }
+
+       if (authenticate(AT_PRIV_ADMIN, AT_PRIV_RETURN)) {
+               $_pages[AT_NAV_COURSE][] = 'tools/index.php';           
+       } else if ($_SESSION['privileges']) {
+               
+               /**
+                * the loop and all this module priv checking is done to hide the Manage tab
+                * when this student has privileges, but no items linked from the Manage tab.
+                * Example: the File Storage privilege does not have a Manage tab item.
+                * In the best case it stops after the first found link.
+                * In the worst case it goes through all the modules and doesn't find a link.
+                */
+               $module_list = $moduleFactory->getModules(AT_MODULE_STATUS_ENABLED, 0, TRUE);
+               $keys = array_keys($module_list);
+
+               foreach ($keys as $module_name) {
+                       $module =& $module_list[$module_name];
+                       if ($module->getPrivilege() && authenticate($module->getPrivilege(), AT_PRIV_RETURN) && ($module->getChildPage('tools/index.php'))) {
+                               $_pages[AT_NAV_COURSE][] = 'tools/index.php';
+                               break;
+                       }
+               }
+       }
+} else if (isset($_SESSION['course_id']) && $_SESSION['course_id'] == -1) {
+       /* admin pages */
+
+       $_pages['admin/index.php']['title_var'] = 'home';
+       $_pages['admin/index.php']['parent']    = AT_NAV_ADMIN;
+       $_pages['admin/index.php']['guide']     = 'admin/?p=configuration.php';
+       $_pages['admin/index.php']['children'] = array_merge(array('admin/admins/my_edit.php', 'admin/admins/my_password.php'), isset($_pages['admin/index.php']['children']) ?  $_pages['admin/index.php']['children'] : array());
+
+       $_pages['admin/admins/my_edit.php']['title_var'] = 'my_account';
+       $_pages['admin/admins/my_edit.php']['parent']    = 'admin/index.php';
+       $_pages['admin/admins/my_edit.php']['guide']     = 'admin/?p=my_account.php';
+
+       $_pages['admin/admins/my_password.php']['title_var'] = 'change_password';
+       $_pages['admin/admins/my_password.php']['parent']    = 'admin/index.php';
+
+       if (admin_authenticate(AT_ADMIN_PRIV_USERS, AT_PRIV_RETURN)) {
+               $_pages[AT_NAV_ADMIN][] = 'admin/config_edit.php';
+
+               $_pages['admin/config_edit.php']['title_var'] = 'system_preferences';
+               $_pages['admin/config_edit.php']['parent']    = AT_NAV_ADMIN;
+               $_pages['admin/config_edit.php']['guide']     = 'admin/?p=system_preferences.php';
+               $_pages['admin/config_edit.php']['children']  = array_merge((array) $_pages['admin/config_edit.php']['children'], array('admin/error_logging.php'));
+       }
+       $_pages['admin/fix_content.php']['title_var'] = 'fix_content_ordering';
+       $_pages['admin/fix_content.php']['parent']    = 'admin/index.php';
+
+       $_pages['admin/error_logging.php']['title_var'] = 'error_logging';
+       $_pages['admin/error_logging.php']['parent']    = 'admin/config_edit.php';
+       $_pages['admin/error_logging.php']['guide']     = 'admin/?p=error_logging.php';
+       $_pages['admin/error_logging.php']['children']  = array_merge(array('admin/error_logging_bundle.php', 'admin/error_logging_reset.php'), isset($_pages['admin/error_logging.php']['children']) ? $_pages['admin/error_logging.php']['children'] : array());
+
+       $_pages['admin/error_logging_reset.php']['title_var'] = 'reset_log';
+       $_pages['admin/error_logging_reset.php']['parent']    = 'admin/error_logging.php';
+
+       $_pages['admin/error_logging_bundle.php']['title_var'] = 'report_errors';
+       $_pages['admin/error_logging_bundle.php']['parent']    = 'admin/error_logging.php';
+
+       $_pages['admin/error_logging_details.php']['title_var'] = 'viewing_profile_bugs';
+       $_pages['admin/error_logging_details.php']['parent']    = 'admin/error_logging.php';
+
+       $_pages['admin/error_logging_view.php']['title_var'] = 'viewing_errors';
+       $_pages['admin/error_logging_view.php']['parent']    = 'admin/error_logging_details.php';
+
+       if (admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {
+               // hide modules from non-super admins
+               $_pages['admin/modules/index.php']['title_var'] = 'modules';
+               $_pages['admin/modules/index.php']['parent']    = AT_NAV_ADMIN;
+               $_pages['admin/modules/index.php']['guide']     = 'admin/?p=modules.php';
+               $_pages['admin/modules/index.php']['children']  = array('admin/modules/add_new.php');
+
+               $_pages['admin/modules/details.php']['title_var'] = 'details';
+               $_pages['admin/modules/details.php']['parent']    = 'admin/modules/index.php';
+
+               $_pages['admin/modules/add_new.php']['title_var'] = 'install_modules';
+               $_pages['admin/modules/add_new.php']['parent']    = 'admin/modules/index.php';
+
+                       $_pages['admin/modules/confirm.php']['title_var'] = 'confirm';
+                       $_pages['admin/modules/confirm.php']['parent']    = 'admin/modules/add_new.php';
+
+               //$_pages['admin/modules/create.php']['title_var'] = 'create_module';
+               //$_pages['admin/modules/create.php']['parent']    = 'admin/modules/index.php';
+
+               $_pages['admin/cron_config.php']['title_var'] = 'cron_config';
+               $_pages['admin/cron_config.php']['parent']    = 'admin/config_edit.php';
+               $_pages['admin/cron_config.php']['guide']     = 'admin/?p=cron_setup.php';
+               $_pages['admin/config_edit.php']['children']  = array_merge((array) $_pages['admin/config_edit.php']['children'], array('admin/cron_config.php'));
+
+               $_pages['admin/auto_enroll.php']['title_var'] = 'auto_enroll';
+               $_pages['admin/auto_enroll.php']['parent']    = 'admin/config_edit.php';
+               $_pages['admin/auto_enroll.php']['guide']     = 'admin/?p=auto_enroll.php';
+               $_pages['admin/auto_enroll.php']['children']  = array_merge(array('admin/auto_enroll_edit.php'));
+               $_pages['admin/config_edit.php']['children']  = array_merge((array) $_pages['admin/config_edit.php']['children'], array('admin/auto_enroll.php'));
+
+               $_pages['admin/auto_enroll_edit.php']['title_var'] = 'auto_enroll_edit';
+               $_pages['admin/auto_enroll_edit.php']['parent']    = 'admin/auto_enroll.php';
+       
+               $_pages['admin/auto_enroll_delete.php']['title_var'] = 'auto_enroll_delete';
+               $_pages['admin/auto_enroll_delete.php']['parent']    = 'admin/auto_enroll.php';
+       
+       }
+}
+
+
+/* public pages */
+$_pages['registration.php']['title_var'] = 'register';
+$_pages['registration.php']['parent']    = AT_NAV_PUBLIC;
+$_pages['registration.php']['children']  = isset($_pages['browse.php']['children']) ? $_pages['browse.php']['children'] : array();
+$_pages['registration.php']['guide']     = 'general/?p=register.php';
+
+$_pages['browse.php']['title_var'] = 'browse_courses';
+$_pages['browse.php']['parent']    = AT_NAV_PUBLIC;
+$_pages['browse.php']['children']  = isset($_pages['browse.php']['children']) ? $_pages['browse.php']['children'] : array();
+$_pages['browse.php']['guide']     = 'general/?p=browse_courses.php';
+
+$_pages['login.php']['title_var'] = 'login';
+$_pages['login.php']['parent']    = AT_NAV_PUBLIC;
+$_pages['login.php']['children']  = array_merge(array('password_reminder.php'), isset($_pages['login.php']['children']) ? $_pages['login.php']['children'] : array());
+$_pages['login.php']['guide']     = 'general/?p=login.php';
+
+$_pages['confirm.php']['title_var'] = 'confirm';
+$_pages['confirm.php']['parent']    = AT_NAV_PUBLIC;
+
+$_pages['password_reminder.php']['title_var'] = 'password_reminder';
+$_pages['password_reminder.php']['parent']    = 'login.php';
+$_pages['password_reminder.php']['guide']     = 'general/?p=password_reminder.php';
+
+$_pages['logout.php']['title_var'] = 'logout';
+$_pages['logout.php']['parent']    = AT_NAV_PUBLIC;
+
+/* my start page pages */
+$_pages['users/index.php']['title_var'] = 'my_courses';
+$_pages['users/index.php']['parent']    = AT_NAV_START;
+$_pages['users/index.php']['guide']     = 'general/?p=my_courses.php';
+if (isset($_SESSION['member_id']) && $_SESSION['member_id'] && (!isset($_SESSION['course_id']) || !$_SESSION['course_id'])) {
+       if ((get_instructor_status() === FALSE) && (!defined('ALLOW_INSTRUCTOR_REQUESTS') || !ALLOW_INSTRUCTOR_REQUESTS)) {
+               $_pages['users/index.php']['children']  = array_merge(array('users/browse.php'), (array) $_pages['users/index.php']['children']);
+       } else {
+               $_pages['users/index.php']['children']  = array_merge(array('users/browse.php', 'users/create_course.php'), isset($_pages['users/index.php']['children']) ? $_pages['users/index.php']['children'] : array());
+       }
+}
+       
+       $_pages['users/browse.php']['title_var'] = 'browse_courses';
+       $_pages['users/browse.php']['parent']    = 'users/index.php';
+       $_pages['users/browse.php']['guide']     = 'general/?p=browse_courses.php';
+       
+       $_pages['users/create_course.php']['title_var'] = 'create_course';
+       $_pages['users/create_course.php']['parent']    = 'users/index.php';
+       $_pages['users/create_course.php']['guide']    = 'instructor/?p=creating_courses.php';
+
+       $_pages['users/private_enroll.php']['title_var'] = 'enroll';
+       $_pages['users/private_enroll.php']['parent']    = 'users/index.php';
+
+       $_pages['users/remove_course.php']['title_var'] = 'unenroll';
+       $_pages['users/remove_course.php']['parent']    = 'users/index.php';
+
+$_pages['users/profile.php']['title_var']    = 'profile';
+$_pages['users/profile.php']['parent']   = AT_NAV_START;
+$_pages['users/profile.php']['guide']     = 'general/?p=profile.php';
+$_pages['users/profile.php']['children']  = array_merge(array('users/password_change.php', 'users/email_change.php'), (array) $_pages['users/profile.php']['children']);
+
+       $_pages['users/password_change.php']['title_var'] = 'change_password';
+       $_pages['users/password_change.php']['parent']    = 'users/profile.php';
+       //$_pages['users/password_change.php']['guide']    = 'instructor/?p=creating_courses.php';
+
+       $_pages['users/email_change.php']['title_var'] = 'change_email';
+       $_pages['users/email_change.php']['parent']    = 'users/profile.php';
+
+$_pages['users/preferences.php']['title_var']  = 'preferences';
+$_pages['users/preferences.php']['parent'] = AT_NAV_START;
+$_pages['users/preferences.php']['guide']  = 'general/?p=preferences.php';
+
+
+/* course pages */
+$_pages['index.php']['title_var']  = 'home';
+$_pages['index.php']['parent'] = AT_NAV_COURSE;
+
+$_pages['enroll.php']['title_var']  = 'enroll';
+$_pages['enroll.php']['parent'] = AT_NAV_COURSE;
+
+/* instructor pages: */
+$_pages['tools/index.php']['title_var'] = 'manage';
+$_pages['tools/index.php']['parent']    = AT_NAV_COURSE;
+
+$_pages['inbox/index.php']['title_var'] = 'inbox';
+$_pages['inbox/index.php']['children']  = array_merge(array('inbox/sent_messages.php', 'inbox/send_message.php', 'inbox/export.php'), isset($_pages['inbox/index.php']['children']) ? $_pages['inbox/index.php']['children'] : array());
+
+       $_pages['inbox/sent_messages.php']['title_var'] = 'sent_messages';
+       $_pages['inbox/sent_messages.php']['parent']    = 'inbox/index.php';
+
+       $_pages['inbox/send_message.php']['title_var'] = 'send_message';
+       $_pages['inbox/send_message.php']['parent']    = 'inbox/index.php';
+
+       $_pages['inbox/export.php']['title_var'] = 'export';
+       $_pages['inbox/export.php']['parent']    = 'inbox/index.php';
+
+$_pages['profile.php']['title_var'] = 'profile';
+$_pages['profile.php']['parent']    = 'index.php';
+
+
+/* global pages */
+$_pages['about.php']['title_var']  = 'about_atutor';
+
+$_pages['404.php']['title_var']  = '404';
+
+$_pages['help/index.php']['title_var']  = 'help';
+$_pages['help/index.php']['children'] = array_merge(array('help/accessibility.php', 'help/contact_support.php'), isset($_pages['help/index.php']['children']) ? $_pages['help/index.php']['children'] : array());
+
+       $_pages['help/accessibility.php']['title_var']  = 'accessibility';
+       $_pages['help/accessibility.php']['parent'] = 'help/index.php';
+
+       $_pages['help/contact_support.php']['title_var']  = 'contact_support';
+       $_pages['help/contact_support.php']['parent'] = 'help/index.php';
+
+
+$_pages['contact_instructor.php']['title_var']  = 'contact_instructor';
+
+$current_page = substr($_SERVER['PHP_SELF'], strlen($_base_path));
+
+function get_num_new_messages() {
+       global $db;
+       static $num_messages;
+
+       if (isset($num_messages)) {
+               return $num_messages;
+       }
+       $sql    = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."messages WHERE to_member_id=$_SESSION[member_id] AND new=1";
+       $result = mysql_query($sql, $db);
+       $row    = mysql_fetch_assoc($result);
+       $num_messages = $row['cnt'];
+
+       return $num_messages;
+}
+
+function get_main_navigation($current_page) {
+       global $_pages, $_base_path;
+
+       $parent_page = $_pages[$current_page]['parent'];
+       $_top_level_pages = array();
+
+       if (isset($parent_page) && defined($parent_page)) {
+               foreach($_pages[$parent_page] as $page) {
+                       if (isset($_pages[$page])) {
+                               if (isset($_pages[$page]['title'])) {
+                                       $_page_title = $_pages[$page]['title'];
+                               } else {
+                                       $_page_title = _AT($_pages[$page]['title_var']);
+                               }
+                               
+                               $_top_level_pages[] = array('url' => $_base_path . url_rewrite($page), 'title' => $_page_title);
+                       }
+               }
+       } else if (isset($parent_page)) {
+               return get_main_navigation($parent_page);
+       }
+
+       return $_top_level_pages;
+}
+
+function get_current_main_page($current_page) {
+       global $_pages, $_base_path;
+
+       $parent_page = $_pages[$current_page]['parent'];
+
+       if (isset($parent_page) && defined($parent_page)) {
+               return $_base_path . url_rewrite($current_page);
+       } else if (isset($parent_page)) {
+               return get_current_main_page($parent_page);
+       }
+}
+
+function get_sub_navigation($current_page) {
+       global $_pages, $_base_path;
+
+       if (isset($current_page) && defined($current_page)) {
+               // reached the top
+               return array();
+       } else if (isset($_pages[$current_page]['children'])) {
+               if (isset($_pages[$current_page]['title'])) {
+                       $_page_title = $_pages[$current_page]['title'];
+               } else {
+                       $_page_title = _AT($_pages[$current_page]['title_var']);
+               }
+
+               $_sub_level_pages[] = array('url' => $_base_path . $current_page, 'title' => $_page_title);
+               foreach ($_pages[$current_page]['children'] as $child) {
+
+                       if (isset($_pages[$child]['title'])) {
+                               $_page_title = $_pages[$child]['title'];
+                       } else {
+                               $_page_title = _AT($_pages[$child]['title_var']);
+                       }
+
+                       $_sub_level_pages[] = array('url' => $_base_path . $child, 'title' => $_page_title, 'has_children' => isset($_pages[$child]['children']));
+               }
+       } else if (isset($_pages[$current_page]['parent'])) {
+               // no children
+
+               $parent_page = $_pages[$current_page]['parent'];
+               return get_sub_navigation($parent_page);
+       }
+
+       return $_sub_level_pages;
+}
+
+function get_current_sub_navigation_page($current_page) {
+       global $_pages, $_base_path;
+
+       $parent_page = $_pages[$current_page]['parent'];
+
+       if (isset($parent_page) && defined($parent_page)) {
+               return $_base_path . $current_page;
+       } else {
+               return $_base_path . $current_page;
+       }
+}
+
+function get_path($current_page) {
+       global $_pages, $_base_path;
+
+       $parent_page = $_pages[$current_page]['parent'];
+
+       if (isset($_pages[$current_page]['title'])) {
+               $_page_title = $_pages[$current_page]['title'];
+       } else {
+               $_page_title = _AT($_pages[$current_page]['title_var']);
+       }
+
+       if (isset($parent_page) && defined($parent_page)) {
+               $path[] = array('url' => $_base_path . url_rewrite($current_page), 'title' => $_page_title);
+               return $path;
+       } else if (isset($parent_page)) {
+               $path[] = array('url' => $_base_path . url_rewrite($current_page), 'title' => $_page_title);
+               $path = array_merge((array) $path, get_path($parent_page));
+       } else {
+               $path[] = array('url' => $_base_path . url_rewrite($current_page), 'title' => $_page_title);
+       }
+       
+       return $path;
+}
+
+function get_home_navigation() {
+       global $_pages, $_base_path;
+
+       $home_links = array();
+       foreach ($_pages[AT_NAV_HOME] as $child) {
+               if (isset($_pages[$child])) {
+                       if (isset($_pages[$child]['title'])) {
+                               $title = $_pages[$child]['title'];
+                       } else {
+                               $title = _AT($_pages[$child]['title_var']);
+                       }
+                       $home_links[] = array('url' => $_base_path . url_rewrite($child), 'title' => $title, 'img' => $_base_path.$_pages[$child]['img']);
+               }
+       }
+
+       return $home_links;
+}
+?>
\ No newline at end of file
diff --git a/include/lib/mime.inc.php b/include/lib/mime.inc.php
new file mode 100644 (file)
index 0000000..67a9d86
--- /dev/null
@@ -0,0 +1,171 @@
+<?php\r
+$mime = array();\r
+$mime['ez']    = array('application/andrew-inset',   '');\r
+$mime['hqx']   = array('application/mac-binhex40',   '');\r
+$mime['cpt']   = array('application/mac-compactpro', '');\r
+$mime['bin']   = array('application/octet-stream',   'binary');\r
+$mime['dms']   = array('application/octet-stream',   'binary');\r
+$mime['lha']   = array('application/octet-stream',   'binary');\r
+$mime['lzh']   = array('application/octet-stream',   'binary');\r
+$mime['exe']   = array('application/octet-stream',   'binary');\r
+$mime['com']   = array('application/octet-stream',   'binary');\r
+$mime['class'] = array('application/octet-stream',   '');\r
+$mime['oda']   = array('application/oda',   '');\r
+$mime['pdf']   = array('application/pdf',   'pdf');\r
+$mime['ai']    = array('application/postscript',   '');\r
+$mime['eps']   = array('application/postscript',   '');\r
+$mime['ps']    = array('application/postscript',   'ps');\r
+$mime['rtf']   = array('application/rtf',   'rtf');\r
+$mime['smi']   = array('application/smil',   '');\r
+$mime['smil']  = array('application/smil',   '');\r
+$mime['mif']   = array('application/vnd.mif',   '');\r
+$mime['slc']   = array('application/vnd.wap.slc',   '');\r
+$mime['sic']   = array('application/vnd.wap.sic',   '');\r
+$mime['wmlc']  = array('application/vnd.wap.wmlc',   '');\r
+$mime['wmlsc'] = array('application/vnd.wap.wmlscriptc',   '');\r
+$mime['bcpio'] = array('application/x-bcpio',   '');\r
+$mime['bz2']   = array('application/x-bzip2',   '');\r
+$mime['vcd']   = array('application/x-cdlink',   '');\r
+$mime['pgn']   = array('application/x-chess-pgn',   '');\r
+$mime['cpio']  = array('application/x-cpio',   '');\r
+$mime['csh']   = array('application/x-csh',   '');\r
+$mime['dcr']   = array('application/x-director',   '');\r
+$mime['dir']   = array('application/x-director',   '');\r
+$mime['dxr']   = array('application/x-director',   '');\r
+$mime['dvi']   = array('application/x-dvi',   'dvi');\r
+$mime['spl']   = array('application/x-futuresplash',   '');\r
+$mime['gtar']  = array('application/x-gtar',   '');\r
+$mime['gz']    = array('application/x-gzip',   'zip');\r
+$mime['tgz']   = array('application/x-gzip',   'zip');\r
+$mime['hdf']   = array('application/x-hdf',   '');\r
+$mime['js']    = array('application/x-javascript',   '');\r
+$mime['kwd']   = array('application/x-kword',   '');\r
+$mime['kwt']   = array('application/x-kword',   '');\r
+$mime['ksp']   = array('application/x-kspread',   '');\r
+$mime['kpr']   = array('application/x-kpresenter',   '');\r
+$mime['kpt']   = array('application/x-kpresenter',   '');\r
+$mime['chrt']  = array('application/x-kchart',   '');\r
+$mime['kil']   = array('application/x-killustrator',   '');\r
+$mime['skp']   = array('application/x-koan',   '');\r
+$mime['skd']   = array('application/x-koan',   '');\r
+$mime['skt']   = array('application/x-koan',   '');\r
+$mime['skm']   = array('application/x-koan',   '');\r
+$mime['latex'] = array('application/x-latex',   '');\r
+$mime['nc']    = array('application/x-netcdf',   '');\r
+$mime['cdf']   = array('application/x-netcdf',   '');\r
+$mime['rpm']   = array('application/x-rpm',   '');\r
+$mime['sh']    = array('application/x-sh',   '');\r
+$mime['shar']  = array('application/x-shar',   '');\r
+$mime['swf']   = array('application/x-shockwave-flash',   'swf');\r
+$mime['sit']   = array('application/x-stuffit',   '');\r
+$mime['sv4cpio'] = array('application/x-sv4cpio',   '');\r
+$mime['sv4crc']  = array('application/x-sv4crc',   '');\r
+$mime['tar']   = array('application/x-tar',   '');\r
+$mime['tcl']   = array('application/x-tcl',   '');\r
+$mime['tex']   = array('application/x-tex',   '');\r
+$mime['texinfo'] = array('application/x-texinfo',   '');\r
+$mime['texi']  = array('application/x-texinfo',   '');\r
+$mime['t']     = array('application/x-troff',   '');\r
+$mime['tr']    = array('application/x-troff',   '');\r
+$mime['roff']  = array('application/x-troff',   '');\r
+$mime['man']   = array('application/x-troff-man',   '');\r
+$mime['me']    = array('application/x-troff-me',   '');\r
+$mime['ms']    = array('application/x-troff-ms',   '');\r
+$mime['ustar'] = array('application/x-ustar',   '');\r
+$mime['src']   = array('application/x-wais-source',   'src');\r
+$mime['zip']   = array('application/zip',   'zip');\r
+\r
+$mime['ogg']   = array('audio/x-ogg',  'audio');\r
+$mime['au']    = array('audio/basic',  'audio');\r
+$mime['snd']   = array('audio/basic',  'audio');\r
+$mime['mid']   = array('audio/midi',   'audio');\r
+$mime['midi']  = array('audio/midi',   'audio');\r
+$mime['kar']   = array('audio/midi',   'audio');\r
+$mime['mpga']  = array('audio/mpeg',   'audio');\r
+$mime['mp2']   = array('audio/mpeg',   'audio');\r
+$mime['mp3']   = array('audio/mpeg',   'audio');\r
+$mime['aif']   = array('audio/x-aiff',   'audio');\r
+$mime['aiff']  = array('audio/x-aiff',   'audio');\r
+$mime['aifc']  = array('audio/x-aiff',   'audio');\r
+$mime['ram']   = array('audio/x-pn-realaudio',   'audio');\r
+$mime['rm']    = array('audio/x-pn-realaudio',   'audio');\r
+$mime['ra']    = array('audio/x-realaudio',   'audio');\r
+$mime['wav']   = array('audio/x-wav',   'audio');\r
+\r
+$mime['pdb']   = array('chemical/x-pdb',   '');\r
+$mime['xyz']   = array('chemical/x-pdb',   '');\r
+\r
+$mime['gif']   = array('image/gif',   'image');\r
+$mime['ief']   = array('image/ief',   'image');\r
+$mime['jpeg']  = array('image/jpeg',   'image');\r
+$mime['jpg']   = array('image/jpeg',   'image');\r
+$mime['jpe']   = array('image/jpeg',   'image');\r
+$mime['png']   = array('image/png',   'image');\r
+$mime['tiff']  = array('image/tiff',   'image');\r
+$mime['tif']   = array('image/tiff',   'image');\r
+$mime['wbmp']  = array('image/vnd.wap.wbmp',   'image');\r
+$mime['bmp']   = array('image/ms-bmp', 'image');\r
+$mime['ras']   = array('image/x-cmu-raster',   'image');\r
+$mime['pnm']   = array('image/x-portable-anymap',   'image');\r
+$mime['pbm']   = array('image/x-portable-bitmap',   'image');\r
+$mime['pgm']   = array('image/x-portable-graymap',   'image');\r
+$mime['ppm']   = array('image/x-portable-pixmap',   'image');\r
+$mime['rgb']   = array('image/x-rgb',   'image');\r
+$mime['xbm']   = array('image/x-xbitmap',   'image');\r
+$mime['xpm']   = array('image/x-xpixmap',   'image');\r
+$mime['xwd']   = array('image/x-xwindowdump',   'image');\r
+$mime['igs']   = array('model/iges',   '');\r
+$mime['iges']  = array('model/iges',   '');\r
+$mime['msh']   = array('model/mesh',   '');\r
+$mime['mesh']  = array('model/mesh',   '');\r
+$mime['silo']  = array('model/mesh',   '');\r
+$mime['wrl']   = array('model/vrml',   '');\r
+$mime['vrml']  = array('model/vrml',   '');\r
+$mime['css']   = array('text/css',   '');\r
+$mime['asc']   = array('text/plain',   '');\r
+$mime['txt']   = array('text/plain',   'txt');\r
+$mime['sql']   = array('text/plain',   'sql2');\r
+$mime['rtx']   = array('text/richtext',   '');\r
+$mime['sgml']  = array('text/sgml',   '');\r
+$mime['sgm']   = array('text/sgml',   '');\r
+$mime['tsv']   = array('text/tab-separated-values',   '');\r
+$mime['sl']    = array('text/vnd.wap.sl',   '');\r
+$mime['si']    = array('text/vnd.wap.si',   '');\r
+$mime['wml']   = array('text/vnd.wap.wml',   '');\r
+$mime['wmls']  = array('text/vnd.wap.wmlscript',   '');\r
+$mime['etx']   = array('text/x-setext',   '');\r
+$mime['xml']   = array('text/xml',   'xml');\r
+$mime['mpeg']  = array('video/mpeg',   'video');\r
+$mime['mpg']   = array('video/mpeg',   'video');\r
+$mime['mpe']   = array('video/mpeg',   'video');\r
+$mime['qt']    = array('video/quicktime',   'qt');\r
+$mime['mov']   = array('video/quicktime',   'qt');\r
+$mime['wmv']   = array('video/x-ms-wmv',   'video');\r
+$mime['avi']   = array('video/x-msvideo',   'video');\r
+$mime['movie'] = array('video/x-sgi-movie',  'video');\r
+$mime['ice']   = array('x-conference/x-cooltalk',   '');\r
+$mime['html']  = array('text/html',   '');\r
+$mime['htm']   = array('text/html',   '');\r
+$mime['log']   = array('text/plain',   '');\r
+$mime['csv']   = array('text/plain',   'xls');\r
+\r
+// microsoft office\r
+$mime['xls']   = array('application/msexcel',   'xls');\r
+$mime['doc']   = array('application/msword',    'doc');\r
+$mime['mdb']   = array('application/msaccess',  'mdb');\r
+$mime['vsd']   = array('application/visio',     'vsd');\r
+$mime['mpp']   = array('application/msproject', 'mpp');\r
+$mime['ppt']   = array('application/vnd.ms-powerpoint',   'ppt');\r
+\r
+// open office\r
+$mime['oot']   = array('application/x-vnd.oasis.openoffice.text',   'oot');\r
+$mime['ott']   = array('application/x-vnd.oasis.openoffice.text',   'oot');\r
+$mime['oos']   = array('application/x-vnd.oasis.openoffice.spreadsheet',   'oos');\r
+$mime['ots']   = array('application/x-vnd.oasis.openoffice.spreadsheet',   'oos');\r
+$mime['ood']   = array('application/x-vnd.oasis.openoffice.drawing',   'ood');\r
+$mime['otd']   = array('application/x-vnd.oasis.openoffice.drawing',   'ood');\r
+$mime['oop']   = array('application/x-vnd.oasis.openoffice.presentation',   'oop');\r
+$mime['otp']   = array('application/x-vnd.oasis.openoffice.presentation',   'oop');\r
+\r
+$mime['psd']   = array('image/x-photoshop', 'psd');\r
+?>
\ No newline at end of file
diff --git a/include/lib/mysql_connect.inc.php b/include/lib/mysql_connect.inc.php
new file mode 100644 (file)
index 0000000..1fb7050
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+
+if (AT_INCLUDE_PATH !== 'NULL') {
+       $db = @mysql_connect(DB_HOST . ':' . DB_PORT, DB_USER, DB_PASSWORD);
+       if (!$db) {
+               /* AT_ERROR_NO_DB_CONNECT */
+               require_once(AT_INCLUDE_PATH . 'classes/ErrorHandler/ErrorHandler.class.php');
+               $err =& new ErrorHandler();
+               trigger_error('VITAL#Unable to connect to db.', E_USER_ERROR);
+               exit;
+       }
+       if (!@mysql_select_db(DB_NAME, $db)) {
+               require_once(AT_INCLUDE_PATH . 'classes/ErrorHandler/ErrorHandler.class.php');
+               $err =& new ErrorHandler();
+               trigger_error('VITAL#DB connection established, but database "'.DB_NAME.'" cannot be selected.',
+                                               E_USER_ERROR);
+               exit;
+       }
+}
+?>
\ No newline at end of file
diff --git a/include/lib/output.inc.php b/include/lib/output.inc.php
new file mode 100644 (file)
index 0000000..986bb06
--- /dev/null
@@ -0,0 +1,954 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+/**********************************************************************************/
+/* Output functions found in this file, in order:
+/*
+/*     - AT_date(format, timestamp, format_type)
+/*
+/*     - _AT([...])
+/*     - AT_print(input, name, Boolean runtime_html)
+/*
+/*     - smile_replace(text)
+/*     - myCodes(text)
+/*     - make_clickable(text)
+/*     - image_replace(text)
+/*     - format_final_output(text, Boolean nl2br)
+/*     - highlight (input, var)
+/*     - format_content(input, Boolean html, glossary)
+/*     - find_terms(find_text)
+/*
+/**********************************************************************************/
+
+
+/**
+* Returns a formatted date string - Uses the same options as date(), but requires a % infront of each argument and the
+* textual values are language dependent (unlike date()).
+* @access  public
+* @param   string $format              preferred date format 
+* @param   string $timestamp   value of timestamp
+* @param   int $format_type            timestamp format, an AT_DATE constant
+* @return  string                              formatted date
+* @see     AT_DATE constants   in include/lib/constants.inc.php
+* @author  Joel Kronenberg
+*/
+
+/* 
+       The following options were added as language dependant:
+       %D: A textual representation of a week, three letters Mon through Sun
+       %F: A full textual representation of a month, such as January or March January through December
+       %l (lowercase 'L'): A full textual representation of the day of the week Sunday through Saturday
+       %M: A short textual representation of a month, three letters Jan through Dec
+
+       Support for the following maybe added later:
+       ?? %S: English ordinal suffix for the day of the month, 2 characters st, nd, rd or th. Works well with j
+       ?? %a: Lowercase Ante meridiem and Post meridiem am or pm 
+       ?? %A: Uppercase Ante meridiem and Post meridiem AM or PM 
+
+       valid format_types:
+       AT_DATE_MYSQL_DATETIME:         YYYY-MM-DD HH:MM:SS
+       AT_DATE_MYSQL_TIMESTAMP_14:     YYYYMMDDHHMMSS
+       AT_DATE_UNIX_TIMESTAMP:         seconds since epoch
+       AT_DATE_INDEX_VALUE:            0-x, index into a date array
+*/
+function AT_date($format='%Y-%M-%d', $timestamp = '', $format_type=AT_DATE_MYSQL_DATETIME) {   
+       static $day_name_ext, $day_name_con, $month_name_ext, $month_name_con;
+
+       if (!isset($day_name_ext)) {
+               $day_name_ext = array(  'date_sunday', 
+                                                               'date_monday', 
+                                                               'date_tuesday', 
+                                                               'date_wednesday', 
+                                                               'date_thursday', 
+                                                               'date_friday',
+                                                               'date_saturday');
+
+               $day_name_con = array(  'date_sun', 
+                                                               'date_mon', 
+                                                               'date_tue', 
+                                                               'date_wed',
+                                                               'date_thu', 
+                                                               'date_fri', 
+                                                               'date_sat');
+
+               $month_name_ext = array('date_january', 
+                                                               'date_february', 
+                                                               'date_march', 
+                                                               'date_april', 
+                                                               'date_may',
+                                                               'date_june', 
+                                                               'date_july', 
+                                                               'date_august', 
+                                                               'date_september', 
+                                                               'date_october', 
+                                                               'date_november',
+                                                               'date_december');
+
+               $month_name_con = array('date_jan', 
+                                                               'date_feb', 
+                                                               'date_mar', 
+                                                               'date_apr', 
+                                                               'date_may_short',
+                                                               'date_jun', 
+                                                               'date_jul', 
+                                                               'date_aug', 
+                                                               'date_sep', 
+                                                               'date_oct', 
+                                                               'date_nov',
+                                                               'date_dec');
+       }
+
+       if ($format_type == AT_DATE_INDEX_VALUE) {
+               if ($format == '%D') {
+                       return _AT($day_name_con[$timestamp-1]);
+               } else if ($format == '%l') {
+                       return _AT($day_name_ext[$timestamp-1]);
+               } else if ($format == '%F') {
+                       return _AT($month_name_ext[$timestamp-1]);
+               } else if ($format == '%M') {
+                       return _AT($month_name_con[$timestamp-1]);
+               }
+       }
+
+       if ($timestamp == '') {
+               $timestamp = time();
+               $format_type = AT_DATE_UNIX_TIMESTAMP;
+       }
+
+       /* convert the date to a Unix timestamp before we do anything with it */
+       if ($format_type == AT_DATE_MYSQL_DATETIME) {
+               $year   = substr($timestamp,0,4);
+               $month  = substr($timestamp,5,2);
+               $day    = substr($timestamp,8,2);
+               $hour   = substr($timestamp,11,2);
+               $min    = substr($timestamp,14,2);
+               $sec    = substr($timestamp,17,2);
+           $timestamp  = mktime($hour, $min, $sec, $month, $day, $year);
+
+       } else if ($format_type == AT_DATE_MYSQL_TIMESTAMP_14) {
+           $year               = substr($timestamp,0,4);
+           $month              = substr($timestamp,4,2);
+           $day                = substr($timestamp,6,2);
+               $hour           = substr($timestamp,8,2);
+           $minute             = substr($timestamp,10,2);
+           $second             = substr($timestamp,12,2);
+           $timestamp  = mktime($hour, $minute, $second, $month, $day, $year);  
+       }
+
+       /* pull out all the %X items from $format */
+       $first_token = strpos($format, '%');
+       if ($first_token === false) {
+               /* no tokens found */
+               return $timestamp;
+       } else {
+               $tokened_format = substr($format, $first_token);
+       }
+       $tokens = explode('%', $tokened_format);
+       array_shift($tokens);
+       $num_tokens = count($tokens);
+
+       $output = $format;
+       for ($i=0; $i<$num_tokens; $i++) {
+               $tokens[$i] = substr($tokens[$i],0,1);
+
+               if ($tokens[$i] == 'D') {
+                       $output = str_replace('%D', _AT($day_name_con[date('w', $timestamp)]),$output);
+               
+               } else if ($tokens[$i] == 'l') {
+                       $output = str_replace('%l', _AT($day_name_ext[date('w', $timestamp)]),$output);
+               
+               } else if ($tokens[$i] == 'F') {
+                       $output = str_replace('%F', _AT($month_name_ext[date('n', $timestamp)-1]),$output);             
+               
+               } else if ($tokens[$i] == 'M') {
+                       $output = str_replace('%M', _AT($month_name_con[date('n', $timestamp)-1]),$output);
+
+               } else {
+
+                       /* this token doesn't need translating */
+                       $value = date($tokens[$i], $timestamp);
+                       if ($value != $tokens[$i]) {
+                               $output = str_replace('%'.$tokens[$i], $value, $output);
+                       } /* else: this token isn't valid. so don't replace it. Eg. try %q */
+               }
+       }
+
+       return $output;
+}
+
+/**
+* Converts language code to actual language message, caches them according to page url
+* @access      public
+* @param       args                            unlimited number of arguments allowed but first arg MUST be name of the language variable/term
+*                                                              i.e             $args[0] = the term to the format string $_template[term]
+*                                                                              $args[1..x] = optional arguments to the formatting string 
+* @return      string|array            full resulting message
+* @see         $db                             in include/vitals.inc.php
+* @see         cache()                         in include/phpCache/phpCache.inc.php
+* @see         cache_variable()        in include/phpCache/phpCache.inc.php
+* @author      Joel Kronenberg
+*/
+function _AT() {
+       global $_cache_template, $lang_et, $_rel_url;
+       static $_template;
+       
+       $args = func_get_args();
+       
+       // a feedback msg
+       if (!is_array($args[0])) {
+               /**
+                * Added functionality for translating language code String (AT_ERROR|AT_INFOS|AT_WARNING|AT_FEEDBACK|AT_HELP).*
+                * to its text and returning the result. No caching needed.
+                * @author Jacek Materna
+                */
+
+               // Check for specific language prefix, extendible as needed
+               // 0002767:  a substring+in_array test should be faster than a preg_match test.
+               // replaced the preg_match with a test of the substring.
+               $sub_arg = substr($args[0], 0, 7); // 7 is the shortest type of msg (AT_HELP)
+               if (in_array($sub_arg, array('AT_ERRO','AT_INFO','AT_WARN','AT_FEED','AT_HELP','AT_CONF'))) {
+                       global $db;
+                       global $_base_path, $addslashes;
+
+                       $args[0] = $addslashes($args[0]);
+                                       
+                       /* get $_msgs_new from the DB */
+                       $sql    = 'SELECT text FROM '.TABLE_PREFIX.'language_text WHERE term="' . $args[0] . '" AND (variable="_msgs" OR variable="_c_msgs") AND language_code="'.$_SESSION['lang'].'" ORDER BY variable ASC LIMIT 1';
+
+                       $result = @mysql_query($sql, $db);
+                       $i = 1;
+                       $msgs = '';
+                                       
+                       if ($row = @mysql_fetch_assoc($result)) {
+                               // do not cache key as a digit (no contstant(), use string)
+                               $msgs = str_replace('SITE_URL/', $_base_path, $row['text']);
+                               if (defined('AT_DEVEL') && AT_DEVEL) {
+                                       $msgs .= ' <small><small>('. $args[0] .')</small></small>';
+                               }
+                       }
+
+                       $sql = 'INSERT INTO '.TABLE_PREFIX.'language_pages (`term`, `page`) VALUES ("'.$args[0].'", "'.$_rel_url.'")';
+                       mysql_query($sql, $db);
+
+                       return $msgs;
+               }
+       }
+       
+       // a template variable
+       if (!isset($_template)) {
+               $url_parts = parse_url(AT_BASE_HREF);
+               $name = substr($_SERVER['PHP_SELF'], strlen($url_parts['path'])-1);
+
+               if ( !($lang_et = cache(120, 'lang', $_SESSION['lang'].'_'.$name)) ) {
+                       global $db;
+
+                       /* get $_template from the DB */
+                       
+                       $sql = "SELECT L.* FROM ".TABLE_PREFIX."language_text L, ".TABLE_PREFIX."language_pages P WHERE L.language_code='{$_SESSION['lang']}' AND L.variable<>'_msgs' AND L.term=P.term AND P.page='$_rel_url' ORDER BY L.variable ASC";
+                       $result = mysql_query($sql, $db);
+                       while ($row = mysql_fetch_assoc($result)) {
+                               //Do not overwrite the variable that existed in the cache_template already.
+                               //The edited terms (_c_template) will always be at the top of the resultset
+                               //0003279
+                               if (isset($_cache_template[$row['term']])){
+                                       continue;
+                               }
+
+                               // saves us from doing an ORDER BY
+                               if ($row['language_code'] == $_SESSION['lang']) {
+                                       $_cache_template[$row['term']] = stripslashes($row['text']);
+                               } else if (!isset($_cache_template[$row['term']])) {
+                                       $_cache_template[$row['term']] = stripslashes($row['text']);
+                               }
+                       }
+               
+                       cache_variable('_cache_template');
+                       endcache(true, false);
+               }
+               $_template = $_cache_template;
+       }
+       $num_args = func_num_args();
+       if (is_array($args[0])) {
+               $args = $args[0];
+               $num_args = count($args);
+       }
+       $format   = array_shift($args);
+
+       if (isset($_template[$format])) {
+               /*
+               var_dump($_template);
+               var_dump($format);
+               var_dump($args);
+               exit;
+               */
+               $outString      = vsprintf($_template[$format], $args);
+               $str = ob_get_contents();
+       } else {
+               $outString = '';
+       }
+
+
+       if ($outString === false) {
+               return ('[Error parsing language. Variable: <code>'.$format.'</code>. Language: <code>'.$_SESSION['lang'].'</code> ]');
+       }
+
+       if (empty($outString)) {
+               global $db;
+               $sql    = 'SELECT L.* FROM '.TABLE_PREFIX.'language_text L WHERE L.language_code="'.$_SESSION['lang'].'" AND L.variable<>"_msgs" AND L.term="'.$format.'"';
+
+               $result = mysql_query($sql, $db);
+               $row = mysql_fetch_assoc($result);
+
+               $_template[$row['term']] = stripslashes($row['text']);
+               $outString = $_template[$row['term']];
+               if (empty($outString)) {
+                       return ('[ '.$format.' ]');
+               }
+               $outString = $_template[$row['term']];
+               $outString = vsprintf($outString, $args);
+
+               /* update the locations */
+               $sql = 'INSERT INTO '.TABLE_PREFIX.'language_pages (`term`, `page`) VALUES ("'.$format.'", "'.$_rel_url.'")';
+               mysql_query($sql, $db);
+       }
+
+       return $outString;
+}
+
+/**********************************************************************************************************/
+       /**
+       *       Transforms text based on formatting preferences.  Original $input is also changed (passed by reference).
+       *       Can be called as:
+       *       1) $output = AT_print($input, $name);
+       *          echo $output;
+       *
+       *       2) echo AT_print($input, $name); // prefered method
+       *
+       * @access       public
+       * @param        string $input                   text being transformed
+       * @param        string $name                    the unique name of this field (convension: table_name.field_name)
+       * @param        boolean $runtime_html   forcefully disables html formatting for $input (only used by fields that 
+       *                                                                       have the 'formatting' option
+       * @return       string                                  transformed $input
+       * @see          AT_FORMAT constants             in include/lib/constants.inc.php
+       * @see          query_bit()                             in include/vitals.inc.php
+       * @author       Joel Kronenberg
+       */
+       function AT_print($input, $name, $runtime_html = true) {
+               global $_field_formatting;
+
+               if (!isset($_field_formatting[$name])) {
+                       /* field not set, check if there's a global setting */
+                       $parts = explode('.', $name);
+                       
+                       /* check if wildcard is set: */
+                       if (isset($_field_formatting[$parts[0].'.*'])) {
+                               $name = $parts[0].'.*';
+                       } else {
+                               /* field not set, and there's no global setting */
+                               /* same as AT_FORMAT_NONE */
+                               return $input;
+                       }
+               }
+
+               if (query_bit($_field_formatting[$name], AT_FORMAT_QUOTES)) {
+                       $input = str_replace('"', '&quot;', $input);
+               }
+
+               if (query_bit($_field_formatting[$name], AT_FORMAT_CONTENT_DIR)) {
+                       $input = str_replace('CONTENT_DIR/', '', $input);
+               }
+
+               if (query_bit($_field_formatting[$name], AT_FORMAT_HTML) && $runtime_html) {
+                       /* what special things do we have to do if this is HTML ? remove unwanted HTML? validate? */
+               } else {
+                       $input = str_replace('<', '&lt;', $input);
+                       $input = nl2br($input);
+               }
+
+               /* this has to be here, only because AT_FORMAT_HTML is the only check that has an else-block */
+               if ($_field_formatting[$name] === AT_FORMAT_NONE) {
+                       return $input;
+               }
+
+               if (query_bit($_field_formatting[$name], AT_FORMAT_EMOTICONS)) {
+                       $input = smile_replace($input);
+               }
+
+               if (query_bit($_field_formatting[$name], AT_FORMAT_ATCODES)) {
+                       $input = trim(myCodes(' ' . $input . ' '));
+               }
+
+               if (query_bit($_field_formatting[$name], AT_FORMAT_LINKS)) {
+                       $input = trim(make_clickable(' ' . $input . ' '));
+               }
+
+               if (query_bit($_field_formatting[$name], AT_FORMAT_IMAGES)) {
+                       $input = trim(image_replace(' ' . $input . ' '));
+               }
+
+       
+               return $input;
+       }
+
+/********************************************************************************************/
+// Global variables for emoticons
+global $smile_pics;
+global $smile_codes;
+if (!isset($smile_pics)) {
+       $smile_pics[0] = $_base_path.'images/forum/smile.gif';
+       $smile_pics[1] = $_base_path.'images/forum/wink.gif';
+       $smile_pics[2] = $_base_path.'images/forum/frown.gif';
+       $smile_pics[3] = $_base_path.'images/forum/ohwell.gif';
+       $smile_pics[4] = $_base_path.'images/forum/tongue.gif';
+       $smile_pics[5] = $_base_path.'images/forum/51.gif';
+       $smile_pics[6] = $_base_path.'images/forum/52.gif';
+       $smile_pics[7] = $_base_path.'images/forum/54.gif';
+       $smile_pics[8] = $_base_path.'images/forum/27.gif';
+       $smile_pics[9] = $_base_path.'images/forum/19.gif';
+       $smile_pics[10] = $_base_path.'images/forum/3.gif';
+       $smile_pics[11] = $_base_path.'images/forum/56.gif';
+}
+
+if (!isset($smile_codes)) {
+       $smile_codes[0] = ':)';
+       $smile_codes[1] = ';)';
+       $smile_codes[2] = ':(';
+       $smile_codes[3] = '::ohwell::';
+       $smile_codes[4] = ':P';
+       $smile_codes[5] = '::evil::';
+       $smile_codes[6] = '::angry::';
+       $smile_codes[7] = '::lol::';
+       $smile_codes[8] = '::crazy::';
+       $smile_codes[9] = '::tired::';
+       $smile_codes[10] = '::confused::';
+       $smile_codes[11] = '::muah::';
+}
+
+/**
+* Replaces smile-code text into smilie image.
+* @access      public
+* @param       string $text            smile text to be transformed
+* @return      string                          transformed $text
+* @see         $smile_pics                     in include/lib/output.inc.php (above)
+* @see         $smile_codes            in include/lib/output.inc.php (above)
+* @author      Joel Kronenberg
+*/
+function smile_replace($text) {
+       global $smile_pics;
+       global $smile_codes;
+       static $smiles;
+
+       $smiles[0] = '<img src="'.$smile_pics[0].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_smile').'" />';
+       $smiles[1] = '<img src="'.$smile_pics[1].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_wink').'" />';
+       $smiles[2] = '<img src="'.$smile_pics[2].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_frown').'" />';
+       $smiles[3]= '<img src="'.$smile_pics[3].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_oh_well').'" />';
+       $smiles[4]= '<img src="'.$smile_pics[4].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_tongue').'" />';
+       $smiles[5]= '<img src="'.$smile_pics[5].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_evil').'" />';
+       $smiles[6]= '<img src="'.$smile_pics[6].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_angry').'" />';
+       $smiles[7]= '<img src="'.$smile_pics[7].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_lol').'" />';
+       $smiles[8]= '<img src="'.$smile_pics[8].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_crazy').'" />';
+       $smiles[9]= '<img src="'.$smile_pics[9].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_tired').'" />';
+       $smiles[10]= '<img src="'.$smile_pics[10].'" border="0" height="17" width="19" align="bottom" alt="'._AT('smile_confused').'" />';
+       $smiles[11]= '<img src="'.$smile_pics[11].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_muah').'" />';
+
+       $text = str_replace($smile_codes[0],$smiles[0],$text);
+       $text = str_replace($smile_codes[1],$smiles[1],$text);
+       $text = str_replace($smile_codes[2],$smiles[2],$text);
+       $text = str_replace($smile_codes[3],$smiles[3],$text);
+       $text = str_replace($smile_codes[4],$smiles[4],$text);
+       $text = str_replace($smile_codes[5],$smiles[5],$text);
+       $text = str_replace($smile_codes[6],$smiles[6],$text);
+       $text = str_replace($smile_codes[7],$smiles[7],$text);
+       $text = str_replace($smile_codes[8],$smiles[8],$text);
+       $text = str_replace($smile_codes[9],$smiles[9],$text);
+       $text = str_replace($smile_codes[10],$smiles[10],$text);
+       $text = str_replace($smile_codes[11],$smiles[11],$text);
+
+       return $text;
+}
+
+
+/* Used specifically for the visual editor
+*/
+function smile_javascript () {
+       global $_base_path;
+       global $smile_pics;
+       global $smile_codes;
+
+       static $i = 0;
+
+       while ($smile_pics [$i]) {
+               echo 'case "'.$smile_codes[$i].'":'."\n";
+               echo 'pic = "'.$smile_pics[$i].'";'."\n";
+               echo 'break;'."\n";
+               $i++;
+       }
+}
+
+function myCodes($text, $html = false) {
+       global $_base_path;
+       global $HTTP_USER_AGENT;
+
+       if (substr($HTTP_USER_AGENT,0,11) == 'Mozilla/4.7') {
+               $text = str_replace('[quote]','</p><p class="block">',$text);
+               $text = str_replace('[/quote]','</p><p>',$text);
+
+               $text = str_replace('[reply]','</p><p class="block">',$text);
+               $text = str_replace('[/reply]','</p><p>',$text);
+       } else {
+               $text = str_replace('[quote]','<blockquote>',$text);
+               $text = str_replace('[/quote]','</blockquote><p>',$text);
+
+               $text = str_replace('[reply]','</p><blockquote class="block"><p>',$text);
+               $text = str_replace('[/reply]','</p></blockquote><p>',$text);
+       }
+
+       $text = str_replace('[b]','<strong>',$text);
+       $text = str_replace('[/b]','</strong>',$text);
+
+       $text = str_replace('[i]','<em>',$text);
+       $text = str_replace('[/i]','</em>',$text);
+
+       $text = str_replace('[u]','<u>',$text);
+       $text = str_replace('[/u]','</u>',$text);
+
+       $text = str_replace('[center]','<center>',$text);
+       $text = str_replace('[/center]','</center><p>',$text);
+
+       /* colours */
+       $text = str_replace('[blue]','<span style="color: blue;">',$text);
+       $text = str_replace('[/blue]','</span>',$text);
+
+       $text = str_replace('[orange]','<span style="color: orange;">',$text);
+       $text = str_replace('[/orange]','</span>',$text);
+
+       $text = str_replace('[red]','<span style="color: red;">',$text);
+       $text = str_replace('[/red]','</span>',$text);
+
+       $text = str_replace('[purple]','<span style="color: purple;">',$text);
+       $text = str_replace('[/purple]','</span>',$text);
+
+       $text = str_replace('[green]','<span style="color: green;">',$text);
+       $text = str_replace('[/green]','</span>',$text);
+
+       $text = str_replace('[gray]','<span style="color: gray;">',$text);
+       $text = str_replace('[/gray]','</span>',$text);
+
+       $text = str_replace('[op]','<span class="bigspacer"></span> <a href="',$text);
+       $text = str_replace('[/op]','">'._AT('view_entire_post').'</a>',$text);
+
+       $text = str_replace('[head1]','<h2>',$text);
+       $text = str_replace('[/head1]','</h2>',$text);
+
+       $text = str_replace('[head2]','<h3>',$text);
+       $text = str_replace('[/head2]','</h3>',$text);
+
+       $text = str_replace('[cid]',$_base_path.'content.php?cid='.$_SESSION['s_cid'],$text);
+
+       global $sequence_links;
+       if (isset($sequence_links['previous']) && $sequence_links['previous']['url']) {
+               $text = str_replace('[pid]', $sequence_links['previous']['url'], $text);
+       }
+       if (isset($sequence_links['next']) && $sequence_links['next']['url']) {
+               $text = str_replace('[nid]', $sequence_links['next']['url'], $text);
+       }
+       if (isset($sequence_links['resume']) && $sequence_links['resume']['url']) {
+               $text = str_replace('[nid]', $sequence_links['resume']['url'], $text);
+       }
+       if (isset($sequence_links['first']) && $sequence_links['first']['url']) {
+               $text = str_replace('[fid]', $sequence_links['first']['url'], $text);
+       }
+
+       /* contributed by Thomas M. Duffey <tduffey at homeboyz.com> */
+       $html = !$html ? 0 : 1;
+       $text = preg_replace("/\[code\]\s*(.*)\s*\[\\/code\]/Usei", "highlight_code(fix_quotes('\\1'), $html)", $text);
+
+       return $text;
+}
+
+/* contributed by Thomas M. Duffey <tduffey at homeboyz.com> */
+function highlight_code($code, $html) {
+       // XHTMLize PHP highlight_string output until it gets fixed in PHP
+       static $search = array(
+               '<br>',
+               '<font',
+               '</font>',
+               'color="');
+
+       static $replace = array(
+               '<br />',
+               '<span',
+               '</span>',
+               'style="color:');
+       if (!$html) {
+               $code = str_replace('&lt;', '<', $code);
+               $code = str_replace("\r", '', $code);
+       }
+
+       return str_replace($search, $replace, highlight_string($code, true));
+}
+
+/* contributed by Thomas M. Duffey <tduffey at homeboyz.com> */
+function fix_quotes($text){
+       return str_replace('\\"', '"', $text);
+}
+
+function embed_media($text) {
+       if (preg_match("/\[media(\|[0-9]+\|[0-9]+)?\]*/", $text)==0){
+               return $text;
+       }
+
+       $media_matches = Array();
+       
+       /*
+               First, we search though the text for all different kinds of media defined by media tags and store the results in $media_matches.
+               
+               Then the different replacements for the different media tags are stored in $media_replace.
+               
+               Lastly, we loop through all $media_matches / $media_replaces. (We choose $media_replace as index because $media_matches is multi-dimensioned.) It is important that for each $media_matches there is a $media_replace with the same index. For each media match we check the width/height, or we use the default value of 425x350. We then replace the height/width/media1/media2 parameter placeholders in $media_replace with the correct ones, before running a str_replace on $text, replacing the given media with its correct replacement.
+               
+       */
+       
+       // youtube videos
+       preg_match_all("#\[media[0-9a-z\|]*\]http://([a-z0-9\.]*)?youtube.com/watch\?v=([a-z0-9_-]+)\[/media\]#i",$text,$media_matches[1],PREG_SET_ORDER);
+       $media_replace[1] = '<object width="##WIDTH##" height="##HEIGHT##"><param name="movie" value="http://##MEDIA1##youtube.com/v/##MEDIA2##"></param><embed src="http://##MEDIA1##youtube.com/v/##MEDIA2##" type="application/x-shockwave-flash" width="##WIDTH##" height="##HEIGHT##"></embed></object>';
+               
+       // .mpg
+       preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+).mpg\[/media\]#i",$text,$media_matches[2],PREG_SET_ORDER);
+       $media_replace[2] = "<object data=\"##MEDIA1##.mpg\" type=\"video/mpeg\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"src\" value=\"##MEDIA1##.mpg\"><param name=\"autoplay\" value=\"false\"><param name=\"autoStart\" value=\"0\"><a href=\"##MEDIA1##.mpg\">##MEDIA1##.mpg</a></object>";
+       
+       // .avi
+       preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+).avi\[/media\]#i",$text,$media_matches[3],PREG_SET_ORDER);
+       $media_replace[3] = "<object data=\"##MEDIA1##.avi\" type=\"video/x-msvideo\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"src\" value=\"##MEDIA1##.avi\"><param name=\"autoplay\" value=\"false\"><param name=\"autoStart\" value=\"0\"><a href=\"##MEDIA1##.avi\">##MEDIA1##.avi</a></object>";
+       
+       // .wmv
+       preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+).wmv\[/media\]#i",$text,$media_matches[4],PREG_SET_ORDER);
+       $media_replace[4] = "<object data=\"##MEDIA1##.wmv\" type=\"video/x-ms-wmv\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"src\" value=\"##MEDIA1##.wmv\"><param name=\"autoplay\" value=\"false\"><param name=\"autoStart\" value=\"0\"><a href=\"##MEDIA1##.wmv\">##MEDIA1##.wmv</a></object>";
+       
+       // .mov
+       preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+).mov\[/media\]#i",$text,$media_matches[5],PREG_SET_ORDER);
+       $media_replace[5] = "<object classid=\"clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B\" codebase=\"http://www.apple.com/qtactivex/qtplugin.cab\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"src\" value=\"##MEDIA1##.mov\"><param name=\"controller\" value=\"true\"><param name=\"autoplay\" value=\"false\"><!--[if gte IE 7]> <!--><object type=\"video/quicktime\" data=\"##MEDIA1##.mov\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"controller\" value=\"true\"><param name=\"autoplay\" value=\"false\"><a href=\"##MEDIA1##.mov\">##MEDIA1##.mov</a></object><!--<![endif]--><!--[if lt IE 7]><a href=\"##MEDIA1##.mov\">##MEDIA1##.mov</a><![endif]--></object>";
+       
+       // .swf
+       preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+).swf\[/media\]#i",$text,$media_matches[6],PREG_SET_ORDER);
+       $media_replace[6] = "<object type=\"application/x-shockwave-flash\" data=\"##MEDIA1##.swf\" width=\"##WIDTH##\" height=\"##HEIGHT##\">  <param name=\"movie\" value=\"##MEDIA1##.swf\"><param name=\"loop\" value=\"false\"><a href=\"##MEDIA1##.swf\">##MEDIA1##.swf</a></object>";
+       
+       // .mp3
+       preg_match_all("#\[media[0-9a-z\|]*\](.+[^\s\"]+).mp3\[/media\]#i",$text,$media_matches[7],PREG_SET_ORDER);
+       $media_replace[7] = "<object type=\"audio/mpeg\" data=\"##MEDIA1##.mp3\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"src\" value=\"##MEDIA1##.mp3\"><param name=\"autoplay\" value=\"false\"><param name=\"autoStart\" value=\"0\"><a href=\"##MEDIA1##.mp3\">##MEDIA1##.mp3</a></object>";
+       
+       // .wav
+       preg_match_all("#\[media[0-9a-z\|]*\](.+[^\s\"]+).wav\[/media\]#i",$text,$media_matches[8],PREG_SET_ORDER);
+       $media_replace[8] ="<object type=\"audio/x-wav\" data=\"##MEDIA1##.wav\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"src\" value=\"##MEDIA1##.wav\"><param name=\"autoplay\" value=\"false\"><param name=\"autoStart\" value=\"0\"><a href=\"##MEDIA1##.wav\">##MEDIA1##.wav</a></object>";
+       
+       // .ogg
+       preg_match_all("#\[media[0-9a-z\|]*\](.+[^\s\"]+).ogg\[/media\]#i",$text,$media_matches[9],PREG_SET_ORDER);
+       $media_replace[9] ="<object type=\"application/ogg\" data=\"##MEDIA1##.ogg\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"src\" value=\"##MEDIA1##.ogg\"><a href=\"##MEDIA1##.ogg\">##MEDIA1##.ogg</a></object>";
+       
+       // .mid
+       preg_match_all("#\[media[0-9a-z\|]*\](.+[^\s\"]+).mid\[/media\]#i",$text,$media_matches[10],PREG_SET_ORDER);
+       $media_replace[10] ="<object type=\"application/x-midi\" data=\"##MEDIA1##.mid\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"src\" value=\"##MEDIA1##.mid\"><a href=\"##MEDIA1##.mid\">##MEDIA1##.mid</a></object>";
+       
+       $text = preg_replace("#\[media[0-9a-z\|]*\](.+[^\s\"]+).mid\[/media\]#i", "<object type=\"application/x-midi\" data=\"\\1.mid\" width=\"".$width."\" height=\"".$height."\"><param name=\"src\" value=\"\\1.mid\"><a href=\"\\1.mid\">\\1.mid</a></object>", $text);
+
+       // Executing the replace
+       for ($i=1;$i<=count($media_replace);$i++){
+               foreach($media_matches[$i] as $media)
+               {
+                       
+                       //find width and height for each matched media
+                       if (preg_match("/\[media\|([0-9]*)\|([0-9]*)\]*/", $media[0], $matches)) 
+                       {
+                               $width = $matches[1];
+                               $height = $matches[2];
+                       }
+                       else
+                       {
+                               $width = 425;
+                               $height = 350;
+                       }
+                       
+                       //replace media tags with embedded media for each media tag
+                       $media_input = $media_replace[$i];
+                       $media_input = str_replace("##WIDTH##","$width",$media_input);
+                       $media_input = str_replace("##HEIGHT##","$height",$media_input);
+                       $media_input = str_replace("##MEDIA1##","$media[1]",$media_input);
+                       $media_input = str_replace("##MEDIA2##","$media[2]",$media_input);
+                       $text = str_replace($media[0],$media_input,$text);
+               }
+       }
+               
+       return $text;
+}
+
+function make_clickable($text) {
+       $text = embed_media($text);
+
+       $text = eregi_replace("([[:space:]])(http[s]?)://([^[:space:]<]*)([[:alnum:]#?/&=])", "\\1<a href=\"\\2://\\3\\4\">\\3\\4</a>", $text);
+
+       $text = eregi_replace(  '([_a-zA-Z0-9\-]+(\.[_a-zA-Z0-9\-]+)*'.
+                                                       '\@'.'[_a-zA-Z0-9\-]+(\.[_a-zA-Z0-9\-]+)*'.'(\.[a-zA-Z]{1,6})+)',
+                                                       "<a href=\"mailto:\\1\">\\1</a>",
+                                                       $text);
+
+       return $text;
+}
+
+function image_replace($text) {
+       /* image urls do not require http:// */
+       
+       $text = eregi_replace("\[image(\|)?([[:alnum:][:space:]]*)\]" .
+                                                "[:space:]*" .
+                                                "([[:alnum:]#?/&=:\"'_.-]+)" .
+                                                "[:space:]*" .
+                                                "((\[/image\])|(.*\[/image\]))",
+                                 "<img src=\"\\3\" alt=\"\\2\" />",
+                                 $text);
+        
+       return $text;
+}
+
+function format_final_output($text, $nl2br = true) {
+       global $_base_path;
+
+       $text = str_replace('CONTENT_DIR/', '', $text);
+
+       if ($nl2br) {
+               return nl2br(image_replace(make_clickable(myCodes(' '.$text, false))));
+       }
+       return image_replace(make_clickable(myCodes(' '.$text, true)));
+}
+
+/****************************************************************************************/
+/* @See: ./user/search.php & ./index.php */
+function highlight($input, $var) {//$input is the string, $var is the text to be highlighted
+       if ($var != "") {
+               $xtemp = "";
+               $i=0;
+               /*
+                       The following 'if' statement is a check to ensure that the search term is not part of the tag, '<strong class="highlight">'.  Words within this string are avoided in case a previously highlighted string is used for the haystack, $input.  To avoid any html breaks in the highlighted string, the search word is avoided completely.
+               */
+               if (strpos('<strong class="highlight">', $var) !== false) {
+                       return $input;
+               }
+               while($i<strlen($input)){
+                       if((($i + strlen($var)) <= strlen($input)) && (strcasecmp($var, substr($input, $i, strlen($var))) == 0)) {
+                               $xtemp .= '<strong class="highlight">' . substr($input, $i , strlen($var)) . '</strong>';
+                               $i += strlen($var);
+                       }
+                       else {
+                               $xtemp .= $input{$i};
+                               $i++;
+                       }
+               }
+               $input = $xtemp;
+       }
+       return $input;
+}
+
+
+/* @See: ./index.php */
+function format_content($input, $html = 0, $glossary, $simple = false) {
+       global $_base_path, $_config_defaults;
+
+       if (!$html) {
+               $input = str_replace('<', '&lt;', $input);
+               $input = str_replace('&lt;?php', '<?php', $input); // for bug #2087
+       }
+
+       /* do the glossary search and replace: */
+       if (is_array($glossary)) {
+               foreach ($glossary as $k => $v) {
+                       $k = urldecode($k);
+                       $v = str_replace("\n", '<br />', $v);
+                       $v = str_replace("\r", '', $v);
+
+                       /* escape special characters */
+                       $k = preg_quote($k);
+
+                       $k = str_replace('&lt;', '<', $k);
+                       $k = str_replace('/', '\/', $k);
+
+                       $original_term = $k;
+                       $term = $original_term;
+
+                       $term = '(\s*'.$term.'\s*)';
+                       $term = str_replace(' ','((<br \/>)*\s*)', $term); 
+
+                       $def = htmlspecialchars($v);            
+                       if ($simple) {
+                               $input = preg_replace
+                                               ("/(\[\?\])$term(\[\/\?\])/i",
+                                               '<a href="'.$simple.'glossary.html#'.urlencode($original_term).'" target="body" class="at-term">\\2</a>',
+                                               $input);
+                       } else {
+                               $input = preg_replace
+                                               ("/(\[\?\])$term(\[\/\?\])/i",
+                                               '\\2<sup><a href="'.$_base_path.'glossary/index.php?g_cid='.$_SESSION['s_cid'].SEP.'w='.urlencode($original_term).'#term" onmouseover="return overlib(\''.$def.'\', CAPTION, \''.addslashes($original_term).'\', AUTOSTATUS);" onmouseout="return nd();" onfocus="return overlib(\''.$def.'\', CAPTION, \''.addslashes($original_term).'\', AUTOSTATUS);" onblur="return nd();"><span style="color: blue; text-decoration: none;font-size:small; font-weight:bolder;">?</span></a></sup>',
+                                               $input);
+                       }
+               }
+       } else if (!$user_glossary) {
+               $input = str_replace(array('[?]','[/?]'), '', $input);
+       }
+
+       $input = str_replace('CONTENT_DIR', '', $input);
+
+       if (isset($_config_defaults['latex_server']) && $_config_defaults['latex_server']) {
+               // see: http://www.forkosh.com/mimetex.html
+               $input = preg_replace('/\[tex\](.*?)\[\/tex\]/sie', "'<img src=\"'.\$_config_defaults['latex_server'].rawurlencode('$1').'\" align=\"middle\">'", $input);
+       }
+
+       if ($html) {
+               $x = format_final_output($input, false);
+               return $x;
+       }
+
+       $output = format_final_output($input);
+
+       $output = '<p>'.$output.'</p>';
+
+       return $output;
+}
+
+function find_terms($find_text) {
+       preg_match_all("/(\[\?\])(.[^\?]*)(\[\/\?\])/i", $find_text, $found_terms, PREG_PATTERN_ORDER);
+       return $found_terms;
+}
+
+/***********************************************************************
+       @See /include/Classes/Message/Message.class.php
+       Jacek Materna
+*/
+
+/**
+* Take a code as input and grab its language specific message. Also cache the resulting 
+* message. Return the message. Same as get_message but key value in cache is string
+* @access  public
+* @param   string $codes       Message Code to translate - > 'term' field in DB
+* @return  string                      The translated language specific message for code $code
+* @author  Jacek Materna
+*/
+function getTranslatedCodeStr($codes) {
+       
+       /* this is where we want to get the msgs from the database inside a static variable */
+       global $_cache_msgs_new;
+       static $_msgs_new;
+
+       if (!isset($_msgs_new)) {
+               if ( !($lang_et = cache(120, 'msgs_new', $_SESSION['lang'])) ) {
+                       global $db, $_base_path;
+
+                       $parent = Language::getParentCode($_SESSION['lang']);
+
+                       /* get $_msgs_new from the DB */
+                       $sql    = 'SELECT * FROM '.TABLE_PREFIX.'language_text WHERE variable="_msgs" AND (language_code="'.$_SESSION['lang'].'" OR language_code="'.$parent.'")';
+                       $result = @mysql_query($sql, $db);
+                       $i = 1;
+                       while ($row = @mysql_fetch_assoc($result)) {
+                               // do not cache key as a digit (no contstant(), use string)
+                               $_cache_msgs_new[$row['term']] = str_replace('SITE_URL/', $_base_path, $row['text']);
+                               if (AT_DEVEL) {
+                                       $_cache_msgs_new[$row['term']] .= ' <small><small>('.$row['term'].')</small></small>';
+                               }
+                       }
+
+                       cache_variable('_cache_msgs_new');
+                       endcache(true, false);
+               }
+               $_msgs_new = $_cache_msgs_new;
+       }
+
+       if (is_array($codes)) {
+               /* this is an array with terms to replace */            
+               $code           = array_shift($codes);
+
+               $message        = $_msgs_new[$code];
+               $terms          = $codes;
+
+               /* replace the tokens with the terms */
+               $message        = vsprintf($message, $terms);
+
+       } else {
+               $message = $_msgs_new[$codes];
+
+               if ($message == '') {
+                       /* the language for this msg is missing: */
+               
+                       $sql    = 'SELECT * FROM '.TABLE_PREFIX.'language_text WHERE variable="_msgs"';
+                       $result = @mysql_query($sql, $db);
+                       $i = 1;
+                       while ($row = @mysql_fetch_assoc($result)) {
+                               if (($row['term']) === $codes) {
+                                       $message = '['.$row['term'].']';
+                                       break;
+                               }
+                       }
+               }
+               $code = $codes;
+       }
+       return $message;
+}
+
+function html_get_list($array) {
+       $list = '';
+       foreach ($array as $value) {
+               $list .= '<li>'.$value.'</li>';
+       }
+       return $list;
+}
+
+/**
+ * print_paginator
+ *
+ * print out list of page links
+ */
+function print_paginator($current_page, $num_rows, $request_args, $rows_per_page = 50, $window = 5) {
+       $num_pages = ceil($num_rows / $rows_per_page);
+       $request_args = '?'.$request_args;
+
+    if ($num_rows) {
+               echo '<div class="paging">';
+           echo '<ul>';
+               
+               $i=max($current_page-$window - max($window-$num_pages+$current_page,0), 1);
+
+               if ($i > 1) {
+                       echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.'&p=1">1</a></li>';
+                       if ($i > 2) {
+                       echo '<li>&hellip;</li>';
+                       }
+               }
+
+               for ($i; $i<= min($current_page+$window -min($current_page-$window,0),$num_pages); $i++) {
+                       if ($current_page == $i) {
+                               echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.'&p='.$i.'" class="current"><em>'.$current_page.'</em></a></li>';
+                       } else {
+                               echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.'&p='.$i.'">'.$i.'</a></li>';
+                       }
+               }
+        if ($i <= $num_pages) {
+                       if ($i < $num_pages) {
+                       echo '<li>&hellip;</li>';
+               }
+                       echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.'&p='.$num_pages.'">'.$num_pages.'</a></li>';
+               }
+               echo '</ul>';
+               echo '</div>';
+       }
+}
+?>
diff --git a/include/lib/search.inc.php b/include/lib/search.inc.php
new file mode 100644 (file)
index 0000000..e52329d
--- /dev/null
@@ -0,0 +1,190 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                      */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg & Boon-Hau Teh */\r
+/* Adaptive Technology Resource Centre / University of Toronto          */\r
+/* http://atutor.ca                                                                                                    */\r
+/*                                                                      */\r
+/* This program is free software. You can redistribute it and/or        */\r
+/* modify it under the terms of the GNU General Public License          */\r
+/* as published by the Free Software Foundation.                                       */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+// NOTE! please see include/html/search.inc.php NOTE!\r
+\r
+function score_cmp($a, $b) {\r
+    if ($a['score'] == $b['score']) {\r
+        return 0;\r
+    }\r
+    return ($a['score'] > $b['score']) ? -1 : 1;\r
+}\r
+\r
+function get_search_result($words, $predicate, $course_id, &$num_found, &$total_score) {\r
+       global $addslashes, $db, $highlight_system_courses, $strlen, $substr, $strtolower;\r
+\r
+       $search_results = array();\r
+       $lower_words    = array();\r
+\r
+       $predicate = " $predicate "; // either 'AND' or 'OR'\r
+\r
+       $words = trim($words);\r
+       $words = explode(' ',$words);\r
+       $words = array_values(array_diff(array_unique($words), array('')));\r
+       $num_words = count($words);\r
+       $course_score = 0;\r
+       for ($i=0; $i<$num_words; $i++) {\r
+               $lower_words[$i] = $strtolower($words[$i]);\r
+\r
+               if ($words_sql) {\r
+                       $words_sql .= $predicate;\r
+               }\r
+               $words[$i] = $addslashes($words[$i]);\r
+               $words_sql .= ' (C.title LIKE "%'.$words[$i].'%" OR C.text LIKE "%'.$words[$i].'%" OR C.keywords LIKE "%'.$words[$i].'%")';\r
+\r
+               /* search through the course title and description keeping track of its total */\r
+               $course_score += 15 * substr_count($strtolower($highlight_system_courses[$course_id]['title']),       $lower_words[$i]);\r
+               $course_score += 12 * substr_count($strtolower($highlight_system_courses[$course_id]['description']), $lower_words[$i]);\r
+\r
+               $highlight_system_courses[$course_id]['title']       = highlight($highlight_system_courses[$course_id]['title'],       $words[$i]);\r
+               $highlight_system_courses[$course_id]['description'] = highlight($highlight_system_courses[$course_id]['description'], $words[$i]);\r
+       }\r
+       if (!$words_sql) {\r
+               return;\r
+       }\r
+\r
+       $sql =  'SELECT C.last_modified, C.course_id, C.content_id, C.title, C.text, C.keywords FROM '.TABLE_PREFIX.'content AS C WHERE C.course_id='.$course_id;\r
+       $sql .= ' AND ('.$words_sql.') LIMIT 200';\r
+\r
+       $result = mysql_query($sql, $db);\r
+       while($row = mysql_fetch_assoc($result)) {\r
+               $score = 0;\r
+\r
+               $row['title'] = strip_tags($row['title']);\r
+               $row['text']  = strip_tags($row['text']);\r
+\r
+               $lower_title     = $strtolower($row['title']);\r
+               $lower_text              = $strtolower($row['text']);\r
+               $lower_keywords  = $strtolower($row['keywords']);\r
+\r
+               if ($strlen($row['text']) > 270) {\r
+                       $row['text']  = $substr($row['text'], 0, 268).'...';\r
+               }\r
+\r
+               for ($i=0; $i<$num_words; $i++) {\r
+                       $score += 8 * substr_count($lower_keywords, $lower_words[$i]); /* keywords are weighed more */\r
+                       $score += 4 * substr_count($lower_title,    $lower_words[$i]);    /* titles are weighed more */\r
+                       $score += 1 * substr_count($lower_text,     $lower_words[$i]);\r
+\r
+                       $row['title']     = highlight($row['title'],    $words[$i]);\r
+                       $row['text']      = highlight($row['text'],             $words[$i]);\r
+                       $row['keywords']  = highlight($row['keywords'], $words[$i]);\r
+\r
+               }\r
+               if ($score != 0) {\r
+                       $score += $course_score;\r
+               }\r
+               $row['score'] = $score;\r
+               $search_results[] = $row;\r
+\r
+               $total_score += $score;\r
+       }\r
+\r
+       if ($total_score == 0) {\r
+               $total_score = $course_score;\r
+       }\r
+\r
+       if ((count($search_results) == 0) && $course_score && ($_GET['display_as'] != 'pages')) {\r
+               $num_found++;\r
+       }\r
+\r
+       $num_found += count($search_results);\r
+\r
+       return $search_results;\r
+}\r
+\r
+\r
+// My Courses - All courses you're enrolled in (including hidden)\r
+function get_my_courses($member_id) {\r
+       global $db;\r
+\r
+       $list = array();\r
+\r
+       $sql = "SELECT course_id FROM ".TABLE_PREFIX."course_enrollment WHERE member_id=$member_id AND (approved='y' OR approved='a')";\r
+       $result = mysql_query($sql, $db);\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               $list[] = $row['course_id']; // list contains all the Course IDs\r
+       }\r
+\r
+       return $list;\r
+}\r
+\r
+\r
+// All courses (display hidden too if you're enrolled in it)\r
+function get_all_courses($member_id) {\r
+       global $system_courses, $db;\r
+\r
+       $list = array();\r
+\r
+       $num_courses = count($system_courses);\r
+\r
+       // add all the courses that are not hidden,then find the hidden courses that you're enrolled in and then add that to array\r
+       foreach ($system_courses as $course_id => $course_info) {\r
+               if (!$course_info['hide']) {\r
+                       $list[] = $course_id;\r
+               }\r
+       }\r
+\r
+       // if there aren't any hidden courses:\r
+       if (count($system_courses) == count($list)) {\r
+               return $list;\r
+       }\r
+\r
+       if ($_SESSION['valid_user']) {\r
+               $my_courses = implode(',', get_my_courses($member_id));\r
+               $sql = "SELECT course_id FROM ".TABLE_PREFIX."courses WHERE hide=1 AND course_id IN (0, $my_courses)";\r
+               $result = mysql_query($sql, $db);\r
+               while ($row = mysql_fetch_assoc($result)) {\r
+                       $list[] = $row['course_id'];\r
+               }\r
+       }\r
+       return $list;\r
+}\r
+\r
+function print_search_pages($result) {\r
+       global $count;\r
+\r
+       foreach ($result as $items) {\r
+               uasort($result, 'score_cmp');\r
+\r
+               echo '<h5>' . $count . '. ';\r
+               \r
+               if ($_SESSION['course_id'] != $items['course_id']) {\r
+\r
+                       echo '<a href="bounce.php?course='.$items['course_id'].SEP.'p='.urlencode('content.php?cid='.$items['content_id'].SEP.'words='.$_GET['words']).'">'.$items['title'].'</a> ';\r
+               } else {\r
+                       echo '<a href="'.url_rewrite('content.php?cid='.$items['content_id'].SEP.'words='.$_GET['words']).'">'.$items['title'].'</a> ';\r
+               }\r
+               echo '</h5>'."\n";\r
+\r
+               echo '<p><small>'.$items['text'];\r
+\r
+               echo '<br /><small class="search-info">[<strong>'._AT('keywords').':</strong> ';\r
+               if ($items['keywords']) {\r
+                       echo $items['keywords'];\r
+               } else {\r
+                       echo '<em>'._AT('none').'</em>';\r
+               }\r
+\r
+               echo '. <strong>'._AT('updated').':</strong> ';\r
+               echo AT_date(_AT('inbox_date_format'), $items['last_modified'], AT_DATE_MYSQL_DATETIME);\r
+\r
+               echo ']</small>';\r
+\r
+               echo '</small></p>'."\n";\r
+               $count++;\r
+       }\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/include/lib/test_result_functions.inc.php b/include/lib/test_result_functions.inc.php
new file mode 100644 (file)
index 0000000..079126d
--- /dev/null
@@ -0,0 +1,191 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+// if a valid user, then can come from the DB, otherwise
+// this might come from _POST or even _SESSION
+function get_test_result_id($test_id, &$max_pos) {
+       global $db;
+
+       if ($_SESSION['member_id']) {
+               $sql    = "SELECT result_id, max_pos FROM ".TABLE_PREFIX."tests_results WHERE test_id=$test_id AND member_id={$_SESSION['member_id']} AND status=0";
+       } else if ($_SESSION['test_result_id']) {
+               // guest with on-going test
+               $sql    = "SELECT result_id, max_pos FROM ".TABLE_PREFIX."tests_results WHERE test_id=$test_id AND result_id={$_SESSION['test_result_id']} AND status=0";
+       } else {
+               return 0; // new guest
+       }
+
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)) {
+               $max_pos = $row['max_pos'];
+               return $row['result_id'];
+       }
+
+       return 0;
+}
+
+function init_test_result_questions($test_id, $is_random, $num_questions) {
+       global $db;
+
+       $sql    = "INSERT INTO ".TABLE_PREFIX."tests_results VALUES (NULL, $test_id, {$_SESSION['member_id']}, NOW(), '', 0, NOW(), 0)";
+       $result = mysql_query($sql, $db);
+       $result_id = mysql_insert_id($db);
+
+       if ($is_random) {
+               // Retrieve 'num_questions' question_id randomly from those who are related to this test_id
+
+               $non_required_questions = array();
+               $required_questions     = array();
+
+               $sql    = "SELECT question_id, required FROM ".TABLE_PREFIX."tests_questions_assoc WHERE test_id=$test_id";
+               $result = mysql_query($sql, $db);
+       
+               while ($row = mysql_fetch_assoc($result)) {
+                       if ($row['required'] == 1) {
+                               $required_questions[] = $row['question_id'];
+                       } else {
+                               $non_required_questions[] = $row['question_id'];
+                       }
+               }
+       
+               $num_required = count($required_questions);
+               if ($num_required < max(1, $num_questions)) {
+                       shuffle($non_required_questions);
+                       $required_questions = array_merge($required_questions, array_slice($non_required_questions, 0, $num_questions - $num_required));
+               }
+
+               $random_id_string = implode(',', $required_questions);
+
+               $sql = "SELECT TQ.*, TQA.* FROM ".TABLE_PREFIX."tests_questions TQ INNER JOIN ".TABLE_PREFIX."tests_questions_assoc TQA USING (question_id) WHERE TQ.course_id={$_SESSION['course_id']} AND TQA.test_id=$test_id AND TQA.question_id IN ($random_id_string) ORDER BY TQ.question_id";
+       } else {
+               $sql = "SELECT TQ.*, TQA.* FROM ".TABLE_PREFIX."tests_questions TQ INNER JOIN ".TABLE_PREFIX."tests_questions_assoc TQA USING (question_id) WHERE TQ.course_id={$_SESSION['course_id']} AND TQA.test_id=$test_id ORDER BY TQA.ordering, TQA.question_id";
+       }
+
+       // $sql either gets a random set of questions (if $test_row['random']) ordered by 'question_id'
+       // or the set of all questions for this test (sorted by 'ordering').
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_assoc($result)) {
+               $sql    = "INSERT INTO ".TABLE_PREFIX."tests_answers VALUES ($result_id, {$row['question_id']}, {$_SESSION['member_id']}, '', '', '')";
+               mysql_query($sql, $db);
+       }
+
+       return $result_id;
+}
+
+// $num_questions must be greater than or equal to $row_required['cnt'] + $row_optional['cnt']
+function get_total_weight($tid, $num_questions = null) {
+       global $db;
+    $sql = "SELECT SUM(weight) AS weight, COUNT(*) AS cnt FROM ".TABLE_PREFIX."tests_questions_assoc WHERE test_id=$tid AND required = '1' GROUP BY required";
+    $result = mysql_query($sql, $db);
+    $row_required = mysql_fetch_assoc($result);
+
+    $sql = "SELECT SUM(weight) AS weight, COUNT(*) AS cnt FROM ".TABLE_PREFIX."tests_questions_assoc WHERE test_id=$tid AND required = '0' GROUP BY required";
+    $result = mysql_query($sql, $db);
+       $row_optional = mysql_fetch_assoc($result);
+       
+       $total_weight = 0;
+
+       if ($num_questions == null) {
+               $total_weight = $row_required['weight'] + $row_optional['weight'];
+       } else if ($row_optional['cnt'] > 0) {
+               $total_weight = $row_required['weight'] + ($row_optional['weight'] / $row_optional['cnt']) * min($num_questions - $row_required['cnt'], $row_optional['cnt']);
+       }
+
+       return $total_weight;
+}
+
+// returns T/F whether or not this member can view this test:
+function authenticate_test($tid) {
+       if (authenticate(AT_PRIV_ADMIN, AT_PRIV_RETURN)) {
+               return TRUE;
+       }
+       if (!$_SESSION['enroll']) {
+               return FALSE;
+       }
+       global $db;
+
+       $sql    = "SELECT approved FROM ".TABLE_PREFIX."course_enrollment WHERE member_id=$_SESSION[member_id] AND course_id=$_SESSION[course_id] AND approved='y'";
+       $result = mysql_query($sql, $db);
+       if (!($row = mysql_fetch_assoc($result))) {
+               return FALSE;
+       }
+
+       $sql    = "SELECT group_id FROM ".TABLE_PREFIX."tests_groups WHERE test_id=$tid";
+       $result = mysql_query($sql, $db);
+       if (mysql_num_rows($result) == 0) {
+               // not limited to any group; everyone has access:
+               return TRUE;
+       }
+       while ($row = mysql_fetch_assoc($result)) {
+               $sql     = "SELECT * FROM ".TABLE_PREFIX."groups_members WHERE group_id=$row[group_id] AND member_id=$_SESSION[member_id]";
+               $result2 = mysql_query($sql, $db);
+
+               if ($row2 = mysql_fetch_assoc($result2)) {
+                       return TRUE;
+               }
+       }
+
+       return FALSE;
+}
+
+function print_question_cats($cat_id = 0) {    
+
+       global $db;
+
+       echo '<option value="0"';
+       if ($cat_id == 0) {
+               echo ' selected="selected"';
+       }
+       echo '>'._AT('cats_uncategorized').'</option>' . "\n";
+
+       $sql    = 'SELECT * FROM '.TABLE_PREFIX.'tests_questions_categories WHERE course_id='.$_SESSION['course_id'].' ORDER BY title';
+       $result = mysql_query($sql, $db);
+
+       while ($row = mysql_fetch_array($result)) {
+               echo '<option value="'.$row['category_id'].'"';
+               if ($row['category_id'] == $cat_id) {
+                       echo ' selected="selected"';
+               }
+               echo '>'.$row['title'].'</option>\n';
+       }
+}
+
+function print_VE ($area) {
+?>
+       <script type="text/javascript" language="javascript">
+               document.writeln('<a href="#" onclick="javascript:window.open(\'<?php echo AT_BASE_HREF; ?>tools/tests/form_editor.php?area=<?php echo $area; ?>\',\'newWin1\',\'toolbar=0,location=0,directories=0,status=0,menubar=0,scrollbars=1,resizable=1,copyhistory=0,width=640,height=480\'); return false;" style="cursor: pointer; text-decoration: none" ><?php echo _AT('use_visual_editor'); ?></a>');
+       </script>
+
+<?php
+       //possibley add a <noscript> link to filemanager with target="_blank"
+}
+
+function get_random_outof($test_id, $result_id) {      
+       global $db;
+       $total = 0;
+
+       $sql    = 'SELECT SUM(Q.weight) AS weight FROM '.TABLE_PREFIX.'tests_questions_assoc Q, '.TABLE_PREFIX.'tests_answers A WHERE Q.test_id='.$test_id.' AND Q.question_id=A.question_id AND A.result_id='.$result_id;
+
+       $result = mysql_query($sql, $db);
+
+       if ($row = mysql_fetch_assoc($result)) {
+               return $row['weight'];
+       }
+
+       return 0;
+}
+
+?>
\ No newline at end of file
diff --git a/include/lib/theme_template.inc.php b/include/lib/theme_template.inc.php
new file mode 100644 (file)
index 0000000..44e5954
--- /dev/null
@@ -0,0 +1,15 @@
+<?php\r
+\r
+$theme_template_xml = '<?xml version="1.0" encoding="EN"?>\r
+<!--This is an ATutor Theme Generator document-->\r
+<!--Created from the ATutor Themes Export Generator-->\r
+\r
+<theme>\r
+       <title>{TITLE}</title>\r
+       <version>{VERSION}</version>\r
+       <last_updated>{LAST_UPDATED}</last_updated>\r
+       <extra_info>{EXTRA_INFO}</extra_info>\r
+</theme>\r
+\r
+';\r
+?>
\ No newline at end of file
diff --git a/include/lib/themes.inc.php b/include/lib/themes.inc.php
new file mode 100644 (file)
index 0000000..71a4c59
--- /dev/null
@@ -0,0 +1,296 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+$db;\r
+\r
+/**\r
+* Gets the name of the folder where the theme is stored\r
+* @access  private\r
+* @param   string $theme_dir   the name of the theme\r
+* @return  string                              theme folder\r
+* @author  Shozub Qureshi\r
+*/\r
+//used by preferences.tmpl.php only\r
+function get_folder ($theme_name) {\r
+       global $db;\r
+\r
+       $sql    = "SELECT dir_name FROM ".TABLE_PREFIX."themes WHERE title = '$theme_name'";\r
+       $result = mysql_query($sql, $db);\r
+       $row    = mysql_fetch_assoc($result);\r
+\r
+       return $row['dir_name'];\r
+}\r
+\r
+\r
+/**\r
+* Gets the attributes of the theme from the themes database table\r
+* @access  private\r
+* @param   string $theme_dir   the name of the theme\r
+* @return  array                               theme info\r
+* @author  Shozub Qureshi\r
+*/\r
+function get_themes_info($theme_dir) {\r
+       global $db;\r
+       //Go to db\r
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."themes WHERE dir_name = '$theme_dir'";\r
+       $result = mysql_query($sql, $db);\r
+       \r
+       $info = mysql_fetch_assoc($result);\r
+\r
+       return $info;\r
+}\r
+\r
+/**\r
+* Gets the name of the theme\r
+* @access  private\r
+* @param   string $theme_dir   theme folder\r
+* @return  string                              theme name\r
+* @author  heidi hazelton\r
+*/\r
+function get_theme_name ($theme_dir) {\r
+       global $db;\r
+\r
+       $sql    = "SELECT title FROM ".TABLE_PREFIX."themes WHERE dir_name = '$theme_dir'";\r
+       $result = mysql_query($sql, $db);\r
+       $row    = mysql_fetch_assoc($result);\r
+\r
+       return $row['title'];\r
+}\r
+\r
+/**\r
+* Gets list of enabled themes\r
+* @access  private\r
+* @return  array                               the version of the theme\r
+* @author  Shozub Qureshi\r
+*/\r
+function get_enabled_themes () {\r
+       global $db;\r
+       //Go to db\r
+       $sql    = "SELECT title FROM ".TABLE_PREFIX."themes WHERE status = '1' OR status = '2' ORDER BY title";\r
+       $result = mysql_query($sql, $db);\r
+       \r
+       //Get all theme names into array\r
+       $i = 0;\r
+       while ($row = mysql_fetch_array($result)) {\r
+               $themes[$i] = $row['title'];\r
+               $i++;\r
+       }\r
+       \r
+       return $themes;\r
+}\r
+\r
+/**\r
+* Gets number of enabled themes\r
+* @access  private\r
+* @return  int                         the number of enabled themes\r
+* @author  Shozub Qureshi\r
+*/\r
+function num_enabled_themes () {\r
+       global $db;\r
+       //Go to db\r
+       $sql    = "SELECT title FROM ".TABLE_PREFIX."themes WHERE status = '1' OR status = '2'";\r
+       $result = mysql_query($sql, $db);\r
+               \r
+       return mysql_num_rows($result);\r
+}\r
+\r
+/**\r
+* Gets list of disabled themes\r
+* @access  private\r
+* @return  array                               the version of the theme\r
+* @author  Shozub Qureshi\r
+*/\r
+function get_disabled_themes () {\r
+       global $db;\r
+       //Go to db\r
+       $sql    = "SELECT title FROM ".TABLE_PREFIX."themes WHERE status = '0'";\r
+       $result = mysql_query($sql, $db);\r
+       \r
+       //Get all theme names into array\r
+       $i = 0;\r
+       while ($row = mysql_fetch_array($result)) {\r
+               $themes[$i] = $row['title'];\r
+               $i++;\r
+       }\r
+       \r
+       return $themes;\r
+}\r
+\r
+/**\r
+* Gets list of all currently installed themes\r
+* @access  private\r
+* @return  array                               the version of the theme\r
+* @author  Shozub Qureshi\r
+*/\r
+function get_all_themes () {\r
+       global $db;\r
+       \r
+       // The ordering is as follow. The default theme followed by ASC ordering of rest of themes\r
+       \r
+       // Assert, one of them must be a default\r
+       $result = mysql_query('SELECT title FROM ' . TABLE_PREFIX . 'themes WHERE status = 2', $db);\r
+       $row = mysql_fetch_assoc($result);\r
+       $first_one = $row['title'];\r
+       \r
+       $themes[$i] = $first_one;\r
+       \r
+       // Go to db\r
+       $sql    = "SELECT title FROM " . TABLE_PREFIX . "themes WHERE title != '$first_one' ORDER BY title ASC";\r
+       $result = mysql_query($sql, $db);\r
+       \r
+       // Get all theme names into array\r
+       $i = 1;\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               $themes[$i] = $row['title'];\r
+               $i++;\r
+       }\r
+       \r
+       return $themes;\r
+}\r
+\r
+function enable_theme ($theme_dir) {\r
+       global $msg, $db;\r
+\r
+       if ($_SESSION['prefs']['PREF_THEME'] != $theme_dir) {\r
+               $sql = "UPDATE ".TABLE_PREFIX."themes SET status = '1' WHERE dir_name = '$theme_dir'";\r
+               $result = mysql_query($sql, $db);\r
+               write_to_log(AT_ADMIN_LOG_UPDATE, 'themes', mysql_affected_rows($db), $sql);\r
+       } \r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+}\r
+\r
+function disable_theme ($theme_dir) {\r
+       global $msg, $db;\r
+\r
+       $sql    = "SELECT status FROM ".TABLE_PREFIX."themes WHERE dir_name = '$theme_dir'";\r
+       $result = mysql_query ($sql, $db);\r
+       $row    = mysql_fetch_array($result);\r
+       $status = intval($row['status']);\r
+\r
+       //If default theme, then it cannot be disabled\r
+       if ($status == 2) {\r
+               $msg->addError('THEME_NOT_DISABLED');\r
+               return;\r
+       } else {\r
+               $sql    = "UPDATE ".TABLE_PREFIX."themes SET status = '0' WHERE dir_name = '$theme_dir'";\r
+               $result = mysql_query($sql, $db);\r
+\r
+               $feedback = array('THEME_DISABLED', $theme_dir);\r
+               $msg->addFeedback($feedback);\r
+\r
+               write_to_log(AT_ADMIN_LOG_UPDATE, 'themes', mysql_affected_rows($db), $sql);\r
+       }\r
+}\r
+\r
+function set_theme_as_default ($theme_dir) {\r
+       global $msg, $db;\r
+       \r
+       //unset current default theme\r
+       $sql    = "UPDATE ".TABLE_PREFIX."themes SET status = '1' WHERE status = '2'";\r
+       $result = mysql_query($sql, $db);\r
+       \r
+       write_to_log(AT_ADMIN_LOG_UPDATE, 'themes', mysql_affected_rows($db), $sql);\r
+\r
+       //set to default\r
+       $sql    = "UPDATE ".TABLE_PREFIX."themes SET status = '2' WHERE dir_name = '$theme_dir'";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       $feedback = array('THEME_DEFAULT', $theme_dir);\r
+       $msg->addFeedback($feedback);\r
+       $_SESSION['prefs']['PREF_THEME'] = $theme_dir;\r
+\r
+       write_to_log(AT_ADMIN_LOG_UPDATE, 'themes', mysql_affected_rows($db), $sql);\r
+}\r
+\r
+function delete_theme ($theme_dir) {\r
+       global $msg, $db;\r
+\r
+       //check status\r
+       $sql    = "SELECT status FROM ".TABLE_PREFIX."themes WHERE dir_name='$theme_dir'";\r
+       $result = mysql_query ($sql, $db);\r
+       $row    = mysql_fetch_assoc($result);\r
+       $status = intval($row['status']);\r
+\r
+       //can't delete original default or current default theme\r
+       if (($theme_dir == 'default') || ($status == 2)) {\r
+               $msg->addError('THEME_NOT_DELETED');\r
+               return FALSE;\r
+\r
+       } else {        //disable, clear directory and delete theme from db\r
+\r
+               require (AT_INCLUDE_PATH . 'lib/filemanager.inc.php'); /* for clr_dir() */\r
+               if ($status != 0) {\r
+                       disable_theme($theme_dir);\r
+                       $msg->deleteFeedback('THEME_DISABLED');\r
+               }\r
+\r
+               $dir = '../../themes/' . $theme_dir;\r
+               //chmod($dir, 0777);\r
+               @clr_dir($dir);\r
+\r
+               $sql1    = "DELETE FROM ".TABLE_PREFIX."themes WHERE dir_name = '$theme_dir'";\r
+               $result1 = mysql_query ($sql1, $db);\r
+\r
+               write_to_log(AT_ADMIN_LOG_DELETE, 'themes', mysql_affected_rows($db), $sql);\r
+\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+               return TRUE;\r
+       }\r
+}\r
+\r
+function export_theme($theme_dir) {\r
+       require(AT_INCLUDE_PATH.'classes/zipfile.class.php');                           /* for zipfile */\r
+       require(AT_INCLUDE_PATH.'classes/XML/XML_HTMLSax/XML_HTMLSax.php');     /* for XML_HTMLSax */\r
+       require('theme_template.inc.php');                                                                      /* for theme XML templates */ \r
+       \r
+       global $db;\r
+       \r
+       //identify current theme and then searches db for relavent info\r
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."themes WHERE dir_name = '$theme_dir'";\r
+       $result = mysql_query($sql, $db);\r
+       $row    = mysql_fetch_assoc($result);\r
+\r
+       $dir          = $row['dir_name'] . '/';\r
+       $title        = $row['title'];\r
+       $version      = $row['version'];\r
+       $last_updated = $row['last_updated'];\r
+       $extra_info   = $row['extra_info'];\r
+\r
+\r
+\r
+       //generate 'theme_info.xml' file based on info  \r
+       $info_xml = str_replace(array('{TITLE}', '{VERSION}', '{LAST_UPDATED}', '{EXTRA_INFO}'), \r
+                                                       array($title, $version, $last_updated, $extra_info),\r
+                                           $theme_template_xml);\r
+\r
+       //zip together all the contents of the folder along with the XML file\r
+       $zipfile = new zipfile();\r
+       $zipfile->create_dir($dir);\r
+\r
+       //update installation folder\r
+       $dir1 = '../../themes/' . $dir;\r
+\r
+       $zipfile->add_file($info_xml, $dir . 'theme_info.xml');\r
+\r
+       /* zip other required files */\r
+       $zipfile->add_dir($dir1, $dir);\r
+\r
+       /*close & send*/\r
+       $zipfile->close();\r
+       //Name the Zip file and sends to user for download\r
+       $zipfile->send_file(str_replace(array(' ', ':'), '_', $title));\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/include/lib/tinymce.inc.php b/include/lib/tinymce.inc.php
new file mode 100644 (file)
index 0000000..e77c3ff
--- /dev/null
@@ -0,0 +1,87 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+function load_editor($name = FALSE, $mode="textareas") {\r
+       global $_base_path, $content_base_href;\r
+\r
+        if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) { \r
+               $course_base_href = 'get.php/'; \r
+       } else {  \r
+               $course_base_href = 'content/' . $_SESSION['course_id'] . '/'; \r
+       }\r
+\r
+// Note: Some tinymce buttons are removed due to lack of accessibility for disabled.\r
+// They are:\r
+//New Document: newdocument\r
+//Insert Time: inserttime\r
+//Insert Date: insertdate\r
+//Preview: preview\r
+//toggle guidelines: visualaid\r
+//spellcheck: iespell\r
+//embed media: media\r
+//print: print\r
+//Insert Layer: insertlayer\r
+//move forward: moveforward\r
+//move backward: movebackward\r
+//toggle absolute positioning: absolute\r
+//citation: cite\r
+//deletion: del\r
+//insertion: ins\r
+//visual control characters on/off: visualchars\r
+//insert non-breaking space character: nonbreaking\r
+//insert predefined template: template\r
+//insert page break: pagebreak\r
+\r
+       echo '\r
+<script language="javascript" type="text/javascript" src="'.AT_BASE_HREF.'jscripts/tiny_mce/tiny_mce.js"></script>\r
+<script language="javascript" type="text/javascript">\r
+tinyMCE.init({ \r
+';\r
+       if ($name) {\r
+               echo '  mode : "exact",';\r
+               echo '  elements : "'.$name.'",';\r
+       } else {\r
+               echo '  mode : "'.$mode.'",';\r
+       }       \r
+       echo 'theme : "advanced",\r
+       relative_urls : true,\r
+       convert_urls : true,\r
+       convert_fonts_to_spans : true,\r
+       accessibility_warnings : true,\r
+       entity_encoding : "raw",\r
+       accessibility_focus : true,\r
+       plugins : "acheck, table,safari,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template",\r
+\r
+       // Theme options\r
+       theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,styleselect,formatselect,fontselect,fontsizeselect",\r
+       theme_advanced_buttons2 : "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,forecolor,backcolor",\r
+       theme_advanced_buttons3 : "tablecontrols,|,hr,removeformat,|,sub,sup,|,charmap,emotions,advhr,|,ltr,rtl,|,fullscreen",\r
+       theme_advanced_buttons4 : "styleprops,|,abbr,acronym,attribs,|,acheck",\r
+       theme_advanced_toolbar_location : "top",\r
+       theme_advanced_toolbar_align : "left",\r
+       theme_advanced_path_location : "bottom",\r
+       theme_advanced_resizing : true,\r
+       remove_linebreaks: false,\r
+       apply_source_formatting: true, //<-- not working sad\r
+\r
+       plugin_insertdate_dateFormat : "%Y-%m-%d",\r
+       plugin_insertdate_timeFormat : "%H:%M:%S",\r
+       extended_valid_elements : "a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]",\r
+       document_base_url: "'.AT_BASE_HREF.$course_base_href.$content_base_href.'"\r
+       });';\r
+       echo '</script>';\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/include/lib/tracker.inc.php b/include/lib/tracker.inc.php
new file mode 100644 (file)
index 0000000..c700ad4
--- /dev/null
@@ -0,0 +1,274 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+/////////////////////////////
+//Display the g_data bar chart for the member selected
+//get the translations to the gdata numbers first
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+// NOTE: this script should not be altered. its use will soon be deprecated.
+
+
+$sql5 = "select * from ".TABLE_PREFIX."g_refs";
+$result = mysql_query($sql5, $db);
+$refs = array();
+while ($row= mysql_fetch_array($result)) {
+       $refs[$row['g_id']] = $row['reference'];
+}
+/* this if-statement doesn't make any sense: */
+if ($_GET['member_id']){
+       $this_member = $_GET['member_id']; 
+} else {
+       $this_member=$_SESSION['member_id'];
+       if(!authenticate(AT_PRIV_ADMIN, AT_PRIV_RETURN)){
+               $_GET['member_id'] = $_SESSION['member_id'];
+       }
+}
+
+$sql2 = "SELECT        g, count(*) AS cnt
+               FROM ".TABLE_PREFIX."g_click_data
+               WHERE member_id=$this_member AND course_id='$_SESSION[course_id]'
+               GROUP BY g
+               ORDER BY cnt DESC";
+
+if ($result7 = mysql_query($sql2, $db)) {
+       while($row2 = mysql_fetch_array($result7)) {
+                       $nav_total = ($nav_total + $row2["cnt"]);
+       }
+}
+
+if (($result = mysql_query($sql2, $db)) && $_GET['member_id']) {
+       echo '<h3>'._AT('nav_tendencies').' '.$this_user[$this_member].'</h3>';
+
+       echo '<table class="data static" rules="cols" summary="">';
+       echo '<thead>';
+       echo '<tr>';
+               echo '<th>' . _AT('access_method') . '</th>';
+               echo '<th>' . _AT('count') . '</th>';
+       echo '</tr>';
+       echo '</thead>';
+
+       echo '<tbody>';
+       while($row = mysql_fetch_array($result)){
+               echo '<tr>';
+               echo '<td>';
+               foreach($refs AS $key => $value){
+                       if($key==$row["g"]){
+                               echo _AT($value);
+                       }
+               }
+               echo '</td>';
+               
+               echo '<td><img src="images/bar.gif" height="12" width="'.((($row["cnt"]/$nav_total)*100)*3).'" alt="" />' . $row["cnt"] . '</td>';
+               echo '</tr>';
+       }
+       echo '</tbody>';
+       echo '</table>';
+       echo '<br /><br />';
+
+
+////////////////////////////
+//Show the member's click path
+       echo '<a name="access"></a>';
+       echo '<h3>'._AT('nav_path').' '.$this_user[$this_member].'</h3>';
+       echo '<table class="data static" rules="cols" summary="">';
+       echo '<thead>';
+       echo '<tr>';
+               echo '<th>' . _AT('access_method') . '</th>';
+               echo '<th>' . _AT('page_viewed')   . '</th>';
+               echo '<th>' . _AT('duration')      . '</th>';
+               echo '<th>' . _AT('date')          . '</th>';
+       echo '</tr>';
+       echo '</thead>';
+
+       if (authenticate(AT_PRIV_ADMIN, AT_PRIV_RETURN)) {
+               $sql = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."g_click_data WHERE course_id=$_SESSION[course_id] AND member_id='$_GET[member_id]'";
+       }
+       else {
+               $sql = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."g_click_data WHERE course_id=$_SESSION[course_id] AND member_id='$_SESSION[member_id]'";
+       }
+       
+       //create the paginator
+       if (!$result = mysql_query($sql, $db)) {
+               echo _AT('page_error');
+       } else {
+               $num_rows = mysql_fetch_assoc($result);
+               
+               $sql3="SELECT 
+                               ".TABLE_PREFIX."content.title,
+                               ".TABLE_PREFIX."content.content_id,
+                               ".TABLE_PREFIX."g_click_data.to_cid,
+                               ".TABLE_PREFIX."g_click_data.g,
+                               ".TABLE_PREFIX."g_click_data.duration,
+                               ".TABLE_PREFIX."g_click_data.timestamp AS t
+                       FROM
+                               ".TABLE_PREFIX."content, 
+                               ".TABLE_PREFIX."g_click_data
+                       WHERE 
+                               ".TABLE_PREFIX."content.content_id=".TABLE_PREFIX."g_click_data.to_cid
+                               AND
+                               ".TABLE_PREFIX."g_click_data.member_id=$this_member
+                               AND
+                               ".TABLE_PREFIX."g_click_data.course_id=$_SESSION[course_id]";
+               
+               $sql4="select
+                               ".TABLE_PREFIX."g_click_data.g,
+                               ".TABLE_PREFIX."g_click_data.member_id, 
+                               ".TABLE_PREFIX."g_click_data.to_cid, 
+                               ".TABLE_PREFIX."g_click_data.duration,
+                               ".TABLE_PREFIX."g_click_data.timestamp AS t
+                       from 
+                               ".TABLE_PREFIX."g_click_data 
+                       where 
+                               ".TABLE_PREFIX."g_click_data.to_cid=0 
+                               AND
+                               ".TABLE_PREFIX."g_click_data.member_id=$this_member
+                               AND
+                               ".TABLE_PREFIX."g_click_data.course_id=$_SESSION[course_id]
+                       order by
+                               t DESC";
+               
+               if ($result=mysql_query($sql3, $db)) {
+                       while($row=mysql_fetch_assoc($result)){
+                               $this_data[$row['t']]= $row;
+                               $page_rows++;
+                       }
+               }
+               //$num_records = count($this_data);
+               if ($result2 = mysql_query($sql4, $db)) {
+                       while ($row=mysql_fetch_assoc($result2)) {
+                               $row['title'] = $refs[$row['g']];
+                               $this_data[$row['t']] = $row;
+                               $tool_rows++;
+                       }
+               }
+                               
+               $num_records = ($num_records+count($this_data));        
+               //$num_records = $num_rows['cnt'];
+
+               $num_per_page = 30;
+               if (!$_GET['page']) {
+                       $page = 1;
+               } else {
+                       $page = intval($_GET['page']);
+               }
+               $start = ($page-1)*$num_per_page;
+               $num_pages = ceil($num_records/$num_per_page);
+               echo '<tbody>';
+               echo '<tr>';
+               echo '<td>'._AT('page').': ';
+                       for ($i=1; $i<=$num_pages; $i++) {
+                               if ($i == $page) {
+                                       echo $i;
+                               } else {
+                                       echo '<a href="' . $_SERVER['PHP_SELF'] . '?coverage=raw' . SEP . 'member_id=' . $_GET["member_id"] . SEP . 'page=' . $i . '#access">' . $i . '</a>';
+                               }
+
+                               if ($i<$num_pages){
+                                       echo ' <span class="spacer">|</span> ';
+                               }
+                       }
+               echo '</td>';
+               echo '</tr>';
+       }
+
+if($this_data){
+       ksort($this_data);
+       $current = current($this_data);
+       $pre_time = $current[t];
+       $q = '';
+       foreach ($this_data AS $key => $value) {
+               $this_page = $p;
+               if ($q >= $start && $q < ($start+$num_per_page)) {
+                       $diff = $value['duration']; // - $pre_time);
+                       $that_g = $refs[$value['g']];
+       
+                       if ($that_g != '') {
+                               echo '<tr>';
+                               if ($that_g == _AT('g_session_start')) {
+                                       echo '<td>';
+                               } 
+                               else {
+                                       echo '<td>';
+                               }
+
+                               echo _AT($that_g);
+                               echo '</td>';
+
+                               if ($that_g == _AT('g_session_start')) {
+                                       echo '<td>';
+                               } else {
+                                       echo '<td>';
+                               }
+
+                               if (substr($value['title'], 0 ,2) == "g_" ) {
+                                       echo _AT($value['title']);
+                               }
+                               else {
+                                       echo $value['title'];
+                               }
+                               
+                               echo '</td>';
+                               if ($that_g == _AT('g_session_start')) {
+                                       echo '<td>';
+                               }else{
+                                       echo '<td>';
+                               }
+       
+                               if ($diff > 60*45) {
+                                       /* time out */
+                                       echo _AT('na');
+                                       $session_time='';
+                               } else {
+                                       $this_time=date('i:s', $diff);
+                                       echo ' '.$this_time;
+                                       $session_time=($session_time+$diff);
+                               }
+                               $remainder = $diff / 60;
+                               echo '</td>';
+
+                               if ($that_g == _AT('g_session_start')) {
+                                       echo '<td>';
+                               } else {
+                                       echo '<td>';
+                               }
+
+                               echo $that_date;
+                               echo '</td>';
+                               echo '</tr>';
+                       }
+                       
+                       }
+
+               $that_date=date("M-j-y g:i:s:a", $value[t]);
+               $that_g=$refs[$value['g']];
+               $that_title=$value['title']."&nbsp;";
+               $pre_time = $value['t'];
+               $q++;
+               }
+}
+       echo '<tr>';
+       echo '<td>';
+
+       if ($start_date>0 && $start_date!=$pre_time) {
+               echo _AT('g_session_start').' '.date("F j, Y,  g:i a", $start_date).' '._AT('session_end').' '.date("F j, Y,  g:i a", $pre_time).'     ('._AT('duration').':'.date('i \m\i\n s \s\e\c',($pre_time-$start_date)).')';
+       }
+
+       else {
+               //echo _AT('invalid_session');
+       }
+       echo '</td>';
+       echo '</tr>';
+       echo '</tbody>';
+       echo '</table>';
+}
+?>
\ No newline at end of file
diff --git a/include/lib/tracker2.inc.php b/include/lib/tracker2.inc.php
new file mode 100644 (file)
index 0000000..3e43818
--- /dev/null
@@ -0,0 +1,131 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+// NOTE: this script should not be altered. its use will soon be deprecated.
+
+
+//how many content pages are in this course
+$sql25 = "SELECT content_id from ".TABLE_PREFIX."content where course_id = $_SESSION[course_id]";
+$result29 = mysql_query($sql25, $db);
+$num_rows_total = mysql_num_rows($result29);
+//get the title for each content_id
+$sql7 = "select
+                       C.title,
+                       C.content_id
+
+               from
+                       ".TABLE_PREFIX."content C
+               where
+                       course_id='$_SESSION[course_id]'";
+       if(!$result7 = mysql_query($sql7, $db)){
+               echo AT_ERRORS_GENERAL;
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+       $title_refs = array();
+       while ($row= mysql_fetch_array($result7)) {
+               $title_refs[$row['content_id']] = $row['title'];
+
+       }
+
+$sql2 = "SELECT * from ".TABLE_PREFIX."g_click_data where member_id = $_SESSION[member_id] AND course_id = $_SESSION[course_id]";
+$result28 = mysql_query($sql2, $db);
+
+echo '<br /><h3>'._AT('tracker_summary_read', $this_user[$_SESSION["member_id"]]).'</h3>';
+echo '<a href="'.$_SERVER['PHP_SELF'].'#not_viewed"><img src="images/clr.gif" border="0" alt="'._AT('tracker_not_viewed').'"/></a>';
+
+echo '<table class="data static" rules="cols" summary="">';
+echo '<thead>';
+echo '<tr>';
+
+echo '<th>' . _AT('page')         . '</th>';
+echo '<th>' . _AT('visits')       . '</th>';
+echo '<th>' . _AT('duration_sec') . '</th>';
+echo '</tr>';
+echo '</thead>';
+
+
+while ($row2= mysql_fetch_array($result28)){
+       $duration[$row2['to_cid']] = ($duration[$row2['to_cid']] + $row2['duration']);
+       $visits[$row2['to_cid']] = ($visits[$row2['to_cid']] +1);
+}
+
+$sql= "SELECT DISTINCT to_cid from ".TABLE_PREFIX."g_click_data where member_id = $_SESSION[member_id] AND course_id = $_SESSION[course_id]";
+$result27 = mysql_query($sql, $db);
+$viewed_page = array();
+
+
+echo '<tbody>';
+while ($row = mysql_fetch_array($result27)) {
+       if ($row['to_cid']) {
+               $viewed_pages[$row['to_cid']] = $title_refs[$row['to_cid']];
+               $num_rows_read = ($num_rows_read +1);
+               
+               if ($title_refs[$row['to_cid']] !='') {
+                       echo '<tr>';
+                       echo '<td>';
+                               echo '<a href="./index.php?cid='.$row['to_cid'].'">';
+                               echo $title_refs[$row['to_cid']].'</a></td><td align="center" class="row1"> '.$visits[$row['to_cid']].' </td><td align="center" class="row1"> '.number_format($duration[$row['to_cid']]);
+                       echo '</td>';
+                       echo '</tr>';
+               }
+       }
+}
+
+if(count($viewed_pages) > 0){
+       foreach($viewed_pages as $key1 => $refs1){
+               $viewed_page_keys[$key1] = $key1;
+       }
+       foreach($title_refs as $key => $ref){
+               if(!in_array($key, $viewed_page_keys)){
+                               $missed_pages .= ' <li><a href="./index.php?cid='.$key.SEP.'g=36">'.$ref.'</a></li>';
+               }
+       }
+}else{
+       echo '<tr><td>'._AT('tracker_none_viewed').'</td></tr>';
+}
+
+if ($num_rows_read < 1) {
+       $num_rows_read = 0;
+}
+
+echo '<tr>';
+echo '<td>'._AT('tracker_pages_total', $num_rows_total, $num_rows_read).'</td>';
+
+$per_cent = 0;
+if ($num_rows_total) {
+       $per_cent = number_format((($num_rows_read/$num_rows_total)*100),1);
+
+}
+echo '<td>' . _AT('tracker_percent_read',$per_cent) . '%</td>';
+echo '</tr>';
+echo '</tbody>';
+echo '</table>';
+
+echo '<a name="not_viewed"></a>';
+
+echo '<br /><hr /><br /><h3>'._AT('unvisited_pages').'</h3>';
+echo '<div class="results">';
+
+// show which pages have not been viewed yet
+if ($missed_pages) {
+       echo '<ul>';
+       echo $missed_pages;
+       echo '</ul>';
+} else {
+       echo _AT('tracking_all_page_viewed');
+}
+
+echo '</div>';
+?>
\ No newline at end of file
diff --git a/include/lib/tracker_stats.inc.php b/include/lib/tracker_stats.inc.php
new file mode 100644 (file)
index 0000000..cbcd31c
--- /dev/null
@@ -0,0 +1,487 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+/////////////////////////////
+//Display the g_data bar chart for the member selected
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+// NOTE: this script should not be altered. its use will soon be deprecated.
+
+
+//get the summary data for all pages
+
+//get the translations for the g numbers
+$to_cid = $_GET['to_cid'];
+$stats = $_GET['stats']; 
+$g_id = $_GET['g_id'];
+$sql5 = "select * from ".TABLE_PREFIX."g_refs";
+       $result = mysql_query($sql5, $db);
+       $refs = array();
+       while ($row= mysql_fetch_array($result)) {
+               $refs[$row['g_id']] = $row['reference'];
+       }
+
+
+//get the g translation for non content pages
+$sql8= "select
+               G.g,
+               R.reference,
+               R.g_id
+       from
+               ".TABLE_PREFIX."g_click_data G,
+               ".TABLE_PREFIX."g_refs R
+       where
+               G.g = R.g_id
+               AND
+               course_id='$_SESSION[course_id]'";
+
+       if(!$result8 = mysql_query($sql8, $db)){
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }else{
+
+               $title_refs = array();
+               while ($row= mysql_fetch_assoc($result8)) {
+                       $title_refs2[$row['g']] = $row['reference'];
+
+               }
+       }
+//get the translations for the content id numbers
+$sql7 = "select
+                       C.title,
+                       C.content_id
+
+               from
+                       ".TABLE_PREFIX."content C
+
+               where
+                       course_id='$_SESSION[course_id]'";
+       if(!$result7 = mysql_query($sql7, $db)){
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+       $title_refs = array();
+       while ($row= mysql_fetch_array($result7)) {
+               $title_refs[$row['content_id']] = $row['title'];
+
+       }
+
+//get tools ATutor tools traffic
+
+$sql9="SELECT 
+                       G.to_cid,
+                       G.g,
+                       R.g_id,
+                       R.reference
+
+               from
+                       ".TABLE_PREFIX."g_click_data G,
+                       ".TABLE_PREFIX."g_refs R
+               where
+                       G.to_cid = 0
+                       AND
+                       course_id='$_SESSION[course_id]'";
+       $title_tools = array();
+       $result9 = mysql_query($sql9, $db);
+       while ($row= mysql_fetch_array($result9)) {
+                       if($row['g'] == $row['g_id']){
+                               $title_tools[$row['g_id']] = $row['reference'];
+                               $tool_grefs[$row['g_id']] = $row['g_id'];
+                               $gcount[$row['g_id']]++;
+                       }
+       }
+$sql10 = "select count(g) from ".TABLE_PREFIX."g_click_data where course_id='$_SESSION[course_id]' GROUP BY g";
+$result10 = mysql_query($sql10, $db);
+while($row=mysql_fetch_array($result10)){
+       $thiscount[]=$row;
+
+}
+
+if($_GET['stats']="summary" && !$to_cid &&!$_GET['csv'] && !$_GET['g_id']){
+
+       $sql12= "select to_cid, g, AVG(duration) AS t, count(g) as c from ".TABLE_PREFIX."g_click_data where to_cid='0' AND course_id='$_SESSION[course_id]' GROUP BY g";
+
+       if($result12=mysql_query($sql12, $db)){
+               while($row=mysql_fetch_array($result12)){
+                       if($row['g']){
+                               $nav_total = ($nav_total + $row['c']);
+                       }
+                       if($row['to_cid']==0){
+                               $that_time[$row['g']]= $row['t'];
+                       }
+               }
+       }else{
+               echo _AT('unknown_error');
+       }
+?>
+       <br />
+       <a name="show_pages"></a>
+       <h3><?php  echo  _AT('tool_summary'); ?></h3>
+       <table class="data static" rules="cols" summary="">
+       <thead>
+       <tr>
+               <th><?php echo _AT('at_tools');     ?></th>
+               <th><?php echo _AT('hit_count');    ?></th>
+               <th><?php echo _AT('avg_duration'); ?></th>
+               <th><?php echo _AT('details');      ?></th>
+       </tr>
+       </thead>
+
+       <tbody>
+<?php
+               //this array needs to be created from the database 
+               //(eventually add new field to g_refs table called "timed" values true/false
+               $timed_tools=array(14=>14, 15=>15, 16=>16, 17=>17, 18=>18, 20=>20, 21=>21, 23=>23, 27=>27, 28=>28, 29=>29, 31=>31, 32=>32, 35=>35);
+               
+               foreach($title_tools as $key=>$value) {
+                       $tool_names[$key] = $gcount[$key];
+               }
+
+               if (is_array($tool_names)) {
+                       arsort($tool_names);
+               
+                       foreach($tool_names as $key=>$value) {
+                               echo '<tr>';
+                                       echo '<td>' . _AT($title_tools[$key]) . '</td>';
+                                       echo '<td><img src="images/bar.gif" height="12" width="' . ((($gcount[$key]/$nav_total)*100)*2) . '" alt="" />' . $value . '</td>';
+
+                               $that_avgtime='';
+                               if($timed_tools[$key]==$key) {  
+                                       $that_avgtime=number_format((number_format($that_time[$key], 1  )/$gcount[$key]),1);
+                               }
+
+                                       echo '<td>';
+                                       if($that_avgtime) {
+                                               echo $that_avgtime;
+                                       } else {
+                                               echo _AT('na');
+                                       }
+                                       echo '</td>';
+
+                                       echo '<td><a href="' . $_SERVER['PHP_SELF'] . '?g_id=' . $key . '#show_pages">' . _AT('details') . '</a></td>';
+                               echo '</tr>';
+                       }
+               }
+?>
+       </tbody>
+       </table>
+
+       <br /><br />
+
+       <h3><?php  echo  _AT('page_stats'); ?></h3>
+       <table class="data static" rules="cols" summary="">
+       <thead>
+       <tr>
+               <th><?php echo _AT('page_title');   ?></th>
+               <th><?php echo _AT('hit_count');    ?></th>
+               <th><?php echo _AT('avg_duration'); ?></th>
+               <th><?php echo _AT('details');      ?></th>
+       </tr>
+       </thead>
+<?php
+       //get content page traffic
+       $sql6 = "SELECT G.to_cid, count(*) AS pages, G.g
+               FROM ".TABLE_PREFIX."g_click_data G
+               WHERE G.to_cid <> 0     AND     course_id='$_SESSION[course_id]'
+               GROUP BY G.to_cid";
+
+       $result6 = mysql_query($sql6, $db);
+
+       if(!$result6) {
+               echo "query failed";
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+       
+       $sql11 = "SELECT to_cid, AVG(duration) AS t FROM ".TABLE_PREFIX."g_click_data WHERE course_id='$_SESSION[course_id]' GROUP BY to_cid";
+       $result11 = mysql_query($sql11, $db);
+
+       if ($result11) {
+               while($row = mysql_fetch_array($result11)) {
+                       $this_time[$row['to_cid']]= $row['t'];
+               }
+       } 
+       
+       else {
+               echo _AT('unknown_error');
+       }
+
+       $max_bar_width='180';
+       $result9 = mysql_query($sql6, $db);
+       
+       while($row = mysql_fetch_array($result9)) {
+               $total_hits=($total_hits + $row["pages"]);
+       }
+       if($total_hits) {
+               $bar_factor = ($max_bar_width/$total_hits);
+       }
+
+       if ($result6 = mysql_query($sql6, $db)) {
+
+               echo '<tbody>';
+
+               while($row = mysql_fetch_array($result6)) {
+                       if($title_refs[$row['to_cid']] != '') {
+                               echo '<tr>';
+                                       echo '<td>' . $title_refs[$row['to_cid']] . '</td>';
+                                       echo '<td><img src="images/bar.gif" height="12" width="' . ($row["pages"]*$bar_factor) . '" alt="" />' . $row["pages"] . '</td>';
+
+                                       $this_avgtime=(number_format($this_time[$row['to_cid']], 1  )/$row["pages"]);
+
+                                       echo '<td>' . number_format($this_avgtime, 1) . '</td>';
+                                       echo '<td><a href="' . $_SERVER['PHP_SELF'] . '?stats=details' . SEP . 'to_cid=' . $row['to_cid'] . '#show_pages">' . _AT('details') . '</a></td>';
+                               echo '</tr>';
+
+                       }
+               }
+               echo '<tbody>';
+       }
+
+       echo '</table>';
+}  //end summary
+
+//get the rawdata for a single page
+if(authenticate(AT_PRIV_ADMIN, AT_PRIV_RETURN)){
+       $sql3="select
+               ".TABLE_PREFIX."content.title,
+               ".TABLE_PREFIX."content.content_id,
+               ".TABLE_PREFIX."g_click_data.member_id as m,
+               ".TABLE_PREFIX."g_click_data.to_cid,
+               ".TABLE_PREFIX."g_click_data.g,
+               ".TABLE_PREFIX."g_click_data.timestamp AS t
+       from
+               ".TABLE_PREFIX."content,
+               ".TABLE_PREFIX."g_click_data
+       where
+               ".TABLE_PREFIX."content.content_id=".TABLE_PREFIX."g_click_data.to_cid
+               AND
+               ".TABLE_PREFIX."g_click_data.to_cid=$to_cid
+               AND
+               ".TABLE_PREFIX."g_click_data.course_id=$_SESSION[course_id]";
+
+
+
+       $result3=mysql_query($sql3, $db);
+       if($result3){
+               while($row=mysql_fetch_array($result3)){
+                       $this_data[$row["t"]]= $row;
+                       $this_user[$row["t"]]= $row['m'];
+               }
+               ksort($this_data);
+               $current = current($this_data);
+               $pre_time = $current[t];
+
+       }
+
+}
+
+
+if($to_cid) {
+       ?>
+       <a name="show_pages"></a>
+       <p>
+               [<a href="<?php echo $_SERVER['PHP_SELF'].'?stats=summary';?>#show_pages"><?php echo _AT('back_to_summary'); ?></a>]
+       </p>
+
+       <h3><?php echo _AT('access_stats'); ?>: <?php echo $current['title']; ?></h3>
+
+
+       <table class="data static" rules="cols" summary="">
+       <thead>
+       <tr>
+               <th scope="col"><?php echo _AT('access_method'); ?></th>
+               <th scope="col"><?php echo _AT('count'); ?></th>
+       </tr>
+       </thead>
+
+<?php
+       //get the number of clicks per g
+       $sql2 = "select
+                       g,
+                       count(*) AS cnt
+               from
+                       ".TABLE_PREFIX."g_click_data
+               where
+                       to_cid=$to_cid
+                       AND
+                       course_id='$_SESSION[course_id]'
+               group by
+                        g";
+       
+       if($result2 = mysql_query($sql2, $db)){
+               echo '<tbody>';
+               while($row = mysql_fetch_array($result2)){
+                       echo '<tr>';
+                       echo '<td>';
+                       foreach($refs AS $key => $value){
+                               if($key==$row["g"]){
+                                       echo _AT($value);
+                               }
+                       }
+                       echo '</td>';
+                       echo '<td><img src="images/bar.gif" height="12" width="' . ($row["cnt"]*2) . '" alt="" />' . $row["cnt"] . '</td>';
+                       echo '</tr>';
+               }
+
+       }
+       echo '</tbody>';
+       echo '</table>';
+       echo '<br />';
+
+       //////////////
+       $sql4="select
+               ".TABLE_PREFIX."g_click_data.g,
+               ".TABLE_PREFIX."g_click_data.member_id AS m,
+               ".TABLE_PREFIX."g_click_data.to_cid,
+               ".TABLE_PREFIX."g_click_data.timestamp AS t
+       from
+               ".TABLE_PREFIX."g_click_data
+       where
+               ".TABLE_PREFIX."g_click_data.to_cid=0
+               AND
+               ".TABLE_PREFIX."g_click_data.to_cid=$to_cid
+               AND
+               ".TABLE_PREFIX."g_click_data.course_id=$_SESSION[course_id]
+               GROUP BY 
+               m
+               ";
+       $result4 = mysql_query($sql4, $db);
+
+       if($result4){
+
+               if($this_data){
+                       echo '<br />';
+                       echo '<a name="show_pages"></a>';
+                       echo '<h3>'._AT('pages_stats', $current["title"]).'</h3>';
+               
+                       echo '<table class="data static" rules="cols" summary="">';
+                       echo '<thead>';
+                       echo '<tr>';
+                               echo '<th scope="col">' . _AT('access_method') . '</th>';
+                               echo '<th scope="col">' . _AT('duration_sec')  . '</th>';
+                               echo '<th scope="col">' . _AT('date')          . '</th>';
+                               echo '<th scope="col">' . _AT('student_id')    . '</th>';
+                       echo '</tr>';
+                       echo '<thead>';                 
+                       echo '<tbody>';
+                       foreach($this_data AS $key => $value){
+                               if(!$start_date){
+                                       $start_date=$pre_time;
+                               }
+                               $diff = abs($value[t] - $pre_time);
+                               if ($diff > 60*45) {
+                                       $end_date=$value[t];
+                                       echo '<tr>';
+                                       echo '<td>';
+                                       if($start_date>0 && $start_date!=$pre_time){
+                                               echo _AT('session_start').' '.date("F j, Y,  g:i a", $start_date).' '._AT('session_end').' '.date("F j, Y,  g:i a", $pre_time).'     ('._AT('duration').':'.date('i \m\i\n s \s\e\c',($pre_time-$start_date)).')';
+                                               
+                                               echo '</td>';
+                                               echo '</tr>';
+                                       }
+                                       else if($value[g]==19) {
+                                               //don't do anything if its a logout
+                                       } 
+                                       else {
+                                               echo _AT('invalid_session');
+                                       }
+                                       $start_date='';
+                               }
+
+                               else {
+                                       if (!$start_date) {
+                                               $start_date=$value[t];
+                                       }
+                               }
+                               echo '<tr>';
+                               echo '<td>';
+                               $that_g=$refs[$value['g']];
+                               echo _AT($that_g);
+                               echo '</td>';
+                               echo '<td>';
+
+                               if ($diff > 60*45) {
+                                       echo _AT('na');
+                                       $session_time='';
+
+                               }else{
+                                       $this_time=date('i.s', $diff);
+                                       echo ' '.$this_time;
+                                       $session_time=($session_time+$diff);
+                               }
+                               $remainder = $diff / 60;
+                               echo '</td>';
+                               echo '<td>';
+                               echo $that_date;
+                               echo '</td>';
+                               echo '<td>'.$this_user[$value['m']].'</td>';
+                               echo '</tr>';
+                               $that_date=date("M-j-y g:i:s:a", $value[t]);
+                               $that_title=$value[title]."&nbsp;";
+                               $pre_time = $value['t'];
+                       }
+                       echo '</tbody>';
+                       echo '</table>';
+               }
+       }
+}  /// end page detail
+
+if($_GET['g_id']){
+       $sql14 = "select member_id, login, first_name, last_name from ".TABLE_PREFIX."members";
+       $result14=mysql_query($sql14, $db);
+       while($row=mysql_fetch_array($result14)){
+               if($row['first_name'] && $row['last_name']){
+                       $this_user[$row['member_id']]= $row['first_name'].' '. $row['last_name'];
+               }else{
+                       $this_user[$row['member_id']]= $row['login'];
+               }
+
+       }
+       $sql13 = "select *, timestamp as t from ".TABLE_PREFIX."g_click_data where to_cid='0' AND g='$_GET[g_id]' AND course_id='$_SESSION[course_id]'";
+       $result13 = mysql_query($sql13, $db);
+       echo '<a name="show_pages"></a>';
+       echo '<h3>'._AT('tools_details').' ('._AT($title_refs2[$g_id]).')</h3>';
+       echo '<p>[<a href="'.$_SERVER['PHP_SELF'].'?stats=summary#show_pages">'._AT('back_to_summary'),'</a>]</p>';
+       
+       echo '<table class="data static" rules="cols" summary="">';
+       echo '<thead>';
+       echo '<tr>';
+               echo '<th scope="col">' . _AT('origin_page')  . '</th>';
+               echo '<th scope="col">' . _AT('duration_sec') . '</th>';
+               echo '<th scope="col">' . _AT('date')         . '</th>';
+               echo '<th scope="col">' . _AT('student_id')   . '</th>';
+       echo '</tr>';
+       echo '</thead>';
+
+       echo '<tbody>';
+
+       while ($row=mysql_fetch_array($result13)){
+               echo '<tr>';
+               if ($row['from_cid'] == 0) {
+                       echo '<td>'._AT($title_refs2[$row['g']]).'</td>';
+               } 
+               else if ($title_refs[$row['from_cid']] != '') {
+                       echo '<td>'.$title_refs[$row['from_cid']].'</td>';
+
+               }
+
+               if ($title_refs[$row['from_cid']] != '' || $row['from_cid'] == 0) {
+                       echo '<td>'.$row['duration'].'</td>';
+                       echo '<td>'.date("M-j-y g:i:s:a",$row['t'] ).'</td>';
+                       echo '<td>'.$this_user[$row['member_id']].'</td>';
+               }
+               echo '</tr>';
+       }
+       echo '</tbody>';
+       echo '</table>';
+}
+?>
\ No newline at end of file
diff --git a/include/lib/tracker_stats2.inc.php b/include/lib/tracker_stats2.inc.php
new file mode 100644 (file)
index 0000000..cbe1d99
--- /dev/null
@@ -0,0 +1,87 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+// NOTE: this script should not be altered. its use will soon be deprecated.
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+//how many content pages are in this course
+$sql25 = "SELECT content_id from ".TABLE_PREFIX."content where course_id = $_SESSION[course_id]";
+$result29 = mysql_query($sql25, $db);
+$num_rows_total = @mysql_num_rows($result29);
+
+//get the title for each content_id
+$sql7 = "select
+                       C.title,
+                       C.content_id
+
+               from
+                       ".TABLE_PREFIX."content C
+               where
+                       course_id='$_SESSION[course_id]'";
+
+       if(!$result7 = mysql_query($sql7, $db)){
+               echo "query failed";
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+       $title_refs = array();
+       while ($row= mysql_fetch_array($result7)) {
+               $title_refs[$row['content_id']] = $row['title'];
+
+       }
+
+$sql2 = "SELECT * FROM ".TABLE_PREFIX."g_click_data WHERE member_id = $_GET[member_id] AND course_id = $_SESSION[course_id]";
+$result28 = mysql_query($sql2, $db);
+
+echo '<br /><h3>'._AT('tracker_summary_read', $this_user[$_GET['member_id']]).'</h3>';
+
+echo '<table class="data static" rules="cols" summary="">';
+echo '<thead>';
+echo '<tr>';
+echo '<th>' . _AT('page')         . '</th>';
+echo '<th>' . _AT('visits')       . '</th>';
+echo '<th>' . _AT('duration_sec') . '</th>';
+echo '</tr>';
+echo '</thead>';
+
+while ($row2= @mysql_fetch_assoc($result28)){
+       $duration[$row2['to_cid']] = ($duration[$row2['to_cid']] + $row2['duration']);
+       $visits[$row2['to_cid']] = ($visits[$row2['to_cid']] +1);
+}
+
+$sql= "SELECT DISTINCT to_cid FROM ".TABLE_PREFIX."g_click_data WHERE member_id = $_GET[member_id] AND course_id = $_SESSION[course_id]";
+$result27 = mysql_query($sql, $db);
+
+echo '<tbody>';
+while ($row= @mysql_fetch_array($result27)) {
+       if($row['to_cid']){
+               $num_rows_read = ($num_rows_read +1);
+               echo '<tr>';
+               echo '<td>' . $title_refs[$row['to_cid']] . '</td>';
+               echo '<td>' . $visits[$row['to_cid']] . '</td>';
+               echo '<td>' . number_format($duration[$row['to_cid']]) . '</td>';
+               echo '</tr>';
+       }
+}
+
+echo '<tr>';
+echo '<td>' . _AT('tracker_pages_total', $num_rows_total, $num_rows_read).'</td>';
+echo '<td>' . _AT('tracker_percent_read',@number_format((($num_rows_read/$num_rows_total)*100),1)) . '%</td>';
+echo '</tr>';
+
+echo '<tbody>';
+echo '</table>';
+
+?>
\ No newline at end of file
diff --git a/include/lib/utf8.php b/include/lib/utf8.php
new file mode 100644 (file)
index 0000000..9a6268e
--- /dev/null
@@ -0,0 +1,1363 @@
+<?php
+/**
+ * UTF8 helper functions
+ *
+ * @license    LGPL (http://www.gnu.org/copyleft/lesser.html)
+ * @author     Andreas Gohr <andi@splitbrain.org>
+ */
+
+/**
+ * check for mb_string support
+ */
+if(!defined('UTF8_MBSTRING')){
+  if(function_exists('mb_substr') && !defined('UTF8_NOMBSTRING')){
+    define('UTF8_MBSTRING',1);
+  }else{
+    define('UTF8_MBSTRING',0);
+  }
+}
+
+if(UTF8_MBSTRING){ mb_internal_encoding('UTF-8'); }
+
+
+/**
+ * URL-Encode a filename to allow unicodecharacters
+ *
+ * Slashes are not encoded
+ *
+ * When the second parameter is true the string will
+ * be encoded only if non ASCII characters are detected -
+ * This makes it safe to run it multiple times on the
+ * same string (default is true)
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @see    urlencode
+ */
+function utf8_encodeFN($file,$safe=true){
+  if($safe && preg_match('#^[a-zA-Z0-9/_\-.%]+$#',$file)){
+    return $file;
+  }
+  $file = urlencode($file);
+  $file = str_replace('%2F','/',$file);
+  return $file;
+}
+
+/**
+ * URL-Decode a filename
+ *
+ * This is just a wrapper around urldecode
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @see    urldecode
+ */
+function utf8_decodeFN($file){
+  $file = urldecode($file);
+  return $file;
+}
+
+/**
+ * Checks if a string contains 7bit ASCII only
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function utf8_isASCII($str){
+  for($i=0; $i<strlen($str); $i++){
+    if(ord($str{$i}) >127) return false;
+  }
+  return true;
+}
+
+/**
+ * Strips all highbyte chars
+ *
+ * Returns a pure ASCII7 string
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function utf8_strip($str){
+  $ascii = '';
+  for($i=0; $i<strlen($str); $i++){
+    if(ord($str{$i}) <128){
+      $ascii .= $str{$i};
+    }
+  }
+  return $ascii;
+}
+
+/**
+ * Tries to detect if a string is in Unicode encoding
+ *
+ * @author <bmorel@ssi.fr>
+ * @link   http://www.php.net/manual/en/function.utf8-encode.php
+ */
+function utf8_check($Str) {
+ for ($i=0; $i<strlen($Str); $i++) {
+  $b = ord($Str[$i]);
+  if ($b < 0x80) continue; # 0bbbbbbb
+  elseif (($b & 0xE0) == 0xC0) $n=1; # 110bbbbb
+  elseif (($b & 0xF0) == 0xE0) $n=2; # 1110bbbb
+  elseif (($b & 0xF8) == 0xF0) $n=3; # 11110bbb
+  elseif (($b & 0xFC) == 0xF8) $n=4; # 111110bb
+  elseif (($b & 0xFE) == 0xFC) $n=5; # 1111110b
+  else return false; # Does not match any model
+  for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
+   if ((++$i == strlen($Str)) || ((ord($Str[$i]) & 0xC0) != 0x80))
+   return false;
+  }
+ }
+ return true;
+}
+
+/**
+ * Unicode aware replacement for strlen()
+ *
+ * utf8_decode() converts characters that are not in ISO-8859-1
+ * to '?', which, for the purpose of counting, is alright - It's
+ * even faster than mb_strlen.
+ *
+ * @author <chernyshevsky at hotmail dot com>
+ * @see    strlen()
+ * @see    utf8_decode()
+ */
+function utf8_strlen($string){
+  return strlen(utf8_decode($string));
+}
+
+/**
+ * UTF-8 aware alternative to substr
+ *
+ * Return part of a string given character offset (and optionally length)
+ *
+ * @author Harry Fuecks <hfuecks@gmail.com>
+ * @author Chris Smith <chris@jalakai.co.uk>
+ * @param string
+ * @param integer number of UTF-8 characters offset (from left)
+ * @param integer (optional) length in UTF-8 characters from offset
+ * @return mixed string or false if failure
+ */
+function utf8_substr($str, $offset, $length = null) {
+    if(UTF8_MBSTRING){
+        if( $length === null ){
+            return mb_substr($str, $offset);
+        }else{
+            return mb_substr($str, $offset, $length);
+        }
+    }
+
+    /*
+     * Notes:
+     *
+     * no mb string support, so we'll use pcre regex's with 'u' flag
+     * pcre only supports repetitions of less than 65536, in order to accept up to MAXINT values for
+     * offset and length, we'll repeat a group of 65535 characters when needed (ok, up to MAXINT-65536)
+     *
+     * substr documentation states false can be returned in some cases (e.g. offset > string length)
+     * mb_substr never returns false, it will return an empty string instead.
+     *
+     * calculating the number of characters in the string is a relatively expensive operation, so
+     * we only carry it out when necessary. It isn't necessary for +ve offsets and no specified length
+     */
+
+    // cast parameters to appropriate types to avoid multiple notices/warnings
+    $str = (string)$str;                          // generates E_NOTICE for PHP4 objects, but not PHP5 objects
+    $offset = (int)$offset;
+    if (!is_null($length)) $length = (int)$length;
+
+    // handle trivial cases
+    if ($length === 0) return '';
+    if ($offset < 0 && $length < 0 && $length < $offset) return '';
+
+    $offset_pattern = '';
+    $length_pattern = '';
+
+    // normalise -ve offsets (we could use a tail anchored pattern, but they are horribly slow!)
+    if ($offset < 0) {
+      $strlen = strlen(utf8_decode($str));        // see notes
+      $offset = $strlen + $offset;
+      if ($offset < 0) $offset = 0;
+    }
+
+    // establish a pattern for offset, a non-captured group equal in length to offset
+    if ($offset > 0) {
+      $Ox = (int)($offset/65535);
+      $Oy = $offset%65535;
+
+      if ($Ox) $offset_pattern = '(?:.{65535}){'.$Ox.'}';
+      $offset_pattern = '^(?:'.$offset_pattern.'.{'.$Oy.'})';
+    } else {
+      $offset_pattern = '^';                      // offset == 0; just anchor the pattern
+    }
+
+    // establish a pattern for length
+    if (is_null($length)) {
+      $length_pattern = '(.*)$';                  // the rest of the string
+    } else {
+
+      if (!isset($strlen)) $strlen = strlen(utf8_decode($str));    // see notes
+      if ($offset > $strlen) return '';           // another trivial case
+
+      if ($length > 0) {
+
+        $length = min($strlen-$offset, $length);  // reduce any length that would go passed the end of the string
+
+        $Lx = (int)($length/65535);
+        $Ly = $length%65535;
+
+        // +ve length requires ... a captured group of length characters
+        if ($Lx) $length_pattern = '(?:.{65535}){'.$Lx.'}';
+        $length_pattern = '('.$length_pattern.'.{'.$Ly.'})';
+
+      } else if ($length < 0) {
+
+        if ($length < ($offset - $strlen)) return '';
+
+        $Lx = (int)((-$length)/65535);
+        $Ly = (-$length)%65535;
+
+        // -ve length requires ... capture everything except a group of -length characters
+        //                         anchored at the tail-end of the string
+        if ($Lx) $length_pattern = '(?:.{65535}){'.$Lx.'}';
+        $length_pattern = '(.*)(?:'.$length_pattern.'.{'.$Ly.'})$';
+      }
+    }
+
+    if (!preg_match('#'.$offset_pattern.$length_pattern.'#us',$str,$match)) return '';
+    return $match[1];
+}
+
+/**
+ * Unicode aware replacement for substr_replace()
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @see    substr_replace()
+ */
+function utf8_substr_replace($string, $replacement, $start , $length=0 ){
+  $ret = '';
+  if($start>0) $ret .= utf8_substr($string, 0, $start);
+  $ret .= $replacement;
+  $ret .= utf8_substr($string, $start+$length);
+  return $ret;
+}
+
+
+/**
+ * Unicode aware replacement for ltrim()
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @see    ltrim()
+ * @return string
+ */
+function utf8_ltrim($str,$charlist=''){
+  if($charlist == '') return ltrim($str);
+
+  //quote charlist for use in a characterclass
+  $charlist = preg_replace('!([\\\\\\-\\]\\[/])!','\\\${1}',$charlist);
+
+  return preg_replace('/^['.$charlist.']+/u','',$str);
+}
+
+/**
+ * Unicode aware replacement for rtrim()
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @see    rtrim()
+ * @return string
+ */
+function  utf8_rtrim($str,$charlist=''){
+  if($charlist == '') return rtrim($str);
+
+  //quote charlist for use in a characterclass
+  $charlist = preg_replace('!([\\\\\\-\\]\\[/])!','\\\${1}',$charlist);
+
+  return preg_replace('/['.$charlist.']+$/u','',$str);
+}
+
+/**
+ * Unicode aware replacement for trim()
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @see    trim()
+ * @return string
+ */
+function  utf8_trim($str,$charlist='') {
+  if($charlist == '') return trim($str);
+
+  return utf8_ltrim(utf8_rtrim($str));
+}
+
+
+/**
+ * This is a unicode aware replacement for strtolower()
+ *
+ * Uses mb_string extension if available
+ *
+ * @author Leo Feyer <leo@typolight.org>
+ * @see    strtolower()
+ * @see    utf8_strtoupper()
+ */
+function utf8_strtolower($string){
+  if(UTF8_MBSTRING) return mb_strtolower($string,'utf-8');
+
+  global $UTF8_UPPER_TO_LOWER;
+  return strtr($string,$UTF8_UPPER_TO_LOWER);
+}
+
+/**
+ * This is a unicode aware replacement for strtoupper()
+ *
+ * Uses mb_string extension if available
+ *
+ * @author Leo Feyer <leo@typolight.org>
+ * @see    strtoupper()
+ * @see    utf8_strtoupper()
+ */
+function utf8_strtoupper($string){
+  if(UTF8_MBSTRING) return mb_strtoupper($string,'utf-8');
+
+  global $UTF8_LOWER_TO_UPPER;
+  return strtr($string,$UTF8_LOWER_TO_UPPER);
+}
+
+/**
+ * Replace accented UTF-8 characters by unaccented ASCII-7 equivalents
+ *
+ * Use the optional parameter to just deaccent lower ($case = -1) or upper ($case = 1)
+ * letters. Default is to deaccent both cases ($case = 0)
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function utf8_deaccent($string,$case=0){
+  if($case <= 0){
+    global $UTF8_LOWER_ACCENTS;
+    $string = strtr($string,$UTF8_LOWER_ACCENTS);
+  }
+  if($case >= 0){
+    global $UTF8_UPPER_ACCENTS;
+    $string = strtr($string,$UTF8_UPPER_ACCENTS);
+  }
+  return $string;
+}
+
+/**
+ * Romanize a non-latin string
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function utf8_romanize($string){
+  if(utf8_isASCII($string)) return $string; //nothing to do
+
+  global $UTF8_ROMANIZATION;
+  return strtr($string,$UTF8_ROMANIZATION);
+}
+
+/**
+ * Removes special characters (nonalphanumeric) from a UTF-8 string
+ *
+ * This function adds the controlchars 0x00 to 0x19 to the array of
+ * stripped chars (they are not included in $UTF8_SPECIAL_CHARS)
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @param  string $string     The UTF8 string to strip of special chars
+ * @param  string $repl       Replace special with this string
+ * @param  string $additional Additional chars to strip (used in regexp char class)
+ */
+function utf8_stripspecials($string,$repl='',$additional=''){
+  global $UTF8_SPECIAL_CHARS;
+  global $UTF8_SPECIAL_CHARS2;
+
+  static $specials = null;
+  if(is_null($specials)){
+#    $specials = preg_quote(unicode_to_utf8($UTF8_SPECIAL_CHARS), '/');
+    $specials = preg_quote($UTF8_SPECIAL_CHARS2, '/');
+  }
+
+  return preg_replace('/['.$additional.'\x00-\x19'.$specials.']/u',$repl,$string);
+}
+
+/**
+ * This is an Unicode aware replacement for strpos
+ *
+ * @author Leo Feyer <leo@typolight.org>
+ * @see    strpos()
+ * @param  string
+ * @param  string
+ * @param  integer
+ * @return integer
+ */
+function utf8_strpos($haystack, $needle, $offset=0){
+    $comp = 0;
+    $length = null;
+
+    while (is_null($length) || $length < $offset) {
+        $pos = strpos($haystack, $needle, $offset + $comp);
+
+        if ($pos === false)
+            return false;
+
+        $length = utf8_strlen(substr($haystack, 0, $pos));
+
+        if ($length < $offset)
+            $comp = $pos - $length;
+    }
+
+    return $length;
+}
+
+
+/**
+ * This is an Unicode aware replacement for strrpos.
+ * Based on utf8_strpos written by Leo
+ *
+ * @author Harris Wong <harris.wong@utoronto.ca>
+ * @see    strrpos()
+ * @param  string
+ * @param  string
+ * @param  integer
+ * @return integer
+ */
+function utf8_strrpos($haystack, $needle, $offset=0){
+    $comp = 0;
+    $length = null;
+
+    while (is_null($length) || $length < $offset) {
+        $pos = strrpos($haystack, $needle, $offset + $comp);
+
+        if ($pos === false)
+            return false;
+
+        $length = utf8_strlen(substr($haystack, 0, $pos));
+
+        if ($length < $offset)
+            $comp = $pos - $length;
+    }
+
+    return $length;
+}
+
+
+/**
+ * Encodes UTF-8 characters to HTML entities
+ *
+ * @author Tom N Harris <tnharris@whoopdedo.org>
+ * @author <vpribish at shopping dot com>
+ * @link   http://www.php.net/manual/en/function.utf8-decode.php
+ */
+function utf8_tohtml ($str) {
+    $ret = '';
+    foreach (utf8_to_unicode($str) as $cp) {
+        if ($cp < 0x80)
+            $ret .= chr($cp);
+        elseif ($cp < 0x100)
+            $ret .= "&#$cp;";
+        else
+            $ret .= '&#x'.dechex($cp).';';
+    }
+    return $ret;
+}
+
+/**
+ * Decodes HTML entities to UTF-8 characters
+ *
+ * Convert any &#..; entity to a codepoint,
+ * The entities flag defaults to only decoding numeric entities.
+ * Pass HTML_ENTITIES and named entities, including &amp; &lt; etc.
+ * are handled as well. Avoids the problem that would occur if you
+ * had to decode "&amp;#38;&#38;amp;#38;"
+ *
+ * unhtmlspecialchars(utf8_unhtml($s)) -> "&#38;&#38;"
+ * utf8_unhtml(unhtmlspecialchars($s)) -> "&&amp#38;"
+ * what it should be                   -> "&#38;&amp#38;"
+ *
+ * @author Tom N Harris <tnharris@whoopdedo.org>
+ * @param  string  $str      UTF-8 encoded string
+ * @param  boolean $entities Flag controlling decoding of named entities.
+ * @return UTF-8 encoded string with numeric (and named) entities replaced.
+ */
+function utf8_unhtml($str, $entities=null) {
+    static $decoder = null;
+    if (is_null($decoder))
+      $decoder = new utf8_entity_decoder();
+    if (is_null($entities))
+        return preg_replace_callback('/(&#([Xx])?([0-9A-Za-z]+);)/m',
+                                     'utf8_decode_numeric', $str);
+    else
+        return preg_replace_callback('/&(#)?([Xx])?([0-9A-Za-z]+);/m',
+                                     array(&$decoder, 'decode'), $str);
+}
+function utf8_decode_numeric($ent) {
+    switch ($ent[2]) {
+      case 'X':
+      case 'x':
+          $cp = hexdec($ent[3]);
+          break;
+      default:
+          $cp = intval($ent[3]);
+          break;
+    }
+    return unicode_to_utf8(array($cp));
+}
+class utf8_entity_decoder {
+    var $table;
+    function utf8_entity_decoder() {
+        $table = get_html_translation_table(HTML_ENTITIES);
+        $table = array_flip($table);
+        $this->table = array_map(array(&$this,'makeutf8'), $table);
+    }
+    function makeutf8($c) {
+        return unicode_to_utf8(array(ord($c)));
+    }
+    function decode($ent) {
+        if ($ent[1] == '#') {
+            return utf8_decode_numeric($ent);
+        } elseif (array_key_exists($ent[0],$this->table)) {
+            return $this->table[$ent[0]];
+        } else {
+            return $ent[0];
+        }
+    }
+}
+
+/**
+ * Takes an UTF-8 string and returns an array of ints representing the
+ * Unicode characters. Astral planes are supported ie. the ints in the
+ * output can be > 0xFFFF. Occurrances of the BOM are ignored. Surrogates
+ * are not allowed.
+ *
+ * If $strict is set to true the function returns false if the input
+ * string isn't a valid UTF-8 octet sequence and raises a PHP error at
+ * level E_USER_WARNING
+ *
+ * Note: this function has been modified slightly in this library to
+ * trigger errors on encountering bad bytes
+ *
+ * @author <hsivonen@iki.fi>
+ * @author Harry Fuecks <hfuecks@gmail.com>
+ * @param  string  UTF-8 encoded string
+ * @param  boolean Check for invalid sequences?
+ * @return mixed array of unicode code points or false if UTF-8 invalid
+ * @see    unicode_to_utf8
+ * @link   http://hsivonen.iki.fi/php-utf8/
+ * @link   http://sourceforge.net/projects/phputf8/
+ */
+function utf8_to_unicode($str,$strict=false) {
+    $mState = 0;     // cached expected number of octets after the current octet
+                     // until the beginning of the next UTF8 character sequence
+    $mUcs4  = 0;     // cached Unicode character
+    $mBytes = 1;     // cached expected number of octets in the current sequence
+
+    $out = array();
+
+    $len = strlen($str);
+
+    for($i = 0; $i < $len; $i++) {
+
+        $in = ord($str{$i});
+
+        if ( $mState == 0) {
+
+            // When mState is zero we expect either a US-ASCII character or a
+            // multi-octet sequence.
+            if (0 == (0x80 & ($in))) {
+                // US-ASCII, pass straight through.
+                $out[] = $in;
+                $mBytes = 1;
+
+            } else if (0xC0 == (0xE0 & ($in))) {
+                // First octet of 2 octet sequence
+                $mUcs4 = ($in);
+                $mUcs4 = ($mUcs4 & 0x1F) << 6;
+                $mState = 1;
+                $mBytes = 2;
+
+            } else if (0xE0 == (0xF0 & ($in))) {
+                // First octet of 3 octet sequence
+                $mUcs4 = ($in);
+                $mUcs4 = ($mUcs4 & 0x0F) << 12;
+                $mState = 2;
+                $mBytes = 3;
+
+            } else if (0xF0 == (0xF8 & ($in))) {
+                // First octet of 4 octet sequence
+                $mUcs4 = ($in);
+                $mUcs4 = ($mUcs4 & 0x07) << 18;
+                $mState = 3;
+                $mBytes = 4;
+
+            } else if (0xF8 == (0xFC & ($in))) {
+                /* First octet of 5 octet sequence.
+                 *
+                 * This is illegal because the encoded codepoint must be either
+                 * (a) not the shortest form or
+                 * (b) outside the Unicode range of 0-0x10FFFF.
+                 * Rather than trying to resynchronize, we will carry on until the end
+                 * of the sequence and let the later error handling code catch it.
+                 */
+                $mUcs4 = ($in);
+                $mUcs4 = ($mUcs4 & 0x03) << 24;
+                $mState = 4;
+                $mBytes = 5;
+
+            } else if (0xFC == (0xFE & ($in))) {
+                // First octet of 6 octet sequence, see comments for 5 octet sequence.
+                $mUcs4 = ($in);
+                $mUcs4 = ($mUcs4 & 1) << 30;
+                $mState = 5;
+                $mBytes = 6;
+
+            } elseif($strict) {
+                /* Current octet is neither in the US-ASCII range nor a legal first
+                 * octet of a multi-octet sequence.
+                 */
+                trigger_error(
+                        'utf8_to_unicode: Illegal sequence identifier '.
+                            'in UTF-8 at byte '.$i,
+                        E_USER_WARNING
+                    );
+                return false;
+
+            }
+
+        } else {
+
+            // When mState is non-zero, we expect a continuation of the multi-octet
+            // sequence
+            if (0x80 == (0xC0 & ($in))) {
+
+                // Legal continuation.
+                $shift = ($mState - 1) * 6;
+                $tmp = $in;
+                $tmp = ($tmp & 0x0000003F) << $shift;
+                $mUcs4 |= $tmp;
+
+                /**
+                 * End of the multi-octet sequence. mUcs4 now contains the final
+                 * Unicode codepoint to be output
+                 */
+                if (0 == --$mState) {
+
+                    /*
+                     * Check for illegal sequences and codepoints.
+                     */
+                    // From Unicode 3.1, non-shortest form is illegal
+                    if (((2 == $mBytes) && ($mUcs4 < 0x0080)) ||
+                        ((3 == $mBytes) && ($mUcs4 < 0x0800)) ||
+                        ((4 == $mBytes) && ($mUcs4 < 0x10000)) ||
+                        (4 < $mBytes) ||
+                        // From Unicode 3.2, surrogate characters are illegal
+                        (($mUcs4 & 0xFFFFF800) == 0xD800) ||
+                        // Codepoints outside the Unicode range are illegal
+                        ($mUcs4 > 0x10FFFF)) {
+
+                        if($strict){
+                            trigger_error(
+                                    'utf8_to_unicode: Illegal sequence or codepoint '.
+                                        'in UTF-8 at byte '.$i,
+                                    E_USER_WARNING
+                                );
+
+                            return false;
+                        }
+
+                    }
+
+                    if (0xFEFF != $mUcs4) {
+                        // BOM is legal but we don't want to output it
+                        $out[] = $mUcs4;
+                    }
+
+                    //initialize UTF8 cache
+                    $mState = 0;
+                    $mUcs4  = 0;
+                    $mBytes = 1;
+                }
+
+            } elseif($strict) {
+                /**
+                 *((0xC0 & (*in) != 0x80) && (mState != 0))
+                 * Incomplete multi-octet sequence.
+                 */
+                trigger_error(
+                        'utf8_to_unicode: Incomplete multi-octet '.
+                        '   sequence in UTF-8 at byte '.$i,
+                        E_USER_WARNING
+                    );
+
+                return false;
+            }
+        }
+    }
+    return $out;
+}
+
+/**
+ * Takes an array of ints representing the Unicode characters and returns
+ * a UTF-8 string. Astral planes are supported ie. the ints in the
+ * input can be > 0xFFFF. Occurrances of the BOM are ignored. Surrogates
+ * are not allowed.
+ *
+ * If $strict is set to true the function returns false if the input
+ * array contains ints that represent surrogates or are outside the
+ * Unicode range and raises a PHP error at level E_USER_WARNING
+ *
+ * Note: this function has been modified slightly in this library to use
+ * output buffering to concatenate the UTF-8 string (faster) as well as
+ * reference the array by it's keys
+ *
+ * @param  array of unicode code points representing a string
+ * @param  boolean Check for invalid sequences?
+ * @return mixed UTF-8 string or false if array contains invalid code points
+ * @author <hsivonen@iki.fi>
+ * @author Harry Fuecks <hfuecks@gmail.com>
+ * @see    utf8_to_unicode
+ * @link   http://hsivonen.iki.fi/php-utf8/
+ * @link   http://sourceforge.net/projects/phputf8/
+ */
+function unicode_to_utf8($arr,$strict=false) {
+    if (!is_array($arr)) return '';
+    ob_start();
+
+    foreach (array_keys($arr) as $k) {
+
+        # ASCII range (including control chars)
+        if ( ($arr[$k] >= 0) && ($arr[$k] <= 0x007f) ) {
+
+            echo chr($arr[$k]);
+
+        # 2 byte sequence
+        } else if ($arr[$k] <= 0x07ff) {
+
+            echo chr(0xc0 | ($arr[$k] >> 6));
+            echo chr(0x80 | ($arr[$k] & 0x003f));
+
+        # Byte order mark (skip)
+        } else if($arr[$k] == 0xFEFF) {
+
+            // nop -- zap the BOM
+
+        # Test for illegal surrogates
+        } else if ($arr[$k] >= 0xD800 && $arr[$k] <= 0xDFFF) {
+
+            // found a surrogate
+            if($strict){
+                trigger_error(
+                    'unicode_to_utf8: Illegal surrogate '.
+                        'at index: '.$k.', value: '.$arr[$k],
+                    E_USER_WARNING
+                    );
+                return false;
+            }
+
+        # 3 byte sequence
+        } else if ($arr[$k] <= 0xffff) {
+
+            echo chr(0xe0 | ($arr[$k] >> 12));
+            echo chr(0x80 | (($arr[$k] >> 6) & 0x003f));
+            echo chr(0x80 | ($arr[$k] & 0x003f));
+
+        # 4 byte sequence
+        } else if ($arr[$k] <= 0x10ffff) {
+
+            echo chr(0xf0 | ($arr[$k] >> 18));
+            echo chr(0x80 | (($arr[$k] >> 12) & 0x3f));
+            echo chr(0x80 | (($arr[$k] >> 6) & 0x3f));
+            echo chr(0x80 | ($arr[$k] & 0x3f));
+
+        } elseif($strict) {
+
+            trigger_error(
+                'unicode_to_utf8: Codepoint out of Unicode range '.
+                    'at index: '.$k.', value: '.$arr[$k],
+                E_USER_WARNING
+                );
+
+            // out of range
+            return false;
+        }
+    }
+
+    $result = ob_get_contents();
+    ob_end_clean();
+    return $result;
+}
+
+/**
+ * UTF-8 to UTF-16BE conversion.
+ *
+ * Maybe really UCS-2 without mb_string due to utf8_to_unicode limits
+ */
+function utf8_to_utf16be(&$str, $bom = false) {
+  $out = $bom ? "\xFE\xFF" : '';
+  if(UTF8_MBSTRING) return $out.mb_convert_encoding($str,'UTF-16BE','UTF-8');
+
+  $uni = utf8_to_unicode($str);
+  foreach($uni as $cp){
+    $out .= pack('n',$cp);
+  }
+  return $out;
+}
+
+/**
+ * UTF-8 to UTF-16BE conversion.
+ *
+ * Maybe really UCS-2 without mb_string due to utf8_to_unicode limits
+ */
+function utf16be_to_utf8(&$str) {
+  $uni = unpack('n*',$str);
+  return unicode_to_utf8($uni);
+}
+
+/**
+ * Replace bad bytes with an alternative character
+ *
+ * ASCII character is recommended for replacement char
+ *
+ * PCRE Pattern to locate bad bytes in a UTF-8 string
+ * Comes from W3 FAQ: Multilingual Forms
+ * Note: modified to include full ASCII range including control chars
+ *
+ * @author Harry Fuecks <hfuecks@gmail.com>
+ * @see http://www.w3.org/International/questions/qa-forms-utf-8
+ * @param string to search
+ * @param string to replace bad bytes with (defaults to '?') - use ASCII
+ * @return string
+ */
+function utf8_bad_replace($str, $replace = '') {
+    $UTF8_BAD =
+     '([\x00-\x7F]'.                          # ASCII (including control chars)
+     '|[\xC2-\xDF][\x80-\xBF]'.               # non-overlong 2-byte
+     '|\xE0[\xA0-\xBF][\x80-\xBF]'.           # excluding overlongs
+     '|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}'.    # straight 3-byte
+     '|\xED[\x80-\x9F][\x80-\xBF]'.           # excluding surrogates
+     '|\xF0[\x90-\xBF][\x80-\xBF]{2}'.        # planes 1-3
+     '|[\xF1-\xF3][\x80-\xBF]{3}'.            # planes 4-15
+     '|\xF4[\x80-\x8F][\x80-\xBF]{2}'.        # plane 16
+     '|(.{1}))';                              # invalid byte
+    ob_start();
+    while (preg_match('/'.$UTF8_BAD.'/S', $str, $matches)) {
+        if ( !isset($matches[2])) {
+            echo $matches[0];
+        } else {
+            echo $replace;
+        }
+        $str = substr($str,strlen($matches[0]));
+    }
+    $result = ob_get_contents();
+    ob_end_clean();
+    return $result;
+}
+
+/**
+ * adjust a byte index into a utf8 string to a utf8 character boundary
+ *
+ * @param $str   string   utf8 character string
+ * @param $i     int      byte index into $str
+ * @param $next  bool     direction to search for boundary,
+ *                           false = up (current character)
+ *                           true = down (next character)
+ *
+ * @return int            byte index into $str now pointing to a utf8 character boundary
+ *
+ * @author       chris smith <chris@jalakai.co.uk>
+ */
+function utf8_correctIdx(&$str,$i,$next=false) {
+
+  if ($i <= 0) return 0;
+
+  $limit = strlen($str);
+  if ($i>=$limit) return $limit;
+
+  if ($next) {
+    while (($i<$limit) && ((ord($str[$i]) & 0xC0) == 0x80)) $i++;
+  } else {
+    while ($i && ((ord($str[$i]) & 0xC0) == 0x80)) $i--;
+  }
+
+  return $i;
+}
+
+// only needed if no mb_string available
+if(!UTF8_MBSTRING){
+  /**
+   * UTF-8 Case lookup table
+   *
+   * This lookuptable defines the upper case letters to their correspponding
+   * lower case letter in UTF-8
+   *
+   * @author Andreas Gohr <andi@splitbrain.org>
+   */
+  global $UTF8_LOWER_TO_UPPER;
+  $UTF8_LOWER_TO_UPPER = array(
+    "z"=>"Z","y"=>"Y","x"=>"X","w"=>"W","v"=>"V","u"=>"U","t"=>"T","s"=>"S","r"=>"R","q"=>"Q",
+    "p"=>"P","o"=>"O","n"=>"N","m"=>"M","l"=>"L","k"=>"K","j"=>"J","i"=>"I","h"=>"H","g"=>"G",
+    "f"=>"F","e"=>"E","d"=>"D","c"=>"C","b"=>"B","a"=>"A","ῳ"=>"ῼ","ῥ"=>"Ῥ","ῡ"=>"Ῡ","ῑ"=>"Ῑ",
+    "ῐ"=>"Ῐ","ῃ"=>"ῌ","ι"=>"Ι","ᾳ"=>"ᾼ","ᾱ"=>"Ᾱ","ᾰ"=>"Ᾰ","ᾧ"=>"ᾯ","ᾦ"=>"ᾮ","ᾥ"=>"ᾭ","ᾤ"=>"ᾬ",
+    "ᾣ"=>"ᾫ","ᾢ"=>"ᾪ","ᾡ"=>"ᾩ","ᾗ"=>"ᾟ","ᾖ"=>"ᾞ","ᾕ"=>"ᾝ","ᾔ"=>"ᾜ","ᾓ"=>"ᾛ","ᾒ"=>"ᾚ","ᾑ"=>"ᾙ",
+    "ᾐ"=>"ᾘ","ᾇ"=>"ᾏ","ᾆ"=>"ᾎ","ᾅ"=>"ᾍ","ᾄ"=>"ᾌ","ᾃ"=>"ᾋ","ᾂ"=>"ᾊ","ᾁ"=>"ᾉ","ᾀ"=>"ᾈ","ώ"=>"Ώ",
+    "ὼ"=>"Ὼ","ύ"=>"Ύ","ὺ"=>"Ὺ","ό"=>"Ό","ὸ"=>"Ὸ","ί"=>"Ί","ὶ"=>"Ὶ","ή"=>"Ή","ὴ"=>"Ὴ","έ"=>"Έ",
+    "ὲ"=>"Ὲ","ά"=>"Ά","ὰ"=>"Ὰ","ὧ"=>"Ὧ","ὦ"=>"Ὦ","ὥ"=>"Ὥ","ὤ"=>"Ὤ","ὣ"=>"Ὣ","ὢ"=>"Ὢ","ὡ"=>"Ὡ",
+    "ὗ"=>"Ὗ","ὕ"=>"Ὕ","ὓ"=>"Ὓ","ὑ"=>"Ὑ","ὅ"=>"Ὅ","ὄ"=>"Ὄ","ὃ"=>"Ὃ","ὂ"=>"Ὂ","ὁ"=>"Ὁ","ὀ"=>"Ὀ",
+    "ἷ"=>"Ἷ","ἶ"=>"Ἶ","ἵ"=>"Ἵ","ἴ"=>"Ἴ","ἳ"=>"Ἳ","ἲ"=>"Ἲ","ἱ"=>"Ἱ","ἰ"=>"Ἰ","ἧ"=>"Ἧ","ἦ"=>"Ἦ",
+    "ἥ"=>"Ἥ","ἤ"=>"Ἤ","ἣ"=>"Ἣ","ἢ"=>"Ἢ","ἡ"=>"Ἡ","ἕ"=>"Ἕ","ἔ"=>"Ἔ","ἓ"=>"Ἓ","ἒ"=>"Ἒ","ἑ"=>"Ἑ",
+    "ἐ"=>"Ἐ","ἇ"=>"Ἇ","ἆ"=>"Ἆ","ἅ"=>"Ἅ","ἄ"=>"Ἄ","ἃ"=>"Ἃ","ἂ"=>"Ἂ","ἁ"=>"Ἁ","ἀ"=>"Ἀ","ỹ"=>"Ỹ",
+    "ỷ"=>"Ỷ","ỵ"=>"Ỵ","ỳ"=>"Ỳ","ự"=>"Ự","ữ"=>"Ữ","ử"=>"Ử","ừ"=>"Ừ","ứ"=>"Ứ","ủ"=>"Ủ","ụ"=>"Ụ",
+    "ợ"=>"Ợ","ỡ"=>"Ỡ","ở"=>"Ở","ờ"=>"Ờ","ớ"=>"Ớ","ộ"=>"Ộ","ỗ"=>"Ỗ","ổ"=>"Ổ","ồ"=>"Ồ","ố"=>"Ố",
+    "ỏ"=>"Ỏ","ọ"=>"Ọ","ị"=>"Ị","ỉ"=>"Ỉ","ệ"=>"Ệ","ễ"=>"Ễ","ể"=>"Ể","ề"=>"Ề","ế"=>"Ế","ẽ"=>"Ẽ",
+    "ẻ"=>"Ẻ","ẹ"=>"Ẹ","ặ"=>"Ặ","ẵ"=>"Ẵ","ẳ"=>"Ẳ","ằ"=>"Ằ","ắ"=>"Ắ","ậ"=>"Ậ","ẫ"=>"Ẫ","ẩ"=>"Ẩ",
+    "ầ"=>"Ầ","ấ"=>"Ấ","ả"=>"Ả","ạ"=>"Ạ","ẛ"=>"Ṡ","ẕ"=>"Ẕ","ẓ"=>"Ẓ","ẑ"=>"Ẑ","ẏ"=>"Ẏ","ẍ"=>"Ẍ",
+    "ẋ"=>"Ẋ","ẉ"=>"Ẉ","ẇ"=>"Ẇ","ẅ"=>"Ẅ","ẃ"=>"Ẃ","ẁ"=>"Ẁ","ṿ"=>"Ṿ","ṽ"=>"Ṽ","ṻ"=>"Ṻ","ṹ"=>"Ṹ",
+    "ṷ"=>"Ṷ","ṵ"=>"Ṵ","ṳ"=>"Ṳ","ṱ"=>"Ṱ","ṯ"=>"Ṯ","ṭ"=>"Ṭ","ṫ"=>"Ṫ","ṩ"=>"Ṩ","ṧ"=>"Ṧ","ṥ"=>"Ṥ",
+    "ṣ"=>"Ṣ","ṡ"=>"Ṡ","ṟ"=>"Ṟ","ṝ"=>"Ṝ","ṛ"=>"Ṛ","ṙ"=>"Ṙ","ṗ"=>"Ṗ","ṕ"=>"Ṕ","ṓ"=>"Ṓ","ṑ"=>"Ṑ",
+    "ṏ"=>"Ṏ","ṍ"=>"Ṍ","ṋ"=>"Ṋ","ṉ"=>"Ṉ","ṇ"=>"Ṇ","ṅ"=>"Ṅ","ṃ"=>"Ṃ","ṁ"=>"Ṁ","ḿ"=>"Ḿ","ḽ"=>"Ḽ",
+    "ḻ"=>"Ḻ","ḹ"=>"Ḹ","ḷ"=>"Ḷ","ḵ"=>"Ḵ","ḳ"=>"Ḳ","ḱ"=>"Ḱ","ḯ"=>"Ḯ","ḭ"=>"Ḭ","ḫ"=>"Ḫ","ḩ"=>"Ḩ",
+    "ḧ"=>"Ḧ","ḥ"=>"Ḥ","ḣ"=>"Ḣ","ḡ"=>"Ḡ","ḟ"=>"Ḟ","ḝ"=>"Ḝ","ḛ"=>"Ḛ","ḙ"=>"Ḙ","ḗ"=>"Ḗ","ḕ"=>"Ḕ",
+    "ḓ"=>"Ḓ","ḑ"=>"Ḑ","ḏ"=>"Ḏ","ḍ"=>"Ḍ","ḋ"=>"Ḋ","ḉ"=>"Ḉ","ḇ"=>"Ḇ","ḅ"=>"Ḅ","ḃ"=>"Ḃ","ḁ"=>"Ḁ",
+    "ֆ"=>"Ֆ","օ"=>"Օ","ք"=>"Ք","փ"=>"Փ","ւ"=>"Ւ","ց"=>"Ց","ր"=>"Ր","տ"=>"Տ","վ"=>"Վ","ս"=>"Ս",
+    "ռ"=>"Ռ","ջ"=>"Ջ","պ"=>"Պ","չ"=>"Չ","ո"=>"Ո","շ"=>"Շ","ն"=>"Ն","յ"=>"Յ","մ"=>"Մ","ճ"=>"Ճ",
+    "ղ"=>"Ղ","ձ"=>"Ձ","հ"=>"Հ","կ"=>"Կ","ծ"=>"Ծ","խ"=>"Խ","լ"=>"Լ","ի"=>"Ի","ժ"=>"Ժ","թ"=>"Թ",
+    "ը"=>"Ը","է"=>"Է","զ"=>"Զ","ե"=>"Ե","դ"=>"Դ","գ"=>"Գ","բ"=>"Բ","ա"=>"Ա","ԏ"=>"Ԏ","ԍ"=>"Ԍ",
+    "ԋ"=>"Ԋ","ԉ"=>"Ԉ","ԇ"=>"Ԇ","ԅ"=>"Ԅ","ԃ"=>"Ԃ","ԁ"=>"Ԁ","ӹ"=>"Ӹ","ӵ"=>"Ӵ","ӳ"=>"Ӳ","ӱ"=>"Ӱ",
+    "ӯ"=>"Ӯ","ӭ"=>"Ӭ","ӫ"=>"Ӫ","ө"=>"Ө","ӧ"=>"Ӧ","ӥ"=>"Ӥ","ӣ"=>"Ӣ","ӡ"=>"Ӡ","ӟ"=>"Ӟ","ӝ"=>"Ӝ",
+    "ӛ"=>"Ӛ","ә"=>"Ә","ӗ"=>"Ӗ","ӕ"=>"Ӕ","ӓ"=>"Ӓ","ӑ"=>"Ӑ","ӎ"=>"Ӎ","ӌ"=>"Ӌ","ӊ"=>"Ӊ","ӈ"=>"Ӈ",
+    "ӆ"=>"Ӆ","ӄ"=>"Ӄ","ӂ"=>"Ӂ","ҿ"=>"Ҿ","ҽ"=>"Ҽ","һ"=>"Һ","ҹ"=>"Ҹ","ҷ"=>"Ҷ","ҵ"=>"Ҵ","ҳ"=>"Ҳ",
+    "ұ"=>"Ұ","ү"=>"Ү","ҭ"=>"Ҭ","ҫ"=>"Ҫ","ҩ"=>"Ҩ","ҧ"=>"Ҧ","ҥ"=>"Ҥ","ң"=>"Ң","ҡ"=>"Ҡ","ҟ"=>"Ҟ",
+    "ҝ"=>"Ҝ","қ"=>"Қ","ҙ"=>"Ҙ","җ"=>"Җ","ҕ"=>"Ҕ","ғ"=>"Ғ","ґ"=>"Ґ","ҏ"=>"Ҏ","ҍ"=>"Ҍ","ҋ"=>"Ҋ",
+    "ҁ"=>"Ҁ","ѿ"=>"Ѿ","ѽ"=>"Ѽ","ѻ"=>"Ѻ","ѹ"=>"Ѹ","ѷ"=>"Ѷ","ѵ"=>"Ѵ","ѳ"=>"Ѳ","ѱ"=>"Ѱ","ѯ"=>"Ѯ",
+    "ѭ"=>"Ѭ","ѫ"=>"Ѫ","ѩ"=>"Ѩ","ѧ"=>"Ѧ","ѥ"=>"Ѥ","ѣ"=>"Ѣ","ѡ"=>"Ѡ","џ"=>"Џ","ў"=>"Ў","ѝ"=>"Ѝ",
+    "ќ"=>"Ќ","ћ"=>"Ћ","њ"=>"Њ","љ"=>"Љ","ј"=>"Ј","ї"=>"Ї","і"=>"І","ѕ"=>"Ѕ","є"=>"Є","ѓ"=>"Ѓ",
+    "ђ"=>"Ђ","ё"=>"Ё","ѐ"=>"Ѐ","я"=>"Я","ю"=>"Ю","э"=>"Э","ь"=>"Ь","ы"=>"Ы","ъ"=>"Ъ","щ"=>"Щ",
+    "ш"=>"Ш","ч"=>"Ч","ц"=>"Ц","х"=>"Х","ф"=>"Ф","у"=>"У","т"=>"Т","с"=>"С","р"=>"Р","п"=>"П",
+    "о"=>"О","н"=>"Н","м"=>"М","л"=>"Л","к"=>"К","й"=>"Й","и"=>"И","з"=>"З","ж"=>"Ж","е"=>"Е",
+    "д"=>"Д","г"=>"Г","в"=>"В","б"=>"Б","а"=>"А","ϵ"=>"Ε","ϲ"=>"Σ","ϱ"=>"Ρ","ϰ"=>"Κ","ϯ"=>"Ϯ",
+    "ϭ"=>"Ϭ","ϫ"=>"Ϫ","ϩ"=>"Ϩ","ϧ"=>"Ϧ","ϥ"=>"Ϥ","ϣ"=>"Ϣ","ϡ"=>"Ϡ","ϟ"=>"Ϟ","ϝ"=>"Ϝ","ϛ"=>"Ϛ",
+    "ϙ"=>"Ϙ","ϖ"=>"Π","ϕ"=>"Φ","ϑ"=>"Θ","ϐ"=>"Β","ώ"=>"Ώ","ύ"=>"Ύ","ό"=>"Ό","ϋ"=>"Ϋ","ϊ"=>"Ϊ",
+    "ω"=>"Ω","ψ"=>"Ψ","χ"=>"Χ","φ"=>"Φ","υ"=>"Υ","τ"=>"Τ","σ"=>"Σ","ς"=>"Σ","ρ"=>"Ρ","π"=>"Π",
+    "ο"=>"Ο","ξ"=>"Ξ","ν"=>"Ν","μ"=>"Μ","λ"=>"Λ","κ"=>"Κ","ι"=>"Ι","θ"=>"Θ","η"=>"Η","ζ"=>"Ζ",
+    "ε"=>"Ε","δ"=>"Δ","γ"=>"Γ","β"=>"Β","α"=>"Α","ί"=>"Ί","ή"=>"Ή","έ"=>"Έ","ά"=>"Ά","ʒ"=>"Ʒ",
+    "ʋ"=>"Ʋ","ʊ"=>"Ʊ","ʈ"=>"Ʈ","ʃ"=>"Ʃ","ʀ"=>"Ʀ","ɵ"=>"Ɵ","ɲ"=>"Ɲ","ɯ"=>"Ɯ","ɩ"=>"Ɩ","ɨ"=>"Ɨ",
+    "ɣ"=>"Ɣ","ɛ"=>"Ɛ","ə"=>"Ə","ɗ"=>"Ɗ","ɖ"=>"Ɖ","ɔ"=>"Ɔ","ɓ"=>"Ɓ","ȳ"=>"Ȳ","ȱ"=>"Ȱ","ȯ"=>"Ȯ",
+    "ȭ"=>"Ȭ","ȫ"=>"Ȫ","ȩ"=>"Ȩ","ȧ"=>"Ȧ","ȥ"=>"Ȥ","ȣ"=>"Ȣ","ȟ"=>"Ȟ","ȝ"=>"Ȝ","ț"=>"Ț","ș"=>"Ș",
+    "ȗ"=>"Ȗ","ȕ"=>"Ȕ","ȓ"=>"Ȓ","ȑ"=>"Ȑ","ȏ"=>"Ȏ","ȍ"=>"Ȍ","ȋ"=>"Ȋ","ȉ"=>"Ȉ","ȇ"=>"Ȇ","ȅ"=>"Ȅ",
+    "ȃ"=>"Ȃ","ȁ"=>"Ȁ","ǿ"=>"Ǿ","ǽ"=>"Ǽ","ǻ"=>"Ǻ","ǹ"=>"Ǹ","ǵ"=>"Ǵ","dz"=>"Dz","ǯ"=>"Ǯ","ǭ"=>"Ǭ",
+    "ǫ"=>"Ǫ","ǩ"=>"Ǩ","ǧ"=>"Ǧ","ǥ"=>"Ǥ","ǣ"=>"Ǣ","ǡ"=>"Ǡ","ǟ"=>"Ǟ","ǝ"=>"Ǝ","ǜ"=>"Ǜ","ǚ"=>"Ǚ",
+    "ǘ"=>"Ǘ","ǖ"=>"Ǖ","ǔ"=>"Ǔ","ǒ"=>"Ǒ","ǐ"=>"Ǐ","ǎ"=>"Ǎ","nj"=>"Nj","lj"=>"Lj","dž"=>"Dž","ƿ"=>"Ƿ",
+    "ƽ"=>"Ƽ","ƹ"=>"Ƹ","ƶ"=>"Ƶ","ƴ"=>"Ƴ","ư"=>"Ư","ƭ"=>"Ƭ","ƨ"=>"Ƨ","ƥ"=>"Ƥ","ƣ"=>"Ƣ","ơ"=>"Ơ",
+    "ƞ"=>"Ƞ","ƙ"=>"Ƙ","ƕ"=>"Ƕ","ƒ"=>"Ƒ","ƌ"=>"Ƌ","ƈ"=>"Ƈ","ƅ"=>"Ƅ","ƃ"=>"Ƃ","ſ"=>"S","ž"=>"Ž",
+    "ż"=>"Ż","ź"=>"Ź","ŷ"=>"Ŷ","ŵ"=>"Ŵ","ų"=>"Ų","ű"=>"Ű","ů"=>"Ů","ŭ"=>"Ŭ","ū"=>"Ū","ũ"=>"Ũ",
+    "ŧ"=>"Ŧ","ť"=>"Ť","ţ"=>"Ţ","š"=>"Š","ş"=>"Ş","ŝ"=>"Ŝ","ś"=>"Ś","ř"=>"Ř","ŗ"=>"Ŗ","ŕ"=>"Ŕ",
+    "œ"=>"Œ","ő"=>"Ő","ŏ"=>"Ŏ","ō"=>"Ō","ŋ"=>"Ŋ","ň"=>"Ň","ņ"=>"Ņ","ń"=>"Ń","ł"=>"Ł","ŀ"=>"Ŀ",
+    "ľ"=>"Ľ","ļ"=>"Ļ","ĺ"=>"Ĺ","ķ"=>"Ķ","ĵ"=>"Ĵ","ij"=>"IJ","ı"=>"I","į"=>"Į","ĭ"=>"Ĭ","ī"=>"Ī",
+    "ĩ"=>"Ĩ","ħ"=>"Ħ","ĥ"=>"Ĥ","ģ"=>"Ģ","ġ"=>"Ġ","ğ"=>"Ğ","ĝ"=>"Ĝ","ě"=>"Ě","ę"=>"Ę","ė"=>"Ė",
+    "ĕ"=>"Ĕ","ē"=>"Ē","đ"=>"Đ","ď"=>"Ď","č"=>"Č","ċ"=>"Ċ","ĉ"=>"Ĉ","ć"=>"Ć","ą"=>"Ą","ă"=>"Ă",
+    "ā"=>"Ā","ÿ"=>"Ÿ","þ"=>"Þ","ý"=>"Ý","ü"=>"Ü","û"=>"Û","ú"=>"Ú","ù"=>"Ù","ø"=>"Ø","ö"=>"Ö",
+    "õ"=>"Õ","ô"=>"Ô","ó"=>"Ó","ò"=>"Ò","ñ"=>"Ñ","ð"=>"Ð","ï"=>"Ï","î"=>"Î","í"=>"Í","ì"=>"Ì",
+    "ë"=>"Ë","ê"=>"Ê","é"=>"É","è"=>"È","ç"=>"Ç","æ"=>"Æ","å"=>"Å","ä"=>"Ä","ã"=>"Ã","â"=>"Â",
+    "á"=>"Á","à"=>"À","µ"=>"Μ","z"=>"Z","y"=>"Y","x"=>"X","w"=>"W","v"=>"V","u"=>"U","t"=>"T",
+    "s"=>"S","r"=>"R","q"=>"Q","p"=>"P","o"=>"O","n"=>"N","m"=>"M","l"=>"L","k"=>"K","j"=>"J",
+    "i"=>"I","h"=>"H","g"=>"G","f"=>"F","e"=>"E","d"=>"D","c"=>"C","b"=>"B","a"=>"A"
+  );
+
+  /**
+   * UTF-8 Case lookup table
+   *
+   * This lookuptable defines the lower case letters to their correspponding
+   * upper case letter in UTF-8
+   *
+   * @author Andreas Gohr <andi@splitbrain.org>
+   */
+  global $UTF8_UPPER_TO_LOWER;
+  $UTF8_UPPER_TO_LOWER = array (
+    "Z"=>"z","Y"=>"y","X"=>"x","W"=>"w","V"=>"v","U"=>"u","T"=>"t","S"=>"s","R"=>"r","Q"=>"q",
+    "P"=>"p","O"=>"o","N"=>"n","M"=>"m","L"=>"l","K"=>"k","J"=>"j","I"=>"i","H"=>"h","G"=>"g",
+    "F"=>"f","E"=>"e","D"=>"d","C"=>"c","B"=>"b","A"=>"a","ῼ"=>"ῳ","Ῥ"=>"ῥ","Ῡ"=>"ῡ","Ῑ"=>"ῑ",
+    "Ῐ"=>"ῐ","ῌ"=>"ῃ","Ι"=>"ι","ᾼ"=>"ᾳ","Ᾱ"=>"ᾱ","Ᾰ"=>"ᾰ","ᾯ"=>"ᾧ","ᾮ"=>"ᾦ","ᾭ"=>"ᾥ","ᾬ"=>"ᾤ",
+    "ᾫ"=>"ᾣ","ᾪ"=>"ᾢ","ᾩ"=>"ᾡ","ᾟ"=>"ᾗ","ᾞ"=>"ᾖ","ᾝ"=>"ᾕ","ᾜ"=>"ᾔ","ᾛ"=>"ᾓ","ᾚ"=>"ᾒ","ᾙ"=>"ᾑ",
+    "ᾘ"=>"ᾐ","ᾏ"=>"ᾇ","ᾎ"=>"ᾆ","ᾍ"=>"ᾅ","ᾌ"=>"ᾄ","ᾋ"=>"ᾃ","ᾊ"=>"ᾂ","ᾉ"=>"ᾁ","ᾈ"=>"ᾀ","Ώ"=>"ώ",
+    "Ὼ"=>"ὼ","Ύ"=>"ύ","Ὺ"=>"ὺ","Ό"=>"ό","Ὸ"=>"ὸ","Ί"=>"ί","Ὶ"=>"ὶ","Ή"=>"ή","Ὴ"=>"ὴ","Έ"=>"έ",
+    "Ὲ"=>"ὲ","Ά"=>"ά","Ὰ"=>"ὰ","Ὧ"=>"ὧ","Ὦ"=>"ὦ","Ὥ"=>"ὥ","Ὤ"=>"ὤ","Ὣ"=>"ὣ","Ὢ"=>"ὢ","Ὡ"=>"ὡ",
+    "Ὗ"=>"ὗ","Ὕ"=>"ὕ","Ὓ"=>"ὓ","Ὑ"=>"ὑ","Ὅ"=>"ὅ","Ὄ"=>"ὄ","Ὃ"=>"ὃ","Ὂ"=>"ὂ","Ὁ"=>"ὁ","Ὀ"=>"ὀ",
+    "Ἷ"=>"ἷ","Ἶ"=>"ἶ","Ἵ"=>"ἵ","Ἴ"=>"ἴ","Ἳ"=>"ἳ","Ἲ"=>"ἲ","Ἱ"=>"ἱ","Ἰ"=>"ἰ","Ἧ"=>"ἧ","Ἦ"=>"ἦ",
+    "Ἥ"=>"ἥ","Ἤ"=>"ἤ","Ἣ"=>"ἣ","Ἢ"=>"ἢ","Ἡ"=>"ἡ","Ἕ"=>"ἕ","Ἔ"=>"ἔ","Ἓ"=>"ἓ","Ἒ"=>"ἒ","Ἑ"=>"ἑ",
+    "Ἐ"=>"ἐ","Ἇ"=>"ἇ","Ἆ"=>"ἆ","Ἅ"=>"ἅ","Ἄ"=>"ἄ","Ἃ"=>"ἃ","Ἂ"=>"ἂ","Ἁ"=>"ἁ","Ἀ"=>"ἀ","Ỹ"=>"ỹ",
+    "Ỷ"=>"ỷ","Ỵ"=>"ỵ","Ỳ"=>"ỳ","Ự"=>"ự","Ữ"=>"ữ","Ử"=>"ử","Ừ"=>"ừ","Ứ"=>"ứ","Ủ"=>"ủ","Ụ"=>"ụ",
+    "Ợ"=>"ợ","Ỡ"=>"ỡ","Ở"=>"ở","Ờ"=>"ờ","Ớ"=>"ớ","Ộ"=>"ộ","Ỗ"=>"ỗ","Ổ"=>"ổ","Ồ"=>"ồ","Ố"=>"ố",
+    "Ỏ"=>"ỏ","Ọ"=>"ọ","Ị"=>"ị","Ỉ"=>"ỉ","Ệ"=>"ệ","Ễ"=>"ễ","Ể"=>"ể","Ề"=>"ề","Ế"=>"ế","Ẽ"=>"ẽ",
+    "Ẻ"=>"ẻ","Ẹ"=>"ẹ","Ặ"=>"ặ","Ẵ"=>"ẵ","Ẳ"=>"ẳ","Ằ"=>"ằ","Ắ"=>"ắ","Ậ"=>"ậ","Ẫ"=>"ẫ","Ẩ"=>"ẩ",
+    "Ầ"=>"ầ","Ấ"=>"ấ","Ả"=>"ả","Ạ"=>"ạ","Ṡ"=>"ẛ","Ẕ"=>"ẕ","Ẓ"=>"ẓ","Ẑ"=>"ẑ","Ẏ"=>"ẏ","Ẍ"=>"ẍ",
+    "Ẋ"=>"ẋ","Ẉ"=>"ẉ","Ẇ"=>"ẇ","Ẅ"=>"ẅ","Ẃ"=>"ẃ","Ẁ"=>"ẁ","Ṿ"=>"ṿ","Ṽ"=>"ṽ","Ṻ"=>"ṻ","Ṹ"=>"ṹ",
+    "Ṷ"=>"ṷ","Ṵ"=>"ṵ","Ṳ"=>"ṳ","Ṱ"=>"ṱ","Ṯ"=>"ṯ","Ṭ"=>"ṭ","Ṫ"=>"ṫ","Ṩ"=>"ṩ","Ṧ"=>"ṧ","Ṥ"=>"ṥ",
+    "Ṣ"=>"ṣ","Ṡ"=>"ṡ","Ṟ"=>"ṟ","Ṝ"=>"ṝ","Ṛ"=>"ṛ","Ṙ"=>"ṙ","Ṗ"=>"ṗ","Ṕ"=>"ṕ","Ṓ"=>"ṓ","Ṑ"=>"ṑ",
+    "Ṏ"=>"ṏ","Ṍ"=>"ṍ","Ṋ"=>"ṋ","Ṉ"=>"ṉ","Ṇ"=>"ṇ","Ṅ"=>"ṅ","Ṃ"=>"ṃ","Ṁ"=>"ṁ","Ḿ"=>"ḿ","Ḽ"=>"ḽ",
+    "Ḻ"=>"ḻ","Ḹ"=>"ḹ","Ḷ"=>"ḷ","Ḵ"=>"ḵ","Ḳ"=>"ḳ","Ḱ"=>"ḱ","Ḯ"=>"ḯ","Ḭ"=>"ḭ","Ḫ"=>"ḫ","Ḩ"=>"ḩ",
+    "Ḧ"=>"ḧ","Ḥ"=>"ḥ","Ḣ"=>"ḣ","Ḡ"=>"ḡ","Ḟ"=>"ḟ","Ḝ"=>"ḝ","Ḛ"=>"ḛ","Ḙ"=>"ḙ","Ḗ"=>"ḗ","Ḕ"=>"ḕ",
+    "Ḓ"=>"ḓ","Ḑ"=>"ḑ","Ḏ"=>"ḏ","Ḍ"=>"ḍ","Ḋ"=>"ḋ","Ḉ"=>"ḉ","Ḇ"=>"ḇ","Ḅ"=>"ḅ","Ḃ"=>"ḃ","Ḁ"=>"ḁ",
+    "Ֆ"=>"ֆ","Օ"=>"օ","Ք"=>"ք","Փ"=>"փ","Ւ"=>"ւ","Ց"=>"ց","Ր"=>"ր","Տ"=>"տ","Վ"=>"վ","Ս"=>"ս",
+    "Ռ"=>"ռ","Ջ"=>"ջ","Պ"=>"պ","Չ"=>"չ","Ո"=>"ո","Շ"=>"շ","Ն"=>"ն","Յ"=>"յ","Մ"=>"մ","Ճ"=>"ճ",
+    "Ղ"=>"ղ","Ձ"=>"ձ","Հ"=>"հ","Կ"=>"կ","Ծ"=>"ծ","Խ"=>"խ","Լ"=>"լ","Ի"=>"ի","Ժ"=>"ժ","Թ"=>"թ",
+    "Ը"=>"ը","Է"=>"է","Զ"=>"զ","Ե"=>"ե","Դ"=>"դ","Գ"=>"գ","Բ"=>"բ","Ա"=>"ա","Ԏ"=>"ԏ","Ԍ"=>"ԍ",
+    "Ԋ"=>"ԋ","Ԉ"=>"ԉ","Ԇ"=>"ԇ","Ԅ"=>"ԅ","Ԃ"=>"ԃ","Ԁ"=>"ԁ","Ӹ"=>"ӹ","Ӵ"=>"ӵ","Ӳ"=>"ӳ","Ӱ"=>"ӱ",
+    "Ӯ"=>"ӯ","Ӭ"=>"ӭ","Ӫ"=>"ӫ","Ө"=>"ө","Ӧ"=>"ӧ","Ӥ"=>"ӥ","Ӣ"=>"ӣ","Ӡ"=>"ӡ","Ӟ"=>"ӟ","Ӝ"=>"ӝ",
+    "Ӛ"=>"ӛ","Ә"=>"ә","Ӗ"=>"ӗ","Ӕ"=>"ӕ","Ӓ"=>"ӓ","Ӑ"=>"ӑ","Ӎ"=>"ӎ","Ӌ"=>"ӌ","Ӊ"=>"ӊ","Ӈ"=>"ӈ",
+    "Ӆ"=>"ӆ","Ӄ"=>"ӄ","Ӂ"=>"ӂ","Ҿ"=>"ҿ","Ҽ"=>"ҽ","Һ"=>"һ","Ҹ"=>"ҹ","Ҷ"=>"ҷ","Ҵ"=>"ҵ","Ҳ"=>"ҳ",
+    "Ұ"=>"ұ","Ү"=>"ү","Ҭ"=>"ҭ","Ҫ"=>"ҫ","Ҩ"=>"ҩ","Ҧ"=>"ҧ","Ҥ"=>"ҥ","Ң"=>"ң","Ҡ"=>"ҡ","Ҟ"=>"ҟ",
+    "Ҝ"=>"ҝ","Қ"=>"қ","Ҙ"=>"ҙ","Җ"=>"җ","Ҕ"=>"ҕ","Ғ"=>"ғ","Ґ"=>"ґ","Ҏ"=>"ҏ","Ҍ"=>"ҍ","Ҋ"=>"ҋ",
+    "Ҁ"=>"ҁ","Ѿ"=>"ѿ","Ѽ"=>"ѽ","Ѻ"=>"ѻ","Ѹ"=>"ѹ","Ѷ"=>"ѷ","Ѵ"=>"ѵ","Ѳ"=>"ѳ","Ѱ"=>"ѱ","Ѯ"=>"ѯ",
+    "Ѭ"=>"ѭ","Ѫ"=>"ѫ","Ѩ"=>"ѩ","Ѧ"=>"ѧ","Ѥ"=>"ѥ","Ѣ"=>"ѣ","Ѡ"=>"ѡ","Џ"=>"џ","Ў"=>"ў","Ѝ"=>"ѝ",
+    "Ќ"=>"ќ","Ћ"=>"ћ","Њ"=>"њ","Љ"=>"љ","Ј"=>"ј","Ї"=>"ї","І"=>"і","Ѕ"=>"ѕ","Є"=>"є","Ѓ"=>"ѓ",
+    "Ђ"=>"ђ","Ё"=>"ё","Ѐ"=>"ѐ","Я"=>"я","Ю"=>"ю","Э"=>"э","Ь"=>"ь","Ы"=>"ы","Ъ"=>"ъ","Щ"=>"щ",
+    "Ш"=>"ш","Ч"=>"ч","Ц"=>"ц","Х"=>"х","Ф"=>"ф","У"=>"у","Т"=>"т","С"=>"с","Р"=>"р","П"=>"п",
+    "О"=>"о","Н"=>"н","М"=>"м","Л"=>"л","К"=>"к","Й"=>"й","И"=>"и","З"=>"з","Ж"=>"ж","Е"=>"е",
+    "Д"=>"д","Г"=>"г","В"=>"в","Б"=>"б","А"=>"а","Ε"=>"ϵ","Σ"=>"ϲ","Ρ"=>"ϱ","Κ"=>"ϰ","Ϯ"=>"ϯ",
+    "Ϭ"=>"ϭ","Ϫ"=>"ϫ","Ϩ"=>"ϩ","Ϧ"=>"ϧ","Ϥ"=>"ϥ","Ϣ"=>"ϣ","Ϡ"=>"ϡ","Ϟ"=>"ϟ","Ϝ"=>"ϝ","Ϛ"=>"ϛ",
+    "Ϙ"=>"ϙ","Π"=>"ϖ","Φ"=>"ϕ","Θ"=>"ϑ","Β"=>"ϐ","Ώ"=>"ώ","Ύ"=>"ύ","Ό"=>"ό","Ϋ"=>"ϋ","Ϊ"=>"ϊ",
+    "Ω"=>"ω","Ψ"=>"ψ","Χ"=>"χ","Φ"=>"φ","Υ"=>"υ","Τ"=>"τ","Σ"=>"σ","Σ"=>"ς","Ρ"=>"ρ","Π"=>"π",
+    "Ο"=>"ο","Ξ"=>"ξ","Ν"=>"ν","Μ"=>"μ","Λ"=>"λ","Κ"=>"κ","Ι"=>"ι","Θ"=>"θ","Η"=>"η","Ζ"=>"ζ",
+    "Ε"=>"ε","Δ"=>"δ","Γ"=>"γ","Β"=>"β","Α"=>"α","Ί"=>"ί","Ή"=>"ή","Έ"=>"έ","Ά"=>"ά","Ʒ"=>"ʒ",
+    "Ʋ"=>"ʋ","Ʊ"=>"ʊ","Ʈ"=>"ʈ","Ʃ"=>"ʃ","Ʀ"=>"ʀ","Ɵ"=>"ɵ","Ɲ"=>"ɲ","Ɯ"=>"ɯ","Ɩ"=>"ɩ","Ɨ"=>"ɨ",
+    "Ɣ"=>"ɣ","Ɛ"=>"ɛ","Ə"=>"ə","Ɗ"=>"ɗ","Ɖ"=>"ɖ","Ɔ"=>"ɔ","Ɓ"=>"ɓ","Ȳ"=>"ȳ","Ȱ"=>"ȱ","Ȯ"=>"ȯ",
+    "Ȭ"=>"ȭ","Ȫ"=>"ȫ","Ȩ"=>"ȩ","Ȧ"=>"ȧ","Ȥ"=>"ȥ","Ȣ"=>"ȣ","Ȟ"=>"ȟ","Ȝ"=>"ȝ","Ț"=>"ț","Ș"=>"ș",
+    "Ȗ"=>"ȗ","Ȕ"=>"ȕ","Ȓ"=>"ȓ","Ȑ"=>"ȑ","Ȏ"=>"ȏ","Ȍ"=>"ȍ","Ȋ"=>"ȋ","Ȉ"=>"ȉ","Ȇ"=>"ȇ","Ȅ"=>"ȅ",
+    "Ȃ"=>"ȃ","Ȁ"=>"ȁ","Ǿ"=>"ǿ","Ǽ"=>"ǽ","Ǻ"=>"ǻ","Ǹ"=>"ǹ","Ǵ"=>"ǵ","Dz"=>"dz","Ǯ"=>"ǯ","Ǭ"=>"ǭ",
+    "Ǫ"=>"ǫ","Ǩ"=>"ǩ","Ǧ"=>"ǧ","Ǥ"=>"ǥ","Ǣ"=>"ǣ","Ǡ"=>"ǡ","Ǟ"=>"ǟ","Ǝ"=>"ǝ","Ǜ"=>"ǜ","Ǚ"=>"ǚ",
+    "Ǘ"=>"ǘ","Ǖ"=>"ǖ","Ǔ"=>"ǔ","Ǒ"=>"ǒ","Ǐ"=>"ǐ","Ǎ"=>"ǎ","Nj"=>"nj","Lj"=>"lj","Dž"=>"dž","Ƿ"=>"ƿ",
+    "Ƽ"=>"ƽ","Ƹ"=>"ƹ","Ƶ"=>"ƶ","Ƴ"=>"ƴ","Ư"=>"ư","Ƭ"=>"ƭ","Ƨ"=>"ƨ","Ƥ"=>"ƥ","Ƣ"=>"ƣ","Ơ"=>"ơ",
+    "Ƞ"=>"ƞ","Ƙ"=>"ƙ","Ƕ"=>"ƕ","Ƒ"=>"ƒ","Ƌ"=>"ƌ","Ƈ"=>"ƈ","Ƅ"=>"ƅ","Ƃ"=>"ƃ","S"=>"ſ","Ž"=>"ž",
+    "Ż"=>"ż","Ź"=>"ź","Ŷ"=>"ŷ","Ŵ"=>"ŵ","Ų"=>"ų","Ű"=>"ű","Ů"=>"ů","Ŭ"=>"ŭ","Ū"=>"ū","Ũ"=>"ũ",
+    "Ŧ"=>"ŧ","Ť"=>"ť","Ţ"=>"ţ","Š"=>"š","Ş"=>"ş","Ŝ"=>"ŝ","Ś"=>"ś","Ř"=>"ř","Ŗ"=>"ŗ","Ŕ"=>"ŕ",
+    "Œ"=>"œ","Ő"=>"ő","Ŏ"=>"ŏ","Ō"=>"ō","Ŋ"=>"ŋ","Ň"=>"ň","Ņ"=>"ņ","Ń"=>"ń","Ł"=>"ł","Ŀ"=>"ŀ",
+    "Ľ"=>"ľ","Ļ"=>"ļ","Ĺ"=>"ĺ","Ķ"=>"ķ","Ĵ"=>"ĵ","IJ"=>"ij","I"=>"ı","Į"=>"į","Ĭ"=>"ĭ","Ī"=>"ī",
+    "Ĩ"=>"ĩ","Ħ"=>"ħ","Ĥ"=>"ĥ","Ģ"=>"ģ","Ġ"=>"ġ","Ğ"=>"ğ","Ĝ"=>"ĝ","Ě"=>"ě","Ę"=>"ę","Ė"=>"ė",
+    "Ĕ"=>"ĕ","Ē"=>"ē","Đ"=>"đ","Ď"=>"ď","Č"=>"č","Ċ"=>"ċ","Ĉ"=>"ĉ","Ć"=>"ć","Ą"=>"ą","Ă"=>"ă",
+    "Ā"=>"ā","Ÿ"=>"ÿ","Þ"=>"þ","Ý"=>"ý","Ü"=>"ü","Û"=>"û","Ú"=>"ú","Ù"=>"ù","Ø"=>"ø","Ö"=>"ö",
+    "Õ"=>"õ","Ô"=>"ô","Ó"=>"ó","Ò"=>"ò","Ñ"=>"ñ","Ð"=>"ð","Ï"=>"ï","Î"=>"î","Í"=>"í","Ì"=>"ì",
+    "Ë"=>"ë","Ê"=>"ê","É"=>"é","È"=>"è","Ç"=>"ç","Æ"=>"æ","Å"=>"å","Ä"=>"ä","Ã"=>"ã","Â"=>"â",
+    "Á"=>"á","À"=>"à","Μ"=>"µ","Z"=>"z","Y"=>"y","X"=>"x","W"=>"w","V"=>"v","U"=>"u","T"=>"t",
+    "S"=>"s","R"=>"r","Q"=>"q","P"=>"p","O"=>"o","N"=>"n","M"=>"m","L"=>"l","K"=>"k","J"=>"j",
+    "I"=>"i","H"=>"h","G"=>"g","F"=>"f","E"=>"e","D"=>"d","C"=>"c","B"=>"b","A"=>"a"
+  );
+}; // end of case lookup tables
+
+/**
+ * UTF-8 lookup table for lower case accented letters
+ *
+ * This lookuptable defines replacements for accented characters from the ASCII-7
+ * range. This are lower case letters only.
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @see    utf8_deaccent()
+ */
+global $UTF8_LOWER_ACCENTS;
+$UTF8_LOWER_ACCENTS = array(
+  'à' => 'a', 'ô' => 'o', 'ď' => 'd', 'ḟ' => 'f', 'ë' => 'e', 'š' => 's', 'ơ' => 'o',
+  'ß' => 'ss', 'ă' => 'a', 'ř' => 'r', 'ț' => 't', 'ň' => 'n', 'ā' => 'a', 'ķ' => 'k',
+  'ŝ' => 's', 'ỳ' => 'y', 'ņ' => 'n', 'ĺ' => 'l', 'ħ' => 'h', 'ṗ' => 'p', 'ó' => 'o',
+  'ú' => 'u', 'ě' => 'e', 'é' => 'e', 'ç' => 'c', 'ẁ' => 'w', 'ċ' => 'c', 'õ' => 'o',
+  'ṡ' => 's', 'ø' => 'o', 'ģ' => 'g', 'ŧ' => 't', 'ș' => 's', 'ė' => 'e', 'ĉ' => 'c',
+  'ś' => 's', 'î' => 'i', 'ű' => 'u', 'ć' => 'c', 'ę' => 'e', 'ŵ' => 'w', 'ṫ' => 't',
+  'ū' => 'u', 'č' => 'c', 'ö' => 'oe', 'è' => 'e', 'ŷ' => 'y', 'ą' => 'a', 'ł' => 'l',
+  'ų' => 'u', 'ů' => 'u', 'ş' => 's', 'ğ' => 'g', 'ļ' => 'l', 'ƒ' => 'f', 'ž' => 'z',
+  'ẃ' => 'w', 'ḃ' => 'b', 'å' => 'a', 'ì' => 'i', 'ï' => 'i', 'ḋ' => 'd', 'ť' => 't',
+  'ŗ' => 'r', 'ä' => 'ae', 'í' => 'i', 'ŕ' => 'r', 'ê' => 'e', 'ü' => 'ue', 'ò' => 'o',
+  'ē' => 'e', 'ñ' => 'n', 'ń' => 'n', 'ĥ' => 'h', 'ĝ' => 'g', 'đ' => 'd', 'ĵ' => 'j',
+  'ÿ' => 'y', 'ũ' => 'u', 'ŭ' => 'u', 'ư' => 'u', 'ţ' => 't', 'ý' => 'y', 'ő' => 'o',
+  'â' => 'a', 'ľ' => 'l', 'ẅ' => 'w', 'ż' => 'z', 'ī' => 'i', 'ã' => 'a', 'ġ' => 'g',
+  'ṁ' => 'm', 'ō' => 'o', 'ĩ' => 'i', 'ù' => 'u', 'į' => 'i', 'ź' => 'z', 'á' => 'a',
+  'û' => 'u', 'þ' => 'th', 'ð' => 'dh', 'æ' => 'ae', 'µ' => 'u', 'ĕ' => 'e',
+);
+
+/**
+ * UTF-8 lookup table for upper case accented letters
+ *
+ * This lookuptable defines replacements for accented characters from the ASCII-7
+ * range. This are upper case letters only.
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @see    utf8_deaccent()
+ */
+global $UTF8_UPPER_ACCENTS;
+$UTF8_UPPER_ACCENTS = array(
+  'À' => 'A', 'Ô' => 'O', 'Ď' => 'D', 'Ḟ' => 'F', 'Ë' => 'E', 'Š' => 'S', 'Ơ' => 'O',
+  'Ă' => 'A', 'Ř' => 'R', 'Ț' => 'T', 'Ň' => 'N', 'Ā' => 'A', 'Ķ' => 'K',
+  'Ŝ' => 'S', 'Ỳ' => 'Y', 'Ņ' => 'N', 'Ĺ' => 'L', 'Ħ' => 'H', 'Ṗ' => 'P', 'Ó' => 'O',
+  'Ú' => 'U', 'Ě' => 'E', 'É' => 'E', 'Ç' => 'C', 'Ẁ' => 'W', 'Ċ' => 'C', 'Õ' => 'O',
+  'Ṡ' => 'S', 'Ø' => 'O', 'Ģ' => 'G', 'Ŧ' => 'T', 'Ș' => 'S', 'Ė' => 'E', 'Ĉ' => 'C',
+  'Ś' => 'S', 'Î' => 'I', 'Ű' => 'U', 'Ć' => 'C', 'Ę' => 'E', 'Ŵ' => 'W', 'Ṫ' => 'T',
+  'Ū' => 'U', 'Č' => 'C', 'Ö' => 'Oe', 'È' => 'E', 'Ŷ' => 'Y', 'Ą' => 'A', 'Ł' => 'L',
+  'Ų' => 'U', 'Ů' => 'U', 'Ş' => 'S', 'Ğ' => 'G', 'Ļ' => 'L', 'Ƒ' => 'F', 'Ž' => 'Z',
+  'Ẃ' => 'W', 'Ḃ' => 'B', 'Å' => 'A', 'Ì' => 'I', 'Ï' => 'I', 'Ḋ' => 'D', 'Ť' => 'T',
+  'Ŗ' => 'R', 'Ä' => 'Ae', 'Í' => 'I', 'Ŕ' => 'R', 'Ê' => 'E', 'Ü' => 'Ue', 'Ò' => 'O',
+  'Ē' => 'E', 'Ñ' => 'N', 'Ń' => 'N', 'Ĥ' => 'H', 'Ĝ' => 'G', 'Đ' => 'D', 'Ĵ' => 'J',
+  'Ÿ' => 'Y', 'Ũ' => 'U', 'Ŭ' => 'U', 'Ư' => 'U', 'Ţ' => 'T', 'Ý' => 'Y', 'Ő' => 'O',
+  'Â' => 'A', 'Ľ' => 'L', 'Ẅ' => 'W', 'Ż' => 'Z', 'Ī' => 'I', 'Ã' => 'A', 'Ġ' => 'G',
+  'Ṁ' => 'M', 'Ō' => 'O', 'Ĩ' => 'I', 'Ù' => 'U', 'Į' => 'I', 'Ź' => 'Z', 'Á' => 'A',
+  'Û' => 'U', 'Þ' => 'Th', 'Ð' => 'Dh', 'Æ' => 'Ae', 'Ĕ' => 'E',
+);
+
+/**
+ * UTF-8 array of common special characters
+ *
+ * This array should contain all special characters (not a letter or digit)
+ * defined in the various local charsets - it's not a complete list of non-alphanum
+ * characters in UTF-8. It's not perfect but should match most cases of special
+ * chars.
+ *
+ * The controlchars 0x00 to 0x19 are _not_ included in this array. The space 0x20 is!
+ * These chars are _not_ in the array either:  _ (0x5f), : 0x3a, . 0x2e, - 0x2d, * 0x2a
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @see    utf8_stripspecials()
+ */
+global $UTF8_SPECIAL_CHARS;
+$UTF8_SPECIAL_CHARS = array(
+  0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023,
+  0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029,         0x002b, 0x002c,
+          0x002f,         0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x005b,
+  0x005c, 0x005d, 0x005e,         0x0060, 0x007b, 0x007c, 0x007d, 0x007e,
+  0x007f, 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088,
+  0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 0x0092,
+  0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c,
+  0x009d, 0x009e, 0x009f, 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6,
+  0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, 0x00b0,
+  0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba,
+  0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, 0x00d7, 0x00f7, 0x02c7, 0x02d8, 0x02d9,
+  0x02da, 0x02db, 0x02dc, 0x02dd, 0x0300, 0x0301, 0x0303, 0x0309, 0x0323, 0x0384,
+  0x0385, 0x0387, 0x03b2, 0x03c6, 0x03d1, 0x03d2, 0x03d5, 0x03d6, 0x05b0, 0x05b1,
+  0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7, 0x05b8, 0x05b9, 0x05bb, 0x05bc,
+  0x05bd, 0x05be, 0x05bf, 0x05c0, 0x05c1, 0x05c2, 0x05c3, 0x05f3, 0x05f4, 0x060c,
+  0x061b, 0x061f, 0x0640, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f, 0x0650, 0x0651,
+  0x0652, 0x066a, 0x0e3f, 0x200c, 0x200d, 0x200e, 0x200f, 0x2013, 0x2014, 0x2015,
+  0x2017, 0x2018, 0x2019, 0x201a, 0x201c, 0x201d, 0x201e, 0x2020, 0x2021, 0x2022,
+  0x2026, 0x2030, 0x2032, 0x2033, 0x2039, 0x203a, 0x2044, 0x20a7, 0x20aa, 0x20ab,
+  0x20ac, 0x2116, 0x2118, 0x2122, 0x2126, 0x2135, 0x2190, 0x2191, 0x2192, 0x2193,
+  0x2194, 0x2195, 0x21b5, 0x21d0, 0x21d1, 0x21d2, 0x21d3, 0x21d4, 0x2200, 0x2202,
+  0x2203, 0x2205, 0x2206, 0x2207, 0x2208, 0x2209, 0x220b, 0x220f, 0x2211, 0x2212,
+  0x2215, 0x2217, 0x2219, 0x221a, 0x221d, 0x221e, 0x2220, 0x2227, 0x2228, 0x2229,
+  0x222a, 0x222b, 0x2234, 0x223c, 0x2245, 0x2248, 0x2260, 0x2261, 0x2264, 0x2265,
+  0x2282, 0x2283, 0x2284, 0x2286, 0x2287, 0x2295, 0x2297, 0x22a5, 0x22c5, 0x2310,
+  0x2320, 0x2321, 0x2329, 0x232a, 0x2469, 0x2500, 0x2502, 0x250c, 0x2510, 0x2514,
+  0x2518, 0x251c, 0x2524, 0x252c, 0x2534, 0x253c, 0x2550, 0x2551, 0x2552, 0x2553,
+  0x2554, 0x2555, 0x2556, 0x2557, 0x2558, 0x2559, 0x255a, 0x255b, 0x255c, 0x255d,
+  0x255e, 0x255f, 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567,
+  0x2568, 0x2569, 0x256a, 0x256b, 0x256c, 0x2580, 0x2584, 0x2588, 0x258c, 0x2590,
+  0x2591, 0x2592, 0x2593, 0x25a0, 0x25b2, 0x25bc, 0x25c6, 0x25ca, 0x25cf, 0x25d7,
+  0x2605, 0x260e, 0x261b, 0x261e, 0x2660, 0x2663, 0x2665, 0x2666, 0x2701, 0x2702,
+  0x2703, 0x2704, 0x2706, 0x2707, 0x2708, 0x2709, 0x270c, 0x270d, 0x270e, 0x270f,
+  0x2710, 0x2711, 0x2712, 0x2713, 0x2714, 0x2715, 0x2716, 0x2717, 0x2718, 0x2719,
+  0x271a, 0x271b, 0x271c, 0x271d, 0x271e, 0x271f, 0x2720, 0x2721, 0x2722, 0x2723,
+  0x2724, 0x2725, 0x2726, 0x2727, 0x2729, 0x272a, 0x272b, 0x272c, 0x272d, 0x272e,
+  0x272f, 0x2730, 0x2731, 0x2732, 0x2733, 0x2734, 0x2735, 0x2736, 0x2737, 0x2738,
+  0x2739, 0x273a, 0x273b, 0x273c, 0x273d, 0x273e, 0x273f, 0x2740, 0x2741, 0x2742,
+  0x2743, 0x2744, 0x2745, 0x2746, 0x2747, 0x2748, 0x2749, 0x274a, 0x274b, 0x274d,
+  0x274f, 0x2750, 0x2751, 0x2752, 0x2756, 0x2758, 0x2759, 0x275a, 0x275b, 0x275c,
+  0x275d, 0x275e, 0x2761, 0x2762, 0x2763, 0x2764, 0x2765, 0x2766, 0x2767, 0x277f,
+  0x2789, 0x2793, 0x2794, 0x2798, 0x2799, 0x279a, 0x279b, 0x279c, 0x279d, 0x279e,
+  0x279f, 0x27a0, 0x27a1, 0x27a2, 0x27a3, 0x27a4, 0x27a5, 0x27a6, 0x27a7, 0x27a8,
+  0x27a9, 0x27aa, 0x27ab, 0x27ac, 0x27ad, 0x27ae, 0x27af, 0x27b1, 0x27b2, 0x27b3,
+  0x27b4, 0x27b5, 0x27b6, 0x27b7, 0x27b8, 0x27b9, 0x27ba, 0x27bb, 0x27bc, 0x27bd,
+  0x27be, 0x3000, 0x3001, 0x3002, 0x3003, 0x3008, 0x3009, 0x300a, 0x300b, 0x300c,
+  0x300d, 0x300e, 0x300f, 0x3010, 0x3011, 0x3012, 0x3014, 0x3015, 0x3016, 0x3017,
+  0x3018, 0x3019, 0x301a, 0x301b, 0x3036,
+  0xf6d9, 0xf6da, 0xf6db, 0xf8d7, 0xf8d8, 0xf8d9, 0xf8da, 0xf8db, 0xf8dc,
+  0xf8dd, 0xf8de, 0xf8df, 0xf8e0, 0xf8e1, 0xf8e2, 0xf8e3, 0xf8e4, 0xf8e5, 0xf8e6,
+  0xf8e7, 0xf8e8, 0xf8e9, 0xf8ea, 0xf8eb, 0xf8ec, 0xf8ed, 0xf8ee, 0xf8ef, 0xf8f0,
+  0xf8f1, 0xf8f2, 0xf8f3, 0xf8f4, 0xf8f5, 0xf8f6, 0xf8f7, 0xf8f8, 0xf8f9, 0xf8fa,
+  0xf8fb, 0xf8fc, 0xf8fd, 0xf8fe, 0xfe7c, 0xfe7d,
+          0xff01, 0xff02, 0xff03, 0xff04, 0xff05, 0xff06, 0xff07, 0xff08, 0xff09,
+  0xff09, 0xff0a, 0xff0b, 0xff0c, 0xff0d, 0xff0e, 0xff0f, 0xff1a, 0xff1b, 0xff1c,
+  0xff1d, 0xff1e, 0xff1f, 0xff20, 0xff3b, 0xff3c, 0xff3d, 0xff3e, 0xff40, 0xff5b,
+  0xff5c, 0xff5d, 0xff5e, 0xff5f, 0xff60, 0xff61, 0xff62, 0xff63, 0xff64, 0xff65,
+  0xffe0, 0xffe1, 0xffe2, 0xffe3, 0xffe4, 0xffe5, 0xffe6, 0xffe8, 0xffe9, 0xffea,
+  0xffeb, 0xffec, 0xffed, 0xffee,
+);
+
+// utf8 version of above data
+global $UTF8_SPECIAL_CHARS2;
+$UTF8_SPECIAL_CHARS2 =
+    "\x1A".'\e\1c\1d\1e\1f !"#$%&\'()+,/;<=>?@[\]^`{|}~\7f\80\81\82\83\84\85\86\87\88\89\8a\8b\8c\8d\8e\8f\90\91\92\93\94\95�'.
+    '�\97\98\99\9a\9b\9c\9d\9e\9f ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½�'.
+    '�¿×÷ˇ˘˙˚˛˜˝̣̀́̃̉΄΅·βφϑϒϕϖְֱֲֳִֵֶַָֹֻּֽ־ֿ�'.
+    '�ׁׂ׃׳״،؛؟ـًٌٍَُِّْ٪฿‌‍‎‏–—―‗‘’‚“”�'.
+    '��†‡•…‰′″‹›⁄₧₪₫€№℘™Ωℵ←↑→↓↔↕↵'.
+    '⇐⇑⇒⇓⇔∀∂∃∅∆∇∈∉∋∏∑−∕∗∙√∝∞∠∧∨�'.
+    '�∪∫∴∼≅≈≠≡≤≥⊂⊃⊄⊆⊇⊕⊗⊥⋅⌐⌠⌡〈〉⑩─�'.
+    '��┌┐└┘├┤┬┴┼═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟╠'.
+    '╡╢╣╤╥╦╧╨╩╪╫╬▀▄█▌▐░▒▓■▲▼◆◊●�'.
+    '�★☎☛☞♠♣♥♦✁✂✃✄✆✇✈✉✌✍✎✏✐✑✒✓✔✕�'.
+    '��✗✘✙✚✛✜✝✞✟✠✡✢✣✤✥✦✧✩✪✫✬✭✮✯✰✱'.
+    '✲✳✴✵✶✷✸✹✺✻✼✽✾✿❀❁❂❃❄❅❆❇❈❉❊❋�'.
+    '�❏❐❑❒❖❘❙❚❛❜❝❞❡❢❣❤❥❦❧❿➉➓➔➘➙➚�'.
+    '��➜➝➞➟➠➡➢➣➤➥➦➧➨➩➪➫➬➭➮➯➱➲➳➴➵➶'.
+    '➷➸➹➺➻➼➽➾'.
+    ' 、。〃〈〉《》「」『』【】〒〔〕〖〗〘〙〚〛〶'.
+    '�'.
+    '�ﹼﹽ'.
+    '!"#$%&'()*+,-./:;<=>?@[\]^`{|}~'.
+    '⦅⦆。「」、・¢£¬ ̄¦¥₩│←↑→↓■○';
+
+/**
+ * Romanization lookup table
+ *
+ * This lookup tables provides a way to transform strings written in a language
+ * different from the ones based upon latin letters into plain ASCII.
+ *
+ * Please note: this is not a scientific transliteration table. It only works
+ * oneway from nonlatin to ASCII and it works by simple character replacement
+ * only. Specialities of each language are not supported.
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Vitaly Blokhin <vitinfo@vitn.com>
+ * @link   http://www.uconv.com/translit.htm
+ * @author Bisqwit <bisqwit@iki.fi>
+ * @link   http://kanjidict.stc.cx/hiragana.php?src=2
+ * @link   http://www.translatum.gr/converter/greek-transliteration.htm
+ * @link   http://en.wikipedia.org/wiki/Royal_Thai_General_System_of_Transcription
+ * @link   http://www.btranslations.com/resources/romanization/korean.asp
+ */
+global $UTF8_ROMANIZATION;
+$UTF8_ROMANIZATION = array(
+  //russian cyrillic
+  'а'=>'a','А'=>'A','б'=>'b','Б'=>'B','в'=>'v','В'=>'V','г'=>'g','Г'=>'G',
+  'д'=>'d','Д'=>'D','е'=>'e','Е'=>'E','ё'=>'jo','Ё'=>'Jo','ж'=>'zh','Ж'=>'Zh',
+  'з'=>'z','З'=>'Z','и'=>'i','И'=>'I','й'=>'j','Й'=>'J','к'=>'k','К'=>'K',
+  'л'=>'l','Л'=>'L','м'=>'m','М'=>'M','н'=>'n','Н'=>'N','о'=>'o','О'=>'O',
+  'п'=>'p','П'=>'P','р'=>'r','Р'=>'R','с'=>'s','С'=>'S','т'=>'t','Т'=>'T',
+  'у'=>'u','У'=>'U','ф'=>'f','Ф'=>'F','х'=>'x','Х'=>'X','ц'=>'c','Ц'=>'C',
+  'ч'=>'ch','Ч'=>'Ch','ш'=>'sh','Ш'=>'Sh','щ'=>'sch','Щ'=>'Sch','ъ'=>'',
+  'Ъ'=>'','ы'=>'y','Ы'=>'Y','ь'=>'','Ь'=>'','э'=>'eh','Э'=>'Eh','ю'=>'ju',
+  'Ю'=>'Ju','я'=>'ja','Я'=>'Ja',
+  // Ukrainian cyrillic
+  'Ґ'=>'Gh','ґ'=>'gh','Є'=>'Je','є'=>'je','І'=>'I','і'=>'i','Ї'=>'Ji','ї'=>'ji',
+  // Georgian
+  'ა'=>'a','ბ'=>'b','გ'=>'g','დ'=>'d','ე'=>'e','ვ'=>'v','ზ'=>'z','თ'=>'th',
+  'ი'=>'i','კ'=>'p','ლ'=>'l','მ'=>'m','ნ'=>'n','ო'=>'o','პ'=>'p','ჟ'=>'zh',
+  'რ'=>'r','ს'=>'s','ტ'=>'t','უ'=>'u','ფ'=>'ph','ქ'=>'kh','ღ'=>'gh','ყ'=>'q',
+  'შ'=>'sh','ჩ'=>'ch','ც'=>'c','ძ'=>'dh','წ'=>'w','ჭ'=>'j','ხ'=>'x','ჯ'=>'jh',
+  'ჰ'=>'xh',
+  //Sanskrit
+  'अ'=>'a','आ'=>'ah','इ'=>'i','ई'=>'ih','उ'=>'u','ऊ'=>'uh','ऋ'=>'ry',
+  'ॠ'=>'ryh','ऌ'=>'ly','ॡ'=>'lyh','ए'=>'e','ऐ'=>'ay','ओ'=>'o','औ'=>'aw',
+  'अं'=>'amh','अः'=>'aq','क'=>'k','ख'=>'kh','ग'=>'g','घ'=>'gh','ङ'=>'nh',
+  'च'=>'c','छ'=>'ch','ज'=>'j','झ'=>'jh','ञ'=>'ny','ट'=>'tq','ठ'=>'tqh',
+  'ड'=>'dq','ढ'=>'dqh','ण'=>'nq','त'=>'t','थ'=>'th','द'=>'d','ध'=>'dh',
+  'न'=>'n','प'=>'p','फ'=>'ph','ब'=>'b','भ'=>'bh','म'=>'m','य'=>'z','र'=>'r',
+  'ल'=>'l','व'=>'v','श'=>'sh','ष'=>'sqh','स'=>'s','ह'=>'x',
+  //Hebrew
+  'א'=>'a', 'ב'=>'b','ג'=>'g','ד'=>'d','ה'=>'h','ו'=>'v','ז'=>'z','ח'=>'kh','ט'=>'th',
+  'י'=>'y','ך'=>'h','כ'=>'k','ל'=>'l','ם'=>'m','מ'=>'m','ן'=>'n','נ'=>'n',
+  'ס'=>'s','ע'=>'ah','ף'=>'f','פ'=>'p','ץ'=>'c','צ'=>'c','ק'=>'q','ר'=>'r',
+  'ש'=>'sh','ת'=>'t',
+  //Arabic
+  'ا'=>'a','ب'=>'b','ت'=>'t','ث'=>'th','ج'=>'g','ح'=>'xh','خ'=>'x','د'=>'d',
+  'ذ'=>'dh','ر'=>'r','ز'=>'z','س'=>'s','ش'=>'sh','ص'=>'s\'','ض'=>'d\'',
+  'ط'=>'t\'','ظ'=>'z\'','ع'=>'y','غ'=>'gh','ف'=>'f','ق'=>'q','ك'=>'k',
+  'ل'=>'l','م'=>'m','ن'=>'n','ه'=>'x\'','و'=>'u','ي'=>'i',
+
+  // Japanese hiragana
+  'あ'=>'a','え'=>'e','い'=>'i','お'=>'o','う'=>'u','ば'=>'ba','べ'=>'be',
+  'び'=>'bi','ぼ'=>'bo','ぶ'=>'bu','し'=>'ci','だ'=>'da','で'=>'de','ぢ'=>'di',
+  'ど'=>'do','づ'=>'du','ふぁ'=>'fa','ふぇ'=>'fe','ふぃ'=>'fi','ふぉ'=>'fo',
+  'ふ'=>'fu','が'=>'ga','げ'=>'ge','ぎ'=>'gi','ご'=>'go','ぐ'=>'gu','は'=>'ha',
+  'へ'=>'he','ひ'=>'hi','ほ'=>'ho','ふ'=>'hu','じゃ'=>'ja','じぇ'=>'je',
+  'じ'=>'ji','じょ'=>'jo','じゅ'=>'ju','か'=>'ka','け'=>'ke','き'=>'ki',
+  'こ'=>'ko','く'=>'ku','ら'=>'la','れ'=>'le','り'=>'li','ろ'=>'lo','る'=>'lu',
+  'ま'=>'ma','め'=>'me','み'=>'mi','も'=>'mo','む'=>'mu','な'=>'na','ね'=>'ne',
+  'に'=>'ni','の'=>'no','ぬ'=>'nu','ぱ'=>'pa','ぺ'=>'pe','ぴ'=>'pi','ぽ'=>'po',
+  'ぷ'=>'pu','ら'=>'ra','れ'=>'re','り'=>'ri','ろ'=>'ro','る'=>'ru','さ'=>'sa',
+  'せ'=>'se','し'=>'si','そ'=>'so','す'=>'su','た'=>'ta','て'=>'te','ち'=>'ti',
+  'と'=>'to','つ'=>'tu','ヴぁ'=>'va','ヴぇ'=>'ve','ヴぃ'=>'vi','ヴぉ'=>'vo',
+  'ヴ'=>'vu','わ'=>'wa','うぇ'=>'we','うぃ'=>'wi','を'=>'wo','や'=>'ya','いぇ'=>'ye',
+  'い'=>'yi','よ'=>'yo','ゆ'=>'yu','ざ'=>'za','ぜ'=>'ze','じ'=>'zi','ぞ'=>'zo',
+  'ず'=>'zu','びゃ'=>'bya','びぇ'=>'bye','びぃ'=>'byi','びょ'=>'byo','びゅ'=>'byu',
+  'ちゃ'=>'cha','ちぇ'=>'che','ち'=>'chi','ちょ'=>'cho','ちゅ'=>'chu','ちゃ'=>'cya',
+  'ちぇ'=>'cye','ちぃ'=>'cyi','ちょ'=>'cyo','ちゅ'=>'cyu','でゃ'=>'dha','でぇ'=>'dhe',
+  'でぃ'=>'dhi','でょ'=>'dho','でゅ'=>'dhu','どぁ'=>'dwa','どぇ'=>'dwe','どぃ'=>'dwi',
+  'どぉ'=>'dwo','どぅ'=>'dwu','ぢゃ'=>'dya','ぢぇ'=>'dye','ぢぃ'=>'dyi','ぢょ'=>'dyo',
+  'ぢゅ'=>'dyu','ぢ'=>'dzi','ふぁ'=>'fwa','ふぇ'=>'fwe','ふぃ'=>'fwi','ふぉ'=>'fwo',
+  'ふぅ'=>'fwu','ふゃ'=>'fya','ふぇ'=>'fye','ふぃ'=>'fyi','ふょ'=>'fyo','ふゅ'=>'fyu',
+  'ぎゃ'=>'gya','ぎぇ'=>'gye','ぎぃ'=>'gyi','ぎょ'=>'gyo','ぎゅ'=>'gyu','ひゃ'=>'hya',
+  'ひぇ'=>'hye','ひぃ'=>'hyi','ひょ'=>'hyo','ひゅ'=>'hyu','じゃ'=>'jya','じぇ'=>'jye',
+  'じぃ'=>'jyi','じょ'=>'jyo','じゅ'=>'jyu','きゃ'=>'kya','きぇ'=>'kye','きぃ'=>'kyi',
+  'きょ'=>'kyo','きゅ'=>'kyu','りゃ'=>'lya','りぇ'=>'lye','りぃ'=>'lyi','りょ'=>'lyo',
+  'りゅ'=>'lyu','みゃ'=>'mya','みぇ'=>'mye','みぃ'=>'myi','みょ'=>'myo','みゅ'=>'myu',
+  'ん'=>'n','にゃ'=>'nya','にぇ'=>'nye','にぃ'=>'nyi','にょ'=>'nyo','にゅ'=>'nyu',
+  'ぴゃ'=>'pya','ぴぇ'=>'pye','ぴぃ'=>'pyi','ぴょ'=>'pyo','ぴゅ'=>'pyu','りゃ'=>'rya',
+  'りぇ'=>'rye','りぃ'=>'ryi','りょ'=>'ryo','りゅ'=>'ryu','しゃ'=>'sha','しぇ'=>'she',
+  'し'=>'shi','しょ'=>'sho','しゅ'=>'shu','すぁ'=>'swa','すぇ'=>'swe','すぃ'=>'swi',
+  'すぉ'=>'swo','すぅ'=>'swu','しゃ'=>'sya','しぇ'=>'sye','しぃ'=>'syi','しょ'=>'syo',
+  'しゅ'=>'syu','てゃ'=>'tha','てぇ'=>'the','てぃ'=>'thi','てょ'=>'tho','てゅ'=>'thu',
+  'つゃ'=>'tsa','つぇ'=>'tse','つぃ'=>'tsi','つょ'=>'tso','つ'=>'tsu','とぁ'=>'twa',
+  'とぇ'=>'twe','とぃ'=>'twi','とぉ'=>'two','とぅ'=>'twu','ちゃ'=>'tya','ちぇ'=>'tye',
+  'ちぃ'=>'tyi','ちょ'=>'tyo','ちゅ'=>'tyu','ヴゃ'=>'vya','ヴぇ'=>'vye','ヴぃ'=>'vyi',
+  'ヴょ'=>'vyo','ヴゅ'=>'vyu','うぁ'=>'wha','うぇ'=>'whe','うぃ'=>'whi','うぉ'=>'who',
+  'うぅ'=>'whu','ゑ'=>'wye','ゐ'=>'wyi','じゃ'=>'zha','じぇ'=>'zhe','じぃ'=>'zhi',
+  'じょ'=>'zho','じゅ'=>'zhu','じゃ'=>'zya','じぇ'=>'zye','じぃ'=>'zyi','じょ'=>'zyo',
+  'じゅ'=>'zyu',
+  // Japanese katakana
+  'ア'=>'a','エ'=>'e','イ'=>'i','オ'=>'o','ウ'=>'u','バ'=>'ba','ベ'=>'be','ビ'=>'bi',
+  'ボ'=>'bo','ブ'=>'bu','シ'=>'ci','ダ'=>'da','デ'=>'de','ヂ'=>'di','ド'=>'do',
+  'ヅ'=>'du','ファ'=>'fa','フェ'=>'fe','フィ'=>'fi','フォ'=>'fo','フ'=>'fu','ガ'=>'ga',
+  'ゲ'=>'ge','ギ'=>'gi','ゴ'=>'go','グ'=>'gu','ハ'=>'ha','ヘ'=>'he','ヒ'=>'hi','ホ'=>'ho',
+  'フ'=>'hu','ジャ'=>'ja','ジェ'=>'je','ジ'=>'ji','ジョ'=>'jo','ジュ'=>'ju','カ'=>'ka',
+  'ケ'=>'ke','キ'=>'ki','コ'=>'ko','ク'=>'ku','ラ'=>'la','レ'=>'le','リ'=>'li','ロ'=>'lo',
+  'ル'=>'lu','マ'=>'ma','メ'=>'me','ミ'=>'mi','モ'=>'mo','ム'=>'mu','ナ'=>'na','ネ'=>'ne',
+  'ニ'=>'ni','ノ'=>'no','ヌ'=>'nu','パ'=>'pa','ペ'=>'pe','ピ'=>'pi','ポ'=>'po','プ'=>'pu',
+  'ラ'=>'ra','レ'=>'re','リ'=>'ri','ロ'=>'ro','ル'=>'ru','サ'=>'sa','セ'=>'se','シ'=>'si',
+  'ソ'=>'so','ス'=>'su','タ'=>'ta','テ'=>'te','チ'=>'ti','ト'=>'to','ツ'=>'tu','ヴァ'=>'va',
+  'ヴェ'=>'ve','ヴィ'=>'vi','ヴォ'=>'vo','ヴ'=>'vu','ワ'=>'wa','ウェ'=>'we','ウィ'=>'wi',
+  'ヲ'=>'wo','ヤ'=>'ya','イェ'=>'ye','イ'=>'yi','ヨ'=>'yo','ユ'=>'yu','ザ'=>'za','ゼ'=>'ze',
+  'ジ'=>'zi','ゾ'=>'zo','ズ'=>'zu','ビャ'=>'bya','ビェ'=>'bye','ビィ'=>'byi','ビョ'=>'byo',
+  'ビュ'=>'byu','チャ'=>'cha','チェ'=>'che','チ'=>'chi','チョ'=>'cho','チュ'=>'chu',
+  'チャ'=>'cya','チェ'=>'cye','チィ'=>'cyi','チョ'=>'cyo','チュ'=>'cyu','デャ'=>'dha',
+  'デェ'=>'dhe','ディ'=>'dhi','デョ'=>'dho','デュ'=>'dhu','ドァ'=>'dwa','ドェ'=>'dwe',
+  'ドィ'=>'dwi','ドォ'=>'dwo','ドゥ'=>'dwu','ヂャ'=>'dya','ヂェ'=>'dye','ヂィ'=>'dyi',
+  'ヂョ'=>'dyo','ヂュ'=>'dyu','ヂ'=>'dzi','ファ'=>'fwa','フェ'=>'fwe','フィ'=>'fwi',
+  'フォ'=>'fwo','フゥ'=>'fwu','フャ'=>'fya','フェ'=>'fye','フィ'=>'fyi','フョ'=>'fyo',
+  'フュ'=>'fyu','ギャ'=>'gya','ギェ'=>'gye','ギィ'=>'gyi','ギョ'=>'gyo','ギュ'=>'gyu',
+  'ヒャ'=>'hya','ヒェ'=>'hye','ヒィ'=>'hyi','ヒョ'=>'hyo','ヒュ'=>'hyu','ジャ'=>'jya',
+  'ジェ'=>'jye','ジィ'=>'jyi','ジョ'=>'jyo','ジュ'=>'jyu','キャ'=>'kya','キェ'=>'kye',
+  'キィ'=>'kyi','キョ'=>'kyo','キュ'=>'kyu','リャ'=>'lya','リェ'=>'lye','リィ'=>'lyi',
+  'リョ'=>'lyo','リュ'=>'lyu','ミャ'=>'mya','ミェ'=>'mye','ミィ'=>'myi','ミョ'=>'myo',
+  'ミュ'=>'myu','ン'=>'n','ニャ'=>'nya','ニェ'=>'nye','ニィ'=>'nyi','ニョ'=>'nyo',
+  'ニュ'=>'nyu','ピャ'=>'pya','ピェ'=>'pye','ピィ'=>'pyi','ピョ'=>'pyo','ピュ'=>'pyu',
+  'リャ'=>'rya','リェ'=>'rye','リィ'=>'ryi','リョ'=>'ryo','リュ'=>'ryu','シャ'=>'sha',
+  'シェ'=>'she','シ'=>'shi','ショ'=>'sho','シュ'=>'shu','スァ'=>'swa','スェ'=>'swe',
+  'スィ'=>'swi','スォ'=>'swo','スゥ'=>'swu','シャ'=>'sya','シェ'=>'sye','シィ'=>'syi',
+  'ショ'=>'syo','シュ'=>'syu','テャ'=>'tha','テェ'=>'the','ティ'=>'thi','テョ'=>'tho',
+  'テュ'=>'thu','ツャ'=>'tsa','ツェ'=>'tse','ツィ'=>'tsi','ツョ'=>'tso','ツ'=>'tsu',
+  'トァ'=>'twa','トェ'=>'twe','トィ'=>'twi','トォ'=>'two','トゥ'=>'twu','チャ'=>'tya',
+  'チェ'=>'tye','チィ'=>'tyi','チョ'=>'tyo','チュ'=>'tyu','ヴャ'=>'vya','ヴェ'=>'vye',
+  'ヴィ'=>'vyi','ヴョ'=>'vyo','ヴュ'=>'vyu','ウァ'=>'wha','ウェ'=>'whe','ウィ'=>'whi',
+  'ウォ'=>'who','ウゥ'=>'whu','ヱ'=>'wye','ヰ'=>'wyi','ジャ'=>'zha','ジェ'=>'zhe',
+  'ジィ'=>'zhi','ジョ'=>'zho','ジュ'=>'zhu','ジャ'=>'zya','ジェ'=>'zye','ジィ'=>'zyi',
+  'ジョ'=>'zyo','ジュ'=>'zyu',
+
+  // "Greeklish"
+  'Γ'=>'G','Δ'=>'E','Θ'=>'Th','Λ'=>'L','Ξ'=>'X','Π'=>'P','Σ'=>'S','Φ'=>'F','Ψ'=>'Ps',
+  'γ'=>'g','δ'=>'e','θ'=>'th','λ'=>'l','ξ'=>'x','π'=>'p','σ'=>'s','φ'=>'f','ψ'=>'ps',
+
+  // Thai
+  'ก'=>'k','ข'=>'kh','ฃ'=>'kh','ค'=>'kh','ฅ'=>'kh','ฆ'=>'kh','ง'=>'ng','จ'=>'ch',
+  'ฉ'=>'ch','ช'=>'ch','ซ'=>'s','ฌ'=>'ch','ญ'=>'y','ฎ'=>'d','ฏ'=>'t','ฐ'=>'th',
+  'ฑ'=>'d','ฒ'=>'th','ณ'=>'n','ด'=>'d','ต'=>'t','ถ'=>'th','ท'=>'th','ธ'=>'th',
+  'น'=>'n','บ'=>'b','ป'=>'p','ผ'=>'ph','ฝ'=>'f','พ'=>'ph','ฟ'=>'f','ภ'=>'ph',
+  'ม'=>'m','ย'=>'y','ร'=>'r','ฤ'=>'rue','ฤๅ'=>'rue','ล'=>'l','ฦ'=>'lue',
+  'ฦๅ'=>'lue','ว'=>'w','ศ'=>'s','ษ'=>'s','ส'=>'s','ห'=>'h','ฬ'=>'l','ฮ'=>'h',
+  'ะ'=>'a','–ั'=>'a','รร'=>'a','า'=>'a','รร'=>'an','ำ'=>'am','–ิ'=>'i','–ี'=>'i',
+  '–ึ'=>'ue','–ื'=>'ue','–ุ'=>'u','–ู'=>'u','เะ'=>'e','เ–็'=>'e','เ'=>'e','แะ'=>'ae',
+  'แ'=>'ae','โะ'=>'o','โ'=>'o','เาะ'=>'o','อ'=>'o','เอะ'=>'oe','เ–ิ'=>'oe',
+  'เอ'=>'oe','เ–ียะ'=>'ia','เ–ีย'=>'ia','เ–ือะ'=>'uea','เ–ือ'=>'uea','–ัวะ'=>'ua',
+  '–ัว'=>'ua','ว'=>'ua','ใ'=>'ai','ไ'=>'ai','–ัย'=>'ai','ไย'=>'ai','าย'=>'ai',
+  'เา'=>'ao','าว'=>'ao','–ุย'=>'ui','โย'=>'oi','อย'=>'oi','เย'=>'oei','เ–ือย'=>'ueai',
+  'วย'=>'uai','–ิว'=>'io','เ–็ว'=>'eo','เว'=>'eo','แ–็ว'=>'aeo','แว'=>'aeo',
+  'เ–ียว'=>'iao',
+
+  // Korean
+  'ㄱ'=>'k','ㅋ'=>'kh','ㄲ'=>'kk','ㄷ'=>'t','ㅌ'=>'th','ㄸ'=>'tt','ㅂ'=>'p',
+  'ㅍ'=>'ph','ㅃ'=>'pp','ㅈ'=>'c','ㅊ'=>'ch','ㅉ'=>'cc','ㅅ'=>'s','ㅆ'=>'ss',
+  'ㅎ'=>'h','ㅇ'=>'ng','ㄴ'=>'n','ㄹ'=>'l','ㅁ'=>'m', 'ㅏ'=>'a','ㅓ'=>'e','ㅗ'=>'o',
+  'ㅜ'=>'wu','ㅡ'=>'u','ㅣ'=>'i','ㅐ'=>'ay','ㅔ'=>'ey','ㅚ'=>'oy','ㅘ'=>'wa','ㅝ'=>'we',
+  'ㅟ'=>'wi','ㅙ'=>'way','ㅞ'=>'wey','ㅢ'=>'uy','ㅑ'=>'ya','ㅕ'=>'ye','ㅛ'=>'oy',
+  'ㅠ'=>'yu','ㅒ'=>'yay','ㅖ'=>'yey',
+);
+
+//Setup VIM: ex: et ts=2 enc=utf-8 :
+
diff --git a/include/phpCache/ChangeLog b/include/phpCache/ChangeLog
new file mode 100644 (file)
index 0000000..23ab95d
--- /dev/null
@@ -0,0 +1,30 @@
+phpCache 1.4:
+       - added $CACHE_HAS["function"] which tells phpCache what functions it can and cant use.  This is for compatibility with php3.
+       - added cache_purge() and cache_purge_all()
+       - cache expire variables and cache variables now have the same scope.  You can now access normal variables from the cache_expire_if() and vice-versa.
+       - Backported to PHP3, added cache_output() for outputting to the cache output (since php3 does not have output buffering).
+       - Storing key/object inside of the cache meta data.  For future use.
+       - Added support for CACHE_MAX_FILENAME_LEN.  If a filename length is longer than CACHE_MAX_FILENAME_LEN, an md5 of it will be used instead.  This prevents fs max file length from occuring if the url is very long. 
+
+phpCache 1.3:
+       - A few tweaks here and there.  Hi Becca!
+       - Cache time is now checked for a change.  If the cache time was changed, cache expires immediately (now you can get rid of those infinite caches without dynamic expressions or an rm :) ).
+       - Support for cache dir hashes.  Cache is now distributed over multiple dirs.  This will speed up sites that have thousands of cache pages.  GC was also redone.  If the GC probability is hit, it will be run on only ONE cache dir (not the entire structure!).  You should use gc.php if you want a complete cleanup, read the header for more information.
+       - phpCache no longer takes control of the output buffering, it just reads the existing content.  It should now be safe to let ob_start() use a different handler without any problems.
+       - Added KFC (Kentucky Fried Cache).  The name is cool eh?  It strips out various things that wont be needed once you get phpCache up and running.  See KentuckyFriedCache.pl for information.
+       
+phpCache 1.2:
+       - Added support for conditional expires.  See expire_mtime.php and expire_every10s.php for examples.
+       - Added support for infinite caching (pass a cache time of 0).  Thanks to Heath Boutwell for the idea.
+
+phpCache 1.1:
+       - Added support for caching headers.  cache_header().
+       - Added two new demos.  thumbnails.php and pager.php.
+       - Added support for cache_variable() that allows you to
+               maintain a variable state between the cache and the
+               uncached versions.  See pager.php
+       - Changed the default object key to use a md5sum of all the
+               passed data.
+
+phpCache 1.0:
+       Intial Release
diff --git a/include/phpCache/LICENSE b/include/phpCache/LICENSE
new file mode 100644 (file)
index 0000000..93d8561
--- /dev/null
@@ -0,0 +1,227 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+   59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
diff --git a/include/phpCache/README b/include/phpCache/README
new file mode 100644 (file)
index 0000000..daba6e9
--- /dev/null
@@ -0,0 +1,33 @@
+phpCache v1.4 by nathan@0x00.org
+http://0x00.org/phpCache/
+
+NOTICE: I would like to hear success stories, please email me with any
+               timing results or whatever.  Before and after, duh.
+
+This is a little caching system for PHP, it allows you to cache blocks of
+code on pages.  There are four functions you need to worry about, all
+sorta documented in phpCache.inc.
+
+These are the basic functions (please see phpCache.inc for the rest):
+
+cache_all($cache_time);
+// Caches the block of code that follows scoped to everyone
+cache_session($cache_time);
+// Caches the block of code that follows scoped to the session
+
+cache($cache_time, $object_name, $object_key);
+// This is the primary function, both cache_all() and cache_session() call
+       this.  It allows you to tweak to storage settings so you can scope it
+       to different things.  If you don't understand this, don't use it.
+
+endcache($store);
+// This function *MUST* be called after all the cached data has been output.
+       It must be called in the block.  If $store is TRUE, the data will be
+       cached.  If it is false, it will not be cached.
+
+Note: All these functions (except endcache()) return 0 if the block needs to be executed.
+       ie: the cache has expired.
+
+Please see the scripts in the demo directory for samples.
+
+-nathan@0x00.org
diff --git a/include/phpCache/gc.php b/include/phpCache/gc.php
new file mode 100644 (file)
index 0000000..2a9f593
--- /dev/null
@@ -0,0 +1,27 @@
+<?
+/*
+   phpCache v1.4 - PHP caching engine 
+   Copyright (C) 2001 Nathan <nathan@0x00.org> 
+
+   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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+/* This script should be run periodically via a cron job or by hand.  phpCache *WILL* try to clean up the cache on its own, but it does not do a full pass of the entire cache structure like this does.  Running this once a day is recommended.  */
+
+       set_time_limit(0);
+       include("phpCache.inc");
+       $ret=cache_gc();
+       print "cache_gc(): $ret\n";
+?>
diff --git a/include/phpCache/phpCache.inc.php b/include/phpCache/phpCache.inc.php
new file mode 100644 (file)
index 0000000..43f0c79
--- /dev/null
@@ -0,0 +1,535 @@
+<?php
+/*
+   phpCache v1.4.1 - PHP caching engine 
+   Copyright (C) 2001 Nathan <nathan@0x00.org> 
+   '.1' Bug Fix By Joel Kronenberg <joel.kronenberg@utoronto.ca>
+
+   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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+if (defined('CACHE_DIR') && (CACHE_DIR != '')) {
+       define('CACHE_ON', 1); /* disable caching */
+} else {
+       define('CACHE_ON', 0); /* enable caching */
+}
+if (!defined('CACHE_DIR')) {
+       define('CACHE_DIR', '');
+}
+
+
+       $CACHE_DEBUG = 0;                       /* Default: 0 - Turn debugging on/off */
+
+       define('THIS_CACHE_DIR', CACHE_DIR . '/atutor_cache_' . DB_NAME);
+
+       define('CACHE_GC', .10);        /* Default: .10 - Probability of garbage collection */
+       define('CACHE_USE_STORAGE_HASH', 0);    /* Default: 1 - Use storage hashing.  This will increase peformance if you are caching many pages. */ 
+       define('CACHE_STORAGE_CREATED', 0);     /* Default: 0 - This is a peformance tweak.  If you set this to 1, phpCache will not check if storage structures have been created.  Don't change this unles you are *SURE* the cache storage has been created. */
+       define('CACHE_MAX_STORAGE_HASH', 23);   /* Don't touch this unless you know what you're doing */
+       define('CACHE_STORAGE_PERM',     0700); /* Default: 0700 - Default permissions for storage directories. */
+       define('CACHE_MAX_FILENAME_LEN', 250);  /* How long the cache storage filename can be before it will md5() the entire thing */
+
+       $CACHE_HAS=array(       'ob_start'      => function_exists('ob_start'),
+                                               'realpath'      => function_exists('realpath'),
+                                               'crc32'         => function_exists('crc32')
+                                       );
+
+       define('CACHE_VERSION', '1.4.1');
+       define('CACHE_STORAGE_CHECKFILE',       THIS_CACHE_DIR 
+                                                                               . '/.phpCache-storage-V'
+                                                                               . CACHE_VERSION
+                                                                               . '-HASH='
+                                                                               . CACHE_USE_STORAGE_HASH);
+
+       define('CACHE_INFO', 'phpCache v1.4.1 By nathan@0x00.org (.1 Bug Fix By joel.kronenberg@utoronto.ca)'); 
+
+       /* This resets the cache state */
+       function cache_reset() {
+               global $cache_pbufferlen, $cache_absfile, $cache_data, $cache_variables, $cache_headers, $cache_expire_cond, $cache_output_buffer;
+
+               cache_debug(__LINE__ .': $cache_absfile -> '.$cache_absfile);
+
+               $cache_pbufferlen = FALSE;
+               $cache_absfile = NULL;
+               $cache_data = array();
+               $cache_fp = NULL;
+               $cache_expire_cond = NULL;
+               $cache_variables=array();
+               $cache_headers=array();
+               $cache_output_buffer='';
+
+               cache_debug(__LINE__ .': $cache_absfile -> '.$cache_absfile);
+       }
+
+       /* Used to output to the cache output, should only be needed if you dont have output buffering (PHP3) */
+       function cache_output($str) {
+               global $cache_output_buffer;
+               if (!$GLOBALS["CACHE_HAS"]['ob_start']) {
+                       $cache_output_buffer.=$str;
+               }
+               print $str;
+       }
+
+       /* Saves a header state between caching */
+       function cache_header($header) {
+               global $cache_headers;
+               Header($header);
+               cache_debug('Adding header '.$header);
+               $cache_headers[]=$header;
+       }
+
+       /* This is a function used internally by phpCache to evaluate the conditional expiration.  This allows the eval() to have its own simulated namespace so it doesnt conflict with any others. */
+       function cache_eval_expire($cond, &$vars) {
+               extract($vars);
+               $EXPIRE=FALSE;
+               eval($cond);
+               return !!$EXPIRE;
+       }
+
+       /* Call this function before a call to cache() to evaluate a dynamic expiration on cache_expire_variable()'s */
+       function cache_expire_if($expr) {
+               global $cache_expire_cond;
+               $cache_expire_cond=$expr;
+       }
+
+       /* Call this function to add a variable to the expire variables store */
+       function cache_expire_variable($vn) {
+               cache_debug("Adding $vn to expire variable store");
+               cache_variable($vn);
+       }
+
+       /* duh ? */
+       function cache_debug($s) {
+               global $CACHE_DEBUG;
+               if ($CACHE_DEBUG) {
+                       print "Debug: $s<br>\n";
+               }
+       }
+
+       /* Saves a variable state between caching */
+       function cache_variable($vn) {
+               global $cache_variables;
+               cache_debug(__LINE__ . ": Adding $vn to the variable store");
+               $cache_variables[] = $vn;
+       }
+
+
+       /* Returns the default key used by the helper functions */
+       function cache_default_key() {
+               global $HTTP_POST_VARS, $HTTP_GET_VARS, $QUERY_STRING;
+               return md5("POST=" . serialize($HTTP_POST_VARS) . " GET=" . serialize($HTTP_GET_VARS) . "QS=" . $QUERY_STRING);
+       }
+
+       /* Returns the default object used by the helper functions */
+       function cache_default_object() {
+               global $REQUEST_URI, $SERVER_NAME, $SCRIPT_FILENAME;
+               if ($GLOBALS["CACHE_HAS"]["realpath"]) {
+                       $sfn=realpath($SCRIPT_FILENAME);
+               } else {
+                       $sfn=$SCRIPT_FILENAME;
+               }
+               $name="http://$SERVER_NAME/$sfn";
+               return $name;
+       }
+
+       /* Caches the current page based on the page name and the GET/POST
+               variables.  All must match or else it will not be fectched
+               from the cache! */
+       function cache_all($cachetime=120) {
+               $key=cache_default_key();
+               $object=cache_default_object();
+               return cache($cachetime, $object, $key);
+       }
+
+       /* Same as cache_all() but it throws the session_id() into
+               the equation */
+       function cache_session($cachetime=120) {
+               global $HTTP_POST_VARS, $HTTP_GET_VARS;
+               $key=cache_default_key() . 'SESSIONID=' . session_id();
+               $object=cache_default_object();
+               return cache($cachetime, $object, $key);
+       }
+
+       /* Manually purge an item in the cache */
+       function cache_purge($object, $key) {
+               $thefile=cache_storage($object, $key);
+               //cache_lock($thefile, TRUE);
+               if (is_file($thefile)) {
+                       $ret=@unlink($thefile);
+               }
+               else {
+                       $ret = false;
+               }
+               //cache_lock($thefile, FALSE);
+               return $ret;
+       }
+
+       /* Manually purge all items in the cache */
+       function cache_purge_all() {
+               return cache_gc(NULL, 1, TRUE);
+       }
+
+       /* Caches $object based on $key for $cachetime, will return 0 if the
+               object has expired or the object does not exist. */
+       function cache($cachetime, $object, $key=NULL) {
+               global $cache_pbufferlen, $cache_absfile, $cache_file, $cache_data, $cache_expire_cond;
+               cache_debug(__LINE__ .': $cache_absfile -> '.$cache_absfile);
+               if (!CACHE_ON) {
+                       cache_debug('Not caching, CACHE_ON is off');
+                       return 0;
+               }
+               $curtime=time();
+               cache_debug(__LINE__.': Caching based on <b>OBJECT</b>='.$object.' <b>KEY</b>='.$key);
+               $cache_absfile=cache_storage($object, $key);
+               cache_debug(__LINE__.': Got cache_storage: '.$cache_absfile);
+               if (($buff=cache_read($cache_absfile))) {
+                       cache_debug('Opened the cache file');
+                       $cdata=unserialize($buff);
+                       if (is_array($cdata)) {
+                               $curco = $cdata['cache_object'];
+                               if ($curco!=$cache_absfile) {
+                                       cache_debug("Holy shit that is not my cache file! why? got=$curco wanted=$cache_absfile");
+                               } else {
+                                       $expireit = FALSE;
+                                       if ($cache_expire_cond) {
+                                               $expireit=cache_eval_expire($cache_expire_cond, $cdata['variables']);
+                                       }
+                                       if ($cdata['cachetime'] != $cachetime) {
+                                               cache_debug('Expiring because cachetime changed');
+                                               $expireit=TRUE;
+                                       }
+                                       if (!$expireit && ($cdata['cachetime']=="0" || $cdata['expire']>=$curtime)) {
+                                               $expirein=$cdata['expire']-$curtime+1;
+                                               cache_debug('Cache expires in '.$expirein);
+                                               if (is_array($cdata['variables'])) {
+                                                       while (list($k,$v)=each($cdata['variables'])) {
+                                                               cache_debug("Restoring variable $k to value $v");
+                                                               $GLOBALS[$k]=$v;
+                                                       }
+                                               }
+                                               if (is_array($cdata['headers'])) {
+                                                       while(list(,$h)=each($cdata['headers'])) {
+                                                               cache_debug("Restoring header $h");
+                                                               Header("$h");
+                                                       }
+                                               }
+                                               print $cdata['content'];
+                                               $ret=$expirein;
+                                               if ($cdata['cachetime']=='0') $ret='INFINITE';
+                                               cache_reset();
+                                               return $ret; 
+                                       }
+                               }
+                       }
+               } else {
+                       cache_debug(__LINE__.': Failed to open previous cache of '.$cache_absfile);
+               }
+       
+               $oldum = umask();
+               umask(0077);
+               /* readlink() is not supported on win32, changed to is_link */
+               if (is_link($cache_absfile)) {
+                       cache_debug("$cache_absfile is a symlink! not caching!");
+                       $cache_absfile=NULL;
+               } else {
+                       cache_debug(__LINE__.': not a symlink');
+                       cache_debug(__LINE__.': Got cache_storage: '.$cache_absfile);
+                       @touch($cache_absfile);
+       
+                       /* cases probs on win32 */
+                       //cache_lock($cache_absfile, TRUE);
+                       /* */
+               }
+               umask($oldum);
+               $cache_data['expire']   = $curtime + $cachetime;
+               $cache_data['cachetime']= $cachetime;
+               $cache_data['curtime']  = $curtime;
+               $cache_data['version']  = CACHE_VERSION;
+               $cache_data['key']              = $key;
+               $cache_data['object']   = $object;
+
+               if ($GLOBALS['CACHE_HAS']['ob_start']) {
+                       $cache_pbufferlen = ob_get_length();
+                       /* If ob_get_length() returns false, output buffering was not on.  turn it on. */
+                       if (cache_iftype($cache_pbufferlen, FALSE)) {
+                               ob_start();
+                       }
+               } else {
+                       $cache_pbufferlen=FALSE;
+               }
+               cache_debug(__LINE__ .': $cache_absfile -> '.$cache_absfile);
+               return 0;
+       }
+
+       /* This *MUST* be at the end of a cache() block or else the cache
+               will not be stored! */ 
+       function endcache($store=TRUE, $send_output = TRUE) {
+               global $cache_pbufferlen, $cache_absfile, $cache_data, $cache_variables, $cache_headers, $cache_ob_handler, $cache_output_buffer;
+               cache_debug(__LINE__ .': $cache_absfile -> '.$cache_absfile);
+               if (!CACHE_ON) {
+                       cache_debug('Not caching, CACHE_ON is off');
+                       return 0;
+               } /* else */
+
+               if ($GLOBALS[CACHE_HAS]['ob_start']) {
+                       $content=ob_get_contents();
+                       if (cache_iftype($cache_pbufferlen,FALSE)) {
+                               /* Output buffering was off before this, we just need to turn it off again */
+
+                               /* JK's fix */
+                               if ($send_output) {
+                                       ob_end_flush();
+                                       cache_debug(__LINE__.': Content sent. flush()');
+                               } else {
+                                       ob_end_clean();
+                                       cache_debug(__LINE__.': Content ignored. clean()');
+                               }
+                               cache_debug(__LINE__ .': $cache_absfile -> '.$cache_absfile);
+                       } else {
+                               /* Output buffering was already on, so get our chunk of data for caching */
+                               $content=substr($content, $cache_pbufferlen);
+                       }
+               } else {
+                       $content=$cache_output_buffer;
+               }
+
+               if (!$store) {
+                       $cache_absfile=NULL;
+               }
+
+               if ($cache_absfile != NULL) {
+                       $cache_data['content'] = $content;
+                       $variables = array();
+                       foreach ($cache_variables as $vn) {
+                       //while(list(,$vn)=each($cache_variables)) {
+                               cache_debug(__LINE__ . ': Found variable: <b>'.$vn.'</b>');
+                               if (isset($GLOBALS[$vn])) {
+                                       $val=$GLOBALS[$vn];
+                                       cache_debug(__LINE__ . ': Setting variable '.$vn.' to '.$val);
+                                       $variables[$vn]=$val;
+                               }
+                       }
+                       $cache_data['cache_object'] = $cache_absfile;
+                       $cache_data['variables']        = $variables;
+                       $cache_data['headers']          = $cache_headers;
+                       $datas = serialize($cache_data);
+                       cache_write($cache_absfile, $datas);
+               } else {
+                       cache_debug(__LINE__ .': no variables found');
+                       cache_debug($cache_variables[0]);
+                       cache_debug(__LINE__ .': $cache_absfile -> '.$cache_absfile);
+               }
+               /* casues probs on win32 */
+               cache_lock($cache_absfile, FALSE);
+               /* */
+               cache_reset();
+
+               cache_debug(__LINE__ .': $cache_absfile -> '.$cache_absfile);
+               cache_debug(__LINE__. ': <b>Caching is done!</b><br>');
+       }
+
+       /* Obtain a lock on the cache storage, this can be stripped out
+               and changed to a different handler like a database or
+               whatever */
+       function cache_lock($file, $open=TRUE) {
+               static $fp;
+
+               if ($open) {
+                       cache_debug('trying to lock '.$file);
+                       $fp  = @fopen($file, 'r');
+                       if ($fp) {
+                               $ret = @flock($fp, LOCK_SH); /* get a shared lock */
+                       }
+               } else {
+                       cache_debug('trying to unlock '.$file);
+                       $ret = @flock($fp, LOCK_UN);
+                       @fclose($fp);
+                       $fp = NULL;
+               }
+               return $ret;
+       }
+
+       /* This is the function that writes out the cache */
+       function cache_write($file, $data) {
+               cache_debug(__LINE__.': Writing cache data to file: '.$file);
+               
+               $fp = fopen($file, 'wb+');
+               @flock($fp, LOCK_EX); /* get a shared lock */
+               if (!$fp) {
+                       cache_debug('Failed to open for write out to '.$file);
+                       return FALSE;
+               }
+               @fwrite($fp, $data, strlen($data));
+               @flock($fp, LOCK_UN); /* get a shared lock */
+               fclose($fp);
+
+               return TRUE;
+       }
+
+       /* This function reads in the cache, duh */
+       function cache_read($file) {
+               $fp = @fopen($file, 'r');
+               if (!$fp) {
+                       cache_debug(__LINE__.': Failed opening file '.realpath($file));
+                       return NULL;
+               }
+               flock($fp, 1);
+               $buff='';
+               while (($tmp=fread($fp, 4096))) {
+                       $buff.=$tmp;
+               }
+               fclose($fp);
+               return $buff;
+       }
+
+       /* This function is called automatically by phpCache to create the cache directory structure */
+       function cache_create_storage() {
+               $failed = 0;
+               $failed |= !@mkdir(THIS_CACHE_DIR, CACHE_STORAGE_PERM);
+               if (CACHE_USE_STORAGE_HASH) {
+                       for ($a=0; $a<CACHE_MAX_STORAGE_HASH; $a++) {
+                               $thedir=THIS_CACHE_DIR . "/$a/";
+                               $failed|=!@mkdir($thedir, CACHE_STORAGE_PERM);
+                               for ($b=0; $b<CACHE_MAX_STORAGE_HASH; $b++) {
+                                       $thedir=THIS_CACHE_DIR . "/$a/$b/";
+                                       $failed|=!@mkdir($thedir, CACHE_STORAGE_PERM);
+                                       for ($c=0; $c<CACHE_MAX_STORAGE_HASH; $c++) {
+                                               $thedir=THIS_CACHE_DIR . "/$a/$b/$c/";
+                                               $failed|=!@mkdir($thedir, CACHE_STORAGE_PERM);
+                                       }
+                               }
+                       }
+               }
+               return TRUE;
+       }
+
+       /* This function hashes the cache object and places it in a cache dir.  This function also handles the GC probability (note that it is run on only *ONE* dir to save time. */
+       function cache_storage($object, $key) {
+               $newobject=eregi_replace("[^A-Z,0-9,=]", 'X', $object);
+               $newkey=eregi_replace("[^A-Z,0-9,=]", 'X', $key);
+               $temp="${newobject}=${newkey}";
+               if (strlen($temp)>=CACHE_MAX_FILENAME_LEN) $temp="HUGE." . md5($temp);
+               $cacheobject = 'phpCache.' . $temp;
+               
+               $thedir=THIS_CACHE_DIR . '/';
+
+               if (CACHE_USE_STORAGE_HASH) {
+                       $chunksize=10;
+                       $ustr=md5($cacheobject);
+                       for ($i=0; $i<3; $i++) {
+                               if ($GLOBALS['CACHE_HAS']['crc32']) {
+                                       $thenum=abs(crc32(substr($ustr,$i,4)))%CACHE_MAX_STORAGE_HASH;
+                               } else {
+                                       $thenum=substr($ustr, $i, 4);
+                                       $thenum=(ord($thenum[0]) . ord($thenum[1]) . ord($thenum[2]) . ord($thenum[3]))%CACHE_MAX_STORAGE_HASH;
+                               }
+                               $thedir.= $thenum . '/';
+                       }
+               }
+               if (CACHE_GC>0) {
+                       $precision=100000;
+                       $r=(mt_rand()%$precision)/$precision;
+                       if ($r<=(CACHE_GC/100)) {
+                               cache_gc($thedir);
+                       }
+               }
+               $theloc = $thedir . $cacheobject;
+
+               return $theloc;
+       }
+
+       /* Cache garbage collection */
+       function cache_gc($dir=NULL, $start=1, $purgeall=FALSE) {
+               static $dirs=0, $files=0, $deleted=0, $ignored=0, $faileddelete=0, $empty=0;
+               if ($start==1) {
+                       cache_debug("Running GC on $dir");
+                       if (!function_exists("getcwd")) {
+                               $cwd=substr(`pwd`, 0, -1);
+                       } else {
+                               $cwd=getcwd();
+                       }
+                       $dirs=$files=$deleted=$ignored=$faileddelete=$empty=0;
+               }
+               if (cache_iftype($dir, NULL)) $dir=THIS_CACHE_DIR;
+               $dp=opendir($dir);
+               if (!$dp) {
+                       cache_debug("Error opening $dir for cleanup");
+                       return FALSE;
+               }
+               chdir($dir);
+               $dirs++;
+               while (!cache_iftype(($de=readdir($dp)),FALSE)) {
+                       if (is_dir($de)) {
+                               if ($de=='.' || $de=='..') continue;
+                               cache_gc($de, 0, $purgeall);
+                               chdir('..');
+                               continue;
+                       }
+
+                       if (eregi("^phpCache.", $de)) {
+                               $files++;
+                               $absfile=$de;
+                               $cachestuff=cache_read($absfile);
+                               $thecache=unserialize($cachestuff);
+                               if (is_array($thecache)) {
+                                       if ($purgeall || ($cdata["cachetime"]!="0" && $thecache["expire"]<=time())) {
+                                               cache_lock($absfile, TRUE);
+                                               if (@unlink($absfile)) {
+                                                       $deleted++;
+                                                       cache_debug("$dir Deleted $absfile");
+                                               } else {
+                                                       $faileddelete++;
+                                                       cache_debug("$dir Failed to delete $absfile");
+                                               }
+                                               cache_lock($absfile, FALSE);
+                                       } else {
+                                               cache_debug("$dir $absfile expires in " . ($thecache["expire"]-time()));
+                                       }
+                               } else {
+                                       cache_debug("$dir $absfile is empty, being processed in another process?");
+                                       $empty++;
+                               }
+                       } else {
+                               $ignored++;
+                       }
+               }
+               closedir($dp);
+               if ($start==1) {
+                       $str="$dir GC Processed: $dirs/dirs     $files/files    $deleted/deleted        $ignored/ignored        $faileddelete/faileddelete      $empty/empty";
+                       cache_debug($str);
+                       chdir($cwd);
+                       return $str;
+               }
+       }
+
+       function cache_iftype($a, $b) {
+               if (gettype($a)==gettype($b) && $a==$b) return TRUE;
+               return FALSE;
+       }
+
+       if (CACHE_ON && !CACHE_STORAGE_CREATED && !@stat(CACHE_STORAGE_CHECKFILE)) {
+               cache_debug('Creating cache storage');
+               cache_create_storage();
+               if (!@touch(CACHE_STORAGE_CHECKFILE)) {
+                       global $msg;
+               
+                       $msg->printErrors('CACHE_DIR_BAD');
+                       exit;
+               }
+       }
+
+       mt_srand(time(NULL));
+       cache_reset();
+
+?>
\ No newline at end of file
diff --git a/include/side_menu.inc.php b/include/side_menu.inc.php
new file mode 100644 (file)
index 0000000..74aed3b
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: footer.inc.php 6614 2006-09-27 19:32:29Z joel $
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+global $next_prev_links;
+global $_base_path, $_my_uri;
+global $_stacks, $db;
+global $system_courses;
+global $savant;
+
+$side_menu = array();
+$stack_files = array();
+
+if ($_SESSION['course_id'] > 0) {
+       $savant->assign('my_uri', $_my_uri);
+
+       $savant->assign('right_menu_open', TRUE);
+       $savant->assign('popup_help', 'MAIN_MENU');
+       $savant->assign('menu_url', '<a name="menu"></a>');
+       $savant->assign('close_menu_url', htmlspecialchars($_my_uri).'disable='.PREF_MAIN_MENU);
+       $savant->assign('close_menus', _AT('close_menus'));
+
+       //copyright can be found in include/html/copyright.inc.php
+
+       $side_menu = explode('|', $system_courses[$_SESSION['course_id']]['side_menu']);
+
+       foreach ($side_menu as $side) {
+               if (isset($_stacks[$side])) {
+                       $stack_files[] = $_stacks[$side]['file'];
+               }
+       }
+}
+
+$savant->assign('side_menu', $stack_files);
+$savant->display('include/side_menu.tmpl.php'); ?>
\ No newline at end of file
diff --git a/include/style_popup.css b/include/style_popup.css
new file mode 100644 (file)
index 0000000..86bf326
--- /dev/null
@@ -0,0 +1,172 @@
+body {\r
+       font-family: Verdana, Helvetica, sans-serif;\r
+       /* line-height: 15pt; */\r
+       font-size: 1em;\r
+       background: #EFEFEF;\r
+       margin: 10px;\r
+       margin-left: 10px;\r
+       margin-bottom: 0px;\r
+       margin-top: 10px;\r
+       margin-right: 10px;\r
+}\r
+a:link, a:visited  {\r
+       color: #006699;\r
+}\r
+a:hover {\r
+       color: #888888;\r
+}\r
+\r
+li {\r
+       font-family: Verdana, Helvetica, sans-serif;\r
+       font-size: small;\r
+    /*line-height: 12pt; */\r
+       padding-bottom: 5px; \r
+       padding: 2px;\r
+}\r
+\r
+ul {\r
+       list-style-position: outside;\r
+       list-style-image: url('/images/bullet.gif');\r
+       margin-top: 0px;\r
+}\r
+ol {\r
+       list-style-position: outside;\r
+       list-style-image: none;\r
+       margin-top: 0px;\r
+}\r
+\r
+h1,h2,h3,h4,h5,h6 {\r
+       margin-bottom: 0px;\r
+       margin-top: 0px;\r
+       color: #152065;\r
+}\r
+\r
+form {\r
+       margin-bottom: 0px;\r
+       margin-top: 0px;\r
+}\r
+\r
+\r
+.small {\r
+       font-family: Verdana, Helvetica, sans-serif;\r
+       color: black;\r
+       text-align: right;\r
+       vertical-align: bottom;\r
+}\r
+\r
+hr {\r
+       color: #006699;\r
+       background-color: #006699;\r
+       margin-top: 0px;\r
+       margin-bottom: 0px;\r
+       height:1px;\r
+       border: 0px;\r
+}\r
+\r
+.input {\r
+       font-family: Helvetica, sans-serif;\r
+       border-right: #006699 dashed 1px;\r
+       border-left: #006699 dashed 1px;\r
+       border-top: #006699 dashed 1px;\r
+       border-bottom: #006699 dashed 1px;\r
+}\r
+.input2 {\r
+       font-family: Helvetica, sans-serif;\r
+       border-right: 0px;\r
+       border-left: #006699 dashed 1px;\r
+       border-top: #006699 dashed 1px;\r
+       border-bottom: #006699 dashed 1px;\r
+}\r
+\r
+\r
+.submit {\r
+       background: #006699;\r
+       color: white;\r
+       border-right: white solid 1px;\r
+       border-left: white solid 1px;\r
+       border-top: white solid 1px;\r
+       border-bottom: white solid 1px;\r
+       padding: 1px;\r
+       font-size: smaller;\r
+}\r
+\r
+.good {\r
+  font-family: Arial, Verdana, Helvetica, sans-serif;\r
+  font-size : 14px;\r
+  color : white;\r
+  background: green;\r
+  font-weight : bold;\r
+  padding: 4px;\r
+ }\r
+\r
+.selected {\r
+ font-family : Arial, Helvetica, Arial Cyr, Arial Ua, sans-serif;\r
+  font-size : 14px;\r
+  color : black;\r
+  background: #F2FF85;\r
+  font-weight : bold;\r
+  padding: 2px;\r
+  width: 45%;\r
+}\r
+\r
+table.box2 {\r
+       background-color: #FFFFFF;\r
+       color: #006699;\r
+\r
+}\r
+\r
+th.box {\r
+       border-bottom: #006699 solid 1px;\r
+       color: white;\r
+    background-color: #006699;\r
+}\r
+\r
+h2 {\r
+       border-bottom: 1px dashed #006699;\r
+       margin-bottom: 10px;\r
+       padding-bottom: 4px;\r
+       width: 98%;\r
+}\r
+\r
+h5.heading2 {\r
+       letter-spacing: 3px;\r
+       /* text-transform: uppercase;  */\r
+       background-color: #eeeeee; \r
+       color: #006699; \r
+       font-weight: bold; \r
+       font-size: small; \r
+       padding-right: 3px; \r
+       padding-left: 3px; \r
+       text-align: center;\r
+}\r
+\r
+table.box {\r
+       background-color: white;\r
+       border-right: #006699 solid 1px;\r
+       border-left: #006699 solid 1px;\r
+       border-top: #006699 solid 1px;\r
+}\r
+\r
+table.box th, table.box td {\r
+       border-bottom: #006699 solid 1px;\r
+       font-size: smaller;\r
+}\r
+\r
+table.box .submit {\r
+       background: #006699;\r
+       color: white;\r
+       font-size: smaller;\r
+}\r
+\r
+table.box .submit:hover {\r
+       background: #0077AA;\r
+       color: white;\r
+       font-size: smaller;\r
+}\r
+\r
+\r
+.submit:hover, .submit:focus {\r
+       background: #0077AA;\r
+       color: white;\r
+       font-size: smaller;\r
+}
\ No newline at end of file
diff --git a/include/vitals.inc.php b/include/vitals.inc.php
new file mode 100644 (file)
index 0000000..a288caf
--- /dev/null
@@ -0,0 +1,1133 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+define('AT_DEVEL', 1);
+define('AT_ERROR_REPORTING', E_ALL ^ E_NOTICE); // default is E_ALL ^ E_NOTICE, use E_ALL or E_ALL + E_STRICT for developing
+define('AT_DEVEL_TRANSLATE', 0);
+
+// Emulate register_globals off. src: http://php.net/manual/en/faq.misc.php#faq.misc.registerglobals
+function unregister_GLOBALS() {
+   if (!ini_get('register_globals')) { return; }
+
+   // Might want to change this perhaps to a nicer error
+   if (isset($_REQUEST['GLOBALS'])) { die('GLOBALS overwrite attempt detected'); }
+
+   // Variables that shouldn't be unset
+   $noUnset = array('GLOBALS','_GET','_POST','_COOKIE','_REQUEST','_SERVER','_ENV', '_FILES');
+   $input = array_merge($_GET,$_POST,$_COOKIE,$_SERVER,$_ENV,$_FILES,isset($_SESSION) && is_array($_SESSION) ? $_SESSION : array());
+  
+   foreach ($input as $k => $v) {
+       if (!in_array($k, $noUnset) && isset($GLOBALS[$k])) { unset($GLOBALS[$k]); }
+   }
+}
+
+/*
+ * structure of this document (in order):
+ *
+ * 0. load config.inc.php
+ * 1. load constants
+ * 2. initilize session
+ * 3. load language constants
+ * 4. enable output compression
+ * 5. initilize db connection
+ * 6. load cache library
+ * 7. initilize session localization
+ * 8. load ContentManagement/output/Savant/Message libraries
+ ***/
+
+/**** 0. start system configuration options block ****/
+       error_reporting(0);
+       if (!defined('AT_REDIRECT_LOADED')){
+               include_once(AT_INCLUDE_PATH.'config.inc.php');
+       }
+       error_reporting(AT_ERROR_REPORTING);
+
+       if (!defined('AT_INSTALL') || !AT_INSTALL) {
+               header('Cache-Control: no-store, no-cache, must-revalidate');
+               header('Pragma: no-cache');
+
+               $relative_path = substr(AT_INCLUDE_PATH, 0, -strlen('include/'));
+               header('Location: ' . $relative_path . 'install/not_installed.php');
+               exit;
+       }
+/*** end system config block ****/
+
+/*** 1. constants ***/
+       if (!defined('AT_REDIRECT_LOADED')){
+               require_once(AT_INCLUDE_PATH.'lib/constants.inc.php');
+       }
+
+/***** 2. start session initilization block ****/
+       if (headers_sent()) {
+               require_once(AT_INCLUDE_PATH . 'classes/ErrorHandler/ErrorHandler.class.php');
+               $err =& new ErrorHandler();
+               trigger_error('VITAL#<br /><br /><code><strong>An error occurred. Output sent before it should have. Please correct the above error(s).' . '</strong></code><br /><hr /><br />', E_USER_ERROR);
+       }
+
+       @set_time_limit(0);
+       @ini_set('session.gc_maxlifetime', '36000'); /* 10 hours */
+       @session_cache_limiter('private, must-revalidate');
+
+       session_name('ATutorID');
+       error_reporting(AT_ERROR_REPORTING);
+
+       if (headers_sent()) {
+               require_once(AT_INCLUDE_PATH . 'classes/ErrorHandler/ErrorHandler.class.php');
+               $err =& new ErrorHandler();
+               trigger_error('VITAL#<br /><code><strong>Headers already sent. ' .
+                                               'Cannot initialise session.</strong></code><br /><hr /><br />', E_USER_ERROR);
+               exit;
+       }
+
+       ob_start();
+       session_set_cookie_params(0, $_base_path);
+       session_start();
+       $str = ob_get_contents();
+       ob_end_clean();
+       unregister_GLOBALS();
+
+       if ($str) {
+               require_once(AT_INCLUDE_PATH . 'classes/ErrorHandler/ErrorHandler.class.php');
+               $err =& new ErrorHandler();
+               trigger_error('VITAL#<br /><code><strong>Error initializing session. ' .
+                                               'Please varify that session.save_path is correctly set in your php.ini file ' .
+                                               'and the directory exists.</strong></code><br /><hr /><br />', E_USER_ERROR);
+               exit;
+       }
+
+       if (!isset($_SESSION['course_id']) && !isset($_SESSION['valid_user']) && (!isset($_user_location) || $_user_location != 'public') && !isset($_pretty_url_course_id)) {
+               if (isset($in_get) && $in_get && (($pos = strpos($_SERVER['PHP_SELF'], 'get.php/')) !== FALSE)) {
+                       $redirect = substr($_SERVER['PHP_SELF'], 0, $pos) . 'login.php';
+                       header('Location: '.$redirect);
+                       exit;
+               }
+
+               header('Location: '.AT_BASE_HREF.'login.php');
+               exit;
+       }
+
+
+/***** end session initilization block ****/
+
+// 4. enable output compression, if it isn't already enabled:
+if ((@ini_get('output_handler') == '') && (@ini_get('zlib.output_handler') == '')) {
+       @ini_set('zlib.output_compression', 1);
+}
+
+/* 5. database connection */
+if (!defined('AT_REDIRECT_LOADED')){
+       require_once(AT_INCLUDE_PATH.'lib/mysql_connect.inc.php');
+}
+
+/* get config variables. if they're not in the db then it uses the installation default value in constants.inc.php */
+$sql    = "SELECT * FROM ".TABLE_PREFIX."config";
+$result = mysql_query($sql, $db);
+while ($row = mysql_fetch_assoc($result)) { 
+       $_config[$row['name']] = $row['value'];
+}
+
+/* following is added as a transition period and backwards compatability: */
+define('EMAIL',                     $_config['contact_email']);
+define('EMAIL_NOTIFY',              $_config['email_notification']);
+define('ALLOW_INSTRUCTOR_REQUESTS', $_config['allow_instructor_requests']);
+define('AUTO_APPROVE_INSTRUCTORS',  $_config['auto_approve_instructors']);
+define('SITE_NAME',                 $_config['site_name']);
+define('HOME_URL',                  $_config['home_url']);
+define('DEFAULT_LANGUAGE',          $_config['default_language']);
+define('CACHE_DIR',                 $_config['cache_dir']);
+define('AT_ENABLE_CATEGORY_THEMES', $_config['theme_categories']);
+define('AT_COURSE_BACKUPS',         $_config['course_backups']);
+define('AT_EMAIL_CONFIRMATION',     $_config['email_confirmation']);
+define('AT_MASTER_LIST',            $_config['master_list']);
+$MaxFileSize       = $_config['max_file_size']; 
+$MaxCourseSize     = $_config['max_course_size'];
+$MaxCourseFloat    = $_config['max_course_float'];
+$IllegalExtentions = explode('|',$_config['illegal_extentions']);
+define('AT_DEFAULT_PREFS',  isset($_config['prefs_default']) ? $_config['prefs_default'] : '');
+$_config['home_defaults'] .= (isset($_config['home_defaults_2']) ? $_config['home_defaults_2'] : '');
+$_config['main_defaults'] .= (isset($_config['main_defaults_2']) ? $_config['main_defaults_2'] : '');
+
+require(AT_INCLUDE_PATH.'phpCache/phpCache.inc.php'); // cache library
+require(AT_INCLUDE_PATH.'lib/utf8.php');                       //UTF-8 multibyte library
+
+if ($_config['time_zone']) {
+       $sql = "SET time_zone='{$_config['time_zone']}'";
+       mysql_query($sql, $db);
+
+       if (function_exists('date_default_timezone_set')) {
+               date_default_timezone_set($_config['time_zone']);
+       } else {
+               @putenv("TZ={$_config['time_zone']}");
+       }
+}
+
+/***** 7. start language block *****/
+       // set current language
+       require(AT_INCLUDE_PATH . 'classes/Language/LanguageManager.class.php');
+       $languageManager =& new LanguageManager();
+
+       $myLang =& $languageManager->getMyLanguage();
+
+       if ($myLang === FALSE) {
+               echo 'There are no languages installed!';
+               exit;
+       }
+       $myLang->saveToSession();
+       if (isset($_GET['lang']) && $_SESSION['valid_user']) {
+               if ($_SESSION['course_id'] == -1) {
+                       $myLang->saveToPreferences($_SESSION['login'], 1);      //1 for admin                   
+               } else {
+                       $myLang->saveToPreferences($_SESSION['member_id'], 0);  //0 for non-admin
+               }
+       }
+       $myLang->sendContentTypeHeader();
+
+       /* set right-to-left language */
+       $rtl = '';
+       if ($myLang->isRTL()) {
+               $rtl = 'rtl_'; /* basically the prefix to a rtl variant directory/filename. eg. rtl_tree */
+       }
+/***** end language block ****/
+
+/* 8. load common libraries */
+       require(AT_INCLUDE_PATH.'classes/ContentManager.class.php');  /* content management class */
+       require_once(AT_INCLUDE_PATH.'lib/output.inc.php');           /* output functions */
+       if (!(defined('AT_REDIRECT_LOADED'))){
+               require_once(AT_INCLUDE_PATH . 'classes/UrlRewrite/UrlParser.class.php');       /* pretty url tool */
+       }
+       require(AT_INCLUDE_PATH.'classes/Savant2/Savant2.php');       /* for the theme and template management */
+
+       // set default template paths:
+       $savant =& new Savant2();
+       $savant->addPath('template', AT_INCLUDE_PATH . '../themes/default/');
+
+       if (isset($_SESSION['prefs']['PREF_THEME']) && file_exists(AT_INCLUDE_PATH . '../themes/' . $_SESSION['prefs']['PREF_THEME']) && isset($_SESSION['valid_user']) && $_SESSION['valid_user']) {
+
+               if ($_SESSION['course_id'] == -1) {
+                       if (!is_dir(AT_INCLUDE_PATH . '../themes/' . $_SESSION['prefs']['PREF_THEME'])) {
+                               $_SESSION['prefs']['PREF_THEME'] = 'default';
+                       }
+                       $savant->addPath('template', AT_INCLUDE_PATH . '../themes/' . $_SESSION['prefs']['PREF_THEME'] . '/');
+               } else {
+                       //check if enabled
+                       $sql    = "SELECT status FROM ".TABLE_PREFIX."themes WHERE dir_name = '".$_SESSION['prefs']['PREF_THEME']."'";
+                       $result = mysql_query($sql, $db);
+                       $row = mysql_fetch_assoc($result);
+                       if ($row['status'] > 0) {
+                               $savant->addPath('template', AT_INCLUDE_PATH . '../themes/' . $_SESSION['prefs']['PREF_THEME'] . '/');
+                       } else {
+                               // get default
+                               $default_theme = get_default_theme();
+                               if (!is_dir(AT_INCLUDE_PATH . '../themes/' . $default_theme['dir_name'])) {
+                                       $default_theme = array('dir_name' => 'default');
+                               }
+                               $savant->addPath('template', AT_INCLUDE_PATH . '../themes/' . $default_theme['dir_name'] . '/');
+                               $_SESSION['prefs']['PREF_THEME'] = $default_theme['dir_name'];
+                       }
+               }
+       } else {
+               // get default
+               $default_theme = get_default_theme();
+               if (!is_dir(AT_INCLUDE_PATH . '../themes/' . $default_theme['dir_name'])) {
+                       $default_theme = array('dir_name' => 'default');
+               }
+               $savant->addPath('template', AT_INCLUDE_PATH . '../themes/' . $default_theme['dir_name'] . '/');
+               $_SESSION['prefs']['PREF_THEME'] = $default_theme['dir_name'];
+       }
+
+       require(AT_INCLUDE_PATH . '../themes/' . $_SESSION['prefs']['PREF_THEME'] . '/theme.cfg.php');
+
+       require(AT_INCLUDE_PATH.'classes/Message/Message.class.php');
+       $msg = new Message($savant);
+
+       $contentManager = new ContentManager($db, isset($_SESSION['course_id']) ? $_SESSION['course_id'] : 0);
+       $contentManager->initContent();
+/**************************************************/
+
+if (isset($_user_location) && ($_user_location == 'users') && $_SESSION['valid_user'] && ($_SESSION['course_id'] > 0)) {
+       $_SESSION['course_id'] = 0;
+}
+
+if ((!isset($_SESSION['course_id']) || $_SESSION['course_id'] == 0) && ($_user_location != 'users') && ($_user_location != 'prog') && !isset($_GET['h']) && ($_user_location != 'public') && (!isset($_pretty_url_course_id) || $_pretty_url_course_id == 0)) {
+       header('Location:'.AT_BASE_HREF.'users/index.php');
+       exit;
+}
+/* check if we are in the requested course, if not, bounce to it.
+ * @author harris, for pretty url, read AT_PRETTY_URL_HANDLER
+ */ 
+if (isset($_pretty_url_course_id) && $_SESSION['course_id'] != $_pretty_url_course_id){
+//     $_SESSION['course_id'] = $_pretty_url_course_id;
+       if($_config['pretty_url'] == 0){
+               header('Location: '.AT_BASE_HREF.'bounce.php?course='.$_pretty_url_course_id.SEP.'pu='.$_SERVER['PATH_INFO'].urlencode('?'.$_SERVER['QUERY_STRING']));
+       } else {
+               header('Location: '.AT_BASE_HREF.'bounce.php?course='.$_pretty_url_course_id.SEP.'pu='.$_SERVER['PATH_INFO']);
+       }
+       exit;
+}
+
+   /**
+   * This function is used for printing variables for debugging.
+   * @access  public
+   * @param   mixed $var       The variable to output
+   * @param   string $title    The name of the variable, or some mark-up identifier.
+   * @author  Joel Kronenberg
+   */
+function debug($var, $title='') {
+       if (!defined('AT_DEVEL') || !AT_DEVEL) {
+               return;
+       }
+       
+       echo '<pre style="border: 1px black solid; padding: 0px; margin: 10px;" title="debugging box">';
+       if ($title) {
+               echo '<h4>'.$title.'</h4>';
+       }
+       
+       ob_start();
+       print_r($var);
+       $str = ob_get_contents();
+       ob_end_clean();
+
+       $str = str_replace('<', '&lt;', $str);
+
+       $str = str_replace('[', '<span style="color: red; font-weight: bold;">[', $str);
+       $str = str_replace(']', ']</span>', $str);
+       $str = str_replace('=>', '<span style="color: blue; font-weight: bold;">=></span>', $str);
+       $str = str_replace('Array', '<span style="color: purple; font-weight: bold;">Array</span>', $str);
+       echo $str;
+       echo '</pre>';
+}
+
+
+/********************************************************************/
+/* the system course information                                                                       */
+/* system_courses[course_id] = array(title, description, subject)      */
+$system_courses = array();
+
+// temporary set to a low number
+$sql = 'SELECT * FROM '.TABLE_PREFIX.'courses ORDER BY title';
+$result = mysql_query($sql, $db);
+while ($row = mysql_fetch_assoc($result)) {
+       $course = $row['course_id'];
+       unset($row['course_id']);
+       $system_courses[$course] = $row;
+}
+/*                                                                                                                                     */
+/********************************************************************/
+
+if (isset($_SESSION['course_id']) && $_SESSION['course_id'] > 0) {
+       $sql = 'SELECT * FROM '.TABLE_PREFIX.'glossary WHERE course_id='.$_SESSION['course_id'].' ORDER BY word';
+       $result = mysql_query($sql, $db);
+       $glossary = array();
+       $glossary_ids = array();
+       while ($row_g = mysql_fetch_assoc($result)) {
+               
+               $row_g['word'] = urlencode($row_g['word']);
+
+               $glossary[$row_g['word']] = str_replace("'", "\'",$row_g['definition']);
+               $glossary_ids[$row_g['word_id']] = $row_g['word'];
+
+               /* a kludge to get the related id's for when editing content */
+               /* it's ugly, but beats putting this query AGAIN on the edit_content.php page */
+               if (isset($get_related_glossary)) {
+                       $glossary_ids_related[$row_g['word']] = $row_g['related_word_id'];
+               }
+       }
+}
+
+function get_html_body($text) {
+       /* strip everything before <body> */
+       $start_pos      = strpos(strtolower($text), '<body');
+       if ($start_pos !== false) {
+               $start_pos      += strlen('<body');
+               $end_pos        = strpos(strtolower($text), '>', $start_pos);
+               $end_pos        += strlen('>');
+
+               $text = substr($text, $end_pos);
+       }
+
+       /* strip everything after </body> */
+       $end_pos        = strpos(strtolower($text), '</body>');
+       if ($end_pos !== false) {
+               $text = trim(substr($text, 0, $end_pos));
+       }
+
+       return $text;
+}
+
+function get_html_head ($text) {
+       /* make all text lower case */
+       $text = strtolower($text);
+
+       /* strip everything before <head> */
+       $start_pos      = strpos($text, '<head');
+       if ($start_pos !== false) {
+               $start_pos      += strlen('<head');
+               $end_pos        = strpos($text, '>', $start_pos);
+               $end_pos        += strlen('>');
+
+               $text = substr($text, $end_pos);
+       }
+
+       /* strip everything after </head> */
+       $end_pos        = strpos($text, '</head');
+       if ($end_pos !== false) {
+               $text = trim(substr($text, 0, $end_pos));
+       }
+       return $text;
+}
+
+/**
+* This function cuts out requested tag information from html head
+* @access  public
+* @param   $text  html text
+* @param   $tags  a string or an array of requested tags
+* @author  Cindy Qi Li
+*/
+function get_html_head_by_tag($text, $tags)
+{
+       $head = get_html_head($text);
+       $rtn_text = "";
+       
+       if (!is_array($tags) && strlen(trim($tags)) > 0)
+       {
+               $tags = array(trim($tags));
+       }
+       
+       foreach ($tags as $tag)
+       {
+               $tag = strtolower($tag);
+
+               /* strip everything before <{tag}> */
+               $start_pos      = strpos($head, '<'.$tag);
+               $temp_head = $head;
+               
+               while ($start_pos !== false) 
+               {
+                       $temp_text = substr($temp_head, $start_pos);
+       
+                       /* strip everything after </{tag}> or />*/
+                       $end_pos        = strpos($temp_text, '</' . $tag . '>');
+       
+                       if ($end_pos !== false) 
+                       {
+                               $end_pos += strlen('</' . $tag . '>');
+                               
+                               // add an empty line after each tag information
+                               $rtn_text .= trim(substr($temp_text, 0, $end_pos)) . '
+       
+';
+                       }
+                       else  // match /> as ending tag if </tag> is not found
+                       {
+                               $end_pos        = strpos($temp_text, '/>');
+                               $end_pos += strlen('/>');
+                               
+                               // add an empty line after each tag information
+                               $rtn_text .= trim(substr($temp_text, 0, $end_pos)) . '
+       
+';
+                       }
+                       
+                       // initialize vars for next round of matching
+                       $temp_head = substr($temp_text, $end_pos);
+                       $start_pos = strpos($temp_head, '<'.$tag);
+               }
+       }
+       
+       return $rtn_text;
+}
+
+if (version_compare(phpversion(), '4.3.0') < 0) {
+       function file_get_contents($filename) {
+               $fd = @fopen($filename, 'rb');
+               if ($fd === false) {
+                       $content = false;
+               } else {
+                       $content = @fread($fd, filesize($filename));
+                       @fclose($fd);
+               }
+
+               return $content;
+       }
+
+       function mysql_real_escape_string($input) {
+               return mysql_escape_string($input);
+       }
+}
+
+
+function add_user_online() {
+       if (!isset($_SESSION['member_id']) || !($_SESSION['member_id'] > 0)) {
+               return;
+       }
+       global $db;
+
+    $expiry = time() + 900; // 15min
+    $sql    = 'REPLACE INTO '.TABLE_PREFIX.'users_online VALUES ('.$_SESSION['member_id'].', '.$_SESSION['course_id'].', "'.addslashes(get_display_name($_SESSION['member_id'])).'", '.$expiry.')';
+    $result = mysql_query($sql, $db);
+
+       /* garbage collect and optimize the table every so often */
+       mt_srand((double) microtime() * 1000000);
+       $rand = mt_rand(1, 20);
+       if ($rand == 1) {
+               $sql = 'DELETE FROM '.TABLE_PREFIX.'users_online WHERE expiry<'.time();
+               $result = @mysql_query($sql, $db);
+       }
+}
+
+/**
+ * Returns the login name of a member.
+ * @access  public
+ * @param   int $id    The ID of the member.
+ * @return  Returns the login name of the member whose ID is $id.
+ * @author  Joel Kronenberg
+ */
+function get_login($id){
+       global $db, $_config_defaults;
+
+       if (is_array($id)) {
+               $id             = implode(',',$id);
+               $sql    = 'SELECT login, member_id FROM '.TABLE_PREFIX.'members WHERE member_id IN ('.$id.') ORDER BY login';
+
+               $rows = array();
+               $result = mysql_query($sql, $db);
+               while( $row     = mysql_fetch_assoc($result)) {
+                       $rows[$row['member_id']] = $row['login'];
+               }
+               return $rows;
+       } else {
+               $id             = intval($id);
+               $sql    = 'SELECT login FROM '.TABLE_PREFIX.'members WHERE member_id='.$id;
+
+               $result = mysql_query($sql, $db);
+               $row    = mysql_fetch_assoc($result);
+
+               return $row['login'];
+       }
+
+}
+
+function get_display_name($id) {
+       static $db, $_config, $display_name_formats;
+
+       if (!$id) {
+               return $_SESSION['login'];
+       }
+
+       if (!isset($db, $_config)) {
+               global $db, $_config, $display_name_formats;
+       }
+
+       $sql    = 'SELECT login, first_name, second_name, last_name FROM '.TABLE_PREFIX.'members WHERE member_id='.$id;
+       $result = mysql_query($sql, $db);
+       $row    = mysql_fetch_assoc($result);
+
+       return _AT($display_name_formats[$_config['display_name_format']], $row['login'], $row['first_name'], $row['second_name'], $row['last_name']);
+}
+
+function get_forum_name($fid){
+       global $db;
+
+       $fid = intval($fid);
+
+       $sql    = 'SELECT title FROM '.TABLE_PREFIX.'forums WHERE forum_id='.$fid;
+       $result = mysql_query($sql, $db);
+       if (($row = mysql_fetch_assoc($result)) && $row['title']) {
+               return $row['title'];           
+       }
+
+       $sql = "SELECT group_id FROM ".TABLE_PREFIX."forums_groups WHERE forum_id=$fid";
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)) {
+               return get_group_title($row['group_id']);
+       }
+
+       return FALSE;
+}
+
+/* takes the array of valid prefs and assigns them to the current session */
+function assign_session_prefs ($prefs) {
+       unset($_SESSION['prefs']);
+       if (is_array($prefs)) {
+               foreach($prefs as $pref_name => $value) {
+                       $_SESSION['prefs'][$pref_name] = $value;
+               }
+       }
+}
+
+function save_prefs( ) {
+       global $db;
+
+       if ($_SESSION['valid_user']) {
+               $data   = addslashes(serialize($_SESSION['prefs']));
+               $sql    = 'UPDATE '.TABLE_PREFIX.'members SET preferences="'.$data.'", creation_date=creation_date, last_login=last_login WHERE member_id='.$_SESSION['member_id'];
+               $result = mysql_query($sql, $db); 
+       }
+       /* else, we're not a valid user so nothing to save. */
+}
+
+/**
+* Saves the last viewed content page in a user's course so that on next visit, user can start reading where they left off
+* @access  public
+* @param   int $cid            the content page id
+* @return  none
+* @see     $db                 in include/vitals.inc.php
+* @author  Joel Kronenberg
+*/
+function save_last_cid($cid) {
+       if ($_SESSION['enroll'] == AT_ENROLL_NO) {
+               return;
+       }
+       global $db;
+
+       $_SESSION['s_cid']    = intval($_GET['cid']);
+
+       if (!$_SESSION['is_admin']   && 
+               !$_SESSION['privileges'] && 
+               !isset($in_get)          && 
+               !$_SESSION['cid_time']   && 
+               ($_SESSION['course_id'] > 0) ) 
+               {
+                       $_SESSION['cid_time'] = time();
+       }
+
+       $sql = "UPDATE ".TABLE_PREFIX."course_enrollment SET last_cid=$cid WHERE course_id=$_SESSION[course_id] AND member_id=$_SESSION[member_id]";
+       mysql_query($sql, $db);
+}
+
+// there has to be a better way of expressing this if-statement!
+// and, does it really have to be here?
+if ((!isset($_SESSION['is_admin']) || !$_SESSION['is_admin'])       && 
+       (!isset($_SESSION['privileges']) || !$_SESSION['privileges'])     &&
+       !isset($in_get)              && 
+       isset($_SESSION['s_cid']) && $_SESSION['s_cid'] && 
+       isset($_SESSION['cid_time']) && $_SESSION['cid_time'] &&
+    ($_SESSION['course_id'] > 0) && 
+       ($_SESSION['s_cid'] != $_GET['cid']) && 
+       ($_SESSION['enroll'] != AT_ENROLL_NO) )  
+       {
+               $diff = time() - $_SESSION['cid_time'];
+               if ($diff > 0) {
+                       $sql = "UPDATE ".TABLE_PREFIX."member_track SET counter=counter+1, duration=duration+$diff, last_accessed=NOW() WHERE member_id=$_SESSION[member_id] AND content_id=$_SESSION[s_cid]";
+
+                       $result = mysql_query($sql, $db);
+
+                       if (mysql_affected_rows($db) == 0) {
+                               $sql = "INSERT INTO ".TABLE_PREFIX."member_track VALUES ($_SESSION[member_id], $_SESSION[course_id], $_SESSION[s_cid], 1, $diff, NOW())";
+                               $result = mysql_query($sql, $db);
+                       }
+               }
+
+               $_SESSION['cid_time'] = 0;
+}
+
+
+/**
+* Checks if the $_SESSION[member_id] is an instructor (true) or not (false)
+* The result is only fetched once - it is then available via a static variable, $is_instructor
+* @access  public
+* @param   none
+* @return  bool        true if is instructor, false otherwise.
+* @see     $db   in include/vitals.inc.php
+* @author  Joel Kronenberg
+*/     
+function get_instructor_status() {
+       static $is_instructor;
+
+       if (isset($is_instructor)) {
+               return $is_instructor;
+       }
+
+       global $db;
+
+       $is_instructor = false;
+
+       $sql = 'SELECT status FROM '.TABLE_PREFIX.'members WHERE member_id='.$_SESSION['member_id'];
+       $result = mysql_query($sql, $db);
+       if (!($row = mysql_fetch_assoc($result))) {
+               $is_instructor = FALSE;
+               return FALSE;
+       }
+
+       if ($row['status'] == AT_STATUS_INSTRUCTOR) {
+               $is_instructor = TRUE;
+               return TRUE;
+       }
+
+       $is_instructor = FALSE;
+       return FALSE;
+}
+
+/****************************************************/
+/* update the user online list                                         */
+if (isset($_SESSION['valid_user']) && $_SESSION['valid_user']) {
+       $new_minute = time()/60;
+       if (!isset($_SESSION['last_updated'])) {
+               $_SESSION['last_updated'] = $new_minute;
+       }
+       $diff       = abs($_SESSION['last_updated'] - $new_minute);
+       if ($diff > ONLINE_UPDATE) {
+               $_SESSION['last_updated'] = $new_minute;
+               add_user_online();
+       }
+}
+
+/****************************************************/
+/* compute the $_my_uri variable                                       */
+       $bits     = explode(SEP, getenv('QUERY_STRING'));
+       $num_bits = count($bits);
+       $_my_uri  = '';
+
+       for ($i=0; $i<$num_bits; $i++) {
+               if (    (strpos($bits[$i], 'enable=')   === 0) 
+                       ||      (strpos($bits[$i], 'disable=')  === 0)
+                       ||      (strpos($bits[$i], 'expand=')   === 0)
+                       ||      (strpos($bits[$i], 'collapse=') === 0)
+                       ||      (strpos($bits[$i], 'lang=')             === 0)
+                       ) {
+                       /* we don't want this variable added to $_my_uri */
+                       continue;
+               }
+
+               if (($_my_uri == '') && ($bits[$i] != '')) {
+                       $_my_uri .= '?';
+               } else if ($bits[$i] != ''){
+                       $_my_uri .= SEP;
+               }
+               $_my_uri .= $bits[$i];
+       }
+       if ($_my_uri == '') {
+               $_my_uri .= '?';
+       } else {
+               $_my_uri .= SEP;
+       }
+       $_my_uri = $_SERVER['PHP_SELF'].$_my_uri;
+
+function my_add_null_slashes( $string ) {
+    return mysql_real_escape_string(stripslashes($string));
+}
+function my_null_slashes($string) {
+       return $string;
+}
+
+if ( get_magic_quotes_gpc() == 1 ) {
+       $addslashes   = 'my_add_null_slashes';
+       $stripslashes = 'stripslashes';
+} else {
+       $addslashes   = 'mysql_real_escape_string';
+       $stripslashes = 'my_null_slashes';
+}
+
+
+/**
+ * If MBString extension is loaded, 4.3.0+, then use it.
+ * Otherwise we will have to use include/utf8 library
+ * @author     Harris
+ * @date Oct 10, 2007
+ * @version    1.5.6
+ */
+ if (extension_loaded('mbstring')){
+        $strtolower = 'mb_strtolower';
+        $strtoupper = 'mb_strtoupper';
+        $substr = 'mb_substr';
+        $strpos = 'mb_strpos';
+        $strrpos = 'mb_strrpos';
+        $strlen = 'mb_strlen';
+ } else {
+        $strtolower = 'utf8_strtolower';
+        $strtoupper = 'utf8_strtoupper';
+        $substr = 'utf8_substr';
+        $strpos = 'utf8_strpos';
+        $strrpos = 'utf8_strrpos';
+        $strlen = 'utf8_strlen';
+ }
+
+
+/**
+* Checks if the data exceeded the database predefined length, if so,
+* truncate it.
+* This is used on data that are being inserted into the database.
+* If this function is used for display purposes, you may want to add the '...' 
+*  at the end of the string by setting the $forDisplay=1
+* @param       the mbstring that needed to be checked
+* @param       the length of what the input should be
+* @param       (OPTIONAL)
+*                      append '...' at the end of the string.  Should not use this when 
+*                      dealing with database.  This should only be set for display purposes.
+* @return      the mbstring safe sql entry
+* @author      Harris Wong
+*/
+function validate_length($input, $len, $forDisplay=0){
+       global $strlen, $substr;
+       if ($strlen($input) > $len) {
+               if ($forDisplay===1){
+                       return $substr($input, 0, $len).'...';
+               }
+               return $substr($input, 0, $len);
+       }
+       return $input;
+}
+
+/**
+ * If pretty URL within admin config is switched on.  We will apply pretty URL 
+ * to all the links in ATutor.  This function will authenticate itself towards the current pages.
+ * In our definition, admins, login, registration pages shouldn't have pretty url applied.  However,
+ * if one want to use url_rewrite on these pages, please force it by using the third parameter.  
+ * Note: If system config has turned off this feature, $force will have no effect.
+ * @param      string  the Url should be a relative link, have to improve this later on, to check if 
+ *                                     it's a relative link, if not, truncate it.
+ * @param      boolean Available values are AT_PRETTY_URL_IS_HEADER, AT_PRETTY_URL_NOT_HEADER(default)
+ *                     use AT_PRETTY_URL_IS_HEADER if url_rewrite is used in php header('Location:..'), absolute path is needed for this.
+ * @param      boolean true to force the url_rewrite, false otheriwse.  False is the default.
+ * @author     Harris Wong
+ */
+function url_rewrite($url, $is_rewriting_header=AT_PRETTY_URL_NOT_HEADER, $force=false){
+       global $_config, $db;
+       $url_parser = new UrlParser();
+       $pathinfo = $url_parser->getPathArray();
+
+       /* If this is any kind of admins, don't prettify the url
+        * $_SESSION['is_guest'] is used to check against login/register/browse page, the links on this page will 
+        * only be prettified when a user has logged in.
+        * Had used $_SESSION[valid_user] before but it created this problem: 
+        * http://www.atutor.ca/atutor/mantis/view.php?id=3426
+        */
+       if ($force || $_SESSION['course_id'] > 0) {
+               //if course id is defined, apply pretty url.
+       } 
+       //if this is something that is displayed on the login page, don't modify the urls.
+       else if ((admin_authenticate(AT_ADMIN_PRIV_ADMIN, AT_PRIV_RETURN) || admin_authenticate($_SESSION['privileges'], AT_PRIV_RETURN))
+               || (isset($_SESSION['is_guest']) && $_SESSION['is_guest']==1)){
+               return $url;
+       } 
+
+       //if we allow pretty url in the system
+       if ($_config['pretty_url'] > 0){
+               //If we allow course dir name from sys perf             
+               if ($_config['course_dir_name'] > 0){
+                       if (preg_match('/bounce.php\?course=([\d]+)$/', $url, $matches) == 1){
+                               // bounce has the highest priority, even if session is set, work on 
+                               // bounce first.
+                               $course_id = $url_parser->getCourseDirName($matches[1]);
+                       } elseif (isset($_REQUEST['course'])){
+                               //jump menu
+                               $course_id = $url_parser->getCourseDirName($_REQUEST['course']);
+                       } elseif (isset($_SESSION['course_id']) && $_SESSION['course_id'] > 0){
+                               $course_id = $url_parser->getCourseDirName($_SESSION['course_id']);
+                       }
+               } else {
+                       $course_id = $_SESSION['course_id'];
+               }
+               $url = $pathinfo[1]->convertToPrettyUrl($course_id, $url);
+       } elseif ($_config['course_dir_name'] > 0) {
+               //enabled course directory name, disabled pretty url
+               if (preg_match('/bounce.php\?course=([\d]+)$/', $url, $matches) == 1){
+                       // bounce has the highest priority, even if session is set, work on 
+                       // bounce first.
+                       $course_id = $url_parser->getCourseDirName($matches[1]);
+               } elseif (isset($_REQUEST['course'])){
+                       $course_id = $url_parser->getCourseDirName($_REQUEST['course']);
+               } elseif (isset($_SESSION['course_id']) && $_SESSION['course_id'] > 0){
+                       $course_id = $url_parser->getCourseDirName($_SESSION['course_id']);
+               } 
+               $url = $pathinfo[1]->convertToPrettyUrl($course_id, $url);
+       }
+
+       //instead of putting AT_BASE_HREF in all the headers location, we will put it here.
+       //Abs paths are required for pretty url because otherwise the url location will be appeneded.
+       //ie.   ATutor_161/blogs/CoURSe_rOAd/blogs/view.php/ot/1/oid/1/ instead of 
+       //              ATutor_161/CoURSe_rOAd/blogs/view.php/ot/1/oid/1/
+       if ($is_rewriting_header==true){
+               return AT_BASE_HREF.$url;
+       } 
+       return $url;
+}
+
+
+/**
+* Applies $addslashes or intval() recursively.
+* @access  public
+* @param   mixed $input        The input to clean.
+* @return  A safe version of $input
+* @author  Joel Kronenberg
+*/
+function sql_quote($input) {
+       global $addslashes;
+
+       if (is_array($input)) {
+               foreach ($input as $key => $value) {
+                       if (is_array($input[$key])) {
+                               $input[$key] = sql_quote($input[$key]);
+                       } else if (!empty($input[$key]) && is_numeric($input[$key])) {
+                               $input[$key] = intval($input[$key]);
+                       } else {
+                               $input[$key] = $addslashes(trim($input[$key]));
+                       }
+               }
+       } else {
+               if (!empty($input) && is_numeric($input)) {
+                       $input = intval($input);
+               } else {
+                       $input = $addslashes(trim($input));
+               }
+       }
+       return $input;
+}
+
+function query_bit( $bitfield, $bit ) {
+       if (!is_int($bitfield)) {
+               $bitfield = intval($bitfield);
+       }
+       if (!is_int($bit)) {
+               $bit = intval($bit);
+       }
+       return ( $bitfield & $bit ) ? true : false;
+} 
+
+/**
+* Authenticates the current user against the specified privilege.
+* @access  public
+* @param   int $privilege              privilege to check against.
+* @param   bool        $check                  whether or not to return the result or to abort/exit.
+* @return  bool        true if this user is authenticated, false otherwise.
+* @see    query_bit() in include/vitals.inc.php
+* @author  Joel Kronenberg
+*/
+function authenticate($privilege, $check = false) {
+       if (!$_SESSION['valid_user']) {
+               return false;
+       }
+       if ($_SESSION['is_admin']) {
+               return true;
+       }
+       $auth = query_bit($_SESSION['privileges'], $privilege);
+
+       if (!$auth && $check) {
+               return false;
+       } else if (!$auth && !$check) {
+               exit;
+       }
+       return true;
+}
+
+function admin_authenticate($privilege = 0, $check = false) {
+       if (!isset($_SESSION['valid_user']) || !$_SESSION['valid_user'] || ($_SESSION['course_id'] != -1)) {
+               if ($check) {
+                       return false;
+               }
+               header('Location: '.AT_BASE_HREF.'login.php');
+               exit;
+       }
+
+       if ($_SESSION['privileges'] == AT_ADMIN_PRIV_ADMIN) {
+               return true;
+       }
+
+       if ($privilege) {
+               $auth = query_bit($_SESSION['privileges'], $privilege);
+
+               if (!$auth) {
+                       if ($check) {
+                               return false;
+                       }
+                       global $msg;
+                       $msg->addError('ACCESS_DENIED');
+                       require(AT_INCLUDE_PATH.'header.inc.php'); 
+                       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+                       exit;
+               }
+       }
+       return true;
+}
+
+function get_default_theme() {
+       global $db;
+
+       $sql    = "SELECT dir_name FROM ".TABLE_PREFIX."themes WHERE status=2";
+       $result = mysql_query($sql, $db);
+       $row = mysql_fetch_assoc($result);
+
+       return $row;
+}
+
+if (isset($_GET['expand'])) {
+       $_SESSION['menu'][intval($_GET['expand'])] = 1;
+} else if (isset($_GET['collapse'])) {
+       unset($_SESSION['menu'][intval($_GET['collapse'])]);
+}
+
+/**
+* Writes present action to admin log db
+* @access  private
+* @param   string $operation_type      The type of operation
+* @param   string $table_name          The table affected
+* @param   string $num_affected                The number of rows in the table affected
+* @author  Shozub Qureshi
+*/
+function write_to_log($operation_type, $table_name, $num_affected, $details) {
+       global $db;
+
+       if ($num_affected > 0) {
+               $details = addslashes(stripslashes($details));
+               $sql    = "INSERT INTO ".TABLE_PREFIX."admin_log VALUES ('$_SESSION[login]', NULL, $operation_type, '$table_name', $num_affected, '$details')";
+               $result = mysql_query($sql, $db);
+       }
+}
+
+function get_group_title($group_id) {
+       global $db;
+       $sql = "SELECT title FROM ".TABLE_PREFIX."groups WHERE group_id=$group_id";
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)) {
+               return $row['title'];
+       }
+       return FALSE;
+}
+
+function get_status_name($status_id) {
+       switch ($status_id) {
+               case AT_STATUS_DISABLED:
+                               return _AT('disabled');
+                               break;
+               case AT_STATUS_UNCONFIRMED:
+                       return _AT('unconfirmed');
+                       break;
+               case AT_STATUS_STUDENT:
+                       return _AT('student');
+                       break;
+               case AT_STATUS_INSTRUCTOR:
+                       return _AT('instructor');
+                       break;
+       }
+}
+
+function profile_image_exists($id) {
+       $extensions = array('gif', 'jpg', 'png');
+
+       foreach ($extensions as $extension) {
+               if (file_exists(AT_CONTENT_DIR.'profile_pictures/originals/'. $id.'.'.$extension)) {
+                       return true;
+               }
+       }
+}
+
+function print_profile_img($id) {
+       global $moduleFactory;
+       $mod = $moduleFactory->getModule('_standard/profile_pictures');
+       if ($mod->isEnabled() === FALSE) {
+               return;
+       }
+       if (profile_image_exists($id)) {
+               echo '<img src="get_profile_img.php?id='.$id.'" class="profile-picture" alt="" />';
+       } else {
+               echo '<img src="images/clr.gif" height="100" width="100" class="profile-picture" alt="" />';
+       }
+}
+
+function profile_image_delete($id) {
+       $extensions = array('gif', 'jpg', 'png');
+
+       foreach ($extensions as $extension) {
+               if (file_exists(AT_CONTENT_DIR.'profile_pictures/originals/'. $id.'.'.$extension)) {
+                       unlink(AT_CONTENT_DIR.'profile_pictures/originals/'. $id.'.'.$extension);
+               }
+               if (file_exists(AT_CONTENT_DIR.'profile_pictures/thumbs/'. $id.'.'.$extension)) {
+                       unlink(AT_CONTENT_DIR.'profile_pictures/thumbs/'. $id.'.'.$extension);
+               }
+       }
+}
+
+/**
+ * get_group_concat
+ * returns a list of $field values from $table using $where_clause, separated by $separator.
+ * uses mysql's GROUP_CONCAT() if available and if within the limit (default is 1024), otherwise
+ * it does it the old school way.
+ * returns the list (as a string) or (int) 0, if none found.
+ */
+function get_group_concat($table, $field, $where_clause = 1, $separator = ',') {
+       global $_config, $db;
+       if (!isset($_config['mysql_group_concat_max_len'])) {
+               $sql = "SELECT  @@global.group_concat_max_len AS max";
+               $result = mysql_query($sql, $db);
+               if ($result && ($row = mysql_fetch_assoc($result))) {
+                       $_config['mysql_group_concat_max_len'] = $row['max'];
+               } else {
+                       $_config['mysql_group_concat_max_len'] = 0;
+               }
+               $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('mysql_group_concat_max_len', '{$_config['mysql_group_concat_max_len']}')";
+               mysql_query($sql, $db);
+       }
+       if ($_config['mysql_group_concat_max_len'] > 0) {
+               $sql = "SELECT GROUP_CONCAT($field SEPARATOR '$separator') AS list FROM ".TABLE_PREFIX."$table WHERE $where_clause";
+               $result = mysql_query($sql, $db);
+               if ($row = mysql_fetch_assoc($result)) {
+                       if (!$row['list']) {
+                               return 0; // empty
+                       } else if ($row['list'] && strlen($row['list']) < $_config['mysql_group_concat_max_len']) {
+                               return $row['list'];
+                       } // else: list is truncated, do it the old way
+               } else {
+                       // doesn't actually get here.
+                       return 0; // empty
+               }
+       } // else:
+
+       $list = '';
+       $sql = "SELECT $field AS id FROM ".TABLE_PREFIX."$table WHERE $where_clause";
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_assoc($result)) {
+               $list .= $row['id'] . ',';
+       }
+       if ($list) {
+               return substr($list, 0, -1);
+       }
+       return 0;
+}
+
+function get_human_time($seconds) {
+       if ($seconds < 0) { 
+               $out = '0'._AT('second_short'); 
+       } else if ($seconds > 60 * 60) { // more than 60 minutes.
+               $hours = floor($seconds / 60 / 60);
+               $minutes = floor(($seconds - $hours * 60 * 60) / 60);
+               $out = $hours ._AT('hour_short').' '.$minutes._AT('minute_short');
+
+               //$out = ($seconds
+       } else if ($seconds > 60) { // more than a minute
+               $minutes = floor($seconds / 60);
+               $out = $minutes ._AT('minute_short').' '.($seconds - $minutes * 60)._AT('second_short');
+       } else { // less than a minute
+               $out = $seconds . _AT('second_short');
+       }
+
+       return $out;
+}
+
+require(AT_INCLUDE_PATH . 'classes/Module/Module.class.php');
+
+$moduleFactory =& new ModuleFactory(TRUE); // TRUE is for auto_loading the module.php files
+
+if (isset($_GET['submit_language']) && $_SESSION['valid_user']) {
+       if ($_SESSION['course_id'] == -1) {
+               $sql = "UPDATE ".TABLE_PREFIX."admins SET language = '$_SESSION[lang]' WHERE login = '$_SESSION[login]'";
+               $result = mysql_query($sql, $db);
+       } else {
+               $sql = "UPDATE ".TABLE_PREFIX."members SET language = '$_SESSION[lang]', creation_date=creation_date, last_login=last_login WHERE member_id = $_SESSION[member_id]";
+               $result = mysql_query($sql, $db);
+       }
+}
+//debug($_SESSION);
+?>
diff --git a/index.php b/index.php
new file mode 100644 (file)
index 0000000..9b8cc98
--- /dev/null
+++ b/index.php
@@ -0,0 +1,100 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', 'include/');
+require(AT_INCLUDE_PATH . 'vitals.inc.php');
+
+if (isset($_GET['cid'])) {
+       header('Location: '.$_base_href.'content.php?cid='.intval($_GET['cid']));
+       exit;
+}
+
+require(AT_INCLUDE_PATH . 'lib/test_result_functions.inc.php');
+       
+if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+       $course_base_href = 'get.php/';
+} else {
+       $course_base_href = 'content/' . $_SESSION['course_id'] . '/';
+}
+
+require(AT_INCLUDE_PATH . 'header.inc.php');
+               
+/* the "home" links: */
+$home_links = get_home_navigation();
+$savant->assign('home_links', $home_links);
+
+
+/* the news announcements: */
+$news = array(); 
+$num_pages = 1;
+$page = isset($_GET['p']) ? intval($_GET['p']) : 1;
+if (!$page) {
+       $page = 1;
+}      
+
+$module =& $moduleFactory->getModule(AT_MODULE_DIR_STANDARD.'/announcements');
+if (!$module->isEnabled()) {
+       $result = FALSE;
+       $news = array();
+} else {
+       $sql    = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."news WHERE course_id=$_SESSION[course_id]";
+       $result = mysql_query($sql, $db);
+}
+
+if ($result && ($row = mysql_fetch_assoc($result))) {
+       $num_results = $row['cnt'];
+       $results_per_page = NUM_ANNOUNCEMENTS;
+       $num_pages = ceil($num_results / $results_per_page);
+
+       $count = (($page-1) * $results_per_page) + 1;
+
+       $offset = ($page-1)*$results_per_page;
+
+       $sql = "SELECT N.*, DATE_FORMAT(N.date, '%Y-%m-%d %H-%i:%s') AS date, first_name, last_name 
+                 FROM ".TABLE_PREFIX."news N, ".TABLE_PREFIX."members M 
+                WHERE N.course_id=$_SESSION[course_id] 
+                  AND N.member_id = M.member_id
+                ORDER BY date DESC LIMIT $offset, $results_per_page";
+       
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_assoc($result)) {
+               /* this can't be cached because it called _AT */
+
+               $news[$row['news_id']] = array(
+                                               'date'          => AT_date(     _AT('announcement_date_format'), 
+                                                                                               $row['date'], 
+                                                                                               AT_DATE_MYSQL_DATETIME),
+                                         'author'  => $row['first_name'] . ' ' . $row['last_name'],
+                                               'title'         => AT_print($row['title'], 'news.title'),
+                                               'body'          => format_content($row['body'], $row['formatting'], $glossary));
+
+       }
+}
+
+$sql = "SELECT banner FROM ".TABLE_PREFIX."courses WHERE course_id=$_SESSION[course_id]";
+$result = mysql_query($sql, $db);
+if ($row = mysql_fetch_assoc($result)) {
+       $savant->assign('banner', AT_print($row['banner'], 'courses.banner'));
+} else {
+       $savant->assign('banner', '');
+}
+
+$savant->assign('announcements', $news);
+$savant->assign('num_pages', $num_pages);
+$savant->assign('current_page', $page);
+$savant->display('index.tmpl.php');
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+
+?>
\ No newline at end of file
diff --git a/install/db/atutor_convert_db_to_utf8.sql b/install/db/atutor_convert_db_to_utf8.sql
new file mode 100644 (file)
index 0000000..b4509b6
--- /dev/null
@@ -0,0 +1,196 @@
+###############################################################\r
+# Database UTF-8 database conversion for ATutor < 1.6\r
+# This script only applies to those databases that have UTF-8\r
+# data in non-UTF-8 tables.\r
+# ref: http://dev.mysql.com/doc/refman/5.0/en/alter-table.html\r
+# @author harris\r
+###############################################################\r
+\r
+# 1.6 UTF 8 Conversion to Binary\r
+ALTER TABLE `admins` MODIFY COLUMN `real_name` BLOB;\r
+ALTER TABLE `assignments` MODIFY COLUMN `title` BLOB;\r
+ALTER TABLE `backups` MODIFY COLUMN `description` BLOB, MODIFY COLUMN `file_name` BLOB;\r
+ALTER TABLE `blog_posts` MODIFY COLUMN `title` BLOB;\r
+ALTER TABLE `content` MODIFY COLUMN `keywords` BLOB, MODIFY COLUMN `content_path` BLOB,\r
+ MODIFY COLUMN `title` BLOB;\r
+ALTER TABLE `courses` MODIFY COLUMN `title` BLOB;\r
+ALTER TABLE `course_cats` MODIFY COLUMN `cat_name` BLOB;\r
+ALTER TABLE `external_resources` MODIFY COLUMN `title` BLOB, MODIFY COLUMN `author` BLOB,\r
+ MODIFY COLUMN `publisher` BLOB, MODIFY COLUMN `comments` BLOB;\r
+ALTER TABLE `faq_entries` MODIFY COLUMN `question` BLOB;\r
+ALTER TABLE `faq_topics` MODIFY COLUMN `name` BLOB;\r
+ALTER TABLE `folders` MODIFY COLUMN `title` BLOB;\r
+ALTER TABLE `forums` MODIFY COLUMN `title` BLOB;\r
+ALTER TABLE `forums_threads` MODIFY COLUMN `subject` BLOB;\r
+ALTER TABLE `glossary` MODIFY COLUMN `word` BLOB;\r
+ALTER TABLE `groups` MODIFY COLUMN `title` BLOB;\r
+ALTER TABLE `groups_types` MODIFY COLUMN `title` BLOB;\r
+ALTER TABLE `links` MODIFY COLUMN `Description` BLOB,\r
+ MODIFY COLUMN `SubmitName` BLOB, MODIFY COLUMN `SubmitEmail` BLOB;\r
+ALTER TABLE `links_categories` MODIFY COLUMN `name` BLOB;\r
+ALTER TABLE `mail_queue` MODIFY COLUMN `subject` BLOB;\r
+ALTER TABLE `members` MODIFY COLUMN `first_name` BLOB, MODIFY COLUMN `second_name` BLOB,\r
+ MODIFY COLUMN `last_name` BLOB, MODIFY COLUMN `address` BLOB, MODIFY COLUMN `city` BLOB,\r
+ MODIFY COLUMN `province` BLOB, MODIFY COLUMN `country` BLOB;\r
+ALTER TABLE `messages` MODIFY COLUMN `subject` BLOB;\r
+ALTER TABLE `messages_sent` MODIFY COLUMN `subject` BLOB;\r
+ALTER TABLE `news` MODIFY COLUMN `title` BLOB;\r
+ALTER TABLE `polls` MODIFY COLUMN `question` BLOB, MODIFY COLUMN `choice1` BLOB,\r
+ MODIFY COLUMN `choice2` BLOB, MODIFY COLUMN `choice3` BLOB, MODIFY COLUMN `choice4` BLOB,\r
+ MODIFY COLUMN `choice5` BLOB, MODIFY COLUMN `choice6` BLOB, MODIFY COLUMN `choice7` BLOB;\r
+ALTER TABLE `tests` MODIFY COLUMN `title` BLOB;\r
+ALTER TABLE `tests_questions` MODIFY COLUMN `choice_0` BLOB,\r
+ MODIFY COLUMN `choice_1` BLOB,\r
+ MODIFY COLUMN `choice_2` BLOB,\r
+ MODIFY COLUMN `choice_3` BLOB,\r
+ MODIFY COLUMN `choice_4` BLOB,\r
+ MODIFY COLUMN `choice_5` BLOB,\r
+ MODIFY COLUMN `choice_6` BLOB,\r
+ MODIFY COLUMN `choice_7` BLOB,\r
+ MODIFY COLUMN `choice_8` BLOB,\r
+ MODIFY COLUMN `choice_9` BLOB,\r
+ MODIFY COLUMN `option_0` BLOB,\r
+ MODIFY COLUMN `option_1` BLOB,\r
+ MODIFY COLUMN `option_2` BLOB,\r
+ MODIFY COLUMN `option_3` BLOB,\r
+ MODIFY COLUMN `option_4` BLOB,\r
+ MODIFY COLUMN `option_5` BLOB,\r
+ MODIFY COLUMN `option_6` BLOB,\r
+ MODIFY COLUMN `option_7` BLOB,\r
+ MODIFY COLUMN `option_8` BLOB,\r
+ MODIFY COLUMN `option_9` BLOB;\r
+\r
+\r
+# 1.6 UTF 8 table VARCHAR * 4 changes\r
+ALTER TABLE `admins` MODIFY COLUMN `real_name` VARCHAR(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `assignments` MODIFY COLUMN `title` VARCHAR(240) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `backups` MODIFY COLUMN `description` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `file_name` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `blog_posts` MODIFY COLUMN `title` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `content` MODIFY COLUMN `keywords` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `content_path` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `title` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `courses` MODIFY COLUMN `title` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `course_cats` MODIFY COLUMN `cat_name` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `external_resources` MODIFY COLUMN `title` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `author` VARCHAR(150) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `publisher` VARCHAR(150) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `comments` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `faq_entries` MODIFY COLUMN `question` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `faq_topics` MODIFY COLUMN `name` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `folders` MODIFY COLUMN `title` VARCHAR(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `forums` MODIFY COLUMN `title` VARCHAR(240) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `forums_threads` MODIFY COLUMN `subject` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `glossary` MODIFY COLUMN `word` VARCHAR(240) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `groups` MODIFY COLUMN `title` VARCHAR(80) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `groups_types` MODIFY COLUMN `title` VARCHAR(80) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `links` MODIFY COLUMN `Description` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `SubmitName` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `SubmitEmail` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `links_categories` MODIFY COLUMN `name` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `mail_queue` MODIFY COLUMN `subject` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `members` MODIFY COLUMN `first_name` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `second_name` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `last_name` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `address` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `city` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `province` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `country` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `messages` MODIFY COLUMN `subject` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `messages_sent` MODIFY COLUMN `subject` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `news` MODIFY COLUMN `title` VARCHAR(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `polls` MODIFY COLUMN `question` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `choice1` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `choice2` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `choice3` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `choice4` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `choice5` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `choice6` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `choice7` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `tests` MODIFY COLUMN `title` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `tests_questions` MODIFY COLUMN `choice_0` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `choice_1` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `choice_2` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `choice_3` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `choice_4` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `choice_5` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `choice_6` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `choice_7` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `choice_8` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `choice_9` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `option_0` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `option_1` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `option_2` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `option_3` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `option_4` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `option_5` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `option_6` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `option_7` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `option_8` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `option_9` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `tests_questions_categories` MODIFY COLUMN `title` CHAR(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+ALTER TABLE `themes` MODIFY COLUMN `title` VARCHAR(80) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\r
+ MODIFY COLUMN `extra_info` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;\r
+\r
+# 1.6.1 Change all table to UTF-8 collation\r
+ALTER TABLE `admins` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `admin_log` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `assignments` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `auto_enroll` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `auto_enroll_courses` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `backups` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `blog_posts` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `blog_posts_comments` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `config` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `content` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `courses` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `course_access` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `course_cats` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `course_enrollment` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `course_stats` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `external_resources` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `faq_entries` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `faq_topics` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `feeds` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `files` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `files_comments` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `file_storage_groups` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `folders` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `forums` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `forums_accessed` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `forums_courses` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `forums_groups` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `forums_subscriptions` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `forums_threads` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `glossary` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `groups` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `groups_members` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `groups_types` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `handbook_notes` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `instructor_approvals` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `languages` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `language_pages` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `language_text` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `links` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `links_categories` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `mail_queue` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `master_list` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `members` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `member_track` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `messages` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `messages_sent` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `modules` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `news` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `polls` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `polls_members` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `reading_list` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `related_content` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `tests` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `tests_answers` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `tests_groups` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `tests_questions` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `tests_questions_assoc` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `tests_questions_categories` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `tests_results` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `themes` CONVERT TO CHARACTER SET utf8;\r
+ALTER TABLE `users_online` CONVERT TO CHARACTER SET utf8;\r
diff --git a/install/db/atutor_language_text.sql b/install/db/atutor_language_text.sql
new file mode 100644 (file)
index 0000000..a105d24
--- /dev/null
@@ -0,0 +1,1783 @@
+# Table structure for table 'language_text'\r
+#\r
+\r
+CREATE TABLE `language_text` (\r
+  `language_code` varchar(20) NOT NULL default '',\r
+  `variable` varchar(120) NOT NULL default '',\r
+  `term` varchar(180) NOT NULL default '',\r
+  `text` text NOT NULL,\r
+  `revised_date` datetime NOT NULL default '0000-00-00 00:00:00',\r
+  `context` text NOT NULL,\r
+  PRIMARY KEY  (`language_code`,`variable`,`term`)\r
+) TYPE=MyISAM;\r
+\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_CONFIRM_ADD_FEED', 'Are you sure you want to add this syndicated feed?', '2005-11-15 13:19:26', ''),\r
+('en', '_msgs', 'AT_CONFIRM_ADD_MODULE', 'Are you sure you want to install the module in <strong><code>%s</code></strong>?', '2005-08-17 12:59:04', ''),\r
+('en', '_msgs', 'AT_CONFIRM_ADD_TEST_QUESTIONS', 'Are you sure you want to <em>add</em> the following questions? \r\n<ul>%s</ul>', '2004-11-23 12:38:56', ''),\r
+('en', '_msgs', 'AT_CONFIRM_ALUMNI', 'Are you sure you want to mark the following users as course alumni: <ul> %s </ul>', '2004-11-23 12:17:53', 'enrollment_manager, make students into alumi'),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE', 'Are you sure you want to delete this item?', '2006-10-03 14:12:34', 'generic delete confirmation msg'),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_ASSIGNMENT', 'Are you sure you want to delete assignment <em>%s</em>?', '2006-05-23 13:10:30', ''),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_CATEGORY', 'Are you sure you want to delete category  <strong>%s</strong>?', '2005-02-17 14:57:18', ''),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_COURSE_1', 'Are you sure you want to <strong>Delete</strong> the course <strong><em>%s</em></strong>?', '2005-03-04 11:27:35', ''),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_COURSE_2', 'Are you <strong>really really</strong> sure you want to <b>Delete</b> the course <strong><em>%s</em></strong>? Deleted courses can not be recovered.', '2005-03-04 11:31:35', ''),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_FAQ_QUESTION', 'Are you sure you want to delete the question <strong>%s</strong>?', '2005-10-19 12:49:55', ''),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_FAQ_TOPIC', 'Are you sure you want to delete the topic <strong>%s</strong> and its questions?', '2005-11-08 13:42:33', ''),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_FEED', 'Are you sure you want to delete feed <strong>%s</strong>.?', '2005-12-07 09:36:25', ''),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_FORUM', 'Are you sure you want to delete <strong>%s</strong> forum? All messages posted to this forum will be erased.', '2005-12-07 09:36:15', 'deleting a forum'),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_GROUP', 'Are you sure you want to delete the group: <strong>%s</strong>?', '2005-02-21 12:07:05', 'deletep enrollment group'),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_GROUP_TYPE', 'Are you sure you want to delete group type <em>%s</em> and all its groups?', '2006-03-23 11:27:52', ''),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_LANG', 'Are you sure you want to delete the language ( <strong>%s </strong>)?', '2004-11-24 13:19:50', ''),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_LINK', 'Are you sure you want to delete the link %s?', '2005-02-21 16:55:38', ''),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_MSGS', 'Are you sure you want to delete the selected messages?', '2007-02-22 13:09:14', ''),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_NEWS', 'Are you sure you want to delete %s?', '2004-11-24 13:37:55', 'news deletion in editor'),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_POLL', 'Are you sure you want to delete this poll \'%s\'?  It cannot be recovered once deleted.', '2004-11-24 14:03:36', 'editor'),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_TEST', 'Are you sure you want to delete the test/survey <strong><em>%s</em></strong> and any results? The questions, however, will not be deleted.', '2004-12-15 10:42:13', 'Deleting Test'),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_TEST_CATEGORY', 'Are you sure you want to delete test category <strong>%s</strong>?', '2005-03-07 11:58:48', ''),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_THEME', 'Are you sure you want to delete the following theme: <b> % s </b>', '2004-11-23 09:30:03', 'confirm message for delete theme'),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_TRACKING', 'Are you sure your want to delete the content usage data for this course?', '2005-08-11 10:08:50', 'reset tracking session'),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_TRANSCRIPT', 'Are you sure you want to delete the transcript <strong>%s</strong>?', '2005-03-30 14:21:00', 'delete chat transcript'),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_USER', 'Are you sure you want to delete the following users? Selected instructors who own courses will not be deleted.<strong>%s</strong>', '2007-02-19 11:44:45', 'deleting user from admin'),\r
+('en', '_msgs', 'AT_CONFIRM_DIR_DELETE', 'Are you sure you want to delete the following folder(s) and all their contents? <ul><strong>%s</strong></ul>', '2004-12-15 09:59:39', 'filemanager'),\r
+('en', '_msgs', 'AT_CONFIRM_DIR_MOVE', 'Are you sure you want to move <strong>%1s</strong> to the folder <strong>%2s</strong>?', '2005-01-10 10:35:17', 'filemanager'),\r
+('en', '_msgs', 'AT_CONFIRM_EDIT_STATUS', 'Are you sure you want to change the following users\' status to  <strong>%s</strong>? Status of selected instructors who own courses will not be changed. %s', '2007-02-19 11:43:37', ''),\r
+('en', '_msgs', 'AT_CONFIRM_ENROLL_STUDENT', 'Are you sure you want to enroll the following users: <ul> %s </ul>', '2004-11-23 12:21:00', 'enrollment manager, enroll confirm'),\r
+('en', '_msgs', 'AT_CONFIRM_FILE_DELETE', 'Are you sure you want to delete the following file(s)? <ul>%s</ul>', '2006-07-05 11:44:15', 'filemanager'),\r
+('en', '_msgs', 'AT_CONFIRM_FILE_EXISTS', 'The file <strong>%s</strong> already exists. Do you want to overwrite the file?', '2005-03-09 16:26:11', 'filemanager'),\r
+('en', '_msgs', 'AT_CONFIRM_FILE_MOVE', 'Are you sure you want to move <strong>%1s</strong> to the folder <strong>%2s</strong>?', '2005-01-10 10:33:21', 'file_manager'),\r
+('en', '_msgs', 'AT_CONFIRM_GLOSSARY_REMAINS', 'Deleting a term will not remove the embedded glossary codes from your content.', '2005-02-24 10:34:33', 'content deletion'),\r
+('en', '_msgs', 'AT_CONFIRM_LIST_DELETE', 'Are you sure you want to delete <strong>%s</strong> Student ID from the master student list?', '2005-04-04 15:47:51', ''),\r
+('en', '_msgs', 'AT_CONFIRM_LOGIN_INSTRUCTOR', '<h3>%2$s</h3>\r\nYou will be logged in as the instructor for this course.  Are you sure you want to continue?', '2006-04-10 13:12:29', 'viewing courses from admin'),\r
+('en', '_msgs', 'AT_CONFIRM_NO_ANSWER', 'You are about to add a question with no correct choice. Continue?', '2004-12-06 14:35:10', 'adding a question without specifying answer'),\r
+('en', '_msgs', 'AT_CONFIRM_REMOVE_STUDENT', 'Are you sure you want to remove the following students: <ul> %s </ul>', '2004-11-23 12:21:12', 'removing a student'),\r
+('en', '_msgs', 'AT_CONFIRM_REMOVE_TEST_QUESTION', 'Are you sure you want to remove this question from this test? Removing the question will not delete it from the question database.', '2004-11-25 10:31:52', ''),\r
+('en', '_msgs', 'AT_CONFIRM_RESET_ADMIN_LOG', 'Are you sure you want to delete the Administrator Activity Log?', '2005-03-03 10:42:50', ''),\r
+('en', '_msgs', 'AT_CONFIRM_RESET_ERROR_LOG', 'Are you sure you want to delete all the error logs?', '2005-03-10 15:49:02', 'error log reset (delete logs folder0'),\r
+('en', '_msgs', 'AT_CONFIRM_RL_DELETE_READING', 'Are you sure you want to delete this reading: <strong>%s</strong>?', '2006-10-04 10:48:51', ''),\r
+('en', '_msgs', 'AT_CONFIRM_RL_DELETE_RESOURCE', 'Are you sure you want to delete this resource: <strong>%s</strong>?<br/>Note: Any readings that use this resource will also be deleted.', '2006-10-04 10:48:36', ''),\r
+('en', '_msgs', 'AT_CONFIRM_STUDENT_GROUP', 'Are you sure you want to add the following users to group \'%s\'? <ul> %s </ul>', '2005-06-02 12:07:05', ''),\r
+('en', '_msgs', 'AT_CONFIRM_STUDENT_REMOVE_GROUP', 'Are you sure you want to <strong>remove</strong> the following users from group \'%s\'? <ul> %s </ul>', '2005-06-02 12:06:56', 'Enrollment'),\r
+('en', '_msgs', 'AT_CONFIRM_SUB_CONTENT_DELETE', 'This content page has sub content. If you delete this page all its sub pages will be deleted as well.<br />', '2004-11-24 13:31:34', 'content deletion'),\r
+('en', '_msgs', 'AT_CONFIRM_UNENROLL', 'Are you sure you want to un-enroll from <strong>%s</strong>?', '2005-03-24 12:43:34', ''),\r
+('en', '_msgs', 'AT_CONFIRM_UNENROLL_PRIV', 'Are you sure you want to un-enroll the following users (the users will have their roles and privileges removed): <ul> %s </ul>', '2004-11-23 12:23:22', 'enrollment manager, unenrolling a TA'),\r
+('en', '_msgs', 'AT_CONFIRM_UNENROLL_STUDENT', 'Are you sure you want to un-enroll the following students: <ul> %s </ul>', '2004-11-23 12:21:36', 'enrollment manager, confirm unenroll'),\r
+('en', '_msgs', 'AT_ERROR_ACCESS_DENIED', 'You do not have permission to access this area.', '2005-06-15 15:13:59', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_ACCOUNT_DISABLED', 'That account has been disabled.', '2005-04-01 10:30:12', ''),\r
+('en', '_msgs', 'AT_ERROR_ADMIN_EDIT_OWN_ACCOUNT', 'To edit your own account use the <a href=\"admin/admins/my_edit.php\">My Account</a> page.', '2006-06-14 13:58:22', ''),\r
+('en', '_msgs', 'AT_ERROR_ALREADY_ENROLED', 'You have already made a request to enroll in this course and you have not yet been approved by the instructor. You will be notifed when your request has been approved.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_ALREADY_OWNED', 'You own this course, and cannot enroll.', '2004-11-26 14:30:22', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_ASSIGNMENT_CUTOFF', 'The assignment cut-off date has past. Submissions are no longer accepted.', '2006-03-20 14:41:46', ''),\r
+('en', '_msgs', 'AT_ERROR_BACKUP_RESTORE', 'Restore failed - file is not a valid backup. Backups older than version 1.3 are not supported.', '2005-11-29 14:33:56', ''),\r
+('en', '_msgs', 'AT_ERROR_BACKUP_UNSUPPORTED_GREATER_VERSION', 'Backups created from versions of ATutor greater than this version are not supported.', '2005-05-11 15:56:50', ''),\r
+('en', '_msgs', 'AT_ERROR_BAD_DATE', 'That date is not valid.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_BAD_FILE_TYPE', 'Unsupported file type. Plain Text or HTML files only.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_BAD_FOLDER_NAME', 'The folder name contains illegal characters. You may choose from alphanumeric characters and underscores, dashes or periods.', '2005-01-10 13:13:55', 'filemanager, foilder with illegal chars'),\r
+('en', '_msgs', 'AT_ERROR_CACHE_DIR_BAD', 'Cache dir cannot be created. Cache disabled. See the configuration options to either disable or fix the problem.', '2003-05-27 13:10:53', 'global'),\r
+('en', '_msgs', 'AT_ERROR_CANNOT_CREATE_DIR', 'Cannot create content directory.', '2003-10-15 12:20:51', ''),\r
+('en', '_msgs', 'AT_ERROR_CANNOT_DELETE_OWN_ACCOUNT', 'You cannot delete your own account.', '2005-03-03 10:59:44', ''),\r
+('en', '_msgs', 'AT_ERROR_CANNOT_OPEN_DIR', 'Unable to open content directory. You may try to <a href=\"tools/filemanager/new.php\">create it now</a>.', '2007-10-12 11:30:32', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_CANNOT_OPEN_FILE', 'Cannot open the file: <b> %s </b>', '2004-10-18 14:38:00', 'Theme Manager'),\r
+('en', '_msgs', 'AT_ERROR_CANNOT_OVERWRITE_FILE', 'Cannot override file.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_CANNOT_READ_FILE', 'Cannot read from file: <b> %s </b>', '2004-11-19 13:00:03', 'admin/error_logging.php'),\r
+('en', '_msgs', 'AT_ERROR_CANNOT_RENAME', 'File or directory cannot be renamed. Either a file or directory with that name already exists, the original file or directory does not exist, or the file or directory name has not changed.', '2004-08-20 12:05:15', ''),\r
+('en', '_msgs', 'AT_ERROR_CANNOT_WRITE_FILE', 'Cannot write to file: <b> %s </b>', '2004-10-18 14:39:10', 'Theme Manager'),\r
+('en', '_msgs', 'AT_ERROR_CHAT_TRAN_REJECTED', 'Transcript filename rejected. Please ensure that it is  alphanumeric and contains no spaces.', '2003-06-02 13:47:39', 'achat'),\r
+('en', '_msgs', 'AT_ERROR_CHOICES_EMPTY', 'Enter at least two answer choices.', '2005-03-08 15:41:49', ''),\r
+('en', '_msgs', 'AT_ERROR_CONFIG_NOT_WRITEABLE', 'It is not possible to edit these settings because the configuration file is locked for security reasons. If you want to make changes, you need to unlock the config.inc.php file first by changing its permissions with the command <kbd>chmod a+rw config.inc.php</kbd>.', '2005-03-03 10:14:48', ''),\r
+('en', '_msgs', 'AT_ERROR_CONFIRM_BAD', 'Your email address and account could not be confirmed.', '2005-05-31 12:55:25', ''),\r
+('en', '_msgs', 'AT_ERROR_CONTACT_INFO_NOT_FOUND', 'Contact Support is not available, because an email address has not been specified.', '2005-03-17 11:33:38', ''),\r
+('en', '_msgs', 'AT_ERROR_COURSE_ENDED', 'This course ended on %s.', '2007-07-16 11:53:27', ''),\r
+('en', '_msgs', 'AT_ERROR_COURSE_NOT_RELEASED', 'This course can only be accessed on %s.', '2006-04-10 14:28:27', ''),\r
+('en', '_msgs', 'AT_ERROR_CREATE_MASTER_USED', 'The Student ID you have entered already belongs to another user. If you wish to over-write this association with the new account, use the over-write checkbox.', '2006-06-12 15:39:43', ''),\r
+('en', '_msgs', 'AT_ERROR_CREATE_NOPERM', 'You do not have permission to create courses.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_DB_NOT_UPDATED', 'Information could not be added to the database.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_DIR_NOT_DELETED', 'Cannot open directory to be deleted.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_DIR_NOT_EXIST', 'Directory <strong>%s</strong> does not exist. Please create it.', '2005-09-22 14:08:05', 'file manager'),\r
+('en', '_msgs', 'AT_ERROR_DIR_NOT_WRITEABLE', 'Directory <strong>%s</strong> is not writeable. On Unix issue the command <kbd>chmod a+rw</kbd> on the directory.', '2005-09-22 14:22:24', ''),\r
+('en', '_msgs', 'AT_ERROR_DIR_NO_PERMISSION', 'Cannot delete folder. You may not have premission, or it may not be empty.', '2003-05-22 12:20:14', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_DISABLE_CORE_MODULE', 'Core modules cannot be disabled.', '2005-08-25 14:00:13', ''),\r
+('en', '_msgs', 'AT_ERROR_DISABLE_MISSING_MODULE', 'You cannot disable a missing module. To continue managing this module you must first restore its directory.', '2005-10-05 16:22:01', ''),\r
+('en', '_msgs', 'AT_ERROR_DOB_INVALID', 'Date of birth has invalid format.', '2004-06-24 12:53:34', ''),\r
+('en', '_msgs', 'AT_ERROR_EMAIL_EXISTS', 'An account with that email address already exists.', '2005-03-01 11:36:57', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_EMAIL_INVALID', 'Email address was invalid.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_EMAIL_NOT_FOUND', 'No account found with that email address.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_EMPTY_FIELDS', 'The following required field(s) are empty:<br />\r\n%s.', '2006-10-05 15:51:52', ''),\r
+('en', '_msgs', 'AT_ERROR_END_DATE_INVALID', 'That end date is not valid.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_ENROLLMENT_NONE_FOUND', 'There is no one to export.', '2006-06-27 11:53:26', ''),\r
+('en', '_msgs', 'AT_ERROR_FEED_NO_CONTENT', 'The feed either cannot be found at that URL or is not valid.', '2005-11-23 10:59:56', ''),\r
+('en', '_msgs', 'AT_ERROR_FILE_EMPTY', 'You did not select a file to import or the file was empty.', '2004-12-09 14:44:43', 'enrollment manager'),\r
+('en', '_msgs', 'AT_ERROR_FILE_ILLEGAL', '%s files are not allowed.', '2003-05-22 11:52:08', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_FILE_MAX_SIZE', 'The file exceeded the maximum allowable size limit of %s.', '2004-05-06 13:18:19', ''),\r
+('en', '_msgs', 'AT_ERROR_FILE_NOT_DELETED', 'Error deleting file. Cannot delete file.', '2004-11-08 16:33:12', 'file manager'),\r
+('en', '_msgs', 'AT_ERROR_FILE_NOT_EXIST', 'The selected file does not exist.', '2005-01-07 09:51:45', 'filemanager, fiule to be edited does not exist'),\r
+('en', '_msgs', 'AT_ERROR_FILE_NOT_FOUND', 'File not found.', '2006-03-20 14:45:12', ''),\r
+('en', '_msgs', 'AT_ERROR_FILE_NOT_SAVED', 'The file cannot be saved.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_FILE_NOT_SELECTED', 'You did not select a file to upload.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_FILE_TOO_BIG', 'The file size exceeds the limit of <strong>%s </strong>. Contact your ATutor Administrator to have this limit increased.', '2005-01-15 18:49:53', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_FIRST_LAST_NAME_UNIQUE', 'First, second, and last names combination must be unique.', '2006-03-27 14:55:34', ''),\r
+('en', '_msgs', 'AT_ERROR_FOLDER_NOT_CREATED', 'The folder \" %s \" could not be created.', '2006-06-02 13:43:53', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_FOLDER_NOT_EXIST', 'Folder not found.', '2006-03-20 15:37:24', ''),\r
+('en', '_msgs', 'AT_ERROR_FORUM_DENIED', 'You do not  have permission to post in this forum.', '2005-08-10 13:48:14', ''),\r
+('en', '_msgs', 'AT_ERROR_FORUM_NOT_FOUND', 'Forum can not be found.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_FORUM_NO_DEL_SHARE', 'You do not have permission to delete a shared forum.', '2004-12-10 11:10:25', ''),\r
+('en', '_msgs', 'AT_ERROR_FORUM_NO_EDIT_SHARE', 'You do not have permission to edit a Shared forum.', '2004-12-10 11:15:41', ''),\r
+('en', '_msgs', 'AT_ERROR_FORUM_NO_SUBSCRIBE', 'Cannot subscribe to the requested thread. Only subscription to the top-level post is allowed.', '2004-12-10 13:44:57', 'forum/subscribe.php'),\r
+('en', '_msgs', 'AT_ERROR_GENERAL', 'This is a search and %s ATutor error.', '2003-05-22 11:52:28', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_GOOGLE_KEY_INVALID', 'Invalid key.', '2005-11-30 14:35:03', ''),\r
+('en', '_msgs', 'AT_ERROR_GOOGLE_KEY_MISSING', 'A Google Key must be entered in order for the enabled Web Search to be available in courses. Enter this key by going to Google Key under the Configuration tab.', '2005-11-30 14:40:38', ''),\r
+('en', '_msgs', 'AT_ERROR_GOOGLE_QUERY_FAILED', 'Query failed.', '2005-10-20 10:52:04', ''),\r
+('en', '_msgs', 'AT_ERROR_GROUP_NOT_FOUND', 'Group not found.', '2004-11-25 16:03:01', ''),\r
+('en', '_msgs', 'AT_ERROR_GROUP_NO_STUDENTS', 'There are no students to create groups for.', '2006-03-22 13:33:24', ''),\r
+('en', '_msgs', 'AT_ERROR_HAND_IN_FOLDER', 'Folders cannot be handed in.', '2006-03-20 15:43:06', ''),\r
+('en', '_msgs', 'AT_ERROR_ID_ZERO', 'Content ID was zero, or was missing.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_IMPORTDIR_FAILED', 'Unable to create import directory.', '2005-07-20 14:02:57', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_IMPORTDIR_IMS_NOTVALID', 'The file does not appear to be a valid ZIP file.', '2005-06-27 11:37:47', 'IMS file is not a ZIP file.'),\r
+('en', '_msgs', 'AT_ERROR_IMPORTFILE_EMPTY', 'The import file must not be empty.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_IMPORT_ERROR_IN_ZIP', 'Zip file could not be extracted because: <b> %s </b>', '2006-06-28 10:30:50', 'theme manager'),\r
+('en', '_msgs', 'AT_ERROR_IMPORT_FAILED', 'Import Failed', '2005-01-15 09:50:40', ''),\r
+('en', '_msgs', 'AT_ERROR_IMPORT_NOT_PROPER_FORMAT', 'The selected file does not appear to be a valid theme package.', '2004-12-09 11:34:27', 'admin/themes/import.php'),\r
+('en', '_msgs', 'AT_ERROR_INCOMPLETE', 'Please fill out the forms as directed below', '2004-10-18 11:14:50', 'enrollment Manager, incomplete info in create list'),\r
+('en', '_msgs', 'AT_ERROR_INCORRECT_FILE_FORMAT', 'File is in the incorrect format. Review line %s of your course list file and make sure it follows format guidelines.', '2006-06-28 10:43:48', ''),\r
+('en', '_msgs', 'AT_ERROR_INST_INFO_NOT_FOUND', 'Instructor information cannot be found.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_INVALID_LINK', 'The link is either invalid or expired.', '2006-05-10 09:08:50', ''),\r
+('en', '_msgs', 'AT_ERROR_INVALID_LOGIN', 'Invalid login/password combination.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_INVALID_URL', 'Localhost is not a valid URL', '2004-11-05 10:22:37', 'AChecker'),\r
+('en', '_msgs', 'AT_ERROR_ITEM_NOT_FOUND', 'Item not found.', '2006-10-04 10:52:48', 'generic something not found msg.'),\r
+('en', '_msgs', 'AT_ERROR_LANG_EXISTS', 'The language pack you are trying to import already exists. Language already exists. You can edit language properties by following the <em>translate</em> in the sub menu above.', '2007-02-06 15:44:17', ''),\r
+('en', '_msgs', 'AT_ERROR_LANG_IMPORT_FAILED', 'Language import failed.', '2003-06-06 11:23:51', 'admin language manager'),\r
+('en', '_msgs', 'AT_ERROR_LANG_NOT_COMPLETE', 'The language pack you are trying to import has not been marked as complete and published. To use incomplete language packs you must enable <em>translating</em> using the instructions at the bottom of this page.', '2005-11-30 14:49:00', ''),\r
+('en', '_msgs', 'AT_ERROR_LANG_WRONG_VERSION', 'The language pack you are trying to import is not compatible with this version of ATutor. If you still want to import this language pack you must enable <em>translating</em> following the instructions at the bottom of this page.', '2005-11-30 14:50:49', ''),\r
+('en', '_msgs', 'AT_ERROR_LAST_LANGUAGE', 'Cannot delete the last language. At least one language must be available.', '2006-06-29 16:50:59', ''),\r
+('en', '_msgs', 'AT_ERROR_LINK_CAT_EMPTY', 'Cannot add a link because there are no categories.', '2005-03-09 13:05:25', 'adding link but no cats'),\r
+('en', '_msgs', 'AT_ERROR_LINK_CAT_NOT_EMPTY', 'Link category cannot be deleted because it contains sub-categories and/or links.', '2005-02-22 15:22:44', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_LOGIN_CHARS', 'Your Login Name must only contain letters, numbers, periods, or underscores (_\'s).', '2006-07-11 10:40:57', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_LOGIN_ENROL', 'You must be logged in to enroll in a course.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_LOGIN_EXISTS', 'That login already exists, please choose another.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_LOGIN_TO_POST', 'You must be logged in to post.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_LOG_NOT_RESET', 'The error log could not be reset.', '2005-03-10 15:54:03', 'error logging'),\r
+('en', '_msgs', 'AT_ERROR_MAX_ATTEMPTS', 'The test cannot be taken.  It is not available at this time, or you have reached the maximum number of attempts for this test.', '2004-09-02 12:59:25', ''),\r
+('en', '_msgs', 'AT_ERROR_MAX_STORAGE_EXCEEDED', 'Adding this file exceeds the maximum course storage limit.', '2003-10-03 16:00:08', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_MISSING_THEMEXML', 'Cannot import. The import package is missing a vital component: themes.xml. Check that the theme package is for version 1.4.3 or above.', '2004-12-09 11:59:21', 'admin/themese/import.php'),\r
+('en', '_msgs', 'AT_ERROR_MODULE_INSTALL', 'The following error(s) were encountered when trying to install this module:\r\n<ul>%s</ul>', '2005-10-11 10:48:49', ''),\r
+('en', '_msgs', 'AT_ERROR_NEED_FILENAME', 'Filename was left empty. Need a filename to create new file.', '2004-11-09 16:19:24', 'file manager'),\r
+('en', '_msgs', 'AT_ERROR_NODELETE_USER', 'Cannot delete this user because they own courses. Delete the courses first.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_NOT_CONFIRMED', 'Your account\'s email address has not yet been confirmed.  Please check your email account for a confirmation message.  Please contact us if you do not receive it.', '2006-06-21 10:59:56', ''),\r
+('en', '_msgs', 'AT_ERROR_NOT_IN_ANY_GROUPS', 'You are not in any groups.', '2006-04-11 13:34:20', ''),\r
+('en', '_msgs', 'AT_ERROR_NOT_OWNER', 'You do not own this course or it does not exist.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_NOT_RELEASED', 'This content has not yet been released. %s', '2003-05-22 11:52:38', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_NO_ACTION_SELECTED', 'No action selected.', '2007-02-21 14:12:39', ''),\r
+('en', '_msgs', 'AT_ERROR_NO_ASSIGNMENTS_FOUND', 'No due assignments are due in this workspace. You might try another workspace.', '2006-06-29 14:47:15', ''),\r
+('en', '_msgs', 'AT_ERROR_NO_CONTENT_SPACE', 'Not enough space to import content directory. %s KB over the limit.', '2003-10-03 15:58:38', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_NO_COURSE_FLOAT', 'Invalid Maximum Course Float value.', '2005-06-20 10:44:45', 'Admin did not specify a float for course size.'),\r
+('en', '_msgs', 'AT_ERROR_NO_FAQ_TOPICS', 'You must first add a topic.', '2005-10-19 12:44:36', ''),\r
+('en', '_msgs', 'AT_ERROR_NO_IMSMANIFEST', 'IMS manifest file is missing. This does not appear to be a valid IMS content package.', '2003-10-27 11:43:08', ''),\r
+('en', '_msgs', 'AT_ERROR_NO_IMS_BACKUP', 'This file appears to be a <a href=\"tools/backup/\">course backup</a> rather than a content package.', '2003-11-03 12:14:37', ''),\r
+('en', '_msgs', 'AT_ERROR_NO_ITEM_SELECTED', 'You must select an item before using a button.', '2005-03-07 16:36:43', ''),\r
+('en', '_msgs', 'AT_ERROR_NO_LANGUAGE', 'Selected language is not supported.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_NO_LOGS_SELECTED', 'You must select at least one profile to create a bundle.', '2004-11-25 11:18:19', 'admin/error_logging_details.php'),\r
+('en', '_msgs', 'AT_ERROR_NO_LOG_SELECTED', 'You did not select a log file.', '2004-11-23 15:59:57', 'admin/error_logging_details.php'),\r
+('en', '_msgs', 'AT_ERROR_NO_MEMBERS', 'No users found.', '2005-05-18 12:43:40', ''),\r
+('en', '_msgs', 'AT_ERROR_NO_PROFILE_SELECTED', 'You did not select a profile.', '2004-11-23 16:01:27', 'admin/error_logging_details.php'),\r
+('en', '_msgs', 'AT_ERROR_NO_QUESTIONS', 'No questions were found for this test.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_NO_QUESTIONS_SELECTED', 'You did not select any questions to add to this test.', '2004-11-23 11:56:45', ''),\r
+('en', '_msgs', 'AT_ERROR_NO_SPACE_LEFT', 'There is no more space in this course to extract this archive.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_NO_STUDENT_SELECTED', 'You did not select any students.', '2006-06-27 12:18:13', 'enrollment manager, no students selected'),\r
+('en', '_msgs', 'AT_ERROR_NO_SUCH_USER', 'The user you selected does not exist.', '2005-03-17 15:34:30', 'veiwing profile but no such user'),\r
+('en', '_msgs', 'AT_ERROR_PACKAGE_DIR_FAILED', 'Problem with Package Directory.', '2005-05-17 12:02:28', ''),\r
+('en', '_msgs', 'AT_ERROR_PAGE_NOT_FOUND', 'Page cannot be found.', '2005-09-19 12:18:06', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_PASSWORD_CHARS', 'The password must contain letters, numbers, and symbols.', '2006-03-28 15:09:40', ''),\r
+('en', '_msgs', 'AT_ERROR_PASSWORD_LENGTH', 'Password must be at least 8 characters long.', '2006-04-10 11:43:46', ''),\r
+('en', '_msgs', 'AT_ERROR_PASSWORD_MISMATCH', 'Passwords did not match.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_POLL_QUESTION_MINIMUM', 'The poll must have at least two questions.', '2005-07-20 10:12:40', ''),\r
+('en', '_msgs', 'AT_ERROR_RAND_TEST_Q_WEIGHT', 'The non-required questions must all have the same weight.', '2007-07-09 15:03:55', ''),\r
+('en', '_msgs', 'AT_ERROR_REGISTER_MASTER_USED', 'The student ID and PIN combination you provided is either being used or is incorrect.', '2005-04-04 13:01:33', ''),\r
+('en', '_msgs', 'AT_ERROR_RESTORE_TOO_BIG', 'The course is too small to restore this backup into.', '2004-10-15 16:42:23', ''),\r
+('en', '_msgs', 'AT_ERROR_RESULTS_NOT_RELEASED', 'You are not permitted to view these test results at this time.', '2004-12-15 10:13:06', ''),\r
+('en', '_msgs', 'AT_ERROR_SCO_DIR_NOT_EXIST', 'The SCORM RTE directory does not exist. Please create a directory called <em>sco</em> in your installations top directory (example: <code>server.com/ATutor/sco</code>).', '2005-05-10 10:58:58', ''),\r
+('en', '_msgs', 'AT_ERROR_SCO_DIR_NOT_WRITEABLE', 'The SCORM RTE directory is not writeable. Please execute the command <code>chmod a+rwx sco</code> while in ATutor\'s top directory.', '2005-05-10 11:00:08', ''),\r
+('en', '_msgs', 'AT_ERROR_SCO_DISABLED', 'The SCORM 1.2 RTE has not been enabled by the Administrator.', '2005-05-10 11:06:09', ''),\r
+('en', '_msgs', 'AT_ERROR_SEARCH_TERM_REQUIRED', 'You must specify at least one search term.', '2003-08-22 12:03:29', 'search form'),\r
+('en', '_msgs', 'AT_ERROR_SELECT_ONE_ITEM', 'Only <em>one</em> item must be selected.', '2007-02-21 14:07:53', ''),\r
+('en', '_msgs', 'AT_ERROR_SENDING_ERROR', 'There was an error sending the email message.', '2005-01-18 13:34:23', 'mail failed to be sent'),\r
+('en', '_msgs', 'AT_ERROR_SEND_ENROL', 'You can only send a message to other members after you enroll in a course.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_SEND_MEMBERS', 'You can only send a message to others who are enrolled in the same courses as you. Your intended recipient may be viewing the course, but not enrolled.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_SESSION_COOKIES', 'Session cookies must be enabled in your browser to login.', '2005-07-22 13:04:11', ''),\r
+('en', '_msgs', 'AT_ERROR_START_DATE_INVALID', 'That start date is not valid.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_STUD_INFO_NOT_FOUND', 'Student information cannot be found.', '2003-05-16 13:42:17', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_TERM_EXISTS', 'The term <strong>%s</strong> already exists.', '2004-07-22 16:55:03', ''),\r
+('en', '_msgs', 'AT_ERROR_THEME_NOT_DELETED', 'The theme could not be deleted because it is either the current default theme or the original default theme.', '2005-05-10 09:27:02', 'theme manager deleting theme'),\r
+('en', '_msgs', 'AT_ERROR_THEME_NOT_DISABLED', 'Theme cannot be disabled because it is currently the default theme.', '2005-05-09 14:27:23', ''),\r
+('en', '_msgs', 'AT_ERROR_TILE_UNAVAILABLE', 'The TILE repository is unavailable.', '2005-02-21 14:40:03', ''),\r
+('en', '_msgs', 'AT_ERROR_TRANSCRIPT_ACTIVE', 'You may not delete an active transcript.', '2005-05-16 12:46:32', ''),\r
+('en', '_msgs', 'AT_ERROR_UNKNOWN', 'An undetermined error has occurred.', '2003-05-16 14:24:59', 'error msg'),\r
+('en', '_msgs', 'AT_ERROR_USER_NOT_FOUND', 'User not found.', '2005-03-09 15:56:27', ''),\r
+('en', '_msgs', 'AT_ERROR_WRONG_PASSWORD', 'Incorrect password.', '2006-05-11 11:34:11', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_ACCOUNT_APPROVED', 'You have successfully upgraded to an instructor account.', '2004-11-05 10:25:41', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_ACCOUNT_CONFIRMED', 'Account has been confirmed.', '2005-03-30 11:56:59', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_ACTION_COMPLETED_SUCCESSFULLY', 'Action completed successfully.', '2006-09-28 11:26:07', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_ADMIN_CREATED', 'Administrator account created successfully.', '2005-03-03 16:12:49', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_ADMIN_DELETED', 'Administrator account deleted successfully.', '2005-03-03 10:49:25', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_ADMIN_LOG_RESET', 'Administrator Activity Log has been reset successfully.', '2005-03-03 10:43:36', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_ALREADY_ENROLLED', 'The following students are already enrolled: <ul> %s </ul>', '2005-06-23 12:50:58', 'enrollment manager, students added were alread enrolled'),\r
+('en', '_msgs', 'AT_FEEDBACK_ALREADY_REQUESTED', 'You have already made a request to enroll in this course and you have not yet been approved by the instructor. You will be notifed when your request has been approved.', '2005-03-17 12:55:24', 'private enroll, already requested approval once'),\r
+('en', '_msgs', 'AT_FEEDBACK_APPROVAL_PENDING', 'Your request has been made. You will be notifed when your request has been approved.', '2005-03-29 12:11:35', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_ARCHIVE_EXTRACTED', 'Archive has been extracted successfully.', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_ASSIGNMENT_ADDED', 'Assignment was successfully added.', '2006-04-20 14:42:13', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_ASSIGNMENT_HANDED_IN', 'Assignment files submitted successfully.', '2006-03-20 14:35:53', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_ATUTOR_UPDATE_AVAILABLE', 'An updated version of ATutor is available! View the <a href=\"http://atutor.ca/atutor/change_log.php\">Change Log</a> for details.', '2005-11-21 12:36:30', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_AUTO_DISABLED', 'Auto-Login has been disabled', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_AUTO_ENABLED', 'Auto-Login has been enabled. Next time you enter ATutor using this computer, you will bypass the login screen. ', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_CANCELLED', 'Successfully cancelled without any changes.', '2003-12-10 10:40:21', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_CLOSED', 'Successfully closed', '2004-05-03 11:26:52', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_CONFIG_SAVED', 'System preferences have been saved successfully. A backup of the old configuration file was created and saved as %s (it\'s in your content directory).', '2005-03-29 15:22:14', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_CONFIRMATION_SENT', 'An email confirmation message has been sent.', '2005-03-22 12:07:10', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_CONFIRM_EMAIL', 'An email message has been sent to the new email address you specified. You must follow the instructions in that email for the changes to take effect.', '2006-05-11 15:55:32', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_CONFIRM_EMAIL2', 'An email with instructions on retrieving your password has been sent.', '2006-05-10 10:23:41', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_CONFIRM_GOOD', 'Your email address has been confirmed successfully.', '2005-04-11 10:29:29', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_CONTENT_DELETED', 'Content was successfully deleted', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_CONTENT_DIR_CREATED', 'Content directory created successfully.', '2003-10-15 12:20:11', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_COURSE_DEFAULT_FSIZE', 'The \'Max File Size\' was set to \'Default\' as the entered file size was either empty or negative.', '2003-10-14 16:13:40', 'course properites: file size was set to default'),\r
+('en', '_msgs', 'AT_FEEDBACK_COURSE_PREFS_SAVED', 'Course preferences were saved', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_COURSE_PROPERTIES', 'Course properties were successfully updated.', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_COURSE_REMOVED', 'Course was removed successfully.', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_DIRS_MOVED', 'Directories successfully moved.', '2004-11-10 14:12:11', 'file manager'),\r
+('en', '_msgs', 'AT_FEEDBACK_DIR_DELETED', 'Folder was successfully deleted.', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_ENROLLED', 'The following unique accounts were successfully added to the course list: <ul> %s </ul>', '2005-06-23 12:51:35', 'enrollment manager, confirm enrollmnet'),\r
+('en', '_msgs', 'AT_FEEDBACK_ERROR_LOG_RESET', 'The error log was reset successfully.', '2005-03-10 15:53:27', 'error logging'),\r
+('en', '_msgs', 'AT_FEEDBACK_EXPORT_CANCELLED', 'Export cancelled successfully.', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_FILES_MOVED', 'Files moved successfully.', '2006-03-20 16:10:58', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_FILE_EDITED', 'File successfully edited.', '2006-08-29 11:07:02', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_FILE_EDITED_SUCCESSFULLY', 'File edited successfully.', '2006-03-20 15:05:28', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_FILE_EXISTS', 'The file <strong>%1$s</strong> already exists. The newly uploaded file was saved as <strong>%2$s</strong>. <a href=\"tools/filemanager/index.php?overwrite=%2$s%5$spathext=%3$s%5$spopup=%4$s\">Overwrite</a> the old existing file with the newer one.', '2005-01-06 14:38:40', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_FILE_OVERWRITE', 'File overwrite successful.', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_FILE_PASTED', 'The file was successfully pasted into the textarea below. <strong><em>Save to apply changes</em></strong>, or Cancel to return to the previously saved content.', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_FILE_SAVED', 'The file was successfully saved as <strong>%s</strong>', '2005-01-10 09:35:48', 'file manager'),\r
+('en', '_msgs', 'AT_FEEDBACK_FILE_UPLOADED', 'File was successfully uploaded.', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_FILE_UPLOADED_ZIP', 'File was successfully uploaded. You may now <a href=\"tools/filemanager/zip.php?pathext=%1$s%4$sfile=%2$s%4$spopup=%3$s\">extract</a> the file.', '2005-01-06 15:26:58', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_FOLDER_EDITED_SUCCESSFULLY', 'Folder edited successfully.', '2006-03-20 15:42:30', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_FORUM_POSTING', 'To post messages to the new forum, log into ATutor as regular users or instructor.', '2004-11-21 10:08:55', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_FORUM_SUBSCRIBED', 'You have successfully subscribed to the <strong>%s</strong> forum. Messages posted to this forum will be delivered to your registered email address. View your profile to modify your email address.', '2004-12-02 15:04:51', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_FORUM_UNSUBSCRIBED', 'You have successfully unsubscribed from the <strong>%s</strong> forum. Messages posted to this forum will no longer be delivered to your email address.', '2004-12-03 17:25:43', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_GOOGLE_KEY_SAVED', 'Google key saved successfully.', '2005-10-20 11:07:29', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_GROUP_DELETED', 'Group deleted.', '2004-11-25 15:48:40', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_GROUP_EDITED_SUCCESSFULLY', 'Group edited successfully.', '2006-03-23 11:09:18', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_GROUP_MEMBERS_SAVED', 'Group members saved successfully.', '2006-04-17 11:43:39', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_GROUP_TYPE_DELETED', 'Group was successsfully deleted.', '2006-05-23 15:33:56', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_GROUP_TYPE_EDITED_SUCCESSFULLY', 'Group type edited successfully.', '2006-03-23 11:18:02', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_GROUP_UPDATED', 'Group updated successfully.', '2004-11-25 15:49:09', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_IMPORT_CANCELLED', 'Import cancelled successfully.', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_IMPORT_LANG_SUCCESS', 'New language was successfully imported. You may view and modify the new language by choosing it from the selection menu below.', '2003-06-05 19:38:41', 'admin language manager'),\r
+('en', '_msgs', 'AT_FEEDBACK_LANG_ADDED', 'New language was successfully created. Use the language selector to choose the new language, then beginning adding translated terms. Translation tools are enabled in include/vitals.inc.php', '2004-11-20 20:14:55', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_LANG_DELETED', 'Language was successfully removed.', '2003-06-05 19:38:01', 'admin language manager'),\r
+('en', '_msgs', 'AT_FEEDBACK_LANG_UPDATED', 'Language successfully updated.', '2005-04-26 16:04:36', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_LINK_ADDED', 'Link added successfully.  Link will become visible if approved.', '2005-02-23 12:07:59', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_LOGIN_SUCCESS', 'You have logged in successfully. Welcome back!', '2005-02-15 17:07:45', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_LOGOUT', 'You have successfully been logged out.', '2003-10-29 10:00:12', 'after logging out'),\r
+('en', '_msgs', 'AT_FEEDBACK_MASTER_LIST_NO_CHANGES', 'No changes were done to the Master Student List.', '2005-06-16 12:32:19', 'When action to master list yields no changes'),\r
+('en', '_msgs', 'AT_FEEDBACK_MASTER_LIST_UPLOADED', 'Master Student List has been updated successfully.', '2005-04-04 16:12:52', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_MEMBERS_ALUMNI', 'Student has been assigned alumni status.', '2004-12-02 11:42:06', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_MEMBERS_ENROLLED', 'The selected students were successfully enrolled in the course.', '2004-12-02 11:42:37', 'enrollment manager, confirm enrollment'),\r
+('en', '_msgs', 'AT_FEEDBACK_MEMBERS_REMOVED', 'The selected users were successfully removed from the course', '2004-10-18 10:58:17', 'enrollment manager, confirm removal'),\r
+('en', '_msgs', 'AT_FEEDBACK_MEMBERS_UNENROLLED', 'The selected users were successfully un-enrolled from the course', '2004-10-18 10:59:09', 'enrollemnt manager, confrm unenrollment'),\r
+('en', '_msgs', 'AT_FEEDBACK_MOD_INSTALLED', 'Module successfully installed.', '2005-08-16 16:15:49', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_MOVED_FILES', 'Files successfully moved.', '2004-11-10 14:11:19', 'file manager'),\r
+('en', '_msgs', 'AT_FEEDBACK_NOT_ENROLLED', 'The following students were not enrolled: <ul> %s </ul>', '2005-06-23 12:50:31', 'When a student was not enrolled when imported/created.'),\r
+('en', '_msgs', 'AT_FEEDBACK_NOW_ENROLLED', 'You are now enrolled in the %s course. You may enter the course at any time. To un-enroll, select \"Un-Enroll\" next to the course listing in My Courses..', '2005-06-06 10:04:55', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_PACKAGES_IMPORT_SUCCESS', 'The packages<ol> %s </ol>were imported successfully.', '2005-05-17 12:03:34', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_PACKAGE_IMPORT_SUCCESS', 'The package &quot;%s&quot; was imported successfully.', '2005-05-17 12:03:10', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_PASSWORD_CHANGED', 'Password changed successfully. You may now login using the new password.', '2006-05-09 14:22:35', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_PASSWORD_SUCCESS', 'Your login and password have been successfully emailed.', '2005-01-18 14:29:55', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_POST_ADDED_SUCCESSFULLY', 'Blog message was successfully posted.', '2006-05-22 12:35:15', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_PREFS_LOGIN', 'You cannot save these preferences because you are not logged in.', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_PRIVS_CHANGED', 'Privileges updated successfully.', '2005-08-24 11:21:49', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_PROFILE_CREATED_ADMIN', 'User account created successfully.', '2005-03-29 15:19:07', 'admin create user'),\r
+('en', '_msgs', 'AT_FEEDBACK_PROFILE_UPDATED', 'Your Profile was successfully updated.', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_PROFILE_UPDATED_ADMIN', 'The user profile was successfully updated', '2004-12-17 11:47:52', 'change user profile from admin area'),\r
+('en', '_msgs', 'AT_FEEDBACK_QUESTION_DELETED', 'Question was successfully deleted.', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_QUESTION_REMOVED', 'Question was successfully removed from test/survey.', '2004-11-24 10:03:12', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_QUESTION_UPDATED', 'Question was successfully updated.', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_REG_THANKS', 'Thank you for registering, please <a href=\"login.php\">login</a>.', '2003-09-25 14:39:50', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_REG_THANKS_CONFIRM', 'Thank-you for registering. Please follow the instructions in the email we sent you on how to confirm your account. You will need to confirm your account before you can login.', '2005-03-22 11:29:22', ''),\r
+('en', '_msgs', 'AT_FEEDBACK_RESULTS_UPDATED', 'Result was successfully updated.', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_RESULT_DELETED', 'Result was successfully deleted.', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_THEME_DEFAULT', 'The theme, <b>%s</b>, is now the default theme.', '2004-10-18 15:17:47', 'Theme Manager'),\r
+('en', '_msgs', 'AT_FEEDBACK_THEME_DISABLED', 'The theme, <b> %s</b>, has been disabled successfully <b>(users currently using the theme will still be able to use the theme until it is deleted)</b>', '2004-10-19 16:55:20', 'theme manager'),\r
+('en', '_msgs', 'AT_FEEDBACK_THREAD_LOCKED', 'Thread has been successfully <strong><em>locked</em></strong>.', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_THREAD_SUBSCRIBED', 'You have successfully subscribed to the <strong>%s</strong> thread. Messages posted to this thread will be forwarded to your registered email address. View your profile to modify your email address.', '2004-12-02 16:21:03', 'forum threads'),\r
+('en', '_msgs', 'AT_FEEDBACK_THREAD_UNLOCKED', 'Thread has been successfully <strong><em>unlocked</em></strong>.', '2003-05-16 13:47:01', 'feedback msg'),\r
+('en', '_msgs', 'AT_FEEDBACK_THREAD_UNSUBSCRIBED', 'You have successfully unsubscribed from the <strong>%s</strong> thread. Messages will no longer be sent to your email address.', '2004-12-02 16:34:13', 'forum threads'),\r
+('en', '_msgs', 'AT_INFOS_404_BLURB', 'The page you are trying to access <i>%s</i> does not exist, or has been moved. Try using the <a href=\"sitemap.php\">SiteMap</a> to find it.', '2005-03-03 14:48:24', '/404.php'),\r
+('en', '_msgs', 'AT_INFOS_ACCESS_PUBLIC', 'This feature is only available for protected or private courses.', '2007-02-13 15:55:47', ''),\r
+('en', '_msgs', 'AT_INFOS_ACCOUNT_APPROVED', 'You have successfully upgraded to an instructor account.', '2004-02-12 12:52:57', ''),\r
+('en', '_msgs', 'AT_INFOS_ALREADY_ENROLLED', 'You have already made a request to enroll in this course and you have not yet been approved by the instructor. You will be notifed when your request has been approved.', '2004-11-05 10:29:01', ''),\r
+('en', '_msgs', 'AT_INFOS_APPROVAL_PENDING', 'Your request has been made. You will be notifed when your request has been approved.<br /><br />Return to <a href=\"users/index.php\">My Courses</a>.', '2004-05-06 14:15:28', ''),\r
+('en', '_msgs', 'AT_INFOS_ASSIGNMENT_FS_SUBMISSIONS', 'Assignments are submitted using the group File Storage tool. Assign to all students, or create a group and enable File Storage for that group, to add an assignment drop-box.', '2006-06-29 14:50:22', ''),\r
+('en', '_msgs', 'AT_INFOS_COURSE_ENDED', 'This course has ended on %s.', '2007-07-16 11:56:16', ''),\r
+('en', '_msgs', 'AT_INFOS_COURSE_RELEASE', 'This course has not yet been released. It is scheduled to be released on %s.', '2006-04-11 12:36:49', ''),\r
+('en', '_msgs', 'AT_INFOS_DECISION_NOT_REVERSED', 'Decisions could not be reversed.', '2004-08-18 12:08:25', 'AChecker - can\'t reverse decision'),\r
+('en', '_msgs', 'AT_INFOS_DECISION_NOT_SAVED', 'Decisions could not be saved.', '2004-08-18 12:09:38', 'AChecker - can\'t save decision'),\r
+('en', '_msgs', 'AT_INFOS_DECISION_REVERSED', 'Decision reversed successfully.', '2004-08-18 12:07:27', 'AChecker - reverse decision'),\r
+('en', '_msgs', 'AT_INFOS_FEATURE_NOT_AVAILABLE', 'This feature is not available.', '2007-02-26 11:12:45', ''),\r
+('en', '_msgs', 'AT_INFOS_GLOSSARY_REMAINS', 'Note that removing a linked glossary term from your content will <strong>not</strong> delete the term from the glossary.', '2003-05-16 13:45:50', 'info msg'),\r
+('en', '_msgs', 'AT_INFOS_INBOX_SENT_MSGS_TTL', 'Sent messages are automatically deleted every %s days.', '2007-02-20 14:19:34', ''),\r
+('en', '_msgs', 'AT_INFOS_INVALID_URL', 'Localhost is not a valid URL', '2004-08-18 12:03:14', 'Used when AChecker reading URL'),\r
+('en', '_msgs', 'AT_INFOS_INVALID_USER', 'You must <a href=\"login.php?course=%s\">login</a> to use this section.', '2004-04-15 13:52:32', ''),\r
+('en', '_msgs', 'AT_INFOS_LOGIN_TO_POST', 'You must be logged in to post.', '2004-11-05 10:29:51', 'info msg'),\r
+('en', '_msgs', 'AT_INFOS_MASTER_LIST_DISABLED', 'The master list has been disabled.  To enable this functionality go to <a href=\"admin/config_edit.php\">System Preferences</a>.', '2005-05-10 15:16:13', ''),\r
+('en', '_msgs', 'AT_INFOS_MSG_SEND_LOGIN', 'You must be logged in to send messages.', '2003-05-16 13:42:17', 'info msg'),\r
+('en', '_msgs', 'AT_INFOS_NOT_ENROLLED', 'You need to be enrolled in this course to access this area.', '2004-05-12 11:35:43', ''),\r
+('en', '_msgs', 'AT_INFOS_NOT_RELEASED', 'This content has not yet been released. It is scheduled to be released on %s.', '2005-11-22 15:21:27', 'info msg'),\r
+('en', '_msgs', 'AT_INFOS_NO_CONTENT', 'This course has no content yet.', '2003-05-16 13:45:50', 'info msg'),\r
+('en', '_msgs', 'AT_INFOS_NO_COURSES', 'No courses found. <a href=\"./users/browse.php\">Browse</a> existing courses.', '2006-11-24 15:24:59', ''),\r
+('en', '_msgs', 'AT_INFOS_NO_COURSES_INST', 'No courses found. <a href=\"./users/browse.php\">Browse</a> existing courses or <a href=\"./users/create_course.php\">create</a> a new one.', '2006-11-24 15:26:19', ''),\r
+('en', '_msgs', 'AT_INFOS_NO_LINK_CATEGORIES', 'There are currently no link categories.  A link may not be suggested until link categories have been created.', '2005-03-16 16:47:22', ''),\r
+('en', '_msgs', 'AT_INFOS_NO_PACKAGES', 'No packages found.', '2005-05-17 12:03:52', ''),\r
+('en', '_msgs', 'AT_INFOS_NO_PAGE_CONTENT', 'There is no content on this page.', '2003-05-16 13:45:50', 'info msg'),\r
+('en', '_msgs', 'AT_INFOS_NO_PERMISSION', 'You do not have permission to access this page.', '2003-05-16 13:45:50', 'info msg'),\r
+('en', '_msgs', 'AT_INFOS_NO_POLLS', 'No polls are available right now.', '2005-03-22 10:52:43', 'no active polls'),\r
+('en', '_msgs', 'AT_INFOS_NO_POSTS_FOUND', 'There are no posts in this forum.', '2003-05-16 13:45:50', 'info msg'),\r
+('en', '_msgs', 'AT_INFOS_NO_SEARCH_RESULTS', 'No search results.', '2003-08-22 11:31:53', 'search page'),\r
+('en', '_msgs', 'AT_INFOS_NO_STUDENTS', 'There are no students enrolled in this course.', '2005-03-22 11:09:35', ''),\r
+('en', '_msgs', 'AT_INFOS_OVER_QUOTA', 'You have reached or passed your maximum quota for this course. You will have to delete some files before you will be able to upload again.', '2003-10-07 15:06:28', ''),\r
+('en', '_msgs', 'AT_INFOS_PRIVATE_ENROL', 'The course you are trying to access is <strong>private</strong>. Enrollment in this course requires instructor approval.<br />', '2003-10-24 15:31:11', 'info msg'),\r
+('en', '_msgs', 'AT_INFOS_SAVE_CONTENT', 'Content must be saved before it can be evaluated.', '2004-08-18 12:06:23', 'AChecker requirement in ATutor content'),\r
+('en', '_msgs', 'AT_INFOS_SERVICE_UNAVAILABLE', 'Service currently unavailable.', '2004-08-18 12:00:53', 'Used for AChecker'),\r
+('en', '_msgs', 'AT_INFOS_TRACKING_NO_INST', 'You have chosen your own ID number. Tracking information is not recorded for course instructors. Choose another user.', '2003-10-24 15:31:44', 'info msg'),\r
+('en', '_msgs', 'AT_INFOS_TRACKING_NO_INST1', 'Tracking information is not recorded for course instructors. See the <a href=\"tools/course_tracker.php\">Course Tracker</a> for a record of course activity.', '2003-10-24 15:31:52', 'info msg'),\r
+('en', '_msgs', 'AT_INFOS_TRACKING_OFFIN', 'Tracking is not enabled for this course. Contact your system administrator to have it turned on.', '2003-05-16 13:45:50', 'info msg'),\r
+('en', '_msgs', 'AT_INFOS_TRACKING_OFFST', 'Tracking is not enabled for this course.', '2003-05-16 13:45:50', 'info msg'),\r
+('en', '_msgs', 'AT_WARNING_CHAT_TRAN_EXISTS', 'A transcript with the name %s already exits. Either delete the original transcript, then resubmit, or rename your new transcript.', '2003-06-02 14:05:26', 'achat instructor transcript tool'),\r
+('en', '_msgs', 'AT_WARNING_DELETE_CATEGORY', 'Are you sure you want to delete this category with all its links?', '2003-05-16 13:46:16', 'warning msg'),\r
+('en', '_msgs', 'AT_WARNING_LANG_EXISTS', 'The language you are uploading is already installed on this system. Delete the existing language first by selecting the \"<strong>Remove</strong>\" link next to its listing below.', '2003-06-06 09:40:14', 'admin language manager'),\r
+('en', '_msgs', 'AT_WARNING_QUESTION_WEIGHT', 'One or more of the questions on this test do not have points associated with them.  Ensure that this is correct, or enter values for questions that do not have points.', '2007-03-05 15:52:54', ''),\r
+('en', '_msgs', 'AT_WARNING_SAVE_YOUR_WORK', 'Save your work before opening or closing the File Manager.', '2003-05-16 13:46:16', 'warning msg'),\r
+('en', '_msgs', 'AT_WARNING_THEME_VERSION_DIFF', 'The theme, <b>%s</b>, may not be compatible with this version of Atutor.', '2004-10-19 14:34:35', 'Theme Manager'),\r
+('en', '_msgs', 'AT_WARNING_TRANSLATE_ON', 'You are currently in Translation Mode. Any user can access the translation page at this time. To turn off the Translate mode please set AT_DEVEL_TRANSLATE in /include/vitals.inc.php to zero.', '2004-12-09 10:53:02', 'admin index and admin language manager'),\r
+('en', '_template', '15_max_chars', '8 characters minimum, 15 characters maximum', '2006-07-17 12:03:40', ''),\r
+('en', '_template', '20_max_chars', '20 character maximum', '2003-06-04 14:52:27', 'login name registration screen'),\r
+('en', '_template', '404', 'Error: Missing Page', '2004-03-10 11:24:10', ''),\r
+('en', '_template', 'a', 'A', '2007-01-10 13:47:54', ''),\r
+('en', '_template', 'about_atutor', 'About ATutor', '2004-01-14 10:25:40', ''),\r
+('en', '_template', 'about_atutor_help_text', 'Learn about various sources of ATutor help, and the help display options available.', '2004-05-19 10:40:00', ''),\r
+('en', '_template', 'about_private', 'Available only to users with an ATutor System Account, and Instructor approved enrollment. Login required. Enrollment is required.', '2004-01-22 14:54:29', ''),\r
+('en', '_template', 'about_protected', 'Available only to users with an ATutor System Account. Login required. Enrollment is optional.', '2004-02-05 09:43:13', ''),\r
+('en', '_template', 'about_public', 'Available to all users with or without an ATutor System Account. Login not required. Enrollment is optional.', '2004-02-05 09:42:59', ''),\r
+('en', '_template', 'accept_late_submissions', 'Accept Late Submissions', '2006-03-23 11:38:02', ''),\r
+('en', '_template', 'access', 'Access', '2007-01-27 13:45:44', 'create a new course'),\r
+('en', '_template', 'accessibility', 'Accessibility', '2003-05-21 13:56:28', 'help page'),\r
+('en', '_template', 'accessibility_features', 'Accessibility Features', '2003-05-21 14:28:03', 'help'),\r
+('en', '_template', 'accessibility_features_text', 'Using ATutor with assistive technology and other accessibility features.', '2003-05-21 14:00:59', 'help'),\r
+('en', '_template', 'access_credit', 'Accessibility report provided by <a title=\"ATRC Web Accessibility Checker (link opens in a new window)\" target=\"_new\" href=\"http://checker.atrc.utoronto.ca?lang=eng\">ATRC Web Accessibility Checker</a>.', '2004-08-18 11:28:42', 'include/html/editor_tabs/accessibility.inc.php'),\r
+('en', '_template', 'access_method', 'Access Method', '2003-05-18 09:07:28', 'tracker'),\r
+('en', '_template', 'access_stats', 'Access Method Statistics for', '2005-02-07 16:22:32', 'context (?)'),\r
+('en', '_template', 'account_authorization', 'Account Creation Authorization', '2005-05-27 13:33:38', 'registration page'),\r
+('en', '_template', 'account_information', 'Account Information', '2003-05-18 09:14:11', 'control centre/registration'),\r
+('en', '_template', 'account_status', 'Account Status', '2005-04-14 11:09:36', ''),\r
+('en', '_template', 'action', 'Action', '2004-10-14 14:10:28', ''),\r
+('en', '_template', 'active_admin', 'Active Administrator', '2005-03-03 11:00:47', ''),\r
+('en', '_template', 'ac_access_groups', 'Access Groups', '2004-03-09 14:22:58', ''),\r
+('en', '_template', 'add', 'Add', '2004-11-24 14:28:53', ''),\r
+('en', '_template', 'add_announcement', 'Add Announcement', '2003-05-18 09:17:38', 'course announcments/home page'),\r
+('en', '_template', 'add_assignment', 'Add Assignment', '2006-03-23 11:36:30', ''),\r
+('en', '_template', 'add_a_new_language', 'Add a new language.', '2004-10-28 13:05:59', ''),\r
+('en', '_template', 'add_code', 'Add Code', '2004-05-06 12:22:57', 'Title for code tags in code picker'),\r
+('en', '_template', 'add_content', 'Create Content', '2005-04-18 11:40:53', 'heading/submit button on Add Content screen'),\r
+('en', '_template', 'add_glossary', 'Add Glossary Term', '2005-03-07 11:42:42', 'glossary screen'),\r
+('en', '_template', 'add_language', 'Add Language', '2004-09-01 15:42:32', ''),\r
+('en', '_template', 'add_link', 'Add Link', '2005-02-22 10:13:06', ''),\r
+('en', '_template', 'add_more', 'Add More Students', '2004-10-15 14:10:59', 'create student list manually in enrollment manager'),\r
+('en', '_template', 'add_poll', 'Add Poll', '2004-06-14 14:41:26', ''),\r
+('en', '_template', 'add_question', 'Add Question', '2005-10-19 12:44:11', ''),\r
+('en', '_template', 'add_questions', 'Add Questions', '2003-05-18 10:27:45', 'test manager add questions screen'),\r
+('en', '_template', 'add_sibling_page', 'Add Sibling Page', '2005-07-21 10:18:21', ''),\r
+('en', '_template', 'add_sub_page', 'Add Sub Page', '2005-03-31 14:17:33', 'content page shortcuts'),\r
+('en', '_template', 'add_term', 'Add Term', '2003-05-18 10:28:38', 'glossary'),\r
+('en', '_template', 'add_topic', 'Add Topic', '2005-10-19 12:43:01', ''),\r
+('en', '_template', 'add_top_page', 'Add Top Page', '2005-07-21 10:18:06', ''),\r
+('en', '_template', 'add_to_test_survey', 'Add to Test/Survey', '2004-11-22 16:38:53', ''),\r
+('en', '_template', 'administration', 'Administration', '2003-06-04 10:51:48', 'admin home page'),\r
+('en', '_template', 'administrators', 'Administrators', '2005-03-03 10:40:40', ''),\r
+('en', '_template', 'admin_bundle_instructions', 'Please select the profile(s) you wish to bundle and send via e-mail. All error logs coupled with these profiles will also be included.', '2005-03-10 15:29:13', 'admin error reporting'),\r
+('en', '_template', 'admin_email', 'Email Users', '2005-01-06 14:57:16', ''),\r
+('en', '_template', 'admin_log', 'Administrator Activity Log', '2005-03-03 10:40:27', ''),\r
+('en', '_template', 'admin_new_account', 'A user account has been created for you at %1s. To access this account, please log into the site. It is strongly suggested you change your password upon logging in.', '2005-06-21 16:38:21', 'Admin creates a new user account.'),\r
+('en', '_template', 'admin_new_account_confirm', 'An account has been created for you at %1s. To access your account, you must first confirm your email by using the following link: %2s. It is strongly suggested you change your password upon logging in.', '2005-06-21 16:37:44', 'Admin creates a new user and confirm is ON'),\r
+('en', '_template', 'affected_entries', 'Affected Entries', '2005-03-03 12:14:33', ''),\r
+('en', '_template', 'after_topic', 'After: %s', '2004-01-16 13:19:46', 'content editor'),\r
+('en', '_template', 'age', 'Age', '2003-05-18 10:38:32', 'registration, profile'),\r
+('en', '_template', 'all', 'All', '2003-05-18 11:35:37', 'glossary'),\r
+('en', '_template', 'allow_editing', 'Allow Editing', '2007-02-20 10:30:01', ''),\r
+('en', '_template', 'allow_guests', 'Allow Guests', '2007-03-06 14:44:45', ''),\r
+('en', '_template', 'allow_instructor_requests', 'Allow Instructor Requests', '2005-03-03 10:51:13', ''),\r
+('en', '_template', 'all_available_courses', 'All available courses', '2004-08-18 12:03:26', ''),\r
+('en', '_template', 'all_courses', 'All Courses', '2005-04-01 14:08:29', 'forums'),\r
+('en', '_template', 'all_forums', 'Share with all courses, or', '2006-06-01 14:31:37', 'admin create shared forum'),\r
+('en', '_template', 'all_label', 'All (%s)', '2005-05-12 10:26:10', ''),\r
+('en', '_template', 'all_questions_on_page', 'All questions on one page', '2007-08-20 15:46:22', 'create/edit test'),\r
+('en', '_template', 'all_students', 'All Students', '2006-03-23 13:39:11', ''),\r
+('en', '_template', 'all_users', 'All Users', '2005-03-10 15:24:33', ''),\r
+('en', '_template', 'alternate_text', 'Alternate Text', '2004-12-08 12:39:27', 'filemanager, image inset alt field'),\r
+('en', '_template', 'alumni', 'Alumni', '2004-10-22 15:56:39', ''),\r
+('en', '_template', 'always', 'Always', '2006-03-23 11:38:33', ''),\r
+('en', '_template', 'announcements', 'Announcements', '2003-05-18 11:36:24', 'course home page'),\r
+('en', '_template', 'announcement_date_format', '%%l %%F %%j, %%Y - %%H:%%i', '2006-04-11 14:10:57', 'course home page'),\r
+('en', '_template', 'anonymous', 'Anonymous', '2004-08-26 13:24:12', ''),\r
+('en', '_template', 'anonymous_test', 'Anonymous', '2004-08-26 12:31:05', ''),\r
+('en', '_template', 'answer', 'Answer', '2003-05-18 11:38:10', 'test question add/edit screens'),\r
+('en', '_template', 'answers', 'Answers', '2007-01-10 13:47:41', ''),\r
+('en', '_template', 'answer_size', 'Answer Size', '2003-05-18 11:38:55', 'add/edit open ended question'),\r
+('en', '_template', 'append_content', 'Append selected material', '2004-10-15 14:18:20', ''),\r
+('en', '_template', 'applies_to_all_sub_pages', 'Applies to all sub pages.', '2007-03-01 10:23:22', 'edit/create content page. release date.'),\r
+('en', '_template', 'apply', 'Apply', '2005-02-10 11:25:17', ''),\r
+('en', '_template', 'apply_theme_subcategories', 'Apply theme to subcategories.', '2004-08-04 11:35:11', ''),\r
+('en', '_template', 'apply_to_all_results', 'Apply to all results', '2007-02-21 11:49:40', ''),\r
+('en', '_template', 'approve', 'Approve', '2003-05-18 11:41:29', 'enrol administration'),\r
+('en', '_template', 'approved', 'Approved', '2005-02-23 12:17:50', ''),\r
+('en', '_template', 'archive_total', 'Archive Total', '2003-05-18 11:42:55', 'file manager zip tool'),\r
+('en', '_template', 'assigned_to', 'Assigned To', '2005-06-02 12:18:18', ''),\r
+('en', '_template', 'assignment', 'Assignment', '2006-03-20 14:38:37', ''),\r
+('en', '_template', 'assignments', 'Assignments', '2006-03-20 14:40:50', ''),\r
+('en', '_template', 'assign_to', 'Assign To', '2006-03-23 11:37:44', ''),\r
+('en', '_template', 'assign_unassigned', 'Assign Unassigned', '2006-03-23 11:07:42', ''),\r
+('en', '_template', 'assistant', 'Assistant', '2006-05-23 15:24:15', ''),\r
+('en', '_template', 'assistants', 'Assistants', '2004-10-15 11:45:31', 'Assistants tab in enrollment manager'),\r
+('en', '_template', 'as_individual_content', 'As individual content pages', '2004-08-18 12:04:21', ''),\r
+('en', '_template', 'at', 'at', '2003-05-18 11:44:08', 'release date tool/links database'),\r
+('en', '_template', 'attempts', 'Attempts', '2004-08-30 11:31:40', ''),\r
+('en', '_template', 'atutor_accessibility_text', '<p>ATutor includes a variety of features designed to ensure that content is accessible to all potential users, including those with slow Internet connections, older Web browsers, and people with disabilities using assistive technologies to access the Web. These features are described in detail below. Depending on the theme being used, ATutor may include all or some of the features listed here. The default theme includes them all.</p>\r\n\r\n<ol>\r\n<li><strong>ByPass Links:</strong> In the top left corner of ATutor is a  hidden bypass link that allows assistive technology users to skip over the navigation elements and jump directly to an anchor at the top of the content being displayed. Press the Tab key once after a page has finished loading to advance to the first bypass link then press Enter to reposition the content to the top of your screen. The content anchor can also be accessed with an accesskey [Alt-c], so it is possible to jump to the top of the content area no matter where the cursor might be located on the screen.<br /><br />\r\n\r\nOther bypass links include: \"jump past table\" so users can skip over various data table to quickly access content that may appear after the table; \"jump past codes\", so users can skip over the emoticon codes near the bottom of message posting form in the Forums.<br /><br /></li>\r\n\r\n<li><strong>Accesskeys:</strong> Keyboard accessibility has been added to many ATutor features. To activate accesskeys, press Alt plus the assigned number, letter, or character. Accesskeys are assigned dynamically to the tabs in the Main Navigation. The first tab will be assigned [Alt-1], the second tab will be assigned [Alt-2], and so on.  Note that not all browsers support accesskeys.<br /><br />\r\n\r\nGeneral AccessKeys\r\n<ul>\r\n<li>[Alt-1 to Alt-0] Main Navigation Tabs</li>\r\n<li>[Alt-,] Previous topic (i.e. Left angle bracket <)</li>\r\n<li>[Alt-.] Next topic (i.e. Right angle bracket > )</li>\r\n<li>[Alt-.] Resume (i.e. Right angle bracket > while outside the course content)</li>\r\n<li>[Alt-j] Jump Menu</li>\r\n<li>[Alt-s] Submit (active on many form pages)</li>\r\n<li>[Alt-c] Jump to content top (top and navigation bypass link)</li>\r\n</ul>\r\n\r\nContent Editor AccessKeys\r\n<ul>\r\n<li>[Alt-n] Content Tab</li>\r\n<li>[Alt-p] Properties Tab</li>\r\n<li>[Alt-g] Glossary Tab</li>\r\n<li>[Alt-r] Preview Tab</li>\r\n<li>[Alt-a] Accessibility Tab</li>\r\n<li>[Alt-s] Save</li>\r\n</ul>\r\n\r\nChat AccessKeys\r\n<ul>\r\n<li>[Alt-c] Jump to Compose Message field</li>\r\n<li>[Alt-r] Refresh Messages</li>\r\n<li>[Alt-m] Jump to Message List</li>\r\n<li>[Alt-q] Quit Chat</li>\r\n</ul>\r\n\r\nInbox AccessKeys\r\n<ul>\r\n<li>[Alt-r] Reply to Messages</li>\r\n</ul>\r\n<br />\r\n\r\nVisual Editor AccessKeys\r\n<ul>\r\n<li>[Alt-q] jump to button bar</li>\r\n<li>[Alt-z] jump to content area of editor</li>\r\n<li>[Alt-x] jump to element path (bottm)</li>\r\n</ul>\r\n</li>\r\n\r\n<li><strong>Accessibility Verifier: </strong>While using the ATutor Content Editor, instructors can check the accessibility of their content to be sure it can accessed by all students, including those using assistive technologies, or older technologies. While using the Content Editor, select [Alt-a] to open the accessibility verifier.</li>\r\n\r\n<li><strong>Alternative Text: </strong>All meaningful images in ATutor include a text alternative that describes the image or its function. Where images are not meaningful the Alt attribute is left empty so assistive technologies  will ignore the image.</li>\r\n\r\n<li><strong>Alternative Navigation: </strong>Global, hierarchical, and sequential navigation tools are available so users can view or structure content in a manner that suits their style of learning.  The ATutor SiteMap provides a full list of all content and tools available, so all features in a course can be accessed from a single location.</li>\r\n\r\n<li><strong>Resume/Continue: </strong>ATutor remembers the last page accessed when users leave the course content, to go to the Forums for instance, so they can quickly find their way back to where they left off. The content location is also remembered between sessions, so when returning to ATutor, users can simply choose the Resume link in the course listing on My Courses, or select the the resume link in the breadcrumbs at the top of the screen once in a course. Using the [Alt-.] accesskey will also return a user to the last content page they were viewing after they have entered into a course.</li>\r\n\r\n<li><strong>Hide Menus:</strong> For users of older assistive technologies that do not support columnar text laid out in tables, it is possible to hide ATutor\'s content navigation menu so that content will be displayed in a linear presentation. Hiding the content menu also conserves space for users viewing ATutor on smaller screens.</li>\r\n\r\n<li><strong>Search and Sort:</strong> Most data tables are accompanied by a search tool, or filter, so specific records can be displayed in the table, reducing the amount of data displayed at any given time. Most data tables can also be sorted by selecting the column header label, again allowing users to narrow down the data display.</li>\r\n\r\n<li><strong>Table  Header Associations: </strong>All data tables are marked up with the TH element and the scope attribute to ensure that screen reader users are able to navigate through data displays and understand what each data cell represents.</li>\r\n\r\n<li><strong>Form Labels: </strong>All form fields throughout ATutor are marked up using the LABEL element to ensure that they are properly described for assistive technology users. Explicit labeling in this manner also makes it possible to click on a form field\'s label to activate the field. This provides a larger target area for those people who have difficulty positioning a mouse pointer on a small form field such as a radio button or a checkbox.</li>\r\n\r\n<li><strong>Style Sheets: </strong>Wherever possible, the presentation of content in ATutor is controlled by style sheet elements. This allows users to override ATutor\'s default appearance and apply their own preferred presentation styles (i.e. increased font sizes, different font styles, colours, etc.)</li>\r\n\r\n<li><strong>Form Field Focus: </strong>For pages where the primary content is a form, the cursor will automatically be placed in the first field so that after a form page loads, users can begin typing into the form.  Users may choose to disable form focus in their preference settings if it interferes with their use of form screens.</li>\r\n\r\n<li><strong>Relative Sizing of Images: </strong>With browsers that support resizing of images, ATutor icons can be magnified for users with low vision, making them more easily visible. (e.g. Netscape 7 press Alt +) . Wherever possible relative measures have also been used for other feature within ATutor so when the interface is magnified or reduced, all features resize relative to each other, maintaining the screen\'s symmetry.</li>\r\n\r\n</ol>', '2005-12-06 14:38:20', ''),\r
+('en', '_template', 'atutor_handbook', 'Official ATutor Handbook', '2005-07-12 10:42:58', ''),\r
+('en', '_template', 'atutor_home', 'ATutor home', '2003-05-18 11:49:37', 'mail response link text'),\r
+('en', '_template', 'atutor_is', '<strong><em>ATutor</em></strong> is an Open Source Web-based <strong>Learning Content Management System (LCMS)</strong> designed with accessibility and adaptability in mind. Administrators can install or update ATutor in minutes. Educators can quickly assemble, package, and redistribute instructional content, and conduct their courses online. Students learn in an adaptive learning environment.', '2004-02-13 14:33:27', ''),\r
+('en', '_template', 'atutor_links', '<p>Learn more about <a href=\"http://atutor.ca/index.php\">ATutor</a> by browsing the following links:</p>\r\n\r\n<ul>\r\n<li><a href=\"http://atutor.ca/atutor/docs/index.php\">FAQs</a> - Frequently asked questions with answers</li>\r\n<li><a href=\"http://atutor.ca/forums/index.php\">Support Forums</a> - Post to the user forums</li>\r\n<li><a href=\"http://atutor.ca/services/index.php\">Support Services</a> - If you need our help, support is available</li>             \r\n<li><a href=\"http://atutor.ca/atutor/translate/index.php\">Translation</a> - Download language packs, become a translator</li>\r\n<li><a href=\"http://atutor.ca/services/licensing.php\">Licensing</a> - ATutor software is available for free under certain terms</li>\r\n<li><a href=\"http://atutor.ca/atutor/download.php\">Download ATutor</a> - All of the system software required to run ATutor can be downloaded here</li>\r\n</ul>', '2005-11-22 14:17:17', ''),\r
+('en', '_template', 'atutor_version', 'ATutor Version', '2005-03-10 11:21:25', ''),\r
+('en', '_template', 'atutor_version_text', '%s. <a href=\"http://atutor.ca/check_atutor_version.php?v=%s\">Check Latest Version</a>.', '2007-07-26 13:52:25', ''),\r
+('en', '_template', 'at_tools', 'ATutor Tools', '2003-05-18 11:51:40', 'tracker column heading'),\r
+('en', '_template', 'authenticated_access', 'Authenticated Access', '2007-02-13 15:37:33', ''),\r
+('en', '_template', 'author', 'Author', '2006-03-20 14:36:23', ''),\r
+('en', '_template', 'auth_access_text', 'Give this link to those you wish to have limited access to your protected or private course.', '2007-02-13 15:54:02', ''),\r
+('en', '_template', 'auto_approve_instructors', 'Auto Approve Instructor Requests', '2005-03-03 10:51:27', ''),\r
+('en', '_template', 'auto_check_new_version', 'Check for ATutor Updates Automatically', '2005-11-21 12:37:42', ''),\r
+('en', '_template', 'auto_install_languages', 'Automatically Install New Language Packs', '2006-07-26 12:08:03', ''),\r
+('en', '_template', 'auto_install_languages_cron', 'You must set-up the <a href=\"admin/cron_config.php\">cron</a> to use this feature.', '2006-07-26 12:08:37', ''),\r
+('en', '_template', 'auto_login1', 'Auto-Login', '2003-05-18 11:53:47', 'control centre'),\r
+('en', '_template', 'availability', 'Availability', '2007-03-06 14:24:05', ''),\r
+('en', '_template', 'available_immediately', 'Release immediately', '2006-04-10 14:37:47', ''),\r
+('en', '_template', 'available_on_my_courses', 'Link From The <em>My Courses</em> Page', '2005-05-02 12:12:35', ''),\r
+('en', '_template', 'average', 'Average', '2003-05-18 11:56:58', 'test results / tracker courses statistics'),\r
+('en', '_template', 'avg_duration', 'Avg. Duration', '2005-03-01 12:40:29', 'tracker column heading'),\r
+('en', '_template', 'b', 'B', '2007-01-10 13:47:58', ''),\r
+('en', '_template', 'back', 'Back', '2003-05-18 12:02:02', 'file manager back up to previous directory'),\r
+('en', '_template', 'backups', 'Backups', '2004-10-15 11:40:09', ''),\r
+('en', '_template', 'backup_manager', 'Backup Manager', '2004-10-14 13:59:50', ''),\r
+('en', '_template', 'back_to', 'Back To:', '2005-03-22 16:08:47', ''),\r
+('en', '_template', 'back_to_main', 'Back to Main', '2004-12-06 12:07:06', ''),\r
+('en', '_template', 'back_to_profile', 'Back to Profile', '2004-12-06 12:09:00', ''),\r
+('en', '_template', 'back_to_summary', 'Back to Summary', '2003-05-18 12:05:32', 'tracker'),\r
+('en', '_template', 'banner', 'Banner', '2006-03-28 14:32:22', ''),\r
+('en', '_template', 'before_topic', 'Before: %s', '2004-01-16 13:19:20', 'content editor'),\r
+('en', '_template', 'blogs', 'Blogs', '2006-05-22 12:10:42', ''),\r
+('en', '_template', 'blue', 'Blue', '2003-05-18 12:09:34', 'global code picker tool'),\r
+('en', '_template', 'blue_guests', 'Blue = Guests', '2003-05-18 12:10:38', 'instructor course statistics'),\r
+('en', '_template', 'body', 'Body', '2003-05-18 12:11:16', 'add/edit forms for body field label'),\r
+('en', '_template', 'bold', 'Bold', '2003-05-18 12:11:41', 'global code picker'),\r
+('en', '_template', 'bottom', 'Bottom', '2003-05-23 16:58:31', 'preference settings option'),\r
+('en', '_template', 'browse_courses', 'Browse Courses', '2003-05-18 12:13:27', 'control centre, about, login screens'),\r
+('en', '_template', 'bug_count', 'Bug Count', '2004-12-06 12:23:46', 'admin/error_logging.php'),\r
+('en', '_template', 'bug_identifier', 'Bug Identifier', '2004-12-06 12:05:07', ''),\r
+('en', '_template', 'bytes', 'Bytes', '2003-05-18 12:15:45', 'admin course size quote, course properties screen'),\r
+('en', '_template', 'c', 'C', '2007-01-10 13:48:02', ''),\r
+('en', '_template', 'cache_directory', 'Cache Directory', '2005-03-03 10:52:26', ''),\r
+('en', '_template', 'cancel', 'Cancel', '2003-05-18 12:16:07', 'global cancel button'),\r
+('en', '_template', 'cannot_find_remote_languages', 'ATutor was unable to connect to the ATutor.ca website to retrieve the list of available languages.', '2004-10-18 14:28:15', ''),\r
+('en', '_template', 'categories', 'Categories', '2005-02-22 10:12:23', ''),\r
+('en', '_template', 'category', 'Category', '2003-05-18 12:16:54', 'links database'),\r
+('en', '_template', 'cats_all', 'All Categories', '2005-02-23 10:22:07', ''),\r
+('en', '_template', 'cats_categories', 'Categories', '2003-09-24 18:21:26', 'admin course categories'),\r
+('en', '_template', 'cats_none', 'None', '2003-09-24 18:13:50', 'admin course categories'),\r
+('en', '_template', 'cats_no_categories', 'No Categories', '2003-09-24 18:28:32', 'admin course categories'),\r
+('en', '_template', 'cats_parent_category', 'Parent Category', '2003-09-24 18:04:38', 'admin course categories'),\r
+('en', '_template', 'cats_uncategorized', 'Uncategorized', '2003-09-24 18:17:50', 'admin course categories'),\r
+('en', '_template', 'cats_view_links', 'Show Links by Category', '2005-03-29 14:08:08', ''),\r
+('en', '_template', 'cat_theme', 'Category Theme', '2004-08-04 11:34:15', ''),\r
+('en', '_template', 'center', 'Center', '2003-05-18 12:20:08', 'global code picker option'),\r
+('en', '_template', 'change_email', 'Change Email', '2006-05-10 11:11:26', ''),\r
+('en', '_template', 'change_password', 'Change Password', '2006-05-10 11:11:41', ''),\r
+('en', '_template', 'charset', 'Character Set', '2004-11-20 19:36:01', 'admin new language'),\r
+('en', '_template', 'chat', 'Chat', '2003-05-18 12:20:29', 'global chat label'),\r
+('en', '_template', 'chat_altc', 'Alt + C: Jump to Compose Message', '2003-05-30 12:41:06', 'chat options frame'),\r
+('en', '_template', 'chat_altm', 'Alt + M: Jump to Messages', '2004-08-18 10:58:16', ''),\r
+('en', '_template', 'chat_altq', 'Alt + Q:  Quit Chat', '2005-05-30 15:04:01', ''),\r
+('en', '_template', 'chat_altr', 'Alt + R: Refresh Messages', '2004-08-18 10:58:42', ''),\r
+('en', '_template', 'chat_auto180_checking', 'Automatic (180 second interval)', '2003-05-15 14:23:13', 'chat message checking preference'),\r
+('en', '_template', 'chat_auto20_checking', 'Automatic (20 second interval)', '2003-05-15 14:22:22', 'chat message checking preference'),\r
+('en', '_template', 'chat_auto5_checking', 'Automatic (5 second interval)', '2003-05-27 09:09:57', 'chat message checking preferences'),\r
+('en', '_template', 'chat_auto60_checking', 'Automatic (60 second interval)', '2003-05-15 14:22:53', 'chat message checking preference'),\r
+('en', '_template', 'chat_chime_help', 'Set to \"Yes\" to recieve an audio tone when new messsages are posted. Does not work in all Web browsers.', '2003-05-15 19:33:11', 'chat message checking preferences'),\r
+('en', '_template', 'chat_compose_message', 'Compose Message', '2003-05-15 13:12:38', 'chat message compose frame'),\r
+('en', '_template', 'chat_currently_active', 'Currently active', '2003-05-15 12:40:47', 'chat hompage transcript activated'),\r
+('en', '_template', 'chat_current_tran', 'A transcript is already being recorded.  You may view the current transcript at', '2005-03-30 14:04:45', 'achat'),\r
+('en', '_template', 'chat_delete_transcript', 'Delete Transcript', '2003-06-30 17:53:55', 'chat home page'),\r
+('en', '_template', 'chat_edit_prefs', 'Edit Preferences', '2003-05-15 13:47:05', 'chat options frame'),\r
+('en', '_template', 'chat_enter', 'Enter Chat', '2003-05-15 14:50:48', 'chat preferences pages'),\r
+('en', '_template', 'chat_exit', 'Exit Chat', '2003-05-15 13:48:43', 'chat options frame'),\r
+('en', '_template', 'chat_full_history', 'Full History', '2003-05-15 14:00:02', 'chat options frame'),\r
+('en', '_template', 'chat_help_display_blurb', '<p>Note: <em>Jump To</em> links and the <em>Quick Key</em> list only appear if you have turned on <em>Navigation Aids</em> in you preferences.</p>\r\n \r\n<ul>\r\n    <li>The <em>Jump to Quick Keys</em> link at the top takes you to a list of quick keys for the Chat. </li>\r\n   <li>The <em>Message Area</em> displays the most recent messages (up to ten). </li>\r\n    <li>The <em>Jump to Messages</em> links take you to the beginning of the list of messages. (Alt+M) </li>\r\n    <li>The <em>Refresh Messages</em> link lets you check for new messages (Alt+R). </li>\r\n    <li>The <em>Compose Message</em> Field and <em>Send Button</em> let you enter and send messages (Alt+C to enter the Compose Field, Enter to send a completed message). </li>\r\n</ul>', '2004-08-18 11:00:36', ''),\r
+('en', '_template', 'chat_help_display_frame', 'Display Frame Help (top left)', '2003-05-15 15:24:02', 'chat help screen'),\r
+('en', '_template', 'chat_help_display_jump', 'Jump to Display Frame Help', '2003-05-27 09:14:57', 'chat help screen'),\r
+('en', '_template', 'chat_help_history_blurb', 'The <em>User List</em> shows the Chat IDs of all the users in the chat. Click on a Chat ID to see the messages sent by that participant, along with your own messages. Click on <em>All Users</em> to see the messages sent by all participants.', '2003-05-15 15:34:10', 'chat help screen'),\r
+('en', '_template', 'chat_help_history_frame', 'User List and History Help', '2003-05-15 15:32:14', 'chat help screen'),\r
+('en', '_template', 'chat_help_history_jump', 'Jump to User List and History Help', '2003-05-15 15:22:23', 'chat help screen'),\r
+('en', '_template', 'chat_help_jump_top', 'Jump to Top', '2003-05-15 15:25:48', 'chat_help screen'),\r
+('en', '_template', 'chat_help_options_blurb', '<ul>\r\n       <li>The <em>Edit Preferences</em> link opens the preferences so you can modify your control and display settings. </li>\r\n    <li>The <em>Exit Chat</em> link ends your chat session.</li>\r\n    <li>The <em>Help</em> link brings you to this screen. (Alt+Q)</li>\r\n</ul>', '2004-08-18 11:01:04', ''),\r
+('en', '_template', 'chat_help_options_frame', 'Options Help (top right)', '2003-05-15 15:24:50', 'chat help screen'),\r
+('en', '_template', 'chat_help_options_jump', 'Jump to Options Help', '2003-05-27 09:15:04', 'chat help screen'),\r
+('en', '_template', 'chat_help_screen', 'Help Screen', '2003-05-15 15:19:33', 'chat help'),\r
+('en', '_template', 'chat_history_messages', 'History - Messages %s to %s of %s', '2003-05-15 15:59:13', 'chat full history screen'),\r
+('en', '_template', 'chat_inactive', 'Inactive', '2005-03-30 14:47:25', ''),\r
+('en', '_template', 'chat_jump_to_message', 'Jump to Message Area', '2003-05-15 13:14:01', 'chat display frame'),\r
+('en', '_template', 'chat_keep_tran', 'This section allows you to keep a transcript of the chat in progress.', '2003-05-28 11:10:47', 'achat'),\r
+('en', '_template', 'chat_layout_prefs', 'Preferences: Layout Settings', '2003-05-15 14:53:04', 'chat layout preferences'),\r
+('en', '_template', 'chat_list_and_history', 'User List and History', '2003-05-15 13:49:37', 'chat options frame'),\r
+('en', '_template', 'chat_logged_out', 'User %s has logged out.', '2003-05-15 16:01:51', 'logout'),\r
+('en', '_template', 'chat_manual_checking', 'Manual Refresh', '2003-05-15 14:23:42', 'chat message checking preference'),\r
+('en', '_template', 'chat_messages', 'Messages', '2003-05-15 13:05:28', 'chat message display frame'),\r
+('en', '_template', 'chat_message_checking', 'Message Checking:', '2003-05-15 14:19:45', 'chat message checking preferences'),\r
+('en', '_template', 'chat_message_check_help', 'Select the interval rate at which new messages are retrieved from the server. Screen reader users set this option to Manual Refresh.', '2003-05-15 14:39:17', 'chat message checking preferences'),\r
+('en', '_template', 'chat_message_chime', 'New Message Chime:', '2003-05-15 14:43:05', 'chat message checking preferences'),\r
+('en', '_template', 'chat_message_new_help', 'Screen reader users choose \"Yes\", along with the Manual Refresh setting.', '2003-05-15 15:05:32', 'chat layout preferences'),\r
+('en', '_template', 'chat_message_order_help', 'Select New to Old to display new messages at the top of the screen, and Old to New to display new messages at the bottom of the screen.', '2003-05-15 14:58:48', 'chat layout preferences'),\r
+('en', '_template', 'chat_newmsg_prefs', 'Show Only New Messages?', '2003-05-15 15:00:44', 'chat layout preferences'),\r
+('en', '_template', 'chat_newold_prefs', 'New to Old', '2003-05-15 14:55:15', 'chat layout preferences'),\r
+('en', '_template', 'chat_none_found', 'No transcripts found.', '2005-03-31 11:32:44', 'chat home page'),\r
+('en', '_template', 'chat_no_new_messages', 'No new messages.', '2003-05-15 13:09:01', 'chat display frames'),\r
+('en', '_template', 'chat_oldnew_prefs', 'Old to New', '2003-05-15 14:54:48', 'chat layout preferences'),\r
+('en', '_template', 'chat_options', 'Options', '2003-05-15 13:45:35', 'chat options frame'),\r
+('en', '_template', 'chat_order_prefs', 'Order of Messages:', '2003-05-15 14:53:59', 'chat layout preferences'),\r
+('en', '_template', 'chat_post', 'Enter: Post a completed message', '2003-05-15 14:07:17', 'chat options frame'),\r
+('en', '_template', 'chat_prefs_checking', 'Preferences: Message Checking Settings', '2003-05-15 14:18:37', 'chat checking preferences'),\r
+('en', '_template', 'chat_quick_keys', 'Quick Keys', '2003-05-15 14:03:24', 'chat options frame'),\r
+('en', '_template', 'chat_refresh_message', 'Refresh Messages', '2003-05-15 13:16:05', 'chat display frame'),\r
+('en', '_template', 'chat_refresh_user_list', 'Refresh User List', '2003-05-15 14:01:12', 'chat options frame'),\r
+('en', '_template', 'chat_return', 'Return to Chat', '2003-05-15 15:20:17', 'chat help screen'),\r
+('en', '_template', 'chat_start_tran', 'Start keeping a transcript', '2003-05-28 11:20:12', 'achat'),\r
+('en', '_template', 'chat_start_transcript', 'Start/Stop Transcript', '2005-05-16 10:55:23', ''),\r
+('en', '_template', 'chat_stop_tran', 'Stop keeping transcript.', '2003-05-28 12:48:38', 'achat'),\r
+('en', '_template', 'chat_system', 'system', '2003-05-15 13:07:42', 'chat display frame system message'),\r
+('en', '_template', 'chat_transcript', 'Transcript', '2003-05-30 11:27:26', 'achat'),\r
+('en', '_template', 'chat_transcript_end', 'Transcript End:', '2003-05-30 11:30:10', 'achat'),\r
+('en', '_template', 'chat_transcript_start', 'Transcript Start:', '2003-05-30 11:29:26', 'achat'),\r
+('en', '_template', 'chat_tran_file_name', 'Transcript name (alphanumeric, no spaces):', '2003-05-28 18:36:35', 'achat'),\r
+('en', '_template', 'chat_user_logged_in', 'User %s has logged in.', '2003-05-15 16:02:29', 'chat display system login message'),\r
+('en', '_template', 'chat_user_logged_out', 'User %s has been logged out due to inactivity.', '2003-05-15 16:02:16', 'chat logout system message'),\r
+('en', '_template', 'chat_you', 'you', '2003-05-15 13:53:10', 'chat users online list'),\r
+('en', '_template', 'checked', 'Checked', '2006-06-26 14:55:53', ''),\r
+('en', '_template', 'child_of', 'Child of: %s', '2004-01-16 13:21:25', ''),\r
+('en', '_template', 'choice', 'Choice', '2003-05-18 12:25:24', 'test manager, multiple choice question editor'),\r
+('en', '_template', 'cid', 'CID', '2003-05-18 13:17:08', 'global code picker url content id indentifier'),\r
+('en', '_template', 'city', 'City', '2003-05-18 13:17:52', 'registration, edit profile'),\r
+('en', '_template', 'click_code', 'Click on the code or emoticon you want to use.', '2003-05-22 15:42:52', 'global code picker instructions'),\r
+('en', '_template', 'close', 'Close', '2005-08-10 16:13:36', ''),\r
+('en', '_template', 'close_after_saving', 'Close after saving', '2004-05-11 11:01:40', ''),\r
+('en', '_template', 'close_file_manager', 'Close File Manager', '2004-11-25 17:34:52', ''),\r
+('en', '_template', 'close_help_window', 'Close Help Window', '2003-05-18 13:21:37', 'close help window link text'),\r
+('en', '_template', 'close_menus', 'Menus', '2005-03-05 18:29:54', 'Menus'),\r
+('en', '_template', 'close_related_topics', 'Related Topics', '2005-03-05 18:30:15', 'Menus'),\r
+('en', '_template', 'close_window', 'Close Window', '2004-12-08 12:04:59', ''),\r
+('en', '_template', 'codes', 'Codes', '2003-05-18 13:23:57', 'global code picker label'),\r
+('en', '_template', 'collapse', 'Collapse', '2003-05-18 13:24:36', 'Menus'),\r
+('en', '_template', 'colors', 'Colours', '2003-05-18 13:25:02', 'global code picker label'),\r
+('en', '_template', 'combination', 'Use a combination of letters, numbers and symbols', '2004-06-21 16:26:17', ''),\r
+('en', '_template', 'comment', 'Comment', '2006-03-20 14:42:32', ''),\r
+('en', '_template', 'comments', 'Comments', '2006-03-20 14:36:45', ''),\r
+('en', '_template', 'comments_num', '%s Comment(s)', '2006-05-25 14:01:48', ''),\r
+('en', '_template', 'completed_tests', 'Your Submissions', '2005-05-11 11:19:25', ''),\r
+('en', '_template', 'configuration', 'Configuration', '2005-02-07 16:04:01', ''),\r
+('en', '_template', 'confirm', 'Confirm', '2004-10-18 11:50:20', 'enrollment manager, confirm action'),\r
+('en', '_template', 'confirm_account_text', 'If you have already created an account, you will have to <a href=\"confirm.php\">confirm your email address</a>.', '2005-07-27 15:05:53', ''),\r
+('en', '_template', 'confirm_admin_create', 'Are you sure you want to create a Super Administrator account?', '2005-03-03 10:34:16', ''),\r
+('en', '_template', 'confirm_deny_instructor', 'You are about to deny the instructor request of the following user:', '2005-07-21 16:16:48', ''),\r
+('en', '_template', 'confirm_password', 'Confirm Password', '2005-03-03 10:47:28', ''),\r
+('en', '_template', 'contact_email', 'Contact Email', '2005-03-03 10:50:32', ''),\r
+('en', '_template', 'contact_instructor', 'Contact Course Instructor', '2003-05-18 13:29:00', 'student contact instructor form'),\r
+('en', '_template', 'contact_name', 'Contact Name', '2003-05-18 13:30:04', 'student contact instructor form'),\r
+('en', '_template', 'contact_support', 'Contact Support', '2005-07-19 10:27:52', ''),\r
+('en', '_template', 'contain_only', 'May contain only letters, numbers, underscores, hyphens or periods.', '2006-07-17 11:01:46', 'registration login name format'),\r
+('en', '_template', 'content', 'Content', '2003-05-18 13:32:22', 'sitemap/delete course'),\r
+('en', '_template', 'contents', 'Contents', '2003-05-18 13:35:43', 'content page table of content menu heading'),\r
+('en', '_template', 'content_editor', 'Content Editor', '2006-11-23 13:17:41', 'user prefs'),\r
+('en', '_template', 'content_navigation', 'Content Navigation', '2005-03-29 12:18:45', 'menu content nav drop down'),\r
+('en', '_template', 'content_packaging', 'Import/Export Content', '2005-04-18 11:39:46', ''),\r
+('en', '_template', 'content_packaging_all', 'Available on every page', '2003-10-15 10:10:17', 'option3'),\r
+('en', '_template', 'content_packaging_disabled', 'Content packaging has been disabled for this course.', '2003-10-15 11:52:51', ''),\r
+('en', '_template', 'content_packaging_none', 'Not available on any of the pages', '2003-10-15 10:09:27', 'option1'),\r
+('en', '_template', 'content_packaging_top', 'Available only for top level pages', '2003-10-15 10:09:50', 'option2'),\r
+('en', '_template', 'content_usage', 'Content Usage', '2005-03-03 15:09:45', ''),\r
+('en', '_template', 'continue', 'Continue', '2006-03-21 16:22:28', ''),\r
+('en', '_template', 'copyright', 'Web site engine\'s code is copyright © 2001-2008 <a href=\"http://www.atutor.ca\" target=\"_new\" title=\"ATutor.ca - opens in a new browser\">ATutor</a><sup>®</sup>', '2006-11-21 15:20:13', ''),\r
+('en', '_template', 'core', 'Core', '2005-08-30 10:17:41', ''),\r
+('en', '_template', 'correct_answer', 'Correct Answer', '2003-05-18 13:38:45', 'test manager add/edit questions'),\r
+('en', '_template', 'count', 'Count', '2003-05-18 13:40:35', 'tracker'),\r
+('en', '_template', 'country', 'Country', '2003-05-18 13:41:28', 'registration / profile edit'),\r
+('en', '_template', 'course', 'Course', '2003-05-18 13:42:31', 'delete course warning screen'),\r
+('en', '_template', 'courses', 'Courses', '2003-05-18 13:43:44', 'admin users/courses manager'),\r
+('en', '_template', 'courses_below', 'Courses Below', '2003-05-18 13:44:41', 'jump menu divider'),\r
+('en', '_template', 'course_available', 'Course Available', '2003-05-18 13:46:03', 'file manager, server space available'),\r
+('en', '_template', 'course_available_zip1', 'Course Available (before extraction)', '2003-05-18 13:46:37', 'file manager zip tool'),\r
+('en', '_template', 'course_available_zip2', 'Course Available (after extraction)', '2003-05-18 13:47:06', 'file manager zip tool'),\r
+('en', '_template', 'course_backups', 'Course Backups', '2005-03-03 10:21:39', ''),\r
+('en', '_template', 'course_copyright', 'Optional Copyright Notice', '2003-05-18 13:47:33', 'course copyright label'),\r
+('en', '_template', 'course_email', 'Course Email', '2003-05-18 13:51:48', 'taught courses table in instructor control centre'),\r
+('en', '_template', 'course_enrolment', 'Enrollment Manager', '2003-10-01 18:54:09', 'instructor - course enrollment (previously ATutor Course Enrollment)'),\r
+('en', '_template', 'course_files', 'Course Files', '2006-03-20 14:40:32', ''),\r
+('en', '_template', 'course_forums', 'Course Forums', '2004-11-13 19:55:06', ''),\r
+('en', '_template', 'course_id', 'Course ID', '2003-05-18 13:54:57', 'admin course manager'),\r
+('en', '_template', 'course_instructor', 'Course Instructor', '2003-05-18 13:57:00', 'student contact instructor form'),\r
+('en', '_template', 'course_list', 'Course List', '2005-03-23 15:17:14', 'enrollment manager'),\r
+('en', '_template', 'course_properties', 'Course Properties', '2003-05-18 14:00:23', 'course properties, admin course manager'),\r
+('en', '_template', 'course_quota', 'Course Quota', '2003-05-18 14:01:10', 'course properties, admin course manager'),\r
+('en', '_template', 'course_stats', 'Course Statistics', '2003-05-18 14:01:59', 'delete course'),\r
+('en', '_template', 'course_summaries', 'Course Summaries', '2004-08-20 15:08:40', ''),\r
+('en', '_template', 'course_total', 'Course Total', '2003-05-18 14:03:39', 'file manager, zip tool'),\r
+('en', '_template', 'course_total_zip', 'Course Total (before extraction)', '2003-05-18 14:04:10', 'file manager zip tool'),\r
+('en', '_template', 'create', 'Create', '2003-05-18 14:06:29', 'links database submit button'),\r
+('en', '_template', 'created', 'Created', '2003-05-18 14:07:28', 'browse courses, control centre'),\r
+('en', '_template', 'created_date', 'Created', '2003-05-18 14:09:05', 'admin course managers, profile editor'),\r
+('en', '_template', 'create_admin', 'Create Administrator Account', '2005-03-03 10:40:10', ''),\r
+('en', '_template', 'create_backup', 'Create Backup', '2004-10-15 14:19:55', ''),\r
+('en', '_template', 'create_backup_about', '<p>Creating a backup of this course will archive all available material into a single compressed ZIP file. Once the backup file is created, it will be available through the Backup Manager for download and safe-keeping, or available to be restored back into this or any other course.</p>\r\n\r\n<p>Depending on the course size and available server resources, the time needed to backup this course may take  some time.</p>\r\n           \r\n<p>Note: You are currently restricted to %s backups per course.</p>', '2005-05-30 15:04:45', ''),\r
+('en', '_template', 'create_basic', 'Create basic announcement, content, and forum.', '2004-10-20 14:28:44', ''),\r
+('en', '_template', 'create_category', 'Create Category', '2005-02-18 10:28:39', ''),\r
+('en', '_template', 'create_course', 'Create Course', '2005-02-15 13:16:16', 'instructor control centre'),\r
+('en', '_template', 'create_folder', 'Create Folder', '2003-05-18 14:12:40', 'file manager'),\r
+('en', '_template', 'create_forum', 'Create Forum', '2005-02-16 12:23:16', ''),\r
+('en', '_template', 'create_group', 'Create Group', '2005-02-22 16:51:56', ''),\r
+('en', '_template', 'create_groups', 'Create Groups', '2006-03-21 14:57:08', ''),\r
+('en', '_template', 'create_module', 'Create Module', '2005-08-17 13:06:07', ''),\r
+('en', '_template', 'create_new_file', 'Create New File', '2005-02-22 15:33:12', ''),\r
+('en', '_template', 'create_new_question', 'Create New Question', '2005-03-07 16:42:11', ''),\r
+('en', '_template', 'create_test', 'Create Test/Survey', '2004-11-24 10:00:42', 'instructor test manager'),\r
+('en', '_template', 'create_user', 'Create User Account', '2005-03-10 15:12:12', ''),\r
+('en', '_template', 'cron', 'Cron', '2006-03-31 15:42:46', ''),\r
+('en', '_template', 'cron_config', 'Cron Set-up', '2006-04-03 14:22:14', ''),\r
+('en', '_template', 'cron_url', 'The URL to your cron service is:', '2006-06-14 12:47:32', ''),\r
+('en', '_template', 'cron_url_usage', 'The URL below must be used when setting-up the cron service. See the <em>Cron Set-Up</em> section in the <em>ATutor Handbook</em> for instructions.', '2006-06-14 12:49:11', ''),\r
+('en', '_template', 'current_course_size', 'Current course size', '2003-10-07 15:41:36', 'admin course info'),\r
+('en', '_template', 'current_location', '(Current location)', '2004-01-16 13:22:03', 'content editor'),\r
+('en', '_template', 'current_path', 'Path to Current Directory:', '2003-05-18 14:13:52', 'file manager'),\r
+('en', '_template', 'curren_tests_surveys', 'Ongoing Tests & Surveys', '2005-01-03 09:57:07', ''),\r
+('en', '_template', 'd', 'D', '2007-01-10 13:48:05', ''),\r
+('en', '_template', 'database', 'Database', '2007-07-26 13:39:36', ''),\r
+('en', '_template', 'database_table', 'Database Table', '2005-03-03 12:14:20', ''),\r
+('en', '_template', 'date', 'Date', '2003-05-19 17:44:42', 'global date label'),\r
+('en', '_template', 'date_apr', 'Apr', '2003-05-20 12:32:27', 'date'),\r
+('en', '_template', 'date_april', 'April', '2003-05-20 12:28:03', 'date'),\r
+('en', '_template', 'date_aug', 'Aug', '2003-05-20 12:33:34', 'date'),\r
+('en', '_template', 'date_august', 'August', '2003-05-20 12:29:12', 'date'),\r
+('en', '_template', 'date_created', 'Date Created', '2003-05-19 17:45:18', 'view profile'),\r
+('en', '_template', 'date_dec', 'Dec', '2003-05-20 12:34:03', 'date'),\r
+('en', '_template', 'date_december', 'December', '2003-05-20 12:30:35', 'date'),\r
+('en', '_template', 'date_feb', 'Feb', '2003-05-20 12:32:12', 'date'),\r
+('en', '_template', 'date_february', 'February', '2003-05-20 12:27:33', 'date'),\r
+('en', '_template', 'date_fri', 'Fri', '2003-05-20 12:26:47', 'date'),\r
+('en', '_template', 'date_friday', 'Friday', '2003-05-20 12:24:40', 'date'),\r
+('en', '_template', 'date_jan', 'Jan', '2003-05-20 12:32:05', 'date'),\r
+('en', '_template', 'date_january', 'January', '2003-05-20 12:27:11', 'date'),\r
+('en', '_template', 'date_jul', 'Jul', '2003-05-20 12:33:27', 'date'),\r
+('en', '_template', 'date_july', 'July', '2003-05-20 12:28:56', 'date'),\r
+('en', '_template', 'date_jun', 'Jun', '2003-05-20 12:33:21', 'date'),\r
+('en', '_template', 'date_june', 'June', '2003-05-20 12:28:41', 'date'),\r
+('en', '_template', 'date_mar', 'Mar', '2003-05-20 12:32:22', 'date'),\r
+('en', '_template', 'date_march', 'March', '2003-05-20 12:27:48', 'date'),\r
+('en', '_template', 'date_may', 'May', '2003-05-20 12:28:20', 'date'),\r
+('en', '_template', 'date_may_short', 'May', '2003-05-20 12:33:14', 'date'),\r
+('en', '_template', 'date_mon', 'Mon', '2003-05-20 12:26:18', 'date'),\r
+('en', '_template', 'date_monday', 'Monday', '2003-05-20 12:24:00', 'date'),\r
+('en', '_template', 'date_nov', 'Nov', '2003-05-20 12:33:56', 'date'),\r
+('en', '_template', 'date_november', 'November', '2003-05-20 12:30:20', 'date'),\r
+('en', '_template', 'date_oct', 'Oct', '2003-05-20 12:33:49', 'date'),\r
+('en', '_template', 'date_october', 'October', '2003-05-20 12:30:02', 'date'),\r
+('en', '_template', 'date_of_birth', 'Date of birth', '2004-06-24 12:31:02', ''),\r
+('en', '_template', 'date_sat', 'Sat', '2003-05-20 12:26:55', 'date'),\r
+('en', '_template', 'date_saturday', 'Saturday', '2003-05-20 12:24:48', 'date'),\r
+('en', '_template', 'date_sep', 'Sep', '2003-05-20 12:33:42', 'date'),\r
+('en', '_template', 'date_september', 'September', '2003-05-20 12:29:44', 'date'),\r
+('en', '_template', 'date_sun', 'Sun', '2003-05-20 12:26:09', 'date'),\r
+('en', '_template', 'date_sunday', 'Sunday', '2003-05-20 12:23:52', 'date'),\r
+('en', '_template', 'date_taken', 'Date Taken', '2003-05-19 17:46:06', 'My Tests'),\r
+('en', '_template', 'date_thu', 'Thu', '2003-05-20 12:26:40', 'date'),\r
+('en', '_template', 'date_thursday', 'Thursday', '2003-05-20 12:24:32', 'date'),\r
+('en', '_template', 'date_tue', 'Tue', '2003-05-20 12:26:24', 'date'),\r
+('en', '_template', 'date_tuesday', 'Tuesday', '2003-05-20 12:24:12', 'date'),\r
+('en', '_template', 'date_wed', 'Wed', '2003-05-20 12:26:32', 'date'),\r
+('en', '_template', 'date_wednesday', 'Wednesday', '2003-05-20 12:24:21', 'date'),\r
+('en', '_template', 'day', 'Day', '2004-06-24 15:45:56', ''),\r
+('en', '_template', 'days', 'days', '2007-02-21 14:04:48', ''),\r
+('en', '_template', 'default', 'Default', '2003-05-19 17:47:07', 'edit header/admin course manager'),\r
+('en', '_template', 'default_announcement', 'This is a welcome announcement. You can access additional help by using the Help link available throughout ATutor.', '2005-05-11 14:52:19', ''),\r
+('en', '_template', 'default_description', 'Default Description', '2006-03-22 11:47:28', ''),\r
+('en', '_template', 'default_language', 'Default Language', '2005-03-03 10:50:22', ''),\r
+('en', '_template', 'default_modules', 'Default Student Tools', '2005-10-04 11:33:16', ''),\r
+('en', '_template', 'default_preferences', 'Default Preferences', '2005-10-05 12:19:22', ''),\r
+('en', '_template', 'default_side_menu', 'Default Side Menu', '2005-10-04 11:33:36', ''),\r
+('en', '_template', 'delete', 'Delete', '2003-05-19 18:25:41', 'global delete label'),\r
+('en', '_template', 'deleted', 'Deleted', '2003-05-19 18:26:45', 'links database'),\r
+('en', '_template', 'delete_admin', 'Delete Administrator Account', '2005-03-03 10:48:32', ''),\r
+('en', '_template', 'delete_announcement', 'Delete Announcement', '2003-05-19 18:27:52', 'delete news screen'),\r
+('en', '_template', 'delete_category', 'Delete Category', '2003-05-19 18:28:24', 'links database'),\r
+('en', '_template', 'delete_content', 'Delete Content', '2003-05-19 18:29:01', 'delete content screen'),\r
+('en', '_template', 'delete_course', 'Delete Course', '2003-05-19 18:29:37', 'delete course screen'),\r
+('en', '_template', 'delete_forum', 'Delete Forum', '2003-05-19 18:30:40', 'instructor delete forum screen'),\r
+('en', '_template', 'delete_from', 'Delete From', '2005-03-03 12:16:04', ''),\r
+('en', '_template', 'delete_glossary', 'Delete Glossary Term', '2005-03-07 11:33:35', ''),\r
+('en', '_template', 'delete_group', 'Delete Group', '2005-01-15 16:01:10', ''),\r
+('en', '_template', 'delete_language', 'Delete Language', '2003-06-05 18:59:51', 'admin language manager'),\r
+('en', '_template', 'delete_link', 'Delete Link', '2005-03-29 14:09:36', 'links manager'),\r
+('en', '_template', 'delete_package', 'Delete Package', '2005-05-17 12:06:21', ''),\r
+('en', '_template', 'delete_poll', 'Delete Poll', '2004-06-14 16:16:15', ''),\r
+('en', '_template', 'delete_post', 'Delete Post', '2006-06-14 11:53:29', ''),\r
+('en', '_template', 'delete_profile', 'Delete Profile', '2004-12-06 11:53:06', 'admin/error_logging.php'),\r
+('en', '_template', 'delete_results', 'Delete Test Results', '2003-05-19 18:31:51', 'test manager'),\r
+('en', '_template', 'delete_selected_package_s', 'Delete selected packages', '2005-07-19 09:54:28', ''),\r
+('en', '_template', 'delete_test', 'Delete Test/Survey', '2004-08-25 14:09:40', ''),\r
+('en', '_template', 'delete_this_page', 'Delete This Page', '2005-03-31 14:18:22', 'content page shortcuts'),\r
+('en', '_template', 'delete_thread', 'Delete Thread', '2003-05-19 18:35:27', 'forums'),\r
+('en', '_template', 'delete_user', 'Delete User', '2003-05-19 18:35:55', 'admin user manager'),\r
+('en', '_template', 'deny', 'Deny', '2005-03-30 15:26:27', ''),\r
+('en', '_template', 'deny_instructor_request', 'Deny Instructor Request', '2005-07-21 16:17:35', ''),\r
+('en', '_template', 'depth_reached', 'Directory depth limit has been reached.', '2003-05-19 18:36:54', 'file manager'),\r
+('en', '_template', 'description', 'Description', '2003-05-19 18:37:34', 'global description label'),\r
+('en', '_template', 'details', 'Details', '2003-05-19 18:38:03', 'instructor taught course table of the control panel'),\r
+('en', '_template', 'direction', 'Direction', '2004-11-20 19:36:34', ''),\r
+('en', '_template', 'directory', 'Directory', '2005-03-09 15:28:11', ''),\r
+('en', '_template', 'directory_name', 'Directory Name', '2003-05-19 18:38:42', 'file manager zip utility'),\r
+('en', '_template', 'directory_total', 'Directory Total', '2003-05-19 18:39:15', 'file manager'),\r
+('en', '_template', 'disable', 'Disable', '2004-10-15 15:46:20', 'to disable a theme in theme manager'),\r
+('en', '_template', 'disabled', 'Disabled', '2005-04-01 10:39:58', ''),\r
+('en', '_template', 'disable_syndicate', 'Disable Announcements syndication', '2005-01-04 09:48:31', ''),\r
+('en', '_template', 'discussions', 'Discussions', '2003-05-19 18:43:39', 'global text for discussions label'),\r
+('en', '_template', 'disk_usage', 'Disk Usage', '2007-07-26 17:02:11', ''),\r
+('en', '_template', 'display', 'Display', '2004-08-18 12:03:48', ''),\r
+('en', '_template', 'display_name_format', 'Display Name Format', '2006-09-07 10:21:44', ''),\r
+('en', '_template', 'display_name_format_fl', '%2$s (%1$s)', '2006-08-21 15:29:17', ''),\r
+('en', '_template', 'display_name_format_fst', '%2$s %3$s %4$s', '2006-08-21 15:27:41', ''),\r
+('en', '_template', 'display_name_format_fstl', '%2$s %3$s %4$s (%1$s)', '2006-08-21 15:28:21', ''),\r
+('en', '_template', 'display_name_format_l', '%s', '2006-08-21 15:25:55', ''),\r
+('en', '_template', 'display_name_format_lf', '%1$s (%2$s)', '2006-08-21 15:29:46', ''),\r
+('en', '_template', 'display_name_format_lfst', '%1$s (%2$s %3$s %4$s)', '2006-08-21 15:30:22', ''),\r
+('en', '_template', 'done', 'Done', '2003-05-19 18:44:34', 'enrolment manager'),\r
+('en', '_template', 'download', 'Download', '2004-04-30 15:35:13', ''),\r
+('en', '_template', 'download_file', 'Download File', '2005-01-10 15:40:00', ''),\r
+('en', '_template', 'download_test_csv', 'Download CSV of Results', '2005-05-30 14:32:27', ''),\r
+('en', '_template', 'due', 'Due', '2006-03-20 14:38:46', ''),\r
+('en', '_template', 'due_date', 'Due Date', '2006-03-23 11:36:41', ''),\r
+('en', '_template', 'duration', 'Total Duration', '2005-03-01 12:40:00', 'tracker'),\r
+('en', '_template', 'duration_sec', 'Duration (sec)', '2003-05-19 18:45:37', 'tracker'),\r
+('en', '_template', 'e', 'E', '2007-01-10 13:48:09', ''),\r
+('en', '_template', 'edit', 'Edit', '2004-05-26 18:31:10', ''),\r
+('en', '_template', 'editor', 'Editor', '2003-10-22 15:01:19', ''),\r
+('en', '_template', 'editor_properties_instructions', 'Use the %1$s and %2$s buttons to place this topic after or before the selected location, respectively. Use the %3$s button to add this topic as a child of the selected location.', '2004-02-11 12:22:15', ''),\r
+('en', '_template', 'editor_properties_insturctions_related', 'Add Related Topics by selecting the topic from the list.', '2004-02-11 12:33:28', 'editor properties instructions'),\r
+('en', '_template', 'edit_admin', 'Edit Administrator Account', '2005-03-03 11:06:16', ''),\r
+('en', '_template', 'edit_after_upload', ' After uploaded use the fields below to edit the content.', '2003-05-19 18:47:10', 'cotent editor'),\r
+('en', '_template', 'edit_announcement', 'Edit Announcement', '2003-05-19 18:47:32', 'instructor announcement editor'),\r
+('en', '_template', 'edit_backup', 'Edit - %s', '2004-10-19 12:46:00', ''),\r
+('en', '_template', 'edit_category', 'Edit Category', '2003-05-19 18:49:44', 'links database'),\r
+('en', '_template', 'edit_content', 'Edit Content', '2003-05-19 18:50:07', 'instructor content editor'),\r
+('en', '_template', 'edit_forum', 'Edit Forum', '2003-05-19 18:50:54', 'instructor forum editor'),\r
+('en', '_template', 'edit_for_minutes', 'for another %s minutes', '2007-02-23 11:53:28', ''),\r
+('en', '_template', 'edit_glossary', 'Edit Glossary Term', '2003-05-19 18:54:15', 'instructor edit glossary term screen'),\r
+('en', '_template', 'edit_language', 'Edit Language', '2005-01-21 18:24:19', ''),\r
+('en', '_template', 'edit_link', 'Edit Link', '2003-05-19 18:54:44', 'links database'),\r
+('en', '_template', 'edit_poll', 'Edit Poll', '2004-06-14 14:53:54', ''),\r
+('en', '_template', 'edit_post', 'Edit Post', '2003-09-25 12:54:59', 'instructor edit forum post'),\r
+('en', '_template', 'edit_question', 'Edit Question', '2004-12-14 17:58:58', ''),\r
+('en', '_template', 'edit_test', 'Edit Test/Survey', '2004-08-25 14:08:30', ''),\r
+('en', '_template', 'edit_this_page', 'Edit This Page', '2005-03-31 14:16:42', 'content page shortcuts'),\r
+('en', '_template', 'edit_user', 'Edit Member', '2004-03-29 11:49:10', ''),\r
+('en', '_template', 'email', 'Email', '2003-05-19 19:07:59', 'global email label'),\r
+('en', '_template', 'email_address', 'Email Address', '2003-05-19 19:09:06', 'profile, password reminder'),\r
+('en', '_template', 'email_approvals', 'Email me when new enrollments require approval.', '2004-01-22 14:57:19', ''),\r
+('en', '_template', 'email_confirmation_message', 'You have registered for an account on %1s. Please finish the registration process by confirming your email address by using the following link: %2s .', '2005-06-24 15:32:49', ''),\r
+('en', '_template', 'email_confirmation_message2', 'To finish changing your account\'s email address on %1s, please confirm your email address by using the following link: %2s .', '2006-05-11 16:08:25', ''),\r
+('en', '_template', 'email_confirmation_subject', 'Email Confirmation', '2005-03-22 11:35:30', ''),\r
+('en', '_template', 'emoticons', 'Emoticons', '2003-05-22 15:43:20', 'code picker'),\r
+('en', '_template', 'empty', 'empty', '2003-05-19 19:10:56', 'prefs page, menu options'),\r
+('en', '_template', 'enable', 'Enable', '2004-10-15 15:52:29', 'enable button in theme'),\r
+('en', '_template', 'enabled', 'Enabled', '2005-05-06 12:49:07', 'theme'),\r
+('en', '_template', 'enable_mail_queue', 'Enable Mail Queue', '2006-04-03 14:21:43', ''),\r
+('en', '_template', 'enable_sco_rte', 'Enable the SCORM 1.2 RTE', '2005-05-10 10:52:42', ''),\r
+('en', '_template', 'enable_syndicate', 'Enable Announcements syndication via <acronym title=\"Rich Site Summary\">RSS</acronym>', '2005-01-04 10:27:41', ''),\r
+('en', '_template', 'end_date', 'End Date', '2003-05-19 19:13:46', 'mytests'),\r
+('en', '_template', 'end_on', 'End on', '2007-07-16 14:26:34', ''),\r
+('en', '_template', 'enroll', 'Enroll', '2003-05-19 19:16:50', 'link text for enroll function'),\r
+('en', '_template', 'enrolled', 'Enrolled', '2003-05-19 19:18:28', 'control centre, delete course, admin course manager, text label'),\r
+('en', '_template', 'enrolled_list_includes_assistants', 'Enrolled Students (includes Assistants)', '2004-10-15 11:56:23', 'enrolled students list in list exporter in enrollement manager'),\r
+('en', '_template', 'enrolled_privileges', 'Enrolled With Privileges', '2005-06-10 10:58:01', ''),\r
+('en', '_template', 'enrollment', 'Enrollment', '2005-12-07 11:19:38', ''),\r
+('en', '_template', 'enroll_me', 'Enroll Me', '2005-04-14 13:15:58', ''),\r
+('en', '_template', 'enroll_to_post', 'You must be enrolled to post to the forums.', '2004-12-09 11:07:43', ''),\r
+('en', '_template', 'enrolment', 'Enrollment', '2006-10-18 11:47:33', ''),\r
+('en', '_template', 'enrol_login', 'You must login to your course to approve the new enrollment request using the Enrollment section.', '2005-07-05 12:15:39', 'instructor enrolment screen'),\r
+('en', '_template', 'enrol_message3', 'ATutor Course Enrollment', '2003-04-21 15:03:49', 'context'),\r
+('en', '_template', 'enrol_messagenew', 'An enrollment request was made for the ATutor course %s. Log into your course at %s , go to Manage and then to the unenrolled tab in the Enrollment Manager.', '2005-03-29 12:23:47', 'instructor enrolment email notice'),\r
+('en', '_template', 'enrol_message_approved', 'Your enrollment request for the course %1s has been approved.\r\nLog into ATutor, then select the course from My Courses or use the login link below:\r\n\r\n%2s', '2005-03-30 11:49:50', 'email message sent to enrollee once approved'),\r
+('en', '_template', 'enrol_message_subject', 'Course enrollment approved', '2003-05-20 11:18:15', 'enroll email approval'),\r
+('en', '_template', 'enrol_msg', 'A new enrollment request has been made for your course %s.', '2005-07-05 12:15:49', 'instructor email enrollment notification message'),\r
+('en', '_template', 'enter_chat', 'Enter the Chat', '2003-05-27 14:20:24', 'achat entry page'),\r
+('en', '_template', 'enter_course', 'Enter Course', '2005-03-14 15:15:57', ''),\r
+('en', '_template', 'entire_course', 'Entire Course', '2006-07-24 10:44:01', ''),\r
+('en', '_template', 'error', 'Error', '2003-05-19 20:20:07', 'global error label'),\r
+('en', '_template', 'error_logging', 'Error Logging', '2005-02-07 16:11:55', ''),\r
+('en', '_template', 'everyone', 'Everyone', '2004-12-07 17:54:16', ''),\r
+('en', '_template', 'existing_type', 'Existing Type:', '2006-03-22 15:11:15', ''),\r
+('en', '_template', 'expand', 'Expand', '2003-05-19 20:20:35', 'menu toggle alt text'),\r
+('en', '_template', 'expired', 'Expired', '2003-05-19 20:21:08', 'mytests'),\r
+('en', '_template', 'expire_never', 'Never expire', '2007-02-13 15:38:14', ''),\r
+('en', '_template', 'expire_on', 'Expire on', '2007-02-13 15:38:24', ''),\r
+('en', '_template', 'expiry_date', 'Expiry Date', '2007-02-13 15:37:50', ''),\r
+('en', '_template', 'export', 'Export', '2003-05-19 20:21:32', 'instructor control centre'),\r
+('en', '_template', 'export_content', 'Export Content', '2003-10-03 11:00:51', ''),\r
+('en', '_template', 'export_content_info', 'Export content as an IMS 1.1.3/SCORM 1.2 conformant content package of the selected topics in a single archive file. Download then unzipped the file to view it offline, by opening the <kbd>index.html</kbd> file within the package. Import the zipped package into ATutor, or into another conformant learning content management system.', '2005-02-21 13:17:46', ''),\r
+('en', '_template', 'export_content_package_what', 'What to export', '2003-10-14 11:11:11', ''),\r
+('en', '_template', 'export_entire_course_or_chap', 'Entire course, or select a chapter below', '2003-10-07 15:14:52', ''),\r
+('en', '_template', 'external_help', 'External Help', '2005-03-17 10:31:39', ''),\r
+('en', '_template', 'extra', 'Extra', '2005-09-21 13:35:05', ''),\r
+('en', '_template', 'extract', 'Extract', '2003-05-19 20:23:33', 'file manager zip utility'),\r
+('en', '_template', 'extract_archive', 'Extract Archive', '2003-05-19 20:23:58', 'file manager zip utility'),\r
+('en', '_template', 'extract_tip', 'Tip: Use an empty directory name to extract the contents into the current directory.', '2003-05-19 20:24:27', 'file manager zip utility'),\r
+('en', '_template', 'f', 'F', '2007-01-10 13:48:14', ''),\r
+('en', '_template', 'false', 'False', '2003-05-20 08:52:19', 'textmanager, mytests t/f label'),\r
+('en', '_template', 'faq', 'Frequently Asked Questions (FAQ)', '2005-10-19 12:41:54', ''),\r
+('en', '_template', 'feedback', 'Feedback', '2003-05-20 09:09:40', 'global feedback label'),\r
+('en', '_template', 'female', 'Female', '2003-05-20 09:18:03', 'registration, profile'),\r
+('en', '_template', 'file', 'File', '2003-05-20 09:18:31', 'file manager, zip tool'),\r
+('en', '_template', 'filemanager_date_format', '%%Y-%%m-%%d %%h:%%i', '2003-05-25 13:42:59', 'file manager date'),\r
+('en', '_template', 'files', 'Files', '2005-08-16 15:27:36', ''),\r
+('en', '_template', 'file_manager', 'File Manager', '2003-05-20 09:27:19', 'global file manager label'),\r
+('en', '_template', 'file_manager_frame', 'File Manager Frame', '2005-01-31 11:14:37', 'viewing files in filemanger frame'),\r
+('en', '_template', 'file_manager_new', 'Create a New File', '2004-10-29 14:53:13', 'file manager'),\r
+('en', '_template', 'file_name', 'File Name', '2004-10-15 12:08:25', ''),\r
+('en', '_template', 'file_size', 'File Size', '2004-10-14 13:57:59', ''),\r
+('en', '_template', 'file_storage', 'File Storage', '2006-03-20 14:36:04', ''),\r
+('en', '_template', 'file_storage_version_control', 'Maintain File Storage Version Control', '2006-03-29 12:43:11', ''),\r
+('en', '_template', 'file_to_read', 'File To Read', '2006-04-13 11:03:16', ''),\r
+('en', '_template', 'fill_groups', 'Fill Groups', '2006-03-22 11:52:47', ''),\r
+('en', '_template', 'fill_groups_randomly', 'Fill groups randomly upon creation.', '2006-03-22 11:53:14', ''),\r
+('en', '_template', 'filter', 'Filter', '2005-03-30 14:52:33', ''),\r
+('en', '_template', 'final_score', 'Final Score', '2007-03-16 14:10:05', ''),\r
+('en', '_template', 'find_results_in', 'Find results in', '2004-08-18 12:02:16', ''),\r
+('en', '_template', 'first_name', 'First Name', '2003-05-20 09:58:26', 'registration, profile'),\r
+('en', '_template', 'fix_content_ordering', 'Fix Content Ordering', '2004-10-18 14:03:47', ''),\r
+('en', '_template', 'fix_content_ordering_text', 'Occasionally, content pages can get disordered due to miscalculation. This is an ongoing issue that will be resolved in an upcoming version of ATutor but until then, we have made a patch available that can be used to fix the issue. If you are experiencing this problem, please use the button below.', '2005-03-10 11:19:41', ''),\r
+('en', '_template', 'folder', 'Folder', '2003-05-20 10:05:51', 'file manager, zip utility'),\r
+('en', '_template', 'formatting', 'Formatting', '2003-05-20 10:07:25', 'add/ edit content, news, export'),\r
+('en', '_template', 'form_editor', 'Atutor Form Editor', '2005-03-11 10:31:45', 'Form editor for test questions'),\r
+('en', '_template', 'form_focus', 'Form Focus On Page Load', '2005-03-29 12:38:11', ''),\r
+('en', '_template', 'forum', 'Forum', '2004-04-16 10:54:23', 'Forum list header'),\r
+('en', '_template', 'forums', 'Forums', '2003-05-20 10:08:05', 'global forums label'),\r
+('en', '_template', 'forum_date_format', '%%D %%M %%j %%H:%%i', '2004-05-26 15:18:29', ''),\r
+('en', '_template', 'forum_email_links', 'All email addresses are made into links.', '2003-05-20 10:11:14', 'forums email address links instruction'),\r
+('en', '_template', 'forum_general_discussion', 'General Discussion', '2004-12-16 11:07:19', 'default forum in forum list'),\r
+('en', '_template', 'forum_html_disabled', 'HTML is disabled.', '2003-05-20 10:11:42', 'forum compose message'),\r
+('en', '_template', 'forum_links', 'All words starting with http:// are made into links.', '2003-05-20 10:12:23', 'forum compose link creation instruction'),\r
+('en', '_template', 'forum_new_submsg', '*DO NOT REPLY TO THIS MESSAGE*\r\nA discussion thread in the ATutor course \"%s\" has recieved a reply. Login to access the \"%s\" forum and view the \"%s\" thread. Login at: %s', '2007-03-30 08:26:03', 'forum email message to thread subscribers'),\r
+('en', '_template', 'forum_posts', 'Forum Posts', '2005-03-16 14:59:41', ''),\r
+('en', '_template', 'forum_reply_to', 'Replying To', '2003-05-20 10:12:48', 'forum reply to label for quoted messages'),\r
+('en', '_template', 'forward', 'Forward', '2007-02-20 16:21:52', ''),\r
+('en', '_template', 'from', 'From', '2003-05-20 10:17:19', 'global from label'),\r
+('en', '_template', 'from_atutor', 'This message was sent through the ATutor system from course %s.', '2003-05-20 10:19:30', 'instructor/admin contact for email message'),\r
+('en', '_template', 'from_email', 'From Email', '2003-05-20 10:21:35', 'instructor/admin contact form'),\r
+('en', '_template', 'from_name', 'From Name', '2003-05-20 10:22:02', 'instrcutor/admin contact from'),\r
+('en', '_template', 'fs_comment', '%s Comment', '2006-06-29 10:09:37', ''),\r
+('en', '_template', 'fs_comments', '%s Comments', '2006-06-29 09:55:11', ''),\r
+('en', '_template', 'fs_revision', '%s Revision', '2006-06-29 10:05:39', ''),\r
+('en', '_template', 'fs_revisions', '%s Revisions', '2006-06-29 09:52:36', ''),\r
+('en', '_template', 'full_name', 'Full Name', '2006-03-27 15:55:44', ''),\r
+('en', '_template', 'fwd', 'Fwd', '2007-02-20 16:20:07', ''),\r
+('en', '_template', 'g', 'G', '2007-01-10 13:48:18', ''),\r
+('en', '_template', 'gender', 'Sex', '2003-05-20 10:22:19', 'registration, profile'),\r
+('en', '_template', 'general_help', 'For guidance on using ATutor see the official <a href=\"%1$s\" onclick=\"poptastic(\'%1$s\'); return false;\" target=\"_new\"><em>ATutor Handbook</em></a>.', '2005-07-05 14:07:32', 'atutor default footer'),\r
+('en', '_template', 'give_description', 'Brief description of your proposed course(s)', '2005-03-09 12:19:48', 'control centre request instructor account form'),\r
+('en', '_template', 'global_more_than_10_pages', 'Global: More than 10 pages.', '2006-09-27 12:42:43', ''),\r
+('en', '_template', 'glossary', 'Glossary', '2003-05-20 10:24:33', 'global glossary label'),\r
+('en', '_template', 'glossary_definition', 'Definition', '2003-05-20 10:25:13', 'glossary add/edit term'),\r
+('en', '_template', 'glossary_related', 'Related Term', '2003-05-20 10:26:35', 'add/edit glossary term'),\r
+('en', '_template', 'glossary_term', 'Term', '2003-05-20 10:27:01', 'add/edit glossary term'),\r
+('en', '_template', 'glossary_terms', 'Glossary Terms', '2003-05-20 10:27:47', 'delete course feedback for terms deleted'),\r
+('en', '_template', 'glossary_term_limit', 'This term exceeds the 60 character limit and cannot be added.', '2005-12-12 11:39:08', ''),\r
+('en', '_template', 'go', 'Go!', '2006-04-26 13:47:29', ''),\r
+('en', '_template', 'google_key', 'Google Key', '2005-10-20 11:02:40', ''),\r
+('en', '_template', 'google_key_txt', 'To access the Google search as an <em>embedded service</em>, you must first create an account and obtain a license key at <a href=\"http://code.google.com/apis/ajaxsearch/signup.html\" target=\"_new\">google.com/apis</a> and enter it below.\r\n<br /><br />\r\nThe search can be used as an external service by clearing the key field below.', '2007-09-04 15:14:30', ''),\r
+('en', '_template', 'google_new_window', 'Search opens in a new window.', '2005-11-30 16:45:26', ''),\r
+('en', '_template', 'google_search', 'Web Search', '2005-10-20 10:35:41', ''),\r
+('en', '_template', 'google_search_ajax', 'Google AJAX Search <em>(requires license key <b>after</b> Dec 5th, 2006)</em>', '2007-08-31 14:55:58', 'Google search'),\r
+('en', '_template', 'google_search_attn', 'Please note that the old Google search is only applicable to those who have obtained a license key before Dec 5th, 2006; any new license key obtained after December 5th, 2006 is only applicable to the new Google AJAX search.', '2007-09-04 14:55:56', 'Google search'),\r
+('en', '_template', 'google_search_books', 'Books', '2007-08-31 11:25:12', 'Google search'),\r
+('en', '_template', 'google_search_images', 'Images', '2007-08-31 11:22:38', 'Google search'),\r
+('en', '_template', 'google_search_local', 'Local', '2007-08-31 11:57:07', 'Google search'),\r
+('en', '_template', 'google_search_news', 'News', '2007-08-31 11:23:30', 'Google search'),\r
+('en', '_template', 'google_search_soap', 'Old Google Search <em>(requires license key <b>before</b> Dec 5th, 2006)</em>', '2007-08-31 14:54:58', 'Google search'),\r
+('en', '_template', 'google_search_txt', 'To search for specific words within a website, enter them below then use the \'Search\' button.  If you wish to search course content, use the <a href=\"search.php\">content search</a>.', '2005-10-20 11:02:02', ''),\r
+('en', '_template', 'google_search_type_txt', 'Please select one of the Google search interfaces.', '2007-08-31 14:36:30', 'Google search'),\r
+('en', '_template', 'google_search_videos', 'Videos', '2007-08-31 11:22:53', 'Google search'),\r
+('en', '_template', 'goto_content', 'Go to content', '2004-05-11 15:18:23', ''),\r
+('en', '_template', 'goto_menu', 'Go to Menu', '2006-07-14 10:14:57', '2nd invisible link on the page'),\r
+('en', '_template', 'goto_top', 'Go to Top', '2003-05-20 10:34:03', 'bypass link text in ATutor header'),\r
+('en', '_template', 'graph', 'Graph', '2003-05-20 10:36:18', 'instructor course details graph label'),\r
+('en', '_template', 'gray', 'Gray', '2003-05-20 10:36:32', 'global code picker'),\r
+('en', '_template', 'green', 'Green', '2003-05-20 10:36:45', 'global code picker'),\r
+('en', '_template', 'group', 'Group', '2005-05-03 15:42:38', ''),\r
+('en', '_template', 'grouped_by_course', 'Grouped by course', '2004-08-18 12:04:40', ''),\r
+('en', '_template', 'groups', 'Groups', '2004-11-25 15:45:26', ''),\r
+('en', '_template', 'groups_create_automatic', 'Create multiple groups automatically', '2006-03-21 15:36:08', ''),\r
+('en', '_template', 'groups_create_manual', 'Create a single group manually', '2006-03-21 15:36:58', ''),\r
+('en', '_template', 'groups_type', 'Groups Type', '2006-03-22 11:16:01', ''),\r
+('en', '_template', 'group_forums', 'Group Forums', '2006-05-24 08:48:58', ''),\r
+('en', '_template', 'group_members', 'Group Members', '2005-06-10 10:34:56', ''),\r
+('en', '_template', 'group_prefix', 'Group Prefix', '2006-03-22 11:17:12', ''),\r
+('en', '_template', 'guest', 'Guest', '2003-05-20 10:37:10', 'name assigned to non-registered users'),\r
+('en', '_template', 'guests', 'Guests', '2003-05-20 10:38:19', 'instructor course stats/details'),\r
+('en', '_template', 'guests_not_listed', 'Guests are not listed', '2003-05-20 10:38:32', 'who\'s on menu'),\r
+('en', '_template', 'h', 'H', '2007-01-10 13:48:22', ''),\r
+('en', '_template', 'handout_to_read', 'Handout to Read', '2006-04-13 11:58:39', ''),\r
+('en', '_template', 'hand_in', 'Hand In', '2006-03-20 14:36:56', ''),\r
+('en', '_template', 'have', 'Have', '2007-02-21 13:22:47', ''),\r
+('en', '_template', 'have_not', 'Have not', '2007-02-21 14:06:25', ''),\r
+('en', '_template', 'help', 'Help', '2003-05-20 10:41:08', 'global help label'),\r
+('en', '_template', 'hidden', 'Hidden', '2003-05-20 10:42:27', 'instructor/admin contact form'),\r
+('en', '_template', 'hide', 'Hide', '2005-03-15 11:37:50', ''),\r
+('en', '_template', 'hide_course', 'Hide this course from the Browse Courses list', '2003-05-20 10:42:41', 'create course screen'),\r
+('en', '_template', 'history', 'History', '2003-05-25 08:36:00', 'context (removed after v1.1)'),\r
+('en', '_template', 'hits', 'Hits', '2003-05-20 10:44:14', 'links database link hit count'),\r
+('en', '_template', 'hit_count', 'Hit Count', '2003-05-20 10:45:17', 'tracker'),\r
+('en', '_template', 'home', 'Home', '2006-05-31 11:12:30', ''),\r
+('en', '_template', 'home_url', 'Home URL', '2005-03-03 10:50:09', ''),\r
+('en', '_template', 'horizontal', 'Horizontal', '2004-12-01 13:35:05', 'edit/create option test questions'),\r
+('en', '_template', 'hot', 'Hot!', '2003-05-20 10:47:10', '(not used)'),\r
+('en', '_template', 'hot_thread', 'Hot very active thread!', '2003-05-20 10:47:30', 'forum message for busy thread'),\r
+('en', '_template', 'hours_24', '24hr', '2003-05-20 10:48:10', 'release date picker'),\r
+('en', '_template', 'hour_short', 'h', '2007-07-09 12:31:21', ''),\r
+('en', '_template', 'howto_course', '<a href=\"http://atutor.ca/atutor/docs/index.php\">ATutor Documentation</a>', '2005-06-01 12:32:03', 'help'),\r
+('en', '_template', 'howto_course_text', 'In addition to the <a href=\"documentation/\" onclick=\"poptastic(\'documentation/\'); return false;\" target=\"_new\"><em>ATutor Handbook</em></a> bundled with ATutor, other documentation sources are available through the <a href=\"http://atutor.ca/atutor/docs/index.php\">ATutor Documentation</a> site.', '2005-07-06 10:04:29', ''),\r
+('en', '_template', 'html', 'HTML', '2003-05-20 10:48:48', 'global HTML label'),\r
+('en', '_template', 'html_only', ' Plain Text or HTML files only.', '2003-05-20 10:49:49', 'add/edit content, header'),\r
+('en', '_template', 'i', 'I', '2007-01-10 13:48:26', ''),\r
+('en', '_template', 'icon', 'Icon', '2005-03-03 11:19:49', ''),\r
+('en', '_template', 'id', 'ID', '2003-05-20 10:50:57', 'global ID (identification number) label'),\r
+('en', '_template', 'illegal_file', 'Illegal File Type', '2003-05-20 10:52:36', 'zip utility when archive contain illegal extension'),\r
+('en', '_template', 'illegal_file_extensions', 'Illegal File Extensions', '2005-03-03 10:52:15', ''),\r
+('en', '_template', 'image', 'Image', '2003-05-20 10:53:28', 'global code picker image code link text'),\r
+('en', '_template', 'import', 'Import', '2003-05-20 11:56:51', 'instructor import/export screen'),\r
+('en', '_template', 'import_a_new_lang', 'Import a New Language', '2003-06-04 15:34:43', 'admin language manager'),\r
+('en', '_template', 'import_content', 'Import Content', '2005-02-18 14:05:57', ''),\r
+('en', '_template', 'import_content_info', 'Import a conformant content package created by ATutor, or another learning content management system. A content package can be appended to the end of the course, after which it can be moved, or it can be added as a sub topic to an existing topic. If you have the Web address directly to a content package, enter it into the URL field to import it directly from the Web.', '2005-02-21 13:20:30', ''),\r
+('en', '_template', 'import_content_package', 'Import Content Package', '2003-10-03 13:07:38', ''),\r
+('en', '_template', 'import_content_package_bottom_subcontent', 'As top level content, or as subcontent selected below', '2003-10-20 13:36:27', ''),\r
+('en', '_template', 'import_content_package_where', 'Import into', '2003-10-14 12:24:03', ''),\r
+('en', '_template', 'import_err_email_exists', 'Account exists.', '2004-01-30 15:38:42', ''),\r
+('en', '_template', 'import_err_email_invalid', 'Email invalid.', '2004-01-30 13:28:32', ''),\r
+('en', '_template', 'import_err_email_missing', 'Email missing.', '2004-01-30 13:28:40', ''),\r
+('en', '_template', 'import_err_full_name_exists', 'First and Last name exist.', '2006-03-28 10:40:02', ''),\r
+('en', '_template', 'import_err_username_exists', 'Username already taken.', '2004-01-30 13:28:48', ''),\r
+('en', '_template', 'import_err_username_invalid', 'Username contains invalid characters.', '2004-01-30 13:28:56', ''),\r
+('en', '_template', 'import_lang_howto', 'You may import additional languages into this installation of ATutor by downloading the language pack from the ATutor.ca website then uploading it using the form below, or if the drop down below is able to detect the available languages remotely then it may be used as well.', '2004-10-18 14:25:21', 'admin language manager'),\r
+('en', '_template', 'import_package', 'Import Package', '2005-05-17 12:06:10', ''),\r
+('en', '_template', 'import_remote_language', 'Or, import a language directly from the ATutor.ca website.', '2004-10-18 14:27:11', ''),\r
+('en', '_template', 'import_sep_txt', 'For auto-generated usernames, separate first and last names with:', '2004-06-22 12:07:48', ''),\r
+('en', '_template', 'import_theme', 'Import Theme', '2004-10-15 15:47:13', 'import theme button in theme manager'),\r
+('en', '_template', 'inactive_admin', 'Inactive Administrator', '2005-03-03 11:00:55', ''),\r
+('en', '_template', 'inbox', 'Inbox', '2003-05-20 11:59:47', 'global Inbox label'),\r
+('en', '_template', 'inbox_date_format', '%%l %%M %%j, %%Y - %%H:%%i', '2003-05-20 12:00:47', 'inbox screen (see www.php.net/date for codes)'),\r
+('en', '_template', 'inbox_notification', 'Inbox Notification', '2005-03-16 14:40:07', ''),\r
+('en', '_template', 'info', 'Course Info', '2005-04-01 15:09:41', 'global info message box label'),\r
+('en', '_template', 'initial_content', 'Initial Content', '2004-10-15 15:45:10', ''),\r
+('en', '_template', 'insert', 'Insert', '2003-05-20 12:02:16', 'instructor add content screen'),\r
+('en', '_template', 'insert_into', 'Insert Into', '2005-03-03 12:15:49', ''),\r
+('en', '_template', 'install', 'Install', '2005-08-16 15:51:57', ''),\r
+('en', '_template', 'install_modules', 'Install Modules', '2005-08-16 16:17:09', ''),\r
+('en', '_template', 'install_module_text', 'To install a new module it must first be extracted into the <code>%s</code> directory for it to appear in the list below.', '2005-08-17 13:47:02', ''),\r
+('en', '_template', 'install_themes_text', 'To install new themes the <code>%s</code> directory must be set to writeable. Use the command <kbd>chmod a+w themes</kbd> on Unix machines, while on Windows the web server must have write permissions on that directory.', '2005-12-14 12:36:08', ''),\r
+('en', '_template', 'instructions', 'Instructions', '2005-04-05 14:25:07', ''),\r
+('en', '_template', 'instructor', 'Instructor', '2003-05-20 12:02:59', 'global instructor label'),\r
+('en', '_template', 'instructors', 'Instructors', '2003-05-20 12:03:37', 'admin general statistics label for number of instructors'),\r
+('en', '_template', 'instructor_contact_form', 'Instructor Contact Form', '2003-05-20 12:12:32', 'instructor contact form heading'),\r
+('en', '_template', 'instructor_request', 'ATutor Instructor Request', '2003-05-25 08:37:50', 'subject line in email to admin when instructor request is made'),\r
+('en', '_template', 'instructor_requests', 'Instructor Requests', '2003-05-20 12:19:52', 'admin home page heading'),\r
+('en', '_template', 'instructor_requests_text', 'There are <strong>%s</strong> instructor requests pending approval.', '2005-03-30 15:30:02', ''),\r
+('en', '_template', 'instructor_request_deny', 'Your ATutor instructor request has been denied.', '2003-10-06 15:14:48', 'email message to denied instructor'),\r
+('en', '_template', 'instructor_request_denymsg1', 'Registration information is incomplete.', '2003-10-06 15:55:47', 'reason why denied'),\r
+('en', '_template', 'instructor_request_denymsg2', 'Inappropriate subject matter.', '2003-10-06 16:01:26', 'reason why denied'),\r
+('en', '_template', 'instructor_request_denymsg3', 'The course description requires more detail.', '2003-10-07 15:47:33', 'deny instructor request'),\r
+('en', '_template', 'instructor_request_denymsg4', 'You have requested enrollment with the wrong form.', '2003-10-07 15:52:12', 'admin deny instructor request'),\r
+('en', '_template', 'instructor_request_email_notification', 'Instructor Request Email Notification', '2005-03-03 10:51:01', ''),\r
+('en', '_template', 'instructor_request_enterdenymsg', 'Choose a message explaining why the user\'s request was denied or enter your own.', '2003-10-06 15:19:05', 'Header text for deny message text area'),\r
+('en', '_template', 'instructor_request_reply', 'Your ATutor instructor request has been approved. Go to %s to login to My Courses, then select \"Create Course\".', '2005-05-27 13:53:06', 'email in reply to instructor account approval'),\r
+('en', '_template', 'invalid_session', 'Not a Valid Session', '2003-05-20 12:26:29', 'tracker'),\r
+('en', '_template', 'in_minutes', 'Minutes', '2007-02-20 10:30:20', ''),\r
+('en', '_template', 'in_reply_to', 'In reply to', '2003-05-20 12:27:21', 'replyto label for quoted forum or inbox message'),\r
+('en', '_template', 'italic', 'Italic', '2003-05-20 12:27:44', 'global code picker link text'),\r
+('en', '_template', 'item', 'Item', '2007-01-10 13:46:39', ''),\r
+('en', '_template', 'j', 'J', '2007-01-10 13:48:30', ''),\r
+('en', '_template', 'jump', 'Jump', '2003-05-20 12:28:03', 'jump menu submit button text'),\r
+('en', '_template', 'jump_codes', 'Jump over the code picker', '2003-05-20 12:29:53', 'alt text for bypass link to jump over the code picker'),\r
+('en', '_template', 'jump_redirect', 'Direct Jump', '2004-11-30 10:03:55', 'preferecnes'),\r
+('en', '_template', 'keep_email_private', 'Keep email hidden from others.', '2006-03-28 11:29:07', ''),\r
+('en', '_template', 'keep_it_short', 'Tip: Keep it short, no spaces.', '2003-05-20 12:31:53', 'file manager suggestion for folder creation'),\r
+('en', '_template', 'keywords', 'Keywords', '2003-09-28 10:22:10', 'content add/edit'),\r
+('en', '_template', 'language', 'Language', '2003-05-20 12:32:05', 'profile, registration'),\r
+('en', '_template', 'languages', 'Languages', '2005-03-03 11:07:50', ''),\r
+('en', '_template', 'lang_code', 'Language Code', '2006-09-27 14:12:11', ''),\r
+('en', '_template', 'last_accessed', 'Last Accessed', '2005-03-01 12:52:16', 'tracker'),\r
+('en', '_template', 'last_comment', 'Last Comment', '2003-05-20 12:33:10', 'forums, thread view column label'),\r
+('en', '_template', 'last_login', 'Last Login', '2005-03-03 11:03:12', ''),\r
+('en', '_template', 'last_modified', 'Last Modified', '2003-05-20 12:36:35', 'instructor content editor link text'),\r
+('en', '_template', 'last_name', 'Last Name', '2003-05-20 12:37:39', 'registration, profile, admin user manager'),\r
+('en', '_template', 'last_post', 'Last Post', '2004-04-16 11:24:59', 'Refers to date of last post in forum'),\r
+('en', '_template', 'last_updated', 'Last updated: %s', '2006-05-19 14:54:08', ''),\r
+('en', '_template', 'leave_blank', 'Leave blank', '2003-05-20 12:39:07', 'mytest/test manager question option'),\r
+('en', '_template', 'leave_unchanged', 'Leave unchanged', '2005-05-10 16:04:07', ''),\r
+('en', '_template', 'left', 'Left', '2004-04-27 11:00:35', ''),\r
+('en', '_template', 'left_blank', 'Left blank', '2003-05-20 12:40:14', 'mytests/test manager question result text for unanswerd question'),\r
+('en', '_template', 'legend', 'Legend', '2003-05-20 12:41:00', 'instructor course statistics/details'),\r
+('en', '_template', 'license', 'License', '2005-08-16 15:27:07', ''),\r
+('en', '_template', 'limit_to_group', 'Assign To Groups', '2004-12-10 14:39:53', ''),\r
+('en', '_template', 'link', 'Link', '2003-05-20 12:41:18', 'links database'),\r
+('en', '_template', 'links', 'Links', '2005-02-09 13:25:20', ''),\r
+('en', '_template', 'list_add_course_list', 'Add to Course List', '2004-10-19 14:39:08', 'Enrollment manager, add students manually button'),\r
+('en', '_template', 'list_add_enrolled_list', 'Add to Enrolled List', '2004-10-19 14:51:02', 'enrollment manager, add to enrolled students list button'),\r
+('en', '_template', 'list_add_unenrolled_list', 'Add to Un-enrolled List', '2004-10-19 14:47:31', 'enrollment manager, add to unenrolled students list button'),\r
+('en', '_template', 'list_create_course_list', 'Create Course List', '2004-10-15 12:04:06', 'create list of students function in enrollement manager'),\r
+('en', '_template', 'list_export_course_list', 'Export Course List', '2003-09-16 10:15:29', 'enrol admin'),\r
+('en', '_template', 'list_import_course_list', 'Import Course List', '2003-09-16 09:35:35', 'import course list'),\r
+('en', '_template', 'list_import_howto', 'A course enrollment list may be imported into ATutor. Create the course list in a comma separated values (CSV) format as follows: <code>\"firstname\", \"lastname\", \"email\"</code> with one student per line.  New students will receive their access instructions by email.', '2004-02-05 10:22:29', ''),\r
+('en', '_template', 'lk_agree', 'Agree', '2004-08-12 15:45:53', ''),\r
+('en', '_template', 'lk_always', 'Always', '2004-08-26 12:23:31', ''),\r
+('en', '_template', 'lk_disagree', 'Disagree', '2004-08-12 15:46:29', ''),\r
+('en', '_template', 'lk_excellent', 'Excellent', '2004-08-12 15:42:09', ''),\r
+('en', '_template', 'lk_fair', 'Fair', '2004-08-12 15:43:07', ''),\r
+('en', '_template', 'lk_good', 'Good', '2004-08-12 15:42:50', ''),\r
+('en', '_template', 'lk_important', 'Important', '2004-08-26 12:26:09', ''),\r
+('en', '_template', 'lk_little_importance', 'Of Little Importance', '2004-08-26 12:26:41', ''),\r
+('en', '_template', 'lk_mod_important', 'Moderately Important', '2004-08-26 12:26:23', ''),\r
+('en', '_template', 'lk_never', 'Never', '2004-08-26 12:25:30', ''),\r
+('en', '_template', 'lk_occasionally', 'Occasionally', '2004-08-26 12:24:04', ''),\r
+('en', '_template', 'lk_poor', 'Poor', '2004-08-12 15:43:18', ''),\r
+('en', '_template', 'lk_rarely', 'Rarely', '2004-08-26 12:24:21', ''),\r
+('en', '_template', 'lk_strongly_agree', 'Strongly Agree', '2004-08-12 15:45:38', ''),\r
+('en', '_template', 'lk_strongly_disagree', 'Strongly Disagree', '2004-08-12 15:46:46', ''),\r
+('en', '_template', 'lk_undecided', 'Undecided', '2004-08-26 11:46:00', ''),\r
+('en', '_template', 'lk_unimportant', 'Unimportant', '2004-08-26 12:27:06', ''),\r
+('en', '_template', 'lk_very_frequently', 'Very Frequently', '2004-08-26 12:23:46', ''),\r
+('en', '_template', 'lk_very_good', 'Very Good', '2004-08-12 15:42:33', ''),\r
+('en', '_template', 'lk_very_important', 'Very Important', '2004-08-26 12:25:52', ''),\r
+('en', '_template', 'lk_very_poor', 'Very Poor', '2004-08-12 15:43:37', ''),\r
+('en', '_template', 'lk_very_rarely', 'Very Rarely', '2004-08-26 12:24:38', ''),\r
+('en', '_template', 'locale', 'Locale', '2004-11-20 19:35:20', ''),\r
+('en', '_template', 'location', 'Location', '2005-03-04 14:06:25', ''),\r
+('en', '_template', 'lock_no_post', 'No posting, but allow reading.', '2003-05-20 12:46:36', 'forum instructor lock text'),\r
+('en', '_template', 'lock_no_post1', 'This thread is locked from posting.', '2003-05-20 12:46:45', 'forum instructor lock text'),\r
+('en', '_template', 'lock_no_read', 'No posting and no reading.', '2003-05-20 12:46:56', 'context'),\r
+('en', '_template', 'lock_no_read1', 'This thread is locked from reading and posting.', '2003-05-20 12:47:24', 'forum thread display lock message'),\r
+('en', '_template', 'lock_submit', 'Apply Lock', '2003-05-20 12:47:50', 'text for instructor forum lock button'),\r
+('en', '_template', 'lock_thread', 'Lock Thread', '2003-05-20 12:48:14', 'Alt text for forum instructor lock icon'),\r
+('en', '_template', 'logged_in_within', 'logged in within', '2007-02-21 13:37:39', ''),\r
+('en', '_template', 'login', 'Login', '2006-07-27 17:35:30', 'global login label'),\r
+('en', '_template', 'login_into_atutor', 'Log into your ATutor Account', '2003-05-20 12:51:48', 'login after enrollment message'),\r
+('en', '_template', 'login_name', 'Login Name', '2003-05-20 12:52:32', 'control centre account information label'),\r
+('en', '_template', 'login_name_or_email', 'Login Name or Email', '2006-03-28 14:21:34', ''),\r
+('en', '_template', 'login_statistics', '%s login statistics for  %s', '2003-05-31 14:49:29', 'course login details'),\r
+('en', '_template', 'login_text', 'Enter the Login Name and Password you chose when you first registered with the system.', '2005-07-27 15:11:33', ''),\r
+('en', '_template', 'logout', 'Log-out', '2003-05-20 12:53:44', 'global logout link text'),\r
+('en', '_template', 'log_file_bundle', 'Log File Bundle', '2005-03-10 16:36:31', 'error logging - email subject'),\r
+('en', '_template', 'ltr', 'Left to Right', '2004-11-20 19:37:04', ''),\r
+('en', '_template', 'mail_queue_cron', 'You must set-up the <a href=\"admin/cron_config.php\">cron</a> to use this feature.', '2006-04-03 14:21:30', ''),\r
+('en', '_template', 'maintainers', 'Maintainers', '2005-08-16 15:26:57', ''),\r
+('en', '_template', 'main_navigation', 'Main Navigation', '2005-03-07 12:09:31', ''),\r
+('en', '_template', 'male', 'Male', '2003-05-20 12:55:53', 'registration, profile, admin user manager'),\r
+('en', '_template', 'manage', 'Manage', '2005-02-23 12:05:42', ''),\r
+('en', '_template', 'manage_languages', 'Manage Existing Languages', '2004-09-23 16:30:59', ''),\r
+('en', '_template', 'manage_lang_howto', 'Below are all the languages currently available in this installation of ATutor. You may export the language as an ATutor language pack or delete it from the installation.', '2004-10-18 14:23:43', ''),\r
+('en', '_template', 'manage_links', 'Manage Links', '2006-05-24 11:24:51', ''),\r
+('en', '_template', 'mark', 'Mark', '2003-05-20 12:56:19', 'mytests/test manager'),\r
+('en', '_template', 'marked_label', 'Marked (%s)', '2005-05-12 10:25:44', ''),\r
+('en', '_template', 'marks', 'marks', '2003-05-20 12:56:34', 'mytests/test manager'),\r
+('en', '_template', 'mark_alumni', 'Mark Alumni', '2004-10-25 12:24:38', ''),\r
+('en', '_template', 'mark_statistics', 'Submission Statistics', '2004-08-26 13:27:13', ''),\r
+('en', '_template', 'master_list_authentication', 'Authenticate Against A Master Student List', '2005-03-31 13:54:01', ''),\r
+('en', '_template', 'master_not_in_list', 'If existing user not in new list', '2005-05-10 16:04:31', ''),\r
+('en', '_template', 'master_student_list', 'Master Student List', '2005-04-04 10:39:26', ''),\r
+('en', '_template', 'material', 'Material', '2004-10-14 14:10:13', ''),\r
+('en', '_template', 'material_announcements', 'Announcements (%s)', '2004-10-14 14:14:23', ''),\r
+('en', '_template', 'material_content_pages', 'Content Pages (%s)', '2004-10-14 14:12:47', ''),\r
+('en', '_template', 'material_files', 'Files (%s)', '2004-10-14 14:22:54', ''),\r
+('en', '_template', 'material_glossary', 'Glossary (%s)', '2004-10-14 14:22:17', ''),\r
+('en', '_template', 'material_groups', 'Groups (%s)', '2004-11-25 15:43:53', ''),\r
+('en', '_template', 'material_links', 'Links (%1$s categories,  %2$s links)', '2004-10-14 14:18:25', ''),\r
+('en', '_template', 'material_polls', 'Polls (%s)', '2004-10-14 14:21:41', ''),\r
+('en', '_template', 'material_select_all', 'Select All', '2004-10-14 14:11:39', ''),\r
+('en', '_template', 'material_stats', 'Statistics (%s days)', '2004-10-14 14:23:22', ''),\r
+('en', '_template', 'maximum', 'Maximum', '2003-05-20 12:59:01', 'instructor course statistics/details'),\r
+('en', '_template', 'maximum_course_float', 'Maximum Course Float', '2005-03-03 10:52:04', ''),\r
+('en', '_template', 'maximum_course_size', 'Maximum Course Size', '2005-03-03 10:51:52', ''),\r
+('en', '_template', 'maximum_file_size', 'Maximum File Size', '2005-03-03 10:51:39', ''),\r
+('en', '_template', 'max_backups_reached', 'You have reached the maximum number of backups allowed.', '2004-10-15 14:16:57', ''),\r
+('en', '_template', 'max_file_size', 'Max File Size', '2003-05-20 12:59:52', 'admin course manager properties'),\r
+('en', '_template', 'max_file_size_system', 'Maximum system allows', '2003-10-14 14:32:52', 'php\'s max file size'),\r
+('en', '_template', 'mb', '<acronym title=\"Megabyte\">MB</acronym>', '2007-07-26 14:05:45', 'short for MB (megabytes)'),\r
+('en', '_template', 'media', 'Media', '2007-06-15 14:41:08', ''),\r
+('en', '_template', 'members', 'Members', '2003-05-20 13:00:39', 'instructor course statistics/details'),\r
+('en', '_template', 'member_id', 'Member ID', '2003-05-20 13:01:18', 'admin user manager column heading'),\r
+('en', '_template', 'member_stats', 'Student Specific Usage', '2005-03-03 15:25:57', ''),\r
+('en', '_template', 'menu', 'Menu', '2003-05-20 13:02:17', 'preferences option'),\r
+('en', '_template', 'menu_menu', 'Content Navigation', '2005-03-30 10:13:27', 'context (?)'),\r
+('en', '_template', 'message', 'Message', '2003-05-20 13:06:56', 'inbox send message screen'),\r
+('en', '_template', 'message_notification', 'Message Notification', '2005-03-14 15:31:15', 'preferences'),\r
+('en', '_template', 'minimum', 'Minimum', '2003-05-20 13:08:57', 'instructor course statistics/details'),\r
+('en', '_template', 'minutes', '%s min.', '2006-03-31 15:41:57', ''),\r
+('en', '_template', 'minute_short', 'm', '2007-07-09 12:31:14', ''),\r
+('en', '_template', 'missing', 'Missing', '2005-10-05 14:02:53', ''),\r
+('en', '_template', 'missing_content', 'Missing Content', '2005-03-07 15:25:10', ''),\r
+('en', '_template', 'missing_info', 'Missing Info', '2005-08-17 13:23:48', ''),\r
+('en', '_template', 'modules', 'Modules', '2005-08-16 13:40:42', ''),\r
+('en', '_template', 'module_install_directory', 'The following directory must be created for this module to install and function: <kbd>%s</kbd>.', '2005-09-22 14:14:34', ''),\r
+('en', '_template', 'module_name', 'Module Name', '2005-08-17 13:11:29', ''),\r
+('en', '_template', 'month', 'Month', '2004-06-24 15:45:43', ''),\r
+('en', '_template', 'more_options', 'More options...', '2007-02-21 11:48:54', ''),\r
+('en', '_template', 'move', 'Move', '2004-01-15 13:31:18', 'editing content'),\r
+('en', '_template', 'move_down', 'Move Down', '2005-03-30 15:54:20', 'modules'),\r
+('en', '_template', 'move_thread', 'Move Thread', '2006-09-06 13:14:56', ''),\r
+('en', '_template', 'move_thread_to', 'Move thread to:', '2006-09-06 13:15:17', ''),\r
+('en', '_template', 'move_to_inbox', 'Move to Inbox', '2007-02-22 13:09:26', ''),\r
+('en', '_template', 'move_up', 'Move Up', '2005-08-02 15:44:46', 'modules'),\r
+('en', '_template', 'mysql_version', 'MySQL Version', '2007-07-26 13:40:50', ''),\r
+('en', '_template', 'my_account', 'My Account', '2005-03-28 14:04:37', ''),\r
+('en', '_template', 'my_courses', 'My Courses', '2004-04-15 12:05:31', ''),\r
+('en', '_template', 'my_enrolled_courses', 'My enrolled courses', '2004-08-18 12:03:04', ''),\r
+('en', '_template', 'my_files', 'My Files', '2006-03-20 14:40:42', ''),\r
+('en', '_template', 'my_start_page', 'My Start Page', '2005-02-08 10:58:06', ''),\r
+('en', '_template', 'my_tests', 'Tests &amp; Surveys', '2005-03-09 14:52:51', ''),\r
+('en', '_template', 'my_tracker', 'My Tracker', '2003-05-20 13:12:27', 'global my tracker  heading'),\r
+('en', '_template', 'na', 'N/A', '2003-05-20 13:12:48', 'short form for \"not applicable\"'),\r
+('en', '_template', 'name', 'Name', '2003-05-20 13:31:04', 'file manager, zip utility column heading'),\r
+('en', '_template', 'name_in_english', 'Language name in English', '2004-11-20 19:41:16', 'admin add language'),\r
+('en', '_template', 'name_in_language', 'Language name translated', '2004-11-20 19:39:49', ''),\r
+('en', '_template', 'nav_path', 'Navigation Path for User', '2003-05-20 13:31:22', 'tracker'),\r
+('en', '_template', 'nav_tendencies', 'Navigation Tendencies for User', '2003-05-20 13:32:03', 'tracker'),\r
+('en', '_template', 'never', 'Never', '2005-03-03 11:03:01', ''),\r
+('en', '_template', 'new', 'New!', '2003-05-20 13:32:52', 'forum/inbox new message indicator'),\r
+('en', '_template', 'new_account_enroll', 'A user account has been created for you at %1s and you have been enrolled into the course %2s. To access this course, please log into the site. It is strongly suggested you change your password upon logging in.', '2005-06-24 15:33:45', 'Message emailed to new users as a result of enrollment.'),\r
+('en', '_template', 'new_account_enroll_confirm', 'You have been enrolled into the course %1s. To access this course, you must first confirm your account by using the following link: %2s. It is strongly suggested you change your password upon logging in.', '2005-06-24 15:33:17', 'If new user created during enrollment and needs confirmation.'),\r
+('en', '_template', 'new_file', 'New File', '2006-03-20 14:36:14', ''),\r
+('en', '_template', 'new_name', 'New Name', '2005-03-07 13:26:12', 'filemanager rename file'),\r
+('en', '_template', 'new_thread', 'New Thread', '2003-05-20 13:37:34', 'forum'),\r
+('en', '_template', 'new_type', 'New Type:', '2006-03-22 15:11:48', ''),\r
+('en', '_template', 'new_user', 'New User', '2005-07-27 15:06:36', ''),\r
+('en', '_template', 'new_window', 'Links open in a new window.', '2005-10-28 12:24:51', ''),\r
+('en', '_template', 'next', 'Next', '2003-05-20 13:38:07', 'sequence arrow link text'),\r
+('en', '_template', 'next_topic', 'Next Topic', '2003-05-20 13:38:42', 'sequence arrow link text'),\r
+('en', '_template', 'no', 'No', '2005-03-03 10:18:39', 'the word no, preferences, admin course manager'),\r
+('en', '_template', 'none', 'None', '2003-05-20 13:40:59', 'global message when no results were retrieved'),\r
+('en', '_template', 'none_available', 'None available.', '2003-05-20 13:41:46', 'instructor add/edit content, glossary'),\r
+('en', '_template', 'none_found', 'None Found.', '2005-05-18 13:12:47', 'glossary, related topis, users online'),\r
+('en', '_template', 'non_group_members', 'Non-Group Members', '2005-06-10 10:51:55', ''),\r
+('en', '_template', 'notes', 'Notes', '2003-05-20 13:43:39', 'admin hime, instructor request notes column heading'),\r
+('en', '_template', 'notification_new_inbox', 'You have received a new message from %s. Login to access your inbox and view the message. Login at: %s', '2005-05-17 14:20:35', 'notification message for new mail in inbox'),\r
+('en', '_template', 'notify', 'Notify', '2003-05-20 13:45:17', 'admin course properties'),\r
+('en', '_template', 'not_created', 'Not Created', '2005-05-10 15:23:30', ''),\r
+('en', '_template', 'not_editable', 'Not editable.', '2006-03-20 15:17:50', ''),\r
+('en', '_template', 'not_enrolled', 'Not Enrolled', '2005-03-23 14:23:18', 'user status on my courses page'),\r
+('en', '_template', 'not_specified', 'Not specified', '2003-05-12 15:26:26', 'registration gender selection'),\r
+('en', '_template', 'no_announcements', 'No Announcements Found', '2003-05-20 13:55:19', 'course homepage when no announcments exist'),\r
+('en', '_template', 'no_content_avail', 'No content available.', '2005-10-20 11:00:59', ''),\r
+('en', '_template', 'no_courses', 'There are no available courses.', '2003-05-20 13:57:26', 'browse message when no courses exist'),\r
+('en', '_template', 'no_courses_found', 'No courses found.', '2003-05-20 13:58:31', 'message when query resuylt in no courses found, admin course manager'),\r
+('en', '_template', 'no_course_found', 'Course not found.', '2003-10-15 14:31:39', 'course not found'),\r
+('en', '_template', 'no_description', 'No description available.', '2004-08-20 15:00:55', ''),\r
+('en', '_template', 'no_due_date', 'No due date', '2006-05-30 12:37:39', ''),\r
+('en', '_template', 'no_end_date', 'No end date', '2007-07-16 14:27:07', ''),\r
+('en', '_template', 'no_forums', 'No Forums Found', '2003-05-20 13:59:58', 'discussions message when no forums exist'),\r
+('en', '_template', 'no_glossary_items', 'No glossary terms found.', '2005-03-07 10:52:11', 'edit glossary'),\r
+('en', '_template', 'no_icon', 'No Icon', '2005-03-03 11:20:05', ''),\r
+('en', '_template', 'no_month_data', 'There is no data for this month.', '2003-05-20 14:01:42', 'instructor course statistics when nonne exist'),\r
+('en', '_template', 'no_post', 'No post found.', '2003-05-20 14:02:44', 'forums message when attempting to view a post that no longer exists'),\r
+('en', '_template', 'no_questions', 'No questions found.', '2003-05-20 14:04:01', 'test manager message when no questions exist for a test.'),\r
+('en', '_template', 'no_results_available', 'No Results Available', '2003-05-20 14:07:22', 'test manager'),\r
+('en', '_template', 'no_results_yet', 'No Results Yet', '2003-05-20 14:07:32', 'my tests'),\r
+('en', '_template', 'no_terms_found', 'There are no glossary terms being used in this content page.', '2004-01-16 10:52:51', 'content editor'),\r
+('en', '_template', 'no_tests', 'No Tests or Surveys Available', '2004-08-25 14:04:15', ''),\r
+('en', '_template', 'no_title', 'No title.', '2005-10-20 11:00:45', ''),\r
+('en', '_template', 'no_user_found', 'No user found', '2003-05-20 14:09:41', 'admin user amanager, profile'),\r
+('en', '_template', 'num', 'No.', '2003-05-20 14:10:36', 'short form for the word number, test manager'),\r
+('en', '_template', 'number_of_groups', 'Number of Groups', '2006-03-22 11:48:03', ''),\r
+('en', '_template', 'number_of_students_per_group', 'Number of Students per Group', '2006-03-22 11:52:10', ''),\r
+('en', '_template', 'num_pages', '# pages', '2005-03-16 13:54:47', 'content manager'),\r
+('en', '_template', 'num_posts', 'Number of Posts', '2005-04-14 11:07:00', ''),\r
+('en', '_template', 'num_questions_per_test', 'questions per test.', '2004-08-23 16:13:24', ''),\r
+('en', '_template', 'num_students_currently_enrolled', 'There are <em>%s</em> students currently enrolled in this course.', '2006-03-22 13:02:01', ''),\r
+('en', '_template', 'num_takes_test', 'Attempts Allowed', '2004-08-26 10:34:04', ''),\r
+('en', '_template', 'num_threads', 'Number of Threads', '2005-04-14 11:07:33', ''),\r
+('en', '_template', 'ok', 'OK', '2004-01-30 11:54:41', ''),\r
+('en', '_template', 'on', 'on', '2003-05-20 14:11:28', 'admin course manager properties tracking option'),\r
+('en', '_template', 'one_page', 'One Page', '2003-05-20 14:12:22', 'test manager open ended question type'),\r
+('en', '_template', 'one_question_per_page', 'One question per page', '2007-08-20 15:46:36', 'edit/create test'),\r
+('en', '_template', 'one_sentence', 'One Sentence', '2003-05-20 14:12:46', 'test manager open ended question type'),\r
+('en', '_template', 'one_word', 'One Word', '2003-05-20 14:12:53', 'test manager open ended question type'),\r
+('en', '_template', 'ongoing', 'On Going!', '2003-05-20 14:13:23', 'mytest currently running test indicator'),\r
+('en', '_template', 'online_status', 'Online Status', '2005-03-11 16:18:30', 'directory'),\r
+('en', '_template', 'only_show_edited_terms', 'Only show edit terms.', '2006-09-25 13:08:06', 'language editor filter form'),\r
+('en', '_template', 'open_file_manager', 'Open File Manager', '2004-11-25 17:31:08', ''),\r
+('en', '_template', 'optional', 'Optional', '2003-05-20 14:40:09', 'registration screen'),\r
+('en', '_template', 'optional_description', 'Optional Description', '2004-10-27 15:31:07', ''),\r
+('en', '_template', 'optional_feedback', 'Optional Feedback', '2004-11-24 14:33:15', ''),\r
+('en', '_template', 'option_alignment', 'Alignment', '2004-12-01 13:36:36', 'edit/create option in test questions'),\r
+('en', '_template', 'or', 'Or', '2003-05-20 14:40:26', 'global word or'),\r
+('en', '_template', 'orange', 'Orange', '2003-05-20 14:40:40', 'global code picker'),\r
+('en', '_template', 'order', 'Order', '2005-03-04 14:07:25', ''),\r
+('en', '_template', 'original_term', 'Original term', '2006-09-25 13:09:48', ''),\r
+('en', '_template', 'origin_page', 'Originating Page', '2003-05-20 14:40:57', 'tracker'),\r
+('en', '_template', 'or_groups', 'Or, Groups:', '2006-08-28 15:58:14', ''),\r
+('en', '_template', 'os', '<acronym title=\"Operating System\">OS</acronym>', '2007-07-26 14:04:11', ''),\r
+('en', '_template', 'other', 'Other', '2005-03-03 12:17:32', ''),\r
+('en', '_template', 'out_of', 'Out of', '2003-05-20 14:42:22', 'mytests, score out of ...'),\r
+('en', '_template', 'override', 'Override selections with this course\'s custom Colour & Font theme.  <small class=\"spacer\">( If available. )</small>', '2003-05-20 14:42:37', 'preferences page'),\r
+('en', '_template', 'overwite_content', 'Overwrite existing material with those selected', '2004-10-15 14:18:47', ''),\r
+('en', '_template', 'overwrite', 'Overwrite', '2004-11-09 15:24:23', 'file manager'),\r
+('en', '_template', 'overwrite_master', 'If an existing account is using this Student ID, overwrite association with new account.', '2006-06-12 13:58:31', ''),\r
+('en', '_template', 'packaged_in', 'Content Package', '2003-10-07 18:21:34', 'apckage label in edit content'),\r
+('en', '_template', 'packages', 'Packages', '2005-05-17 12:09:25', ''),\r
+('en', '_template', 'packages_auto_advance', 'Automatically start next Learning Object', '2005-05-17 12:10:27', ''),\r
+('en', '_template', 'package_settings', 'Package Settings', '2005-05-17 12:06:33', ''),\r
+('en', '_template', 'package_type', 'Package Type', '2005-05-17 12:09:36', ''),\r
+('en', '_template', 'package_type_info', 'Please select the type of package you wish to upload.', '2005-05-17 12:07:10', ''),\r
+('en', '_template', 'package_upload_file', 'Package File', '2005-05-17 12:07:32', ''),\r
+('en', '_template', 'package_upload_file_info', 'Select the package file from your computer', '2005-05-17 12:07:20', ''),\r
+('en', '_template', 'package_upload_url', 'Package URL', '2005-05-17 12:06:58', ''),\r
+('en', '_template', 'package_upload_url_info', 'or specify the URL to your web accessible package file', '2005-05-17 12:06:47', ''),\r
+('en', '_template', 'page', 'Page', '2003-05-20 14:43:17', 'forum thread pages menu, tracker pages menu'),\r
+('en', '_template', 'pages_found', '%s pages found', '2004-08-20 15:09:44', ''),\r
+('en', '_template', 'pages_stats', 'Page Tracking Statistics for %s.', '2003-06-08 09:20:38', 'tracker'),\r
+('en', '_template', 'page_error', 'An error occured while generating the paginator', '2003-05-20 14:44:01', 'tracker'),\r
+('en', '_template', 'page_info', 'Last Modified: %s.  Revision: %s.  Release Date: %s.', '2004-02-12 11:27:02', ''),\r
+('en', '_template', 'page_stats', 'Content Tracking Summary', '2003-05-20 14:44:48', 'tracker'),\r
+('en', '_template', 'page_title', 'Page Title', '2003-05-20 14:45:16', 'tracker column heading'),\r
+('en', '_template', 'page_viewed', 'Page Viewed', '2003-05-20 14:45:44', 'tracker'),\r
+('en', '_template', 'parent', 'Parent', '2005-03-29 13:04:13', 'categories'),\r
+('en', '_template', 'password', 'Password', '2003-05-20 14:45:56', 'global password word'),\r
+('en', '_template', 'password_again', 'Password Again', '2003-05-20 14:46:52', 'registration, edit profile'),\r
+('en', '_template', 'password_blurb', 'Enter your account\'s email address below and an email with instructions on retrieving your password will be sent to you. The email address must be the same as the one you used for\r\nregistration.', '2006-06-08 11:20:16', ''),\r
+('en', '_template', 'password_changed', 'Password Change', '2005-11-30 13:54:49', ''),\r
+('en', '_template', 'password_change_confirm', 'Your password on %s has been changed successfully. Go to %s to login.', '2006-05-09 15:28:37', ''),\r
+('en', '_template', 'password_change_msg', 'Your password has been altered. Please use the information below.', '2005-11-30 13:55:47', ''),\r
+('en', '_template', 'password_forgot', 'Forgot Password', '2006-05-09 15:00:16', ''),\r
+('en', '_template', 'password_new_blurb', 'Enter a new password for your account.', '2006-05-09 15:54:44', ''),\r
+('en', '_template', 'password_old', 'Old Password', '2006-05-11 11:34:39', ''),\r
+('en', '_template', 'password_reminder', 'Forgot your password?', '2006-05-09 14:29:49', 'password reminder screen heading, public login header'),\r
+('en', '_template', 'password_reminder_text', 'If you have lost your password, use the forgotten password feature to regain access to your account.', '2006-05-09 14:56:46', ''),\r
+('en', '_template', 'password_request2', 'Dear %1$s,\r\n\r\nYour login name is %1$s.\r\n\r\nTo regain access to your ATutor account on %2$s, follow the link below. The link will become invalid after %3$s days.\r\n\r\n%4$s\r\n(If this link does not take you to the site, copy and paste it into the addres bar of your internet browser)', '2006-06-21 10:38:52', 'password reminder'),\r
+('en', '_template', 'paste', 'Paste', '2004-12-03 10:30:28', 'form_editor in create question'),\r
+('en', '_template', 'paste_file', 'Paste From File', '2003-05-20 14:49:35', 'instructor content editor'),\r
+('en', '_template', 'pending', 'Pending', '2003-05-20 14:50:41', 'mytests, control centre'),\r
+('en', '_template', 'pending_approval', '(pending approval)', '2003-05-20 14:51:49', 'control centre'),\r
+('en', '_template', 'pending_enrollment', 'Pending Enrollment', '2005-06-10 10:14:46', ''),\r
+('en', '_template', 'period', 'Period', '2004-06-22 12:09:54', ''),\r
+('en', '_template', 'personal_information', 'Personal Information', '2003-05-20 14:53:12', 'registration, profile edit'),\r
+('en', '_template', 'per_day', 'per day', '2003-05-20 14:54:04', 'instructor course statistics, details'),\r
+('en', '_template', 'phone', 'Telephone Number', '2006-11-23 11:33:30', 'global phone number field label'),\r
+('en', '_template', 'php_version', 'PHP Version', '2007-07-26 13:40:22', ''),\r
+('en', '_template', 'picture', 'Picture', '2007-02-26 17:22:49', ''),\r
+('en', '_template', 'plain_text', 'Plain Text', '2006-11-23 13:16:30', 'instructor content editor, news, inbox, forum message format'),\r
+('en', '_template', 'points', 'Points', '2007-03-05 15:51:38', ''),\r
+('en', '_template', 'poll', 'Poll', '2004-06-25 13:17:51', ''),\r
+('en', '_template', 'polls', 'Polls', '2004-06-14 13:55:42', ''),\r
+('en', '_template', 'post', 'Post', '2003-05-20 14:56:13', 'forum new thread post button'),\r
+('en', '_template', 'postal_code', 'Postal/Zip Code', '2003-05-20 14:56:34', 'global postal code filed labal'),\r
+('en', '_template', 'posted_by', 'By', '2003-05-20 14:57:31', 'forum message submitter'),\r
+('en', '_template', 'posted_on', 'on', '2003-05-20 14:58:10', 'forum message post date, inbox'),\r
+('en', '_template', 'posts', 'Forum Threads', '2005-03-07 13:37:56', 'Header for posts in Forum List'),\r
+('en', '_template', 'post_lock', 'Locked from posting', '2003-05-20 14:58:32', 'forum lock thread message'),\r
+('en', '_template', 'powered_by_google', 'Results by <a href=\"http://www.google.com\">Google</a>.', '2005-10-20 10:52:51', ''),\r
+('en', '_template', 'preferences', 'Preferences', '2003-05-20 14:59:08', 'global preferences word'),\r
+('en', '_template', 'presets', 'Presets', '2004-08-24 11:56:35', ''),\r
+('en', '_template', 'preset_scales', 'Preset &amp; Previously Used Scales', '2004-08-24 13:48:44', ''),\r
+('en', '_template', 'preview', 'Preview', '2003-05-20 14:59:52', 'test manager preview test'),\r
+('en', '_template', 'preview_questions', 'Preview Questions', '2005-06-21 14:06:13', ''),\r
+('en', '_template', 'previous', 'Previous', '2003-05-20 15:01:31', 'global sequence arrow alt/link text'),\r
+('en', '_template', 'previous_posts', 'Previous Posts', '2006-06-14 10:47:00', ''),\r
+('en', '_template', 'previous_topic', 'Previous Topic', '2003-05-20 15:02:06', 'global sequence arrow alt/link text'),\r
+('en', '_template', 'prev_used', 'Previously Used', '2004-08-13 13:29:47', ''),\r
+('en', '_template', 'primary_language', 'Primary Language', '2004-07-05 15:12:57', ''),\r
+('en', '_template', 'private', 'Private', '2003-05-20 15:03:14', 'global private course indicator'),\r
+('en', '_template', 'private_enroll', 'The course you are trying to access is <strong>private</strong>. Enrollment in this course requires instructor approval.<br />', '2005-03-17 11:51:06', 'requesting enrollment in private course'),\r
+('en', '_template', 'privileges', 'Privileges', '2004-03-05 12:29:02', ''),\r
+('en', '_template', 'priv_ac_access_all', 'ACollab: Access all Groups', '2005-08-10 15:21:20', ''),\r
+('en', '_template', 'priv_ac_create', 'ACollab: Create Group', '2005-08-10 15:20:47', ''),\r
+('en', '_template', 'priv_admin_super', 'Super Administrator', '2005-03-03 10:36:48', ''),\r
+('en', '_template', 'priv_admin_themes', 'Themes', '2005-03-03 10:38:07', ''),\r
+('en', '_template', 'priv_forums', 'Forums & Chat', '2004-03-08 10:04:06', ''),\r
+('en', '_template', 'priv_test_create', 'Test Creation', '2005-08-10 15:20:29', ''),\r
+('en', '_template', 'priv_test_mark', 'Test Marking', '2005-08-10 15:22:12', ''),\r
+('en', '_template', 'profile', 'Profile', '2003-05-20 16:24:30', 'control centre heading'),\r
+('en', '_template', 'profile_bundle_select', 'Profile Bundle Selection', '2004-12-06 12:13:34', ''),\r
+('en', '_template', 'profile_pictures', 'Profile Pictures', '2007-02-27 13:43:00', ''),\r
+('en', '_template', 'profile_student_information', 'Student Information', '2003-09-16 11:49:35', 'view profile'),\r
+('en', '_template', 'properties', 'Properties', '2003-05-21 12:15:58', 'instructor control centre'),\r
+('en', '_template', 'protected', 'Protected', '2003-05-21 12:16:46', 'browse, create coruse, control centre, course properties'),\r
+('en', '_template', 'province', 'Province/State', '2003-05-21 12:17:22', 'registration, profile editor'),\r
+('en', '_template', 'public', 'Public', '2003-05-21 12:18:37', 'browse courses, create course, course properties, control centre'),\r
+('en', '_template', 'purple', 'Purple', '2003-05-21 12:18:50', 'global code picker'),\r
+('en', '_template', 'put_link', 'put link name here', '2004-12-08 12:38:42', 'filemanager, isert text'),\r
+('en', '_template', 'question', 'Question', '2003-05-21 12:30:21', 'test manager'),\r
+('en', '_template', 'questions', 'Questions', '2003-05-21 12:30:40', 'test manager'),\r
+('en', '_template', 'questions_for', 'Questions for', '2003-05-21 12:30:50', 'test manager'),\r
+('en', '_template', 'question_categories', 'Question Categories', '2005-02-22 14:17:33', ''),\r
+('en', '_template', 'question_database', 'Question Database', '2004-11-24 10:14:16', ''),\r
+('en', '_template', 'question_statistics', 'Question Statistics', '2004-08-26 13:26:17', ''),\r
+('en', '_template', 'quote', 'Quote', '2003-05-21 12:31:19', 'code picker alt text'),\r
+('en', '_template', 'randomize_questions', 'Randomize Questions', '2004-05-18 10:44:48', ''),\r
+('en', '_template', 'raw', 'Raw', '2003-09-13 09:25:20', 'course tracker member picker'),\r
+('en', '_template', 'raw_data', 'Raw Data', '2003-05-21 12:31:48', 'instructor course statistics/details'),\r
+('en', '_template', 're', 'Re', '2007-02-20 16:20:00', ''),\r
+('en', '_template', 'reading_list', 'Reading List', '2006-05-09 14:19:55', ''),\r
+('en', '_template', 'read_lock', 'Locked from posting & reading', '2003-05-21 12:32:39', 'forum lock message in thread list'),\r
+('en', '_template', 'real_name', 'Real Name', '2003-10-20 11:33:14', 'course properties'),\r
+('en', '_template', 'recipient_address', 'Recipient Address', '2004-12-06 12:20:03', 'admin/error_logging_bundle.php'),\r
+('en', '_template', 'red', 'Red', '2003-05-21 12:32:57', 'global code picker'),\r
+('en', '_template', 'red_members', 'Red = Members', '2003-05-21 12:33:55', 'instructor course statistics/details'),\r
+('en', '_template', 'regenerate', 'Regenerate', '2007-02-16 14:00:06', ''),\r
+('en', '_template', 'register', 'Register', '2003-11-26 15:09:00', ''),\r
+('en', '_template', 'register_an_account', 'Register an ATutor System Account', '2003-05-21 12:36:01', 'private course enrolment screen, login screen'),\r
+('en', '_template', 'registration_text', 'If you do not have an account on this system,  please create a new account by clicking on the Register Button below.', '2005-07-27 15:11:59', ''),\r
+('en', '_template', 'reg_exp', 'Regular Expression', '2004-11-20 19:38:23', ''),\r
+('en', '_template', 'related_topics', 'Related Topics', '2003-05-21 12:38:26', 'context(?)'),\r
+('en', '_template', 'release_date', 'Release Date', '2003-05-21 12:39:24', 'instructor add/edit content, control centre'),\r
+('en', '_template', 'release_immediate', 'Once quiz has been submitted', '2004-12-13 13:55:49', ''),\r
+('en', '_template', 'release_marked', 'Once quiz has been submitted and all questions have been marked', '2004-12-13 13:55:57', ''),\r
+('en', '_template', 'release_never', 'Do not release results', '2004-12-13 14:02:13', ''),\r
+('en', '_template', 'release_on', 'Release on', '2006-04-10 14:37:58', ''),\r
+('en', '_template', 'remove', 'Remove', '2003-05-21 12:40:11', 'control centre, admin user manager, instructor enrolment manager'),\r
+('en', '_template', 'removed', 'Removed', '2004-02-03 09:36:19', ''),\r
+('en', '_template', 'remove_frame', 'Remove Frame', '2005-01-10 14:31:34', 'filemanager preview'),\r
+('en', '_template', 'remove_question', 'Remove Question', '2004-11-25 10:30:59', ''),\r
+('en', '_template', 'rename', 'Rename', '2004-08-11 14:00:49', ''),\r
+('en', '_template', 'replace_into', 'Replace Into', '2005-03-03 12:16:28', ''),\r
+('en', '_template', 'replied', 'Replied', '2003-05-21 12:40:35', 'inbox message status label'),\r
+('en', '_template', 'replies', 'Replies', '2003-05-21 12:40:50', 'forum'),\r
+('en', '_template', 'reply', 'Reply', '2003-05-21 12:41:20', 'forum, inbox'),\r
+('en', '_template', 'report_errors', 'Report Errors', '2004-12-06 12:08:05', ''),\r
+('en', '_template', 'request_enrollment', 'Request Enrollment', '2003-10-21 13:04:17', ''),\r
+('en', '_template', 'request_instructor', 'You do not yet have permission to create courses. If you would like an instructor account, enter the required description of the course you wish to create.', '2005-03-09 12:22:12', ''),\r
+('en', '_template', 'request_instructor_account', 'Request Instructor Account', '2003-05-21 12:43:12', 'control centre non-instructor'),\r
+('en', '_template', 'request_instructor_pending', 'Your instructor account request has been made. You will be notifed by email when your request has been approved.', '2005-03-09 12:35:15', ''),\r
+('en', '_template', 'required', 'Required', '2003-05-21 12:43:54', 'registration, export course, test manager question editor'),\r
+('en', '_template', 'required_field', 'Required Field', '2005-03-04 12:52:17', ''),\r
+('en', '_template', 'required_information', 'Required Information', '2005-03-04 14:08:38', ''),\r
+('en', '_template', 'require_email_confirmation', 'Require Email Confirmation Upon Registration', '2005-03-22 10:55:04', ''),\r
+('en', '_template', 'req_message9', 'ATutor Instructor Request', '2003-05-21 18:52:38', 'email message subject line from control centre instructor request'),\r
+('en', '_template', 'req_message_instructor', 'A new Instructor account request has been made by: %s.\r\n\r\nCourse Description: %s\r\n\r\nYou must login as the administrator at %s to approve or reject this request.', '2004-02-16 16:38:30', ''),\r
+('en', '_template', 'reset', 'Reset', '2003-05-21 18:53:27', 'global text for reset buttons'),\r
+('en', '_template', 'reset_filter', 'Reset Filter', '2005-03-30 14:52:42', ''),\r
+('en', '_template', 'reset_log', 'Reset Log', '2005-03-03 10:42:24', ''),\r
+('en', '_template', 'resource_categories', 'Resource Categories', '2003-05-21 18:57:43', 'instructor export course feedback'),\r
+('en', '_template', 'resource_links', 'Resource Links', '2003-05-21 18:58:34', 'instructor export course feedback'),\r
+('en', '_template', 'response_text', 'The following answers were given in response to:', '2004-08-25 12:20:59', ''),\r
+('en', '_template', 'restore', 'Restore', '2003-05-21 18:59:34', 'preferences page (removed 1.2)'),\r
+('en', '_template', 'restore_backup_about', 'Choose the checkboxes next to the content to be restored, select course into which to restore the content, then choose to append the content to the course, or replace the content in the course.', '2004-12-10 09:53:40', ''),\r
+('en', '_template', 'restore_upload', 'To upload a backup file, enter a description of the backup, choose a file to upload, and use the \"Upload\" button. Only backups created using ATutor 1.3 and later are supported. Depending on the size of the course and your Internet connection speed,  uploading a backup may take a long time.', '2004-12-10 18:06:04', ''),\r
+('en', '_template', 'resubmit', 'Resubmit', '2004-01-30 16:34:56', ''),\r
+('en', '_template', 'result', 'Result', '2004-08-12 15:22:08', 'single result in search engine'),\r
+('en', '_template', 'results', 'Results', '2003-05-21 19:00:51', 'test manager'),\r
+('en', '_template', 'results_found', 'Results Found: %s', '2005-04-14 11:01:25', ''),\r
+('en', '_template', 'results_from', 'Results from %s', '2004-08-18 12:05:27', ''),\r
+('en', '_template', 'result_release', 'Release Results', '2004-12-13 13:57:31', ''),\r
+('en', '_template', 'resume', 'Resume', '2003-05-21 19:01:48', 'alt/link text for the resume arrow'),\r
+('en', '_template', 'return', 'Return', '2003-05-21 19:02:25', 'escape from delete course function'),\r
+('en', '_template', 'return_file_manager', 'Return to the File Manager', '2004-11-05 11:20:30', 'file manager'),\r
+('en', '_template', 'return_to_admin_area', 'Return to Admin Area', '2006-03-28 12:31:38', ''),\r
+('en', '_template', 'revision', 'Revision', '2003-05-21 19:04:01', 'instructor content editor statistics below embedded links'),\r
+('en', '_template', 'revisions', 'Revisions', '2006-03-20 14:36:35', ''),\r
+('en', '_template', 'revision_comment', 'Revisions Comment', '2006-03-20 14:37:58', ''),\r
+('en', '_template', 'right', 'Right', '2004-04-27 11:00:46', ''),\r
+('en', '_template', 'rl_add_av_material_to_resources', 'Add AV Material To Resources', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_add_resource_av', 'Add Resource AV', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_add_resource_book', 'Add Resource Book', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_add_resource_file', 'Add Resource File', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_add_resource_handout', 'Add Resource Handout', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_add_resource_url', 'Add Resource URL', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_av', 'AV', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_av_material_to_view', 'AV Material to View', '2006-04-13 12:18:36', ''),\r
+('en', '_template', 'rl_book', 'book', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_book_to_read', 'Book To Read', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_create_new_av', 'Create New AV', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_create_new_book', 'Create New Book', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_create_new_file', 'Create New File', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_create_new_handout', 'Create New Handout', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_create_new_url', 'Create New URL', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_date_format', '%%M %%d, %%Y', '2006-06-26 16:10:05', ''),\r
+('en', '_template', 'rl_delete_reading', 'Delete Reading', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_delete_resource', 'Delete Resource', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_display_resource', 'Display Resource', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_display_resources', 'Resources', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_edit_reading_av', 'Edit Reading AV', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_edit_reading_book', 'Edit Reading Book', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_edit_reading_file', 'Edit Reading File', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_edit_reading_handout', 'Edit Reading Handout', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_edit_reading_url', 'Edit Reading URL', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_edit_resource_av', 'Edit Resource', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_edit_resource_book', 'Edit Resource Book', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_edit_resource_file', 'Edit Resource File', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_edit_resource_handout', 'Edit Resource Handout', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_edit_resource_url', 'Edit Resource URL', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_end', 'End', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_file', 'file', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_goto_url', 'view page', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_handout', 'handout', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_isbn_number', 'ISBN', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_name_reading', 'Name Of Reading', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_new_reading_av', 'New Reading AV', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_new_reading_book', 'New Reading Book', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_new_reading_file', 'New Reading File', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_new_reading_handout', 'New Reading Handout', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_new_reading_url', 'New Reading URL', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_no_read_by_date', 'No Read By Date', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_optional_reading', 'Optional Reading', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_or', 'or', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_pages', 'Pages', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_publisher', 'Publisher', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_reading_date', 'Reading Date', '2006-02-23 09:18:51', ''),\r
+('en', '_template', 'rl_read_by_date', 'Read by Date', '2006-04-13 10:58:30', ''),\r
+('en', '_template', 'rl_select_book', 'Select Book', '2006-07-25 09:08:20', ''),\r
+('en', '_template', 'rl_select_file', 'Select File', '2006-07-25 09:15:44', ''),\r
+('en', '_template', 'rl_select_handout', 'Select Handout', '2006-07-25 09:13:13', ''),\r
+('en', '_template', 'rl_select_url', 'Select URL', '2006-07-25 09:12:21', ''),\r
+('en', '_template', 'rl_start', 'Start', '2006-06-21 08:53:43', ''),\r
+('en', '_template', 'rl_type_of_reading', 'Type of Reading', '2006-07-31 15:23:22', ''),\r
+('en', '_template', 'rl_type_of_resource', 'Type of Resource', '2006-07-14 10:24:21', ''),\r
+('en', '_template', 'rl_url', 'URL', '2007-08-02 10:46:30', 'resource type picker'),\r
+('en', '_template', 'rl_year_written', 'Year Written', '2006-06-21 08:55:34', ''),\r
+('en', '_template', 'role', 'Role', '2004-03-05 12:26:47', ''),\r
+('en', '_template', 'rss_feeds', 'Syndicated Feeds', '2005-10-28 11:07:06', ''),\r
+('en', '_template', 'rtl', 'Right to Left', '2004-11-20 19:37:58', ''),\r
+('en', '_template', 'same_course_users', 'Only users in the same courses as you are listed.', '2003-05-21 19:05:32', 'inbox send message form'),\r
+('en', '_template', 'save', 'Save', '2004-10-29 14:57:46', 'file manager'),\r
+('en', '_template', 'save_changes', 'Save Changes', '2004-05-11 10:48:01', ''),\r
+('en', '_template', 'save_changes_saved', 'All changes have been saved.', '2004-02-16 14:06:16', ''),\r
+('en', '_template', 'save_changes_unsaved', 'Unsaved changes have been made.', '2004-02-16 14:04:25', ''),\r
+('en', '_template', 'search', 'Search', '2003-05-21 19:19:30', 'links database'),\r
+('en', '_template', 'search_all_words', 'All words', '2003-08-11 11:22:04', ''),\r
+('en', '_template', 'search_any_word', 'Any word', '2003-08-11 11:22:14', ''),\r
+('en', '_template', 'search_in', 'Search in', '2004-04-30 10:51:57', ''),\r
+('en', '_template', 'search_match', 'Match', '2003-08-11 11:21:50', ''),\r
+('en', '_template', 'search_results', 'Search Results', '2003-05-21 19:21:29', 'links database'),\r
+('en', '_template', 'search_site', 'Only search within <strong>%s</strong>.', '2005-10-20 10:53:28', ''),\r
+('en', '_template', 'search_words', 'Words', '2003-08-11 11:21:36', ''),\r
+('en', '_template', 'second_name', 'Second Name', '2006-03-27 14:53:50', ''),\r
+('en', '_template', 'second_short', 's', '2007-07-09 12:31:07', ''),\r
+('en', '_template', 'section', 'Section', '2005-03-04 14:06:06', ''),\r
+('en', '_template', 'see', 'See', '2003-05-21 19:24:22', 'glossary - \"see\" related terms'),\r
+('en', '_template', 'see_attached', 'See attached.', '2005-03-10 16:37:04', 'error logging - email body'),\r
+('en', '_template', 'select', 'Select', '2007-02-21 13:22:15', ''),\r
+('en', '_template', 'select_all', 'select/unselect all', '2004-10-29 13:25:57', 'file manager and enrollment manager'),\r
+('en', '_template', 'select_av', 'Select Audio/Visual', '2006-07-25 09:14:57', ''),\r
+('en', '_template', 'select_cat', 'Select Category', '2005-02-23 12:23:56', ''),\r
+('en', '_template', 'select_directory', 'Please choose the folder you want to move the selected files to:', '2004-11-30 11:40:08', 'Filamanger, moving a file'),\r
+('en', '_template', 'select_member', 'Select a Member to View', '2003-05-21 19:29:27', 'instructor course tracker'),\r
+('en', '_template', 'select_parent_topic', 'Select parent topic', '2005-03-16 13:37:00', 'content manager'),\r
+('en', '_template', 'select_term_to_edit', 'Select term to edit.', '2006-09-25 13:08:38', ''),\r
+('en', '_template', 'send', 'Send', '2003-05-21 19:31:57', 'global message send button text'),\r
+('en', '_template', 'send_bundle', 'Send Bundle', '2004-12-06 12:16:19', ''),\r
+('en', '_template', 'send_confirmation', 'Enter your email address below and the account confirmation message will be resent.', '2005-03-24 09:57:32', ''),\r
+('en', '_template', 'send_delete', 'Send & Delete', '2003-05-21 19:32:55', 'send a message from the inbox and delete the original'),\r
+('en', '_template', 'send_message', 'Send Message', '2003-05-21 19:34:13', 'inbox send message button text'),\r
+('en', '_template', 'sent_messages', 'Sent Messages', '2007-02-20 16:21:09', ''),\r
+('en', '_template', 'sent_msgs_ttl_text', 'Number of Days to Keep Copied Sent Messages for', '2007-02-20 14:00:45', ''),\r
+('en', '_template', 'sent_via_atutor', 'Sent via an ATutor system at %s', '2003-05-21 20:04:50', 'global email message footer'),\r
+('en', '_template', 'sequence', 'Sequence', '2003-05-21 20:05:50', 'context (removed 1.2)'),\r
+('en', '_template', 'session_end', 'and ended on', '2003-05-21 20:12:12', 'tracker - to be updated ( started on [date] and ended on [date])'),\r
+('en', '_template', 'session_start', 'Session above started on', '2003-05-21 20:11:35', 'tracker (to be updated)'),\r
+('en', '_template', 'set', 'Set', '2003-06-30 17:02:05', 'admin language manager'),\r
+('en', '_template', 'set_default', 'Set as Default', '2004-10-15 15:48:04', 'set as default button in theme manager'),\r
+('en', '_template', 'set_preset', 'Apply Preset', '2003-05-24 10:52:43', 'preferences'),\r
+('en', '_template', 'shared_forums', 'Shared Forums', '2004-11-03 11:18:31', ''),\r
+('en', '_template', 'shortcuts', 'Shortcuts', '2004-04-27 14:57:01', ''),\r
+('en', '_template', 'short_paragraph', 'Short Paragraph', '2003-05-21 20:13:03', 'test manager test type'),\r
+('en', '_template', 'show', 'Show', '2005-03-15 11:37:59', ''),\r
+('en', '_template', 'show_numbers', 'Topic Numbering', '2005-02-09 10:20:54', 'preference option'),\r
+('en', '_template', 'show_raw_tracking', 'Show raw tracking', '2003-11-26 15:19:12', ''),\r
+('en', '_template', 'show_summary_tracking', 'Show summary tracking', '2003-11-26 15:18:39', ''),\r
+('en', '_template', 'side_menu', 'Side Menu', '2005-03-04 14:37:00', ''),\r
+('en', '_template', 'side_menu_text', 'Choose which menu items you would like displayed at the side.', '2005-03-04 15:17:16', ''),\r
+('en', '_template', 'sitemap', 'Site-map', '2003-05-21 20:17:21', 'global site-map text'),\r
+('en', '_template', 'site_name', 'Site Name', '2005-03-03 10:49:59', ''),\r
+('en', '_template', 'size', 'Size', '2003-05-22 13:01:20', 'file manager, zip tool'),\r
+('en', '_template', 'smile_angry', 'angry', '2004-02-12 12:20:44', ''),\r
+('en', '_template', 'smile_confused', 'confused', '2004-02-12 12:21:15', ''),\r
+('en', '_template', 'smile_crazy', 'crazy', '2004-02-12 12:20:59', ''),\r
+('en', '_template', 'smile_evil', 'evil', '2004-02-12 12:20:37', ''),\r
+('en', '_template', 'smile_frown', 'frown', '2004-02-12 12:20:14', ''),\r
+('en', '_template', 'smile_lol', 'laughing out loud', '2004-02-12 12:20:53', ''),\r
+('en', '_template', 'smile_muah', 'muah', '2004-02-12 12:21:23', ''),\r
+('en', '_template', 'smile_oh_well', 'oh well', '2004-02-12 12:20:21', ''),\r
+('en', '_template', 'smile_smile', 'smile', '2004-02-12 12:20:02', ''),\r
+('en', '_template', 'smile_tired', 'tired', '2004-02-12 12:21:06', ''),\r
+('en', '_template', 'smile_tongue', 'tongue', '2004-02-12 12:20:27', ''),\r
+('en', '_template', 'smile_wink', 'wink', '2004-02-12 12:20:08', ''),\r
+('en', '_template', 'specific_groups', 'Specific Groups', '2006-03-23 13:39:26', ''),\r
+('en', '_template', 'specify_url_to_content_package', 'Or, Specify a URL to a Content Package', '2004-04-30 15:33:57', ''),\r
+('en', '_template', 'specify_url_to_theme_package', 'Or, Specify a URL to a Theme', '2004-10-18 15:10:35', ''),\r
+('en', '_template', 'standard', 'Standard', '2005-09-21 13:35:25', ''),\r
+('en', '_template', 'started_by', 'Started By', '2003-05-22 13:02:38', 'forums thread display table column header'),\r
+('en', '_template', 'start_date', 'Start Date', '2003-05-22 13:03:05', 'mytests, test manager'),\r
+('en', '_template', 'state', 'State', '2005-08-16 15:27:15', ''),\r
+('en', '_template', 'statement', 'Statement', '2003-05-22 13:07:22', 'test manager add/edit questions'),\r
+('en', '_template', 'statistics', 'Statistics', '2003-05-22 13:08:06', 'instructor course statistics/details'),\r
+('en', '_template', 'statistics_information', 'Statistics &amp; Information', '2007-07-26 13:39:49', ''),\r
+('en', '_template', 'status', 'Status', '2003-05-22 13:09:29', 'test manager, control center, profile, admin user manager'),\r
+('en', '_template', 'sticky_thread', 'Sticky Thread - always at the top', '2003-05-22 13:10:18', 'instructor forum option alt text'),\r
+('en', '_template', 'street_address', 'Street Address', '2003-05-22 13:10:43', 'registration, profile'),\r
+('en', '_template', 'student', 'Student', '2003-10-27 11:44:47', 'tracker'),\r
+('en', '_template', 'student1', 'Student', '2003-05-22 13:11:42', 'admin user manager'),\r
+('en', '_template', 'students', 'Students', '2003-05-21 20:01:44', 'course email (removed 1.2)'),\r
+('en', '_template', 'student_id', 'Student ID', '2003-05-22 13:12:40', 'tracker'),\r
+('en', '_template', 'student_pin', 'Student PIN', '2005-05-27 13:35:11', ''),\r
+('en', '_template', 'student_tools', 'Student Tools', '2005-04-28 12:15:39', ''),\r
+('en', '_template', 'style_editor', 'Stylesheet Editor', '2003-05-22 13:13:22', 'tool page/ stylesheet editor heading text'),\r
+('en', '_template', 'subject', 'Subject', '2003-05-22 13:14:21', 'global message subject label'),\r
+('en', '_template', 'submission', 'Submission', '2005-05-11 11:29:07', ''),\r
+('en', '_template', 'submissions', 'Submissions', '2003-05-22 13:14:47', 'links database'),\r
+('en', '_template', 'submit', 'Submit', '2003-05-22 13:15:05', 'global submit button text'),\r
+('en', '_template', 'submitted_by', 'Submitted By', '2005-02-23 12:23:06', ''),\r
+('en', '_template', 'submit_no', 'No', '2004-11-22 16:23:09', ''),\r
+('en', '_template', 'submit_yes', 'Yes', '2004-11-22 16:23:00', ''),\r
+('en', '_template', 'subscribe', 'Subscribe to this thread to receive notification via email of new replies.', '2003-11-06 13:47:10', ''),\r
+('en', '_template', 'subscribe1', 'Subscribe', '2004-12-02 15:32:01', ''),\r
+('en', '_template', 'sub_topics', 'Subtopics', '2005-03-16 13:55:12', 'content manager'),\r
+('en', '_template', 'suggest_link', 'Suggest Course Link', '2006-05-25 11:40:32', ''),\r
+('en', '_template', 'summary', 'Summary', '2003-09-13 09:24:55', 'course tracker member picker'),\r
+('en', '_template', 'switch_text', 'Switch to text editor', '2004-05-27 10:50:47', 'Content editor'),\r
+('en', '_template', 'switch_visual', 'Switch to visual editor', '2004-05-27 10:52:19', 'Used in content editor'),\r
+('en', '_template', 'syndicate_announcements', 'Syndicate Announcements', '2005-01-04 09:46:15', ''),\r
+('en', '_template', 'system_preferences', 'System Preferences', '2005-03-03 10:49:44', ''),\r
+('en', '_template', 'table_of_contents', 'Table of Contents', '2003-05-22 13:53:36', 'preferences'),\r
+('en', '_template', 'take_test', 'Take Test', '2003-05-22 13:54:16', 'MyTests'),\r
+('en', '_template', 'tech_support_forum', 'Technical Support Forum', '2003-05-21 15:16:00', 'help'),\r
+('en', '_template', 'tech_support_forum_text', 'Support questions should be of a technical nature.', '2005-07-05 14:13:20', 'help'),\r
+('en', '_template', 'template', 'Template', '2006-09-25 13:07:42', ''),\r
+('en', '_template', 'tests', 'Tests &amp; Surveys', '2004-08-25 14:13:43', ''),\r
+('en', '_template', 'test_anonymous', 'This test/survey is anonymous.', '2004-09-02 13:42:31', ''),\r
+('en', '_template', 'test_lk', 'Likert', '2004-08-12 15:55:22', ''),\r
+('en', '_template', 'test_ma', 'Multiple Answer', '2007-02-01 15:49:57', ''),\r
+('en', '_template', 'test_matching', 'Matching (Simple)', '2007-02-01 16:20:41', ''),\r
+('en', '_template', 'test_matchingdd', 'Matching (Graphical)', '2007-02-01 16:20:28', ''),\r
+('en', '_template', 'test_mc', 'Multiple Choice', '2003-05-22 14:03:29', 'test manager question type'),\r
+('en', '_template', 'test_open', 'Open Ended', '2003-05-22 14:03:45', 'test manager question type'),\r
+('en', '_template', 'test_ordering', 'Ordering', '2007-01-10 13:45:26', ''),\r
+('en', '_template', 'test_tf', 'True or False', '2003-05-22 14:09:05', 'test manager question type'),\r
+('en', '_template', 'text', 'Text', '2004-04-20 16:40:07', ''),\r
+('en', '_template', 'theme', 'Theme', '2004-04-23 15:26:57', ''),\r
+('en', '_template', 'themes', 'Themes', '2003-05-22 14:10:24', 'preferences'),\r
+('en', '_template', 'themes_disabled', 'The personal theme preference has been disabled in favour of theme specific categories.', '2004-08-04 11:58:33', ''),\r
+('en', '_template', 'theme_screenshot', 'Screenshot', '2005-05-06 14:18:00', 'theme manager, screentshot alt/title'),\r
+('en', '_template', 'theme_specific_categories', 'Theme Specific Categories', '2005-03-31 13:49:53', ''),\r
+('en', '_template', 'the_follow_errors_occurred', 'The following errors occurred:', '2005-03-07 12:41:09', ''),\r
+('en', '_template', 'this_course_only', 'This course only', '2004-08-18 12:02:37', ''),\r
+('en', '_template', 'this_is_content', 'This is just a blank content page. Use the Edit Content link to edit this page. You can manage this course by accessing the Manage section.', '2005-05-11 14:52:47', 'default content insert when a new course is created'),\r
+('en', '_template', 'thread_already_subscribed', 'You are already subscribed to this thread.', '2003-05-22 14:11:25', 'forum view thread subscribe feedback'),\r
+('en', '_template', 'thread_locked', 'Thread Locked', '2003-05-22 14:11:58', 'forum thread view thread lock message'),\r
+('en', '_template', 'thread_notify1', 'Thread Subscription', '2005-01-08 09:18:48', 'Thread email notify subject'),\r
+('en', '_template', 'thread_subscribe', 'Subscribe to this thread to receive notification via email of replies.', '2003-05-22 14:42:57', 'forum thread subscribe description'),\r
+('en', '_template', 'tile_any_field', 'Any Field', '2004-05-03 13:14:02', ''),\r
+('en', '_template', 'tile_author', 'Author', '2004-05-03 13:14:17', ''),\r
+('en', '_template', 'tile_export', 'Export content to the TILE repository. A valid TILE account is required.', '2004-05-20 11:00:26', ''),\r
+('en', '_template', 'tile_import_content_package_about', 'Import the content directly into this course.', '2004-05-03 13:15:54', ''),\r
+('en', '_template', 'tile_keyword', 'Keyword', '2004-05-03 13:14:23', ''),\r
+('en', '_template', 'tile_progress', 'TILE Importing in Progress...', '2004-05-05 16:03:44', ''),\r
+('en', '_template', 'tile_search', 'TILE Repository Search', '2004-03-25 09:48:17', ''),\r
+('en', '_template', 'tile_technical_format', 'Technical Format', '2004-05-03 13:14:51', ''),\r
+('en', '_template', 'timestamp', 'Timestamp', '2004-12-06 12:04:30', ''),\r
+('en', '_template', 'time_spent', 'Time Spent', '2007-07-09 12:32:33', ''),\r
+('en', '_template', 'time_zone', 'Time Zone', '2006-11-01 13:02:56', 'appears on the config page'),\r
+('en', '_template', 'time_zones_not_supported', 'Your server is not set-up to support time zones. See the Handbook for more details.', '2006-11-01 13:06:40', ''),\r
+('en', '_template', 'title', 'Title', '2003-05-22 14:43:54', 'admin course manager column heading'),\r
+('en', '_template', 'to', 'To', '2003-05-22 14:45:14', 'inbox send message \"to\" a user'),\r
+('en', '_template', 'to1', 'to', '2003-05-22 14:48:13', 'login form header row login -to- some place'),\r
+('en', '_template', 'toggle_disabled', 'Toggle Disabled', '2003-05-22 15:10:01', 'alt text for menu toggle'),\r
+('en', '_template', 'tools', 'Tools', '2006-03-22 12:52:10', ''),\r
+('en', '_template', 'tools_details', 'Details for Tool Usage', '2003-05-22 15:11:15', 'tracker'),\r
+('en', '_template', 'tool_summary', 'Tools Usage Summary', '2003-05-22 15:11:26', 'tracker'),\r
+('en', '_template', 'top', 'Top', '2003-05-22 15:11:53', 'global alt text for jump to top link/icon'),\r
+('en', '_template', 'topic', 'Topic', '2003-05-22 15:12:45', 'forum thread list column heading'),\r
+('en', '_template', 'top_20', 'Only the top 20 results have been displayed.', '2005-10-20 10:50:41', ''),\r
+('en', '_template', 'top_level', 'Top Level', '2005-03-16 13:36:35', 'content manager'),\r
+('en', '_template', 'total', 'Total', '2003-05-22 15:14:13', 'instructor course statistic/details, test manager'),\r
+('en', '_template', 'total_votes', 'Total Votes', '2005-03-11 15:51:33', ''),\r
+('en', '_template', 'to_2', 'to', '2003-05-22 15:15:16', 'test manager date'),\r
+('en', '_template', 'to_email', 'To Email', '2003-05-22 15:17:02', 'help admin/instructor contact forms'),\r
+('en', '_template', 'to_name', 'To Name', '2003-05-22 15:17:20', 'help admin/instructor contact forms'),\r
+('en', '_template', 'tracker', 'Content Tracker', '2005-11-25 18:36:21', ''),\r
+('en', '_template', 'tracker_none_viewed', 'No content pages have been viewed in this course yet.', '2003-09-15 11:53:06', 'mytracker summary view'),\r
+('en', '_template', 'tracker_not_viewed', 'Jump to pages not yet viewed.', '2003-09-13 12:16:10', 'mytracker bypass to not viewed alt text'),\r
+('en', '_template', 'tracker_pages_total', 'Total pages in this course %s (pages visited: %s.)', '2003-09-13 09:11:43', 'tracker summary pages read'),\r
+('en', '_template', 'tracker_percent_read', 'Percentage of pages viewed %s.', '2003-09-13 12:09:57', 'tracker pages read'),\r
+('en', '_template', 'tracker_summary_read', 'Summary of pages viewed by user %s.', '2003-09-13 12:30:44', 'tracker summary read'),\r
+('en', '_template', 'tracking', 'Tracking', '2003-05-22 15:18:11', 'admin course manager '),\r
+('en', '_template', 'tracking_all_page_viewed', 'All pages in this course have been viewed.', '2003-09-13 12:37:23', 'mytracker page not viewed'),\r
+('en', '_template', 'translate', 'Translate', '2004-12-07 13:59:44', 'language manager translate button'),\r
+('en', '_template', 'translate_lang_howto', 'In order to translate a language you must : <br />\r\n1. Set the AT_DEVEL_TRANSLATE constant in /include/vitals.inc.php to \'1\' <br />\r\n2. Make sure that you have added the new language to the database<br />\r\n3. Select  the new language as the one you want to translate from the \'translate to:\' option at the bottom of the page<br />\r\n4. Use the translate button and translate the new language in a new window<br />', '2004-12-10 16:29:48', 'Language Manager, translation message'),\r
+('en', '_template', 'translate_to', 'Translate to:', '2003-05-22 15:19:14', 'footer'),\r
+('en', '_template', 'true', 'True', '2003-05-22 15:19:50', 'test manager question answer option'),\r
+('en', '_template', 'type', 'Type', '2003-05-22 15:20:30', 'test manager questions column heading'),\r
+('en', '_template', 'unchecked', 'Un-checked', '2006-06-26 14:56:06', ''),\r
+('en', '_template', 'unconfirmed', 'Unconfirmed', '2005-04-01 10:39:51', ''),\r
+('en', '_template', 'underline', 'Underline', '2003-05-22 15:21:31', 'global code picker'),\r
+('en', '_template', 'underscore', 'Underscore', '2004-06-22 12:09:46', ''),\r
+('en', '_template', 'unenroll', 'Un-enroll', '2004-10-15 11:51:25', 'unenroll button in enrollment manager'),\r
+('en', '_template', 'unenrolled', 'Un-enrolled', '2004-10-15 11:50:06', 'unenrolled tab in enrollement manager'),\r
+('en', '_template', 'unique_visits', 'Unique Visits', '2005-03-01 12:41:13', 'tracker'),\r
+('en', '_template', 'unknown', 'Unknown', '2003-06-06 10:41:35', 'links database , file upload progress window'),\r
+('en', '_template', 'unknown_error', 'An unknown error occured', '2003-05-22 15:22:55', 'general catch all error message'),\r
+('en', '_template', 'unlimited', 'Unlimited', '2005-03-01 11:22:02', 'admin course properties & file manager'),\r
+('en', '_template', 'unlock_thread', 'Unlock Thread', '2003-05-22 15:24:58', 'forum instructor lock screen'),\r
+('en', '_template', 'unmarked', 'Unmarked', '2003-05-22 15:25:33', 'mytests, test manager'),\r
+('en', '_template', 'unmarked_label', 'Unmarked (%s)', '2005-05-12 10:25:56', ''),\r
+('en', '_template', 'unreleased', 'Unreleased', '2005-05-04 13:59:37', ''),\r
+('en', '_template', 'unshared_forums', 'Unshared Forums', '2004-11-05 10:50:02', ''),\r
+('en', '_template', 'unsubscribe', 'UnSubscribe from this thread to cancel receiving notifications via email of new replies.', '2003-11-06 13:47:20', ''),\r
+('en', '_template', 'unsubscribe1', 'Unsubscribe', '2004-12-02 15:32:28', ''),\r
+('en', '_template', 'until', 'Until', '2006-03-23 11:38:49', ''),\r
+('en', '_template', 'unvisited_pages', 'You have not viewed the following pages:', '2003-09-13 11:56:50', 'mytracker summary'),\r
+('en', '_template', 'update', 'Update', '2004-11-24 14:28:45', ''),\r
+('en', '_template', 'updated', 'Updated', '2003-05-22 15:33:15', 'admin course manager'),\r
+('en', '_template', 'update_list', 'Update List', '2005-05-10 14:31:59', ''),\r
+('en', '_template', 'update_to', 'Update To', '2005-03-03 12:16:15', ''),\r
+('en', '_template', 'upload', 'Upload', '2003-05-22 15:56:16', 'global upload button/link text'),\r
+('en', '_template', 'upload_content_package', 'Upload a Content Package', '2004-04-30 15:33:40', ''),\r
+('en', '_template', 'upload_file', 'Upload File', '2006-03-20 14:37:46', ''),\r
+('en', '_template', 'upload_new_picture', 'Upload new picture', '2007-02-26 17:23:08', ''),\r
+('en', '_template', 'upload_progress', 'File Upload in Progress...', '2003-06-06 10:36:38', 'file upload progress window'),\r
+('en', '_template', 'upload_theme_package', 'Upload a Theme', '2004-10-18 15:09:32', 'Theme Manager'),\r
+('en', '_template', 'url', 'URL', '2003-05-22 15:56:36', 'links database'),\r
+('en', '_template', 'url_to_read', 'URL To Read', '2006-04-13 12:01:15', ''),\r
+('en', '_template', 'usage', 'Usage', '2005-03-16 13:55:31', 'content manager'),\r
+('en', '_template', 'usaved_changes_made', 'Unsaved changes made', '2004-01-15 13:30:06', 'editing content'),\r
+('en', '_template', 'user', 'User', '2003-05-22 15:59:34', 'links database'),\r
+('en', '_template', 'username', 'Username', '2003-05-22 16:00:31', 'global username label/link text'),\r
+('en', '_template', 'users', 'Users', '2003-05-22 16:02:26', 'forum, admin user manager'),\r
+('en', '_template', 'users_online', 'Users Online', '2003-05-22 16:03:00', 'discussions page text'),\r
+('en', '_template', 'user_contributed_notes', 'User Contributed Handbook Notes', '2005-07-27 12:01:52', ''),\r
+('en', '_template', 'user_offline', 'Offline', '2005-03-11 16:19:14', 'directory'),\r
+('en', '_template', 'user_online', 'Online', '2005-03-11 16:19:28', 'directory'),\r
+('en', '_template', 'use_enrol_button', 'Use the button below to enroll in this course.', '2003-05-22 16:03:37', 'enrol screen instruction'),\r
+('en', '_template', 'use_parent_theme', 'Use parent category\'s theme.', '2004-08-04 11:34:41', ''),\r
+('en', '_template', 'use_system_time', 'Use the system\'s time', '2006-11-01 13:06:01', ''),\r
+('en', '_template', 'use_visual_editor', '<small style=\"text-decoration:underline;\">(Editor)</small>', '2004-12-08 12:15:36', 'form editor in create test question'),\r
+('en', '_template', 'version', 'Version', '2003-05-22 16:04:54', 'copyright notice in footer'),\r
+('en', '_template', 'vertical', 'Vertical', '2004-12-01 13:34:28', 'create/edit test question option'),\r
+('en', '_template', 'view', 'View', '2004-02-16 15:23:09', ''),\r
+('en', '_template', 'viewing_errors', 'Viewing Error(s)', '2004-12-06 12:10:05', ''),\r
+('en', '_template', 'viewing_profile_bugs', 'Viewing Profile Bugs', '2004-12-06 12:03:33', ''),\r
+('en', '_template', 'view_all', 'View All', '2005-08-04 09:54:04', ''),\r
+('en', '_template', 'view_details', 'View Details', '2005-03-11 11:27:43', ''),\r
+('en', '_template', 'view_entire_post', 'View Entire Post', '2003-05-22 16:07:57', 'forum message view'),\r
+('en', '_template', 'view_log', 'View Activity Log', '2005-03-03 10:44:12', ''),\r
+('en', '_template', 'view_mark_test', 'View & Mark Test', '2003-05-22 16:08:11', 'test manager'),\r
+('en', '_template', 'view_message', 'View Message', '2005-03-14 11:48:21', ''),\r
+('en', '_template', 'view_profile_bugs', 'View Profile Bugs', '2004-12-06 11:51:58', 'admin/error_logging.php'),\r
+('en', '_template', 'view_responses', 'View Responses', '2004-08-25 11:53:13', ''),\r
+('en', '_template', 'view_results', 'View Results', '2003-05-22 16:09:09', 'mytests, test manager'),\r
+('en', '_template', 'view_selected_bugs', 'View Selected Bugs', '2004-12-06 12:06:26', ''),\r
+('en', '_template', 'view_sub_topics', 'View subtopics', '2005-03-16 13:35:47', 'content manager'),\r
+('en', '_template', 'view_tracking', 'View Tracking', '2003-05-22 16:09:31', 'tracker'),\r
+('en', '_template', 'visits', 'Visits', '2003-09-13 09:19:09', 'tracker summary read'),\r
+('en', '_template', 'visual_editor', 'Visual Editor', '2006-11-23 13:31:56', ''),\r
+('en', '_template', 'vote_to_see_results', 'Vote to see results.', '2004-06-21 16:55:42', ''),\r
+('en', '_template', 'warning', 'Warning', '2003-05-22 16:09:47', 'text for warning message'),\r
+('en', '_template', 'web_site', 'Web Site', '2003-05-22 16:10:20', 'registration, profile'),\r
+('en', '_template', 'weight', 'Weight', '2003-05-22 16:10:31', 'test manager'),\r
+('en', '_template', 'welcome_to_atutor', 'Welcome To ATutor', '2003-05-31 15:30:38', 'announcement default heading for new course'),\r
+('en', '_template', 'window_auto_close', 'This window will close automatically.', '2003-06-06 10:37:43', 'file upload progress window'),\r
+('en', '_template', 'workspace', 'Workspace', '2006-03-20 14:38:08', ''),\r
+('en', '_template', 'wrong_answer', 'Wrong Answer', '2003-05-22 16:11:51', 'test manager question editor'),\r
+('en', '_template', 'year', 'Year', '2004-06-24 15:45:35', ''),\r
+('en', '_template', 'yes', 'Yes', '2005-03-03 10:18:48', 'preferences, admin course manager'),\r
+('en', '_template', 'yes_delete', 'Yes / Delete', '2003-05-22 16:14:23', 'global delete response option'),\r
+('en', '_template', 'you_are_here', 'You are here', '2003-10-02 16:46:28', 'ALT text Global/Local Navigation link to self'),\r
+('en', '_template', 'zip_archive', 'Zip Archive', '2003-05-22 16:20:01', 'file manager'),\r
+('en', '_template', 'zip_file_manager', 'Zip File Manager', '2003-05-22 16:20:14', 'file manager'),\r
+('en', '_template', 'zip_illegal_contents', 'The contents of this archive are listed below. Illegal file types will not be extracted, and file names containing illegal characters will be translated.', '2004-08-10 15:10:04', ''),\r
+('en', '_template', 'pass_score', 'Pass Score', now(), ''),\r
+('en', '_template', 'pass_feedback', 'Pass Feedback', now(), ''),\r
+('en', '_template', 'fail_feedback', 'Fail Feedback', now(), ''),\r
+('en', '_template', 'test_description', 'Test Description', now(), ''),\r
+('en', '_template', 'no_pass_score', 'No pass score', now(), ''),\r
+('en', '_template', 'percentage_score', 'percentage score', now(), ''),\r
+('en', '_template', 'points_score', 'points score', now(), ''),\r
+('en', '_template', 'all_passed_students', 'All Passed Students', now(), ''),\r
+('en', '_template', 'all_failed_students', 'All Failed Students', now(), ''),\r
+('en', '_template', 'auto_enroll', 'Auto Enrollment At Registration', now(), ''),\r
+('en', '_msgs', 'AT_CONFIRM_DELETE_AUTO_ENROLL', 'Are you sure you want to <strong>delete</strong> auto enrollment for <strong>%s</strong>', now(), ''),\r
+('en', '_template', 'course_to_auto_enroll', 'Courses to Enroll', now(), ''),\r
+('en', '_template', 'auto_enroll_delete', 'Delete Auto Enrollment', now(), 'links database'),\r
+('en', '_template', 'auto_enroll_edit', 'Create/Edit Auto Enrollment', now(), ''),\r
+('en', '_template', 'auto_enroll_msg', 'You will be enrolled into these courses.', now(), ''),\r
+('en', '_template', 'auto_enrolled_msg', 'You have been enrolled into these courses:', now(), ''),\r
+('en', '_template', 'go_to_my_start_page', 'Go To My Start Page', now(), '')\r
+;\r
+\r
+# Patcher language\r
+INSERT INTO `language_text` VALUES ('en', '_module','patcher','Patcher',NOW(),'');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'get_my_patch', 'Get My Patch', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'atutor_patch_id', 'ATutor Patch ID', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'available_to', 'Available To', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'available_patches', 'Available Patches', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'available_patches_text', 'There are <strong>%s</strong> patches available to install.', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PATCH_ALREADY_INSTALLED', 'The selected patch is already installed.', now(), 'error msg');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_CHOOSE_UNINSTALLED_PATCH', 'Please choose an uninstalled patch.', now(), 'error msg');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PATCH_XML_NOT_FOUND', 'Patch XML file is not found.', now(), 'error msg');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_REMOVE_WRITE_PERMISSION', 'Please remove write permission from the listed files.', now(), 'error msg');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_CANNOT_UNZIP', 'Can NOT unzip the uploaded file.', now(), 'error msg');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_PATCH_INSTALLED_SUCCESSFULLY', 'The patch has been installed successfully.', now(), 'feedback msg');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PATCH_DEPENDENCY', 'Due to patch dependency, please install the listed patches before installing this patch: %s', now(), 'error msg');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_INFOS_PATCH_INSTALLED_AND_REMOVE_PERMISSION', 'The patch has been installed. Please remove write permission as instruction.', now(), 'info msg');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'patcher_overwrite_modified_files', \r
+'The listed files are modified locally. If you choose to proceed, the patch file will be copied to your local machine. \r
+You have to manually merge this file and your local copy.<br>', now(), 'patcher');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'patch_local_file_not_exist', \r
+'Cannot proceed. The listed files are not exist in your local machine. If you renamed them to your copy, in order to proceed, please rename back.<br>', now(), 'patcher');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'patcher_alter_modified_files', \r
+'The listed files are modified locally. If you choose to proceed, your local file will be modified. The original\r
+file will be backup before the modification. Please note that the modification on your customized code may break your customization.<br>', now(), 'patcher');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'grant_write_permission', \r
+'Please grant <strong>write</strong> permission to folders and files listed below:<p><strong>Note:</strong> To change permissions on Unix use <kbd>chmod a+rw</kbd> then the file name.</p>', now(), 'patcher');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'remove_write_permission', \r
+'<span style="color:red">Please <strong>REMOVE</strong> write permission on the listed folders and files for your security:</span><p><strong>Note:</strong> To remove permissions on Unix use <kbd>chmod 755</kbd> then the file name..</p>', now(), 'patcher');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'patcher_show_backup_files', \r
+'Below is the list of the backup files created by patch installation. After ensuring ATutor works properly with the patch, you may want to \r
+delete these files. If  ATutor does not work properly with the patch, you can always revert back to the old files by renaming the backup files \r
+to the original file names,  removing the [patch_id].old portion of the file name. <br>', now(), 'patcher');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'patcher_show_patch_files', \r
+'Below is the list of the patch files copied to your computer. \r
+Please manually merge the change between the patch files and your local copy. <br>', now(), 'patcher');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'patch_dependent_patch_not_installed', \r
+'<br><span style="color: red">Waring: Due to patch dependency, please install the listed patches first: </span>', now(), 'patcher');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'upload_patch', \r
+'Upload a zip file to install patch:', now(), 'patcher');\r
+\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'myown_patches', 'My Own Patches', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'atutor_version_to_apply', 'ATutor Version to Apply', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'dependent_patches', 'Dependent Patches', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'dependent_patch_id', 'Dependent Patch ID', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'add_dependent_patch', 'Add A Dependent Patch', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'sql_statement', 'SQL Statement', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'relative_directory', 'Directory is relative directory to ATutor root, for example: docs/images/ or tools/tests/. Leave empty if it is ATutor root directory.', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'create_patch', 'Create Patch', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'edit_patch', 'Edit Patch', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'delete_patch', 'Delete Patch', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'add_a_file', 'Add A File', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'delete_this_file', 'Delete This File', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'replace_file', 'Replace File', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'alter', 'Alter', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'code_to_replace_from', 'Code To Replace From', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'code_to_replace_to', 'Code To Replace To', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_CHOOSE_ACTION', 'Please choose action for file <strong>%s</strong>', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_PATCH_CREATED_SUCCESSFULLY', 'The patch has been created successfully.', now(), 'feedback msg');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_CONFIRM_DELETE_MYOWN_PATCH', 'Are you sure you want to <strong>delete</strong> patch <strong>%s</strong>', now(), '');\r
+\r
diff --git a/install/db/atutor_schema.sql b/install/db/atutor_schema.sql
new file mode 100644 (file)
index 0000000..ebed3e4
--- /dev/null
@@ -0,0 +1,1038 @@
+#####################################################
+# Database setup SQL for a new install of ATutor
+#####################################################
+# $Id$
+
+# --------------------------------------------------------
+# Table structure for table `admin_log`
+# since 1.5
+
+CREATE TABLE `admins` (
+   `login` VARCHAR( 30 ) NOT NULL default '',
+   `password` VARCHAR( 40 ) NOT NULL default '',
+   `real_name` VARCHAR( 120 ) NOT NULL default '',
+   `email` VARCHAR( 50 ) NOT NULL default '',
+   `language` varchar(5) NOT NULL default '',
+   `privileges` MEDIUMINT UNSIGNED NOT NULL default 0,
+   `last_login` TIMESTAMP NOT NULL default 0,
+   PRIMARY KEY ( `login` )
+) TYPE = MYISAM;
+
+CREATE TABLE `admin_log` (
+  `login` varchar(30) NOT NULL default '',
+  `time` TIMESTAMP NOT NULL,
+  `operation` varchar(20) NOT NULL default '',
+  `table` varchar(30) NOT NULL default '',
+  `num_affected` tinyint(3) NOT NULL default '0',
+  `details` TEXT NOT NULL,
+  KEY `login` (`login`)
+) TYPE = MYISAM;
+
+
+# --------------------------------------------------------
+# Table structure for table `assignments`
+# since 1.5.3
+
+CREATE TABLE `assignments` (
+       `assignment_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+       `course_id` MEDIUMINT UNSIGNED NOT NULL default 0,
+       `title` VARCHAR(240) NOT NULL default '',
+       `assign_to` MEDIUMINT UNSIGNED default 0,
+       `date_due` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
+       `date_cutoff` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
+       `multi_submit` TINYINT DEFAULT '0',
+       PRIMARY KEY  (`assignment_id`),
+       INDEX (`course_id`)
+) TYPE = MYISAM;
+
+# --------------------------------------------------------
+# Table structure for table `backups`
+# since 1.4.3
+
+CREATE TABLE `backups` (
+  `backup_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `course_id` mediumint(8) unsigned NOT NULL default '0',
+  `date` TIMESTAMP NOT NULL,
+  `description` TEXT NOT NULL ,
+  `file_size` int(10) unsigned NOT NULL default 0,
+  `system_file_name` varchar(50) NOT NULL default '',
+  `file_name` TEXT NOT NULL ,
+  `contents` TEXT NOT NULL ,
+  PRIMARY KEY  (`backup_id`),
+  KEY `course_id` (`course_id`)
+) TYPE=MyISAM;
+
+
+# --------------------------------------------------------
+## Table for `blog_posts`
+
+CREATE TABLE `blog_posts` (
+  `post_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `member_id` mediumint(8) unsigned NOT NULL default '0',
+  `owner_type` tinyint(3) unsigned NOT NULL default '0',
+  `owner_id` mediumint(8) unsigned NOT NULL default '0',
+  `private` tinyint(3) unsigned NOT NULL default '0',
+  `date` TIMESTAMP NOT NULL,
+  `num_comments` tinyint(3) unsigned NOT NULL default '0',
+  `title` VARCHAR(255) NOT NULL,
+  `body` text NOT NULL,
+  PRIMARY KEY  (`post_id`)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+## Table for `blog_posts_comments`
+
+CREATE TABLE `blog_posts_comments` (
+   `comment_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT ,
+   `post_id` MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL ,
+   `member_id` MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL ,
+   `date` TIMESTAMP NOT NULL,
+   `private` TINYINT UNSIGNED DEFAULT '0' NOT NULL ,
+   `comment` TEXT NOT NULL ,
+   PRIMARY KEY ( `comment_id` ) ,
+   INDEX ( `post_id` )
+) TYPE = MYISAM;
+
+# --------------------------------------------------------
+# Table structure for table `config`
+# since 1.5.2
+
+CREATE TABLE `config` (
+  `name` CHAR( 30 ) NOT NULL default '',
+  `value` CHAR( 255 ) NOT NULL default '',
+  PRIMARY KEY ( `name` )
+) TYPE = MYISAM;
+
+# --------------------------------------------------------
+# Table structure for table `content`
+
+CREATE TABLE `content` (
+  `content_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `course_id` mediumint(8) unsigned NOT NULL default '0',
+  `content_parent_id` mediumint(8) unsigned NOT NULL default '0',
+  `ordering` mediumint(8) NOT NULL default '0',
+  `last_modified` TIMESTAMP NOT NULL,
+  `revision` tinyint(3) unsigned NOT NULL default '0',
+  `formatting` tinyint(4) NOT NULL default '0',
+  `release_date` datetime NOT NULL default '0000-00-00 00:00:00',
+  `keywords` TEXT NOT NULL ,
+  `content_path` TEXT NOT NULL ,
+  `title` VARCHAR(255) NOT NULL ,
+  `text` text NOT NULL ,
+  `head` TEXT NOT NULL,
+  `use_customized_head` TINYINT(4) NOT NULL,
+  PRIMARY KEY  (`content_id`),
+  KEY `course_id` (`course_id`)
+) TYPE=MyISAM ;
+
+
+# --------------------------------------------------------
+# Table structure for table `course_access`
+
+CREATE TABLE `course_access` (
+  `password` char(8) NOT NULL ,
+  `course_id` mediumint(8) unsigned NOT NULL ,
+  `expiry_date` timestamp NOT NULL ,
+  `enabled` tinyint(4) NOT NULL ,
+  PRIMARY KEY ( `password` ) ,
+  UNIQUE (`course_id`)
+) TYPE=MyISAM ;
+
+# --------------------------------------------------------
+# Table structure for table `course_cats`
+
+CREATE TABLE `course_cats` (
+  `cat_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `cat_name` VARCHAR(255) NOT NULL ,
+  `cat_parent` mediumint(8) unsigned NOT NULL default '0',
+  `theme` VARCHAR(30) NOT NULL default '',
+  PRIMARY KEY  (`cat_id`)
+) TYPE=MyISAM;
+
+
+# --------------------------------------------------------
+# Table structure for table `course_enrollment`
+
+CREATE TABLE `course_enrollment` (
+  `member_id` mediumint(8) unsigned NOT NULL default '0',
+  `course_id` mediumint(8) unsigned NOT NULL default '0',
+  `approved` enum('y','n','a') NOT NULL default 'n',
+  `privileges` INT(10) unsigned NOT NULL default '0',
+  `role` varchar(35) NOT NULL default '',
+  `last_cid` mediumint(8) unsigned NOT NULL default '0',
+  PRIMARY KEY  (`member_id`,`course_id`)
+) TYPE=MyISAM;
+
+
+
+# --------------------------------------------------------
+# Table structure for table `course_stats`
+
+CREATE TABLE `course_stats` (
+  `course_id` mediumint(8) unsigned NOT NULL default '0',
+  `login_date` date NOT NULL default '0000-00-00',
+  `guests` mediumint(8) unsigned NOT NULL default '0',
+  `members` mediumint(8) unsigned NOT NULL default '0',
+  PRIMARY KEY  (`course_id`,`login_date`)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+# Table structure for table `courses`
+
+CREATE TABLE `courses` (
+  `course_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `member_id` mediumint(8) unsigned NOT NULL default '0',
+  `cat_id` mediumint(8) unsigned NOT NULL default '0',
+  `content_packaging` enum('none','top','all') NOT NULL default 'top',
+  `access` enum('public','protected','private') NOT NULL default 'public',
+  `created_date` datetime NOT NULL default '0000-00-00 00:00:00',
+  `title` VARCHAR(255) NOT NULL ,
+  `description` text NOT NULL ,
+  `course_dir_name` VARCHAR(255) NOT NULL,
+  `notify` tinyint(4) NOT NULL default '0',
+  `max_quota` varchar(30) NOT NULL default '',
+  `max_file_size` varchar(30) NOT NULL default '',
+  `hide` tinyint(4) NOT NULL default '0',
+  `copyright` text NOT NULL ,
+  `primary_language` varchar(5) NOT NULL default '',
+  `rss` tinyint NOT NULL default 0,
+  `icon` varchar(75) NOT NULL default '',
+  `home_links` text NOT NULL ,
+  `main_links` text NOT NULL ,
+  `side_menu` VARCHAR( 255 ) NOT NULL default '',
+  `release_date` datetime NOT NULL default '0000-00-00 00:00:00',
+  `end_date` datetime NOT NULL default '0000-00-00 00:00:00',
+   `banner` TEXT NOT NULL ,
+  PRIMARY KEY  (`course_id`)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+# Table structure for table `faq_topics`
+
+CREATE TABLE `faq_topics` (
+  `topic_id` mediumint(8) NOT NULL auto_increment,
+  `course_id` mediumint(8) unsigned NOT NULL default '0',
+  `name` TEXT NOT NULL ,
+  KEY `course_id` (`course_id`),
+  PRIMARY KEY  (`topic_id`)
+) TYPE = MYISAM;
+
+# --------------------------------------------------------
+# Table structure for table `faq_entries`
+CREATE TABLE `faq_entries` (
+  `entry_id` mediumint(8) NOT NULL auto_increment,
+  `topic_id` mediumint(8) NOT NULL default '0',
+  `revised_date` TIMESTAMP NOT NULL,
+  `approved` tinyint(4) NOT NULL default '0',
+  `question` TEXT NOT NULL ,
+  `answer` text NOT NULL ,
+  PRIMARY KEY  (`entry_id`)
+) TYPE = MYISAM ;
+
+# --------------------------------------------------------
+# Table structure for table `feeds`
+CREATE TABLE `feeds` (
+  `feed_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `url` varchar(255) NOT NULL default '',
+  PRIMARY KEY  (`feed_id`)
+) ;
+
+# --------------------------------------------------------
+
+#
+# Table structure for table `file_storage_groups`
+# added 1.5.3
+
+CREATE TABLE `file_storage_groups` (
+  `group_id` MEDIUMINT UNSIGNED NOT NULL default 0,
+  PRIMARY KEY ( `group_id` )
+) TYPE = MYISAM;
+
+#
+# Table structure for table `files`
+# added 1.5.3
+
+CREATE TABLE `files` (
+  `file_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `owner_type` tinyint(3) unsigned NOT NULL default '0',
+  `owner_id` mediumint(8) unsigned NOT NULL default '0',
+  `member_id` mediumint(8) unsigned NOT NULL default '0',
+  `folder_id` mediumint(8) unsigned NOT NULL default '0',
+  `parent_file_id` mediumint(8) unsigned NOT NULL default '0',
+  `date` TIMESTAMP NOT NULL,
+  `num_comments` tinyint(3) unsigned NOT NULL default '0',
+  `num_revisions` tinyint(3) unsigned NOT NULL default '0',
+  `file_name` varchar(80) NOT NULL default '',
+  `file_size` int(11) NOT NULL default '0',
+  `description` text NOT NULL ,
+  PRIMARY KEY  (`file_id`)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+
+#
+# Table structure for table `files_comments`
+# added 1.5.3
+
+CREATE TABLE `files_comments` (
+  `comment_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `file_id` mediumint(8) unsigned NOT NULL default '0',
+  `member_id` mediumint(8) unsigned NOT NULL default '0',
+  `date` TIMESTAMP NOT NULL,
+  `comment` text NOT NULL ,
+  PRIMARY KEY  (`comment_id`)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+
+#
+# Table structure for table `folders`
+# added 1.5.3
+
+CREATE TABLE `folders` (
+  `folder_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `parent_folder_id` mediumint(8) unsigned NOT NULL default '0',
+  `owner_type` tinyint(3) unsigned NOT NULL default '0',
+  `owner_id` mediumint(8) unsigned NOT NULL default '0',
+  `title` varchar(120) NOT NULL default '',
+  PRIMARY KEY  (`folder_id`)
+) TYPE=MyISAM;
+
+
+# --------------------------------------------------------
+# Table structure for table `forums`
+
+CREATE TABLE `forums` (
+  `forum_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `title` varchar(240) NOT NULL default '',
+  `description` text NOT NULL ,
+  `num_topics` MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL ,
+  `num_posts` MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL ,
+  `last_post` TIMESTAMP NOT NULL,
+  `mins_to_edit` SMALLINT UNSIGNED NOT NULL DEFAULT '0',
+  PRIMARY KEY  (`forum_id`)
+) TYPE=MyISAM;
+
+
+# --------------------------------------------------------
+# Table structure for table `forums_accessed`
+
+CREATE TABLE `forums_accessed` (
+  `post_id` mediumint(8) unsigned NOT NULL default '0',
+  `member_id` mediumint(8) unsigned NOT NULL default '0',
+  `last_accessed` timestamp NOT NULL,
+  `subscribe` tinyint(4) NOT NULL default '0',
+  PRIMARY KEY  (`post_id`,`member_id`)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+# Table structure for table `forums_courses`
+
+CREATE TABLE `forums_courses` (
+  `forum_id` MEDIUMINT UNSIGNED NOT NULL default '0',
+  `course_id` MEDIUMINT UNSIGNED NOT NULL default '0',
+  PRIMARY KEY (`forum_id`,`course_id`),
+  KEY `course_id` (`course_id`)
+) TYPE=MyISAM;
+
+
+# --------------------------------------------------------
+# Table structure for table `forums_groups`
+
+CREATE TABLE `forums_groups` (
+`forum_id` mediumint( 8 ) unsigned NOT NULL default '0',
+`group_id` mediumint( 8 ) unsigned NOT NULL default '0',
+PRIMARY KEY ( `forum_id` , `group_id` ) ,
+KEY `group_id` ( `group_id` )
+) TYPE = MYISAM ;
+
+# --------------------------------------------------------
+# Table structure for table `forums_subscriptions`
+#
+
+CREATE TABLE `forums_subscriptions` (
+  forum_id mediumint(8) unsigned NOT NULL default '0',
+  member_id mediumint(8) unsigned NOT NULL default '0',
+  PRIMARY KEY  (`forum_id`,`member_id`)
+) TYPE=MyISAM;
+
+
+# --------------------------------------------------------
+# Table structure for table `forums_threads`
+
+CREATE TABLE `forums_threads` (
+  `post_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `parent_id` mediumint(8) unsigned NOT NULL default '0',
+  `member_id` mediumint(8) unsigned NOT NULL default '0',
+  `forum_id` mediumint(8) unsigned NOT NULL default '0',
+  `last_comment` TIMESTAMP NOT NULL,
+  `num_comments` mediumint(8) unsigned NOT NULL default '0',
+  `subject` VARCHAR(255) NOT NULL ,
+  `body` text NOT NULL ,
+  `date` TIMESTAMP NOT NULL,
+  `locked` tinyint(4) NOT NULL default '0',
+  `sticky` tinyint(4) NOT NULL default '0',
+  PRIMARY KEY  (`post_id`)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+# Table structure for table `glossary`
+
+CREATE TABLE `glossary` (
+  `word_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `course_id` mediumint(8) unsigned NOT NULL default '0',
+  `word` varchar(240) NOT NULL default '',
+  `definition` text NOT NULL ,
+  `related_word_id` mediumint(8) unsigned NOT NULL default '0',
+  PRIMARY KEY  (`word_id`),
+  KEY `course_id` (`course_id`)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+# Table structure for table `groups`
+
+CREATE TABLE `groups` (
+  `group_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `type_id` mediumint(8) unsigned NOT NULL default '0',
+  `title` varchar(80) NOT NULL default '',
+  `description` text NOT NULL ,
+  `modules` varchar(100) NOT NULL default '',
+  PRIMARY KEY  (`group_id`)
+) TYPE = MYISAM;
+
+
+# --------------------------------------------------------
+# Table structure for table `groups_members`
+
+CREATE TABLE `groups_members` (
+`group_id` MEDIUMINT UNSIGNED NOT NULL default '0',
+`member_id` MEDIUMINT UNSIGNED NOT NULL default '0',
+ PRIMARY KEY  (`group_id`,`member_id`)
+) TYPE = MYISAM;
+
+# --------------------------------------------------------
+# Table structure for table `groups_types` (since 1.5.3)
+
+CREATE TABLE `groups_types` (
+  `type_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `course_id` mediumint(8) unsigned NOT NULL default '0',
+  `title` VARCHAR(80) NOT NULL ,
+  PRIMARY KEY  (`type_id`),
+  KEY `course_id` (`course_id`)
+) TYPE = MYISAM;
+
+# --------------------------------------------------------
+# Table structure for table `handbook_notes`
+
+CREATE TABLE `handbook_notes` (
+`note_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT ,
+`date` TIMESTAMP NOT NULL,
+`section` VARCHAR( 15 ) NOT NULL default '',
+`page` VARCHAR( 50 ) NOT NULL default '',
+`approved` tinyint NOT NULL default 0,
+`email` VARCHAR( 50 ) NOT NULL default '',
+`note` TEXT NOT NULL ,
+PRIMARY KEY ( `note_id` )
+) TYPE = MYISAM;
+
+
+# --------------------------------------------------------
+# Table structure for table `instructor_approvals`
+
+CREATE TABLE `instructor_approvals` (
+  `member_id` mediumint(8) unsigned NOT NULL default '0',
+  `request_date` TIMESTAMP NOT NULL,
+  `notes` text NOT NULL ,
+  PRIMARY KEY  (`member_id`)
+) TYPE=MyISAM;
+
+
+CREATE TABLE `languages` (
+  `language_code` varchar(20) NOT NULL default '',
+  `char_set` varchar(80) NOT NULL default '',
+  `direction` varchar(16) NOT NULL default '',
+  `reg_exp` varchar(124) NOT NULL default '',
+  `native_name` varchar(80) NOT NULL default '',
+  `english_name` varchar(80) NOT NULL default '',
+  `status` TINYINT UNSIGNED DEFAULT '0' NOT NULL,
+  PRIMARY KEY  (`language_code`,`char_set`)
+) TYPE=MyISAM;
+
+#
+# Dumping data for table `languages`
+#
+
+INSERT INTO `languages` VALUES ('en', 'utf-8', 'ltr', 'en([-_][[:alpha:]]{2})?|english', 'English', 'English', 3);
+    
+
+# Table structure for table `links_categories`
+
+CREATE TABLE `links_categories` (
+  `cat_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `owner_type` tinyint(4) NOT NULL default '0',
+  `owner_id` mediumint(8) unsigned NOT NULL default '0',
+  `name` VARCHAR(255) NOT NULL ,
+  `parent_id` mediumint(8) unsigned default NULL,
+  PRIMARY KEY  (`cat_id`),
+  KEY `owner_id` (`owner_id`)
+) TYPE=MyISAM ;
+
+
+# --------------------------------------------------------
+# Table structure for table `links`
+
+CREATE TABLE `links` (
+  `link_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `cat_id` mediumint(8) unsigned NOT NULL default '0',
+  `Url` varchar(255) NOT NULL default '',
+  `LinkName` varchar(64) NOT NULL default '',
+  `Description` TEXT NOT NULL ,
+  `Approved` tinyint(8) default '0',
+  `SubmitName` varchar(64) NOT NULL default '',
+  `SubmitEmail` varchar(64) NOT NULL default '',
+  `SubmitDate` date NOT NULL default '0000-00-00',
+  `hits` int(11) default '0',
+  PRIMARY KEY  (`link_id`)
+) TYPE=MyISAM ;
+
+# --------------------------------------------------------
+# Table structure for table `language_pages`
+
+CREATE TABLE `language_pages` (
+  `term` varchar(30) NOT NULL default '',
+  `page` varchar(50) NOT NULL default '',
+  PRIMARY KEY  (`term`,`page`)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+# Table structure for table `master_list`
+
+CREATE TABLE `master_list` (
+  `public_field` CHAR( 30 ) NOT NULL default '',
+  `hash_field` CHAR( 40 ) NOT NULL default '',
+  `member_id` MEDIUMINT UNSIGNED NOT NULL default 0,
+  PRIMARY KEY ( `public_field` )
+) TYPE = MYISAM;
+
+# --------------------------------------------------------
+# Table structure for table `members`
+
+CREATE TABLE `members` (
+  `member_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `login` varchar(20) NOT NULL default '',
+  `password` varchar(40) NOT NULL default '',
+  `email` varchar(50) NOT NULL default '',
+  `website` varchar(200) NOT NULL default '',
+  `first_name` VARCHAR(100) NOT NULL ,
+  `second_name` varchar(100) NOT NULL default '',
+  `last_name` VARCHAR(100) NOT NULL ,
+  `dob` date NOT NULL default '0000-00-00',
+  `gender` enum('m','f','n') NOT NULL default 'n',
+  `address` TEXT NOT NULL ,
+  `postal` varchar(15) NOT NULL default '',
+  `city` varchar(100) NOT NULL default '',
+  `province` varchar(100) NOT NULL default '',
+  `country` varchar(100) NOT NULL default '',
+  `phone` varchar(15) NOT NULL default '',
+  `status` tinyint(4) NOT NULL default '0',
+  `preferences` text NOT NULL ,
+  `creation_date` TIMESTAMP NOT NULL,
+  `language` varchar(5) NOT NULL default '',
+  `inbox_notify` tinyint(3) unsigned NOT NULL default '0',
+  `private_email` TINYINT DEFAULT '1' NOT NULL,
+  `last_login` TIMESTAMP NOT NULL,
+  PRIMARY KEY  (`member_id`),
+  UNIQUE KEY `login` (`login`)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+# Table structure for table `member_track`
+
+CREATE TABLE `member_track` (
+  `member_id` mediumint(8) unsigned NOT NULL default '0',
+  `course_id` mediumint(8) unsigned NOT NULL default '0',
+  `content_id` mediumint(8) unsigned NOT NULL default '0',
+  `counter` mediumint(8) unsigned NOT NULL default '0',
+  `duration` mediumint(8) unsigned NOT NULL default '0',
+  `last_accessed` TIMESTAMP NULL,
+  KEY `member_id` (`member_id`),
+  KEY `content_id` (`content_id`)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+# Table structure for table `messages`
+
+CREATE TABLE `messages` (
+  `message_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `course_id` mediumint(8) unsigned NOT NULL default '0',
+  `from_member_id` mediumint(8) unsigned NOT NULL default '0',
+  `to_member_id` mediumint(8) unsigned NOT NULL default '0',
+  `date_sent` TIMESTAMP NOT NULL,
+  `new` tinyint(4) NOT NULL default '0',
+  `replied` tinyint(4) NOT NULL default '0',
+  `subject` VARCHAR(255) NOT NULL ,
+  `body` text NOT NULL ,
+  PRIMARY KEY  (`message_id`),
+  KEY `to_member_id` (`to_member_id`)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+# Table structure for table `messages_sent` (since 1.5.4)
+
+CREATE TABLE `messages_sent` (
+   `message_id` mediumint( 8 ) unsigned NOT NULL AUTO_INCREMENT ,
+   `course_id` mediumint( 8 ) unsigned NOT NULL default '0',
+   `from_member_id` mediumint( 8 ) unsigned NOT NULL default '0',
+   `to_member_id` mediumint( 8 ) unsigned NOT NULL default '0',
+   `date_sent` timestamp NOT NULL ,
+   `subject` VARCHAR(255) NOT NULL ,
+   `body` text NOT NULL ,
+   PRIMARY KEY ( `message_id` ) ,
+   KEY `from_member_id` ( `from_member_id` )
+) TYPE = MYISAM;
+
+# --------------------------------------------------------
+# Table structure for table `modules` (since 1.5.2)
+
+CREATE TABLE `modules` (  
+  `dir_name` VARCHAR( 50 ) NOT NULL default '',  
+  `status` TINYINT NOT NULL default 0,
+  `privilege` INT UNSIGNED NOT NULL default 0,  
+  `admin_privilege` MEDIUMINT UNSIGNED NOT NULL default 0, 
+  `cron_interval` SMALLINT UNSIGNED DEFAULT '0' NOT NULL ,
+  `cron_last_run` INT UNSIGNED DEFAULT '0' NOT NULL,
+  PRIMARY KEY ( `dir_name` )
+) TYPE = MYISAM;
+
+INSERT INTO `modules` VALUES ('_core/properties',        2, 1,         0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/statistics',    2, 1,         0, 0, 0);
+INSERT INTO `modules` VALUES ('_core/content',           2, 2,         0, 0, 0);
+INSERT INTO `modules` VALUES ('_core/glossary',          2, 4,         0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/tests',         2, 8,         0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/chat',          2, 16,        0, 0, 0);
+INSERT INTO `modules` VALUES ('_core/file_manager',      2, 32,        0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/links',         2, 64,        0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/forums',        2, 128,       16, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/student_tools', 2, 256,       0, 0, 0);
+INSERT INTO `modules` VALUES ('_core/enrolment',         2, 512,       512, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/course_email',  2, 1024,      0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/announcements', 2, 2048,      0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/polls',         2, 16384,     0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/faq',           2, 32768,     0, 0, 0);
+INSERT INTO `modules` VALUES ('_core/groups',            2, 65536,     0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/reading_list',  2, 131072,    0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/file_storage',  2, 262144,    0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/assignments',   2, 524288,    0, 0, 0);
+INSERT INTO `modules` VALUES ('_core/users',             2, 0,         2, 0, 0);
+INSERT INTO `modules` VALUES ('_core/courses',           2, 0,         4, 0, 0);
+INSERT INTO `modules` VALUES ('_core/backups',           2, 1,         8, 0, 0);
+INSERT INTO `modules` VALUES ('_core/cats_categories',   2, 0,         32, 0, 0);
+INSERT INTO `modules` VALUES ('_core/languages',         2, 0,         64, 1440, 0);
+INSERT INTO `modules` VALUES ('_core/themes',            2, 0,         128, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/rss_feeds',    2, 0,         256, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/directory',     2, 0, 0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/tile_search',   2, 0, 0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/sitemap',       2, 0, 0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/tracker',       2, 0, 0, 0, 0);
+INSERT INTO `modules` VALUES ('_core/content_packaging', 2, 0, 0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/google_search', 2, 0, 0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/blogs',         2, 0, 0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/profile_pictures', 2, 0, 0, 0, 0);
+INSERT INTO `modules` VALUES ('_standard/patcher', 2, 0, 1024, 0, 0);
+
+# --------------------------------------------------------
+# Table structure for table `news`
+
+CREATE TABLE `news` (
+  `news_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `course_id` mediumint(8) unsigned NOT NULL default '0',
+  `member_id` mediumint(8) unsigned NOT NULL default '0',
+  `date` TIMESTAMP NOT NULL,
+  `formatting` tinyint(4) NOT NULL default '0',
+  `title` VARCHAR(200) NOT NULL ,
+  `body` text NOT NULL ,
+  PRIMARY KEY  (`news_id`)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+
+# Table structure for table `polls`
+CREATE TABLE `polls` (
+  `poll_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT ,
+  `course_id` MEDIUMINT UNSIGNED NOT NULL default 0,
+  `question` VARCHAR(255) NOT NULL ,
+  `created_date` TIMESTAMP NOT NULL,
+  `total` SMALLINT UNSIGNED NOT NULL default '0',
+  `choice1` VARCHAR(255) NOT NULL ,
+  `count1` SMALLINT UNSIGNED NOT NULL default '0',
+  `choice2` VARCHAR(255) NOT NULL ,
+  `count2` SMALLINT UNSIGNED NOT NULL default '0',
+  `choice3` VARCHAR(255) NOT NULL ,
+  `count3` SMALLINT UNSIGNED NOT NULL default '0',
+  `choice4` VARCHAR(255) NOT NULL ,
+  `count4` SMALLINT UNSIGNED NOT NULL default '0',
+  `choice5` VARCHAR(255) NOT NULL ,
+  `count5` SMALLINT UNSIGNED NOT NULL default '0',
+  `choice6` VARCHAR(255) NOT NULL ,
+  `count6` SMALLINT UNSIGNED NOT NULL default '0',
+  `choice7` VARCHAR(255) NOT NULL ,
+  `count7` SMALLINT UNSIGNED NOT NULL default '0',
+  PRIMARY KEY ( `poll_id` ) ,
+  INDEX ( `course_id` )
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+# Table structure for table `mail_queue`
+# since 1.5.3
+
+CREATE TABLE `mail_queue` (
+  `mail_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT ,
+  `to_email` VARCHAR( 50 ) NOT NULL default '',
+  `to_name` VARCHAR( 50 ) NOT NULL default '',
+  `from_email` VARCHAR( 50 ) NOT NULL default '',
+  `from_name` VARCHAR( 50 ) NOT NULL default '',
+  `char_set` VARCHAR( 20 ) NOT NULL default '',
+  `subject` VARCHAR(255) NOT NULL ,
+  `body` TEXT NOT NULL ,
+  PRIMARY KEY ( `mail_id` )
+) TYPE = MYISAM;
+
+# --------------------------------------------------------
+
+# Table structure for table `polls_members`
+
+CREATE TABLE `polls_members` (
+  `poll_id` MEDIUMINT UNSIGNED NOT NULL default '0',
+  `member_id` MEDIUMINT UNSIGNED NOT NULL default '0',
+  PRIMARY KEY ( `poll_id` , `member_id` )
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+
+# Table structure for table `related_content`
+CREATE TABLE `related_content` (
+  `content_id` mediumint(8) unsigned NOT NULL default '0',
+  `related_content_id` mediumint(8) unsigned NOT NULL default '0',
+  PRIMARY KEY  (`content_id`,`related_content_id`)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+# Since 1.5.3
+# Table structure for table `reading_list`
+
+CREATE TABLE `reading_list` (
+       `reading_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+       `course_id` MEDIUMINT UNSIGNED NOT NULL default 0,
+       `resource_id` MEDIUMINT UNSIGNED NOT NULL default 0,
+       `required` enum('required','optional') NOT NULL DEFAULT 'required',
+       `date_start` DATE NOT NULL DEFAULT '0000-00-00',
+       `date_end` DATE NOT NULL DEFAULT '0000-00-00',
+       `comment` text NOT NULL ,
+       PRIMARY KEY  (`reading_id`),
+       INDEX (`course_id`)
+) TYPE = MYISAM;
+
+# Since 1.5.3
+# Table structure for table `external_resources`
+
+CREATE TABLE `external_resources` (
+       `resource_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+       `course_id` MEDIUMINT UNSIGNED NOT NULL default 0,
+       `type` TINYINT UNSIGNED NOT NULL DEFAULT 0,
+       `title` VARCHAR(255) NOT NULL ,
+       `author` VARCHAR(150) NOT NULL ,
+       `publisher` VARCHAR(150) NOT NULL ,
+       `date` varchar(20) NOT NULL DEFAULT '',
+       `comments` TEXT NOT NULL ,
+       `id` varchar(50) NOT NULL DEFAULT '',
+       `url` varchar(255) NOT NULL DEFAULT '',
+       PRIMARY KEY (`resource_id`),
+       INDEX (`course_id`)
+) TYPE = MYISAM;
+
+
+# --------------------------------------------------------
+# Table structure for table `tests`
+
+CREATE TABLE `tests` (
+  `test_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `course_id` mediumint(8) unsigned NOT NULL default '0',
+  `title` VARCHAR(255) NOT NULL ,
+  `format` tinyint(4) NOT NULL default '0',
+  `start_date` datetime NOT NULL default '0000-00-00 00:00:00',
+  `end_date` datetime NOT NULL default '0000-00-00 00:00:00',
+  `randomize_order` tinyint(4) NOT NULL default '0',
+  `num_questions` tinyint(3) unsigned NOT NULL default '0',
+  `instructions` text NOT NULL ,
+  `content_id` mediumint(8) NOT NULL default '0',
+  `result_release` tinyint(4) unsigned NOT NULL default '0',
+  `random` tinyint(4) unsigned NOT NULL default '0',
+  `difficulty` tinyint(4) unsigned NOT NULL default '0',
+  `num_takes` tinyint(4) unsigned NOT NULL default '0',
+  `anonymous` tinyint(4) NOT NULL default '0',
+  `out_of` varchar(4) NOT NULL default '',
+  `guests` TINYINT NOT NULL DEFAULT '0',
+  `display` TINYINT NOT NULL DEFAULT '0',
+  `description` TEXT NOT NULL,
+  `passscore` MEDIUMINT NOT NULL default '0',
+  `passpercent` MEDIUMINT NOT NULL default '0',
+  `passfeedback` TEXT NOT NULL,
+  `failfeedback` TEXT NOT NULL,
+  PRIMARY KEY  (`test_id`)
+) TYPE=MyISAM;
+
+
+# --------------------------------------------------------
+# Table structure for table `tests_answers`
+
+CREATE TABLE `tests_answers` (
+  `result_id` mediumint(8) unsigned NOT NULL default '0',
+  `question_id` mediumint(8) unsigned NOT NULL default '0',
+  `member_id` mediumint(8) unsigned NOT NULL default '0',
+  `answer` text NOT NULL ,
+  `score` varchar(5) NOT NULL default '',
+  `notes` text NOT NULL ,
+  PRIMARY KEY  (`result_id`,`question_id`,`member_id`)
+) TYPE=MyISAM;
+
+
+# --------------------------------------------------------
+# Table structure for table `tests_groups`
+
+CREATE TABLE `tests_groups` (
+  `test_id` MEDIUMINT UNSIGNED NOT NULL default '0',
+  `group_id` MEDIUMINT UNSIGNED NOT NULL default '0',
+  PRIMARY KEY (`test_id`,`group_id`),
+  KEY `test_id` (`test_id`)
+) TYPE=MyISAM;
+
+
+# --------------------------------------------------------
+# Table structure for table `tests_questions`
+
+CREATE TABLE `tests_questions` (
+  `question_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `category_id` mediumint(8) unsigned NOT NULL default '0',
+  `course_id` mediumint(8) unsigned NOT NULL default '0',
+  `type` tinyint(3) unsigned NOT NULL default '0',
+  `feedback` text NOT NULL ,
+  `question` text NOT NULL ,
+  `choice_0` TEXT NOT NULL ,
+  `choice_1` TEXT NOT NULL ,
+  `choice_2` TEXT NOT NULL ,
+  `choice_3` TEXT NOT NULL ,
+  `choice_4` TEXT NOT NULL ,
+  `choice_5` TEXT NOT NULL ,
+  `choice_6` TEXT NOT NULL ,
+  `choice_7` TEXT NOT NULL ,
+  `choice_8` TEXT NOT NULL ,
+  `choice_9` TEXT NOT NULL ,
+  `answer_0` tinyint(4) NOT NULL default '0',
+  `answer_1` tinyint(4) NOT NULL default '0',
+  `answer_2` tinyint(4) NOT NULL default '0',
+  `answer_3` tinyint(4) NOT NULL default '0',
+  `answer_4` tinyint(4) NOT NULL default '0',
+  `answer_5` tinyint(4) NOT NULL default '0',
+  `answer_6` tinyint(4) NOT NULL default '0',
+  `answer_7` tinyint(4) NOT NULL default '0',
+  `answer_8` tinyint(4) NOT NULL default '0',
+  `answer_9` tinyint(4) NOT NULL default '0',
+  `option_0` TEXT NOT NULL ,
+  `option_1` TEXT NOT NULL ,
+  `option_2` TEXT NOT NULL ,
+  `option_3` TEXT NOT NULL ,
+  `option_4` TEXT NOT NULL ,
+  `option_5` TEXT NOT NULL ,
+  `option_6` TEXT NOT NULL ,
+  `option_7` TEXT NOT NULL ,
+  `option_8` TEXT NOT NULL ,
+  `option_9` TEXT NOT NULL ,
+  `properties` tinyint(4) NOT NULL default '0',
+  `content_id` mediumint(8) NOT NULL,  
+  PRIMARY KEY  (`question_id`),
+  KEY `category_id` (category_id)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+# Table structure for table `tests_questions_assoc`
+
+CREATE TABLE `tests_questions_assoc` (
+  `test_id` mediumint(8) unsigned NOT NULL default '0',
+  `question_id` mediumint(8) unsigned NOT NULL default '0',
+  `weight` varchar(4) NOT NULL default '',
+  `ordering` mediumint(8) unsigned NOT NULL default '0',
+  `required` tinyint(3) unsigned NOT NULL default '0',
+  PRIMARY KEY  (`test_id`,`question_id`)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+# Table structure for table `tests_questions_categories`
+
+CREATE TABLE `tests_questions_categories` (
+  `category_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `course_id` mediumint(8) unsigned NOT NULL default '0',
+  `title` char(200) NOT NULL default '',
+  PRIMARY KEY  (`category_id`),
+  KEY `course_id` (`course_id`)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+# Table structure for table `tests_results`
+
+CREATE TABLE `tests_results` (
+  `result_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `test_id` mediumint(8) unsigned NOT NULL default '0',
+  `member_id` mediumint(8) unsigned NOT NULL default '0',
+  `date_taken` TIMESTAMP NOT NULL,
+  `final_score` char(5) NOT NULL default '',
+  `status` TINYINT NOT NULL DEFAULT '0',
+  `end_time` TIMESTAMP NOT NULL ,
+  `max_pos` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+  PRIMARY KEY  (`result_id`),
+  KEY `test_id` (`test_id`)
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+# Table structure for table `themes`
+# since 1.4.3
+
+CREATE TABLE `themes` (
+  `title` varchar(80) NOT NULL default '',
+  `version` varchar(10) NOT NULL default '',
+  `dir_name` varchar(20) NOT NULL default '',
+  `last_updated` date NOT NULL default '0000-00-00',
+  `extra_info` TEXT NOT NULL ,
+  `status` tinyint(3) unsigned NOT NULL default '1',
+  PRIMARY KEY  (`title`)
+) TYPE = MYISAM;
+
+
+# --------------------------------------------------------
+# Table structure for table `patches`
+# since 1.6.1
+
+CREATE TABLE `patches` (
+       `patches_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+       `atutor_patch_id` VARCHAR(20) NOT NULL default '',
+       `applied_version` VARCHAR(10) NOT NULL default '',
+       `patch_folder` VARCHAR(250) NOT NULL default '',
+  `description` TEXT NOT NULL,
+       `available_to` VARCHAR(250) NOT NULL default '',
+  `sql_statement` text NOT NULL,
+  `status` varchar(20) NOT NULL default '',
+  `remove_permission_files` text NOT NULL,
+  `backup_files` text NOT NULL,
+  `patch_files` text NOT NULL,
+       PRIMARY KEY  (`patches_id`)
+);
+
+
+# --------------------------------------------------------
+# Table structure for table `patches_files`
+# since 1.6.1
+
+CREATE TABLE `patches_files` (
+       `patches_files_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+       `patches_id` MEDIUMINT UNSIGNED NOT NULL default 0,
+       `action` VARCHAR(20) NOT NULL default '',
+       `name` TEXT NOT NULL,
+       `location` VARCHAR(250) NOT NULL default '',
+       PRIMARY KEY  (`patches_files_id`)
+);
+
+# --------------------------------------------------------
+# Table structure for table `patches_files_actions`
+# since 1.6.1
+
+CREATE TABLE `patches_files_actions` (
+       `patches_files_actions_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+       `patches_files_id` MEDIUMINT UNSIGNED NOT NULL default 0,
+       `action` VARCHAR(20) NOT NULL default '',
+       `code_from` TEXT NOT NULL,
+       `code_to` TEXT NOT NULL,
+       PRIMARY KEY  (`patches_files_actions_id`)
+);
+
+
+
+# --------------------------------------------------------
+# New tables for patch creator
+# since 1.6.1
+CREATE TABLE `myown_patches` (
+       `myown_patch_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+       `atutor_patch_id` VARCHAR(20) NOT NULL default '',
+       `applied_version` VARCHAR(10) NOT NULL default '',
+  `description` TEXT NOT NULL,
+  `sql_statement` text NOT NULL,
+  `status` varchar(20) NOT NULL default '',
+  `last_modified` datetime NOT NULL,
+       PRIMARY KEY  (`myown_patch_id`)
+);
+
+CREATE TABLE `myown_patches_dependent` (
+       `myown_patches_dependent_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+       `myown_patch_id` MEDIUMINT UNSIGNED NOT NULL,
+       `dependent_patch_id` VARCHAR(50) NOT NULL default '',
+       PRIMARY KEY  (`myown_patches_dependent_id`)
+);
+
+CREATE TABLE `myown_patches_files` (
+       `myown_patches_files_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+       `myown_patch_id` MEDIUMINT UNSIGNED NOT NULL,
+       `action` VARCHAR(20) NOT NULL default '',
+       `name` VARCHAR(250) NOT NULL,
+       `location` VARCHAR(250) NOT NULL default '',
+       `code_from` TEXT NOT NULL,
+       `code_to` TEXT NOT NULL,
+       `uploaded_file` TEXT NOT NULL,
+       PRIMARY KEY  (`myown_patches_files_id`)
+);
+
+
+
+
+
+# insert the default theme
+INSERT INTO `themes` VALUES ('ATutor', '1.6.1', 'default', NOW(), 'This is the default ATutor theme and cannot be deleted as other themes inherit from it. Please do not alter this theme directly as it would complicate upgrading. Instead, create a new theme derived from this one.', 2);
+INSERT INTO `themes` VALUES ('Fuild', '1.6.1', 'fuild', NOW(), 'Theme that implements the Fluid reorderer used to drag-and-drop the menu from side-to-side.', 1);
+INSERT INTO `themes` VALUES ('ATutor Classic', '1.6.1', 'default_classic', NOW(), 'This is the ATutor Classic theme which makes use of the custom Header and logo images. To customize those images you must edit the <code>theme.cfg.php</code> in this theme\'s directory.', 1);
+
+
+INSERT INTO `themes` VALUES ('Blumin', '1.6.1', 'blumin', NOW(), 'This is the plone look-alike theme.', 1);
+INSERT INTO `themes` VALUES ('Greenmin', '1.6.1', 'greenmin', NOW(), 'This is the plone look-alike theme in green.', 1);
+INSERT INTO `themes` VALUES ('ATutor 1.5', '1.6.1', 'default15', NOW(), 'This is the 1.5 series default theme.', 1);
+
+
+# --------------------------------------------------------
+# Table structure for table `users_online`
+
+CREATE TABLE `users_online` (
+  `member_id` mediumint(8) unsigned NOT NULL default '0',
+  `course_id` mediumint(8) unsigned NOT NULL default '0',
+  `login` varchar(255) NOT NULL default '',
+  `expiry` int(10) unsigned NOT NULL default '0',
+  PRIMARY KEY  (`member_id`)
+) TYPE=HEAP MAX_ROWS=500;
+
+# --------------------------------------------------------
+# Table structure for table `auto_enroll`
+
+CREATE TABLE `auto_enroll` (
+   `auto_enroll_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+   `associate_string` VARCHAR(10) NOT NULL,
+   `name` VARCHAR( 50 ) NOT NULL default '',
+   PRIMARY KEY ( `auto_enroll_id` )
+);
+
+# --------------------------------------------------------
+# Table structure for table `auto_enroll_courses`
+
+CREATE TABLE `auto_enroll_courses` (
+   `auto_enroll_courses_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+   `auto_enroll_id` MEDIUMINT UNSIGNED NOT NULL default 0,
+   `course_id` MEDIUMINT UNSIGNED NOT NULL default 0,
+   PRIMARY KEY ( `auto_enroll_courses_id` )
+);
+
+
diff --git a/install/db/atutor_upgrade_1.0_to_1.1.sql b/install/db/atutor_upgrade_1.0_to_1.1.sql
new file mode 100644 (file)
index 0000000..1b68c94
--- /dev/null
@@ -0,0 +1,182 @@
+###############################################################
+# Database upgrade SQL from ATutor 1.0-Stable to ATutor 1.1
+###############################################################
+
+##################################
+# `news` table
+
+ALTER TABLE `news` ADD `formatting` TINYINT DEFAULT '0' NOT NULL AFTER `date`;
+UPDATE `news` SET formatting=1;
+
+
+##################################
+# `courses` table
+ALTER TABLE `courses` ADD `preferences` TEXT NOT NULL ,
+ADD `header` TEXT NOT NULL ,
+ADD `footer` TEXT NOT NULL ,
+ADD `copyright` TEXT NOT NULL ,
+ADD `tracking` ENUM( 'on', 'off' ) DEFAULT 'off' NOT NULL ;
+
+##################################
+# `g_click_data`
+ALTER TABLE `g_click_data` ADD `course_id` MEDIUMINT UNSIGNED NOT NULL AFTER `member_id` ;
+ALTER TABLE `g_click_data` CHANGE `timestamp` `timestamp` INT UNSIGNED NOT NULL ;
+ALTER TABLE `g_click_data` ADD `duration` DOUBLE UNSIGNED NOT NULL ;
+
+##################################
+# `g_refs`
+
+CREATE TABLE g_refs (
+  g_id tinyint(4) default NULL,
+  reference varchar(65) default NULL,
+  KEY g_id (g_id)
+) TYPE=MyISAM;
+
+
+# data for `g_refs`
+
+INSERT INTO g_refs VALUES (1, 'Users Online');
+INSERT INTO g_refs VALUES (2, 'Local Menu');
+INSERT INTO g_refs VALUES (3, 'Global Menu');
+INSERT INTO g_refs VALUES (4, 'Related topic');
+INSERT INTO g_refs VALUES (5, 'Jump');
+INSERT INTO g_refs VALUES (6, 'Top/#bypass anchor');
+INSERT INTO g_refs VALUES (7, 'Sequence');
+INSERT INTO g_refs VALUES (8, 'Within sitemap');
+INSERT INTO g_refs VALUES (9, 'Global Home link');
+INSERT INTO g_refs VALUES (10, 'Breadcrumb');
+INSERT INTO g_refs VALUES (11, 'Headings');
+INSERT INTO g_refs VALUES (12, 'Embedded links');
+INSERT INTO g_refs VALUES (13, 'Table of contents');
+INSERT INTO g_refs VALUES (14, 'Home');
+INSERT INTO g_refs VALUES (15, 'Tools');
+INSERT INTO g_refs VALUES (16, 'Resources');
+INSERT INTO g_refs VALUES (17, 'Discussions');
+INSERT INTO g_refs VALUES (18, 'Help');
+INSERT INTO g_refs VALUES (19, 'Logout');
+INSERT INTO g_refs VALUES (20, 'Preferences');
+INSERT INTO g_refs VALUES (21, 'Inbox');
+INSERT INTO g_refs VALUES (22, 'Local major topic');
+INSERT INTO g_refs VALUES (23, 'To sitemap');
+INSERT INTO g_refs VALUES (24, 'Embedded glossary');
+INSERT INTO g_refs VALUES (25, 'Menu glossary');
+INSERT INTO g_refs VALUES (26, 'Local Home link');
+INSERT INTO g_refs VALUES (27, 'Print Compiler');
+INSERT INTO g_refs VALUES (28, 'My Tracker');
+INSERT INTO g_refs VALUES (29, 'Links DB');
+INSERT INTO g_refs VALUES (30, 'Session Start');
+
+##################################
+# `instructor_approvals`
+ALTER TABLE `instructor_approvals` ADD `request_date` DATETIME NOT NULL ,
+ADD `notes` TEXT NOT NULL ;
+
+
+##################################
+# `messages`
+ALTER TABLE `messages` ADD INDEX ( `to_member_id` );
+
+##################################
+# `preferences`
+CREATE TABLE preferences (
+  member_id mediumint(8) unsigned NOT NULL default '0',
+  course_id mediumint(8) unsigned NOT NULL default '0',
+  preferences text NOT NULL,
+  PRIMARY KEY  (member_id,course_id)
+) TYPE=MyISAM;
+
+##################################
+# `tests`
+CREATE TABLE tests (
+  test_id mediumint(8) unsigned NOT NULL auto_increment,
+  course_id mediumint(8) unsigned NOT NULL default '0',
+  title varchar(100) NOT NULL default '',
+  format tinyint(4) NOT NULL default '0',
+  start_date datetime NOT NULL default '0000-00-00 00:00:00',
+  end_date datetime NOT NULL default '0000-00-00 00:00:00',
+  randomize_order tinyint(4) NOT NULL default '0',
+  num_questions tinyint(3) unsigned NOT NULL default '0',
+  instructions text NOT NULL,
+  PRIMARY KEY  (test_id)
+) TYPE=MyISAM;
+
+
+##################################
+# `tests_answers`
+CREATE TABLE tests_answers (
+  result_id mediumint(8) unsigned NOT NULL default '0',
+  question_id mediumint(8) unsigned NOT NULL default '0',
+  member_id mediumint(8) unsigned NOT NULL default '0',
+  answer text NOT NULL,
+  score varchar(5) NOT NULL default '',
+  notes text NOT NULL,
+  PRIMARY KEY  (result_id,question_id,member_id)
+) TYPE=MyISAM;
+
+
+##################################
+# `tests_questions`
+CREATE TABLE tests_questions (
+  question_id mediumint(8) unsigned NOT NULL auto_increment,
+  test_id mediumint(8) unsigned NOT NULL default '0',
+  course_id mediumint(8) unsigned NOT NULL default '0',
+  ordering tinyint(3) unsigned NOT NULL default '0',
+  type tinyint(3) unsigned NOT NULL default '0',
+  weight tinyint(3) unsigned NOT NULL default '0',
+  required tinyint(4) NOT NULL default '0',
+  feedback text NOT NULL,
+  question text NOT NULL,
+  choice_0 varchar(255) NOT NULL default '',
+  choice_1 varchar(255) NOT NULL default '',
+  choice_2 varchar(255) NOT NULL default '',
+  choice_3 varchar(255) NOT NULL default '',
+  choice_4 varchar(255) NOT NULL default '',
+  choice_5 varchar(255) NOT NULL default '',
+  choice_6 varchar(255) NOT NULL default '',
+  choice_7 varchar(255) NOT NULL default '',
+  choice_8 varchar(255) NOT NULL default '',
+  choice_9 varchar(255) NOT NULL default '',
+  answer_0 tinyint(4) NOT NULL default '0',
+  answer_1 tinyint(4) NOT NULL default '0',
+  answer_2 tinyint(4) NOT NULL default '0',
+  answer_3 tinyint(4) NOT NULL default '0',
+  answer_4 tinyint(4) NOT NULL default '0',
+  answer_5 tinyint(4) NOT NULL default '0',
+  answer_6 tinyint(4) NOT NULL default '0',
+  answer_7 tinyint(4) NOT NULL default '0',
+  answer_8 tinyint(4) NOT NULL default '0',
+  answer_9 tinyint(4) NOT NULL default '0',
+  answer_size tinyint(4) NOT NULL default '0',
+  PRIMARY KEY  (question_id),
+  KEY test_id (test_id)
+) TYPE=MyISAM;
+
+##################################
+# table `tests_results`
+CREATE TABLE tests_results (
+  result_id mediumint(8) unsigned NOT NULL auto_increment,
+  test_id mediumint(8) unsigned NOT NULL default '0',
+  member_id mediumint(8) unsigned NOT NULL default '0',
+  date_taken datetime NOT NULL default '0000-00-00 00:00:00',
+  final_score char(5) NOT NULL default '',
+  PRIMARY KEY  (result_id),
+  KEY test_id (test_id)
+) TYPE=MyISAM;
+
+##################################
+# `theme_settings`
+CREATE TABLE theme_settings (
+  theme_id tinyint(4) unsigned NOT NULL auto_increment,
+  name varchar(50) NOT NULL default '',
+  preferences text NOT NULL,
+  PRIMARY KEY  (theme_id)
+) TYPE=MyISAM;
+
+# data for `theme_settings`
+INSERT INTO theme_settings VALUES (1, 'Accessbility', 
+
+'a:16:{s:19:"PREF_MAIN_MENU_SIDE";i:2;s:14:"PREF_MAIN_MENU";i:0;s:10:"PREF_THEME";i:0;s:12:"PREF_DISPLAY";i:0;s:9:"PREF_TIPS";i:0;s:8:"PREF_SEQ";i:1;s:8:"PREF_TOC";i:2;s:14:"PREF_NUMBERING";i:0;s:11:"PREF_ONLINE";i:0;s:14:"PREF_SEQ_ICONS";i:2;s:14:"PREF_NAV_ICONS";i:2;s:16:"PREF_LOGIN_ICONS";i:2;s:13:"PREF_HEADINGS";i:0;s:16:"PREF_BREADCRUMBS";i:0;s:9:"PREF_FONT";i:0;s:15:"PREF_STYLESHEET";i:0;}');
+INSERT INTO theme_settings VALUES (2, 'Icons only', 'a:4:{s:14:"PREF_SEQ_ICONS";i:1;s:14:"PREF_NAV_ICONS";i:1;s:16:"PREF_LOGIN_ICONS";i:1;s:16:"PREF_BREADCRUMBS";i:1;}');
+INSERT INTO theme_settings VALUES (3, 'Both icons and text', 'a:5:{s:14:"PREF_MAIN_MENU";i:1;s:14:"PREF_SEQ_ICONS";i:0;s:14:"PREF_NAV_ICONS";i:0;s:16:"PREF_LOGIN_ICONS";i:0;s:16:"PREF_BREADCRUMBS";i:1;}');
+INSERT INTO theme_settings VALUES (4, 'ATutor Defaults', 'a:17:{s:10:\"PREF_STACK\";a:5:{i:0;s:1:\"0\";i:1;s:1:\"1\";i:2;s:1:\"2\";i:3;s:1:\"3\";i:4;s:1:\"4\";}s:14:\"PREF_MAIN_MENU\";i:1;s:9:\"PREF_MENU\";i:1;s:19:\"PREF_MAIN_MENU_SIDE\";i:2;s:8:\"PREF_SEQ\";i:3;s:8:\"PREF_TOC\";i:2;s:14:\"PREF_SEQ_ICONS\";i:0;s:14:\"PREF_NAV_ICONS\";i:0;s:16:\"PREF_LOGIN_ICONS\";i:0;s:9:\"PREF_FONT\";i:0;s:15:\"PREF_STYLESHEET\";i:0;s:14:\"PREF_NUMBERING\";i:0;s:13:\"PREF_HEADINGS\";i:0;s:16:\"PREF_BREADCRUMBS\";i:1;s:13:\"PREF_OVERRIDE\";i:0;s:9:\"PREF_HELP\";i:1;s:14:\"PREF_MINI_HELP\";i:1;}');
+
diff --git a/install/db/atutor_upgrade_1.1_to_1.2.sql b/install/db/atutor_upgrade_1.1_to_1.2.sql
new file mode 100644 (file)
index 0000000..1280af5
--- /dev/null
@@ -0,0 +1,139 @@
+###############################################################
+# Database upgrade SQL from ATutor 1.1-Stable to ATutor 1.2
+###############################################################
+
+# delete the old phpMyChat tables
+DROP TABLE `c_ban_users`;
+DROP TABLE `c_messages` ;
+DROP TABLE `c_reg_users`;
+DROP TABLE `c_users`;
+
+# --------------------------------------------------------
+
+# empty the old g_refs and replace them with the new language enables ones
+
+DELETE FROM `g_refs`;
+INSERT INTO `g_refs` VALUES (1, 'g_users_online'),
+(2, 'g_local_menu'),
+(3, 'g_global_menu'),
+(4, 'g_related_topic'),
+(5, 'g_jump'),
+(6, 'g_top_bypass'),
+(7, 'g_sequence'),
+(8, 'g_within_sitemap'),
+(9, 'g_global_home'),
+(10, 'g_breadcrumb'),
+(11, 'g_headings'),
+(12, 'g_embedded_links'),
+(13, 'g_table_of_contents'),
+(14, 'g_home'),
+(15, 'g_tools'),
+(16, 'g_resources'),
+(17, 'g_discussions'),
+(18, 'g_help'),
+(19, 'g_logout'),
+(20, 'g_preferences'),
+(21, 'g_inbox'),
+(22, 'g_local_major_topic'),
+(23, 'g_to_sitemap'),
+(24, 'g_embedded_glossary'),
+(25, 'g_menu_glossary'),
+(26, 'g_local_home'),
+(27, 'g_print_compiler'),
+(28, 'g_my_tracker'),
+(29, 'g_links_db'),
+(30, 'g_session_start'),
+(31, 'g_chat'),
+(32, 'g_mytests'),
+(33, 'g_new_thread'),
+(34, 'g_forum_reply'),
+(35, 'g_view_thread');
+
+ALTER TABLE `members` ADD `language` VARCHAR( 10 ) NOT NULL ;
+ALTER TABLE `g_click_data` CHANGE `timestamp` `timestamp` INT( 11 ) UNSIGNED DEFAULT '0' NOT NULL;
+
+
+#----------------------------------------------------------------
+
+#create the language tables and insert the default English language
+
+CREATE TABLE `lang2` (
+  `lang` char(3) NOT NULL default '',
+  `variable` varchar(30) NOT NULL default '',
+  `key` varchar(50) NOT NULL default '',
+  `text` text NOT NULL,
+  `revised_date` datetime NOT NULL default '0000-00-00 00:00:00',
+  PRIMARY KEY  (`lang`,`variable`,`key`),
+  KEY `lang_variable` (`lang`,`variable`)
+) TYPE=MyISAM;
+
+CREATE TABLE `lang_base` (
+  `variable` varchar(30) NOT NULL default '',
+  `key` varchar(50) NOT NULL default '',
+  `text` text NOT NULL,
+  `revised_date` datetime NOT NULL default '0000-00-00 00:00:00',
+  `context` text NOT NULL,
+  PRIMARY KEY  (`variable`,`key`)
+) TYPE=MyISAM;
+
+CREATE TABLE `lang_base_pages` (
+  `variable` varchar(30) NOT NULL default '',
+  `key` varchar(30) NOT NULL default '',
+  `page` varchar(50) NOT NULL default '',
+  PRIMARY KEY  (`variable`,`key`,`page`)
+) TYPE=MyISAM;
+
+
+# --------------------------------------------------------
+
+# replace the old learning concepts with the new language enabled one
+
+DROP TABLE `learning_concepts`;
+
+CREATE TABLE `learning_concepts` (
+  `course_id` mediumint(8) unsigned NOT NULL default '0',
+  `tag` varchar(20) NOT NULL default '',
+  PRIMARY KEY  (`tag`,`course_id`),
+  KEY `course_id` (`course_id`)
+) TYPE=MyISAM;
+
+DELETE FROM `learning_concepts`;
+
+INSERT INTO `learning_concepts` VALUES (0, 'discussion'),
+(0, 'do'),
+(0, 'dont'),
+(0, 'important'),
+(0, 'information'),
+(0, 'link'),
+(0, 'listen'),
+(0, 'project'),
+(0, 'question'),
+(0, 'read'),
+(0, 'test'),
+(0, 'think'),
+(0, 'write');
+# --------------------------------------------------------
+
+DELETE FROM `theme_settings`;
+
+INSERT INTO `theme_settings` VALUES (1, 'accessibility', 'a:16:{s:19:"PREF_MAIN_MENU_SIDE";i:2;s:14:"PREF_MAIN_MENU";i:0;s:10:"PREF_THEME";i:0;s:12:"PREF_DISPLAY";i:0;s:9:"PREF_TIPS";i:0;s:8:"PREF_SEQ";i:1;s:8:"PREF_TOC";i:2;s:14:"PREF_NUMBERING";i:0;s:11:"PREF_ONLINE";i:0;s:14:"PREF_SEQ_ICONS";i:2;s:14:"PREF_NAV_ICONS";i:2;s:16:"PREF_LOGIN_ICONS";i:2;s:13:"PREF_HEADINGS";i:0;s:16:"PREF_BREADCRUMBS";i:0;s:9:"PREF_FONT";i:0;s:15:"PREF_STYLESHEET";i:0;}'),
+(2, 'icons_only', 'a:4:{s:14:"PREF_SEQ_ICONS";i:1;s:14:"PREF_NAV_ICONS";i:1;s:16:"PREF_LOGIN_ICONS";i:1;s:16:"PREF_BREADCRUMBS";i:1;}'),
+(3, 'both_icons_and_text', 'a:5:{s:14:"PREF_MAIN_MENU";i:1;s:14:"PREF_SEQ_ICONS";i:0;s:14:"PREF_NAV_ICONS";i:0;s:16:"PREF_LOGIN_ICONS";i:0;s:16:"PREF_BREADCRUMBS";i:1;}'),
+(4, 'atutor_defaults', 'a:18:{s:10:"PREF_STACK";a:5:{i:0;i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;i:4;}s:19:"PREF_MAIN_MENU_SIDE";i:2;s:8:"PREF_SEQ";i:3;s:14:"PREF_NUMBERING";i:1;s:8:"PREF_TOC";i:1;s:14:"PREF_SEQ_ICONS";i:1;s:14:"PREF_NAV_ICONS";i:0;s:16:"PREF_LOGIN_ICONS";i:0;s:13:"PREF_HEADINGS";i:1;s:16:"PREF_BREADCRUMBS";i:1;s:9:"PREF_FONT";i:0;s:15:"PREF_STYLESHEET";i:0;s:9:"PREF_HELP";i:1;s:14:"PREF_MINI_HELP";i:1;s:18:"PREF_CONTENT_ICONS";i:0;s:14:"PREF_MAIN_MENU";i:1;s:11:"PREF_ONLINE";i:1;s:9:"PREF_MENU";i:1;}');
+# --------------------------------------------------------
+
+DROP TABLE users_online;
+
+CREATE TABLE users_online (
+  member_id mediumint(8) unsigned NOT NULL default '0',
+  course_id mediumint(8) unsigned NOT NULL default '0',
+  login varchar(20) NOT NULL default '',
+  expiry int(10) unsigned NOT NULL default '0',
+  PRIMARY KEY  (member_id)
+) TYPE=HEAP MAX_ROWS=500;
+
+
+
+
+
+
diff --git a/install/db/atutor_upgrade_1.2_to_1.3.sql b/install/db/atutor_upgrade_1.2_to_1.3.sql
new file mode 100644 (file)
index 0000000..fa7afc4
--- /dev/null
@@ -0,0 +1,86 @@
+###############################################################
+# Database upgrade SQL from ATutor 1.2.x to ATutor 1.3
+###############################################################
+
+
+# add two new fields to content table, change ints to medints
+
+ALTER TABLE `content` CHANGE `content_id` `content_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT, CHANGE `content_parent_id` `content_parent_id` MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL;
+
+ALTER TABLE `content` ADD `keywords` VARCHAR( 100 ) NOT NULL AFTER `release_date` , ADD `content_path` VARCHAR( 100 ) NOT NULL AFTER `keywords`;
+#----------------------------------------------------------------
+
+# create table `course_cats`
+
+CREATE TABLE course_cats (
+  cat_id mediumint(8) unsigned NOT NULL auto_increment,
+  cat_name varchar(100) NOT NULL default '',
+  cat_parent mediumint(8) unsigned NOT NULL default '0',
+  PRIMARY KEY  (cat_id)
+) TYPE=MyISAM;
+#----------------------------------------------------------------
+
+# add two new fields to courses table, then set default content_packaging for all records
+
+ALTER TABLE `courses` ADD `cat_id` MEDIUMINT( 8 ) UNSIGNED DEFAULT '0' NOT NULL AFTER `member_id` ,
+ADD `content_packaging` ENUM( 'none', 'top', 'all' ) DEFAULT 'top' NOT NULL AFTER `cat_id` ;
+
+UPDATE `courses` SET `content_packaging`='top' WHERE 1;
+#----------------------------------------------------------------
+
+# change ints to medints
+
+ALTER TABLE `g_click_data` CHANGE `from_cid` `from_cid` MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL ,
+CHANGE `to_cid` `to_cid` MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL; 
+#----------------------------------------------------------------
+
+# add one new record to g_refs
+
+INSERT INTO `g_refs` ( `g_id` , `reference` ) VALUES ('36', 'g_from_tracker');
+UPDATE `g_refs` SET reference='g_content_packaging' WHERE g_id=27;
+
+#----------------------------------------------------------------
+
+#
+# Table structure for table `lang2`
+#
+
+DROP TABLE `lang2`;
+
+CREATE TABLE `lang2` (
+  `lang` char(3) NOT NULL default '',
+  `variable` varchar(30) NOT NULL default '',
+  `key` varchar(50) NOT NULL default '',
+  `text` text NOT NULL,
+  `revised_date` datetime NOT NULL default '0000-00-00 00:00:00',
+  PRIMARY KEY  (`lang`,`variable`,`key`),
+  KEY `lang_variable` (`lang`,`variable`)
+) TYPE=MyISAM;
+
+
+
+#----------------------------------------------------------------
+
+# change id's to medium ints instead of ints in 'related_content`
+
+ALTER TABLE `related_content` CHANGE `content_id` `content_id` MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL ,
+CHANGE `related_content_id` `related_content_id` MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL;
+
+#----------------------------------------------------------------
+
+# change id's to medium ints instead of big ints in 'resource_categories`
+
+ALTER TABLE `resource_categories` CHANGE `CatID` `CatID` MEDIUMINT( 8 ) UNSIGNED NOT NULL AUTO_INCREMENT, CHANGE `CatParent` `CatParent` MEDIUMINT( 8 ) UNSIGNED DEFAULT NULL; 
+#----------------------------------------------------------------
+
+# this one too 
+
+ALTER TABLE `resource_links` CHANGE `LinkID` `LinkID` MEDIUMINT( 8 ) UNSIGNED NOT NULL AUTO_INCREMENT, CHANGE `CatID` `CatID` MEDIUMINT( 8 ) UNSIGNED DEFAULT '0' NOT NULL;
+#----------------------------------------------------------------
+
+# revise the theme_settings preferences for two records
+
+UPDATE `theme_settings` SET `preferences` = 'a:27:{s:10:"PREF_STACK";a:6:{i:0;s:1:"5";i:1;s:1:"0";i:2;s:1:"1";i:3;s:1:"3";i:4;s:1:"4";i:5;s:1:"2";}s:19:"PREF_MAIN_MENU_SIDE";i:2;s:8:"PREF_SEQ";i:1;s:14:"PREF_NUMBERING";i:1;s:8:"PREF_TOC";i:1;s:14:"PREF_SEQ_ICONS";i:2;s:14:"PREF_NAV_ICONS";i:2;s:16:"PREF_LOGIN_ICONS";i:2;s:13:"PREF_HEADINGS";i:0;s:16:"PREF_BREADCRUMBS";i:0;s:9:"PREF_FONT";i:0;s:15:"PREF_STYLESHEET";i:0;s:9:"PREF_HELP";i:0;s:14:"PREF_MINI_HELP";i:1;s:18:"PREF_CONTENT_ICONS";i:2;s:14:"PREF_MAIN_MENU";i:0;s:11:"PREF_ONLINE";i:0;s:9:"PREF_MENU";i:1;s:10:"PREF_THEME";i:0;s:12:"PREF_DISPLAY";i:0;s:9:"PREF_TIPS";i:0;s:13:"PREF_OVERRIDE";i:1;s:9:"PREF_EDIT";i:1;s:10:"PREF_LOCAL";i:0;s:13:"PREF_GLOSSARY";i:0;s:11:"PREF_SEARCH";i:1;s:12:"PREF_RELATED";i:0;}' WHERE `theme_id` = '1' LIMIT 1 ;
+
+UPDATE `theme_settings` SET `preferences` = 'a:27:{s:10:"PREF_STACK";a:6:{i:0;s:1:"0";i:1;s:1:"1";i:2;s:1:"2";i:3;s:1:"3";i:4;s:1:"4";i:5;s:1:"5";}s:19:"PREF_MAIN_MENU_SIDE";i:2;s:8:"PREF_SEQ";i:3;s:14:"PREF_NUMBERING";i:1;s:8:"PREF_TOC";i:1;s:14:"PREF_SEQ_ICONS";i:1;s:14:"PREF_NAV_ICONS";i:0;s:16:"PREF_LOGIN_ICONS";i:0;s:13:"PREF_HEADINGS";i:1;s:16:"PREF_BREADCRUMBS";i:1;s:9:"PREF_FONT";i:0;s:15:"PREF_STYLESHEET";i:0;s:9:"PREF_HELP";i:1;s:14:"PREF_MINI_HELP";i:1;s:18:"PREF_CONTENT_ICONS";i:0;s:14:"PREF_MAIN_MENU";i:1;s:11:"PREF_ONLINE";i:1;s:9:"PREF_MENU";i:1;s:13:"PREF_OVERRIDE";i:1;s:11:"PREF_SEARCH";i:1;s:10:"PREF_THEME";i:0;s:12:"PREF_DISPLAY";i:0;s:9:"PREF_TIPS";i:0;s:9:"PREF_EDIT";i:1;s:10:"PREF_LOCAL";i:0;s:13:"PREF_GLOSSARY";i:0;s:12:"PREF_RELATED";i:0;}' WHERE `theme_id` = '4' LIMIT 1 ;
+#----------------------------------------------------------------
diff --git a/install/db/atutor_upgrade_1.3.2_to_1.4.sql b/install/db/atutor_upgrade_1.3.2_to_1.4.sql
new file mode 100644 (file)
index 0000000..45abd4a
--- /dev/null
@@ -0,0 +1,44 @@
+###############################################################
+# Database upgrade SQL from ATutor 1.3.2 to ATutor 1.4
+###############################################################
+
+# add new fields to course_enrollment table
+
+ALTER TABLE `course_enrollment` ADD `privileges` SMALLINT UNSIGNED NOT NULL AFTER `approved` ,
+ADD `role` varchar(35) NOT NULL default '' AFTER `privileges` ;
+
+ALTER TABLE `content` ADD `inherit_release_date` TINYINT UNSIGNED NOT NULL AFTER `text`;
+
+
+# add new fields to forums table
+
+ALTER TABLE `forums` ADD `num_topics` MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL , 
+ADD `num_posts` MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL , 
+ADD `last_post` DATETIME DEFAULT '0000-00-00 00:00:00' NOT NULL ;
+
+
+# add new fields to courses table
+
+ALTER TABLE `courses` ADD `banner_text` TEXT NOT NULL AFTER `copyright` , 
+ADD `banner_styles` TEXT NOT NULL AFTER `banner_text` ;
+
+# remove preferences table
+
+DROP TABLE `preferences`;
+
+# add new fields to tests and tests_questions:
+ALTER TABLE `tests` ADD `content_id` MEDIUMINT UNSIGNED NOT NULL , 
+ADD `automark` TINYINT UNSIGNED NOT NULL , 
+ADD `random` TINYINT UNSIGNED NOT NULL , 
+ADD `difficulty` TINYINT UNSIGNED NOT NULL ;
+
+ALTER TABLE `tests_questions` ADD `content_id` mediumint(8) NOT NULL AFTER `answer_size` ;
+
+
+# update `theme_settings` data
+
+UPDATE `theme_settings` SET preferences='a:24:{s:10:"PREF_STACK";a:6:{i:0;s:1:"5";i:1;s:1:"0";i:2;s:1:"1";i:3;s:1:"3";i:4;s:1:"4";i:5;s:1:"2";}s:19:"PREF_MAIN_MENU_SIDE";i:2;s:8:"PREF_SEQ";i:1;s:14:"PREF_NUMBERING";i:1;s:8:"PREF_TOC";i:1;s:14:"PREF_SEQ_ICONS";i:2;s:14:"PREF_NAV_ICONS";i:2;s:16:"PREF_LOGIN_ICONS";i:2;s:13:"PREF_HEADINGS";i:0;s:16:"PREF_BREADCRUMBS";i:0;s:9:"PREF_HELP";i:0;s:14:"PREF_MINI_HELP";i:1;s:18:"PREF_CONTENT_ICONS";i:2;s:14:"PREF_MAIN_MENU";i:0;s:11:"PREF_ONLINE";i:0;s:9:"PREF_MENU";i:1;s:10:"PREF_THEME";i:0;s:12:"PREF_DISPLAY";i:0;s:9:"PREF_TIPS";i:0;s:9:"PREF_EDIT";i:1;s:10:"PREF_LOCAL";i:0;s:13:"PREF_GLOSSARY";i:0;s:11:"PREF_SEARCH";i:1;s:12:"PREF_RELATED";i:0;}' WHERE theme_id=1;
+UPDATE `theme_settings` SET preferences='a:4:{s:14:"PREF_SEQ_ICONS";i:1;s:14:"PREF_NAV_ICONS";i:1;s:16:"PREF_LOGIN_ICONS";i:1;s:16:"PREF_BREADCRUMBS";i:1;}' WHERE theme_id=2;
+UPDATE `theme_settings` SET preferences='a:5:{s:14:"PREF_MAIN_MENU";i:1;s:14:"PREF_SEQ_ICONS";i:0;s:14:"PREF_NAV_ICONS";i:0;s:16:"PREF_LOGIN_ICONS";i:0;s:16:"PREF_BREADCRUMBS";i:1;}' WHERE theme_id=3;
+UPDATE `theme_settings` SET preferences='a:17:{s:10:"PREF_STACK";a:5:{i:0;i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;i:4;}s:19:"PREF_MAIN_MENU_SIDE";i:2;s:8:"PREF_SEQ";i:3;s:14:"PREF_NUMBERING";i:1;s:8:"PREF_TOC";i:1;s:14:"PREF_SEQ_ICONS";i:0;s:14:"PREF_NAV_ICONS";i:0;s:16:"PREF_LOGIN_ICONS";i:0;s:13:"PREF_HEADINGS";i:1;s:16:"PREF_BREADCRUMBS";i:1;s:9:"PREF_HELP";i:1;s:14:"PREF_MINI_HELP";i:1;s:18:"PREF_CONTENT_ICONS";i:0;s:14:"PREF_MAIN_MENU";i:1;s:11:"PREF_ONLINE";i:1;s:9:"PREF_MENU";i:1;s:10:"PREF_THEME";s:7:"default";}' WHERE theme_id=4;
+
diff --git a/install/db/atutor_upgrade_1.3_to_1.3.2.sql b/install/db/atutor_upgrade_1.3_to_1.3.2.sql
new file mode 100644 (file)
index 0000000..7bc18d4
--- /dev/null
@@ -0,0 +1,12 @@
+###############################################################
+# Database upgrade SQL from ATutor 1.3 to ATutor 1.3.2
+###############################################################
+
+# add new field to course_enrollment table
+
+ALTER TABLE `course_enrollment` ADD `last_cid` MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL;
+
+
+# add new field to content table
+
+ALTER TABLE `content` ADD `inherit_release_date` TINYINT UNSIGNED DEFAULT '0' NOT NULL;
diff --git a/install/db/atutor_upgrade_1.4.1_to_1.4.2.sql b/install/db/atutor_upgrade_1.4.1_to_1.4.2.sql
new file mode 100644 (file)
index 0000000..98eb63e
--- /dev/null
@@ -0,0 +1,11 @@
+###############################################################
+# Database upgrade SQL from ATutor 1.4.1 to ATutor 1.4.2
+###############################################################
+
+# Table structure for table `course_cats`
+ALTER TABLE `course_cats` ADD `theme` VARCHAR( 30 ) NOT NULL ;
+
+
+# Table structure for table `tests`
+ALTER TABLE `tests` ADD `num_takes` TINYINT UNSIGNED NOT NULL ;
+ALTER TABLE `tests` ADD `anonymous` TINYINT DEFAULT '0' NOT NULL ;
diff --git a/install/db/atutor_upgrade_1.4.2_to_1.4.3.sql b/install/db/atutor_upgrade_1.4.2_to_1.4.3.sql
new file mode 100644 (file)
index 0000000..dacd992
--- /dev/null
@@ -0,0 +1,156 @@
+###############################################################
+# Database upgrade SQL from ATutor 1.4.2 to ATutor 1.4.3
+###############################################################
+
+CREATE TABLE `languages` (
+  `language_code` varchar(5) NOT NULL default '',
+  `char_set` varchar(20) NOT NULL default '',
+  `direction` varchar(4) NOT NULL default '',
+  `reg_exp` varchar(31) NOT NULL default '',
+  `native_name` varchar(20) NOT NULL default '',
+  `english_name` varchar(20) NOT NULL default '',
+  `status` TINYINT UNSIGNED DEFAULT '0' NOT NULL,
+  PRIMARY KEY  (`language_code`,`char_set`)
+) TYPE=MyISAM;
+
+INSERT INTO `languages` VALUES ('en', 'iso-8859-1', 'ltr', 'en([-_][[:alpha:]]{2})?|english', 'English', 'English', 3);
+
+# --------------------------------------------------------
+# Table structure for table `language_pages`
+
+CREATE TABLE `language_pages` (
+  `term` varchar(30) NOT NULL default '',
+  `page` varchar(50) NOT NULL default '',
+  PRIMARY KEY  (`term`,`page`)
+) TYPE=MyISAM;
+
+CREATE TABLE `themes` (
+  `title` varchar(20) NOT NULL default '',
+  `version` varchar(10) NOT NULL default '',
+  `dir_name` varchar(20) NOT NULL default '',
+  `last_updated` date NOT NULL default '0000-00-00',
+  `extra_info` varchar(40) NOT NULL default '',
+  `status` tinyint(3) unsigned NOT NULL default '1',
+  PRIMARY KEY  (`title`)
+);
+
+# insert the default theme
+INSERT INTO themes VALUES ('Atutor', '1.4.3', 'default', NOW(), 'This is the default Atutor theme.', 2);
+
+
+# the backups table
+CREATE TABLE `backups` (
+  `backup_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `course_id` mediumint(8) unsigned NOT NULL default '0',
+  `date` datetime NOT NULL default '0000-00-00 00:00:00',
+  `description` varchar(100) NOT NULL default '',
+  `file_size` int(10) unsigned NOT NULL default '0',
+  `system_file_name` varchar(50) NOT NULL default '',
+  `file_name` varchar(50) NOT NULL default '',
+  `contents` TEXT NOT NULL default '',
+  PRIMARY KEY  (`backup_id`),
+  KEY `course_id` (`course_id`)
+) TYPE=MyISAM;
+
+
+##### changes to the `forums_*` tables #####
+
+# the new course forums table
+CREATE TABLE `forums_courses` (
+  `forum_id` MEDIUMINT UNSIGNED NOT NULL default '0',
+  `course_id` MEDIUMINT UNSIGNED NOT NULL default '0',
+  PRIMARY KEY (`forum_id`,`course_id`),
+  KEY `course_id` (`course_id`)
+) TYPE=MyISAM;
+
+# insert the current forums into the new table
+INSERT INTO forums_courses SELECT forum_id, course_id FROM `forums`;
+
+# remove the old course_id from the forums table and forums_threads
+ALTER TABLE `forums` DROP `course_id`;
+ALTER TABLE `forums_threads` DROP `course_id`;
+
+DROP TABLE forums_subscriptions;
+
+# setup forum subscription
+CREATE TABLE `forums_subscriptions` (
+  forum_id mediumint(8) unsigned NOT NULL default '0',
+  member_id mediumint(8) unsigned NOT NULL default '0',
+  PRIMARY KEY  (`forum_id`,`member_id`)
+) TYPE=MyISAM;
+
+
+ALTER TABLE `forums_accessed` ADD `subscribe` TINYINT NOT NULL ;
+
+
+#adding alumni status
+ALTER TABLE `course_enrollment` CHANGE `approved` `approved` ENUM( 'y', 'n', 'a' ) DEFAULT 'n' NOT NULL;
+
+UPDATE `theme_settings` SET `preferences` = 'a:25:{s:10:"PREF_STACK";a:8:{i:0;s:1:"0";i:1;s:1:"1";i:2;s:1:"2";i:3;s:1:"3";i:4;s:1:"4";i:5;s:1:"5";i:6;s:1:"6";i:7;s:1:"7";}s:19:"PREF_MAIN_MENU_SIDE";i:2;s:8:"PREF_SEQ";i:3;s:14:"PREF_NUMBERING";i:1;s:8:"PREF_TOC";i:1;s:14:"PREF_SEQ_ICONS";i:1;s:14:"PREF_NAV_ICONS";i:0;s:16:"PREF_LOGIN_ICONS";i:0;s:13:"PREF_HEADINGS";i:1;s:16:"PREF_BREADCRUMBS";i:1;s:9:"PREF_HELP";i:1;s:14:"PREF_MINI_HELP";i:1;s:18:"PREF_CONTENT_ICONS";i:0;s:14:"PREF_MAIN_MENU";i:1;s:11:"PREF_ONLINE";i:1;s:9:"PREF_MENU";i:1;s:10:"PREF_THEME";s:7:"default";s:9:"PREF_EDIT";i:1;s:18:"PREF_JUMP_REDIRECT";i:0;s:10:"PREF_LOCAL";i:1;s:12:"PREF_RELATED";i:1;s:13:"PREF_GLOSSARY";i:1;s:11:"PREF_SEARCH";i:1;s:10:"PREF_POSTS";i:1;s:9:"PREF_POLL";i:1;}' WHERE `theme_id` = '4';
+
+###### changes to the `tests_*` tables #####
+CREATE TABLE `tests_questions_assoc` (
+  `test_id` mediumint(8) unsigned NOT NULL default '0',
+  `question_id` mediumint(8) unsigned NOT NULL default '0',
+  `weight` varchar(4) NOT NULL default '',
+  `ordering` tinyint(3) unsigned NOT NULL default '0',
+  `required` tinyint(3) unsigned NOT NULL default '0',
+  PRIMARY KEY  (`test_id`,`question_id`),
+  KEY `test_id` (`test_id`)
+) TYPE=MyISAM;
+
+CREATE TABLE `tests_questions_categories` (
+  `category_id` mediumint(8) unsigned NOT NULL auto_increment,
+  `course_id` mediumint(8) unsigned NOT NULL default '0',
+  `title` char(50) NOT NULL default '',
+  PRIMARY KEY  (`category_id`),
+  KEY `course_id` (`course_id`)
+) TYPE=MyISAM;
+
+ALTER TABLE `tests` ADD INDEX ( `course_id` );
+
+INSERT INTO `tests_questions_assoc` SELECT test_id, question_id, weight, ordering, required FROM `tests_questions`;
+
+ALTER TABLE `tests_questions` CHANGE `test_id` `category_id` MEDIUMINT( 8 ) UNSIGNED DEFAULT '0' NOT NULL;
+ALTER TABLE `tests_questions` CHANGE `answer_size` `properties` TINYINT( 4 ) DEFAULT '0' NOT NULL;
+ALTER TABLE `tests_questions` DROP `ordering`, DROP `required`, DROP `weight`;
+UPDATE `tests_questions` SET `category_id`=0;
+
+##### new `groups_*` tables #####
+CREATE TABLE `groups` (
+`group_id` MEDIUMINT UNSIGNED NOT NULL auto_increment,
+`course_id` MEDIUMINT UNSIGNED NOT NULL default '0',
+`title` varchar(20) NOT NULL default '',
+PRIMARY KEY ( `group_id` ),
+KEY `course_id` (`course_id`)
+) TYPE=MyISAM;
+
+
+CREATE TABLE `groups_members` (
+`group_id` MEDIUMINT UNSIGNED NOT NULL default '0',
+`member_id` MEDIUMINT UNSIGNED NOT NULL default '0',
+ PRIMARY KEY  (`group_id`,`member_id`)
+);
+
+
+CREATE TABLE `tests_groups` (
+  `test_id` MEDIUMINT UNSIGNED NOT NULL default '0',
+  `group_id` MEDIUMINT UNSIGNED NOT NULL default '0',
+  PRIMARY KEY (`test_id`,`group_id`),
+  KEY `test_id` (`test_id`)
+) TYPE=MyISAM;
+
+
+# Add tracking g for the search tool
+INSERT INTO g_refs VALUES (37, 'g_search');
+
+# Change automark to selective release field
+ALTER TABLE `tests` CHANGE `automark` `result_release` TINYINT( 4 ) UNSIGNED DEFAULT '0' NOT NULL;
+ALTER TABLE `tests` ADD `out_of` VARCHAR( 5 ) NOT NULL ;
+
+UPDATE tests SET result_release=0;
+DROP TABLE `lang2`;
+DROP TABLE `lang_base`;
+
+# add RSS feeds to courses
+ALTER TABLE `courses` ADD `rss` TINYINT DEFAULT '0' NOT NULL ;
\ No newline at end of file
diff --git a/install/db/atutor_upgrade_1.4.3_to_1.5.sql b/install/db/atutor_upgrade_1.4.3_to_1.5.sql
new file mode 100644 (file)
index 0000000..2531c0c
--- /dev/null
@@ -0,0 +1,80 @@
+###############################################################\r
+# Database upgrade SQL from ATutor 1.4.3 to ATutor 1.5\r
+###############################################################\r
+\r
+ALTER TABLE `courses` ADD `icon` VARCHAR( 20 ) NOT NULL , ADD `home_links` VARCHAR( 255 ) NOT NULL , ADD `main_links` VARCHAR( 255 ) NOT NULL , ADD `side_menu` VARCHAR( 255 ) NOT NULL;\r
+\r
+UPDATE `courses` SET home_links='forum/list.php|glossary/index.php|chat/index.php|tile.php|links/index.php|tools/my_tests.php|sitemap.php|export.php|my_stats.php|polls/index.php|directory.php';\r
+UPDATE `courses` SET main_links='forum/list.php|glossary/index.php';\r
+UPDATE `courses` SET side_menu ='menu_menu|related_topics|users_online|glossary|search|poll|posts';\r
+\r
+#fix for backup file names\r
+ALTER TABLE `backups` CHANGE `file_name` `file_name` VARCHAR( 150 ) NOT NULL;\r
+\r
+\r
+CREATE TABLE `member_track` (\r
+  `member_id` mediumint(8) unsigned NOT NULL default '0',\r
+  `course_id` mediumint(8) unsigned NOT NULL default '0',\r
+  `content_id` mediumint(8) unsigned NOT NULL default '0',\r
+  `counter` mediumint(8) unsigned NOT NULL default '0',\r
+  `duration` mediumint(8) unsigned NOT NULL default '0',\r
+  `last_accessed` datetime default NULL,\r
+  KEY `member_id` (`member_id`),\r
+  KEY `content_id` (`content_id`)\r
+) TYPE=MyISAM;\r
+\r
+\r
+CREATE TABLE `admins` (\r
+   `login` VARCHAR( 30 ) NOT NULL ,\r
+   `password` VARCHAR( 30 ) NOT NULL ,\r
+   `real_name` VARCHAR( 30 ) NOT NULL ,\r
+   `email` VARCHAR( 50 ) NOT NULL ,\r
+   `language` varchar(5) NOT NULL default '',\r
+   `privileges` MEDIUMINT UNSIGNED NOT NULL ,\r
+   `last_login` DATETIME NOT NULL ,\r
+   PRIMARY KEY ( `login` )\r
+);\r
+\r
+-- Table structure for table `admin_log`\r
+\r
+CREATE TABLE `admin_log` (\r
+  `login` varchar(30) NOT NULL default '',\r
+  `time` datetime NOT NULL default '0000-00-00 00:00:00',\r
+  `operation` varchar(20) NOT NULL default '',\r
+  `table` varchar(30) NOT NULL default '',\r
+  `num_affected` tinyint(3) NOT NULL default '0',\r
+  `details` varchar(255) NOT NULL default '',\r
+  KEY `login` (`login`)\r
+) TYPE=MyISAM;\r
+\r
+ALTER TABLE `courses` DROP `tracking` ;\r
+\r
+ALTER TABLE `members` ADD `inbox_notify` TINYINT(3) UNSIGNED DEFAULT '0' NOT NULL ;\r
+## instructors:\r
+UPDATE `members` SET `status`=3 WHERE `status`=1;\r
+## students:\r
+UPDATE `members` SET `status`=2 WHERE `status`=0;\r
+\r
+DROP TABLE `learning_concepts`;\r
+DROP TABLE `theme_settings`;\r
+\r
+ALTER TABLE `courses` CHANGE `primary_language` `primary_language` VARCHAR( 5 ) NOT NULL;\r
+ALTER TABLE `members` CHANGE `language` `language` VARCHAR( 5 ) NOT NULL;\r
+\r
+UPDATE `themes` SET status=0;\r
+ALTER TABLE `themes` CHANGE `extra_info` `extra_info` VARCHAR( 255 ) NOT NULL;\r
+REPLACE INTO `themes` VALUES ('ATutor', '1.5', 'default', NOW(), 'This is the default ATutor theme and cannot be deleted as other themes inherit from it. Please do not alter this theme directly as it would complicate upgrading. Instead, create a new theme derived from this one.', 2);\r
+\r
+REPLACE INTO `themes` VALUES ('ATutor Classic', '1.5', 'default_classic', NOW(), 'This is the ATutor Classic theme which makes use of the custom Header and logo images. To customize those images you must edit the <code>theme.cfg.php</code> in this theme\'s directory.', 1);\r
+\r
+\r
+ALTER TABLE `messages` ADD `course_id` MEDIUMINT( 8 ) UNSIGNED DEFAULT '0' NOT NULL AFTER `message_id` ;\r
+\r
+\r
+# Table structure for table `master_list`\r
+CREATE TABLE `master_list` (\r
+  `public_field` CHAR( 30 ) NOT NULL ,\r
+  `hash_field` CHAR( 40 ) NOT NULL ,\r
+  `member_id` MEDIUMINT UNSIGNED NOT NULL 0,\r
+  PRIMARY KEY ( `public_field` )\r
+);\r
diff --git a/install/db/atutor_upgrade_1.4_to_1.4.1.sql b/install/db/atutor_upgrade_1.4_to_1.4.1.sql
new file mode 100644 (file)
index 0000000..4d86e24
--- /dev/null
@@ -0,0 +1,45 @@
+###############################################################
+# Database upgrade SQL from ATutor 1.4 to ATutor 1.4.1
+###############################################################
+
+# Table structure for table `polls`
+CREATE TABLE `polls` (
+  `poll_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT ,
+  `course_id` MEDIUMINT UNSIGNED NOT NULL ,
+  `question` VARCHAR( 100 ) NOT NULL ,
+  `created_date` DATETIME NOT NULL ,
+  `total` SMALLINT UNSIGNED NOT NULL ,
+  `choice1` VARCHAR( 100 ) NOT NULL ,
+  `count1` SMALLINT UNSIGNED NOT NULL ,
+  `choice2` VARCHAR( 100 ) NOT NULL ,
+  `count2` SMALLINT UNSIGNED NOT NULL ,
+  `choice3` VARCHAR( 100 ) NOT NULL ,
+  `count3` SMALLINT UNSIGNED NOT NULL ,
+  `choice4` VARCHAR( 100 ) NOT NULL ,
+  `count4` SMALLINT UNSIGNED NOT NULL ,
+  `choice5` VARCHAR( 100 ) NOT NULL ,
+  `count5` SMALLINT UNSIGNED NOT NULL ,
+  `choice6` VARCHAR( 100 ) NOT NULL ,
+  `count6` SMALLINT UNSIGNED NOT NULL ,
+  `choice7` VARCHAR( 100 ) NOT NULL ,
+  `count7` SMALLINT UNSIGNED NOT NULL ,
+  PRIMARY KEY ( `poll_id` ) ,
+  INDEX ( `course_id` )
+) TYPE=MyISAM;
+
+# --------------------------------------------------------
+
+# Table structure for table `polls_members`
+
+CREATE TABLE `polls_members` (
+  `poll_id` MEDIUMINT UNSIGNED NOT NULL ,
+  `member_id` MEDIUMINT UNSIGNED NOT NULL ,
+  PRIMARY KEY ( `poll_id` , `member_id` )
+) TYPE=MyISAM;
+
+
+# Change age to date of birth 
+ALTER TABLE `members` CHANGE `age` `dob` DATE NOT NULL;
+
+# Add `primary_language` to the `courses` table
+ALTER TABLE `courses` ADD `primary_language` VARCHAR( 4 ) DEFAULT 'en' NOT NULL;
diff --git a/install/db/atutor_upgrade_1.5.1_to_1.5.2.sql b/install/db/atutor_upgrade_1.5.1_to_1.5.2.sql
new file mode 100644 (file)
index 0000000..586730f
--- /dev/null
@@ -0,0 +1,91 @@
+###############################################################\r
+# Database upgrade SQL from ATutor 1.5.1 to ATutor 1.5.2\r
+###############################################################\r
+\r
+# --------------------------------------------------------\r
+# Table structure for table `faq_topics`\r
+\r
+CREATE TABLE `faq_topics` (\r
+  `topic_id` mediumint(8) NOT NULL auto_increment,\r
+  `course_id` mediumint(8) unsigned NOT NULL default '0',\r
+  `name` varchar(250) NOT NULL default '',\r
+  KEY `course_id` (`course_id`),\r
+  PRIMARY KEY  (`topic_id`)\r
+) ;\r
+\r
+# --------------------------------------------------------\r
+# Table structure for table `faq_entries`\r
+CREATE TABLE `faq_entries` (\r
+  `entry_id` mediumint(8) NOT NULL auto_increment,\r
+  `topic_id` mediumint(8) NOT NULL default '0',\r
+  `revised_date` datetime NOT NULL default '0000-00-00 00:00:00',\r
+  `approved` tinyint(4) NOT NULL default '0',\r
+  `question` varchar(250) NOT NULL default '',\r
+  `answer` text NOT NULL,\r
+  PRIMARY KEY  (`entry_id`)\r
+) ;\r
+\r
+# --------------------------------------------------------\r
+# Table structure for table `feeds`\r
+CREATE TABLE `feeds` (\r
+  `feed_id` mediumint(8) unsigned NOT NULL auto_increment,\r
+  `url` varchar(255) NOT NULL default '',\r
+  PRIMARY KEY  (`feed_id`)\r
+) ;\r
+\r
+\r
+\r
+# Table structure for table `config`\r
+\r
+CREATE TABLE `config` (\r
+  `name` CHAR( 30 ) NOT NULL ,\r
+  `value` CHAR( 255 ) NOT NULL ,\r
+PRIMARY KEY ( `name` )\r
+);\r
+\r
+# modules\r
+\r
+CREATE TABLE `modules` (  \r
+`dir_name` VARCHAR( 50 ) NOT NULL ,  \r
+`status` TINYINT NOT NULL ,  \r
+`privilege` MEDIUMINT UNSIGNED NOT NULL ,  \r
+`admin_privilege` MEDIUMINT UNSIGNED NOT NULL ,\r
+PRIMARY KEY ( `dir_name` )  \r
+);\r
+\r
+INSERT INTO `modules` VALUES ('_core/properties',        2, 1,         0);\r
+INSERT INTO `modules` VALUES ('_standard/statistics',    2, 1,         0);\r
+INSERT INTO `modules` VALUES ('_core/content',           2, 2,         0);\r
+INSERT INTO `modules` VALUES ('_core/glossary',          2, 4,         0);\r
+INSERT INTO `modules` VALUES ('_standard/tests',         2, 8,         0);\r
+INSERT INTO `modules` VALUES ('_standard/chat',          2, 16,        0);\r
+INSERT INTO `modules` VALUES ('_core/file_manager',      2, 32,        0);\r
+INSERT INTO `modules` VALUES ('_standard/links',         2, 64,        0);\r
+INSERT INTO `modules` VALUES ('_standard/forums',        2, 128,       16);\r
+INSERT INTO `modules` VALUES ('_standard/student_tools', 2, 256,       0);\r
+INSERT INTO `modules` VALUES ('_core/enrolment',         2, 512,       0);\r
+INSERT INTO `modules` VALUES ('_standard/course_email',  2, 1024,      0);\r
+INSERT INTO `modules` VALUES ('_standard/announcements', 2, 2048,      0);\r
+# INSERT INTO `modules` VALUES ('acollab',               2, 8192+4096, 0);\r
+INSERT INTO `modules` VALUES ('_standard/polls',         2, 16384,     0);\r
+INSERT INTO `modules` VALUES ('_standard/faq',           2, 32768,     0);\r
+INSERT INTO `modules` VALUES ('_core/users',             2, 0,         2);\r
+INSERT INTO `modules` VALUES ('_core/courses',           2, 0,         4);\r
+INSERT INTO `modules` VALUES ('_core/backups',           2, 1,         8);\r
+INSERT INTO `modules` VALUES ('_core/cats_categories',   2, 0,         32);\r
+INSERT INTO `modules` VALUES ('_core/languages',         2, 0,         64);\r
+INSERT INTO `modules` VALUES ('_core/themes',            2, 0,         128);\r
+INSERT INTO `modules` VALUES ('_standard/rss_feeds',    2, 0,         256);\r
+INSERT INTO `modules` VALUES ('_core/groups',            2, 0, 0);\r
+INSERT INTO `modules` VALUES ('_standard/directory',     2, 0, 0);\r
+INSERT INTO `modules` VALUES ('_standard/tile_search',   2, 0, 0);\r
+INSERT INTO `modules` VALUES ('_standard/sitemap',       2, 0, 0);\r
+INSERT INTO `modules` VALUES ('_standard/tracker',       2, 0, 0);\r
+INSERT INTO `modules` VALUES ('_core/content_packaging', 2, 0, 0);\r
+INSERT INTO `modules` VALUES ('_standard/google_search', 2, 0, 0);\r
+\r
+\r
+ALTER TABLE `admin_log` CHANGE `details` `details` TEXT NOT NULL;\r
+\r
+\r
+ALTER TABLE `courses` CHANGE `home_links` `home_links` TEXT NOT NULL ,CHANGE `main_links` `main_links` TEXT NOT NULL;\r
diff --git a/install/db/atutor_upgrade_1.5.2_to_1.5.3.sql b/install/db/atutor_upgrade_1.5.2_to_1.5.3.sql
new file mode 100644 (file)
index 0000000..02c46a9
--- /dev/null
@@ -0,0 +1,218 @@
+###############################################################\r
+# Database upgrade SQL from ATutor 1.5.2 to ATutor 1.5.3\r
+###############################################################\r
+\r
+CREATE TABLE `groups_types` (\r
+       `type_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT ,\r
+       `course_id` MEDIUMINT UNSIGNED NOT NULL default '0',\r
+       `title` VARCHAR( 80 ) NOT NULL default '',\r
+       PRIMARY KEY ( `type_id` ) ,\r
+       KEY ( `course_id` )\r
+) TYPE = MYISAM;\r
+\r
+ALTER TABLE `groups` CHANGE `course_id` `type_id` MEDIUMINT( 8 ) UNSIGNED DEFAULT '0' NOT NULL;\r
+ALTER TABLE `groups` ADD `description` TEXT NOT NULL default '' , ADD `modules` VARCHAR(100) NOT NULL default '';\r
+\r
+UPDATE `modules` SET `privilege`=1048576 WHERE `dir_name`='_core/groups';\r
+INSERT INTO `modules` VALUES ('_standard/reading_list',  2, 131072,    0);\r
+INSERT INTO `modules` VALUES ('_standard/file_storage',  2, 262144,    0);\r
+INSERT INTO `modules` VALUES ('_standard/assignments',   2, 524288,    0);\r
+\r
+# cron support for modules\r
+#Dec 6, 2007 - duplicated column name\r
+ALTER TABLE `modules` ADD `cron_interval` SMALLINT UNSIGNED DEFAULT '0' NOT NULL , ADD `cron_last_run` INT UNSIGNED DEFAULT '0' NOT NULL ;\r
+\r
+\r
+# forum groups table\r
+CREATE TABLE `forums_groups` (\r
+  `forum_id` mediumint( 8 ) unsigned NOT NULL default '0',\r
+  `group_id` mediumint( 8 ) unsigned NOT NULL default '0',\r
+  PRIMARY KEY ( `forum_id` , `group_id` ) ,\r
+  KEY `group_id` ( `group_id` )\r
+) TYPE = MYISAM ;\r
+\r
+# release date for courses\r
+ALTER TABLE `courses` ADD `release_date` datetime NOT NULL default '0000-00-00 00:00:00';\r
+ALTER TABLE `courses` ADD `banner` TEXT NOT NULL default '';\r
+\r
+# --------------------------------------------------------\r
+# Table structure for table `reading_list`\r
+\r
+CREATE TABLE `reading_list` (\r
+       `reading_id` MEDIUMINT(6) UNSIGNED NOT NULL AUTO_INCREMENT,\r
+       `course_id` MEDIUMINT UNSIGNED NOT NULL default 0,\r
+       `resource_id` MEDIUMINT UNSIGNED NOT NULL default 0,\r
+       `required` enum('required','optional') NOT NULL DEFAULT 'required',\r
+       `date_start` DATE NOT NULL DEFAULT '0000-00-00',\r
+       `date_end` DATE NOT NULL DEFAULT '0000-00-00',\r
+       `comment` text NOT NULL default '',\r
+       PRIMARY KEY  (`reading_id`),\r
+       INDEX (`course_id`)\r
+) TYPE = MYISAM;\r
+\r
+# Table structure for table `external_resources`\r
+\r
+CREATE TABLE `external_resources` (\r
+       `resource_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,\r
+       `course_id` MEDIUMINT UNSIGNED NOT NULL default 0,\r
+       `type` TINYINT UNSIGNED NOT NULL DEFAULT 0,\r
+       `title` varchar(255) NOT NULL DEFAULT '',\r
+       `author` varchar(150) NOT NULL DEFAULT '',\r
+       `publisher` varchar(150) NOT NULL DEFAULT '',\r
+       `date` varchar(20) NOT NULL DEFAULT '',\r
+       `comments` varchar(255) NOT NULL DEFAULT '',\r
+       `id` varchar(50) NOT NULL DEFAULT '',\r
+       `url` varchar(255) NOT NULL DEFAULT '',\r
+       PRIMARY KEY (`resource_id`),\r
+       INDEX (`course_id`)\r
+) TYPE = MYISAM;\r
+\r
+# for the file storage\r
+# --------------------------------------------------------\r
+\r
+CREATE TABLE `file_storage_groups` (\r
+  `group_id` MEDIUMINT UNSIGNED NOT NULL default '0',\r
+  PRIMARY KEY ( `group_id` )\r
+) TYPE = MYISAM;\r
+\r
+\r
+CREATE TABLE `files` (\r
+  `file_id` mediumint(8) unsigned NOT NULL auto_increment,\r
+  `owner_type` tinyint(3) unsigned NOT NULL default '0',\r
+  `owner_id` mediumint(8) unsigned NOT NULL default '0',\r
+  `member_id` mediumint(8) unsigned NOT NULL default '0',\r
+  `folder_id` mediumint(8) unsigned NOT NULL default '0',\r
+  `parent_file_id` mediumint(8) unsigned NOT NULL default '0',\r
+  `date` datetime NOT NULL default '0000-00-00 00:00:00',\r
+  `num_comments` tinyint(3) unsigned NOT NULL default '0',\r
+  `num_revisions` tinyint(3) unsigned NOT NULL default '0',\r
+  `file_name` varchar(80) NOT NULL default '',\r
+  `file_size` int(11) NOT NULL default '0',\r
+  `description` text NOT NULL default '',\r
+  PRIMARY KEY  (`file_id`)\r
+) TYPE=MyISAM;\r
+\r
+CREATE TABLE `files_comments` (\r
+  `comment_id` mediumint(8) unsigned NOT NULL auto_increment,\r
+  `file_id` mediumint(8) unsigned NOT NULL default '0',\r
+  `member_id` mediumint(8) unsigned NOT NULL default '0',\r
+  `date` datetime NOT NULL default '0000-00-00 00:00:00',\r
+  `comment` text NOT NULL default '',\r
+  PRIMARY KEY  (`comment_id`)\r
+) TYPE=MyISAM;\r
+\r
+CREATE TABLE `folders` (\r
+  `folder_id` mediumint(8) unsigned NOT NULL auto_increment,\r
+  `parent_folder_id` mediumint(8) unsigned NOT NULL default '0',\r
+  `owner_type` tinyint(3) unsigned NOT NULL default '0',\r
+  `owner_id` mediumint(8) unsigned NOT NULL default '0',\r
+  `title` varchar(30) NOT NULL default '',\r
+  PRIMARY KEY  (`folder_id`)\r
+) TYPE=MyISAM;\r
+\r
+## assignment manager\r
+CREATE TABLE `assignments` (\r
+  `assignment_id` MEDIUMINT(6) UNSIGNED NOT NULL AUTO_INCREMENT,\r
+  `course_id` MEDIUMINT UNSIGNED NOT NULL default 0,\r
+  `title` VARCHAR(60) NOT NULL default '',\r
+  `assign_to` MEDIUMINT UNSIGNED DEFAULT 0,\r
+  `date_due` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',\r
+  `date_cutoff` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',\r
+  `multi_submit` TINYINT DEFAULT '0',\r
+  PRIMARY KEY  (`assignment_id`),\r
+  INDEX (`course_id`)\r
+) TYPE = MYISAM;\r
+\r
+# make the privs field bigger\r
+ALTER TABLE `course_enrollment` CHANGE `privileges` `privileges` INT UNSIGNED DEFAULT '0' NOT NULL;\r
+ALTER TABLE `modules` CHANGE `privilege` `privilege` INT UNSIGNED DEFAULT '0' NOT NULL;\r
+\r
+# second name field\r
+ALTER TABLE `members` ADD `second_name` CHAR( 30 ) NOT NULL default '' AFTER `first_name` ;\r
+ALTER TABLE `members` ADD `private_email` TINYINT DEFAULT '1' NOT NULL ;\r
+\r
+# increase length of users_online `login` field to support a full display name. or close to it.\r
+ALTER TABLE `users_online` CHANGE `login` `login` varchar(255) NOT NULL default '';\r
+\r
+# Table structure for table `mail_queue`\r
+# since 1.5.3\r
+CREATE TABLE `mail_queue` (\r
+  `mail_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT ,\r
+  `to_email` VARCHAR( 50 ) NOT NULL default '',\r
+  `to_name` VARCHAR( 50 ) NOT NULL default '',\r
+  `from_email` VARCHAR( 50 ) NOT NULL default '',\r
+  `from_name` VARCHAR( 50 ) NOT NULL default '',\r
+  `char_set` VARCHAR( 20 ) NOT NULL default '',\r
+  `subject` VARCHAR( 200 ) NOT NULL default '',\r
+  `body` TEXT NOT NULL default '',\r
+  PRIMARY KEY ( `mail_id` )\r
+) TYPE = MYISAM;\r
+\r
+#install new themes\r
+\r
+INSERT INTO `themes` VALUES ('Blumin', '1.5.3', 'blumin', NOW(), 'This is the plone look-alike theme.', 1);\r
+\r
+# --------------------------------------------------------\r
+## Table for `blog_posts`\r
+\r
+CREATE TABLE `blog_posts` (\r
+  `post_id` mediumint(8) unsigned NOT NULL auto_increment,\r
+  `member_id` mediumint(8) unsigned NOT NULL default '0',\r
+  `owner_type` tinyint(3) unsigned NOT NULL default '0',\r
+  `owner_id` mediumint(8) unsigned NOT NULL default '0',\r
+  `private` tinyint(3) unsigned NOT NULL default '0',\r
+  `date` datetime NOT NULL default '0000-00-00 00:00:00',\r
+  `num_comments` tinyint(3) unsigned NOT NULL default '0',\r
+  `title` varchar(100) NOT NULL default '',\r
+  `body` text NOT NULL default '',\r
+  PRIMARY KEY  (`post_id`)\r
+) TYPE=MyISAM;\r
+\r
+## Table for `blog_posts_comments`\r
+# --------------------------------------------------------\r
+CREATE TABLE `blog_posts_comments` (\r
+   `comment_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT ,\r
+   `post_id` MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL ,\r
+   `member_id` MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL ,\r
+   `date` DATETIME NOT NULL default '0000-00-00 00:00:00',\r
+   `private` TINYINT UNSIGNED DEFAULT '0' NOT NULL ,\r
+   `comment` TEXT NOT NULL default '',\r
+   PRIMARY KEY ( `comment_id` ) ,\r
+   INDEX ( `post_id` )\r
+) TYPE = MYISAM;\r
+\r
+## add blog to the modules (added to 1.5.3.1)\r
+##INSERT INTO `modules` VALUES ('_standard/blogs',         2, 0, 0, 0, 0);\r
+\r
+\r
+ALTER TABLE `members` CHANGE `gender` `gender` ENUM( 'm', 'f', 'n' ) DEFAULT 'n' NOT NULL;\r
+\r
+## link table updates\r
+# Dec,6, 2007 duplicated column name\r
+ ALTER TABLE `resource_categories` RENAME `links_categories` ;\r
+# Dec,6, 2007 duplicated column name\r
+ ALTER TABLE `links_categories` \r
+       CHANGE `CatID` `cat_id` mediumint(8) unsigned NOT NULL auto_increment , \r
+       CHANGE `course_id` `owner_id` mediumint(8) unsigned NOT NULL default '0' , \r
+       CHANGE `CatName` `name` varchar(100) NOT NULL default '' , \r
+       CHANGE `CatParent` `parent_id` mediumint(8) unsigned default NULL , \r
+       ADD `owner_type` tinyint(4) NOT NULL default '0' AFTER `cat_id` ;\r
+\r
+# Dec,6, 2007 duplicated column name\r
+ALTER TABLE `links_categories` \r
+       DROP INDEX `course_id` ,\r
+       ADD INDEX `owner_id` ( `owner_id` );\r
+\r
+UPDATE `links_categories` SET owner_type=1 WHERE owner_type=0 ;\r
+\r
+# Dec,6, 2007 duplicated column name\r
+ALTER TABLE `resource_links` RENAME `links` ;\r
+ALTER TABLE `links` \r
+       CHANGE `LinkID` `link_id` mediumint(8) unsigned NOT NULL auto_increment , \r
+        CHANGE `CatID` `cat_id` mediumint(8) unsigned NOT NULL default '0' ;\r
+\r
+\r
+ALTER TABLE `members` CHANGE `gender` `gender` ENUM( 'm', 'f', 'n' ) DEFAULT 'n' NOT NULL;\r
+\r
+# Dec,6, 2007 duplicated column name\r
+ALTER TABLE `handbook_notes` ADD `approved` TINYINT DEFAULT '0' NOT NULL AFTER `page` ;\r
diff --git a/install/db/atutor_upgrade_1.5.3.1_to_1.5.3.2.sql b/install/db/atutor_upgrade_1.5.3.1_to_1.5.3.2.sql
new file mode 100644 (file)
index 0000000..50b0934
--- /dev/null
@@ -0,0 +1,5 @@
+###############################################################
+# Database upgrade SQL from ATutor 1.5.3.1 to ATutor 1.5.3.2
+###############################################################
+
+UPDATE `modules` SET `cron_interval` = '1440' WHERE `dir_name` = '_core/languages';
diff --git a/install/db/atutor_upgrade_1.5.3.2_to_1.5.3.3.sql b/install/db/atutor_upgrade_1.5.3.2_to_1.5.3.3.sql
new file mode 100644 (file)
index 0000000..4d0d6f5
--- /dev/null
@@ -0,0 +1,27 @@
+###############################################################\r
+# Database upgrade SQL from ATutor 1.5.3.2 to ATutor 1.5.3.3\r
+###############################################################\r
+\r
+# convert DATETIME fields to TIMESTAMP\r
+ALTER TABLE `admins`                CHANGE `last_login` `last_login`       TIMESTAMP     NULL ;\r
+ALTER TABLE `admin_log`             CHANGE `time` `time`                   TIMESTAMP NOT NULL ;\r
+\r
+ALTER TABLE `backups`               CHANGE `date` `date`                   TIMESTAMP NOT NULL ;\r
+ALTER TABLE `blog_posts`            CHANGE `date` `date`                   TIMESTAMP NOT NULL ;\r
+ALTER TABLE `blog_posts_comments`   CHANGE `date` `date`                   TIMESTAMP NOT NULL ;\r
+ALTER TABLE `content`               CHANGE `last_modified` `last_modified` TIMESTAMP NOT NULL ;\r
+\r
+ALTER TABLE `faq_entries`           CHANGE `revised_date` `revised_date`   TIMESTAMP NOT NULL ;\r
+ALTER TABLE `files`                 CHANGE `date` `date`                   TIMESTAMP NOT NULL ;\r
+ALTER TABLE `files_comments`        CHANGE `date` `date`                   TIMESTAMP NOT NULL ;\r
+ALTER TABLE `forums`                CHANGE `last_post` `last_post`         TIMESTAMP NOT NULL ;\r
+ALTER TABLE `forums_threads`       CHANGE `last_comment` `last_comment`   TIMESTAMP NOT NULL ,\r
+                                    CHANGE `date` `date`                   TIMESTAMP NOT NULL ;\r
+ALTER TABLE `handbook_notes`        CHANGE `date` `date`                   TIMESTAMP NOT NULL ;\r
+ALTER TABLE `instructor_approvals`  CHANGE `request_date` `request_date`   TIMESTAMP NOT NULL ;\r
+ALTER TABLE `members`               CHANGE `creation_date` `creation_date` TIMESTAMP NOT NULL ;\r
+ALTER TABLE `member_track`          CHANGE `last_accessed` `last_accessed` TIMESTAMP     NULL ;\r
+ALTER TABLE `messages`              CHANGE `date_sent` `date_sent`         TIMESTAMP NOT NULL ;\r
+ALTER TABLE `news`                  CHANGE `date` `date`                   TIMESTAMP NOT NULL ;\r
+ALTER TABLE `polls`                 CHANGE `created_date` `created_date`   TIMESTAMP NOT NULL ;\r
+ALTER TABLE `tests_results`         CHANGE `date_taken` `date_taken`       TIMESTAMP NOT NULL ;\r
diff --git a/install/db/atutor_upgrade_1.5.3.3_to_1.5.4.sql b/install/db/atutor_upgrade_1.5.3.3_to_1.5.4.sql
new file mode 100644 (file)
index 0000000..2913e38
--- /dev/null
@@ -0,0 +1,56 @@
+###############################################################
+# Database upgrade SQL from ATutor 1.5.3.3 to ATutor 1.5.4
+###############################################################
+
+## alter the test questions table to support matching type questions
+
+ALTER TABLE `tests_questions` ADD `option_0` VARCHAR( 255 ) NOT NULL AFTER `answer_9` ,
+ADD `option_1` VARCHAR( 255 ) NOT NULL AFTER `option_0` ,
+ADD `option_2` VARCHAR( 255 ) NOT NULL AFTER `option_1` ,
+ADD `option_3` VARCHAR( 255 ) NOT NULL AFTER `option_2` ,
+ADD `option_4` VARCHAR( 255 ) NOT NULL AFTER `option_3` ,
+ADD `option_5` VARCHAR( 255 ) NOT NULL AFTER `option_4` ,
+ADD `option_6` VARCHAR( 255 ) NOT NULL AFTER `option_5` ,
+ADD `option_7` VARCHAR( 255 ) NOT NULL AFTER `option_6` ,
+ADD `option_8` VARCHAR( 255 ) NOT NULL AFTER `option_7` ,
+ADD `option_9` VARCHAR( 255 ) NOT NULL AFTER `option_8` ;
+
+## alter the tests table to support guest tests
+ALTER TABLE `tests` ADD `guests` TINYINT NOT NULL DEFAULT '0';
+
+# --------------------------------------------------------
+# Table structure for table `course_access`
+
+CREATE TABLE `course_access` (
+  `password` char(8) NOT NULL ,
+  `course_id` mediumint(8) unsigned NOT NULL ,
+  `expiry_date` timestamp NOT NULL ,
+  `enabled` tinyint(4) NOT NULL ,
+  PRIMARY KEY ( `password` ) ,
+  UNIQUE (`course_id`)
+) TYPE=MyISAM ;
+
+## alter the members table to support last login
+ALTER TABLE `members` ADD `last_login` TIMESTAMP NOT NULL ;
+
+## alter the forums table to support minutes to edit
+ALTER TABLE `forums` ADD `mins_to_edit` SMALLINT UNSIGNED NOT NULL DEFAULT '0';
+
+## table for saving sent inbox messages
+CREATE TABLE `messages_sent` (
+   `message_id` mediumint( 8 ) unsigned NOT NULL AUTO_INCREMENT ,
+   `course_id` mediumint( 8 ) unsigned NOT NULL default '0',
+   `from_member_id` mediumint( 8 ) unsigned NOT NULL default '0',
+   `to_member_id` mediumint( 8 ) unsigned NOT NULL default '0',
+   `date_sent` timestamp NOT NULL ,
+   `subject` varchar( 150 ) NOT NULL default '',
+   `body` text NOT NULL ,
+   PRIMARY KEY ( `message_id` ) ,
+   KEY `from_member_id` ( `from_member_id` )
+) TYPE = MYISAM;
+
+## add the profile_pictures module
+INSERT INTO `modules` VALUES ('_standard/profile_pictures', 2, 0, 0, 0, 0);
+
+## remove inherit_release_date field
+ALTER TABLE `content` DROP `inherit_release_date`;
diff --git a/install/db/atutor_upgrade_1.5.3_to_1.5.3.1.sql b/install/db/atutor_upgrade_1.5.3_to_1.5.3.1.sql
new file mode 100644 (file)
index 0000000..82de9ed
--- /dev/null
@@ -0,0 +1,5 @@
+###############################################################\r
+# Database upgrade SQL from ATutor 1.5.3 to ATutor 1.5.3.1\r
+###############################################################\r
+\r
+INSERT INTO `modules` VALUES ('_standard/blogs',         2, 0, 0, 0, 0);\r
diff --git a/install/db/atutor_upgrade_1.5.4_to_1.5.5.sql b/install/db/atutor_upgrade_1.5.4_to_1.5.5.sql
new file mode 100644 (file)
index 0000000..8a2902a
--- /dev/null
@@ -0,0 +1,17 @@
+###############################################################
+# Database upgrade SQL from ATutor 1.5.4 to ATutor 1.5.5
+###############################################################
+
+
+## remove login field - #3032
+ALTER TABLE `forums_threads` DROP `login`;
+
+## refresh test issue - #2362
+ALTER TABLE `tests_questions_assoc` DROP INDEX `test_id`;
+ALTER TABLE `tests_results` ADD `status` TINYINT NOT NULL DEFAULT '0';
+
+## times tests - #3084
+ALTER TABLE `tests_results` ADD `end_time` TIMESTAMP NOT NULL ;
+
+## end date - #3089
+ALTER TABLE `courses` ADD `end_date` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `release_date`;
diff --git a/install/db/atutor_upgrade_1.5.5_to_1.6.sql b/install/db/atutor_upgrade_1.5.5_to_1.6.sql
new file mode 100644 (file)
index 0000000..5c4ce29
--- /dev/null
@@ -0,0 +1,16 @@
+###############################################################
+# Database upgrade SQL from ATutor 1.5.5 to ATutor 1.5.6
+###############################################################
+
+# one question per page - #3090
+ALTER TABLE `tests_results` ADD `max_pos` TINYINT UNSIGNED NOT NULL DEFAULT '0';
+ALTER TABLE `tests` ADD `display` TINYINT NOT NULL DEFAULT '0';
+
+INSERT INTO `themes` VALUES ('Greenmin', '1.6', 'greenmin', NOW(), 'This is the plone look-alike theme in green.', 1);
+INSERT INTO `themes` VALUES ('ATutor 1.5', '1.6', 'default15', NOW(), 'This is the 1.5 series default theme.', 1);
+UPDATE  `languages` SET char_set='utf-8' WHERE language_code = 'en';
+
+# Support SHA1 encryption for admins table
+ALTER TABLE `admins` MODIFY COLUMN `password` VARCHAR(40) NOT NULL;
+UPDATE `admins` SET password = SHA1(password);
\ No newline at end of file
diff --git a/install/db/atutor_upgrade_1.5_to_1.5.1.sql b/install/db/atutor_upgrade_1.5_to_1.5.1.sql
new file mode 100644 (file)
index 0000000..59414c3
--- /dev/null
@@ -0,0 +1,17 @@
+###############################################################\r
+# Database upgrade SQL from ATutor 1.5 to ATutor 1.5.1\r
+###############################################################\r
+\r
+# handbook notes:\r
+CREATE TABLE `handbook_notes` (\r
+`note_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT ,\r
+`date` DATETIME NOT NULL ,\r
+`section` VARCHAR( 15 ) NOT NULL ,\r
+`page` VARCHAR( 50 ) NOT NULL ,\r
+`email` VARCHAR( 50 ) NOT NULL ,\r
+`note` TEXT NOT NULL ,\r
+PRIMARY KEY ( `note_id` )\r
+);\r
+\r
+#Dec 6, 2007 - duplicated column name\r
+#ALTER TABLE `admins` ADD  `language` varchar(5) default '' NOT NULL AFTER `email` ;\r
diff --git a/install/db/atutor_upgrade_1.6_to_1.6.1.sql b/install/db/atutor_upgrade_1.6_to_1.6.1.sql
new file mode 100644 (file)
index 0000000..6282f34
--- /dev/null
@@ -0,0 +1,147 @@
+###############################################################
+# Database upgrade SQL from ATutor 1.6 to ATutor 1.6.1
+###############################################################
+
+# support new changes for Test/Survey
+ALTER TABLE `tests`
+ADD `description` TEXT NOT NULL, 
+ADD `passscore` MEDIUMINT NOT NULL, 
+ADD `passpercent` MEDIUMINT NOT NULL,
+ADD `passfeedback` TEXT NOT NULL, 
+ADD `failfeedback` TEXT NOT NULL;
+
+# support auto enrollment at registration
+CREATE TABLE `auto_enroll` (
+   `auto_enroll_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+   `associate_string` VARCHAR(10) NOT NULL,
+   `name` VARCHAR( 50 ) NOT NULL default '',
+   PRIMARY KEY ( `auto_enroll_id` )
+) DEFAULT CHARACTER SET = 'utf8';
+
+CREATE TABLE `auto_enroll_courses` (
+   `auto_enroll_courses_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+   `auto_enroll_id` MEDIUMINT UNSIGNED NOT NULL default 0,
+   `course_id` MEDIUMINT UNSIGNED NOT NULL default 0,
+   PRIMARY KEY ( `auto_enroll_courses_id` )
+) DEFAULT CHARACTER SET = 'utf8';
+
+# course directory name
+ALTER TABLE `courses` ADD COLUMN `course_dir_name` VARCHAR(255) NOT NULL AFTER `description`;
+
+# Extend members.password for encrypted password
+ALTER TABLE `members` MODIFY password VARCHAR(40);
+UPDATE `members` SET password = SHA1(password);
+
+# --------------------------------------------------------
+# Table structure for table `patches`
+# since 1.6.1
+
+CREATE TABLE `patches` (
+       `patches_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+       `atutor_patch_id` VARCHAR(20) NOT NULL default '',
+       `applied_version` VARCHAR(10) NOT NULL default '',
+       `patch_folder` VARCHAR(250) NOT NULL default '',
+  `description` TEXT NOT NULL,
+       `available_to` VARCHAR(250) NOT NULL default '',
+  `sql_statement` text NOT NULL,
+  `status` varchar(20) NOT NULL default '',
+  `remove_permission_files` text NOT NULL,
+  `backup_files` text NOT NULL,
+  `patch_files` text NOT NULL,
+       PRIMARY KEY  (`patches_id`)
+) DEFAULT CHARACTER SET = 'utf8';
+
+
+# --------------------------------------------------------
+# Table structure for table `patches_files`
+# since 1.6.1
+
+CREATE TABLE `patches_files` (
+       `patches_files_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+       `patches_id` MEDIUMINT UNSIGNED NOT NULL default 0,
+       `action` VARCHAR(20) NOT NULL default '',
+       `name` TEXT NOT NULL,
+       `location` VARCHAR(250) NOT NULL default '',
+       PRIMARY KEY  (`patches_files_id`)
+) DEFAULT CHARACTER SET = 'utf8';;
+
+# --------------------------------------------------------
+# Table structure for table `patches_files_actions`
+# since 1.6.1
+
+CREATE TABLE `patches_files_actions` (
+       `patches_files_actions_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+       `patches_files_id` MEDIUMINT UNSIGNED NOT NULL default 0,
+       `action` VARCHAR(20) NOT NULL default '',
+       `code_from` TEXT NOT NULL,
+       `code_to` TEXT NOT NULL,
+       PRIMARY KEY  (`patches_files_actions_id`)
+) DEFAULT CHARACTER SET = 'utf8';
+
+
+
+# --------------------------------------------------------
+# New tables for patch creator
+# since 1.6.1
+
+CREATE TABLE `myown_patches` (
+       `myown_patch_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+       `atutor_patch_id` VARCHAR(20) NOT NULL default '',
+       `applied_version` VARCHAR(10) NOT NULL default '',
+  `description` TEXT NOT NULL,
+  `sql_statement` text NOT NULL,
+  `status` varchar(20) NOT NULL default '',
+  `last_modified` datetime NOT NULL,
+       PRIMARY KEY  (`myown_patch_id`)
+) DEFAULT CHARACTER SET = 'utf8';;
+
+CREATE TABLE `myown_patches_dependent` (
+       `myown_patches_dependent_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+       `myown_patch_id` MEDIUMINT UNSIGNED NOT NULL,
+       `dependent_patch_id` VARCHAR(50) NOT NULL default '',
+       PRIMARY KEY  (`myown_patches_dependent_id`)
+) DEFAULT CHARACTER SET = 'utf8';
+
+CREATE TABLE `myown_patches_files` (
+       `myown_patches_files_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
+       `myown_patch_id` MEDIUMINT UNSIGNED NOT NULL,
+       `action` VARCHAR(20) NOT NULL default '',
+       `name` VARCHAR(250) NOT NULL,
+       `location` VARCHAR(250) NOT NULL default '',
+       `code_from` TEXT NOT NULL,
+       `code_to` TEXT NOT NULL,
+       `uploaded_file` TEXT NOT NULL,
+       PRIMARY KEY  (`myown_patches_files_id`)
+) DEFAULT CHARACTER SET = 'utf8';
+
+# --------------------------------------------------------
+# Include Patcher as a standard module
+# since 1.6.1
+
+INSERT INTO `modules`
+SELECT '_standard/patcher', 2, 0, MAX(admin_privilege)*2, 0, 0 FROM `modules`;
+
+# --------------------------------------------------------
+# Support customized head
+# since 1.6.1
+
+ALTER TABLE `content`
+ADD head TEXT NOT NULL, 
+ADD use_customized_head TINYINT(4) NOT NULL;
+
+# --------------------------------------------------------
+# courses.created_date is modified to datetime
+# remove unused fields: courses.preferences, courses.header, courses.footer, courses.banner_text, courses.banner_styles
+# since 1.6.1
+
+ALTER TABLE `courses` MODIFY created_date DATETIME;
+ALTER TABLE `courses` DROP preferences, DROP header, DROP footer, DROP banner_text, DROP banner_styles;
+
+#---------------------------------------------------------
+# Adds the fluid theme to the default theme provided in the public distribution
+INSERT INTO `themes` VALUES ('Fluid', '1.6.1', 'fluid', NOW(), 'Theme that implements the Fluid reorderer used to drag-and-drop the menu from side-to-side.', 1);
+
+# --------------------------------------------------------
+# Increase course icon filename size
+# http://www.atutor.ca/atutor/mantis/view.php?id=3319
+ALTER TABLE `courses` MODIFY COLUMN `icon` VARCHAR(75);
diff --git a/install/images/bad.gif b/install/images/bad.gif
new file mode 100644 (file)
index 0000000..80a2e7b
Binary files /dev/null and b/install/images/bad.gif differ
diff --git a/install/images/feedback.gif b/install/images/feedback.gif
new file mode 100644 (file)
index 0000000..a909231
Binary files /dev/null and b/install/images/feedback.gif differ
diff --git a/install/images/question.gif b/install/images/question.gif
new file mode 100644 (file)
index 0000000..02fd449
Binary files /dev/null and b/install/images/question.gif differ
diff --git a/install/include/classes/TableConversion.class.php b/install/include/classes/TableConversion.class.php
new file mode 100644 (file)
index 0000000..3611ab0
--- /dev/null
@@ -0,0 +1,1979 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Harris Wong                                            */\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+\r
+/* Constances, refer to /include/lib/constants.inc.php */\r
+/* files */\r
+define('WORKSPACE_COURSE',     1); // aka Course Files\r
+define('WORKSPACE_PERSONAL',   2); // aka My Files\r
+define('WORKSPACE_ASSIGNMENT', 3);\r
+define('WORKSPACE_GROUP',      4);\r
+/* links */\r
+define('LINK_CAT_COURSE',      1);\r
+define('LINK_CAT_GROUP',       2);\r
+define('LINK_CAT_SELF',                3);\r
+\r
+/**\r
+ * This class handles different types of conversions for the ATutor tables.\r
+ * Table entries based on the course's Primary Language will be converted by convertTableByClass($,$)\r
+ * Table entries based on the System Defualt Language will be converted by convertTableBySysDefualt()\r
+ * @access                     public\r
+ * @author                     Harris Wong\r
+ * @precondition       MySQL connected, mbstring lib enabled.\r
+ * @date                       Dec 12, 2007\r
+ */\r
+ class ConversionDriver{\r
+        /** variable */\r
+       var $sys_default_lang;\r
+       var $table_prefix;\r
+\r
+        /** \r
+         * Constructor\r
+         * @param      table_prefix\r
+         */\r
+        function ConversionDriver($table_prefix){\r
+                $this->sys_default_lang = 'iso-8859-1';\r
+                $this->table_prefix = $table_prefix;\r
+        }\r
+\r
+        /**\r
+         * This function runs all the table that uses the system default language\r
+         */\r
+        function convertTableBySysDefault(){\r
+               global $errors;\r
+\r
+               $temp_table =& new CourseCategoriesTable($this->table_prefix, 'course_cats', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'course_cats was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['CourseCategoriesTable'] = array($this->table_prefix, 'course_cats', $char_set, $course_id);\r
+               }\r
+\r
+               $temp_table =& new MembersTable($this->table_prefix, 'members', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'members was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['MembersTable'] = array($this->table_prefix, 'members', $char_set, $course_id);\r
+               }\r
+        }\r
+\r
+       /**\r
+        * This function runs all the table that uses the system default language\r
+        * Particular for 1.6.1, since 1.6 didn't convret all table\r
+        */\r
+       function convertTableBySysDefault_161(){\r
+               global $errors;\r
+\r
+               $temp_table =& new AdminsTable($this->table_prefix, 'admins', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'admins was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['AdminsTable'] = array($this->table_prefix, 'admins', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new AdminLogTable($this->table_prefix, 'admin_log', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'admin_log was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['AdminLogTable'] = array($this->table_prefix, 'admin_log', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new AutoEnrollTable($this->table_prefix, 'auto_enroll', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'auto_enroll was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['AutoEnrollTable'] = array($this->table_prefix, 'auto_enroll', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new AutoEnrollCoursesTable($this->table_prefix, 'auto_enroll_courses', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'auto_enroll_courses was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['AutoEnrollCourses'] = array($this->table_prefix, 'auto_enroll_courses', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new ConfigTable($this->table_prefix, 'config', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'config was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['ConfigTable'] = array($this->table_prefix, 'config', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new CourseAccessTable($this->table_prefix, 'course_access', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'course_access was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['CourseAccessTable'] = array($this->table_prefix, 'course_access', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new CourseStatsTable($this->table_prefix, 'course_stats', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'course_stats was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['CourseStatsTable'] = array($this->table_prefix, 'course_stats', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new FeedsTable($this->table_prefix, 'feeds', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'feeds was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['FeedsTable'] = array($this->table_prefix, 'feeds', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new FileStorageGroupsTable($this->table_prefix, 'file_storage_groups', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'file_storage_groups was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['FileStorageGroupsTable'] = array($this->table_prefix, 'file_storage_groups', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new ForumsAccessedTable($this->table_prefix, 'forums_accessed', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'forums_accessed was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['ForumsAccessedTable'] = array($this->table_prefix, 'forums_accessed', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new ForumsCoursesTable($this->table_prefix, 'forums_courses', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'forums_courses was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['ForumsCoursesTable'] = array($this->table_prefix, 'forums_courses', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new ForumsGroupsTable($this->table_prefix, 'forums_groups', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'forums_groups was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['ForumsGroupsTable'] = array($this->table_prefix, 'forums_groups', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new ForumsSubscriptionsTable($this->table_prefix, 'forums_subscriptions', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'forums_subscriptions was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['ForumsSubscriptionsTable'] = array($this->table_prefix, 'forums_subscriptions', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new GroupsMembersTable($this->table_prefix, 'groups_members', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'groups_members was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['GroupsMembersTable'] = array($this->table_prefix, 'groups_members', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new HandbookNotesTable($this->table_prefix, 'handbook_notes', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'handbook_notes was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['HandbookNotesTable'] = array($this->table_prefix, 'handbook_notes', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new InstructorApprovalsTable($this->table_prefix, 'instructor_approvals', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'instructor_approvals was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['InstructorApprovalsTable'] = array($this->table_prefix, 'instructor_approvals', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new LanguagesTable($this->table_prefix, 'languages', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'languages was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['LanguagesTable'] = array($this->table_prefix, 'languages', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new LanguagePagesTable($this->table_prefix, 'language_pages', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'language_pages was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['LanguagePagesTable'] = array($this->table_prefix, 'language_pages', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new LanguageTextTable($this->table_prefix, 'language_text', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'language_text was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['LanguageTextTable'] = array($this->table_prefix, 'language_text', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new MailQueueTable($this->table_prefix, 'mail_queue', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'mail_queue was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['MailQueueTable'] = array($this->table_prefix, 'mail_queue', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new MasterListTable($this->table_prefix, 'master_list', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'master_list was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['MasterListTable'] = array($this->table_prefix, 'master_list', $this->sys_default_lang, $course_id);\r
+               }\r
+       \r
+               $temp_table =& new MemberTrackTable($this->table_prefix, 'member_track', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'member_track was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['MemberTrackTable'] = array($this->table_prefix, 'member_track', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new ModulesTable($this->table_prefix, 'modules', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'modules was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['ModulesTable'] = array($this->table_prefix, 'modules', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new PollsMembersTable($this->table_prefix, 'polls_members', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'polls_members was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['PollsMembersTable'] = array($this->table_prefix, 'polls_members', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new RelatedContentTable($this->table_prefix, 'related_content', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'related_content was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['RelatedContentTable'] = array($this->table_prefix, 'related_content', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new TestsGroupsTable($this->table_prefix, 'tests_groups', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'tests_groups was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['TestsGroupsTable'] = array($this->table_prefix, 'tests_groups', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new TestsQuestionsAssocTable($this->table_prefix, 'tests_questions_assoc', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'tests_questions_assoc was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['TestsQuestionsAssocTable'] = array($this->table_prefix, 'tests_questions_assoc', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new TestsResultsTable($this->table_prefix, 'tests_results', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'tests_results was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['TestsResultsTable'] = array($this->table_prefix, 'tests_results', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new ThemesTable($this->table_prefix, 'themes', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'themes was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['ThemesTable'] = array($this->table_prefix, 'themes', $this->sys_default_lang, $course_id);\r
+               }\r
+\r
+               $temp_table =& new UsersOnlineTable($this->table_prefix, 'users_online', $this->sys_default_lang);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $this->table_prefix.'users_online was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['UsersOnlineTable'] = array($this->table_prefix, 'users_online', $this->sys_default_lang, $course_id);\r
+               }\r
+       }\r
+\r
+        /**\r
+         * This function runs through all the table that are class dependent.\r
+         */\r
+        function convertTableByClass($course_title, $char_set, $course_id){\r
+                global $errors;\r
+               //Run through all ATutor table and convert only those rows with the above courses.\r
+               //todo: implement a driver class inside the TableConversion class.\r
+               $temp_table =& new AssignmentsTable($this->table_prefix, 'assignments', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'assignments was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['AssignmentsTable'] = array($this->table_prefix, 'assignments', $char_set, $course_id);\r
+               }\r
+\r
+               $temp_table =& new BackupsTable($this->table_prefix, 'backups', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'backups was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['BackupsTable'] = array($this->table_prefix, 'backups', $char_set, $course_id);\r
+               }\r
+\r
+               $temp_table =& new BlogPostsTable($this->table_prefix, 'blog_posts', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'blog_posts was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['BlogPostsTable'] = array($this->table_prefix, 'blog_posts', $char_set, $course_id);\r
+               }\r
+               \r
+               $temp_table =& new ContentTable($this->table_prefix, 'content', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'content was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['ContentTable'] = array($this->table_prefix, 'content', $char_set, $course_id);\r
+               }\r
+               \r
+               $temp_table =& new CoursesTable($this->table_prefix, 'courses', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'courses was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['CoursesTable'] = array($this->table_prefix, 'courses', $char_set, $course_id);\r
+               }\r
+               \r
+               $temp_table =& new CourseEnrollmentTable($this->table_prefix, 'course_enrollment', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'course_enrollment was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['CourseEnrollmentTable'] = array($this->table_prefix, 'course_enrollment', $char_set, $course_id);\r
+               }\r
+\r
+               $temp_table =& new ExternalResourcesTable($this->table_prefix, 'external_resources', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'external_resources was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['ExternalResourcesTable'] = array($this->table_prefix, 'external_resources', $char_set, $course_id);\r
+               }\r
+\r
+               $temp_table =& new FaqTopicsTable($this->table_prefix, 'faq_topics', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'faq_topics was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['FaqTopicsTable'] = array($this->table_prefix, 'faq_topics', $char_set, $course_id);\r
+               }\r
+               \r
+               $temp_table =& new FoldersTable($this->table_prefix, 'folders', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'folders was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['FoldersTable'] = array($this->table_prefix, 'folders', $char_set, $course_id);\r
+               }\r
+\r
+               $temp_table =& new FilesTable($this->table_prefix, 'files', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'files was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['FilesTable'] = array($this->table_prefix, 'files', $char_set, $course_id);\r
+               }\r
+               \r
+               $temp_table =& new ForumsTable($this->table_prefix, 'forums', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'forums was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['ForumsTable'] = array($this->table_prefix, 'forums', $char_set, $course_id);\r
+               }\r
+\r
+               $temp_table =& new GlossaryTable($this->table_prefix, 'glossary', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'glossary was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['GlossaryTable'] = array($this->table_prefix, 'glossary', $char_set, $course_id);\r
+               }\r
+\r
+               $temp_table =& new GroupsTypesTable($this->table_prefix, 'groups_types', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'groups_types was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['GroupsTypesTable'] = array($this->table_prefix, 'groups_types', $char_set, $course_id);\r
+               }\r
+\r
+               $temp_table =& new LinksCategoriesTable($this->table_prefix, 'links_categories', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'links_categories was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['LinksCategoriesTable'] = array($this->table_prefix, 'links_categories', $char_set, $course_id);\r
+               }\r
+\r
+               $temp_table =& new MessagesTable($this->table_prefix, 'messages', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'messages was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['MessagesTable'] = array($this->table_prefix, 'messages', $char_set, $course_id);\r
+               }\r
+\r
+               $temp_table =& new MessagesSentTable($this->table_prefix, 'messages_sent', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'messages_sent was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['MessagesSentTable'] = array($this->table_prefix, 'messages_sent', $char_set, $course_id);\r
+               }\r
+\r
+               $temp_table =& new NewsTable($this->table_prefix, 'news', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'news was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['NewsTable'] = array($this->table_prefix, 'news', $char_set, $course_id);\r
+               }\r
+\r
+               $temp_table =& new PollsTable($this->table_prefix, 'polls', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'polls was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['PollsTable'] = array($this->table_prefix, 'polls', $char_set, $course_id);\r
+               }\r
+\r
+               $temp_table =& new ReadingListTable($this->table_prefix, 'reading_list', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'reading_list was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['ReadingListTable'] = array($this->table_prefix, 'reading_list', $char_set, $course_id);\r
+               }\r
+\r
+               $temp_table =& new TestsTable($this->table_prefix, 'tests', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'tests was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['TestsTable'] = array($this->table_prefix, 'tests', $char_set, $course_id);\r
+               }\r
+\r
+               $temp_table =& new TestQuestionsTable($this->table_prefix, 'tests_questions', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'tests_questions was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['TestQuestionsTable'] = array($this->table_prefix, 'tests_questions', $char_set, $course_id);\r
+               }\r
+\r
+               $temp_table =& new TestsQuestionsCategoriesTable($this->table_prefix, 'tests_questions_categories', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'tests_questions_categories was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['TestsQuestionsCategoriesTable'] = array($this->table_prefix, 'tests_questions_categories', $char_set, $course_id);\r
+               }\r
+        }\r
+\r
+        /**\r
+         * This function runs through all the table that are class dependent.\r
+         * Particular for the tables that haven't been converted during 1.5.5 to 1.6\r
+         */\r
+        function convertTableByClass_161($course_title, $char_set, $course_id){\r
+                global $errors;\r
+               //Run through all ATutor table and convert only those rows with the above courses.\r
+               //todo: implement a driver class inside the TableConversion class.\r
+               $temp_table =& new MessagesTable($this->table_prefix, 'messages', $char_set, $course_id);\r
+               if (!$temp_table->convert()){\r
+                       $errors[]= $course_title.': '.$this->table_prefix.'messages was not converted.';\r
+                       $_SESSION['redo_conversion'][$course_title]['MessagesTable'] = array($this->table_prefix, 'messages', $char_set, $course_id);\r
+               }\r
+        }\r
+\r
+        /**\r
+         * This function will alter all table's charset to UTF-8\r
+         */\r
+        function alter_all_charset(){\r
+                global $errors;\r
+                $sql = 'SHOW TABLES';\r
+                $result = mysql_query($sql);\r
+                if (mysql_numrows($result) > 0) {\r
+                        while ($row = mysql_fetch_array($result)){\r
+                                $sql = 'ALTER TABLE `'.$row[0].'` CONVERT TO CHARACTER SET utf8';\r
+                                mysql_query($sql);\r
+                        }\r
+                }\r
+        }\r
+ }\r
+\r
+\r
+/**\r
+* This class will handle utf8 conversion on all tables associated with a specific course.\r
+* This class can be potentially upgraded to a automated table parser to optimize codes, instead of having \r
+* different abstract classes for each individual table inside ATutor.  \r
+* Note: Keeping in mind that this class will not be used a lot after 1.6 conversion.  \r
+* @access                      public\r
+* @author                      Harris Wong\r
+* @precondition                MySQL connected, mbstring lib enabled.\r
+* @date                                Nov 28, 2007\r
+*/\r
+class ATutorTable{\r
+       /** variables */\r
+       var $table;\r
+       var $table_prefix;\r
+       var $from_encoding;\r
+       var $courseID;\r
+       var $to_encoding;\r
+\r
+       /**\r
+        * Constructor\r
+        * @param       table prefix\r
+        * @param       table is the table name of which we want to covert\r
+        * @param       from_encoding is the encoding which the content will be converted from.\r
+        * @param       foreign_ID is the primary key/foreign key of the table.  $foreign_ID will be the primary key when\r
+        *                      the table has a "course_id" column, foreign key when it doesn't.  \r
+        *                      foreign_ID is an empty string if this table does not depend on courses, such as members, \r
+        *                      course categories tables.\r
+        */\r
+       function ATutorTable($table_prefix, $table, $from_encoding, $foreign_ID=''){\r
+               $this->table_prefix = $table_prefix;\r
+               $this->table = $table;\r
+               $this->from_encoding = $from_encoding;\r
+               $this->foreign_ID= $foreign_ID;\r
+               $this->to_encoding = "UTF-8";\r
+               //check if mb_string library is enabled, die o/w\r
+                if (!extension_loaded('mbstring')){\r
+                        die("Please have mbstring library enabled");\r
+                }\r
+               \r
+               //Alter table\r
+               $this->alterTable();\r
+       }\r
+\r
+\r
+       /**\r
+        * alterTable\r
+        * Perform mysql ALTER table function, to switch to UTF-8 tables.\r
+        */\r
+       function alterTable(){\r
+               $query = 'ALTER TABLE `'.$this->table_prefix.$this->table.'` CONVERT TO CHARACTER SET utf8';\r
+               mysql_query($query);\r
+       }\r
+\r
+\r
+       /**\r
+        * getContent\r
+        * This method will get all the contents from this table with the given courseID.\r
+        * @param courseDependent = false when this table isn't related to course encoding, true if it is related (default)\r
+        * @return      result set, and null on failure or 0 rows\r
+        */\r
+       function getContent($courseDependent = true){\r
+               if ($courseDependent) {\r
+                       $sql = "SELECT * FROM `".$this->table_prefix.$this->table."` WHERE course_id=".$this->foreign_ID;\r
+               } else {\r
+                       $sql = 'SELECT * FROM `'.$this->table_prefix.$this->table;\r
+               }\r
+               $result = mysql_query($sql);\r
+               if ($result && mysql_num_rows($result)>0){\r
+                       return $result;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /**\r
+        * convert\r
+        * Abstract class that convert the table contents to UTF8\r
+        * @return mysql_query's return object\r
+        */\r
+       function convert(){/* Abstract */}\r
+       \r
+       \r
+       /**\r
+        * executeSQL\r
+        * This runs the sql statement\r
+        * @param value_array contains all the new values mapped by their column names\r
+        * @param primary_key is the primary key of this table.\r
+        */\r
+       function generate_sql($value_array, $primary_key_col, $primary_key){\r
+               $sql = "UPDATE `".$this->table_prefix.$this->table."` SET ";\r
+               $i = 1;\r
+               foreach($value_array as $column_name=>$column_value){\r
+                       $column_value = mysql_real_escape_string($column_value);\r
+                       $column_name = mysql_real_escape_string($column_name);\r
+                       $sql .= "`$column_name`='$column_value'";\r
+                       if ($i < sizeof($value_array)) {\r
+                               $sql .= ', ';\r
+                       }\r
+                       $i++;\r
+               }\r
+               //If there are more than 1 key\r
+               if (is_array($primary_key_col)){\r
+                       $j = 1;\r
+                       $sql .= " WHERE ";\r
+                       foreach ($primary_key_col as $k=>$v){\r
+                               $v = mysql_real_escape_string($v);\r
+                               $sql .= $v.'='.$primary_key[$k];\r
+                               if ($j < sizeof($primary_key_col)){\r
+                                       $sql .= " AND ";\r
+                               }\r
+                               $j++;\r
+                       }\r
+               } else {\r
+                       $sql .= " WHERE `$primary_key_col`=";\r
+                       if (preg_match('/^[0-9]+$/', $primary_key)==1){\r
+                               $sql .= $primary_key;\r
+                       } else {\r
+                               //prim key is a string, put it around a pair of quotes\r
+                               $sql .= "'$primary_key'";\r
+                       }\r
+               }\r
+//             echo "<hr/>";\r
+               return $sql;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for Admins\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class AdminsTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent(false);\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'login';\r
+                       //Convert all neccessary entries\r
+                       $value_array['real_name'] = mb_convert_encoding($row['real_name'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+                       echo mysql_error();\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for AdminLog\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class AdminLogTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent(false);\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'time';\r
+                       //Convert all neccessary entries\r
+                       $value_array['operation'] = mb_convert_encoding($row['operation'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['table'] = mb_convert_encoding($row['table'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['details'] = mb_convert_encoding($row['details'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/** \r
+ * Class for Assignments\r
+ */\r
+class AssignmentsTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'assignment_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['title'] = mb_convert_encoding($row['title'], $this->to_encoding, $this->from_encoding);\r
+\r
+                       //Convert Folders table, that is related to assignments.\r
+                       $folders =& new FoldersTable($this->table_prefix, 'folders', $this->from_encoding, $row[$key_col]);\r
+                       $result &= $folders->convert(WORKSPACE_ASSIGNMENT);\r
+                       //Convert Files table, that is related to assignments.\r
+                       $files_table =& new FilesTable($this->table_prefix, 'files', $this->from_encoding, $row[$key_col]);\r
+                       $result &= $files_table->convert(WORKSPACE_ASSIGNMENT);\r
+\r
+                       //Generate SQL\r
+                       //echo (mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]))) ;\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               } \r
+               //Needs to alter related tables\r
+               if (!$rs) {                     \r
+                       new FoldersTable($this->table_prefix, 'folders', '');\r
+                       new FilesTable($this->table_prefix, 'files', '');\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for auto_enroll\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class AutoEnrollTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent(false);\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'auto_enroll_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['associate_string'] = mb_convert_encoding($row['associate_string'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['name'] = mb_convert_encoding($row['name'], $this->to_encoding, $this->from_encoding);\r
+\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for auto_enroll_courses\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class AutoEnrollCoursesTable extends ATutorTable{\r
+       //Nothing to convert in this table except the table structure.\r
+       function convert(){\r
+               return true;\r
+       }\r
+}\r
+\r
+\r
+/** \r
+ * Class for Backups\r
+ */\r
+class BackupsTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'backup_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['date'] = $row['date'];\r
+                       $value_array['description'] = mb_convert_encoding($row['description'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['system_file_name'] = mb_convert_encoding($row['system_file_name'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['file_name'] = mb_convert_encoding($row['file_name'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['contents'] = mb_convert_encoding($row['contents'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/** \r
+ * Class for Blog posts\r
+ */\r
+class BlogPostsTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'post_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['date'] = $row['date'];\r
+                       $value_array['title'] = mb_convert_encoding($row['title'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['body'] = mb_convert_encoding($row['body'], $this->to_encoding, $this->from_encoding);\r
+                       //Convert sub post comment.\r
+                       $commentPosts =& new BlogPostsCommentsTable($this->table_prefix, 'blog_posts_comments', $this->from_encoding, $row[$key_col]);\r
+                       $result &= $commentPosts->convert();\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               //Needs to alter related tables\r
+               if (!$rs) {                     \r
+                       new BlogPostsCommentsTable($this->table_prefix, 'blog_posts_comments', '');\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/** \r
+ * Class for Blog posts comments\r
+ * Used only by BlogPostsTable\r
+ * Foreign key = post_id\r
+ */\r
+class BlogPostsCommentsTable extends ATutorTable{\r
+       //Overrider\r
+       function getContent(){\r
+               $sql = "SELECT * FROM `".$this->table_prefix.$this->table."` WHERE post_id=".$this->foreign_ID;\r
+               $result = mysql_query($sql);\r
+               if ($result && mysql_num_rows($result)>0){\r
+                       return $result;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'comment_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['date'] = $row['date'];\r
+                       $value_array['text'] = mb_convert_encoding($row['text'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for config\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class ConfigTable extends ATutorTable{\r
+       function convert(){\r
+               //nothing to convert\r
+               return true;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for course_access\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class CourseAccessTable extends ATutorTable{\r
+       function convert(){\r
+               //nothing to convert\r
+               return true;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for course_stats\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class CourseStatsTable extends ATutorTable{\r
+       function convert(){\r
+               //nothing to convert\r
+               return true;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for Content\r
+ */\r
+class ContentTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'content_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['last_modified'] = $row['last_modified'];\r
+                       $value_array['keywords'] = mb_convert_encoding($row['keywords'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['title'] = mb_convert_encoding($row['title'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['text'] = mb_convert_encoding($row['text'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for Courses\r
+ */\r
+class CoursesTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'course_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['title'] = mb_convert_encoding($row['title'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['description'] = mb_convert_encoding($row['description'], $this->to_encoding, $this->from_encoding);\r
+//                     $value_array['preferences'] = mb_convert_encoding($row['preferences'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['copyright'] = mb_convert_encoding($row['copyright'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['banner'] = mb_convert_encoding($row['banner'], $this->to_encoding, $this->from_encoding);\r
+                       /* The following should not needed to be converted after they are deprecated */\r
+//                     $value_array['header'] = mb_convert_encoding($row['header'], $this->to_encoding, $this->from_encoding);\r
+//                     $value_array['footer'] = mb_convert_encoding($row['footer'], $this->to_encoding, $this->from_encoding);                 \r
+//                     $value_array['banner_text'] = mb_convert_encoding($row['banner_text'], $this->to_encoding, $this->from_encoding);\r
+//                     $value_array['banner_styles'] = mb_convert_encoding($row['banner_styles'], $this->to_encoding, $this->from_encoding);                   \r
+\r
+                       //Generate SQL\r
+//                     echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for Courses enrollment\r
+ */\r
+class CourseEnrollmentTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'course_id';\r
+                       $key_col2 = 'member_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['role'] = mb_convert_encoding($row['role'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, array($key_col, $key_col2), array($row[$key_col], $row[$key_col2]));\r
+                       $result &= mysql_query($this->generate_sql($value_array, array($key_col, $key_col2), array($row[$key_col], $row[$key_col2])));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for Course Categories\r
+ * Course Categories are created by admins, the language encoding should be based on\r
+ * the admin's language setting for >= 1.5.1\r
+ * Otherwise, default it to iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class CourseCategoriesTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent(false);\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'cat_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['cat_name'] = mb_convert_encoding($row['cat_name'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for External resources\r
+ */\r
+class ExternalResourcesTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'resource_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['title'] = mb_convert_encoding($row['title'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['author'] = mb_convert_encoding($row['author'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['publisher'] = mb_convert_encoding($row['publisher'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['comments'] = mb_convert_encoding($row['comments'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for Faq topics\r
+ */\r
+class FaqTopicsTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'topic_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['name'] = mb_convert_encoding($row['name'], $this->to_encoding, $this->from_encoding);\r
+                       //Convert faq entries\r
+                       $faqEntries =& new FaqEntriesTable($this->table_prefix, 'faq_entries', $this->from_encoding, $row[$key_col]);\r
+                       $faqEntries->convert();\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               //Needs to alter related tables\r
+               if (!$rs) {                     \r
+                       new FaqEntriesTable($this->table_prefix, 'faq_entries', '');\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for Faq Entries \r
+ * Used only by FaqTopicsTable\r
+ * Foreign key = topic_id\r
+ */\r
+class FaqEntriesTable extends ATutorTable{\r
+       //Overrider\r
+       function getContent(){\r
+               $sql = 'SELECT * FROM `'.$this->table_prefix.$this->table.'` WHERE topic_id='.$this->foreign_ID;\r
+               $result = mysql_query($sql);\r
+               if ($result && mysql_num_rows($result)>0){\r
+                       return $result;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'entry_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['revised_date'] = $row['revised_date'];\r
+                       $value_array['question'] = mb_convert_encoding($row['question'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['answer'] = mb_convert_encoding($row['answer'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for feeds\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class FeedsTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent(false);\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'feed_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['url'] = mb_convert_encoding($row['url'], $this->to_encoding, $this->from_encoding);\r
+\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for Forums \r
+ */\r
+class ForumsTable extends ATutorTable{\r
+       //Overrider\r
+       function getContent(){\r
+               $sql = 'SELECT this_forum.* FROM `'.$this->table_prefix.$this->table.'` this_forum NATURAL JOIN `'.$this->table_prefix.'forums_courses` this_course WHERE this_course.course_id='.$this->foreign_ID;\r
+               $result = mysql_query($sql);\r
+               if ($result && mysql_num_rows($result)>0){\r
+                       return $result;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'forum_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['last_post'] = $row['last_post'];\r
+                       $value_array['title'] = mb_convert_encoding($row['title'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['description'] = mb_convert_encoding($row['description'], $this->to_encoding, $this->from_encoding);\r
+                       //Convert faq entries\r
+                       $forumThread=& new ForumsThreadsTable($this->table_prefix, 'forums_threads', $this->from_encoding, $row[$key_col]);\r
+                       $result &= $forumThread->convert();\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result = mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               //Needs to alter related tables\r
+               if (!$rs) {                     \r
+                       new ForumsThreadsTable($this->table_prefix, 'forums_threads', '');\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for forums_accessed\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class ForumsAccessedTable extends ATutorTable{\r
+       function convert(){\r
+               //nothing to convert\r
+               return true;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for forums_courses\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class ForumsCoursesTable extends ATutorTable{\r
+       function convert(){\r
+               //nothing to convert\r
+               return true;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for forums_groups\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class ForumsGroupsTable extends ATutorTable{\r
+       function convert(){\r
+               //nothing to convert\r
+               return true;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for forums_subscriptions\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class ForumsSubscriptionsTable extends ATutorTable{\r
+       function convert(){\r
+               //nothing to convert\r
+               return true;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for Forums threads\r
+ * Used only by ForumsTable\r
+ * Foreign key = forum_id\r
+ */\r
+class ForumsThreadsTable extends ATutorTable{\r
+       //Overrider\r
+       function getContent(){\r
+               $sql = 'SELECT * FROM `'.$this->table_prefix.$this->table.'` WHERE forum_id='.$this->foreign_ID;\r
+               $result = mysql_query($sql);\r
+               if ($result && mysql_num_rows($result)>0){\r
+                       return $result;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'post_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['last_comment'] = $row['last_comment'];\r
+                       $value_array['subject'] = mb_convert_encoding($row['subject'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['body'] = mb_convert_encoding($row['body'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for Folders\r
+ * Associated with Groups, Links\r
+ */\r
+ class FoldersTable extends ATutorTable{\r
+       /*\r
+        * Overrider\r
+        * owner_id means category_id, owner_type refers to the different link type defined in the constants.inc.php.\r
+        * @param       $owner_type are defined by the constances, which are course, groups, self\r
+        */\r
+       function getContent($owner_type){\r
+               $sql = 'SELECT * FROM `'.$this->table_prefix.$this->table.'` WHERE owner_type='.$owner_type.' AND owner_id='.$this->foreign_ID;\r
+               $result = mysql_query($sql);\r
+               if ($result && mysql_num_rows($result)>0){\r
+                       return $result;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /*\r
+        * @param       $owner_type are defined by the constances, which are course, groups, self; defaulted to be WORKSPACE_COURSE\r
+        */\r
+       function convert($owner_type=WORKSPACE_COURSE){\r
+               $rs = $this->getContent($owner_type);\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'folder_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['title'] = mb_convert_encoding($row['title'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+ }\r
+\r
+/**\r
+ * Class for Files\r
+ * Associated with Groups, Links\r
+ */\r
+ class FilesTable extends ATutorTable{\r
+       /*\r
+        * Overrider\r
+        * owner_id means category_id, owner_type refers to the different link type defined in the constants.inc.php.\r
+        * @param       $owner_type are defined by the constances, which are course, groups, self\r
+        */\r
+       function getContent($owner_type){\r
+               $sql = 'SELECT * FROM `'.$this->table_prefix.$this->table.'` WHERE owner_type='.$owner_type.' AND owner_id='.$this->foreign_ID;\r
+               $result = mysql_query($sql);\r
+               if ($result && mysql_num_rows($result)>0){\r
+                       return $result;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /*\r
+        * @param       $owner_type are defined by the constances, which are course, groups, self; defaulted to be WORKSPACE_COURSE\r
+        */\r
+       function convert($owner_type=WORKSPACE_COURSE){\r
+               $rs = $this->getContent($owner_type);\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'file_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['date'] = $row['date'];\r
+                       $value_array['file_name'] = mb_convert_encoding($row['file_name'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['description'] = mb_convert_encoding($row['description'], $this->to_encoding, $this->from_encoding);\r
+                       //Convert faq entries\r
+                       $filesComments=& new FilesCommentsTable($this->table_prefix, 'files_comments', $this->from_encoding, $row[$key_col]);\r
+                       $result &= $filesComments->convert();\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               //Needs to alter related tables\r
+               if (!$rs) {                     \r
+                       new FilesCommentsTable($this->table_prefix, 'files_comments', '');\r
+               }\r
+               return $result;\r
+       }\r
+ }\r
+\r
+\r
+/**\r
+ * Class for Files comments \r
+ * Used only by FilesTable\r
+ * Foreign key = file_id\r
+ */\r
+class FilesCommentsTable extends ATutorTable{\r
+       //Overrider\r
+       function getContent(){\r
+               $sql = 'SELECT * FROM `'.$this->table_prefix.$this->table.'` WHERE file_id='.$this->foreign_ID;\r
+               $result = mysql_query($sql);\r
+               if ($result && mysql_num_rows($result)>0){\r
+                       return $result;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'comment_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['date'] = $row['date'];\r
+                       $value_array['comment'] = mb_convert_encoding($row['comment'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for file_storage_groups\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class FileStorageGroupsTable extends ATutorTable{\r
+       function convert(){\r
+               //nothing to convert\r
+               return true;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for Glossary \r
+ */\r
+class GlossaryTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'word_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['word'] = mb_convert_encoding($row['word'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['definition'] = mb_convert_encoding($row['definition'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for Group types\r
+ */\r
+class GroupsTypesTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'type_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['title'] = mb_convert_encoding($row['title'], $this->to_encoding, $this->from_encoding);\r
+                       \r
+                       //Convert group table\r
+                       $groups =& new GroupsTable($this->table_prefix, 'groups', $this->from_encoding, $row[$key_col]);\r
+                       $result &= $groups->convert();\r
+                       //Convert links table, that has owner_type=group\r
+                       $linkscats =& new LinksCategoriesTable($this->table_prefix, 'links_categories', $this->from_encoding, $row[$key_col]);\r
+                       $result &= $linkscats->convert(LINK_CAT_GROUP);\r
+                       //Convert folder tables, that has owner_type=group\r
+                       $folders =& new FoldersTable($this->table_prefix, 'folders', $this->from_encoding, $row[$key_col]);\r
+                       $result &= $folders->convert(WORKSPACE_GROUP);\r
+                       //Convert file tables, that has owner_type=group\r
+                       $files_table =& new FilesTable($this->table_prefix, 'files', $this->from_encoding, $row[$key_col]);\r
+                       $result &= $files_table->convert(WORKSPACE_GROUP);\r
+\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               //Needs to alter related tables\r
+               if (!$rs) {                     \r
+                       new GroupsTable($this->table_prefix, 'groups', '');\r
+                       new LinksCategoriesTable($this->table_prefix, 'links_categories', '');\r
+                       new FoldersTable($this->table_prefix, 'folders', '');\r
+                       new FilesTable($this->table_prefix, 'files', '');\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for Groups\r
+ * Used only by GroupTypesTable\r
+ * Foreign key = type_id\r
+ */\r
+class GroupsTable extends ATutorTable{\r
+       //Overrider\r
+       function getContent(){\r
+               $sql = 'SELECT * FROM `'.$this->table_prefix.$this->table.'` WHERE type_id='.$this->foreign_ID;\r
+               $result = mysql_query($sql);\r
+               if ($result && mysql_num_rows($result)>0){\r
+                       return $result;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'group_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['title'] = mb_convert_encoding($row['title'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['description'] = mb_convert_encoding($row['description'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for groups_members\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class GroupsMembersTable extends ATutorTable{\r
+       function convert(){\r
+               //nothing to convert\r
+               return true;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for handbooks_notes\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class HandbookNotesTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent(false);\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'note_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['section'] = mb_convert_encoding($row['section'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['page'] = mb_convert_encoding($row['page'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['note'] = mb_convert_encoding($row['note'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for instructor_approvals\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class InstructorApprovalsTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent(false);\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'member_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['notes'] = mb_convert_encoding($row['notes'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for lanaguages\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class LanguagesTable extends ATutorTable{\r
+       function convert(){\r
+               //will only have english language remains.\r
+               return true;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for lanaguage_pages\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class LanguagePagesTable extends ATutorTable{\r
+       function convert(){\r
+               //will only have iso88591, which is in ascii\r
+               return true;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for language_text\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class LanguageTextTable extends ATutorTable{\r
+       function convert(){\r
+               //will only have iso88591, which is in ascii\r
+               return true;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for Links Categories\r
+ * Links' owner_id can be of courses, groups, self.\r
+ */\r
+class LinksCategoriesTable extends ATutorTable{\r
+       /*\r
+        * Overrider\r
+        * owner_id means category_id, owner_type refers to the different link type defined in the constants.inc.php.\r
+        * @param       $owner_type are defined by the constances\r
+        */\r
+       function getContent($owner_type){\r
+               $sql = 'SELECT * FROM `'.$this->table_prefix.$this->table.'` WHERE owner_type='.$owner_type.' AND owner_id='.$this->foreign_ID;\r
+               $result = mysql_query($sql);\r
+               if ($result && mysql_num_rows($result)>0){\r
+                       return $result;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /*\r
+        * @param       $owner_type are defined by the constances, which are course, groups, self; defaulted to be LINK_CAT_COURSE\r
+        */\r
+       function convert($owner_type=LINK_CAT_COURSE){\r
+               $rs = $this->getContent($owner_type);\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'cat_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['name'] = mb_convert_encoding($row['name'], $this->to_encoding, $this->from_encoding);\r
+                       //Convert links table\r
+                       $linkscats =& new LinksTable($this->table_prefix, 'links', $this->from_encoding, $row[$key_col]);\r
+                       $result &= $linkscats->convert();\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               //Needs to alter related tables\r
+               if (!$rs) {                     \r
+                       new LinksTable($this->table_prefix, 'links', '');\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for Links\r
+ * Used only by LinksCategoriesTable\r
+ * Foreign key = cat_id\r
+ */\r
+ class LinksTable extends ATutorTable{\r
+       //Overrider\r
+       function getContent(){\r
+               $sql = 'SELECT * FROM `'.$this->table_prefix.$this->table.'` WHERE cat_id='.$this->foreign_ID;\r
+               $result = mysql_query($sql);\r
+               if ($result && mysql_num_rows($result)>0){\r
+                       return $result;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'link_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['LinkName'] = mb_convert_encoding($row['LinkName'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['Description'] = mb_convert_encoding($row['Description'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['SubmitName'] = mb_convert_encoding($row['SubmitName'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+ }\r
+\r
+/**\r
+ * Class for mail_queue\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class MailQueueTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent(false);\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'mail_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['to_name'] = mb_convert_encoding($row['to_name'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['from_name'] = mb_convert_encoding($row['from_name'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['subject'] = mb_convert_encoding($row['subject'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['body'] = mb_convert_encoding($row['body'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for master_list\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class MasterListTable extends ATutorTable{\r
+       function convert(){\r
+               //nothong to convert\r
+               return true;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for Members \r
+ * Note: This class is independent from courses\r
+ */\r
+class MembersTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent(false);\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'member_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['first_name'] = mb_convert_encoding($row['first_name'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['second_name'] = mb_convert_encoding($row['second_name'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['last_name'] = mb_convert_encoding($row['last_name'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['address'] = mb_convert_encoding($row['address'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['city'] = mb_convert_encoding($row['city'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['province'] = mb_convert_encoding($row['province'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['creation_date'] = $row['creation_date'];\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for member_track\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class MemberTrackTable extends ATutorTable{\r
+       function convert(){\r
+               //nothong to convert\r
+               return true;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for Messages\r
+ */\r
+class MessagesTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true; \r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'message_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['date_sent'] = $row['date_sent'];\r
+                       $value_array['subject'] = mb_convert_encoding($row['subject'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['body'] = mb_convert_encoding($row['body'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for Messages Sent\r
+ */\r
+class MessagesSentTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true; \r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'message_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['date_sent'] = $row['date_sent'];\r
+                       $value_array['subject'] = mb_convert_encoding($row['subject'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['body'] = mb_convert_encoding($row['body'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for modules\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class ModulesTable extends ATutorTable{\r
+       function convert(){\r
+               //nothong to convert\r
+               return true;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for News\r
+ */\r
+class NewsTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'news_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['date'] = $row['date'];\r
+                       $value_array['title'] = mb_convert_encoding($row['title'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['body'] = mb_convert_encoding($row['body'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for Polls\r
+ */\r
+class PollsTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'poll_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['created_date'] = $row['created_date'];\r
+                       $value_array['question'] = mb_convert_encoding($row['question'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['choice1'] = mb_convert_encoding($row['choice1'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['choice2'] = mb_convert_encoding($row['choice2'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['choice3'] = mb_convert_encoding($row['choice3'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['choice4'] = mb_convert_encoding($row['choice4'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['choice5'] = mb_convert_encoding($row['choice5'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['choice6'] = mb_convert_encoding($row['choice6'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['choice7'] = mb_convert_encoding($row['choice7'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for PollsMembers\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class PollsMembersTable extends ATutorTable{\r
+       function convert(){\r
+               //nothong to convert\r
+               return true;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for RelatedContent\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class RelatedContentTable extends ATutorTable{\r
+       function convert(){\r
+               //nothong to convert\r
+               return true;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for Readlig list\r
+ */\r
+class ReadingListTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'reading_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['comment'] = mb_convert_encoding($row['comment'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for Tests\r
+ */\r
+class TestsTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'test_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['title'] = mb_convert_encoding($row['title'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['instructions'] = mb_convert_encoding($row['instructions'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for Test questions\r
+ */\r
+class TestQuestionsTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'question_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['question'] = mb_convert_encoding($row['question'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['feedback'] = mb_convert_encoding($row['feedback'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['question'] = mb_convert_encoding($row['question'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['choice_0'] = mb_convert_encoding($row['choice_0'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['choice_1'] = mb_convert_encoding($row['choice_1'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['choice_2'] = mb_convert_encoding($row['choice_2'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['choice_3'] = mb_convert_encoding($row['choice_3'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['choice_4'] = mb_convert_encoding($row['choice_4'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['choice_5'] = mb_convert_encoding($row['choice_5'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['choice_6'] = mb_convert_encoding($row['choice_6'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['choice_7'] = mb_convert_encoding($row['choice_7'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['choice_8'] = mb_convert_encoding($row['choice_8'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['choice_9'] = mb_convert_encoding($row['choice_9'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['option_0'] = mb_convert_encoding($row['option_0'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['option_1'] = mb_convert_encoding($row['option_1'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['option_2'] = mb_convert_encoding($row['option_2'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['option_3'] = mb_convert_encoding($row['option_3'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['option_4'] = mb_convert_encoding($row['option_4'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['option_5'] = mb_convert_encoding($row['option_5'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['option_6'] = mb_convert_encoding($row['option_6'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['option_7'] = mb_convert_encoding($row['option_7'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['option_8'] = mb_convert_encoding($row['option_8'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['option_9'] = mb_convert_encoding($row['option_9'], $this->to_encoding, $this->from_encoding);\r
+\r
+                       //Convert links table\r
+                       $tests_answers =& new TestsAnswersTable($this->table_prefix, 'tests_answers', $this->from_encoding, $row[$key_col]);\r
+                       $result &= $tests_answers->convert();\r
+\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               //Needs to alter related tables\r
+               if (!$rs) {                     \r
+                       new TestsAnswersTable($this->table_prefix, 'tests_answers', '');\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for Test answers\r
+ * Used only by TestQuestionTable\r
+ * Foreign key = question_id, since question is one-to-many answers mapping.\r
+ */\r
+ class TestsAnswersTable extends ATutorTable{\r
+       //Overrider\r
+       function getContent(){\r
+               $sql = 'SELECT * FROM `'.$this->table_prefix.$this->table.'` WHERE question_id='.$this->foreign_ID;\r
+               $result = mysql_query($sql);\r
+               if ($result && mysql_num_rows($result)>0){\r
+                       return $result;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col1 = 'question_id';\r
+                       $key_col2 = 'result_id';\r
+                       $key_col3 = 'member_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['answer'] = mb_convert_encoding($row['answer'], $this->to_encoding, $this->from_encoding);\r
+                       $value_array['notes'] = mb_convert_encoding($row['notes'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, array($key_col1, $key_col2, $key_col3), \r
+                               array($row[$key_col1], $row[$key_col2], $row[$key_col3])));\r
+               }\r
+               return $result;\r
+       }\r
+ }\r
+\r
+/**\r
+ * Class for tests_groups\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class TestsGroupsTable extends ATutorTable{\r
+       function convert(){\r
+               //nothong to convert\r
+               return true;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for tests_questions_assoc\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class TestsQuestionsAssocTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent(false);\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'test_id';\r
+                       $key_col2 = 'question_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['weight'] = mb_convert_encoding($row['weight'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, array($key_col, $key_col2), array($row[$key_col], $row[$key_col2])));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+/**\r
+ * Class for Tests questions category\r
+ */\r
+class TestsQuestionsCategoriesTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent();\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'category_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['title'] = mb_convert_encoding($row['title'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for tests_results\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class TestsResultsTable extends ATutorTable{\r
+       function convert(){\r
+               //nothong to convert\r
+               return true;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for themes\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class ThemesTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent(false);\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'title';\r
+                       //Convert all neccessary entries\r
+                       $value_array['extra_info'] = mb_convert_encoding($row['extra_info'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Class for users_online\r
+ * Default language iso-8859-1.\r
+ * Note: This class is independent from courses\r
+ */\r
+class UsersOnlineTable extends ATutorTable{\r
+       function convert(){\r
+               $rs = $this->getContent(false);\r
+               $result = true;\r
+               while ($rs!=false && $row = mysql_fetch_assoc($rs)){\r
+                       //Store the key for updating purposes.\r
+                       $key_col = 'member_id';\r
+                       //Convert all neccessary entries\r
+                       $value_array['login'] = mb_convert_encoding($row['login'], $this->to_encoding, $this->from_encoding);\r
+                       //Generate SQL\r
+                       //echo $this->generate_sql($value_array, $key_col, $row[$key_col]);\r
+                       $result &= mysql_query($this->generate_sql($value_array, $key_col, $row[$key_col]));\r
+               }\r
+               return $result;\r
+       }\r
+}\r
+?>\r
diff --git a/install/include/classes/sqlutility.php b/install/include/classes/sqlutility.php
new file mode 100644 (file)
index 0000000..923205d
--- /dev/null
@@ -0,0 +1,155 @@
+<?php
+
+
+class SqlUtility
+{
+       /**
+       * Function from phpMyAdmin (http://phpwizard.net/projects/phpMyAdmin/)
+       *
+       * Removes comment and splits large sql files into individual queries
+       *
+       * Last revision: September 23, 2001 - gandon
+       *
+       * @param   array    the splitted sql commands
+       * @param   string   the sql commands
+       * @return  boolean  always true
+       * @access  public
+       */
+       function splitSqlFile(&$ret, $sql)
+       {
+               $sql               = trim($sql);
+               $sql_len           = strlen($sql);
+               $char              = '';
+       $string_start      = '';
+       $in_string         = false;
+
+       for ($i = 0; $i < $sql_len; ++$i) {
+               $char = $sql[$i];
+
+           // We are in a string, check for not escaped end of
+                  // strings except for backquotes that can't be escaped
+           if ($in_string) {
+                       for (;;) {
+                               $i         = strpos($sql, $string_start, $i);
+                                       // No end of string found -> add the current
+                                       // substring to the returned array
+                       if (!$i) {
+                                               $ret[] = $sql;
+                       return true;
+                       }
+                                       // Backquotes or no backslashes before 
+                                       // quotes: it's indeed the end of the 
+                                       // string -> exit the loop
+                       else if ($string_start == '`' || $sql[$i-1] != '\\') {
+                                               $string_start      = '';
+                               $in_string         = false;
+                       break;
+                       }
+                       // one or more Backslashes before the presumed 
+                                       // end of string...
+                       else {
+                                               // first checks for escaped backslashes
+                       $j                     = 2;
+                       $escaped_backslash     = false;
+                                               while ($i-$j > 0 && $sql[$i-$j] == '\\') {
+                                                       $escaped_backslash = !$escaped_backslash;
+                               $j++;
+                       }
+                       // ... if escaped backslashes: it's really the 
+                                               // end of the string -> exit the loop
+                       if ($escaped_backslash) {
+                                                       $string_start  = '';
+                               $in_string     = false;
+                                                       break;
+                       }
+                       // ... else loop
+                       else {
+                                                       $i++;
+                       }
+                       } // end if...elseif...else
+               } // end for
+               } // end if (in string)
+               // We are not in a string, first check for delimiter...
+               else if ($char == ';') {
+                               // if delimiter found, add the parsed part to the returned array
+               $ret[]    = substr($sql, 0, $i);
+               $sql      = ltrim(substr($sql, min($i + 1, $sql_len)));
+                       $sql_len  = strlen($sql);
+               if ($sql_len) {
+                                       $i      = -1;
+               } else {
+                       // The submited statement(s) end(s) here
+                       return true;
+                               }
+               } // end else if (is delimiter)
+               // ... then check for start of a string,...
+               else if (($char == '"') || ($char == '\'') || ($char == '`')) {
+                               $in_string    = true;
+                               $string_start = $char;
+               } // end else if (is start of string)
+
+               // for start of a comment (and remove this comment if found)...
+               else if ($char == '#' || ($char == ' ' && $i > 1 && $sql[$i-2] . $sql[$i-1] == '--')) {
+               // starting position of the comment depends on the comment type
+                       $start_of_comment = (($sql[$i] == '#') ? $i : $i-2);
+               // if no "\n" exits in the remaining string, checks for "\r"
+               // (Mac eol style)
+                       $end_of_comment   = (strpos(' ' . $sql, "\012", $i+2))
+                              ? strpos(' ' . $sql, "\012", $i+2)
+                              : strpos(' ' . $sql, "\015", $i+2);
+                       if (!$end_of_comment) {
+                // no eol found after '#', add the parsed part to the returned
+                // array and exit
+                               $ret[]   = trim(substr($sql, 0, $i-1));
+                               return true;
+                               } else {
+                       $sql     = substr($sql, 0, $start_of_comment) . ltrim(substr($sql, $end_of_comment));
+                       $sql_len = strlen($sql);
+                       $i--;
+               } // end if...else
+               } // end else if (is comment)
+       } // end for
+
+       // add any rest to the returned array
+       if (!empty($sql) && trim($sql) != '') {
+                       $ret[] = $sql;
+       }
+       return true;
+       }
+
+       /**
+        * add a prefix.'_' to all tablenames in a query
+     * 
+     * @param   string  $query  valid MySQL query string
+     * @param   string  $prefix prefix to add to all table names
+        * @return  mixed   FALSE on failure
+        */
+       function prefixQuery($query, $prefix)
+       {
+               $pattern = "/^(INSERT INTO|REPLACE INTO|CREATE TABLE|ALTER TABLE|UPDATE)(\s)+([`]?)([^`\s]+)\\3(\s)+/siU";
+               $pattern2 = "/^(DROP TABLE)(\s)+([`]?)([^`\s]+)\\3(\s)?$/siU";
+               if (preg_match($pattern, $query, $matches) || preg_match($pattern2, $query, $matches)) {
+                       $replace = "\\1 ".$prefix."\\4\\5";
+                       $matches[0] = preg_replace($pattern, $replace, $query);
+
+                       if ($matches[1] == 'INSERT INTO') {
+                               $parts = explode(' ', $matches[0]);
+                               $size_of_parts = count($parts);
+                               if ($parts[$size_of_parts-2] == 'FROM') {
+                                       $parts[$size_of_parts-1] = $prefix . str_replace('`', '', $parts[$size_of_parts-1]);
+                                       $matches[0] = implode(' ', $parts);
+                               }
+                       } else if ($matches[1] == 'ALTER TABLE') {
+                               $parts = explode(' ', $matches[0]);
+                               if ($parts[3] == 'RENAME') {
+                                       $parts[4] = $prefix . str_replace('`', '', $parts[4]);
+                                       $matches[0] = implode(' ', $parts);
+                               }
+                       }
+
+                       return $matches;
+               }
+               return false;
+       }
+}
+?>
\ No newline at end of file
diff --git a/install/include/common.inc.php b/install/include/common.inc.php
new file mode 100644 (file)
index 0000000..443632b
--- /dev/null
@@ -0,0 +1,244 @@
+<?php
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+error_reporting(E_ALL ^ E_NOTICE);
+
+/* atutor default configuration options */
+/* used on: ustep1.php, step3.php, step5.php */
+$_defaults['admin_username'] = ($_POST['old_path'] ? 'admin' : '');
+$_defaults['admin_password'] = '';
+$_defaults['admin_email'] = '';
+
+$_defaults['site_name'] = 'Course Server';
+$_defaults['header_img'] = '';
+$_defaults['header_logo'] = '';
+$_defaults['home_url'] = '';
+
+$_defaults['email_notification'] = 'TRUE';
+$_defaults['email_confirmation'] = 'TRUE';
+$_defaults['allow_instructor_requests'] = 'TRUE';
+$_defaults['auto_approve_instructors'] = 'FALSE';
+
+$_defaults['max_file_size'] = '1048576';
+$_defaults['max_course_size'] = '10485760';
+$_defaults['max_course_float'] = '2097152';
+$_defaults['ill_ext'] = 'exe, asp, php, php3, bat, cgi, pl, com, vbs, reg, pcd, pif, scr, bas, inf, vb, vbe, wsc, wsf, wsh';
+$_defaults['cache_dir'] = '';
+
+$_defaults['theme_categories'] = 'FALSE';
+$_defaults['content_dir'] = realpath('../').DIRECTORY_SEPARATOR.'content';
+
+$_defaults['course_backups'] = 5;
+
+require('include/classes/sqlutility.php');
+
+
+function my_add_null_slashes( $string ) {
+    return @mysql_real_escape_string(stripslashes($string));
+}
+function my_null_slashes($string) {
+       return $string;
+}
+
+if ( get_magic_quotes_gpc() == 1 ) {
+       $addslashes   = 'my_add_null_slashes';
+       $stripslashes = 'stripslashes';
+} else {
+       $addslashes   = 'mysql_real_escape_string';
+       $stripslashes = 'my_null_slashes';
+}
+
+    function queryFromFile($sql_file_path){
+               global $db, $progress, $errors;
+               
+               $tables = array();
+
+        if (!file_exists($sql_file_path)) {
+            return false;
+        }
+
+        $sql_query = trim(fread(fopen($sql_file_path, 'r'), filesize($sql_file_path)));
+        SqlUtility::splitSqlFile($pieces, $sql_query);
+
+           foreach ($pieces as $piece) {
+               $piece = trim($piece);
+            // [0] contains the prefixed query
+            // [4] contains unprefixed table name
+
+
+                       if ($_POST['tb_prefix'] || ($_POST['tb_prefix'] == '')) {
+                   $prefixed_query = SqlUtility::prefixQuery($piece, $_POST['tb_prefix']);
+                       } else {
+                               $prefixed_query = $piece;
+                       }
+
+                       if ($prefixed_query != false ) {
+                $table = $_POST['tb_prefix'].$prefixed_query[4];
+                if($prefixed_query[1] == 'CREATE TABLE'){
+                    if (mysql_query($prefixed_query[0],$db) !== false) {
+                                               $progress[] = 'Table <strong>'.$table . '</strong> created successfully.';
+                    } else {
+                                               if (mysql_errno($db) == 1050) {
+                                                       $progress[] = 'Table <strong>'.$table . '</strong> already exists. Skipping.';
+                                               } else {
+                                                       $errors[] = 'Table <strong>' . $table . '</strong> creation failed.';
+                                               }
+                    }
+                }
+                elseif($prefixed_query[1] == 'INSERT INTO'){
+                    mysql_query($prefixed_query[0],$db);
+                }elseif($prefixed_query[1] == 'REPLACE INTO'){
+                    mysql_query($prefixed_query[0],$db);
+                }elseif($prefixed_query[1] == 'ALTER TABLE'){
+                    if (mysql_query($prefixed_query[0],$db) !== false) {
+                                               $progress[] = 'Table <strong>'.$table.'</strong> altered successfully.';
+                                       } else {
+                                               $errors[] = 'Table <strong>'.$table.'</strong> alteration failed.';
+                                       }
+
+                }elseif($prefixed_query[1] == 'DROP TABLE'){
+                    mysql_query($prefixed_query[1] . ' ' .$table,$db);
+                }elseif($prefixed_query[1] == 'UPDATE'){
+                    mysql_query($prefixed_query[0],$db);
+                }
+            }
+               }
+        return true;
+    }
+
+function print_errors( $errors ) {
+       ?>
+       <br />
+       <table border="0" class="errbox" cellpadding="3" cellspacing="2" width="90%" summary="" align="center">
+       <tr class="errbox">
+       <td>
+               <h3 class="err"><img src="images/bad.gif" align="top" alt="" class="img" /> Error</h3>
+               <?php
+                       echo '<ul>';
+                       foreach ($errors as $p) {
+                               echo '<li>'.$p.'</li>';
+                       }
+                       echo '</ul>';
+               ?>
+               </td>
+       </tr>
+       </table>        <br />
+<?php
+}
+
+function print_feedback( $feedback ) {
+       ?>
+       <br />
+       <table border="0" class="fbkbox" cellpadding="3" cellspacing="2" width="90%" summary="" align="center">
+       <tr class="fbkbox">
+       <td><h3 class="feedback2"><img src="images/feedback.gif" align="top" alt="" class="img" /> Feedback</h3>
+               <?php
+                       echo '<ul>';
+                       foreach ($feedback as $p) {
+                               echo '<li>'.$p.'</li>';
+                       }
+                       echo '</ul>';
+               ?></td>
+       </tr>
+       </table>
+       <br />
+<?php
+}
+
+function store_steps($step) {
+
+       global $stripslashes;
+
+       foreach($_POST as $key => $value) {
+               if (substr($key, 0, strlen('step')) == 'step') {
+                       continue;
+               } else if ($key == 'step') {
+                       continue;
+               } else if ($key == 'action') {
+                       continue;
+               } else if ($key == 'submit') {
+                       continue;
+               }
+
+               $_POST['step'.$step][$key] = urlencode($stripslashes($value));
+       }
+}
+
+
+function print_hidden($current_step) {
+       for ($i=1; $i<$current_step; $i++) {
+               if (is_array($_POST['step'.$i])) {
+                       foreach($_POST['step'.$i] as $key => $value) {
+                               echo '<input type="hidden" name="step'.$i.'['.$key.']" value="'.$value.'" />'."\n";
+                       }
+               }
+       }
+}
+
+function print_progress($step) {
+       global $install_steps;
+       
+       echo '<div class="install"><h3>Installation Progress</h3><p>';
+
+       $num_steps = count($install_steps);
+       for ($i=0; $i<$num_steps; $i++) {
+               if ($i == $step) {
+                       echo '<strong style="margin-left: 12px; color: #006699;">Step '.$i.': '.$install_steps[$i]['name'].'</strong>';
+               } else {
+                       echo '<small style="margin-left: 10px; color: gray;">';
+                       if ($step > $i) {
+                               echo '<img src="../images/check.gif" height="9" width="9" alt="Step Done!" /> ';
+                       } else {
+                               echo '<img src="../images/clr.gif" height="9" width="9" alt="" /> ';
+                       }
+                       echo 'Step '.$i.': '.$install_steps[$i]['name'].'</small>';
+               }
+               if ($i+1 < $num_steps) {
+                       echo '<br />';
+               }
+       }
+       echo '</p></div><br />';
+
+       echo '<h3>'.$install_steps[$step]['name'].'</h3>';
+}
+
+
+if (version_compare(phpversion(), '5.0') < 0) {
+       function scandir($dirstr) {
+               $files = array();
+               $fh = opendir($dirstr);
+               while (false !== ($filename = readdir($fh))) {
+                       array_push($files, $filename);
+               }
+               closedir($fh);
+               return $files;
+       }
+}
+
+/**
+ * This function is used for printing variables for debugging.
+ * @access  public
+ * @param   mixed $var The variable to output
+ * @param   string $title      The name of the variable, or some mark-up identifier.
+ * @author  Joel Kronenberg
+ */
+function debug($var, $title='') {
+       echo '<pre style="border: 1px black solid; padding: 0px; margin: 10px;" title="debugging box">';
+       if ($title) {
+               echo '<h4>'.$title.'</h4>';
+       }
+       
+       ob_start();
+       print_r($var);
+       $str = ob_get_contents();
+       ob_end_clean();
+
+       $str = str_replace('<', '&lt;', $str);
+
+       $str = str_replace('[', '<span style="color: red; font-weight: bold;">[', $str);
+       $str = str_replace(']', ']</span>', $str);
+       $str = str_replace('=>', '<span style="color: blue; font-weight: bold;">=></span>', $str);
+       $str = str_replace('Array', '<span style="color: purple; font-weight: bold;">Array</span>', $str);
+       echo $str;
+       echo '</pre>';
+}
+?>
\ No newline at end of file
diff --git a/install/include/config_template.php b/install/include/config_template.php
new file mode 100644 (file)
index 0000000..c978652
--- /dev/null
@@ -0,0 +1,132 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+function write_config_file($filename, $comments) {
+       global $config_template;
+
+       $tokens = array('{USER}',
+                                       '{PASSWORD}',
+                                       '{HOST}',
+                                       '{PORT}',
+                                       '{DBNAME}',
+                                       '{TABLE_PREFIX}',
+                                       '{HEADER_IMG}',
+                                       '{HEADER_LOGO}',
+                                       '{GENERATED_COMMENTS}',
+                                       '{CONTENT_DIR}',
+                                       '{MAIL_USE_SMTP}',
+                                       '{GET_FILE}'
+                               );
+
+       if ($_POST['step1']['old_path'] != '') {
+               $values = array(urldecode($_POST['step1']['db_login']),
+                                       addslashes(urldecode($_POST['step1']['db_password'])),
+                                       $_POST['step1']['db_host'],
+                                       $_POST['step1']['db_port'],
+                                       $_POST['step1']['db_name'],
+                                       $_POST['step1']['tb_prefix'],
+                                       addslashes(urldecode($_POST['step1']['header_img'])),
+                                       addslashes(urldecode($_POST['step1']['header_logo'])),
+                                       $comments,
+                                       addslashes(urldecode($_POST['step5']['content_dir'])),
+                                       $_POST['step1']['smtp'],
+                                       $_POST['step1']['get_file']
+                               );
+       } else {
+               $values = array(urldecode($_POST['step2']['db_login']),
+                                       addslashes(urldecode($_POST['step2']['db_password'])),
+                                       $_POST['step2']['db_host'],
+                                       $_POST['step2']['db_port'],
+                                       $_POST['step2']['db_name'],
+                                       $_POST['step2']['tb_prefix'],
+                                       '', //header image
+                                       '', //header logo
+                                       $comments,
+                                       addslashes(urldecode($_POST['step4']['content_dir'])),
+                                       $_POST['step3']['smtp'],
+                                       $_POST['step4']['get_file']
+                               );
+       }
+
+       $config_template = str_replace($tokens, $values, $config_template);
+
+       if (!$handle = @fopen($filename, 'wb')) {
+         return false;
+    }
+       @ftruncate($handle,0);
+    if (!@fwrite($handle, $config_template, strlen($config_template))) {
+               return false;
+    }
+        
+    @fclose($handle);
+       return true;
+}
+
+$config_template = "<"."?php 
+/************************************************************************/
+/* ATutor                                                               */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton */
+/* http://atutor.ca                                                     */
+/*                                                                      */
+/* 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.                        */
+/************************************************************************/
+{GENERATED_COMMENTS}
+/************************************************************************/
+/************************************************************************/
+/* the database user name                                               */
+define('DB_USER',                      '{USER}');
+
+/* the database password                                                */
+define('DB_PASSWORD',                  '{PASSWORD}');
+
+/* the database host                                                    */
+define('DB_HOST',                      '{HOST}');
+
+/* the database tcp/ip port                                             */
+define('DB_PORT',                      '{PORT}');
+
+/* the database name                                                    */
+define('DB_NAME',                      '{DBNAME}');
+
+/* The prefix to add to table names to avoid conflicts with existing    */
+/* tables. Default: AT_                                                 */
+define('TABLE_PREFIX',                 '{TABLE_PREFIX}');
+
+/* Where the course content files are located.  This includes all file  */
+/* manager and imported files.  If security is a concern, it is         */
+/* recommended that the content directory be moved outside of the web  */
+/* accessible area.                                                                                                            */
+define('AT_CONTENT_DIR', '{CONTENT_DIR}');
+
+/* Whether or not to use the default php.ini SMTP settings.             */
+/* If false, then mail will try to be sent using sendmail.              */
+define('MAIL_USE_SMTP', {MAIL_USE_SMTP});
+
+/* Whether or not to use the AT_CONTENT_DIR as a protected directory.   */
+/* If set to FALSE then the content directory will be hard coded        */
+/* to ATutor_install_dir/content/ and AT_CONTENT_DIR will be ignored.   */
+/* This option is used for compatability with IIS and Apache 2.         */
+define('AT_FORCE_GET_FILE', {GET_FILE});
+
+/* DO NOT ALTER THIS LAST LINE                                          */
+define('AT_INSTALL', TRUE);
+
+?".">";
+
+?>
\ No newline at end of file
diff --git a/install/include/footer.php b/install/include/footer.php
new file mode 100644 (file)
index 0000000..d734f06
--- /dev/null
@@ -0,0 +1,18 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+?>
+</div>
+<div style="margin-top: 20px; height: 30px; background-color: #354A81; padding: 10px">&nbsp;</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/install/include/header.php b/install/include/header.php
new file mode 100644 (file)
index 0000000..6408d20
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+error_reporting(E_ALL ^ E_NOTICE);
+
+if ($step < 4) {
+       error_reporting(0);
+       include('../include/config.inc.php');
+       error_reporting(E_ALL ^ E_NOTICE);
+       if (defined('AT_INSTALL')) {
+               echo 'ATutor appears to have been installed already.';
+               exit;
+       }
+}
+
+$install_steps[0] = array('name' => 'Introduction');
+$install_steps[1] = array('name' => 'Terms of Use');
+$install_steps[2] = array('name' => 'Database');
+$install_steps[3] = array('name' => 'Accounts &amp; Preferences');
+$install_steps[4] = array('name' => 'Content Directory');
+$install_steps[5] = array('name' => 'Save Configuration');
+$install_steps[6] = array('name' => 'Anonymous Usage Collection');
+$install_steps[7] = array('name' => 'Done!');
+
+?><!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="utf-8"> 
+<head>
+       <title>ATutor Installation</title>
+       <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+       <link rel="stylesheet" href="stylesheet.css" type="text/css" />
+</head>
+<body>
+<div style="height: 70px; vertical-align: bottom; background-color: #354A81">
+       <h1 id="header">ATutor <?php echo $new_version; ?> Installation</h1>
+       <img src="../images/logo.gif" height="29" width="84" alt="ATutor Logo" id="logo" />
+</div>
+<div class="content">
\ No newline at end of file
diff --git a/install/include/step1.php b/install/include/step1.php
new file mode 100644 (file)
index 0000000..14eddf7
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+if (isset($_POST['submit'])) {
+       if ($_POST['submit'] == 'I Agree') {
+               unset($_POST['submit']);
+               $step++;
+               unset($_POST['action']);
+               return;
+       } else {
+               exit;
+       }
+}
+
+print_progress($step);
+?>
+<p>ATutor is licensed under the terms of the <a href="http://atutor.ca/services/licensing_gpl.php" target="_new">GNU General Public License (GPL)</a>, which essentially allows for the free distribution and modification of ATutor. ATutor has its own license that governs its use outside the bounds of the GPL.</p>
+
+<p>Please see <a href="http://atutor.ca/services/licensing.php" target="_new">atutor.ca</a> for additional details.</p>
+
+<p>If you do not agree to the Terms of Use then you may not install and use ATutor.</p>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+       <input type="hidden" name="action" value="process" />
+       <input type="hidden" name="step" value="1" />
+       <input type="hidden" name="new_version" value="<?php echo $new_version; ?>" />
+       <div align="center">
+               <input type="submit" name="submit" class="button" value="I Agree" /> - <input type="submit" name="submit" class="button" value="I Disagree" /><br />
+       </div>
+</form>
\ No newline at end of file
diff --git a/install/include/step2.php b/install/include/step2.php
new file mode 100644 (file)
index 0000000..91ccca7
--- /dev/null
@@ -0,0 +1,140 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+if(isset($_POST['submit'])) {
+       unset($errors);
+       unset($progress);
+
+       //check DB & table connection
+
+       $db = @mysql_connect($_POST['db_host'] . ':' . $_POST['db_port'], $_POST['db_login'], $_POST['db_password']);
+       if (!$db) {
+               $errors[] = 'Unable to connect to database server.';
+       } else {
+               // check mysql version number
+               $sql = "SELECT VERSION() AS version";
+               $result = mysql_query($sql, $db);
+               $row = mysql_fetch_assoc($result);
+               if (version_compare($row['version'], '4.1.10', '>=') === FALSE) {
+                       $errors[] = 'MySQL version '.$row['version'].' was detected. ATutor requires version 4.1.10 or later.';
+               }
+
+               if (!isset($errors)){
+                       if (!mysql_select_db($_POST['db_name'], $db)) {
+                               $sql = "CREATE DATABASE $_POST[db_name] CHARACTER SET utf8 COLLATE utf8_general_ci";
+                               $result = mysql_query($sql, $db);
+                               if (!$result) {
+                                       $errors[] = 'Unable to select or create database <b>'.$_POST['db_name'].'</b>.';
+                               } else {
+                                       $progress[] = 'Database <b>'.$_POST['db_name'].'</b> created successfully.';
+                                       mysql_select_db($_POST['db_name'], $db);
+                               }
+                       } else {
+                               /* Check if the database that existed is in UTF-8, if not, ask for retry */
+                               $sql = "SHOW CREATE DATABASE $_POST[db_name]";
+                               $result = mysql_query($sql, $db);
+                               $row = mysql_fetch_assoc($result);
+                               
+                               if (!preg_match('/CHARACTER SET utf8/i', $row['Create Database'])){
+                                       $errors[] = 'Database <b>'.$_POST['db_name'].'</b> is not in UTF8.  Please set the database character set to UTF8 before continuing by using the following query: ALTER DATABASE `'.$_POST['db_name'].'` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci.  To use ALTER DATABASE, you need the ALTER privilege on the database.';
+                               }
+                       }
+               }
+
+               if (!isset($errors)) {
+                       $progress[] = 'Connected to database <b>'.$_POST['db_name'].'</b> successfully.';
+                       $errors = array();
+                       
+                       /* @See include/classes/dbmanager.php */
+                       queryFromFile('db/atutor_schema.sql');
+                       queryFromFile('db/atutor_language_text.sql');
+
+                       if (!$errors) {
+                               print_progress($step);
+
+                               unset($_POST['submit']);
+                               unset($_POST['action']);
+                               store_steps($step);
+                               print_feedback($progress);
+
+                               echo '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="form">
+                               <input type="hidden" name="step" value="3" />';
+                               print_hidden(3);
+                               echo '<p align="center"><input type="submit" class="button" value="Next &raquo; " name="submit" /></p></form>';
+                               return;
+                       }
+               }
+
+       }
+}
+
+print_progress($step);
+
+
+echo '<p>Please enter your database information: </p>';
+
+
+if (isset($progress)) {
+       print_feedback($progress);
+}
+
+if (isset($errors)) {
+       print_errors($errors);
+}
+
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+       <input type="hidden" name="action" value="process" />
+       <input type="hidden" name="step" value="2" />
+       <input type="hidden" name="new_version" value="<?php echo $_POST['new_version']; ?>" />
+
+       <table width="65%" class="tableborder" cellspacing="0" cellpadding="1" border="0" align="center">
+       <tr>
+               <td class="row1"><div class="required" title="Required Field">*</div><b><label for="db">Database Hostname:</label></b><br />
+                       Hostname of the database server. Default: <kbd>localhost</kbd></td>
+               <td class="row1" valign="middle"><input type="text" name="db_host" id="db" value="<?php if (!empty($_POST['db_host'])) { echo stripslashes(htmlspecialchars($_POST['db_host'])); } else { echo 'localhost'; } ?>" class="formfield" /></td>
+       </tr>
+       <tr>
+               <td class="row1"><div class="required" title="Required Field">*</div><b><label for="port">Database Port:</label></b><br />
+                       The port to the database server. Default: <kbd>3306</kbd></td>
+               <td class="row1"><input type="text" name="db_port" id="port" value="<?php if (!empty($_POST['db_port'])) { echo stripslashes(htmlspecialchars($_POST['db_port'])); } else { echo '3306'; } ?>" class="formfield" /></td>
+       </tr>
+       <tr>
+               <td class="row1"><div class="required" title="Required Field">*</div><b><label for="username">Database Username:</label></b><br />
+                       The username to the database server.</td>
+               <td class="row1"><input type="text" name="db_login" id="username" value="<?php echo stripslashes(htmlspecialchars($_POST['db_login'])); ?>" class="formfield" /></td>
+       </tr>
+       <tr>
+               <td class="row1"><div class="required" title="Required Field">*</div><b><label for="pass">Database Password:</label></b><br />
+                       The password to the database server.</td>
+               <td class="row1"><input type="text" name="db_password" id="pass" value="<?php echo stripslashes(htmlspecialchars($_POST['db_password'])); ?>" class="formfield" /></td>
+       </tr>
+       <tr>
+               <td class="row1"><div class="required" title="Required Field">*</div><b><label for="name">Database Name:</label></b><br />
+                       The name of the database to use. It will be created if it does not exist.<br />Default: <kbd>atutor</kbd></td>
+               <td class="row1"><input type="text" name="db_name" id="name" value="<?php if (!empty($_POST['db_name'])) { echo stripslashes(htmlspecialchars($_POST['db_name'])); } else { echo 'atutor'; } ?>" class="formfield" /></td>
+       </tr>
+       <tr>
+               <td class="row1"><div class="optional" title="Optional Field">?</div><b><label for="prefix">Table Prefix:</label></b><br />
+                       The prefix to add to table names to avoid conflicts with existing tables.<br />
+                       Default: <kbd>AT_</kbd></td>
+               <td class="row1"><input type="text" name="tb_prefix" id="prefix" value="<?php if (!empty($_POST['tb_prefix'])) { echo stripslashes(htmlspecialchars($_POST['tb_prefix'])); } else { echo 'AT_'; } ?>" class="formfield" /></td>
+       </tr>
+       </table>
+
+       <br /><br /><p align="center"><input type="submit" class="button" value="Next &raquo; " name="submit" /></p>
+
+</form>
diff --git a/install/include/step3.php b/install/include/step3.php
new file mode 100644 (file)
index 0000000..b953dad
--- /dev/null
@@ -0,0 +1,259 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+if(isset($_POST['submit']) && ($_POST['action'] == 'process')) {
+       unset($errors);
+
+       $_POST['admin_username'] = trim($_POST['admin_username']);
+       $_POST['admin_email']    = trim($_POST['admin_email']);
+       $_POST['site_name']      = trim($_POST['site_name']);
+       $_POST['home_url']           = trim($_POST['home_url']);
+       $_POST['email']          = trim($_POST['email']);
+       $_POST['account_email']  = trim($_POST['account_email']);
+       $_POST['account_fname']  = trim($_POST['account_fname']);
+       $_POST['account_lname']  = trim($_POST['account_lname']);
+
+       /* Super Administrator Account checking: */
+       if ($_POST['admin_username'] == ''){
+               $errors[] = 'Administrator username cannot be empty.';
+       } else {
+               /* check for special characters */
+               if (!(eregi("^[a-zA-Z0-9_]([a-zA-Z0-9_])*$", $_POST['admin_username']))){
+                       $errors[] = 'Administrator username is not valid.';
+               }
+       }
+       if ($_POST['form_admin_password_hidden'] == '') {
+               $errors[] = 'Administrator password cannot be empty.';
+       }
+       if ($_POST['admin_email'] == '') {
+               $errors[] = 'Administrator email cannot be empty.';
+       } else if (!eregi("^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$", $_POST['admin_email'])) {
+               $errors[] = 'Administrator email is not valid.';
+       }
+
+       /* System Preferences checking: */
+       if ($_POST['site_name'] == '') {
+               $errors[] = 'Site name cannot be empty.';
+       }
+       if ($_POST['email'] == '') {
+               $errors[] = 'Contact email cannot be empty.';
+       } else if (!eregi("^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$", $_POST['email'])) {
+               $errors[] = 'Contact email is not valid.';
+       }
+
+       /* Personal Account checking: */
+       if ($_POST['account_username'] == ''){
+               $errors[] = 'Personal Account Username cannot be empty.';
+       } else {
+               /* check for special characters */
+               if (!(eregi("^[a-zA-Z0-9_]([a-zA-Z0-9_])*$", $_POST['account_username']))){
+                       $errors[] = 'Personal Account Username is not valid.';
+               } else {
+                       if ($_POST['account_username'] == $_POST['admin_username']) {
+                               $errors[] = 'That Personal Account Username is already being used for the Administrator account, choose another.';
+                       }
+               }
+       }
+       if ($_POST['form_account_password_hidden'] == '') {
+               $errors[] = 'Personal Account Password cannot be empty.';
+       }
+       if ($_POST['account_email'] == '') {
+               $errors[] = 'Personal Account email cannot be empty.';
+       } else if (!eregi("^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$", $_POST['account_email'])) {
+               $errors[] = 'Invalid Personal Account email is not valid.';
+       }
+
+       if ($_POST['account_fname'] == '') {
+               $errors[] = 'Personal Account First Name cannot be empty.';
+       }
+       if ($_POST['account_lname'] == '') {
+               $errors[] = 'Personal Account Last Name cannot be empty.';
+       }
+       if (!isset($errors)) {
+               $db = @mysql_connect($_POST['step2']['db_host'] . ':' . $_POST['step2']['db_port'], $_POST['step2']['db_login'], urldecode($_POST['step2']['db_password']));
+               @mysql_select_db($_POST['step2']['db_name'], $db);
+
+               $_POST['account_email'] = $addslashes($_POST['account_email']);
+               $_POST['account_fname'] = $addslashes($_POST['account_fname']);
+               $_POST['account_lname'] = $addslashes($_POST['account_lname']);
+
+               $status = 3; // for instructor account
+
+               $sql = "INSERT INTO ".$_POST['step2']['tb_prefix']."admins VALUES ('$_POST[admin_username]', '$_POST[form_admin_password_hidden]', '', '$_POST[admin_email]', 'en', 1, NOW())";
+               $result= mysql_query($sql, $db);
+
+               $sql = "INSERT INTO ".$_POST['step2']['tb_prefix']."members VALUES (NULL,'$_POST[account_username]','$_POST[form_account_password_hidden]','$_POST[account_email]','','$_POST[account_fname]','','$_POST[account_lname]','0000-00-00','n', '','','','','', '',$status,'', NOW(),'en', 0, 1, '0000-00-00 00:00:00')";
+               $result = mysql_query($sql ,$db);
+
+               $_POST['site_name'] = $addslashes($_POST['site_name']);
+               $sql = "INSERT INTO ".$_POST['step2']['tb_prefix']."config VALUES ('site_name', '$_POST[site_name]')";
+               $result = mysql_query($sql ,$db);
+
+               $_POST['email'] = $addslashes($_POST['email']);
+               $sql = "INSERT INTO ".$_POST['step2']['tb_prefix']."config VALUES ('contact_email', '$_POST[email]')";
+               $result = mysql_query($sql ,$db);
+
+               $_POST['home_url'] = $addslashes($_POST['home_url']);
+               if ($_POST['home_url'] != '') {
+                       $sql = "INSERT INTO ".$_POST['step2']['tb_prefix']."config VALUES ('home_url', '$_POST[home_url]')";
+                       $result = mysql_query($sql ,$db);
+               }
+
+               unset($_POST['admin_username']);
+               unset($_POST['form_admin_password_hidden']);
+               unset($_POST['admin_email']);
+               unset($_POST['account_username']);
+               unset($_POST['form_account_password_hidden']);
+               unset($_POST['account_email']);
+               unset($_POST['home_url']);
+               unset($_POST['email']);
+               unset($_POST['site_name']);
+
+               unset($errors);
+               unset($_POST['submit']);
+               unset($action);
+               store_steps($step);
+               $step++;
+               return;
+       }
+}      
+
+print_progress($step);
+
+if (isset($errors)) {
+       print_errors($errors);
+}
+
+if (isset($_POST['step1']['old_version']) && $_POST['upgrade_action']) {
+       $defaults['admin_username'] = urldecode($_POST['step1']['admin_username']);
+       $defaults['admin_email']    = urldecode($_POST['step1']['admin_email']);
+
+       $defaults['site_name']   = urldecode($_POST['step1']['site_name']);
+       $defaults['header_img']  = urldecode($_POST['step1']['header_img']);
+       $defaults['header_logo'] = urldecode($_POST['step1']['header_logo']);
+       $defaults['home_url']    = urldecode($_POST['step1']['home_url']);
+} else {
+       $defaults = $_defaults;
+}
+
+?>
+<script language="JavaScript" src="<?php echo AT_INCLUDE_PATH; ?>../../sha-1factory.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+function encrypt_password()
+{
+       document.form.form_admin_password_hidden.value = hex_sha1(document.form.admin_password.value);
+       document.form.form_account_password_hidden.value = hex_sha1(document.form.account_password.value);
+       document.form.admin_password.value = "";
+       document.form.account_password.value = "";
+}
+</script>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+       <input type="hidden" name="action" value="process" />
+       <input type="hidden" name="form_admin_password_hidden" value="" />
+       <input type="hidden" name="form_account_password_hidden" value="" />
+       <input type="hidden" name="step" value="<?php echo $step; ?>" />
+       <?php print_hidden($step); ?>
+
+       <?php
+               /* detect mail settings. if sendmail_path is empty then use SMTP. */
+               if (@ini_get('sendmail_path') == '') { 
+                       echo '<input type="hidden" name="smtp" value="true" />';
+               } else {
+                       echo '<input type="hidden" name="smtp" value="false" />';
+               }
+       ?>
+       <br />
+               <table width="70%" class="tableborder" cellspacing="0" cellpadding="1" align="center">
+               <tr>
+                       <th colspan="2">Super Administrator Account</th>
+               </tr>
+               <tr>
+                       <td colspan="2" class="row1">The Super Administrator account is used for managing ATutor. The Super Administrator can also create additional Administrators each with their own privileges and roles. Administrator accounts cannot enroll in courses.</td>
+               </tr>
+               <tr>
+                       <td class="row1"><div class="required" title="Required Field">*</div><b><label for="username">Administrator Username:</label></b><br />
+                       May contain only letters, numbers, or underscores.</td>
+                       <td class="row1"><input type="text" name="admin_username" id="username" maxlength="20" size="20" value="<?php if (!empty($_POST['admin_username'])) { echo stripslashes(htmlspecialchars($_POST['admin_username'])); } else { echo $defaults['admin_username']; } ?>" class="formfield" /></td>
+               </tr>
+               <tr>
+                       <td class="row1"><div class="required" title="Required Field">*</div><b><label for="password">Administrator Password:</label></b></td>
+                       <td class="row1"><input type="text" name="admin_password" id="password" maxlength="15" size="15" class="formfield" /></td>
+               </tr>
+               <tr>
+                       <td class="row1"><div class="required" title="Required Field">*</div><b><label for="email">Administrator Email:</label></b></td>
+                       <td class="row1"><input type="text" name="admin_email" id="email" size="40" value="<?php if (!empty($_POST['admin_email'])) { echo stripslashes(htmlspecialchars($_POST['admin_email'])); } else { echo $defaults['admin_email']; } ?>" class="formfield" /></td>
+               </tr>
+               </table>
+
+       <br />
+
+               <table width="70%" class="tableborder" cellspacing="0" cellpadding="1" align="center">
+               <tr>
+                       <th colspan="2">System Preferences</th>
+               </tr>
+               <tr>
+                       <td class="row1"><div class="required" title="Required Field">*</div><b><label for="sitename">Site Name:</label></b><br />
+                       The name of your course server website.<br />Default: <kbd><?php echo $defaults['site_name']; ?></kbd></td>
+                       <td class="row1"><input type="text" name="site_name" size="28" maxlength="60" id="sitename" value="<?php if (!empty($_POST['site_name'])) { echo stripslashes(htmlspecialchars($_POST['site_name'])); } else { echo $defaults['site_name']; } ?>" class="formfield" /></td>
+               </tr>
+               <tr>
+                       <td class="row1"><div class="required" title="Required Field">*</div><b><label for="cemail">Contact Email:</label></b><br />
+                       The email that will be used as the return email when needed.</td>
+                       <td class="row1"><input type="text" name="email" id="cemail" size="40" value="<?php if (!empty($_POST['email'])) { echo stripslashes(htmlspecialchars($_POST['email'])); } else { echo $defaults['email']; } ?>" class="formfield" /></td>
+               </tr>
+               <tr>
+                       <td class="row1"><div class="optional" title="Optional Field">?</div><b><label for="home_url">Optional 'Home' URL:</label></b><br />
+                       This will be the URL for the 'Home' link in the Public Area. Leave empty to have this link not appear. <br /></td>
+                       <td class="row1"><input type="text" name="home_url" size="28" maxlength="60" id="home_url" value="<?php if (!empty($_POST['home_url'])) { echo stripslashes(htmlspecialchars($_POST['home_url'])); } else { echo $defaults['home_url']; } ?>" class="formfield" /></td>
+               </tr>
+               </table>
+
+       <br />
+
+               <table width="70%" class="tableborder" cellspacing="0" cellpadding="1" align="center">
+               <tr>
+                       <th colspan="2">Personal Account</th>
+               </tr>
+               <tr>
+                       <td colspan="2" class="row1">You will need a personal account to view and create courses.</td>
+               </tr>
+               <tr>
+                       <td class="row1"><div class="required" title="Required Field">*</div><b><label for="account_username">Username:</label></b><br />
+                       May contain only letters, numbers, and underscores.</td>
+                       <td class="row1"><input type="text" name="account_username" id="account_username" maxlength="20" size="20" value="<?php if (!empty($_POST['account_username'])) { echo stripslashes(htmlspecialchars($_POST['account_username'])); } ?>" class="formfield" /></td>
+               </tr>
+               <tr>
+                       <td class="row1"><div class="required" title="Required Field">*</div><b><label for="account_password">Password:</label></b></td>
+                       <td class="row1"><input type="text" name="account_password" id="account_password" maxlength="15" size="15" class="formfield" /></td>
+               </tr>
+               <tr>
+                       <td class="row1"><div class="required" title="Required Field">*</div><b><label for="account_email">Email:</label></b></td>
+                       <td class="row1"><input type="text" name="account_email" id="account_email" size="40" maxlength="60" value="<?php if (!empty($_POST['account_email'])) { echo stripslashes(htmlspecialchars($_POST['account_email'])); } ?>" class="formfield" /></td>
+               </tr>
+               <tr>
+                       <td class="row1"><div class="required" title="Required Field">*</div><b><label for="account_fname">First Name:</label></b></td>
+                       <td class="row1"><input type="text" name="account_fname" id="account_fname" size="40" maxlength="60" value="<?php if (!empty($_POST['account_fname'])) { echo stripslashes(htmlspecialchars($_POST['account_fname'])); } ?>" class="formfield" /></td>
+               </tr>
+               <tr>
+                       <td class="row1"><div class="required" title="Required Field">*</div><b><label for="account_lname">Last Name:</label></b></td>
+                       <td class="row1"><input type="text" name="account_lname" id="account_lname" size="40" maxlength="60" value="<?php if (!empty($_POST['account_lname'])) { echo stripslashes(htmlspecialchars($_POST['account_lname'])); } ?>" class="formfield" /></td>
+               </tr>
+               </table>
+       <br />
+       <br />
+       <div align="center"><input type="submit" class="button" value=" Next &raquo;" name="submit" onclick="return encrypt_password();" /></div>
+</form>
\ No newline at end of file
diff --git a/install/include/step4.php b/install/include/step4.php
new file mode 100644 (file)
index 0000000..39d845d
--- /dev/null
@@ -0,0 +1,127 @@
+<?php
+exit('this file is no longer used');
+
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+if(isset($_POST['submit']) && ($_POST['action'] == 'process')) {
+       unset($errors);
+       $_POST['username'] = trim($_POST['username']);
+       $_POST['password'] = trim($_POST['password']);
+       $_POST['email']    = trim($_POST['email']);
+
+       $_POST['instructor'] = intval($_POST['instructor']);
+       $_POST['welcome_course'] = intval($_POST['welcome_course']);
+
+       /* login name check */
+       if ($_POST['username'] == ''){
+               $errors[] = 'Username cannot be empty.';
+       } else {
+               /* check for special characters */
+               if (!(eregi("^[a-zA-Z0-9_]([a-zA-Z0-9_])*$", $_POST['username']))){
+                       $errors[] = 'Username is not valid.';
+               } else {
+                       if ($_POST['username'] == $_POST['step3']['admin_username']) {
+                               $errors[] = 'That Username is already being used for the Administrator account, choose another.';
+                       }
+               }
+       }
+
+       if ($_POST['password'] == '') {
+               $errors[] = 'Password cannot be empty.';
+       }
+
+       if ($_POST['email'] == '') {
+               $errors[] = 'Email cannot be empty.';
+       } else if (!eregi("^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$", $_POST['email'])) {
+               $errors[] = 'Invalid email format.';
+       }
+       
+       if (!isset($errors)) {
+               unset($_POST['submit']);
+               unset($_POST['action']);
+
+               if ($_POST['instructor']) {
+                       $status = 3;
+               } else {
+                       $status = 2;
+               }
+
+               $db = mysql_connect($_POST['step2']['db_host'] . ':' . $_POST['step2']['db_port'], $_POST['step2']['db_login'], urldecode($_POST['step2']['db_password']));
+               mysql_select_db($_POST['step2']['db_name'], $db);
+
+               $sql = "INSERT INTO ".$_POST['step2']['tb_prefix']."members VALUES (NULL,'$_POST[username]','$_POST[password]','$_POST[email]','','','','', '','', '','','','','', '',$status,'', NOW(),'en', 0, 1, '0000-00-00 00:00:00')";
+               $result = mysql_query($sql ,$db);
+               $m_id   = mysql_insert_id($db);
+
+               if ($_POST['welcome_course'] && $_POST['instructor']) {
+                       $_POST['tb_prefix'] = $_POST['step2']['tb_prefix'];
+                       queryFromFile('db/atutor_welcome_course.sql');
+               }
+               
+               store_steps($step);
+               $step++;
+               return;
+       }
+} else {
+       unset($_POST['email']);
+}
+
+print_progress($step);
+
+if (isset($errors)) {
+       print_errors($errors);
+}
+
+?>
+<p>You will need a personal account to view and, optionally, create courses.</p>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+       <input type="hidden" name="step" value="4" />
+       <input type="hidden" name="action" value="process" />
+       <?php
+               print_hidden($step);
+       ?>
+       <table width="70%" class="tableborder" cellspacing="0" cellpadding="1" align="center">
+       <tr>
+               <td class="row1"><small><b><label for="username">Username:</label></b><br />
+               May contain only letters, numbers, or underscores.<br />20 character maximum.</small></td>
+               <td class="row1"><input type="text" name="username" id="username" maxlength="20" size="20" value="<?php if (!empty($_POST['username'])) { echo $stripslashes(htmlspecialchars($_POST['username'])); } ?>" class="formfield" /></td>
+       </tr>
+       <tr>
+               <td class="row1"><small><b><label for="password">Password:</label></b><br />
+               Use a combination of letters, numbers and symbols.<br />15 character maximum.</small></td>
+               <td class="row1"><input type="text" name="password" id="password" maxlength="15" size="15" value="<?php if (!empty($_POST['password'])) { echo $stripslashes(htmlspecialchars($_POST['password'])); } ?>" class="formfield" /></td>
+       </tr>
+       <tr>
+               <td class="row1"><small><b><label for="email">Email:</label></b></small></td>
+               <td class="row1"><input type="text" name="email" id="email" size="30" maxlength="60" value="<?php if (!empty($_POST['email'])) { echo $stripslashes(htmlspecialchars($_POST['email'])); } ?>" class="formfield" /></td>
+       </tr>
+       <tr>
+               <td class="row1"><small><b>Instructor Account:</b><br />
+               Do you want this to be an instructor account allowing you to create courses?<br />
+               Default: <kbd>Yes</kbd></small></td>
+               <td class="row1"><input type="radio" name="instructor" value="1" id="en_y" <?php if($_POST['instructor']== 1 || empty($_POST['instructor'])) { echo "checked"; }?>/><label for="en_y">Yes</label>, <input type="radio" name="instructor" value="0" id="en_n" <?php if($_POST['instructor']===0) { echo "checked"; }?>/><label for="en_n">No</label></td>
+       </tr>
+       <tr>
+               <td class="row1"><small><b>Welcome Course:</b><br />
+               Do you want the basic <em>Welcome Course</em> created? Only possible if an instructor account above is created.<br />
+               Default: <kbd>Yes</kbd></small></td>
+               <td class="row1"><input type="radio" name="welcome_course" value="1" id="wc_y" <?php if($_POST['welcome_course']== 1 || empty($_POST['welcome_course'])) { echo 'checked'; }?>/><label for="wc_y">Yes</label>, <input type="radio" name="welcome_course" value="0" id="wc_n" <?php if ($_POST['welcome_course'] === 0) { echo 'checked'; }?>/><label for="wc_n">No</label></td>
+       </tr>
+       </table>
+
+       <br /><br /><p align="center"><input type="submit" class="button" value="Next &raquo; " name="submit" /></p>
+
+</form>
\ No newline at end of file
diff --git a/install/include/step5.php b/install/include/step5.php
new file mode 100644 (file)
index 0000000..64a6679
--- /dev/null
@@ -0,0 +1,245 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+if (isset($_POST['submit'])) {
+       $_POST['content_dir'] = $stripslashes($_POST['content_dir']);
+
+       unset($errors);
+
+       if (!file_exists($_POST['content_dir']) || !realpath($_POST['content_dir'])) {
+               $errors[] = '<strong>Content Directory</strong> entered does not exist.';
+       } else if (!is_dir($_POST['content_dir'])) {
+               $errors[] = '<strong>Content Directory</strong> is not a directory.';
+       } else if (!is_writable($_POST['content_dir'])){
+               $errors[] = 'The Content Directory is not writable.';
+       } else {
+
+               $_POST['content_dir'] = realpath(urldecode($_POST['content_dir']));
+
+               if (!is_dir($_POST['content_dir'].'/import')) {
+                       if (!@mkdir($_POST['content_dir'].'/import')) {
+                               $errors[] = '<strong>'.$_POST['content_dir'].'/import</strong> directory does not exist and cannot be created.';  
+                       }
+               } else if (!is_writable($_POST['content_dir'].'/import')){
+                       $errors[] = '<strong>'.$_POST['content_dir'].'/import</strong> directory is not writable.';
+               } 
+
+               if (!is_dir($_POST['content_dir'].'/chat')) {
+                       if (!@mkdir($_POST['content_dir'].'/chat')) {
+                               $errors[] = '<strong>'.$_POST['content_dir'].'/chat</strong> directory does not exist and cannot be created.';  
+                       }
+               } else if (!is_writable($_POST['content_dir'].'/chat')){
+                       $errors[] = '<strong>'.$_POST['content_dir'].'/chat</strong> directory is not writable.';
+               }
+
+               if (!is_dir($_POST['content_dir'].'/backups')) {
+                       if (!@mkdir($_POST['content_dir'].'/backups')) {
+                               $errors[] = '<strong>'.$_POST['content_dir'].'/backups</strong> directory does not exist and cannot be created.';  
+                       }
+               } else if (!is_writable($_POST['content_dir'].'/backups')){
+                       $errors[] = '<strong>'.$_POST['content_dir'].'/backups</strong> directory is not writable.';
+               }
+               if (!is_dir($_POST['content_dir'].'/feeds')) {
+                       if (!@mkdir($_POST['content_dir'].'/feeds')) {
+                               $errors[] = '<strong>'.$_POST['content_dir'].'/feeds</strong> directory does not exist and cannot be created.';  
+                       }
+               } else if (!is_writable($_POST['content_dir'].'/feeds')){
+                       $errors[] = '<strong>'.$_POST['content_dir'].'/feeds</strong> directory is not writable.';
+               }
+
+               if (!is_dir($_POST['content_dir'].'/file_storage')) {
+                       if (!@mkdir($_POST['content_dir'].'/file_storage')) {
+                               $errors[] = '<strong>'.$_POST['content_dir'].'/file_storage</strong> directory does not exist and cannot be created.';  
+                       }
+               } else if (!is_writable($_POST['content_dir'].'/file_storage')){
+                       $errors[] = '<strong>'.$_POST['content_dir'].'/file_storage</strong> directory is not writable.';
+               }
+
+               if (!is_dir($_POST['content_dir'].'/profile_pictures')) {
+                       if (!@mkdir($_POST['content_dir'].'/profile_pictures')) {
+                               $errors[] = '<strong>'.$_POST['content_dir'].'/profile_pictures</strong> directory does not exist and cannot be created.';  
+                       } else {
+                               mkdir($_POST['content_dir'].'/profile_pictures/originals');
+                               mkdir($_POST['content_dir'].'/profile_pictures/thumbs');
+                       }
+               } else if (!is_writable($_POST['content_dir'].'/profile_pictures')){
+                       $errors[] = '<strong>'.$_POST['content_dir'].'/profile_pictures</strong> directory is not writable.';
+               }
+               if (!is_dir($_POST['content_dir'].'/patcher')) {
+                       if (!@mkdir($_POST['content_dir'].'/patcher')) {
+                               $errors[] = '<strong>'.$_POST['content_dir'].'/patcher</strong> directory does not exist and cannot be created.';  
+                       }
+               } else if (!is_writable($_POST['content_dir'].'/patcher')){
+                       $errors[] = '<strong>'.$_POST['content_dir'].'/patcher</strong> directory is not writable.';
+               }
+
+               // save blank index.html pages to those directories
+               @copy('../images/index.html', $_POST['content_dir'] . '/import/index.html');
+               @copy('../images/index.html', $_POST['content_dir'] . '/chat/index.html');
+               @copy('../images/index.html', $_POST['content_dir'] . '/backups/index.html');
+               @copy('../images/index.html', $_POST['content_dir'] . '/feeds/index.html');
+               @copy('../images/index.html', $_POST['content_dir'] . '/file_storage/index.html');
+               @copy('../images/index.html', $_POST['content_dir'] . '/profile_pictures/index.html');
+               @copy('../images/index.html', $_POST['content_dir'] . '/index.html');
+       }
+
+       if (!isset($errors)) {
+               unset($errors);
+               unset($_POST['submit']);
+               unset($action);
+
+               if (substr($_POST['content_dir'], -1) !='\\'){
+                       $_POST['content_dir'] .= DIRECTORY_SEPARATOR;
+               }
+
+               // kludge to fix the missing slashes when magic_quotes_gpc is On
+               if ($addslashes != 'mysql_real_escape_string') {
+                       $_POST['content_dir'] = addslashes($_POST['content_dir']);
+               }
+
+               store_steps($step);
+               $step++;
+               return;
+       } else {
+               // kludge to fix the missing slashes when magic_quotes_gpc is On
+               if ($addslashes != 'mysql_real_escape_string') {
+                       $_POST['content_dir'] = addslashes($_POST['content_dir']);
+               }
+       }
+}      
+
+print_progress($step);
+
+if (isset($errors)) {
+       print_errors($errors);
+}
+
+if (isset($_POST['step1']['old_version'])) {
+       //get real path to old content
+
+       $old_install   = realpath('../../' . DIRECTORY_SEPARATOR . $_POST['step1']['old_path']);
+       $old_config_cd = urldecode($_POST['step1']['content_dir']); // this path may not exist
+       $new_install   = realpath('../');
+
+       $path_info = pathinfo($old_config_cd);
+       $content_dir_name = $path_info['basename'];
+
+       if ($new_install . DIRECTORY_SEPARATOR . $content_dir_name . DIRECTORY_SEPARATOR == $old_config_cd) {
+               // case 2
+               $copy_from     = $old_install . DIRECTORY_SEPARATOR . $content_dir_name;
+       } else {
+               // case 3 + 4
+               // it's outside
+               $copy_from = '';
+       }
+
+       $_defaults['content_dir'] = $old_config_cd;
+
+} else {
+       $defaults = $_defaults;
+       $blurb = '';
+
+       // the following code checks to see if get.php is being executed, then sets $_POST['get_file'] appropriately:
+       $headers = array();
+       $path  = substr($_SERVER['PHP_SELF'], 0, -strlen('install/install.php')) . 'get.php/?test';
+       $port = isset($_SERVER['SERVER_PORT']) ? $_SERVER['SERVER_PORT'] : 80;
+
+       $host = parse_url($_SERVER['HTTP_HOST']);
+
+       if (isset($host['path'])) {
+               $host = $host['path'];
+       } else if (isset($host['host'])) {
+               $host = $host['host'];
+       } else {
+               $_SERVER['HTTP_HOST'];
+       }
+       if ($port == 443) {
+               // if we're using SSL, but don't know if support is compiled into PHP:
+               $fd = @fopen('https://'.$host.$path, 'rb');
+               if ($fd === false) {
+                       $content = false;
+               } else {
+                       $content = @fread($fd, filesize($filename));
+                       @fclose($fd);
+               }
+
+               if (strlen($content) == 0) {
+                       $headers[] = 'ATutor-Get: OK';
+               } else {
+                       $headers[] = '';
+               }
+       } else {
+               $fp   = @fsockopen($host, $port, $errno, $errstr, 15);
+
+               if($fp) {
+                       $head = 'HEAD '.@$path. " HTTP/1.0\r\nHost: ".@$host."\r\n\r\n";
+                       fputs($fp, $head);
+                       while(!feof($fp)) {
+                               if ($header = trim(fgets($fp, 1024))) {
+                                       $headers[] = $header;
+                               }
+                       }
+               }
+       }
+       if (in_array('ATutor-Get: OK', $headers)) {
+               $get_file = 'TRUE';
+       } else {
+               $get_file = 'FALSE';
+       }
+}
+
+?>
+<br />
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+       <input type="hidden" name="step" value="<?php echo $step; ?>" />
+       <input type="hidden" name="copy_from" value="<?php echo $copy_from; ?>" />
+       <input type="hidden" name="get_file" value="<?php echo $get_file; ?>" />
+       <?php print_hidden($step); ?>
+
+<?php if (isset($_POST['step1']['old_version'])) : ?>
+       <input type="hidden" name="content_dir" value="<?php echo $_defaults['content_dir']; ?>" />
+       <table width="80%" class="tableborder" cellspacing="0" cellpadding="1" align="center">  
+       <tr>
+               <td class="row1">The content directory at <strong><?php echo $_defaults['content_dir']; ?> </strong> will be used for this installation's content. Please create it if it does not already exist.</td>
+       </tr>
+       </table>
+<?php elseif ($get_file == 'FALSE') : ?>
+       <input type="hidden" name="content_dir" value="<?php if (!empty($_POST['content_dir'])) { echo $_POST['content_dir']; } else { echo $_defaults['content_dir']; } ?>" />
+
+       <table width="80%" class="tableborder" cellspacing="0" cellpadding="1" align="center">  
+       <tr>
+               <td class="row1"><div class="required" title="Required Field">*</div><strong><label for="contentdir">Content Directory</label></strong>
+               <p>It has been detected that your webserver does not support the protected content directory feature. The content directory stores all of the courses' files.</p>
+               <p>Due to that restriction your content directory must exist within your ATutor installation directory and cannot be moved. Its path is specified below. Please create it if it does not already exist.</p>
+               <br /><br />
+               <input type="text" name="content_dir_disabled" id="contentdir" value="<?php if (!empty($_POST['content_dir'])) { echo $_POST['content_dir']; } else { echo $_defaults['content_dir']; } ?>" class="formfield" size="70" disabled="disabled" /></td>
+       </tr>
+       </table>
+<?php else: ?>
+       <table width="80%" class="tableborder" cellspacing="0" cellpadding="1" align="center">  
+       <tr>
+               <td class="row1"><div class="required" title="Required Field">*</div><strong><label for="contentdir">Content Directory</label></strong>
+               <p>Please specify where the content directory should be. The content directory stores all of the courses' files. As a security measure, the content directory should be placed <em>outside</em> of your ATutor installation (for example, to a non-web-accessible location that is not publically available).</p>
+               
+               <p>On a Windows machine, the path should look like <kbd>C:\content</kbd>, while on Unix it should look like <kbd>/var/content</kbd>.</p>
+               
+               <p>The directory you specify must be created if it does not already exist and be writeable by the webserver. On Unix machines issue the command <kbd>chmod a+rwx content</kbd>, additionally the path may not contain any symbolic links.</p>
+
+               <input type="text" name="content_dir" id="contentdir" value="<?php if (!empty($_POST['content_dir'])) { echo $_POST['content_dir']; } else { echo $_defaults['content_dir']; } ?>" class="formfield" size="70" /></td>
+       </tr>
+       </table>
+<?php endif; ?>
+       <br /><br /><p align="center"><input type="submit" class="button" value=" Next &raquo;" name="submit" /></p>
+</form>
\ No newline at end of file
diff --git a/install/include/step6.php b/install/include/step6.php
new file mode 100644 (file)
index 0000000..0473d14
--- /dev/null
@@ -0,0 +1,112 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+if(isset($_POST['submit'])) {
+       unset($_POST['submit']);
+       unset($action);
+       store_steps($step);
+       $step++;
+       return;
+}
+
+$file = '../include/config.inc.php';
+
+unset($errors);
+unset($progress);
+
+if ( file_exists($file) ) {
+       @chmod($file, 0666);
+       if (!is_writeable($file)) {
+               $errors[] = '<strong>' . $file . '</strong> is not writeable.';
+       }else{
+               $progress[] = '<strong>' . $file . '</strong> is writeable.';
+       }
+} else {
+       $errors[] = '<strong>' . $file . '</strong> does not exist.';
+}
+
+print_progress($step);
+
+echo '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="form">';
+
+if (isset($errors)) {
+       if (isset($progress)) {
+               print_feedback($progress);
+       }
+       print_errors($errors);
+
+       echo'<input type="hidden" name="step" value="'.$step.'" />';
+
+       unset($_POST['step']);
+       unset($_POST['action']);
+       unset($errors);
+       print_hidden($step);
+
+       echo '<p><strong>Note:</strong> To change permissions on Unix use <kbd>chmod a+rw</kbd> then the file name.</p>';
+
+       echo '<p align="center"><input type="submit" class="button" value=" Try Again " name="retry" />';
+
+} else {
+       require('include/config_template.php');
+               
+       $comments = '/*'.str_pad(' This file was generated by the ATutor '.$new_version. ' installation script.', 70, ' ').'*/
+/*'.str_pad(' File generated '.date('Y-m-d H:m:s'), 70, ' ').'*/';
+
+       if (!write_config_file('../include/config.inc.php', $comments)) {
+               echo '<input type="hidden" name="step" value="'.$step.'" />';
+
+               print_feedback($progress);
+
+               $errors[] = 'include/config.inc.php cannot be written! Please verify that the file exists and is writeable. On Unix issue the command <kbd>chmod a+rw include/config.inc.php</kbd> to make the file writeable. On Windows edit the file\'s properties ensuring that the <kbd>Read-only</kbd> attribute is <em>not</em> checked and that <kbd>Everyone</kbd> access permissions are given to that file.';
+               print_errors($errors);
+
+               echo '<p><strong>Note:</strong> To change permissions on Unix use <kbd>chmod a+rw</kbd> then the file name.</p>';
+
+               echo '<p align="center"><input type="submit" class="button" value=" Try Again " name="retry" />';
+
+       } else {
+               /* if header img and logo were carried forward AND the upgrade was from 1.4.3 to 1.5 then */
+               if (($_POST['step1']['header_img'] != '' || $_POST['step1']['header_logo'] != '') 
+                       && $new_version == '1.5' && $_POST['step1']['old_version'] == '1.4.3')
+                       {
+                               $db = mysql_connect($_POST['step1']['db_host'] . ':' . $_POST['step1']['db_port'], $_POST['step1']['db_login'], urldecode($_POST['step1']['db_password']));
+                               mysql_select_db($_POST['step1']['db_name'], $db);
+
+                               $sql = "INSERT INTO ".$_POST['step1']['tb_prefix']."themes VALUES ('ATutor_alt', '1.5', 'default_oldheader', NOW() , 'Backwards compatible default theme', 2)";
+                               @mysql_query($sql, $db);
+
+                               $sql = "UPDATE ".$_POST['step1']['tb_prefix']."themes SET status=0, version='1.5' WHERE dir_name = 'default'";
+                               @mysql_query($sql, $db);
+                       }
+
+               echo '<input type="hidden" name="step" value="'.$step.'" />';
+               print_hidden($step);
+
+               $progress[] =  'Data has been saved successfully.';
+
+               $cdir = urldecode(trim($_POST['step4']['content_dir']));
+
+               @chmod('../include/config.inc.php', 0444);
+
+               print_feedback($progress);
+
+               echo '<p align="center"><input type="submit" class="button" value=" Next &raquo; " name="submit" /></p>';
+               
+       }
+}
+
+?>
+
+</form>
\ No newline at end of file
diff --git a/install/include/step7.php b/install/include/step7.php
new file mode 100644 (file)
index 0000000..82a426e
--- /dev/null
@@ -0,0 +1,186 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+require('../svn.php');
+
+$svn_data   = explode("\n", $svn_data);
+
+if (substr($svn_data[1], 0, 1) == 'r') {
+       $svn_data = $svn_data[1];
+} else if (substr($svn_data[2], 0, 1) == 'r') {
+       $svn_data = $svn_data[2];
+}
+
+if (count($svn_data) > 1) {
+       $build = 'unknown';
+       $build_date = date('Y-m-d H:i:s');
+} else {
+       $svn_data   = explode(' ', $svn_data);
+
+       $build      = $svn_data[0];
+       $build_date = $svn_data[4] .' '. $svn_data[5];
+}
+
+if (!$build) {
+       $build = 'unknown';
+}
+
+$os = php_uname('s') . ' '. php_uname('r'). ' '. php_uname('v'). ' '. php_uname('m');
+
+
+if (isset($_POST['submit'])) {
+       unset($_POST['submit']);
+       unset($action);
+
+       if ($_POST['log_yes']) {
+
+               $request  = '&upgrade=' . urlencode($stripslashes($_POST['log_upgrade']));
+               $request .= '&version=' . urlencode($stripslashes($new_version));
+               $request .= '&build='   . urlencode($stripslashes($build));
+               $request .= '&build_date=' . urlencode($stripslashes($build_date));
+               $request .= '&os='      . urlencode($stripslashes($_POST['log_os']));
+               $request .= '&server='  . urlencode($stripslashes($_POST['log_server']));
+               $request .= '&php='     . urlencode($stripslashes($_POST['log_php']));
+               $request .= '&mysql='   . urlencode($stripslashes($_POST['log_mysql']));
+
+               if ($_POST['step1']['old_path'] != '') {
+                       // get some usage data from this upgrade:
+                       $db     = @mysql_connect($_POST['step1']['db_host'] . ':' . $_POST['step1']['db_port'], $_POST['step1']['db_login'], urldecode($_POST['step1']['db_password']));
+                       @mysql_select_db($_POST['step1']['db_name'], $db);
+
+                       $db_size = 0; // db size in bytes
+                       $sql = 'SHOW TABLE STATUS';
+                       $result = mysql_query($sql, $db);
+                       while ($row = mysql_fetch_assoc($result)) {
+                               $db_size += $row['Data_length']+$row['Index_length'];
+                       }
+
+                       $sql = "SELECT COUNT(*) AS cnt FROM ".$_POST['step1']['tb_prefix']."courses";
+                       $result = mysql_query($sql, $db);
+                       $row = mysql_fetch_assoc($result);
+                       $num_courses = $row['cnt'];
+
+                       $sql = "SELECT COUNT(*) AS cnt FROM ".$_POST['step1']['tb_prefix']."members";
+                       $result = mysql_query($sql, $db);
+                       $row = mysql_fetch_assoc($result);
+                       $num_users = $row['cnt'];
+
+                       $sql = "SELECT COUNT(*) AS cnt FROM ".$_POST['step1']['tb_prefix']."admins";
+                       $result = mysql_query($sql, $db);
+                       $row = mysql_fetch_assoc($result);
+                       $num_users += $row['cnt'];
+
+                       $sql = "SELECT GROUP_CONCAT(language_code) AS langs FROM ".$_POST['step1']['tb_prefix']."languages";
+                       $result = mysql_query($sql, $db);
+                       $row = mysql_fetch_assoc($result);
+                       $languages = $row['langs'];
+
+                       $request .= '&db='      . $db_size;     // db size in bytes
+                       $request .= '&courses=' . $num_courses; // number of courses
+                       $request .= '&users='   . $num_users;   // number of users (including admins)
+                       $request .= '&langs='   . $languages;   // comma separated list of installed languages
+               }
+
+               if ($_POST['log_url_yes']) {
+                       $request .= '&url=' . urlencode($stripslashes($_POST['log_url']));
+               }
+
+               $header = "POST /install_log.php HTTP/1.1\r\n";
+               $header .= "Host: atutor.ca\r\n";
+               $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
+               $header .= "Content-Length: " . strlen($request) . "\r\n\r\n";
+               $fp = fsockopen('www.atutor.ca', 80, $errno, $errstr, 30);
+
+               if ($fp) {
+                       fputs($fp, $header . $request . "\r\n\r\n");
+                       fclose($fp);
+               }
+       }
+
+       store_steps($step);
+       $step++;
+       return;
+}
+
+print_progress($step);
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="step" value="<?php echo $step; ?>" />
+<?php
+       if ($_POST['step1']['old_path'] != '') {
+               echo '<input type="hidden" name="log_upgrade" value="1" />';
+       } else {
+               echo '<input type="hidden" name="log_upgrade" value="0" />';
+       }
+               print_hidden($step);
+       ?>
+<br />
+       <table width="80%" class="tableborder" cellspacing="0" cellpadding="1" align="center">  
+       <tr>
+               <td class="row1" colspan="2">The following information to the atutor.ca server anonymously? The information we gather helps us plan our development resources to better suit the needs of the community. You may optionally choose to send the URL of your ATutor installation.</td>
+       </tr>
+       <tr>
+               <td class="row1" width="20%"><b>ATutor Version:</b></td>
+               <td class="row1"><?php echo $new_version; ?> (build <?php echo $build . ' - '.$build_date; ?>)</td>
+       </tr>
+       <tr>
+               <td class="row1" nowrap="nowrap"><b>Operating System:</b></td>
+               <td class="row1"><?php echo $os; ?> <input type="hidden" name="log_os" value="<?php echo $os; ?>" /></td>
+       </tr>
+       <tr>
+               <td class="row1"><b>Web Server:</b></td>
+               <td class="row1"><?php echo $_SERVER['SERVER_SOFTWARE']; ?> <input type="hidden" name="log_server" value="<?php echo $_SERVER['SERVER_SOFTWARE']; ?>" /></td>
+       </tr>
+       <tr>
+               <td class="row1"><b>PHP Version:</b></td>
+               <td class="row1"><?php echo phpversion(); ?> <input type="hidden" name="log_php" value="<?php echo phpversion(); ?>" /></td>
+       </tr>
+       <tr>
+               <td class="row1"><b>MySQL Version:</b></td>
+               <td class="row1"><?php
+
+                       if ($_POST['step1']['old_path'] != '') {
+                               $db     = @mysql_connect($_POST['step1']['db_host'] . ':' . $_POST['step1']['db_port'], $_POST['step1']['db_login'], urldecode($_POST['step1']['db_password']));
+                       } else {
+                               $db     = @mysql_connect($_POST['step2']['db_host'] . ':' . $_POST['step2']['db_port'], $_POST['step2']['db_login'], $_POST['step2']['db_password']);
+                       }
+
+                       $sql    = 'SELECT VERSION() AS version';
+                       $result = @mysql_query($sql, $db);
+                       $row    = @mysql_fetch_assoc($result);
+                       echo $row['version'];
+                       ?> <input type="hidden" name="log_mysql" value="<?php echo $row['version']; ?>" /></td>
+       </tr>
+       <tr>
+               <td class="row1" valign="top"><div class="optional" title="Optional Field">?</div><b>Optional URL:</b></td>
+               <td class="row1"><?php
+                       $url = 'http' . ((isset($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) == 'on') ? 's' : '') . '://' . $_SERVER['SERVER_NAME'] . substr($_SERVER['PHP_SELF'], 0, -strlen('install/install.php'));
+                       echo $url; ?><input type="hidden" name="log_url" value="<?php echo $url; ?>" /><br />
+               <input type="checkbox" name="log_url_yes" value="1" id="url_yes" checked="checked"/><label for="url_yes">Include this URL as well.</label></td>
+       </tr>
+       <!--tr>
+               <td class="row1" colspan="2">
+
+<div class="optional" title="Optional Field">?</div><input type="checkbox" name="log_yes" value="1" checked="checked" id="yes_send" /><label for="yes_send">Yes, send this information to atutor.ca.</label>
+<input type="hidden" name="log_yes" value="1" />
+</td>
+       </tr -->
+       </table>
+<input type="hidden" name="log_yes" value="1" />
+<br />
+<p align="center"><input type="submit" class="button" value=" Next &raquo; " name="submit" /></p>
+
+</form>
\ No newline at end of file
diff --git a/install/include/step8.php b/install/include/step8.php
new file mode 100644 (file)
index 0000000..7a94085
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+print_progress($step);
+
+?>
+<p><strong>Congratulations on your installation of ATutor <?php echo $new_version; ?><i>!</i></strong></p>
+
+<p>You may now login using your personal and administrator accounts you created in Step 3.</p>
+
+<p>For security reasons once you have confirmed that ATutor has installed correctly, you should delete the <kbd>install/</kbd> directory,
+and reset the permissions on the config.inc.php file to read only.</p>
+
+<p>See the <a href="http://atutor.ca/forums/">Support Forums</a> on <a href="http://atutor.ca">atutor.ca</a> for additional help &amp; support.</p>
+
+<br />
+
+<form method="get" action="../login.php">
+       <div align="center">
+               <input type="submit" name="submit" value="&raquo; Log-in!" class="button" />
+       </div>
+</form>
\ No newline at end of file
diff --git a/install/include/upgrade_header.php b/install/include/upgrade_header.php
new file mode 100644 (file)
index 0000000..089810b
--- /dev/null
@@ -0,0 +1,54 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+error_reporting(E_ALL ^ E_NOTICE);\r
+\r
+if ($step < 6) {\r
+       error_reporting(0);\r
+       include('../include/config.inc.php');\r
+       error_reporting(E_ALL ^ E_NOTICE);\r
+       if (defined('AT_INSTALL')) {\r
+               echo 'ATutor appears to have been installed already.';\r
+               exit;\r
+       }\r
+}\r
+\r
+$new_version = $new_version ? $new_version : $_POST['step1']['new_version'];\r
+\r
+$install_steps[0] = array('name' => 'Introduction');\r
+$install_steps[1] = array('name' => 'Locate Old Version');\r
+$install_steps[2] = array('name' => 'Database');\r
+$install_steps[3] = array('name' => 'Conversion');\r
+$install_steps[4] = array('name' => 'New '.$new_version.' Configuration Options');\r
+$install_steps[5] = array('name' => 'Content Directory');\r
+$install_steps[6] = array('name' => 'Content Files');\r
+$install_steps[7] = array('name' => 'Save Configuration');\r
+$install_steps[8] = array('name' => 'Anonymous Usage Collection');\r
+$install_steps[9] = array('name' => 'Done!');\r
+\r
+\r
+?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="utf-8"> \r
+<head>\r
+<title>ATutor Upgrade</title>\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<link rel="stylesheet" href="stylesheet.css" type="text/css" />\r
+</head>\r
+\r
+<body>\r
+<div style="height: 70px; vertical-align: bottom; background: #354A81">\r
+       <h1 id="header">ATutor <?php echo $new_version; ?> Upgrade</h1>\r
+       <img src="../images/logo.gif" height="29" width="84" alt="ATutor Logo" id="logo" />\r
+</div>\r
+<div style="clear: all"></div>\r
+<div class="content">
\ No newline at end of file
diff --git a/install/include/ustep1.php b/install/include/ustep1.php
new file mode 100644 (file)
index 0000000..fb2ed07
--- /dev/null
@@ -0,0 +1,270 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+session_unset();       //clear session before using it
+$_SESSION = array();
+print_progress($step);
+
+if (isset($_POST['submit']) && (trim($_POST['old_path']) != '')) {
+       if ((strpos($_POST['old_path'], '/') === false) && is_dir('../../'.$_POST['old_path'])) {
+               if ( file_exists('../../'.$_POST['old_path'] . '/include/config.inc.php') ) {
+                       
+                       require('../../'.$_POST['old_path'] . '/include/lib/constants.inc.php');
+                       if (!defined('VERSION')) {
+                               $errors[] = 'Cannot detect version number. Only ATutor versions greater than 1.0 can be upgraded. Upgrade to 1.1 manually then try upgrading to the latest version again.';
+                       } else {
+                               $progress[] = 'Found ATutor version <kbd><b>'.VERSION . '</b></kbd> in path <kbd><b>'.$_POST['old_path'].'</b></kbd>.';
+                       }
+                       if (!version_compare(VERSION, $new_version, '<')) {
+                               $errors[] = 'The version upgrading (<kbd><b>'.VERSION.'</b></kbd>) is not older than the new version (<kbd><b>'.$new_version.'</b></kbd>).';
+                       }
+
+                       if (!$errors) {
+                               $progress[] = 'Will be upgrading from version <kbd><b>'.VERSION.'</b></kbd> to version <kbd><b>'.$new_version.'</b></kbd>.';
+                               print_feedback($progress);
+
+                               require('../../'.$_POST['old_path'] . '/include/config.inc.php');
+
+                               if (is_array($IllegalExtentions)) {
+                                       $IllegalExtentions = implode(',', $IllegalExtentions);
+                               }
+
+                               echo '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="form">';
+                               echo '<input type="hidden" name="step" value="2" />';
+                               echo '<input type="hidden" name="old_path" value="'.$_POST['old_path'].'" />';
+
+                               echo '<input type="hidden" name="db_login" value="'.urlencode(DB_USER).'" />';
+                               echo '<input type="hidden" name="db_password" value="'.urlencode(DB_PASSWORD).'" />';
+                               echo '<input type="hidden" name="db_host" value="'.DB_HOST.'" />';
+                               if (defined('DB_PORT')) {
+                                       echo '<input type="hidden" name="db_port" value="'.DB_PORT.'" />';
+                               } else {
+                                       echo '<input type="hidden" name="db_port" value="3306" />';
+                               }
+                               echo '<input type="hidden" name="db_name" value="'.DB_NAME.'" />';
+
+                               if (defined('TABLE_PREFIX')) {
+                                       echo '<input type="hidden" name="tb_prefix" value="'.TABLE_PREFIX.'" />';
+                               } else {
+                                       echo '<input type="hidden" name="tb_prefix" value="" />';
+                               }
+                               if (defined('SITE_NAME')) {
+                                       echo '<input type="hidden" name="site_name" value="'.urlencode(SITE_NAME).'" />';
+                               } else {
+                                       echo '<input type="hidden" name="site_name" value="'.$_defaults['site_name'].'" />';
+                               }
+                               if (defined('HEADER_IMAGE')) {
+                                       echo '<input type="hidden" name="header_img" value="'.HEADER_IMAGE.'" />';
+                               } else {
+                                       echo '<input type="hidden" name="header_img" value="'.$_defaults['header_img'].'" />';
+                               }
+                               if (defined('HEADER_LOGO')) {
+                                       echo '<input type="hidden" name="header_logo" value="'.HEADER_LOGO.'" />';
+                               } else {
+                                       echo '<input type="hidden" name="header_logo" value="'.$_defaults['header_logo'].'" />';
+                               }
+                               if (defined('HOME_URL')) {
+                                       echo '<input type="hidden" name="home_url" value="'.HOME_URL.'" />';
+                               } else {
+                                       echo '<input type="hidden" name="home_url" value="'.$_defaults['home_url'].'" />';
+                               }
+
+                               if (defined('MAIL_USE_SMTP')) {
+                                       echo '<input type="hidden" name="smtp" value="'.(MAIL_USE_SMTP ? 'TRUE' : 'FALSE').'" />';
+                               } else {
+                                       echo '<input type="hidden" name="smtp" value="FALSE" />';
+                               }
+                               if (defined('AT_FORCE_GET_FILE')) {
+                                       echo '<input type="hidden" name="get_file" value="'.(AT_FORCE_GET_FILE ? 'TRUE' : 'FALSE').'" />';
+                               } else {
+                                       echo '<input type="hidden" name="get_file" value="FALSE" />';
+                               }
+                               echo '<input type="hidden" name="admin_password" value="'.urlencode(ADMIN_PASSWORD).'" />';
+
+                               if (defined('ADMIN_USERNAME')) {
+                                       echo '<input type="hidden" name="admin_username" value="'.ADMIN_USERNAME.'" />';
+                               } else {
+                                       echo '<input type="hidden" name="admin_username" value="'.$_defaults['admin_username'].'" />';
+                               }
+
+                               if (defined('ADMIN_EMAIL')) {
+                                       echo '<input type="hidden" name="admin_email" value="'.ADMIN_EMAIL.'" />';
+                               } else {
+                                       echo '<input type="hidden" name="admin_email" value="'.$_defaults['admin_email'].'" />';
+                               }
+                               if (defined('EMAIL')) {
+                                       echo '<input type="hidden" name="contact_email" value="'.EMAIL.'" />';
+                               } else if (defined('ADMIN_EMAIL')) {
+                                       echo '<input type="hidden" name="contact_email" value="'.ADMIN_EMAIL.'" />';
+                               } else {
+                                       echo '<input type="hidden" name="contact_email" value="'.$_defaults['admin_email'].'" />';
+                               }
+                               if (defined('EMAIL_NOTIFY')) {
+                                       echo '<input type="hidden" name="email_notification" value="'.(EMAIL_NOTIFY ? 'TRUE' : 'FALSE').'" />';
+                               } else {
+                                       echo '<input type="hidden" name="email_notification" value="'.$_defaults['email_notification'].'" />';
+                               }
+                               if (defined('ALLOW_INSTRUCTOR_REQUESTS')) {
+                                       echo '<input type="hidden" name="allow_instructor_requests" value="'.(ALLOW_INSTRUCTOR_REQUESTS ? 'TRUE' : 'FALSE').'" />';
+                               } else {
+                                       echo '<input type="hidden" name="allow_instructor_requests" value="'.$_defaults['allow_instructor_requests'].'" />';
+                               }
+
+                               if (defined('AT_EMAIL_CONFIRMATION')) {
+                                       echo '<input type="hidden" name="email_confirmation" value="'.(AT_EMAIL_CONFIRMATION ? 'TRUE' : 'FALSE').'" />';
+                               } else {
+                                       echo '<input type="hidden" name="email_confirmation" value="FALSE" />';
+                               }
+                               
+                               if (defined('AT_MASTER_LIST')) {
+                                       echo '<input type="hidden" name="master_list" value="'.(AT_MASTER_LIST ? 'TRUE' : 'FALSE').'" />';
+                               } else {
+                                       echo '<input type="hidden" name="master_list" value="FALSE" />';
+                               }
+                               if (defined('AT_ENABLE_HANDBOOK_NOTES')) {
+                                       echo '<input type="hidden" name="enable_handbook_notes" value="'.(AT_ENABLE_HANDBOOK_NOTES ? 'TRUE' : 'FALSE').'" />';
+                               } else {
+                                       echo '<input type="hidden" name="enable_handbook_notes" value="FALSE" />';
+                               }
+                               if (defined('AUTO_APPROVE_INSTRUCTORS')) {
+                                       echo '<input type="hidden" name="auto_approve" value="'.(AUTO_APPROVE_INSTRUCTORS ? 'TRUE' : 'FALSE').'" />';
+                               } else {
+                                       echo '<input type="hidden" name="auto_approve" value="'.$_defaults['auto_approve'].'" />';
+                               }
+
+                               if (isset($MaxFileSize)) {
+                                       echo '<input type="hidden" name="max_file_size" value="'.$MaxFileSize.'" />';
+                               } else {
+                                       echo '<input type="hidden" name="max_file_size" value="'.$_defaults['max_file_size'].'" />';
+                               }
+                               if (isset($MaxCourseSize)) {
+                                       echo '<input type="hidden" name="max_course_size" value="'.$MaxCourseSize.'" />';
+                               } else {
+                                       echo '<input type="hidden" name="max_course_size" value="'.$_defaults['max_course_size'].'" />';
+                               }
+                               if (isset($MaxCourseFloat)) {
+                                       echo '<input type="hidden" name="max_course_float" value="'.$MaxCourseFloat.'" />';
+                               } else {
+                                       echo '<input type="hidden" name="max_course_float" value="' . $_defaults['max_course_float'] . '" />';
+                               }
+                               
+                               if (isset($IllegalExtentions)) {
+                                       echo '<input type="hidden" name="ill_ext" value="' . $IllegalExtentions . '" />';
+                               } else {
+                                       echo '<input type="hidden" name="ill_ext" value="' . $_defaults['ill_ext'] . '" />';
+                               }
+                               if (defined('CACHE_DIR')) {
+                                       echo '<input type="hidden" name="cache_dir" value="' . CACHE_DIR . '" />';
+                               } else {
+                                       echo '<input type="hidden" name="cache_dir" value="' . $_defaults['cache_dir'] . '" />';
+                               }
+
+                               if (defined('AT_ENABLE_CATEGORY_THEMES')) {
+                                       echo '<input type="hidden" name="theme_categories" value="' . (AT_ENABLE_CATEGORY_THEMES ? 'TRUE' : 'FALSE') . '" />';
+                               } else {
+                                       echo '<input type="hidden" name="theme_categories" value="' . $_defaults['theme_categories'] . '" />';
+                               }
+
+                               if (defined('AT_COURSE_BACKUPS')) {
+                                       echo '<input type="hidden" name="course_backups" value="' . AT_COURSE_BACKUPS . '" />';
+                               } else {
+                                       echo '<input type="hidden" name="course_backups" value="' . $_defaults['course_backups'] . '" />';
+                               }
+
+                               if (defined('AT_CONTENT_DIR')) {
+                                       echo '<input type="hidden" name="content_dir" value="'.AT_CONTENT_DIR.'" />';
+                               } else {
+                                       echo '<input type="hidden" name="content_dir" value="'.$_defaults['content_dir'].'" />';
+                               }
+                               echo '<input type="hidden" name="new_version" value="'.$new_version.'" />';
+                               echo '<input type="hidden" name="old_version" value="'.VERSION.'" />';
+                               echo '<p align="center"><input type="submit" class="button" value=" Next &raquo; " name="submit" /></p></form>';
+                               return;
+                       }
+               } else {
+                       $errors[] = 'Directory was found, but the old configuration file cannot be found.';
+               }
+       } else {
+               $errors[] = 'Directory does not exist relative to the new installation.';
+       }
+}
+
+if (isset($progress)) {
+       print_feedback($progress);
+}
+
+if (isset($errors)) {
+       print_errors($errors);
+}
+
+?>
+<p>Please specify the location of the old ATutor installation.</p>
+
+<ol>
+       <li>Release Candidate (RC) installations cannot be upgraded.</li>
+       <li>Depending on the size of the existing courses, some steps (particularly 2 and 6) of the upgrade may require considerable time to complete.</li>
+       <li>All installed language packs will be deleted.</li>
+       <li>Some installed themes may not be supported by this version.</li>
+       <li>All extra modules will have to be reinstalled before they can be enabled again.</li>
+</ol>
+
+<p>Select the old ATutor installation directory below.</p>
+
+<?php
+       $dirs = scandir('../../');
+       $path = realpath('../../').'/';
+       $current_dir = basename(realpath(getcwd() .'../../'));
+       foreach ($dirs as $key => $value) {
+               if ($value == '.' || $value == '..') {
+                       unset($dirs[$key]);
+               }
+               if ($current_dir == $value) {
+                       unset($dirs[$key]);
+                       continue;
+               }
+               if (!is_dir($path . $value) || !file_exists($path . $value . '/include/config.inc.php')) {
+                       unset($dirs[$key]);
+               }
+       }
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="new_version" value="<?php echo $new_version; ?>" />
+<input type="hidden" name="step" value="1" />
+
+<table width="70%" class="tableborder" cellspacing="0" cellpadding="1" border="0" align="center">
+<tr>
+       <td class="row1"><div class="required" title="Required Field">*</div><b><label for="dir">Old Directory Name:</label></b><br />
+               The old directory must be at the same level as the current directory.</td>
+               <td class="row1" valign="middle">
+               <?php if ($dirs): ?>
+                       <select name="old_path">
+                               <?php foreach ($dirs as $dir): ?>
+                                       <option value="<?php echo htmlspecialchars($dir); ?>"><?php echo $dir; ?>/</option>
+                               <?php endforeach; ?>
+                       </select>
+               <?php else: ?>
+                       <em>None found.</em>
+               <?php endif; ?>
+               </td>
+</tr>
+</table>
+
+<br />
+
+<?php if ($dirs): ?>
+       <br /><p align="center"><input type="submit" class="button" value="Next &raquo; " name="submit" /></p>
+<?php endif; ?>
+
+</form>
\ No newline at end of file
diff --git a/install/include/ustep2.php b/install/include/ustep2.php
new file mode 100644 (file)
index 0000000..6881a71
--- /dev/null
@@ -0,0 +1,168 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+ignore_user_abort(true); 
+@set_time_limit(0); 
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+function update_one_ver($up_file) {
+       global $progress;
+       $update_file = implode('_',$up_file);
+       queryFromFile('db/'.$update_file.'sql');
+       //$progress[] = 'Successful update from version '.$up_file[2].' to '.$up_file[4];
+       return $up_file[4];
+}
+
+$_POST['db_login'] = urldecode($_POST['db_login']);
+$_POST['db_password'] = urldecode($_POST['db_password']);
+
+       unset($errors);
+
+       //check DB & table connection
+
+       $db = @mysql_connect($_POST['db_host'] . ':' . $_POST['db_port'], $_POST['db_login'], urldecode($_POST['db_password']));
+
+       if (!$db) {
+               $error_no = mysql_errno();
+               if ($error_no == 2005) {
+                       $errors[] = 'Unable to connect to database server. Database with hostname '.$_POST['db_host'].' not found.';
+               } else {
+                       $errors[] = 'Unable to connect to database server. Wrong username/password combination.';
+               }
+       } else {
+               if (!mysql_select_db($_POST['db_name'], $db)) {
+                       $errors[] = 'Unable to connect to database <b>'.$_POST['db_name'].'</b>.';
+               }
+
+               $sql = "SELECT VERSION() AS version";
+               $result = mysql_query($sql, $db);
+               $row = mysql_fetch_assoc($result);
+               if (version_compare($row['version'], '4.3', '>=') === FALSE) {
+                       $errors[] = 'MySQL version '.$row['version'].' was detected. ATutor requires version 4.3 or later.';
+               }
+
+               if (!$errors) {
+                       $progress[] = 'Connected to database <b>'.$_POST['db_name'].'</b> successfully.';
+                       unset($errors);
+
+                       //Save all the course primary language into session variables iff it has not been set. 
+                       if (!isset($_SESSION['course_info'])){
+                               $sql = "SELECT a.course_id, a.title, l.language_code, l.char_set FROM ".$_POST['tb_prefix']."courses a left join ".$_POST['tb_prefix']."languages l ON l.language_code = a.primary_language";
+                               $result = mysql_query($sql, $db);
+                               while ($row = mysql_fetch_assoc($result)){
+                                       $_SESSION['course_info'][$row['course_id']] = array('char_set'=>$row['char_set'], 'language_code'=>$row['language_code']);
+                               }
+                       }
+
+                       $sql = "DELETE FROM ".$_POST['tb_prefix']."language_text WHERE `variable`<>'_c_template' AND `variable`<>'_c_msgs'";
+                       @mysql_query($sql, $db);
+
+                       $sql = "DELETE FROM ".$_POST['tb_prefix']."languages WHERE language_code<>'en'";
+                       @mysql_query($sql, $db);
+
+                       //get list of all update scripts minus sql extension
+                       $files = scandir('db'); 
+                       foreach ($files as $file) {
+                               if(count($file = explode('_',$file))==5) {
+                                       $file[4] = substr($file[4],0,-3);
+                                       $update_files[$file[2]] = $file;
+                               }
+                       }
+                       
+                       $curr_ver = $_POST['old_version'];
+                       ksort($update_files);
+                       foreach ($update_files as $up_file) {
+                               if(version_compare($curr_ver, $up_file[4], '<')) {
+                                       update_one_ver($up_file);
+                               }
+                       }
+                       
+                       /* reset all the accounts to English */
+                       $sql = "UPDATE ".$_POST['tb_prefix']."members SET language='en', creation_date=creation_date, last_login=last_login";
+                       @mysql_query($sql, $db);
+
+                       /* set all the courses to 'en' as primary language if empty. added 1.4.1 */
+                       $sql = "UPDATE ".$_POST['tb_prefix']."courses SET primary_language='en' WHERE primary_language=''";
+                       @mysql_query($sql, $db);
+
+                       queryFromFile('db/atutor_language_text.sql');
+
+                       if (!$errors) {
+                               print_progress($step);
+
+                               unset($_POST['submit']);
+                               store_steps(1);
+                               print_feedback($progress);
+
+                               echo '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="form">
+                               <input type="hidden" name="step" value="3" />
+                               <input type="hidden" name="upgrade_action" value="true" />';
+                               echo '<input type="hidden" name="db_login" value="'.urlencode($_POST['db_login']).'" />';
+                               echo '<input type="hidden" name="db_password" value="'.urlencode($_POST['db_password']).'" />';
+                               echo '<input type="hidden" name="db_host" value="'.$_POST['db_host'].'" />';
+                               echo '<input type="hidden" name="db_name" value="'.$_POST['db_name'].'" />';
+                               echo '<input type="hidden" name="db_port" value="'.$_POST['db_port'].'" />';
+                               echo '<input type="hidden" name="tb_prefix" value="'.$_POST['tb_prefix'].'" />';
+                               echo '<input type="hidden" name="old_version" value="'.$_POST['old_version'].'" />';
+                               echo '<input type="hidden" name="new_version" value="'.$_POST['new_version'].'" />';
+                               print_hidden(2);
+                               echo '<p align="center"><input type="submit" class="button" value=" Next &raquo; " name="submit" /></p></form>';
+                               return;
+                       }
+               }
+       }
+
+       print_progress($step);
+
+       unset($_POST['submit']);
+       if (isset($progress)) {
+               print_feedback($progress);
+       }
+
+       if (isset($errors)) {
+               print_errors($errors);
+       }
+
+
+       echo '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="form">
+       <input type="hidden" name="step" value="2" />';
+       store_steps(1);
+       print_hidden(2);
+       
+       if ($found_lang) {
+?>
+<table width="60%" class="tableborder" cellspacing="0" cellpadding="1" border="0" align="center">
+<tr>
+       <td colspan="2" class="row1"><p><small>All installed language packs and changes made to the default English language will be deleted. You will have to re-install any language packs by downloading the latest versions from ATutor.ca. Some language packs may not currently be available.</small></p></td>
+</tr>
+<tr>
+       <td class="row1"><small><b><label for="dir">Continue with the upgrade?</label></b></small></td>
+               <td class="row1" valign="middle" nowrap="nowrap"><input type="radio" name="override" value="1" id="c2" /><label for="c2">Yes, Continue</label>, <input type="radio" name="override" value="0" id="c1" checked="checked" /><label for="c1">No, Cancel</label></td>
+</tr>
+</table><br />
+       <?php
+       }
+
+       echo '<input type="hidden" name="db_login" value="'.urlencode($_POST['db_login']).'" />';
+       echo '<input type="hidden" name="db_password" value="'.urlencode($_POST['db_password']).'" />';
+       echo '<input type="hidden" name="db_host" value="'.$_POST['db_host'].'" />';
+       echo '<input type="hidden" name="db_name" value="'.$_POST['db_name'].'" />';
+       echo '<input type="hidden" name="db_port" value="'.$_POST['db_port'].'" />';
+       echo '<input type="hidden" name="tb_prefix" value="'.$_POST['tb_prefix'].'" />';
+       echo '<input type="hidden" name="old_version" value="'.$_POST['old_version'].'" />';
+       echo '<input type="hidden" name="new_version" value="'.$_POST['new_version'].'" />';
+
+       echo '<p align="center"><input type="submit" class="button" value=" Retry " name="submit" /></p></form>';
+       return;
+?>
\ No newline at end of file
diff --git a/install/include/ustep3.php b/install/include/ustep3.php
new file mode 100644 (file)
index 0000000..731ac01
--- /dev/null
@@ -0,0 +1,253 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+$_POST['db_login']    = urldecode($_POST['db_login']);
+$_POST['db_password'] = urldecode($_POST['db_password']);
+/* Destory session */
+session_unset();
+$_SESSION= array();
+if(isset($_POST['submit']) && ($_POST['action'] == 'process')) {
+       unset($errors);
+       $db = @mysql_connect($_POST['step1']['db_host'] . ':' . $_POST['step1']['db_port'], $_POST['step1']['db_login'], urldecode($_POST['step1']['db_password']));
+       @mysql_select_db($_POST['step1']['db_name'], $db);
+
+       if (version_compare($_POST['step1']['old_version'], '1.5', '<')) {
+               $_POST['admin_username'] = trim($_POST['admin_username']);
+               $_POST['admin_password'] = trim($_POST['admin_password']);
+               $_POST['admin_email']    = trim($_POST['admin_email']);
+               $_POST['site_name']      = trim($_POST['site_name']);
+               $_POST['home_url']           = trim($_POST['home_url']);
+
+               /* Super Administrator Account checking: */
+               if ($_POST['admin_username'] == ''){
+                       $errors[] = 'Administrator username cannot be empty.';
+               } else {
+                       /* check for special characters */
+                       if (!(eregi("^[a-zA-Z0-9_]([a-zA-Z0-9_])*$", $_POST['admin_username']))){
+                               $errors[] = 'Administrator username is not valid.';
+                       }
+               }
+               if ($_POST['admin_password'] == '') {
+                       $errors[] = 'Administrator password cannot be empty.';
+               }
+               if ($_POST['admin_email'] == '') {
+                       $errors[] = 'Administrator email cannot be empty.';
+               } else if (!eregi("^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$", $_POST['admin_email'])) {
+                       $errors[] = 'Administrator email is not valid.';
+               }
+
+               /* System Preferences checking: */
+               if ($_POST['email'] == '') {
+                       $errors[] = 'Contact email cannot be empty.';
+               } else if (!eregi("^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$", $_POST['email'])) {
+                       $errors[] = 'Contact email is not valid.';
+               }
+
+               if (!isset($errors)) {
+                       $sql = "INSERT INTO ".$_POST['step1']['tb_prefix']."admins VALUES ('$_POST[admin_username]', '$_POST[admin_password]', '', '$_POST[admin_email]', 'en', 1, NOW())";
+                       $result= mysql_query($sql, $db);
+
+                       unset($_POST['admin_username']);
+                       unset($_POST['admin_password']);
+                       unset($_POST['admin_email']);
+               }
+       }
+       if (version_compare($_POST['step1']['old_version'], '1.5.2', '<')) {
+               // update config table
+               $sql = "REPLACE INTO ".$_POST['step1']['tb_prefix']."config VALUES ('contact_email', '".urldecode($_POST['step1']['contact_email'])."')";
+               mysql_query($sql, $db);
+
+               $sql = "REPLACE INTO ".$_POST['step1']['tb_prefix']."config VALUES ('email_notification', '".($_POST['step1']['email_notification'] ? 1 : 0)."')";
+               mysql_query($sql, $db);
+
+               $sql = "REPLACE INTO ".$_POST['step1']['tb_prefix']."config VALUES ('allow_instructor_requests', '".($_POST['step1']['allow_instructor_requests'] ? 1 : 0)."')";
+               mysql_query($sql, $db);
+
+               $sql = "REPLACE INTO ".$_POST['step1']['tb_prefix']."config VALUES ('auto_approve_instructors', '".($_POST['step1']['auto_approve'] ? 1 : 0)."')";
+               mysql_query($sql, $db);
+
+               $sql = "REPLACE INTO ".$_POST['step1']['tb_prefix']."config VALUES ('max_file_size', '".(int) $_POST['step1']['max_file_size']."')";
+               mysql_query($sql, $db);
+
+               $sql = "REPLACE INTO ".$_POST['step1']['tb_prefix']."config VALUES ('max_course_size', '".(int) $_POST['step1']['max_course_size']."')";
+               mysql_query($sql, $db);
+
+               $sql = "REPLACE INTO ".$_POST['step1']['tb_prefix']."config VALUES ('max_course_float', '".(int) $_POST['step1']['max_course_float']."')";
+               mysql_query($sql, $db);
+
+               $sql = "REPLACE INTO ".$_POST['step1']['tb_prefix']."config VALUES ('illegal_extentions', '".str_replace(',','|',urldecode($_POST['step1']['ill_ext']))."')";
+               mysql_query($sql, $db);
+
+               $sql = "REPLACE INTO ".$_POST['step1']['tb_prefix']."config VALUES ('site_name', '".urldecode($_POST['step1']['site_name'])."')";
+               mysql_query($sql, $db);
+
+               $sql = "REPLACE INTO ".$_POST['step1']['tb_prefix']."config VALUES ('home_url', '".urldecode($_POST['step1']['home_url'])."')";
+               mysql_query($sql, $db);
+
+               $sql = "REPLACE INTO ".$_POST['step1']['tb_prefix']."config VALUES ('default_language', 'en')";
+               mysql_query($sql, $db);
+
+               $sql = "REPLACE INTO ".$_POST['step1']['tb_prefix']."config VALUES ('cache_dir', '".urldecode($_POST['step1']['cache_dir'])."')";
+               mysql_query($sql, $db);
+
+               $sql = "REPLACE INTO ".$_POST['step1']['tb_prefix']."config VALUES ('enable_category_themes', '".($_POST['step1']['theme_categories'] ? 1 : 0)."')";
+               mysql_query($sql, $db);
+
+               $sql = "REPLACE INTO ".$_POST['step1']['tb_prefix']."config VALUES ('course_backups', '". (int) $_POST['step1']['course_backups']."')";
+               mysql_query($sql, $db);
+
+               $sql = "REPLACE INTO ".$_POST['step1']['tb_prefix']."config VALUES ('email_confirmation', '".($_POST['step1']['email_confirmation'] ? 1 : 0)."')";
+               mysql_query($sql, $db);
+
+               $sql = "REPLACE INTO ".$_POST['step1']['tb_prefix']."config VALUES ('master_list', '".($_POST['step1']['master_list'] ? 1 : 0)."')";
+               mysql_query($sql, $db);
+
+               $sql = "REPLACE INTO ".$_POST['step1']['tb_prefix']."config VALUES ('enable_handbook_notes', '".($_POST['step1']['enable_handbook_notes'] ? 1 : 0)."')";
+               mysql_query($sql, $db);
+
+               // check for bits 8192 and 4096 and remove them if they're set.
+               $sql = "UPDATE ".$_POST['step1']['tb_prefix']."course_enrollment SET `privileges` = `privileges` - 8192 WHERE `privileges` & 8192";
+               mysql_query($sql, $db);
+
+               $sql = "UPDATE ".$_POST['step1']['tb_prefix']."course_enrollment SET `privileges` = `privileges` - 4096 WHERE `privileges` & 4096";
+               mysql_query($sql, $db);
+       }
+
+       if (version_compare($_POST['step1']['old_version'], '1.5.3', '<')) {
+               $sql = "DELETE FROM ".$_POST['step1']['tb_prefix']."groups";
+               mysql_query($sql, $db);
+
+               $sql = "DELETE FROM ".$_POST['step1']['tb_prefix']."groups_members";
+               mysql_query($sql, $db);
+
+               $sql = "DELETE FROM ".$_POST['step1']['tb_prefix']."tests_groups";
+               mysql_query($sql, $db);
+       }
+       if (version_compare($_POST['step1']['old_version'], '1.5.3.3', '<')) {
+               // set display_name_format to "login"
+               $sql = "INSERT INTO ".$_POST['step1']['tb_prefix']."config VALUES ('display_name_format', '0')";
+               mysql_query($sql, $db);
+       }
+
+       if (version_compare($_POST['step1']['old_version'], '1.5.4', '<')) {
+               /* find all the multiple choice multiple answer questions and convert them to 
+                * Multiple Answer which is number 7.
+                */
+               $sql = "UPDATE ".$_POST['step1']['tb_prefix']."tests_questions SET type=7 WHERE type=1 AND answer_0 + answer_1 + answer_2 + answer_3 + answer_4 + answer_5 + answer_6 + answer_7 + answer_8 + answer_9 > 1";
+               mysql_query($sql, $db);
+
+               $sql = "SELECT MAX(admin_privilege) AS max FROM ".$_POST['step1']['tb_prefix']."modules";
+               $result = mysql_query($sql, $db);
+               $row = mysql_fetch_assoc($result);
+               $priv = $row['max'] * 2;
+
+               $sql = "UPDATE ".$_POST['step1']['tb_prefix']."modules SET `admin_privilege`=$priv WHERE `dir_name`='_core/enrolment'";
+               mysql_query($sql, $db);
+       }
+       if (version_compare($_POST['step1']['old_version'], '1.5.5', '<')) {
+               $sql = "UPDATE ".$_POST['step1']['tb_prefix']."tests_results SET status=1, date_taken=date_taken, end_time=date_taken";
+               mysql_query($sql, $db);
+       }
+
+       /* deal with the extra modules: */
+       /* for each module in the modules table check if that module still exists in the mod directory. */
+       /* if that module does not exist then check the old directory and prompt to have it copied */
+       /* or delete it from the modules table. or maybe disable it instead? */
+       if (version_compare($_POST['step1']['old_version'], '1.5.1', '>')) {
+               define('TABLE_PREFIX', $_POST['step1']['tb_prefix']);
+               require(AT_INCLUDE_PATH . 'classes/Module/Module.class.php');
+               $moduleFactory = new ModuleFactory(FALSE);
+               $module_list =& $moduleFactory->getModules(AT_MODULE_STATUS_DISABLED | AT_MODULE_STATUS_ENABLED);
+               $keys = array_keys($module_list);
+               foreach($keys as $dir_name) {
+                       $module =& $module_list[$dir_name];
+                       $module->setIsMissing($module->isExtra());
+               }
+       }
+
+
+       if (!isset($errors)) {
+               unset($errors);
+               unset($_POST['submit']);
+               unset($action);
+               store_steps($step);
+               $step++;
+               return;
+       }
+}
+
+print_progress($step);
+
+if (isset($errors)) {
+       print_errors($errors);
+}
+
+
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+       <input type="hidden" name="action" value="process" />
+       <input type="hidden" name="step" value="<?php echo $step; ?>" />
+       <?php print_hidden($step); ?>
+
+<?php if (version_compare($_POST['step1']['old_version'], '1.5', '<')): ?>
+       <p>Below are new configuration options that are available for this version.</p>
+
+       <br />
+               <table width="70%" class="tableborder" cellspacing="0" cellpadding="1" align="center">
+               <tr>
+                       <th colspan="2">Super Administrator</th>
+               </tr>
+               <tr>
+                       <td class="row1" colspan="2">The Super Administrator account is used for managing ATutor. Since ATutor version 1.5 the Super Administrator can also create additional Administrators each with their own privileges and roles.</td>
+               </tr>
+               <tr>
+                       <td class="row1"><div class="required" title="Required Field">*</div><b><label for="username">Administrator Username:</label></b><br />
+                       May contain only letters, numbers, or underscores.</td>
+                       <td class="row1"><input type="text" name="admin_username" id="username" maxlength="20" size="20" value="<?php if (!empty($_POST['admin_username'])) { echo $stripslashes(htmlspecialchars($_POST['admin_username'])); } else { echo urldecode($_POST['step1']['admin_username']); } ?>" class="formfield" /></td>
+               </tr>
+               <tr>
+                       <td class="row1"><div class="required" title="Required Field">*</div><b><label for="password">Administrator Password:</label></b></td>
+                       <td class="row1"><input type="text" name="admin_password" id="password" maxlength="15" size="15" value="<?php if (!empty($_POST['admin_password'])) { echo $stripslashes(htmlspecialchars($_POST['admin_password'])); } else { echo urldecode($_POST['step1']['admin_password']); } ?>" class="formfield" /></td>
+               </tr>
+               <tr>
+                       <td class="row1"><div class="required" title="Required Field">*</div><b><label for="email">Administrator Email:</label></b></td>
+                       <td class="row1"><input type="text" name="admin_email" id="email" size="30" value="<?php if (!empty($_POST['admin_email'])) { echo $stripslashes(htmlspecialchars($_POST['admin_email'])); } else { echo urldecode($_POST['step1']['admin_email']); } ?>" class="formfield" /></td>
+               </tr>
+               </table>
+
+               <br />
+
+               <table width="70%" class="tableborder" cellspacing="0" cellpadding="1" align="center">
+               <tr>
+                       <th colspan="2">System Preferences</th>
+               </tr>
+               <tr>
+                       <td class="row1"><div class="required" title="Required Field">*</div><b><label for="cemail">Contact Email:</label></b><br />
+                       The email that will be used as the return email when needed and when instructor account requests are made.</td>
+                       <td class="row1"><input type="text" name="email" id="cemail" size="30" value="<?php if (!empty($_POST['email'])) { echo $stripslashes(htmlspecialchars($_POST['admin_email'])); } else { echo urldecode($_POST['step1']['admin_email']); } ?>" class="formfield" /></td>
+               </tr>
+               </table>
+<?php endif; ?>
+<?php if (version_compare($_POST['step1']['old_version'], '1.5.3', '<')): ?>
+       <p>Groups made prior to 1.5.3 are not backwards compatible and will be removed.</p>
+<?php else: ?>
+       <p>There are no new configuration options for this version.</p>
+<?php endif; ?>
+
+       <br />
+       <br />
+       <div align="center"><input type="submit" class="button" value=" Next &raquo;" name="submit" /></div>
+</form>
\ No newline at end of file
diff --git a/install/include/ustep4.php b/install/include/ustep4.php
new file mode 100644 (file)
index 0000000..f583639
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+ignore_user_abort(true); 
+@set_time_limit(0); 
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+if (isset($_POST['submit'])) {
+       if (!isset($errors)) {
+               unset($_POST['submit']);
+               unset($action);
+               store_steps($step);
+               $step++;
+               return;
+       }
+}
+
+print_progress($step);
+
+/* try copying the content over from the old dir to the new one */
+require('../include/lib/filemanager.inc.php'); // for copys()
+
+$content_dir = urldecode(trim($_POST['step5']['content_dir']));
+$_POST['step5']['copy_from'] = urldecode(trim($_POST['step5']['copy_from'])) . DIRECTORY_SEPARATOR;
+
+//copy if copy_from is not empty
+
+if ($_POST['step5']['copy_from'] && ($_POST['step5']['copy_from'] != DIRECTORY_SEPARATOR)) {
+       if (is_dir($_POST['step5']['copy_from'])) {
+               $files = scandir($_POST['step5']['copy_from']);
+
+               foreach ($files as $file) {
+                       if ($file == '.' || $file == '..') { continue; }
+                       if (is_dir($_POST['step5']['copy_from'] . $file)) {
+                               copys($_POST['step5']['copy_from'] . $file, $content_dir . $file);
+                               if (is_dir($content_dir.$course)) {                     
+                                       $progress[] = 'Course content directory <b>'.$file.'</b> copied successfully.';
+                               } else {
+                                       $errors[] = 'Course content directory <b>'.$file.'</b> <strong>NOT</strong> copied.';
+                               }
+                       } else {
+                               // a regular file
+                               copy($_POST['step5']['copy_from'] . $file, $content_dir  .$file);
+                       }
+               }
+       }
+
+} else {
+       $progress[] = 'Using existing content directory <strong>'.$content_dir.'</strong>.';
+}
+/////////////////////
+// Create the patcher content directory
+if (!is_dir($content_dir.'/patcher')) {
+       if (!@mkdir($content_dir.'/patcher')) {
+               $errors[] = '<strong>'.$content_dir.'/patcher</strong> directory does not exist and cannot be created.';  
+       }
+} else if (!is_writable($content_dir.'/patcher')){
+       $errors[] = '<strong>'.$content_dir.'/patcher</strong> directory is not writable.';
+}
+////////////////////////
+echo '<br />';
+if (isset($progress)) {
+       print_feedback($progress);
+}
+if (isset($errors)) {
+       print_errors($errors);
+}
+
+if ($_POST['step1']['cache_dir'] != '') {
+       define('CACHE_DIR', urldecode($_POST['step1']['cache_dir']));
+       define('CACHE_ON', 1);
+       require('../include/phpCache/phpCache.inc.php');
+       cache_gc(NULL, 1, true);
+}
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="step" value="<?php echo $step;?>" />
+<?php print_hidden($step); ?>
+
+<br /><br /><p align="center"><input type="submit" class="button" value=" Next &raquo;" name="submit" /></p>
+</form>
\ No newline at end of file
diff --git a/install/include/ustep5.php b/install/include/ustep5.php
new file mode 100644 (file)
index 0000000..56fd28c
--- /dev/null
@@ -0,0 +1,103 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+if(isset($_POST['submit'])) {
+       unset($_POST['submit']);
+       unset($action);
+       store_steps($step);
+       $step++;
+       return;
+}
+
+$file = '../include/config.inc.php';
+
+unset($errors);
+unset($progress);
+
+if ( file_exists($file) ) {
+       @chmod($file, 0666);
+       if (!is_writeable($file)) {
+               $errors[] = '<strong>' . $file . '</strong> is not writeable. Use <kbd>chmod a+rw '.$file.'</kbd> to change permissions.';
+       }else{
+               $progress[] = '<strong>' . $file . '</strong> is writeable.';
+       }
+} else {
+       $errors[] = '<strong>' . $file . '</strong> does not exist.';
+}
+
+print_progress($step);
+
+echo '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="form">';
+
+if (isset($errors)) {
+       if (isset($progress)) {
+               print_feedback($progress);
+       }
+       print_errors($errors);
+
+       echo'<input type="hidden" name="step" value="'.$step.'" />';
+
+       unset($_POST['step']);
+       unset($_POST['action']);
+       unset($errors);
+       print_hidden($step);
+
+       echo '<p><strong>Note:</strong> To change permissions on Unix use <kbd>chmod a+rw</kbd> then the file name.</p>';
+
+       echo '<p align="center"><input type="submit" class="button" value=" Try Again " name="retry" />';
+
+} else {
+
+       if (!copy('../../'.$_POST['step1']['old_path'] . '/include/config.inc.php', '../include/config.inc.php')) {
+               echo '<input type="hidden" name="step" value="'.$step.'" />';
+
+               print_feedback($progress);
+
+               $errors[] = 'include/config.inc.php cannot be written! Please verify that the file exists and is writeable. On Unix issue the command <kbd>chmod a+rw include/config.inc.php</kbd> to make the file writeable. On Windows edit the file\'s properties ensuring that the <kbd>Read-only</kbd> attribute is <em>not</em> checked and that <kbd>Everyone</kbd> access permissions are given to that file.';
+               print_errors($errors);
+
+               echo '<p><strong>Note:</strong> To change permissions on Unix use <kbd>chmod a+rw</kbd> then the file name.</p>';
+
+               echo '<p align="center"><input type="submit" class="button" value=" Try Again " name="retry" />';
+
+       } else {
+               echo '<input type="hidden" name="step" value="'.$step.'" />';
+               print_hidden($step);
+
+               $progress[] =  'Data has been saved successfully.';
+
+               if (version_compare($_POST['step1']['old_version'], '1.5.2', '<')) {
+                       require('include/config_template.php');
+                       
+                       $comments = '/*'.str_pad(' This file was generated by the ATutor 1.5.2 installation script.', 70, ' ').'*/
+               /*'.str_pad(' File generated '.date('Y-m-d H:m:s'), 70, ' ').'*/';
+
+                       $_POST['db_login'] = urldecode($_POST['db_login']);
+                       $_POST['db_password'] = urldecode($_POST['db_password']);
+
+                       write_config_file('../include/config.inc.php', $comments);
+               }
+               @chmod('../include/config.inc.php', 0444);
+
+               print_feedback($progress);
+
+               echo '<p align="center"><input type="submit" class="button" value=" Next &raquo; " name="submit" /></p>';
+               
+       }
+}
+
+?>
+
+</form>
\ No newline at end of file
diff --git a/install/include/ustep6.php b/install/include/ustep6.php
new file mode 100644 (file)
index 0000000..351ec05
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+print_progress($step);
+
+?>
+<p><strong>Congratulations on your upgrade of ATutor <?php echo $new_version; ?><i>!</i></strong></p>
+
+<p>It is important that you login as the ATutor administrator to review and set any new System Configuration options.</p>
+<p>For security reasons,  after you have confirmed the installation was successful, it is also important that you delete the <kbd>install/</kbd> directory and reset the<kbd> /include/config.inc.php</kbd> file to read-only. On Linux/Unix systems, use <kbd>chmod a-w include/config.inc.php</kbd>.</p>
+<p>See the <a href="http://atutor.ca/forums/">Support Forums</a> on <a href="http://atutor.ca">atutor.ca</a> for additional help &amp; support.</p>
+
+<br />
+
+<form method="get" action="../login.php">
+       <div align="center">
+               <input type="submit" name="submit" value="&raquo; Log-in!" class="button" />
+       </div>
+</form>
\ No newline at end of file
diff --git a/install/include/ustep7.php b/install/include/ustep7.php
new file mode 100644 (file)
index 0000000..43cb1e6
--- /dev/null
@@ -0,0 +1,566 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id: ustep2.php 6902 2007-04-13 18:19:10Z joel $\r
+\r
+ignore_user_abort(true); \r
+@set_time_limit(0); \r
+\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+require('classes/TableConversion.class.php');\r
+$_POST['db_login'] = urldecode($_POST['db_login']);\r
+$_POST['db_password'] = urldecode($_POST['db_password']);\r
+unset($errors);\r
+\r
+//check DB & table connection\r
+$db = @mysql_connect($_POST['db_host'] . ':' . $_POST['db_port'], $_POST['db_login'], urldecode($_POST['db_password']));\r
+\r
+if (!$db) {\r
+       $error_no = mysql_errno();\r
+       if ($error_no == 2005) {\r
+               $errors[] = 'Unable to connect to database server. Database with hostname '.$_POST['db_host'].' not found.';\r
+       } else {\r
+               $errors[] = 'Unable to connect to database server. Wrong username/password combination.';\r
+       }\r
+} else {\r
+       if (!mysql_select_db($_POST['db_name'], $db)) {\r
+               $errors[] = 'Unable to connect to database <b>'.$_POST['db_name'].'</b>.';\r
+       }\r
+\r
+       $sql = "SELECT VERSION() AS version";\r
+       $result = mysql_query($sql, $db);\r
+       $row = mysql_fetch_assoc($result);\r
+       if (version_compare($row['version'], '4.0.2', '>=') === FALSE) {\r
+               $errors[] = 'MySQL version '.$row['version'].' was detected. ATutor requires version 4.0.2 or later.';\r
+       }\r
+\r
+       if (!$errors) {\r
+               print_progress($step);\r
+\r
+               /* \r
+                * Check if version is > 1.6, if so, this entire step can be skipped\r
+                * OR if db table are already all in utf8.\r
+                */\r
+               if (version_compare($_POST['step1']['old_version'], '1.6.1', '>') === TRUE ||\r
+                       check_db_default_charset($db) === TRUE) {\r
+                       $progress[] = 'Version <kbd><b>'.$_POST['step1']['old_version'].'</b></kbd> found.';\r
+                       $progress[] = 'UTF-8 Conversion is not needed, skipping.';\r
+                       print_feedback($progress);\r
+                       echo '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="form">\r
+                       <input type="hidden" name="step" value="4" />';\r
+                       print_hidden(2);\r
+                       echo '<p align="center"><input type="submit" class="button" value=" Next &raquo;" name="submit" /></p></form>';\r
+                       return;\r
+               }\r
+\r
+               unset($_POST['submit']);\r
+               if (isset($progress)) {\r
+                       print_feedback($progress);\r
+               }\r
+\r
+               $progress[] = 'Connected to database <b>'.$_POST['db_name'].'</b> successfully.';\r
+               unset($errors);\r
+\r
+               //If this is a Retry on step3 failure, load step2 post values back to jump right back to where it left off.\r
+               if (isset($_POST['step2'])){\r
+                       $temp = $_POST;\r
+                       $_POST = $_POST['step2'];\r
+                       $_POST['step1'] = $temp['step1'];\r
+               }\r
+\r
+               //Conversion type set\r
+               if ($_POST['con_step']=='2'){\r
+                       //Get list of unqiue encoding; skip utf8\r
+                       $char_encodings = array();\r
+                       foreach($_SESSION['course_info'] AS $course_id=>$temp){\r
+                               if (strtolower($temp['char_set'])!='utf-8' && strtolower($temp['char_set'])!='utf8' \r
+                                       && !in_array($temp['char_set'], $char_encodings)){\r
+                                       $char_encodings[] = $temp['char_set'];\r
+                               }\r
+                       }\r
+                       echo '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="form">\r
+                       <input type="hidden" name="step" value="3" />';\r
+\r
+                       print_hidden(2);\r
+                       /*\r
+                        * If we are converting the entire database, then all we need is just 1 language encoding;\r
+                        * if we are converting each class individually, then we need to output all the classes and allow language \r
+                        * options to choose from\r
+                        */\r
+                       $convert_type = $_POST['convert_type'];\r
+                       $recommanded_conversion = $_POST['recommanded_conversion'];\r
+                       $confirm_con_step = $_POST['confirm_con_step'];\r
+                       //check if the user-selected convert_type is the same as the recommanded conversion type, if not, give a warning msg\r
+                       if ($convert_type!=$recommanded_conversion && $confirm_con_step==""){\r
+                               //The html fragment that sets the suggested conversion type on bold \r
+                               $suggestion = array('class="suggested"', 'checked="checked"');  \r
+                               $suggestion_skip="";\r
+                               $suggestion_all="";\r
+                               $suggestion_courses=""; \r
+                               echo '<div><p>You have selected a different conversion option from the recommanded one.  Please verify your option and click "Yes, please continue." to continue.</p><p>Please be aware that invalid conversion may lose your data.</p></div>';\r
+                               generateCourseLangTable($_POST['tb_prefix'], $_SESSION['course_info']);\r
+                               //Print the selected options from the previous user option.\r
+                               switch($convert_type){\r
+                                       case "all": \r
+                                               $suggestion_all[1] =& $suggestion[1] ;\r
+                                               break;\r
+                                       case "skip":\r
+                                               $suggestion_skip[1] =& $suggestion[1];\r
+                                               break;\r
+                                       case "courses":\r
+                                               $suggestion_courses[1] =& $suggestion[1];\r
+                                               break;\r
+                               }\r
+                               switch($recommanded_conversion){\r
+                                       case "all": \r
+                                               $suggestion_all[0] =& $suggestion[0] ;\r
+                                               break;\r
+                                       case "skip":\r
+                                               $suggestion_skip[0] =& $suggestion[0];\r
+                                               break;\r
+                                       case "courses":\r
+                                               $suggestion_courses[0] =& $suggestion[0];\r
+                                               break;\r
+                               }\r
+\r
+\r
+                               echo '<div '.$suggestion_all[0].'><input type="radio" id="convert_all" name="convert_type" value="all" '.$suggestion_all[1].'/>';\r
+                               echo '<label for="convert_all">Convert all content</label></div>';\r
+\r
+                               echo '<div '.$suggestion_courses[0].'><input type="radio" id="convert_courses" name="convert_type" value="courses" '.$suggestion_courses[1].'/>';\r
+                               echo '<label for="convert_courses">Convert content by courses</label></div>';\r
+\r
+                               echo '<div '.$suggestion_skip[0].'><input type="radio" id="convert_skip" name="convert_type" value="skip" '.$suggestion_skip[1].'/>';\r
+                               echo '<label for="convert_skip">Skip conversion</label></div>';\r
+                       \r
+                               print_post_for_step9($_POST);\r
+                               echo '<input type="hidden" name="step" value="3" />';  \r
+                               echo '<input type="hidden" name="con_step" value="2" />'; \r
+                               echo '<input type="hidden" name="confirm_con_step" value="true" />';\r
+                               echo '<p align="center"><input type="submit" class="button" value=" Yes, please continue. " name="submit" /></p></form>';\r
+                               return;\r
+                       }\r
+\r
+                       if ($convert_type=='all'){\r
+                               echo "<div><p>You have chosen the <strong>Convert all content</strong> option.  All ATutor's content will be converted to UTF-8 from the encoding listed below.</p></div>";\r
+                               echo "<div><p>Note: This might take up to several minutes, please be patient while you wait.</p></div><br/>";\r
+                               echo "<div><label>Convert From: </label><select name='encoding_code'>";\r
+                       \r
+                               foreach ($char_encodings as $index=>$encoding){\r
+                                       $selected='';\r
+                                       if ($encoding==$_POST['conv_all_char_set']){\r
+                                               $selected = 'selected="selected" ';\r
+                                       }\r
+                                       echo "<option value='$encoding' $selected>$encoding</option>";\r
+                               }\r
+                               echo "</select></div>";\r
+                       } elseif ($convert_type=='courses'){\r
+                               echo "<div><p>You have chosen the conversion by course.  Each of the following courses' content will be converted to UTF-8 with respect to its Course Primary Language. </p></div>";\r
+                               echo '<div><p>Notes:</p><ul>';\r
+                               echo '<li class="important">Please backup your ATutor database before clicking next.</li>';\r
+                               echo '<li>This conversion will convert only course related tables, other tables will be converted from the ATutor default (ISO-8859-1) to UTF-8.</li>';\r
+                               echo '<li>If the "Course Primary Language" listed below is not the language that you wish to convert from, please change the "Course Primary Language" under "Course Properties" to the language you want to convert from.</li>';\r
+                               echo '</ul></div>';\r
+                               generateCourseLangTable($_POST['tb_prefix'], $_SESSION['course_info']);\r
+                       } elseif ($convert_type=='skip'){\r
+                               //When 'skip' has been chosen, check if version# < 1.6, if so, convert database structure(not content); o/w skip to next step.\r
+                               if (version_compare($_POST['step1']['old_version'], '1.6', '<') === TRUE) {\r
+                                       unset($progress);\r
+                                       $progress[] = "Will not be converting database content.";\r
+                                       $progress[] = "Will be converting database table column structure (charset, collation) to UTF-8.";\r
+                                       print_feedback($progress);\r
+                                       print_post_for_step9($_POST);\r
+                                       echo '<input type="hidden" name="step" value="3" />'; \r
+                                       echo '<input type="hidden" name="con_step" value="3" />';\r
+                                       echo '<p align="center"><input type="submit" class="button" value=" Next &raquo;" name="submit" /></p></form>';\r
+                                       return;\r
+                               } elseif (version_compare($_POST['step1']['old_version'], '1.6.1', '<') === TRUE) {\r
+                                       //Check if version#=1.6 if so, then this 1.6 database must already been upgraded before.\r
+                                       //change all table to utf-8.\r
+                                       $conversionDriver =& new ConversionDriver($_POST['tb_prefix']);\r
+                                       $conversionDriver->alter_all_charset();\r
+                                       unset($progress);\r
+                                       $progress[] = "All tables' charset are now in UTF-8.";\r
+                                       print_feedback($progress);\r
+                                       print_post_for_step9($_POST);\r
+                                       echo '<input type="hidden" name="step" value="3" />'; \r
+                                       echo '<input type="hidden" name="con_step" value="4" />';\r
+                                       echo '<p align="center"><input type="submit" class="button" value=" Next &raquo;" name="submit" /></p></form>';\r
+                                       return;\r
+                               }\r
+                               echo "<div><p>Skipping UTF-8 Conversion.</p><p>No content will be converted.</p></div>";\r
+                               echo '<input type="hidden" name="step" value="4" />'; //skip to next step\r
+                               echo '<p align="center"><input type="submit" class="button" value=" Next &raquo;" name="submit" /></p></form>';\r
+                               return;\r
+                       } else {\r
+                               $errors[] = "No conversion type selected.";\r
+                               print_errors($errors);\r
+                               print_post_for_step9($_POST);\r
+                               echo '<input type="hidden" name="step" value="3" />';  \r
+                               echo '<p align="center"><input type="submit" class="button" value=" Retry &raquo;" name="submit" /></p></form>';\r
+                               return;\r
+                       }                       \r
+                       print_post_for_step9($_POST);\r
+                       echo '<input type="hidden" name="convert_type" value="'.$convert_type.'"/>';\r
+                       echo '<input type="hidden" name="con_step" value="3" />';\r
+                       echo '<p align="center"><input type="submit" class="button" value=" Next &raquo;" name="submit" /></p></form>';\r
+                       return;\r
+               } elseif ($_POST['con_step'] == '3'){\r
+                       //Check if this is a refresh request, if so, don't convert the db.\r
+                       if (isset($_SESSION['conversion_completed']) && $_SESSION['conversion_completed']==true){\r
+                               $progress[] ='Database has already been converted, click next to continue.';\r
+                               print_feedback($progress);\r
+                               echo '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="form">\r
+                               <input type="hidden" name="step" value="3" />\r
+                               <input type="hidden" name="con_step" value="4" /> \r
+                               <input type="hidden" name="upgrade_action" value="true" />';\r
+                               print_hidden(2);\r
+                               print_post_for_step9($_POST);\r
+                               echo '<p align="center"><input type="submit" class="button" value=" Next &raquo; " name="submit" /></p></form>';\r
+                               return;\r
+                       }\r
+\r
+                       $result = '';\r
+                       // Get course code to map encoding/charset\r
+                       if ($_POST['convert_type'] == 'all' || $_POST['convert_type'] == 'courses' ){                   \r
+                               $query = "SELECT course_id, title FROM ".$_POST['tb_prefix']."courses";\r
+                               $result = mysql_query($query);\r
+                               if (mysql_num_rows($result) <= 0){\r
+                                       return false;\r
+                               }                               \r
+                       } else {\r
+                               //'Skip' was selected, convert table structure only                             \r
+                               queryFromFile('db/atutor_convert_db_to_utf8.sql');\r
+                               $progress[] = 'Database table structure has been converted to UTF-8.';\r
+                               print_feedback($progress);\r
+                               if (isset($errors)){\r
+                                       print_errors($errors);\r
+                                       echo '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="form">\r
+                                       <input type="hidden" name="step" value="3" />';\r
+                                       print_hidden(2);\r
+                                       print_post_for_step9($_POST);\r
+                                       echo '<p align="center"><input type="submit" class="button" value=" Retry " name="submit" /></p></form>';\r
+                                       return;\r
+                               }\r
+                               echo '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="form">\r
+                                       <input type="hidden" name="step" value="3" />';\r
+                               echo '<input type="hidden" name="con_step" value="4" />'; \r
+                               print_hidden(2);\r
+                               print_post_for_step9($_POST);\r
+                               echo '<p align="center"><input type="submit" class="button" value=" Next &raquo; " name="submit" /></p></form>';                                \r
+                               return;         \r
+                       }\r
+                       \r
+                       /* \r
+                        * redo_conversion SESSION variable keep tracks of the table that failed conversion.  \r
+                        * If it is set, then run only those tables inside the redo_conversion SESSION variable.  \r
+                        */\r
+                       if (isset($_SESSION['redo_conversion'])){\r
+                               unset($errors);\r
+                               foreach($_SESSION['redo_conversion'] as $course_title=>$class_obj){\r
+                                       foreach($class_obj as $class_name=>$class_param){\r
+                                               $temp_table =& new $class_name ($class_param[0], $class_param[1], $class_param[2], $class_param[3]);\r
+                                               if (!$temp_table->convert()){\r
+                                                       $errors[]= $course_title.': '.$class_param[0].$class_param[1].' was not converted.';\r
+                                               } else {\r
+                                                       unset($_SESSION['redo_conversion'][$class_name]);\r
+                                                       $progress[] = "$class_param[1]  has now been converted.";\r
+                                               }\r
+                                       }\r
+                               }\r
+                       } else {\r
+                               /* \r
+                                * Convert course independent materials such as user information, categories \r
+                                * Decide which language to use\r
+                                */\r
+                               $conversionDriver =& new ConversionDriver($_POST['tb_prefix']);\r
+                               if (version_compare($_POST['step1']['old_version'], '1.6', '<') === TRUE) {\r
+                                       $conversionDriver->convertTableBySysDefault();\r
+                               } \r
+                               $conversionDriver->convertTableBySysDefault_161();\r
+\r
+                               /* \r
+                                * Loop through all the courses, and convert all the course's content \r
+                                * Flush out the process in the mean time.\r
+                                */     \r
+                               echo '<div style="padding-left:1em; margin-top: 0.5em; margin-left:1em; overflow:auto; height:100px; border:1px solid #30b626;;">';\r
+                               while ($row = mysql_fetch_assoc($result)){\r
+                                       $course_id = $row['course_id'];\r
+                                       //Get charset\r
+                                       if (isset($_POST['encoding_code'])&& $_POST['encoding_code']!=""){\r
+                                               $char_set = $_POST['encoding_code'];\r
+                                       } else {\r
+                                               $char_set = $_SESSION['course_info'][$course_id]['char_set'];\r
+                                       }\r
+                                       $row['title'] = mb_convert_encoding($row['title'], "UTF-8", $char_set);\r
+\r
+                                       //If this is already in UTF-8, skip conversion\r
+                                       if (strtolower($char_set)=="utf-8" || strtolower($char_set)=="utf8"){\r
+                                               $progress[] = 'Course ('.$row['title'].') <strong>has been skipped</strong>, course\'s content are already in UTF-8.';\r
+                                               continue;\r
+                                       }\r
+                                       $progress[] = 'Course ('.$row['title'].') <strong>has been converted</strong> from '.$char_set;\r
+\r
+                                       //Run through all ATutor table and convert only those rows with the above courses.\r
+                                       //todo: implement a driver class inside the TableConversion class.\r
+                                       ob_start();\r
+                                       echo "Converting $row[title]...<br/>";\r
+                                       ob_flush();\r
+                                       flush();\r
+                                       ob_end_flush();\r
+                                       if (version_compare($_POST['step1']['old_version'], '1.6', '<') === TRUE) {\r
+                                               $conversionDriver->convertTableByClass($row['title'], $char_set, $course_id);\r
+                                       } \r
+                                       $conversionDriver->convertTableByClass_161($row['title'], $char_set, $course_id);\r
+                               }\r
+                               echo '</div>';\r
+                       }\r
+                       //Check if there are any errors, if not, jump to next step\r
+                       if (!$errors) {\r
+                               unset($_POST['submit']);\r
+//                             store_steps(1);\r
+                               //Will not allow refresh on this screen, because it will re-convert the database.\r
+                               $_SESSION['conversion_completed'] = true;\r
+\r
+                               print_feedback($progress);\r
+\r
+                               if (isset($errors)){\r
+                                       print_errors($errors);\r
+                                       echo '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="form">\r
+                                       <input type="hidden" name="step" value="3" />\r
+                                       <input type="hidden" name="con_step" value="4" />';\r
+                                       print_hidden(2);\r
+                                       print_post_for_step9($_POST);\r
+                                       echo '<p align="center"><input type="submit" class="button" value=" Retry " name="submit" /></p></form>';\r
+                                       return;\r
+                               }\r
+\r
+                               echo '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="form">\r
+                               <input type="hidden" name="step" value="3" />\r
+                               <input type="hidden" name="con_step" value="4" />\r
+                               <input type="hidden" name="upgrade_action" value="true" />';\r
+                               print_hidden(2);\r
+                               print_post_for_step9($_POST);\r
+                               echo '<p align="center"><input type="submit" class="button" value=" Next &raquo; " name="submit" /></p></form>';\r
+                               return;\r
+                       }\r
+               } elseif ($_POST['con_step'] == '4'){\r
+                       //Convert the database charset to UTF8.\r
+                       if (!check_db_default_charset($db)){\r
+                               $sql = 'ALTER DATABASE `'.$_POST['db_name'].'` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci';\r
+                               if (mysql_query($sql)===false){\r
+                                       //Alter failed, probably the user doesn't have permission.\r
+                                       $errors[] = 'Failed to change the database default character set to UTF-8.  Please set the database character set to UTF8 before continuing by using the following query: ALTER DATABASE `'.$_POST['db_name'].'` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci.  To use ALTER DATABASE, you need the ALTER privilege on the database.';\r
+                               }\r
+                       }\r
+                       $progress[] ='Database default charset is now in UTF-8, click next to continue.';\r
+                       print_feedback($progress);\r
+                       echo '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="form">\r
+                               <input type="hidden" name="step" value="4" />';\r
+                       print_hidden(2);\r
+                       print_post_for_step9($_POST);\r
+                       echo '<p align="center"><input type="submit" class="button" value=" Next &raquo; " name="submit" /></p></form>';                                \r
+                       return;\r
+               } else {\r
+                       /* If the installation has been stopped right after the conversion step.  The session variable\r
+                        * that prevents refreshes will still be set, have to unset it to carry on the installation.\r
+                        */\r
+                       if (isset($_SESSION['conversion_completed'])){\r
+                               unset($_SESSION['conversion_completed']);\r
+                       }\r
+\r
+                       $html = '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="form">\r
+                       <input type="hidden" name="step" value="3" />';\r
+//                     store_steps(1);\r
+\r
+                       $html .= '<div><p>ATutor 1.6 upgrade requires you to convert ATutor content to UTF-8.  The courses are listed below with their associated primary language.  </p><p>Please choose one of the conversion options listed below, the recommanded option(in blue) is already selected for you.</p><p>For a more detailed description for each of these conversions, please visit our <a href="http://wiki.atutor.ca/display/atutorwiki/UTF-8+Conversion" target="blank">ATutor Wiki page</a></p></div>';\r
+\r
+                       //The html fragment that sets the suggested conversion type on bold \r
+                       $suggestion = array('class="suggested"', 'checked="checked"');  \r
+                       $suggestion_skip="";\r
+                       $suggestion_all="";\r
+                       $suggestion_courses=""; \r
+                       $recommanded_conversion = "";\r
+\r
+                       $html .= '<table class="data">';\r
+                       $html .= '<tr><th>Course Title</th><th>Course Primary Language</th></tr>';\r
+\r
+                       //Get all courses and their associated language from $_POST\r
+                       $prev_language = "";  //Keep tracks of the course primary language in each loop.\r
+                       $is_same_language = true;\r
+                       if (isset($_SESSION['course_info'])){\r
+                               foreach ($_SESSION['course_info'] as $course_id=>$row){\r
+                                       if ($prev_language==""){\r
+                                               $prev_language = $row['char_set'];\r
+                                       } elseif ($is_same_language==true) {\r
+                                               if($prev_language != $row['char_set']){\r
+                                                       $is_same_language &= false;\r
+                                               }\r
+                                       }\r
+                                       //Get title\r
+                                       $query = 'SELECT title, primary_language FROM '.$_POST['tb_prefix'].'courses WHERE course_id='.$course_id;\r
+                                       $result = mysql_query($query);\r
+                                       if ($result && mysql_numrows($result) > 0){\r
+                                               $rs_row = mysql_fetch_assoc($result);\r
+                                               //if the char_set of the course is not defined, the array will be emptied.\r
+                                               $html .= '<tr><td>';\r
+                                               $html .= @mb_convert_encoding($rs_row['title'], "UTF-8", $row['char_set']);\r
+                                               $html .= '</td><td>'.$row['char_set'];\r
+                                               if ($row['char_set']==''){\r
+                                                       $errors[] = "<strong>$rs_row[title]</strong> has a primary language that does not appear to be installed on the system.  Before continuing, either set the primary language to one that is installed, or install the missing language pack.";\r
+                                                       $html .= ' <strong style="color:red;">Missing "'.$rs_row['primary_language'].'"</strong>';\r
+                                               } \r
+                                               $html .= '</td></tr>';\r
+                                       }\r
+                               }\r
+                       }\r
+                       if ($is_same_language == true){\r
+                               if (strtolower($prev_language)=="utf8" || strtolower($prev_language)=="utf-8" ){\r
+                                       $suggestion_skip =& $suggestion;\r
+                                       $recommanded_conversion = "skip";\r
+                               } else {\r
+                                       $suggestion_all =& $suggestion;\r
+                                       $recommanded_conversion = "all";\r
+                                       $html .= '<input type="hidden" name="conv_all_char_set" value="'.$prev_language.'" />';\r
+                               }\r
+                       } else {\r
+                               $suggestion_courses =& $suggestion;\r
+                               $recommanded_conversion = "courses";\r
+                       }\r
+                       $html .= '</table><br/>';\r
+\r
+                       $html .= '<div><p><strong>Convert all content:</strong> Use this option if you are using just <i><u>one</u></i> non-UTF-8 language pack in your ATutor.</p>';\r
+                       $html .= '<p><strong>Convert content by courses:</strong> Use this option when you are using <i><u>more than one</u></i> UTF-8 or non-UTF-8 language pack in your ATutor.</p>';\r
+                       $html .= '<p><strong>Skip conversion:</strong> Use this option when you have <i><u>only UTF-8</u></i> language packs in your ATutor.</p>';\r
+                       $html .= '</div>';\r
+\r
+                       $html .= '<div '.$suggestion_all[0].'><input type="radio" id="convert_all" name="convert_type" value="all" '.$suggestion_all[1].'/>';\r
+                       $html .= '<label for="convert_all">Convert all content</label></div>';\r
+\r
+                       $html .= '<div '.$suggestion_courses[0].'><input type="radio" id="convert_courses" name="convert_type" value="courses" '.$suggestion_courses[1].'/>';\r
+                       $html .= '<label for="convert_courses">Convert content by courses</label></div>';\r
+\r
+                       $html .= '<div '.$suggestion_skip[0].'><input type="radio" id="convert_skip" name="convert_type" value="skip" '.$suggestion_skip[1].'/>';\r
+                       $html .= '<label for="convert_skip">Skip conversion</label></div>';\r
+       \r
+                       //States flags for ustep9\r
+                       $html .= '<input type="hidden" name="con_step" value="2" />';\r
+                       $html .= '<input type="hidden" name="recommanded_conversion" value="'.$recommanded_conversion.'" />';\r
+                       if (isset($errors)){\r
+                               print_errors($errors);\r
+                               $html .= '<p align="center"><input type="submit" class="button" value=" Retry " name="submit" /></p>';\r
+                       } else {\r
+                               $html .= '<p align="center"><input type="submit" class="button" value=" Next &raquo;" name="submit" /></p>';\r
+                       }\r
+                       echo $html;\r
+                       print_hidden(2);\r
+                       print_post_for_step9($_POST);\r
+                       echo '</form>';                 \r
+                       return;\r
+               }\r
+       }\r
+}\r
+\r
+       //Failed \r
+       if (isset($errors)) {\r
+               print_errors($errors);\r
+       }\r
+\r
+       echo '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="form">\r
+       <input type="hidden" name="step" value="3" />';\r
+       store_steps(2);\r
+       print_hidden(3);\r
+       print_post_for_step9($_POST);\r
+       echo '<p align="center"><input type="submit" class="button" value=" Retry " name="submit" /></p></form>';\r
+       return;\r
+\r
+\r
+/** ---------------------------------------------------------------------------\r
+ * Functions declaraion\r
+ *  ---------------------------------------------------------------------------\r
+ */\r
+/**\r
+ * Runs through the database and get all the courses' titles and languages out\r
+ * @param              table_prefix is the database table prefix\r
+ * @course_info        is the array that stores the course_id->[charset, encoding] mapping.\r
+ */\r
+ function generateCourseLangTable($table_prefix, $course_info){\r
+       echo '<table class="data">';\r
+       echo '<tr><th>Course Title</th><th>Course Primary Language</th></tr>';\r
+       //Get all courses and their associated languages out    \r
+       foreach ($course_info AS $course_id=>$row){\r
+               $query = 'SELECT title FROM '.$table_prefix.'courses WHERE course_id='.$course_id;\r
+               $result = mysql_query($query);\r
+               if ($result && mysql_numrows($result) > 0){\r
+                       $rs_row = mysql_fetch_assoc($result);\r
+               } else {\r
+                       return;\r
+               }\r
+               echo '<tr><td>';\r
+               if ($row['char_set']==''){\r
+                       echo $rs_row['title'];\r
+                       echo '</td><td>Undefined</td></tr>';\r
+               } else {\r
+                       echo mb_convert_encoding($rs_row['title'], "UTF-8", $row['char_set']);\r
+                       echo '</td><td>'.$row['char_set'].'</td></tr>';\r
+               }               \r
+       }\r
+       echo '</table>';\r
+ }\r
+\r
+/**\r
+ * This function prints out the post values that need to be carried over along\r
+ * the entire step 9.\r
+ * @param $_post the post parameter\r
+ */\r
+function print_post_for_step9($_POST){\r
+       echo '<input type="hidden" name="db_login" value="'.urlencode($_POST['db_login']).'" />';\r
+       echo '<input type="hidden" name="db_password" value="'.urlencode($_POST['db_password']).'" />';\r
+       echo '<input type="hidden" name="db_host" value="'.$_POST['db_host'].'" />';\r
+       echo '<input type="hidden" name="db_name" value="'.$_POST['db_name'].'" />';\r
+       echo '<input type="hidden" name="db_port" value="'.$_POST['db_port'].'" />';\r
+       echo '<input type="hidden" name="tb_prefix" value="'.$_POST['tb_prefix'].'" />';\r
+       echo '<input type="hidden" name="old_version" value="'.$_POST['old_version'].'" />';\r
+       echo '<input type="hidden" name="new_version" value="'.$_POST['new_version'].'" />';\r
+}\r
+\r
+\r
+/**\r
+ * This function checks if the database's and tbale's default charset are UTF-8.\r
+ * @return true if db default charset is UTF-8, false otherwise.\r
+ */\r
+function check_db_default_charset($db){\r
+       //Check database's default charset\r
+       $sql = "SHOW CREATE DATABASE `$_POST[db_name]`";\r
+       $result = mysql_query($sql, $db);\r
+       $row = mysql_fetch_assoc($result);\r
+\r
+       if (!preg_match('/CHARACTER SET utf8/i', $row['Create Database'])){\r
+               return false;\r
+       } \r
+\r
+       //check tables\r
+       $sql = "SHOW TABLES";\r
+       $result = mysql_query($sql, $db);\r
+       while ($row = mysql_fetch_row($result)){\r
+               $row[0];\r
+               $sql2 = "SHOW CREATE TABLE `$row[0]`";\r
+               $result2 = mysql_query($sql2, $db);\r
+               $row2 = mysql_fetch_row($result);\r
+\r
+               if (!preg_match('/DEFAULT CHARSET\=utf8/i', $row[1])){\r
+                       return false;\r
+               }                       \r
+       }\r
+\r
+       return true;\r
+}\r
+?>
\ No newline at end of file
diff --git a/install/include/ustep_pwd_encryt.php b/install/include/ustep_pwd_encryt.php
new file mode 100644 (file)
index 0000000..9cc9a93
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: ustep1.php 7208 2008-01-09 16:07:24Z greg $
+
+define('AT_INCLUDE_PATH', '../../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+print "Checking database<br><br>";
+
+$sql = "SELECT member_id, first_name, last_name, password FROM ".TABLE_PREFIX."members";
+$result = mysql_query($sql, $db);
+
+while ($row = mysql_fetch_assoc($result))
+{
+       if (strlen($row["password"]) < 40)
+       {
+               print "updating member ".$row["first_name"]." ".$row["last_name"].": from ".$row["password"]." to " .sha1($row["password"])."<br>";
+               $sql_update = "UPDATE ".TABLE_PREFIX."members set password = '".sha1($row["password"])."' WHERE member_id=".$row["member_id"];
+               $result_update = mysql_query($sql_update, $db);
+       }
+}
+
+print "<br>Done!";
+?>
diff --git a/install/index.php b/install/index.php
new file mode 100644 (file)
index 0000000..6a76e1d
--- /dev/null
@@ -0,0 +1,351 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', 'include/');
+error_reporting(E_ALL ^ E_NOTICE);
+
+require('../include/lib/constants.inc.php');
+
+$new_version = VERSION;
+
+header('Cache-Control: no-store, no-cache, must-revalidate');
+header('Pragma: no-cache');
+
+$session_error = '';
+error_reporting(E_ALL);
+ob_start();
+session_start();
+$session_error = ob_get_contents();
+ob_end_clean();
+error_reporting(E_ALL ^ E_NOTICE);
+
+require(AT_INCLUDE_PATH.'header.php');
+$bad  = '<img src="images/bad.gif" width="14" height="13" border="0" alt="Bad" title="Bad" />';
+$good = '<img src="images/feedback.gif" width="16" height="13" border="0" alt="Good" title="Good" />';
+
+$no_good = FALSE;
+$not_as_good = FALSE;
+?>
+<h3>Welcome to the ATutor Installation</h3>
+<p>This process will step you through your ATutor installation or upgrade.</p>
+<p>During this process be sure not to use your browser's <em>Refresh</em> or <em>Reload</em> feature as it may complicate the installation process.</p>
+
+<p>Before you continue you may want to review the <a href="../documentation/admin/" target="_new"><em>ATutor Handbook</em></a> for more detailed instructions.</p>
+
+<h4>Requirements</h4>
+<p>Please review the requirements below before proceeding.</p>
+               <table class="data" style="width: 75%; max-width: 600px;">
+               <tbody>
+               <tr>
+                       <th scope="col">File Integrity</th>
+                       <th scope="col">Detected</th>
+                       <th scope="col">Status</th>
+               </tr>
+               <tr>
+                       <td>Case Sensitivity</td>
+                       <td><?php if (file_exists('../include/classes/CSVExport.class.php') && file_exists('../include/classes/csvexport.class.php')) {
+                                               echo 'Ignored</td><td align="center">';
+                                               echo $good;
+                                       } else if (file_exists('../include/classes/CSVExport.class.php')) {
+                                               echo 'Enforced</td><td align="center">';
+                                               echo $good;
+                                       } else {
+                                               echo 'Enforced</td><td align="center">';
+                                               echo $bad;
+                                               $no_good = TRUE;
+                                       } ?></td>
+               </tr>
+               </tbody>
+               <tbody>
+               <tr>
+                       <th scope="col">PHP Options</th>
+                       <th scope="col">Detected</th>
+                       <th scope="col">Status</th>
+               </tr>
+               <tr>
+                       <td>PHP 4.3.0+</td>
+                       <td><?php echo phpversion(); ?></td>
+                       <td align="center"><?php        if (version_compare(phpversion(), '4.3.0', '>=')) {
+                                                       echo $good;
+                                               } else {
+                                                       echo $bad;
+                                                       $no_good = TRUE;
+                                               } ?></td>
+               </tr>
+               <tr>
+                       <td><kbd>zlib</kbd></td>
+                       <td><?php if (extension_loaded('zlib')) {
+                                               echo 'Enabled</td><td align="center">';
+                                               echo $good;
+                                       } else {
+                                               echo 'Disabled</td><td align="center">';
+                                               echo $bad;
+                                               $no_good = TRUE;
+                                       } ?></td>
+               </tr>
+               <tr>
+                       <td><kbd>mbstring</kbd></td>
+                       <td><?php if (extension_loaded('mbstring')) {
+                                               echo 'Enabled</td><td align="center">';
+                                               echo $good;
+                                       } else {
+                                               echo 'Disabled</td><td align="center">';
+                                               echo $bad;
+                                               $not_as_good = TRUE;
+                                       } ?></td>
+               </tr>
+               <tr>
+                       <td><kbd>mysql</kbd></td>
+                       <td><?php if (extension_loaded('mysql')) {
+                                               echo 'Enabled</td><td align="center">';
+                                               echo $good;
+                                       } else {
+                                               echo 'Disabled</td><td align="center">';
+                                               echo $bad;
+                                               $no_good = TRUE;
+                                       } ?></td>
+               </tr>
+               <tr>
+                       <td><kbd>safe_mode = Off</kbd></td>
+                       <td><?php if (ini_get('safe_mode')) {
+                                                       echo 'On</td><td align="center">'; 
+                                                       echo $bad;
+                                                       $no_good = TRUE;
+                                               } else {
+                                                       echo 'Off</td><td align="center">';
+                                                       echo $good;
+                                               } ?></td>
+               </tr>
+               <tr>
+                       <td><kbd>file_uploads = On</kbd></td>
+                       <td><?php if (ini_get('file_uploads')) {
+                                                       echo 'On</td><td align="center">';
+                                                       echo $good;
+                                               } else {
+                                                       echo 'Off</td><td align="center">';
+                                                       echo $bad;
+                                                       $no_good = TRUE;
+                                               } ?></td>
+               </tr>
+               <tr>
+                       <td><kbd>upload_max_filesize</kbd> &gt;= 2 MB</td>
+                       <td><?php echo $filesize = ini_get('upload_max_filesize'); ?></td>
+                       <td align="center"><?php 
+                               $filesize_int = intval($filesize);
+                               if ("$filesize_int" == $filesize) {
+                                       // value is in Bytes
+                                       if ($filesize_int < 2 * 1024 * 1024) {
+                                               echo $bad;
+                                       } else {
+                                               echo $good;
+                                       }
+                               } else if (stristr($filesize, 'M') !== FALSE) {
+                                       // value is in MegaBytes
+                                       if ($filesize_int < 2) {
+                                               echo $bad;
+                                       } else {
+                                               echo $good;
+                                       }
+                               } else if (stristr($filesize, 'K') !== FALSE) {
+                                       // value is in KiloBytes
+                                       if ($filesize_int < 2 * 1024) {
+                                               echo $bad;
+                                       } else {
+                                               echo $good;
+                                       }
+                               } else if (stristr($filesize, 'G') !== FALSE) {
+                                       // value is in GigaBytes
+                                       echo $good;
+                               } else {
+                                       // not set?
+                               }
+                               ?></td>
+               </tr>
+               <tr>
+                       <td><kbd>post_max_size</kbd> &gt;= 8 MB</td>
+                       <td><?php echo $filesize = ini_get('post_max_size'); ?></td>
+                       <td align="center"><?php 
+                               $filesize_int = intval($filesize);
+                               if ("$filesize_int" == $filesize) {
+                                       // value is in Bytes
+                                       if ($filesize_int < 8 * 1024 * 1024) {
+                                               echo $bad;
+                                       } else {
+                                               echo $good;
+                                       }
+                               } else if (stristr($filesize, 'M') !== FALSE) {
+                                       // value is in MegaBytes
+                                       if ($filesize_int < 8) {
+                                               echo $bad;
+                                       } else {
+                                               echo $good;
+                                       }
+                               } else if (stristr($filesize, 'K') !== FALSE) {
+                                       // value is in KiloBytes
+                                       if ($filesize_int < 8 * 1024) {
+                                               echo $bad;
+                                       } else {
+                                               echo $good;
+                                       }
+                               } else if (stristr($filesize, 'G') !== FALSE) {
+                                       // value is in GigaBytes
+                                       echo $good;
+                               } else {
+                                       // not set?
+                               }
+                               ?></td>
+               </tr>
+               <tr>
+                       <td><kbd>sessions</kbd></td>
+                       <td><?php if (extension_loaded('session')) {
+                                               echo 'Enabled</td><td align="center">';
+                                               echo $good;
+                                       } else {
+                                               echo 'Disabled</td><td align="center">';
+                                               echo $bad;
+                                               $no_good = TRUE;
+                                       } ?></td>
+               </tr>
+               <tr>
+                       <td><kbd>session.auto_start = 0</kbd></td>
+                       <td><?php if (ini_get('session.auto_start')) {
+                                                       echo '1</td><td align="center">';
+                                                       echo $bad;
+                                                       $no_good = TRUE;
+                                               } else {
+                                                       echo '0</td><td align="center">';
+                                                       echo $good;
+                                               } ?></td>
+               </tr>
+               <tr>
+                       <td><kbd>session.save_path</kbd></td>
+                       <td><?php
+                               if ($session_error == '') {
+                                       echo 'Directory Writeable</td><td align="center">';
+                                       echo $good;
+                               } else {
+                                       echo 'Directory Not Writeable</td><td align="center">';
+                                       echo $bad;
+                                       $no_good = TRUE;                                        
+                               }
+                       ?></td>
+               </tr>
+               <tr>
+                       <td><kbd>.</kbd> in <kbd>include_path</kbd></td>
+                       <td><?php
+                               $include_path = explode(PATH_SEPARATOR, ini_get('include_path'));
+                               if (in_array('.', $include_path)) {
+                                       echo 'Enabled</td><td align="center">';
+                                       echo $good;
+                               } else {
+                                       echo 'Disabled</td><td align="center">';
+                                       echo $bad;
+                                       $no_good = TRUE;                                        
+                               }
+                       ?></td>
+               </tr>
+               </tbody>
+               <tbody>
+               <tr>
+                       <th scope="col">MySQL Options</th>
+                       <th scope="col">Detected</th>
+                       <th scope="col">Status</th>
+               </tr>
+               <tr>
+                       <td>MySQL 4.1.10+</td>
+                       <td><?php if (defined('MYSQL_NUM')) {
+                                               $mysql_version = mysql_get_client_info();
+                                               echo 'Found  Version '.$mysql_version.'</td><td align="center">';
+                                               echo $good;
+                                       } else {
+                                               echo 'Not Found</td><td align="center">';
+                                               echo $bad;
+                                               $no_good = TRUE;
+                                       } ?></td>
+               </tr>
+               </tbody>
+               </table>
+<br />
+
+<?php if ($no_good): ?>
+       <table cellspacing="0" class="tableborder" cellpadding="1" align="center" width="70%">
+       <tr>
+               <td class="row1"><strong>Your server does not meet the minimum requirements!<br />
+                                               Please correct the above errors to continue.</strong></td>
+       </tr>
+       </table>
+<?php elseif ($not_as_good): ?>
+       <table cellspacing="0" class="tableborder" cellpadding="1" align="center" width="70%">
+       <tr>
+               <td class="row1"><strong>ATutor has indicated that the 'mbstring' library is missing from the PHP.  <br />
+                                               We strongly encourage you to install the 'mbstring' library before continuing, however, if you choose not to install the library from PHP, a third party library within ATutor will be used.  <br/><br/>
+                                               For production systems, we strongly encourage you to install the PHP with <a href="http://ca.php.net/manual/en/ref.mbstring.php" target="php_site">mbstring</a> support.  <br/><br/>
+                                               You may choose to by pass the mbstring check for the installation at your own risk by clicking <a href="javascript:void(0);" onclick="javascript:document.form.next.disabled=false;">continue</a>.</strong></td>
+               <td class="row1"></td>
+       </tr>
+       <tr>
+               <td align="right" class="row1" nowrap="nowrap"><strong>New Installation &raquo;</strong></td>
+               <td class="row1" width="150" align="center">
+               <div id=''>
+                       <form action="install.php" method="post" name="form">
+                       <input type="hidden" name="new_version" value="<?php echo $new_version; ?>" />
+                       <input type="submit" class="button" value="  Install  " name="next" disabled="true" />
+                       </form>
+               </div>
+               </td>
+       </tr>
+       </table>
+       <table cellspacing="0" cellpadding="10" align="center" width="45%">
+       <tr>
+               <td align="center"><b>Or</b></td>
+       </tr>
+       </table>
+       <table cellspacing="0" class="tableborder" cellpadding="1" align="center" width="70%">
+       <tr>
+               <td class="row1"><strong>Upgrading from previous ATutor must have mbstring library installed.</strong></td>
+               <td class="row1"></td>
+       </tr>
+       <tr>
+               <td align="right" class="row1" nowrap="nowrap"><strong>Upgrade an Existing Installation &raquo;</strong></td>
+               <td class="row1" width="150" align="center">
+               <input type="button" class="button" value="Upgrade" name="next" disabled="true"/>
+               </form></td>
+       </tr>
+       </table>
+<?php else: ?>
+       <table cellspacing="0" class="tableborder" cellpadding="1" align="center" width="70%">
+       <tr>
+               <td align="right" class="row1" nowrap="nowrap"><strong>New Installation &raquo;</strong></td>
+               <td class="row1" width="150" align="center"><form action="install.php" method="post" name="form">
+               <input type="hidden" name="new_version" value="<?php echo $new_version; ?>" />
+               <input type="submit" class="button" value="  Install  " name="next" />
+               </form></td>
+       </tr>
+       </table>
+       <table cellspacing="0" cellpadding="10" align="center" width="45%">
+       <tr>
+               <td align="center"><b>Or</b></td>
+       </tr>
+       </table>
+       <table cellspacing="0" class="tableborder" cellpadding="1" align="center" width="70%">
+       <tr>
+               <td align="right" class="row1" nowrap="nowrap"><strong>Upgrade an Existing Installation &raquo;</strong></td>
+               <td class="row1" width="150" align="center"><form action="upgrade.php" method="post" name="form">
+               <input type="hidden" name="new_version" value="<?php echo $new_version; ?>" />
+               <input type="submit" class="button" value="Upgrade" name="next" />
+               </form></td>
+       </tr>
+       </table>
+<?php endif; ?>
+
+<?php require(AT_INCLUDE_PATH.'footer.php'); ?>
diff --git a/install/install.php b/install/install.php
new file mode 100644 (file)
index 0000000..23c4572
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', 'include/');
+require(AT_INCLUDE_PATH.'common.inc.php');
+
+if (!$new_version = $_POST['new_version']) {
+       $new_version = $_POST['step2']['new_version'];
+}
+
+$step = intval($_POST['step']);
+
+if ($step == 0) {
+       $step = 1;
+}
+
+if ($_POST['submit'] == 'I Disagree'){
+       Header ("Location: index.php");
+}
+
+require(AT_INCLUDE_PATH.'header.php');
+
+/* agree to terms of use */
+if ($step == 1) {
+       require(AT_INCLUDE_PATH.'step1.php');
+}
+
+/* db */
+if ($step == 2) {
+       require(AT_INCLUDE_PATH.'step2.php');
+}
+
+/* preferences */
+if ($step == 3) {      
+       require(AT_INCLUDE_PATH.'step3.php');
+}
+
+/* personal account + welcome course */
+//if ($step == 4) {    
+       //require(AT_INCLUDE_PATH.'step4.php');
+//}
+
+/* content directory */
+if ($step == 4) {
+       require(AT_INCLUDE_PATH.'step5.php');
+}
+
+/* directory permissions and generating the config.inc.php file */
+if ($step == 5) {      
+       require(AT_INCLUDE_PATH.'step6.php');
+}
+
+/* anonymous data collection */
+if ($step == 6) {      
+       require(AT_INCLUDE_PATH.'step7.php');
+}
+
+/* done! */
+if ($step == 7) {      
+       require(AT_INCLUDE_PATH.'step8.php');
+}
+
+require(AT_INCLUDE_PATH.'footer.php');
+?>
\ No newline at end of file
diff --git a/install/not_installed.php b/install/not_installed.php
new file mode 100644 (file)
index 0000000..68675eb
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', 'include/');
+error_reporting(E_ALL ^ E_NOTICE);
+
+require('../include/lib/constants.inc.php');
+
+$new_version = VERSION;
+
+header('Cache-Control: no-store, no-cache, must-revalidate');
+header('Pragma: no-cache');
+
+require(AT_INCLUDE_PATH.'header.php');
+?>
+
+
+<p>ATutor does not appear to be installed. <a href="index.php">Continue on to the installation</a>.</p>
+
+
+<?php require(AT_INCLUDE_PATH.'footer.php'); ?>
\ No newline at end of file
diff --git a/install/stylesheet.css b/install/stylesheet.css
new file mode 100644 (file)
index 0000000..d3ad882
--- /dev/null
@@ -0,0 +1,503 @@
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+/* $Id$ */
+
+/* main body attributes */
+body {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       color: black;
+       background-color: white;
+       background-image: url();
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-left: 0px;
+       margin-right: 0px;
+       font-size: small;
+}
+
+code {
+       font-size: x-small;
+       color: black;
+}
+
+kbd {
+  padding: 0px 1px 0px 1px;
+  border-width: 1px 2px 2px 1px;
+  border-style: solid;
+  background: #faf6f6;
+  color: #000;
+  border-color:  #edd #baa #baa #eed;
+  font-size: small;
+  white-space: nowrap;
+}
+
+/* paragraph attributes */
+p {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       color: black;
+       margin-bottom: 10px;
+       margin-top: 0px;
+       margin-left: 5px;
+       margin-right: 0px;
+       font-size: small;
+}
+
+p.heading {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       font-weight: bold;
+       font-size: 1em;
+       color: black;
+       margin-bottom: 10px;
+       margin-top: 0px;
+       margin-left: 5px;
+       margin-right: 0px;
+}
+
+p.error {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       font-weight: bold;
+       color: red;
+       margin-bottom: 10px;
+       margin-top: 0px;
+       margin-left: 5px;
+       margin-right: 0px;
+}
+
+h1#header {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       color: white;
+       float: left;
+       display: inline;
+       margin: 10px;
+}
+
+
+/* list attributes */
+ul {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       margin-bottom: 5px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+
+li {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+li.important{
+       color: red;
+}
+
+/* link attributes */
+a:link {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       color: #384F89;
+       border-bottom: 1px solid #384F89;
+       text-decoration: none;
+}
+a:visited {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       color: #51286C;
+}
+a:hover {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       color: black;
+}
+
+/* formfield attributes */
+.formfield {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       color: black;
+       border:  #003399  solid 1px;
+       padding: 2px;
+}
+
+.formfield:focus {
+       border:  #0033FF  solid 1px;
+}
+
+form {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-left: 0px;
+       margin-right: 0px;
+}
+
+/* main submit button */
+.button {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       background-color: #F8F8F8;
+       font-weight: bold;
+       border:  #354A81  solid 1px;
+}
+.button:hover, .button:focus {
+       cursor: pointer;
+       border:  #354AFF solid 1px;
+       color:  #0000FF;
+}
+
+/* small submit button at top */
+.button2 {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       background-color: #F8F8F8;
+       font-size: 0.7em;
+       border-top:  #354A81  solid 1px;
+       border-bottom: #354A81  solid 1px;
+       border-right: #354A81  solid 1px;
+       border-left: #354A81  solid 1px;
+}
+
+/* table border */
+.tableborder {
+       border-left: 1px #98AAB1 solid;
+       border-right: 1px #98AAB1 solid;
+       border-top: 1px #98AAB1 solid;
+}
+
+/* user menu at top */
+.topbar {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       background-image: url('images/cellpic1.gif');
+       background-repeat: repeat-x;
+       background-color: #D1D7DC;
+       text-align: center;
+       padding: 3px;
+}
+
+/* breadcrumbs */
+td.breadcrumbs {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       background-image: url('images/cellpic3.gif');
+       color: #FFFFFF;
+       background-color: #006699;
+       height: 26px;
+}
+.breadcrumbs { 
+       font-family: Verdana, Arial, Helvetica, sans-serif; 
+       color: white
+       text-decoration: none;  
+       letter-spacing: 1px; 
+}
+a.breadcrumbs { 
+       font-family: Verdana, Arial, Helvetica, sans-serif; 
+       color: #CCCCCC;
+       text-decoration: none;  
+}
+a.breadcrumbs:hover { 
+       font-family: Verdana, Arial, Helvetica, sans-serif; 
+       color: #CCCC00;
+       text-decoration: none; 
+}
+a.breadcrumbs:visited {
+       font-family: Verdana, Arial, Helvetica, sans-serif; 
+       color : #CCCCCC;
+       text-decoration: none; 
+}
+
+/* 
+td.rowpic {
+               background-color: #FFFFFF;
+               background-image: url('images/cellpic2.jpg');
+               background-repeat: repeat-y;
+}
+*/
+
+/* the menu */
+td.row1, table.row1 { 
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       font-weight: normal;
+       background-color: #EFEFEF;
+       vertical-align: top;    
+       padding: 8px;
+       border-bottom: 1px #98AAB1 solid;
+}
+
+/* menu titles*/
+td.cat, th {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       background-image: url('images/cellpic1.gif');
+       background-repeat: repeat-x;
+       background-color:#D1D7DC; 
+       height: 25px;
+       text-align: center;
+       font-weight: bold;
+       padding-top: 3px;
+       padding-left: 5px;
+       padding-right: 5px;
+       white-space: nowrap;
+}
+td.cat2 {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       background-image: url('images/cellpic1.gif');
+       background-repeat: repeat;
+       text-align: center;
+       font-weight: bold;
+       padding: 1px;
+       border: 1px #98AAB1 solid;
+}
+td.cat2b {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       background-image: url('images/cellpic1.gif');
+       background-repeat: repeat;
+       text-align: center;
+       font-weight: bold;
+       height: 27px;
+       padding: 1px;
+       border: 1px #98AAB1 solid;
+}
+td.cat2c {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       background-image: url('images/cellpic1.gif');
+       background-repeat: repeat;
+       text-align: center;
+       font-weight: bold;
+       height: 27px;
+       padding: 1px;
+       border: 1px #98AAB1 solid;
+}
+td.cat2d {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       background-image: url('images/cellpic1.gif');
+       background-repeat: repeat;
+       text-align: center;
+       font-weight: bold;
+       height: 27px;
+       padding: 1px;
+       border: 1px #98AAB1 solid;
+}
+td.cat2e {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       background-image: url('images/cellpic1.gif');
+       background-repeat: repeat;
+       text-align: center;
+       font-weight: bold;
+       height: 27px;
+       padding: 1px;
+       border: 1px #98AAB1 solid;
+}
+table.cat2 {
+font-family: Verdana, Arial, Helvetica, sans-serif;
+       background-image: url('images/cellpic1.gif');
+       background-repeat: repeat-x;
+       /*Remove this attribute, to fix Opera menu display problem*/
+       /*height: 27px;*/
+       text-align: center;
+       font-weight: bold;
+       border: 1px #98AAB1 solid;
+}
+table.cat3 {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       background-color: ;
+}
+
+/* various line breaks */
+td.row2 { 
+       background-color: #98AAB1; 
+       font-weight: normal;
+       height: 1px;
+}
+td.row3 {
+       background-color: #006699;
+       font-weight: normal;
+       height: 1px;
+}
+td.row4 {
+       background-color: #f3f3f2;
+       font-weight: normal;
+       height: 1px;
+}
+
+/* align text to the left */
+.left {
+       text-align: left;
+}
+
+/* pipe attribute  */
+.spacer {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       color: #006699;
+       font-size: 0.65em;
+}
+
+/* previous/next text attribute */
+.bigspacer {
+       color: #006699;
+}
+
+.bodyline { 
+       background-color: #FFFFFF; 
+       border: 1px #98AAB1 solid; 
+}
+/* date attributes */
+small.date {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       color: #006699; 
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-left: 5px;
+       margin-right: 0px;
+       font-size: 0.7em;
+}
+
+.menuimage {
+       vertical-align: middle;
+       margin-top: 0px;
+}
+
+/* page breakline */
+hr {
+       color: #98AAB1;
+       background-color: white;
+       height: 1px;
+}
+
+/* box around a forum reply */
+.block {
+       position: relative;
+       font-size: 0.9em;
+       background-color: #FFFFFF;
+       border: 1px dotted #98AAB1;
+       padding: 5px;
+       margin-right: 5px;
+       margin-left: 15px;
+       margin-bottom: 0px;
+}
+
+
+select.dropdown {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+    background-color: #F1F3F1;                            
+}                                                             
+  
+h1, h2, h3, h4, h5, h6 {
+       margin-top: 0px;
+       margin-bottom: 0px;
+       margin-left: 5px;
+}
+
+h3 {
+       border-bottom: 1px solid #354A81;
+}
+
+
+.content {
+       padding: 20px;
+       font-size: small;
+}
+
+/* error box */
+table.errbox{
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       background-color: #FF0000;
+       border: 2px #EEEEEE solid;
+}
+tr.errbox {
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       background-color: white;
+       vertical-align:top;
+       font-size: smaller;
+}
+h3.err {
+       color: red;
+       border: 0px;
+}
+
+h3.good {
+       color: green;
+       border: 0px;
+}
+
+
+ /* feedback box */
+table.fbkbox{
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       background-color: #30B626;
+       border: 2px #EEEEEE solid;
+}
+tr.fbkbox{
+       font-family: Verdana, Arial, Helvetica, sans-serif;
+       background-color: white;
+       vertical-align: top;
+       font-size: smaller;
+}
+img#logo {
+       padding: 10px;
+       background-color: #eeeeee;
+       border: 1px solid #cccccc;
+       margin: 10px;
+       float: right;
+}
+
+div.install {
+       border: 1px solid #354A81;
+}
+
+div.install h3 {
+       background-color: #354A81;
+       margin-left: 0px;
+       padding: 2px;
+       color: white;
+       border: 0px;
+}
+div.install p {
+       font-size: small;
+}
+div.suggested {
+       font-weight: bold;
+       color: blue;
+       border: 1px solid #e3e3e3;
+}
+
+/* for data tables */
+table.data {
+       border: 1px solid #f0f0f0;
+       width: 90%; 
+       margin-left: auto;
+       margin-right: auto;
+       border-spacing: 0px;
+       border-collapse: collapse;
+} 
+
+table.data th {
+       background-color: #fafafa;
+       border-bottom: 1px solid #f0f0f0;
+       padding: 2px;
+       white-space: nowrap;
+       border-top: 1px solid #f0f0f0;
+}
+
+table.data td {
+       padding: 3px;
+}
+
+div.required {
+       font-weight: bold;
+       color: red;
+       font-size: x-large;
+       float: left;
+       position: relative;
+       margin-top: -3px;
+       height: 15px;
+       padding-right: 0px;
+}
+div.optional {
+       font-weight: bold;
+       color: red;
+       font-size: large;
+       float: left;
+       position: relative;
+       margin-top: -3px;
+       height: 15px;
+       padding-right: 3px;
+}
\ No newline at end of file
diff --git a/install/update_config.php b/install/update_config.php
new file mode 100644 (file)
index 0000000..08066da
--- /dev/null
@@ -0,0 +1,58 @@
+<?php\r
+exit;\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('contact_email', '".EMAIL."')";\r
+mysql_query($sql, $db);\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('email_notification', '".(int) EMAIL_NOTIFY."')";\r
+mysql_query($sql, $db);\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('allow_instructor_requests', '".(int) ALLOW_INSTRUCTOR_REQUESTS."')";\r
+mysql_query($sql, $db);\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('auto_approve_instructors', '".(int) AUTO_APPROVE_INSTRUCTORS."')";\r
+mysql_query($sql, $db);\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('max_file_size', '".(int) $MaxFileSize."')";\r
+mysql_query($sql, $db);\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('max_course_size', '".(int) $MaxCourseSize."')";\r
+mysql_query($sql, $db);\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('max_course_float', '".(int) $MaxCourseFloat."')";\r
+mysql_query($sql, $db);\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('illegal_extentions', '".implode('|',$IllegalExtentions)."')";\r
+mysql_query($sql, $db);\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('site_name', '".SITE_NAME."')";\r
+mysql_query($sql, $db);\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('home_url', '".HOME_URL."')";\r
+mysql_query($sql, $db);\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('default_language', '".DEFAULT_LANGUAGE."')";\r
+mysql_query($sql, $db);\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('cache_dir', '".CACHE_DIR."')";\r
+mysql_query($sql, $db);\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('enable_category_themes', '".(int) AT_ENABLE_CATEGORY_THEMES."')";\r
+mysql_query($sql, $db);\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('course_backups', '".(int) AT_COURSE_BACKUPS."')";\r
+mysql_query($sql, $db);\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('email_confirmation', '".(int) AT_EMAIL_CONFIRMATION."')";\r
+mysql_query($sql, $db);\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('master_list', '".(int) AT_MASTER_LIST."')";\r
+mysql_query($sql, $db);\r
+\r
+$sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('enable_handbook_notes', '".(int) AT_ENABLE_HANDBOOK_NOTES."')";\r
+mysql_query($sql, $db);\r
+\r
+?>
\ No newline at end of file
diff --git a/install/upgrade.php b/install/upgrade.php
new file mode 100644 (file)
index 0000000..a55a0b5
--- /dev/null
@@ -0,0 +1,86 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+
+if (isset($_POST['new_version'])) {
+       $new_version = $_POST['new_version'];
+}
+
+if (isset($_POST['step'])) {
+       $step = intval($_POST['step']);
+}
+
+if (!isset($step) || ($step == 0)) {
+       $step = 1;
+}
+
+require('include/common.inc.php');
+
+if (($step == 2) && isset($_POST['override']) && ($_POST['override'] == 0)) {
+       header('Location: index.php');
+       exit;
+}
+session_start();
+require('include/upgrade_header.php');
+
+if ($step == 1) {
+       if (!$new_version) {
+               echo 'You cannot access this page directly. <a href="index.php">Upgrade from here</a> using the <em>Upgrade</em> button.';
+               require('include/footer.php');
+               exit;
+       }
+       // in:  select directory
+       // out: confirm verions
+       require('include/ustep1.php');
+}
+if ($step == 2) {
+       // in:  update database
+       // out: -
+       require('include/ustep2.php');
+}
+if ($step == 3) {
+       // in:  database info
+       // out: convert database from <encoding> to UTF-8
+       require('include/ustep7.php');
+}
+if ($step == 4) {
+       // in:  display version specific notices
+       // out: update database with new options
+       require('include/ustep3.php');
+}
+if ($step == 5) {
+       // in:  determine where the old content dir is and if it has to be copied
+       // out: try to create the directory and set permissions
+       require('include/step5.php');
+}
+if ($step == 6) {
+       // in:  copy the content if needed
+       // out: -
+       require('include/ustep4.php');
+}
+if ($step == 7) {
+       // in:  copy the config file
+       // out: -
+       require('include/ustep5.php');
+}
+/* anonymous data collection */
+if ($step == 8) {      
+       require('include/step7.php');
+}
+
+if ($step == 9) {
+       require('include/ustep6.php');
+}
+require('include/footer.php');
+?>
\ No newline at end of file
diff --git a/jscripts/Fluid-all.js b/jscripts/Fluid-all.js
new file mode 100644 (file)
index 0000000..0111f88
--- /dev/null
@@ -0,0 +1 @@
+(function(){if(window.jQuery){var _jQuery=window.jQuery}var jQuery=window.jQuery=function(selector,context){return new jQuery.prototype.init(selector,context)};if(window.$){var _$=window.$}window.$=jQuery;var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;var isSimple=/^.[^:#\[\.]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this}else{if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1]){selector=jQuery.clean([match[1]],context)}else{var elem=document.getElementById(match[3]);if(elem){if(elem.id!=match[3]){return jQuery().find(selector)}else{this[0]=elem;this.length=1;return this}}else{selector=[]}}}else{return new jQuery(context).find(selector)}}else{if(jQuery.isFunction(selector)){return new jQuery(document)[jQuery.fn.ready?"ready":"load"](selector)}}}return this.setArray(selector.constructor==Array&&selector||(selector.jquery||selector.length&&selector!=window&&!selector.nodeType&&selector[0]!=undefined&&selector[0].nodeType)&&jQuery.makeArray(selector)||[selector])},jquery:"1.2.3",size:function(){return this.length},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num]},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this},each:function(callback,args){return jQuery.each(this,callback,args)},index:function(elem){var ret=-1;this.each(function(i){if(this==elem){ret=i}});return ret},attr:function(name,value,type){var options=name;if(name.constructor==String){if(value==undefined){return this.length&&jQuery[type||"attr"](this[0],name)||undefined}else{options={};options[name]=value}}return this.each(function(i){for(name in options){jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name))}})},css:function(key,value){if((key=="width"||key=="height")&&parseFloat(value)<0){value=undefined}return this.attr(key,value,"curCSS")},text:function(text){if(typeof text!="object"&&text!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text))}var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8){ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this])}})});return ret},wrapAll:function(html){if(this[0]){jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild){elem=elem.firstChild}return elem}).append(this)}return this},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html)})},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html)})},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1){this.appendChild(elem)}})},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1){this.insertBefore(elem,this.firstChild)}})},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this)})},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling)})},end:function(){return this.prevObject||jQuery([])},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem)});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems)},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0]}else{return this.cloneNode(true)}});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined){this[expando]=null}});if(events===true){this.find("*").andSelf().each(function(i){if(this.nodeType==3){return }var events=jQuery.data(this,"events");for(var type in events){for(var handler in events[type]){jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data)}}})}return ret},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i)})||jQuery.multiFilter(selector,this))},not:function(selector){if(selector.constructor==String){if(isSimple.test(selector)){return this.pushStack(jQuery.multiFilter(selector,this,true))}else{selector=jQuery.multiFilter(selector,this)}}var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector})},add:function(selector){return !selector?this:this.pushStack(jQuery.merge(this.get(),selector.constructor==String?jQuery(selector).get():selector.length!=undefined&&(!selector.nodeName||jQuery.nodeName(selector,"form"))?selector:[selector]))},is:function(selector){return selector?jQuery.multiFilter(selector,this).length>0:false},hasClass:function(selector){return this.is("."+selector)},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0){return null}for(var i=one?index:0,max=one?index+1:options.length;i<max;i++){var option=options[i];if(option.selected){value=jQuery.browser.msie&&!option.attributes.value.specified?option.text:option.value;if(one){return value}values.push(value)}}return values}else{return(this[0].value||"").replace(/\r/g,"")}}return undefined}return this.each(function(){if(this.nodeType!=1){return }if(value.constructor==Array&&/radio|checkbox/.test(this.type)){this.checked=(jQuery.inArray(this.value,value)>=0||jQuery.inArray(this.name,value)>=0)}else{if(jQuery.nodeName(this,"select")){var values=value.constructor==Array?value:[value];jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0)});if(!values.length){this.selectedIndex=-1}}else{this.value=value}}})},html:function(value){return value==undefined?(this.length?this[0].innerHTML:null):this.empty().append(value)},replaceWith:function(value){return this.after(value).remove()},eq:function(i){return this.slice(i,i+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments))},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem)}))},andSelf:function(){return this.add(this.prevObject)},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value==null){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data==undefined&&this.length){data=jQuery.data(this[0],key)}return data==null&&parts[1]?this.data(parts[0]):data}else{return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value)})}},removeData:function(key){return this.each(function(){jQuery.removeData(this,key)})},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse){elems.reverse()}}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr")){obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"))}var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script")){scripts=scripts.add(elem)}else{if(elem.nodeType==1){scripts=scripts.add(jQuery("script",elem).remove())}callback.call(obj,elem)}});scripts.each(evalScript)})}};jQuery.prototype.init.prototype=jQuery.prototype;function evalScript(i,elem){if(elem.src){jQuery.ajax({url:elem.src,async:false,dataType:"script"})}else{jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"")}if(elem.parentNode){elem.parentNode.removeChild(elem)}}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2}if(typeof target!="object"&&typeof target!="function"){target={}}if(length==1){target=this;i=0}for(;i<length;i++){if((options=arguments[i])!=null){for(var name in options){if(target===options[name]){continue}if(deep&&options[name]&&typeof options[name]=="object"&&target[name]&&!options[name].nodeType){target[name]=jQuery.extend(target[name],options[name])}else{if(options[name]!=undefined){target[name]=options[name]}}}}}return target};var expando="jQuery"+(new Date()).getTime(),uuid=0,windowData={};var exclude=/z-?index|font-?weight|opacity|zoom|line-?height/i;jQuery.extend({noConflict:function(deep){window.$=_$;if(deep){window.jQuery=_jQuery}return jQuery},isFunction:function(fn){return !!fn&&typeof fn!="string"&&!fn.nodeName&&fn.constructor!=Array&&/function/i.test(fn+"")},isXMLDoc:function(elem){return elem.documentElement&&!elem.body||elem.tagName&&elem.ownerDocument&&!elem.ownerDocument.body},globalEval:function(data){data=jQuery.trim(data);if(data){var head=document.getElementsByTagName("head")[0]||document.documentElement,script=document.createElement("script");script.type="text/javascript";if(jQuery.browser.msie){script.text=data}else{script.appendChild(document.createTextNode(data))}head.appendChild(script);head.removeChild(script)}},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toUpperCase()==name.toUpperCase()},cache:{},data:function(elem,name,data){elem=elem==window?windowData:elem;var id=elem[expando];if(!id){id=elem[expando]=++uuid}if(name&&!jQuery.cache[id]){jQuery.cache[id]={}}if(data!=undefined){jQuery.cache[id][name]=data}return name?jQuery.cache[id][name]:id},removeData:function(elem,name){elem=elem==window?windowData:elem;var id=elem[expando];if(name){if(jQuery.cache[id]){delete jQuery.cache[id][name];name="";for(name in jQuery.cache[id]){break}if(!name){jQuery.removeData(elem)}}}else{try{delete elem[expando]}catch(e){if(elem.removeAttribute){elem.removeAttribute(expando)}}delete jQuery.cache[id]}},each:function(object,callback,args){if(args){if(object.length==undefined){for(var name in object){if(callback.apply(object[name],args)===false){break}}}else{for(var i=0,length=object.length;i<length;i++){if(callback.apply(object[i],args)===false){break}}}}else{if(object.length==undefined){for(var name in object){if(callback.call(object[name],name,object[name])===false){break}}}else{for(var i=0,length=object.length,value=object[0];i<length&&callback.call(value,i,value)!==false;value=object[++i]){}}}return object},prop:function(elem,value,type,i,name){if(jQuery.isFunction(value)){value=value.call(elem,i)}return value&&value.constructor==Number&&type=="curCSS"&&!exclude.test(name)?value+"px":value},className:{add:function(elem,classNames){jQuery.each((classNames||"").split(/\s+/),function(i,className){if(elem.nodeType==1&&!jQuery.className.has(elem.className,className)){elem.className+=(elem.className?" ":"")+className}})},remove:function(elem,classNames){if(elem.nodeType==1){elem.className=classNames!=undefined?jQuery.grep(elem.className.split(/\s+/),function(className){return !jQuery.className.has(classNames,className)}).join(" "):""}},has:function(elem,className){return jQuery.inArray(className,(elem.className||elem).toString().split(/\s+/))>-1}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name]}callback.call(elem);for(var name in options){elem.style[name]=old[name]}},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0});val-=Math.round(padding+border)}if(jQuery(elem).is(":visible")){getWH()}else{jQuery.swap(elem,props,getWH)}return Math.max(0,val)}return jQuery.curCSS(elem,name,force)},curCSS:function(elem,name,force){var ret;function color(elem){if(!jQuery.browser.safari){return false}var ret=document.defaultView.getComputedStyle(elem,null);return !ret||ret.getPropertyValue("color")==""}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(elem.style,"opacity");return ret==""?"1":ret}if(jQuery.browser.opera&&name=="display"){var save=elem.style.outline;elem.style.outline="0 solid black";elem.style.outline=save}if(name.match(/float/i)){name=styleFloat}if(!force&&elem.style&&elem.style[name]){ret=elem.style[name]}else{if(document.defaultView&&document.defaultView.getComputedStyle){if(name.match(/float/i)){name="float"}name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var getComputedStyle=document.defaultView.getComputedStyle(elem,null);if(getComputedStyle&&!color(elem)){ret=getComputedStyle.getPropertyValue(name)}else{var swap=[],stack=[];for(var a=elem;a&&color(a);a=a.parentNode){stack.unshift(a)}for(var i=0;i<stack.length;i++){if(color(stack[i])){swap[i]=stack[i].style.display;stack[i].style.display="block"}}ret=name=="display"&&swap[stack.length-1]!=null?"none":(getComputedStyle&&getComputedStyle.getPropertyValue(name))||"";for(var i=0;i<swap.length;i++){if(swap[i]!=null){stack[i].style.display=swap[i]}}}if(name=="opacity"&&ret==""){ret="1"}}else{if(elem.currentStyle){var camelCase=name.replace(/\-(\w)/g,function(all,letter){return letter.toUpperCase()});ret=elem.currentStyle[name]||elem.currentStyle[camelCase];if(!/^\d+(px)?$/i.test(ret)&&/^\d/.test(ret)){var style=elem.style.left,runtimeStyle=elem.runtimeStyle.left;elem.runtimeStyle.left=elem.currentStyle.left;elem.style.left=ret||0;ret=elem.style.pixelLeft+"px";elem.style.left=style;elem.runtimeStyle.left=runtimeStyle}}}}return ret},clean:function(elems,context){var ret=[];context=context||document;if(typeof context.createElement=="undefined"){context=context.ownerDocument||context[0]&&context[0].ownerDocument||document}jQuery.each(elems,function(i,elem){if(!elem){return }if(elem.constructor==Number){elem=elem.toString()}if(typeof elem=="string"){elem=elem.replace(/(<(\w+)[^>]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+"></"+tag+">"});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!tags.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!tags.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!tags.indexOf("<td")||!tags.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!tags.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||jQuery.browser.msie&&[1,"div<div>","</div>"]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--){div=div.lastChild}if(jQuery.browser.msie){var tbody=!tags.indexOf("<table")&&tags.indexOf("<tbody")<0?div.firstChild&&div.firstChild.childNodes:wrap[1]=="<table>"&&tags.indexOf("<tbody")<0?div.childNodes:[];for(var j=tbody.length-1;j>=0;--j){if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length){tbody[j].parentNode.removeChild(tbody[j])}}if(/^\s/.test(elem)){div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild)}}elem=jQuery.makeArray(div.childNodes)}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select"))){return }if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options){ret.push(elem)}else{ret=jQuery.merge(ret,elem)}});return ret},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8){return undefined}var fix=jQuery.isXMLDoc(elem)?{}:jQuery.props;if(name=="selected"&&jQuery.browser.safari){elem.parentNode.selectedIndex}if(fix[name]){if(value!=undefined){elem[fix[name]]=value}return elem[fix[name]]}else{if(jQuery.browser.msie&&name=="style"){return jQuery.attr(elem.style,"cssText",value)}else{if(value==undefined&&jQuery.browser.msie&&jQuery.nodeName(elem,"form")&&(name=="action"||name=="method")){return elem.getAttributeNode(name).nodeValue}else{if(elem.tagName){if(value!=undefined){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode){throw"type property can't be changed"}elem.setAttribute(name,""+value)}if(jQuery.browser.msie&&/href|src/.test(name)&&!jQuery.isXMLDoc(elem)){return elem.getAttribute(name,2)}return elem.getAttribute(name)}else{if(name=="opacity"&&jQuery.browser.msie){if(value!=undefined){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseFloat(value).toString()=="NaN"?"":"alpha(opacity="+value*100+")")}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100).toString():""}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase()});if(value!=undefined){elem[name]=value}return elem[name]}}}}},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"")},makeArray:function(array){var ret=[];if(typeof array!="array"){for(var i=0,length=array.length;i<length;i++){ret.push(array[i])}}else{ret=array.slice(0)}return ret},inArray:function(elem,array){for(var i=0,length=array.length;i<length;i++){if(array[i]==elem){return i}}return -1},merge:function(first,second){if(jQuery.browser.msie){for(var i=0;second[i];i++){if(second[i].nodeType!=8){first.push(second[i])}}}else{for(var i=0;second[i];i++){first.push(second[i])}}return first},unique:function(array){var ret=[],done={};try{for(var i=0,length=array.length;i<length;i++){var id=jQuery.data(array[i]);if(!done[id]){done[id]=true;ret.push(array[i])}}}catch(e){ret=array}return ret},grep:function(elems,callback,inv){var ret=[];for(var i=0,length=elems.length;i<length;i++){if(!inv&&callback(elems[i],i)||inv&&!callback(elems[i],i)){ret.push(elems[i])}}return ret},map:function(elems,callback){var ret=[];for(var i=0,length=elems.length;i<length;i++){var value=callback(elems[i],i);if(value!==null&&value!=undefined){if(value.constructor!=Array){value=[value]}ret=ret.concat(value)}}return ret}});var userAgent=navigator.userAgent.toLowerCase();jQuery.browser={version:(userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1],safari:/webkit/.test(userAgent),opera:/opera/.test(userAgent),msie:/msie/.test(userAgent)&&!/opera/.test(userAgent),mozilla:/mozilla/.test(userAgent)&&!/(compatible|webkit)/.test(userAgent)};var styleFloat=jQuery.browser.msie?"styleFloat":"cssFloat";jQuery.extend({boxModel:!jQuery.browser.msie||document.compatMode=="CSS1Compat",props:{"for":"htmlFor","class":"className","float":styleFloat,cssFloat:styleFloat,styleFloat:styleFloat,innerHTML:"innerHTML",className:"className",value:"value",disabled:"disabled",checked:"checked",readonly:"readOnly",selected:"selected",maxlength:"maxLength",selectedIndex:"selectedIndex",defaultValue:"defaultValue",tagName:"tagName",nodeName:"nodeName"}});jQuery.each({parent:function(elem){return elem.parentNode},parents:function(elem){return jQuery.dir(elem,"parentNode")},next:function(elem){return jQuery.nth(elem,2,"nextSibling")},prev:function(elem){return jQuery.nth(elem,2,"previousSibling")},nextAll:function(elem){return jQuery.dir(elem,"nextSibling")},prevAll:function(elem){return jQuery.dir(elem,"previousSibling")},siblings:function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem)},children:function(elem){return jQuery.sibling(elem.firstChild)},contents:function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes)}},function(name,fn){jQuery.fn[name]=function(selector){var ret=jQuery.map(this,fn);if(selector&&typeof selector=="string"){ret=jQuery.multiFilter(selector,ret)}return this.pushStack(jQuery.unique(ret))}});jQuery.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(name,original){jQuery.fn[name]=function(){var args=arguments;return this.each(function(){for(var i=0,length=args.length;i<length;i++){jQuery(args[i])[original](this)}})}});jQuery.each({removeAttr:function(name){jQuery.attr(this,name,"");if(this.nodeType==1){this.removeAttribute(name)}},addClass:function(classNames){jQuery.className.add(this,classNames)},removeClass:function(classNames){jQuery.className.remove(this,classNames)},toggleClass:function(classNames){jQuery.className[jQuery.className.has(this,classNames)?"remove":"add"](this,classNames)},remove:function(selector){if(!selector||jQuery.filter(selector,[this]).r.length){jQuery("*",this).add(this).each(function(){jQuery.event.remove(this);jQuery.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){jQuery(">*",this).remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments)}});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px")}});var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2])},"#":function(a,i,m){return a.getAttribute("id")==m[2]},":":{lt:function(a,i,m){return i<m[3]-0},gt:function(a,i,m){return i>m[3]-0},nth:function(a,i,m){return m[3]-0==i},eq:function(a,i,m){return m[3]-0==i},first:function(a,i){return i==0},last:function(a,i,m,r){return i==r.length-1},even:function(a,i){return i%2==0},odd:function(a,i){return i%2},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a},"only-child":function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling")},parent:function(a){return a.firstChild},empty:function(a){return !a.firstChild},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden"},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden"},enabled:function(a){return !a.disabled},disabled:function(a){return a.disabled},checked:function(a){return a.checked},selected:function(a){return a.selected||jQuery.attr(a,"selected")},text:function(a){return"text"==a.type},radio:function(a){return"radio"==a.type},checkbox:function(a){return"checkbox"==a.type},file:function(a){return"file"==a.type},password:function(a){return"password"==a.type},submit:function(a){return"submit"==a.type},image:function(a){return"image"==a.type},reset:function(a){return"reset"==a.type},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button")},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},has:function(a,i,m){return jQuery.find(m[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem}).length}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r)}return cur},find:function(t,context){if(typeof t!="string"){return[t]}if(context&&context.nodeType!=1&&context.nodeType!=9){return[]}context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false;var re=quickChild;var m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++){for(var c=ret[i].firstChild;c;c=c.nextSibling){if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName)){r.push(c)}}}ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0){continue}foundToken=true}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j<rl;j++){var n=m=="~"||m=="+"?ret[j].nextSibling:ret[j].firstChild;for(;n;n=n.nextSibling){if(n.nodeType==1){var id=jQuery.data(n);if(m=="~"&&merge[id]){break}if(!nodeName||n.nodeName.toUpperCase()==nodeName){if(m=="~"){merge[id]=true}r.push(n)}if(m=="+"){break}}}}ret=r;t=jQuery.trim(t.replace(re,""));foundToken=true}}if(t&&!foundToken){if(!t.indexOf(",")){if(context==ret[0]){ret.shift()}done=jQuery.merge(done,ret);r=ret=[context];t=" "+t.substr(1,t.length)}else{var re2=quickID;var m=re2.exec(t);if(m){m=[0,m[2],m[3],m[1]]}else{re2=quickClass;m=re2.exec(t)}m[2]=m[2].replace(/\\/g,"");var elem=ret[ret.length-1];if(m[1]=="#"&&elem&&elem.getElementById&&!jQuery.isXMLDoc(elem)){var oid=elem.getElementById(m[2]);if((jQuery.browser.msie||jQuery.browser.opera)&&oid&&typeof oid.id=="string"&&oid.id!=m[2]){oid=jQuery('[@id="'+m[2]+'"]',elem)[0]}ret=r=oid&&(!m[3]||jQuery.nodeName(oid,m[3]))?[oid]:[]}else{for(var i=0;ret[i];i++){var tag=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];if(tag=="*"&&ret[i].nodeName.toLowerCase()=="object"){tag="param"}r=jQuery.merge(r,ret[i].getElementsByTagName(tag))}if(m[1]=="."){r=jQuery.classFilter(r,m[2])}if(m[1]=="#"){var tmp=[];for(var i=0;r[i];i++){if(r[i].getAttribute("id")==m[2]){tmp=[r[i]];break}}r=tmp}ret=r}t=t.replace(re2,"")}}if(t){var val=jQuery.filter(t,r);ret=r=val.r;t=jQuery.trim(val.t)}}if(t){ret=[]}if(ret&&context==ret[0]){ret.shift()}done=jQuery.merge(done,ret);return done},classFilter:function(r,m,not){m=" "+m+" ";var tmp=[];for(var i=0;r[i];i++){var pass=(" "+r[i].className+" ").indexOf(m)>=0;if(!not&&pass||not&&!pass){tmp.push(r[i])}}return tmp},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break}}if(!m){break}if(m[1]==":"&&m[2]=="not"){r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3])}else{if(m[1]=="."){r=jQuery.classFilter(r,m[2],not)}else{if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i<rl;i++){var a=r[i],z=a[jQuery.props[m[2]]||m[2]];if(z==null||/href|src|selected/.test(m[2])){z=jQuery.attr(a,m[2])||""}if((type==""&&!!z||type=="="&&z==m[5]||type=="!="&&z!=m[5]||type=="^="&&z&&!z.indexOf(m[5])||type=="$="&&z.substr(z.length-m[5].length)==m[5]||(type=="*="||type=="~=")&&z.indexOf(m[5])>=0)^not){tmp.push(a)}}r=tmp}else{if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i<rl;i++){var node=r[i],parentNode=node.parentNode,id=jQuery.data(parentNode);if(!merge[id]){var c=1;for(var n=parentNode.firstChild;n;n=n.nextSibling){if(n.nodeType==1){n.nodeIndex=c++}}merge[id]=true}var add=false;if(first==0){if(node.nodeIndex==last){add=true}}else{if((node.nodeIndex-last)%first==0&&(node.nodeIndex-last)/first>=0){add=true}}if(add^not){tmp.push(node)}}r=tmp}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object"){fn=fn[m[2]]}if(typeof fn=="string"){fn=eval("false||function(a,i){return "+fn+";}")}r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r)},not)}}}}}return{r:r,t:t}},dir:function(elem,dir){var matched=[];var cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1){matched.push(cur)}cur=cur[dir]}return matched},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir]){if(cur.nodeType==1&&++num==result){break}}return cur},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&(!elem||n!=elem)){r.push(n)}}return r}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8){return }if(jQuery.browser.msie&&elem.setInterval!=undefined){elem=window}if(!handler.guid){handler.guid=this.guid++}if(data!=undefined){var fn=handler;handler=function(){return fn.apply(this,arguments)};handler.data=data;handler.guid=fn.guid}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){var val;if(typeof jQuery=="undefined"||jQuery.event.triggered){return val}val=jQuery.event.handle.apply(arguments.callee.elem,arguments);return val});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener){elem.addEventListener(type,handle,false)}else{if(elem.attachEvent){elem.attachEvent("on"+type,handle)}}}}handlers[handler.guid]=handler;jQuery.event.global[type]=true});elem=null},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8){return }var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)==".")){for(var type in events){this.remove(elem,type+(types||""))}}else{if(types.type){handler=types.handler;types=types.type}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler){delete events[type][handler.guid]}else{for(handler in events[type]){if(!parts[1]||events[type][handler].type==parts[1]){delete events[type][handler]}}}for(ret in events[type]){break}if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener){elem.removeEventListener(type,jQuery.data(elem,"handle"),false)}else{if(elem.detachEvent){elem.detachEvent("on"+type,jQuery.data(elem,"handle"))}}}ret=null;delete events[type]}}})}for(ret in events){break}if(!ret){var handle=jQuery.data(elem,"handle");if(handle){handle.elem=null}jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle")}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data||[]);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true}if(!elem){if(this.global[type]){jQuery("*").add([window,document]).trigger(type,data)}}else{if(elem.nodeType==3||elem.nodeType==8){return undefined}var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event){data.unshift(this.fix({type:type,target:elem}))}data[0].type=type;if(exclusive){data[0].exclusive=true}if(jQuery.isFunction(jQuery.data(elem,"handle"))){val=jQuery.data(elem,"handle").apply(elem,data)}if(!fn&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false){val=false}if(event){data.shift()}if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined){val=ret}}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,"a")&&type=="click")){this.triggered=true;try{elem[type]()}catch(e){}}this.triggered=false}return val},handle:function(event){var val;event=jQuery.event.fix(event||window.event||{});var parts=event.type.split(".");event.type=parts[0];var handlers=jQuery.data(this,"events")&&jQuery.data(this,"events")[event.type],args=Array.prototype.slice.call(arguments,1);args.unshift(event);for(var j in handlers){var handler=handlers[j];args[0].handler=handler;args[0].data=handler.data;if(!parts[1]&&!event.exclusive||handler.type==parts[1]){var ret=handler.apply(this,args);if(val!==false){val=ret}if(ret===false){event.preventDefault();event.stopPropagation()}}}if(jQuery.browser.msie){event.target=event.preventDefault=event.stopPropagation=event.handler=event.data=null}return val},fix:function(event){var originalEvent=event;event=jQuery.extend({},originalEvent);event.preventDefault=function(){if(originalEvent.preventDefault){originalEvent.preventDefault()}originalEvent.returnValue=false};event.stopPropagation=function(){if(originalEvent.stopPropagation){originalEvent.stopPropagation()}originalEvent.cancelBubble=true};if(!event.target){event.target=event.srcElement||document}if(event.target.nodeType==3){event.target=originalEvent.target.parentNode}if(!event.relatedTarget&&event.fromElement){event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement}if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0)}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode)){event.which=event.charCode||event.keyCode}if(!event.metaKey&&event.ctrlKey){event.metaKey=event.ctrlKey}if(!event.which&&event.button){event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)))}return event},special:{ready:{setup:function(){bindReady();return },teardown:function(){return }},mouseenter:{setup:function(){if(jQuery.browser.msie){return false}jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true},teardown:function(){if(jQuery.browser.msie){return false}jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true},handler:function(event){if(withinElement(event,this)){return true}arguments[0].type="mouseenter";return jQuery.event.handle.apply(this,arguments)}},mouseleave:{setup:function(){if(jQuery.browser.msie){return false}jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true},teardown:function(){if(jQuery.browser.msie){return false}jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true},handler:function(event){if(withinElement(event,this)){return true}arguments[0].type="mouseleave";return jQuery.event.handle.apply(this,arguments)}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data)})},one:function(type,data,fn){return this.each(function(){jQuery.event.add(this,type,function(event){jQuery(this).unbind(event);return(fn||data).apply(this,arguments)},fn&&data)})},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn)})},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn)})},triggerHandler:function(type,data,fn){if(this[0]){return jQuery.event.trigger(type,data,this[0],false,fn)}return undefined},toggle:function(){var args=arguments;return this.click(function(event){this.lastToggle=0==this.lastToggle?1:0;event.preventDefault();return args[this.lastToggle].apply(this,arguments)||false})},hover:function(fnOver,fnOut){return this.bind("mouseenter",fnOver).bind("mouseleave",fnOut)},ready:function(fn){bindReady();if(jQuery.isReady){fn.call(document,jQuery)}else{jQuery.readyList.push(function(){return fn.call(this,jQuery)})}return this}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.apply(document)});jQuery.readyList=null}jQuery(document).triggerHandler("ready")}}});var readyBound=false;function bindReady(){if(readyBound){return }readyBound=true;if(document.addEventListener&&!jQuery.browser.opera){document.addEventListener("DOMContentLoaded",jQuery.ready,false)}if(jQuery.browser.msie&&window==top){(function(){if(jQuery.isReady){return }try{document.documentElement.doScroll("left")}catch(error){setTimeout(arguments.callee,0);return }jQuery.ready()})()}if(jQuery.browser.opera){document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady){return }for(var i=0;i<document.styleSheets.length;i++){if(document.styleSheets[i].disabled){setTimeout(arguments.callee,0);return }}jQuery.ready()},false)}if(jQuery.browser.safari){var numStyles;(function(){if(jQuery.isReady){return }if(document.readyState!="loaded"&&document.readyState!="complete"){setTimeout(arguments.callee,0);return }if(numStyles===undefined){numStyles=jQuery("style, link[rel=stylesheet]").length}if(document.styleSheets.length!=numStyles){setTimeout(arguments.callee,0);return }jQuery.ready()})()}jQuery.event.add(window,"load",jQuery.ready)}jQuery.each(("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,change,select,submit,keydown,keypress,keyup,error").split(","),function(i,name){jQuery.fn[name]=function(fn){return fn?this.bind(name,fn):this.trigger(name)}});var withinElement=function(event,elem){var parent=event.relatedTarget;while(parent&&parent!=elem){try{parent=parent.parentNode}catch(error){parent=elem}}return parent==elem};jQuery(window).bind("unload",function(){jQuery("*").add(document).unbind()});jQuery.fn.extend({load:function(url,params,callback){if(jQuery.isFunction(url)){return this.bind("load",url)}var off=url.indexOf(" ");if(off>=0){var selector=url.slice(off,url.length);url=url.slice(0,off)}callback=callback||function(){};var type="GET";if(params){if(jQuery.isFunction(params)){callback=params;params=null}else{params=jQuery.param(params);type="POST"}}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified"){self.html(selector?jQuery("<div/>").append(res.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(selector):res.responseText)}self.each(callback,[res.responseText,status,res])}});return this},serialize:function(){return jQuery.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type))}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val}}):{name:elem.name,value:val}}).get()}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f)}});var jsc=(new Date).getTime();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type})},getScript:function(url,callback){return jQuery.get(url,null,callback,"script")},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json")},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={}}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type})},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings)},ajaxSettings:{global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){var jsonp,jsre=/=\?(&|$)/g,status,data;s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));if(s.data&&s.processData&&typeof s.data!="string"){s.data=jQuery.param(s.data)}if(s.dataType=="jsonp"){if(s.type.toLowerCase()=="get"){if(!s.url.match(jsre)){s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?"}}else{if(!s.data||!s.data.match(jsre)){s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?"}}s.dataType="json"}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data){s.data=(s.data+"").replace(jsre,"="+jsonp+"$1")}s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp]}catch(e){}if(head){head.removeChild(script)}}}if(s.dataType=="script"&&s.cache==null){s.cache=false}if(s.cache===false&&s.type.toLowerCase()=="get"){var ts=(new Date()).getTime();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"")}if(s.data&&s.type.toLowerCase()=="get"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null}if(s.global&&!jQuery.active++){jQuery.event.trigger("ajaxStart")}if((!s.url.indexOf("http")||!s.url.indexOf("//"))&&s.dataType=="script"&&s.type.toLowerCase()=="get"){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset){script.charset=s.scriptCharset}if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script)}}}head.appendChild(script);return undefined}var requestDone=false;var xml=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();xml.open(s.type,s.url,s.async,s.username,s.password);try{if(s.data){xml.setRequestHeader("Content-Type",s.contentType)}if(s.ifModified){xml.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}xml.setRequestHeader("X-Requested-With","XMLHttpRequest");xml.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default)}catch(e){}if(s.beforeSend){s.beforeSend(xml)}if(s.global){jQuery.event.trigger("ajaxSend",[xml,s])}var onreadystatechange=function(isTimeout){if(!requestDone&&xml&&(xml.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xml)&&"error"||s.ifModified&&jQuery.httpNotModified(xml,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xml,s.dataType)}catch(e){status="parsererror"}}if(status=="success"){var modRes;try{modRes=xml.getResponseHeader("Last-Modified")}catch(e){}if(s.ifModified&&modRes){jQuery.lastModified[s.url]=modRes}if(!jsonp){success()}}else{jQuery.handleError(s,xml,status)}complete();if(s.async){xml=null}}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0){setTimeout(function(){if(xml){xml.abort();if(!requestDone){onreadystatechange("timeout")}}},s.timeout)}}try{xml.send(s.data)}catch(e){jQuery.handleError(s,xml,null,e)}if(!s.async){onreadystatechange()}function success(){if(s.success){s.success(data,status)}if(s.global){jQuery.event.trigger("ajaxSuccess",[xml,s])}}function complete(){if(s.complete){s.complete(xml,status)}if(s.global){jQuery.event.trigger("ajaxComplete",[xml,s])}if(s.global&&!--jQuery.active){jQuery.event.trigger("ajaxStop")}}return xml},handleError:function(s,xml,status,e){if(s.error){s.error(xml,status,e)}if(s.global){jQuery.event.trigger("ajaxError",[xml,s,e])}},active:0,httpSuccess:function(r){try{return !r.status&&location.protocol=="file:"||(r.status>=200&&r.status<300)||r.status==304||r.status==1223||jQuery.browser.safari&&r.status==undefined}catch(e){}return false},httpNotModified:function(xml,url){try{var xmlRes=xml.getResponseHeader("Last-Modified");return xml.status==304||xmlRes==jQuery.lastModified[url]||jQuery.browser.safari&&xml.status==undefined}catch(e){}return false},httpData:function(r,type){var ct=r.getResponseHeader("content-type");var xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0;var data=xml?r.responseXML:r.responseText;if(xml&&data.documentElement.tagName=="parsererror"){throw"parsererror"}if(type=="script"){jQuery.globalEval(data)}if(type=="json"){data=eval("("+data+")")}return data},param:function(a){var s=[];if(a.constructor==Array||a.jquery){jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value))})}else{for(var j in a){if(a[j]&&a[j].constructor==Array){jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this))})}else{s.push(encodeURIComponent(j)+"="+encodeURIComponent(a[j]))}}}return s.join("&").replace(/%20/g,"+")}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none"){this.style.display="block"}elem.remove()}}).end()},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none"}).end()},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle(fn,fn2):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]()})},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback)},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback)},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback)},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback)},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback)},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback)},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1){return false}var opt=jQuery.extend({},optall);var hidden=jQuery(this).is(":hidden"),self=this;for(var p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden){return jQuery.isFunction(opt.complete)&&opt.complete.apply(this)}if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow}}if(opt.overflow!=null){this.style.overflow="hidden"}opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val)){e[val=="toggle"?hidden?"show":"hide":val](prop)}else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit}if(parts[1]){end=((parts[1]=="-="?-1:1)*end)+start}e.custom(start,end,unit)}else{e.custom(start,val,"")}}});return true})},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx"}if(!type||(typeof type=="string"&&!fn)){return queue(this[0],type)}return this.each(function(){if(fn.constructor==Array){queue(this,type,fn)}else{queue(this,type).push(fn);if(queue(this,type).length==1){fn.apply(this)}}})},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue){this.queue([])}this.each(function(){for(var i=timers.length-1;i>=0;i--){if(timers[i].elem==this){if(gotoEnd){timers[i](true)}timers.splice(i,1)}}});if(!gotoEnd){this.dequeue()}return this}});var queue=function(elem,type,array){if(!elem){return undefined}type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array){q=jQuery.data(elem,type+"queue",array?jQuery.makeArray(array):[])}return q};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length){q[0].apply(this)}})};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:{slow:600,fast:200}[opt.duration])||400;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false){jQuery(this).dequeue()}if(jQuery.isFunction(opt.old)){opt.old.apply(this)}};return opt},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig){options.orig={}}}});jQuery.fx.prototype={update:function(){if(this.options.step){this.options.step.apply(this.elem,[this.now,this])}(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width"){this.elem.style.display="block"}},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null){return this.elem[this.prop]}var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0},custom:function(from,to,unit){this.startTime=(new Date()).getTime();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd)}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;i<timers.length;i++){if(!timers[i]()){timers.splice(i--,1)}}if(!timers.length){clearInterval(jQuery.timerId);jQuery.timerId=null}},13)}},show:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.show=true;this.custom(0,this.cur());if(this.prop=="width"||this.prop=="height"){this.elem.style[this.prop]="1px"}jQuery(this.elem).show()},hide:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(gotoEnd){var t=(new Date()).getTime();if(gotoEnd||t>this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim){if(this.options.curAnim[i]!==true){done=false}}if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){this.elem.style.display="none"}if(this.options.hide||this.options.show){for(var p in this.options.curAnim){jQuery.attr(this.elem.style,p,this.options.orig[p])}}}if(done&&jQuery.isFunction(this.options.complete)){this.options.complete.apply(this.elem)}return false}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};jQuery.fx.step={scrollLeft:function(fx){fx.elem.scrollLeft=fx.now},scrollTop:function(fx){fx.elem.scrollTop=fx.now},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now)},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit}};jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem){with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),fixed=jQuery.css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop)}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2){border(offsetParent)}if(!fixed&&jQuery.css(offsetParent,"position")=="fixed"){fixed=true}offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(jQuery.css(parent,"display"))){add(-parent.scrollLeft,-parent.scrollTop)}if(mozilla&&jQuery.css(parent,"overflow")!="visible"){border(parent)}parent=parent.parentNode}if((safari2&&(fixed||jQuery.css(offsetChild,"position")=="absolute"))||(mozilla&&jQuery.css(offsetChild,"position")!="absolute")){add(-doc.body.offsetLeft,-doc.body.offsetTop)}if(fixed){add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop))}}results={top:top,left:left}}}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true))}function add(l,t){left+=parseInt(l)||0;top+=parseInt(t)||0}return results}})();(function(C){var E=function(){return C.browser.msie?"tabIndex":"tabindex"};var B=function(G){if(G.length<=0){return undefined}if(!G.hasTabindexAttr()){return A(G)?Number(0):undefined}var F=G[0].getAttribute(E());return Number(F)};var D=function(F,G){return F.each(function(H,I){C(I).attr(E(),G)})};var A=function(F){if(F.length<=0){return false}return jQuery(F[0]).is("a, input, button, select, area, textarea, object")};C.fn.tabindex=function(F){if(F!==null&&F!==undefined){return D(this,F)}else{return B(this)}};C.fn.removeTabindex=function(){return this.each(function(F,G){C(G).removeAttr(E())})};C.fn.hasTabindexAttr=function(){if(this.length<=0){return false}var F=this[0].getAttributeNode(E());return F?F.specified:false};C.fn.hasTabindex=function(){return this.hasTabindexAttr()||A(this)}})(jQuery);(function(J){J.a11y=J.a11y||{};J.a11y.keys={UP:38,DOWN:40,LEFT:37,RIGHT:39,SPACE:32,ENTER:13,TAB:9,CTRL:17,SHIFT:16,ALT:18};J.a11y.orientation={HORIZONTAL:0,VERTICAL:1,BOTH:2};var T="keyboard-a11y";var N="selectionContext";var P="userHandlers";var c="defaultActivate";var U={next:J.a11y.keys.DOWN,previous:J.a11y.keys.UP};var B={next:J.a11y.keys.RIGHT,previous:J.a11y.keys.LEFT};var Z=function(e){return(e.jquery)?e[0]:e};var O=function(f,e,g){if(f.willLeaveContainer){f.willLeaveContainer(e.activeItem)}else{if(f.willUnselect){f.willUnselect(e.activeItem)}}if(!g){e.activeItem=null}};var A=function(j,f){if(!j.modifier){return true}var g=j.modifier;var h=(g&&f.ctrlKey);var e=(g&&f.altKey);var i=(g&&f.shiftKey);return(h||e||i)};var F=function(e){return function(f){if(f.which===e.key&&e.activateHandler&&A(e,f)){e.activateHandler(f.target,f);f.preventDefault()}}};var M=function(e,f){if(f){f(e)}};var W=function(f,e){if(e){e(f)}};var E=function(g,e,f){W(g,f.willUnselect)};var X=function(e,f,g){if(f.activeItem){E(f.activeItem,f,g)}e=Z(e);if(f.selectables.index(e)===-1){return }f.activeItem=e;M(e,g.willSelect)};var d=function(e,f){return function(g){X(g.target,e,f);return g.stopPropagation()}};var G=function(e,f){return function(g){E(g.target,e,f);return g.stopPropagation()}};var a=function(f){var g=f.selectables;var i=f.activeItem;var h=(!i)?-1:g.index(i);var e=h+1;e=(e>=g.length)?e=0:e;g.eq(e).focus()};var L=function(e){var f=e.selectables;var i=e.activeItem;var h=(!i)?0:f.index(i);var g=h-1;g=(g<0)?f.length-1:g;f.eq(g).focus()};var I=function(e,g,f){return function(h){if(h.which===g.next){a(e);h.preventDefault()}else{if(h.which===g.previous){L(e);h.preventDefault()}}}};var S=function(e){var f;if(e===J.a11y.orientation.HORIZONTAL){f=B}else{f=U}return f};var Q=function(f,e,g){return function(h){var i=(g.constructor===Function)?g():g;if(f.focusIsLeavingContainer){i=false}if(i&&h.target===e.get(0)){if(!f.activeItem){a(f)}else{jQuery(f.activeItem).focus()}}return h.stopPropagation()}};var Y=function(e){return function(f){e.focusIsLeavingContainer=false;return f.stopPropagation()}};var V=function(e){e.each(function(f,g){g=J(g);if(!g.hasTabindex()||(g.tabindex()<0)){g.tabindex(0)}})};var b=function(h,l,e,f){var k=[];J(e).each(function(i,m){k.push({modifier:null,key:m,activateHandler:l})});if(f&&f.additionalBindings){k=k.concat(f.additionalBindings)}for(var g=0;g<k.length;g=g+1){var j=k[g];h.keydown(F(j))}};var C=function(f,e,g){return function(h){if(h.which!==J.a11y.keys.TAB){return }O(f,e,g);if(h.shiftKey){e.focusIsLeavingContainer=true}}};var D=function(g,e,h,j,i){h=h||{};var l=J.extend({},j,i);var k=S(l.direction);var f={activeItem:undefined,selectables:e,focusIsLeavingContainer:false};g.keydown(I(f,k,h));g.keydown(C(h,f,l.rememberSelectionState));g.focus(Q(f,g,l.shouldSelectOnFocus));g.blur(Y(f));e.tabindex(-1);e.focus(d(f,h));e.blur(G(f,h));return f};var K=function(f,e){return function(g){if(!e){return }g=Z(g);if(f.index(g)===-1){return }e(g)}};var R=function(f,e){var g=f.data(T);return g?g[e]:undefined};var H=function(f,e,h){var g=f.data(T)||{};g[e]=h;f.data(T,g)};J.fn.tabbable=function(){V(this);return this};J.fn.selectable=function(f,g,h){var e=D(J(f),this,g,this.selectable.defaults,h);H(this,N,e);H(this,P,g);return this};J.fn.activatable=function(f,e){b(this,f,this.activatable.defaults.keys,e);H(this,c,K(this,f));return this};J.fn.select=function(e){e.focus();return this};J.fn.selectNext=function(){a(R(this,N));return this};J.fn.selectPrevious=function(){L(R(this,N));return this};J.fn.currentSelection=function(){return J(R(this,N).activeItem)};J.fn.activate=function(f){var e=R(this,c);e(f);return this};J.fn.activatable.defaults={keys:[J.a11y.keys.ENTER,J.a11y.keys.SPACE]};J.fn.selectable.defaults={direction:this.VERTICAL,shouldSelectOnFocus:true,rememberSelectionState:true}})(jQuery);(function(E){var C="http://www.w3.org/2005/07/aaa";var F=["main","secondary","navigation","banner","contentinfo","statements","note","seealso","search"];var A=new RegExp("^"+F.join("|")+"$");var D=E.browser.mozilla&&(parseFloat(E.browser.version)<1.9);var B=(function(){if(D){return function(I,G,H){if(typeof H!="undefined"){I.each(function(J,K){K.setAttributeNS(C,G,H)})}else{return I.get(0).getAttributeNS(C,G)}}}else{return function(I,G,H){if(typeof H!="undefined"){I.each(function(J,K){E(K).attr("aria-"+G,H)})}else{return I.attr("aria-"+G)}}}})();E.fn.extend({ariaRole:function(H){var G=this;if(H){H=(A.test(H)||!D)?H:"wairole:"+H;G.each(function(I,J){E(J).attr("role",H)});return G}else{var H=G.eq(0).attr("role");if(H){H=H.replace(/^wairole:/,"")}return H}},ariaState:function(){var G=arguments;var H=this;if(G.length==2){H.each(function(I,J){B(E(J),G[0],G[1])});return H}else{if(typeof G[0]=="string"){return B(H.eq(0),G[0])}else{H.each(function(I,J){E.each(G[0],function(K,L){E(J).ariaState(K,L)})});return H}}}});E.extend(E.expr[":"],{ariaRole:"jQuery(a).ariaRole()==m[3]",ariaState:"jQuery(a).ariaState(m[3].split(/=/)[0])==(/=/.test(m[3])?m[3].split(/=/)[1]:'true')"})})(jQuery);(function(B){B.dimensions={version:"@VERSION"};B.each(["Height","Width"],function(D,C){B.fn["inner"+C]=function(){if(!this[0]){return }var F=C=="Height"?"Top":"Left",E=C=="Height"?"Bottom":"Right";return this.css("display")!="none"?this[0]["client"+C]:A(this,C.toLowerCase())+A(this,"padding"+F)+A(this,"padding"+E)};B.fn["outer"+C]=function(F){if(!this[0]){return }var H=C=="Height"?"Top":"Left",E=C=="Height"?"Bottom":"Right";F=B.extend({margin:false},F||{});var G=this.css("display")!="none"?this[0]["offset"+C]:A(this,C.toLowerCase())+A(this,"border"+H+"Width")+A(this,"border"+E+"Width")+A(this,"padding"+H)+A(this,"padding"+E);return G+(F.margin?(A(this,"margin"+H)+A(this,"margin"+E)):0)}});B.each(["Left","Top"],function(D,C){B.fn["scroll"+C]=function(E){if(!this[0]){return }return E!=undefined?this.each(function(){this==window||this==document?window.scrollTo(C=="Left"?E:B(window)["scrollLeft"](),C=="Top"?E:B(window)["scrollTop"]()):this["scroll"+C]=E}):this[0]==window||this[0]==document?self[(C=="Left"?"pageXOffset":"pageYOffset")]||B.boxModel&&document.documentElement["scroll"+C]||document.body["scroll"+C]:this[0]["scroll"+C]}});B.fn.extend({position:function(){var H=0,G=0,F=this[0],I,C,E,D;if(F){E=this.offsetParent();I=this.offset();C=E.offset();I.top-=A(F,"marginTop");I.left-=A(F,"marginLeft");C.top+=A(E,"borderTopWidth");C.left+=A(E,"borderLeftWidth");D={top:I.top-C.top,left:I.left-C.left}}return D},offsetParent:function(){var C=this[0].offsetParent;while(C&&(!/^body|html$/i.test(C.tagName)&&B.css(C,"position")=="static")){C=C.offsetParent}return B(C)}});function A(C,D){return parseInt(B.curCSS(C.jquery?C[0]:C,D,true))||0}})(jQuery);(function(C){C.ui=C.ui||{};C.extend(C.ui,{plugin:{add:function(E,F,H){var G=C.ui[E].prototype;for(var D in H){G.plugins[D]=G.plugins[D]||[];G.plugins[D].push([F,H[D]])}},call:function(D,E,G){var H=D.plugins[E];if(!H){return }for(var F=0;F<H.length;F++){if(D.options[H[F][0]]){H[F][1].apply(D.element,G)}}}},cssCache:{},css:function(D){if(C.ui.cssCache[D]){return C.ui.cssCache[D]}var E=C('<div class="ui-resizable-gen">').addClass(D).css({position:"absolute",top:"-5000px",left:"-5000px",display:"block"}).appendTo("body");C.ui.cssCache[D]=!!((!/auto|default/.test(E.css("cursor"))||(/^[1-9]/).test(E.css("height"))||(/^[1-9]/).test(E.css("width"))||!(/none/).test(E.css("backgroundImage"))||!(/transparent|rgba\(0, 0, 0, 0\)/).test(E.css("backgroundColor"))));try{C("body").get(0).removeChild(E.get(0))}catch(F){}return C.ui.cssCache[D]},disableSelection:function(D){D.unselectable="on";D.onselectstart=function(){return false};if(D.style){D.style.MozUserSelect="none"}},enableSelection:function(D){D.unselectable="off";D.onselectstart=function(){return true};if(D.style){D.style.MozUserSelect=""}},hasScroll:function(G,E){var D=/top/.test(E||"top")?"scrollTop":"scrollLeft",F=false;if(G[D]>0){return true}G[D]=1;F=G[D]>0?true:false;G[D]=0;return F}});C.each(["Left","Top"],function(E,D){if(!C.fn["scroll"+D]){C.fn["scroll"+D]=function(F){return F!=undefined?this.each(function(){this==window||this==document?window.scrollTo(D=="Left"?F:C(window)["scrollLeft"](),D=="Top"?F:C(window)["scrollTop"]()):this["scroll"+D]=F}):this[0]==window||this[0]==document?self[(D=="Left"?"pageXOffset":"pageYOffset")]||C.boxModel&&document.documentElement["scroll"+D]||document.body["scroll"+D]:this[0]["scroll"+D]}}});var B=C.fn.remove;C.fn.extend({position:function(){var F=this.offset();var E=this.offsetParent();var D=E.offset();return{top:F.top-A(this[0],"marginTop")-D.top-A(E,"borderTopWidth"),left:F.left-A(this[0],"marginLeft")-D.left-A(E,"borderLeftWidth")}},offsetParent:function(){var D=this[0].offsetParent;while(D&&(!/^body|html$/i.test(D.tagName)&&C.css(D,"position")=="static")){D=D.offsetParent}return C(D)},mouseInteraction:function(D){return this.each(function(){new C.ui.mouseInteraction(this,D)})},removeMouseInteraction:function(D){return this.each(function(){if(C.data(this,"ui-mouse")){C.data(this,"ui-mouse").destroy()}})},remove:function(){this.trigger("remove");return B.apply(this,arguments)}});function A(D,E){return parseInt(C.curCSS(D.jquery?D[0]:D,E,true))||0}C.ui.mouseInteraction=function(F,E){var D=this;this.element=F;C.data(this.element,"ui-mouse",this);this.options=C.extend({},E);C(F).bind("mousedown.draggable",function(){return D.click.apply(D,arguments)});if(C.browser.msie){C(F).attr("unselectable","on")}C(F).mouseup(function(){if(D.timer){clearInterval(D.timer)}})};C.extend(C.ui.mouseInteraction.prototype,{destroy:function(){C(this.element).unbind("mousedown.draggable")},trigger:function(){return this.click.apply(this,arguments)},click:function(F){if(F.which!=1||C.inArray(F.target.nodeName.toLowerCase(),this.options.dragPrevention||[])!=-1||(this.options.condition&&!this.options.condition.apply(this.options.executor||this,[F,this.element]))){return true}var E=this;var D=function(){E._MP={left:F.pageX,top:F.pageY};C(document).bind("mouseup.draggable",function(){return E.stop.apply(E,arguments)});C(document).bind("mousemove.draggable",function(){return E.drag.apply(E,arguments)});if(!E.initalized&&Math.abs(E._MP.left-F.pageX)>=E.options.distance||Math.abs(E._MP.top-F.pageY)>=E.options.distance){if(E.options.start){E.options.start.call(E.options.executor||E,F,E.element)}if(E.options.drag){E.options.drag.call(E.options.executor||E,F,this.element)}E.initialized=true}};if(this.options.delay){if(this.timer){clearInterval(this.timer)}this.timer=setTimeout(D,this.options.delay)}else{D()}return false},stop:function(D){var E=this.options;if(!this.initialized){return C(document).unbind("mouseup.draggable").unbind("mousemove.draggable")}if(this.options.stop){this.options.stop.call(this.options.executor||this,D,this.element)}C(document).unbind("mouseup.draggable").unbind("mousemove.draggable");this.initialized=false;return false},drag:function(D){var E=this.options;if(C.browser.msie&&!D.button){return this.stop.apply(this,[D])}if(!this.initialized&&(Math.abs(this._MP.left-D.pageX)>=E.distance||Math.abs(this._MP.top-D.pageY)>=E.distance)){if(this.options.start){this.options.start.call(this.options.executor||this,D,this.element)}this.initialized=true}else{if(!this.initialized){return false}}if(E.drag){E.drag.call(this.options.executor||this,D,this.element)}return false}})})(jQuery);(function(B){B.ui=B.ui||{};B.fn.extend({dialog:function(D,E){var C=Array.prototype.slice.call(arguments,1);return this.each(function(){if(typeof D=="string"){var F=B.data(this,"ui-dialog")||B.data(B(this).parents(".ui-dialog:first").find(".ui-dialog-content")[0],"ui-dialog");F[D].apply(F,C)}else{if(!B(this).is(".ui-dialog-content")){new B.ui.dialog(this,D)}}})}});B.ui.dialog=function(E,M){this.options=M=B.extend({},B.ui.dialog.defaults,M&&M.modal?{resizable:false}:{},M);this.element=E;var L=this;B.data(this.element,"ui-dialog",this);B(E).bind("setData.dialog",function(O,N,P){M[N]=P}).bind("getData.dialog",function(O,N){return M[N]});var F=B(E).addClass("ui-dialog-content");if(!F.parent().length){F.appendTo("body")}F.wrap(document.createElement("div")).wrap(document.createElement("div"));var I=F.parent().addClass("ui-dialog-container").css({position:"relative"});var K=this.uiDialog=I.parent().hide().addClass("ui-dialog").css({position:"absolute",width:M.width,height:M.height,overflow:"hidden"});var C=F.attr("className").split(" ");B.each(C,function(N,O){if(O!="ui-dialog-content"){K.addClass(O)}});if(M.resizable&&B.fn.resizable){K.append('<div class="ui-resizable-n ui-resizable-handle"></div>').append('<div class="ui-resizable-s ui-resizable-handle"></div>').append('<div class="ui-resizable-e ui-resizable-handle"></div>').append('<div class="ui-resizable-w ui-resizable-handle"></div>').append('<div class="ui-resizable-ne ui-resizable-handle"></div>').append('<div class="ui-resizable-se ui-resizable-handle"></div>').append('<div class="ui-resizable-sw ui-resizable-handle"></div>').append('<div class="ui-resizable-nw ui-resizable-handle"></div>');K.resizable({maxWidth:M.maxWidth,maxHeight:M.maxHeight,minWidth:M.minWidth,minHeight:M.minHeight})}I.prepend('<div class="ui-dialog-titlebar"></div>');var D=B(".ui-dialog-titlebar",I);var J=(M.title)?M.title:(F.attr("title"))?F.attr("title"):"";D.append('<span class="ui-dialog-title">'+J+"</span>");D.append('<a href="#" class="ui-dialog-titlebar-close"><span>X</span></a>');this.uiDialogTitlebarClose=B(".ui-dialog-titlebar-close",D).hover(function(){B(this).addClass("ui-dialog-titlebar-close-hover")},function(){B(this).removeClass("ui-dialog-titlebar-close-hover")}).mousedown(function(N){N.stopPropagation()}).click(function(){L.close();return false}).keydown(function(N){var O=27;N.keyCode&&N.keyCode==O&&L.close()});var G=0;B.each(M.buttons,function(){G=1;return false});if(G==1){K.append('<div class="ui-dialog-buttonpane"></div>');var H=B(".ui-dialog-buttonpane",K);B.each(M.buttons,function(N,P){var O=B(document.createElement("button")).text(N).click(P);H.append(O)})}if(M.draggable&&B.fn.draggable){K.draggable({handle:".ui-dialog-titlebar",start:function(){L.activate()}})}K.mousedown(function(){L.activate()});D.click(function(){L.activate()});M.bgiframe&&B.fn.bgiframe&&K.bgiframe();this.open=function(){M.modal&&A.show(L,M.overlay);K.appendTo("body");var P=B(window),S=B(document),R=S.scrollTop(),Q=S.scrollLeft();if(M.position.constructor==Array){R+=M.position[1];Q+=M.position[0]}else{switch(M.position){case"center":R+=(P.height()/2)-(K.height()/2);Q+=(P.width()/2)-(K.width()/2);break;case"top":R+=0;Q+=(P.width()/2)-(K.width()/2);break;case"right":R+=(P.height()/2)-(K.height()/2);Q+=(P.width())-(K.width());break;case"bottom":R+=(P.height())-(K.height());Q+=(P.width()/2)-(K.width()/2);break;case"left":R+=(P.height()/2)-(K.height()/2);Q+=0;break;default:R+=(P.height()/2)-(K.height()/2);Q+=(P.width()/2)-(K.width()/2)}}R=R<S.scrollTop()?S.scrollTop():R;K.css({top:R,left:Q});K.show();L.activate();var N=null;var O={options:M};this.uiDialogTitlebarClose.focus();B(this.element).triggerHandler("dialogopen",[N,O],M.open)};this.activate=function(){var N=0;B(".ui-dialog:visible").each(function(){N=Math.max(N,parseInt(B(this).css("z-index"),10))});A.$el&&A.$el.css("z-index",++N);K.css("z-index",++N)};this.close=function(){M.modal&&A.hide();K.hide();var O=null;var N={options:M};B(this.element).triggerHandler("dialogclose",[O,N],M.close)};if(M.autoOpen){this.open()}};B.extend(B.ui.dialog,{defaults:{autoOpen:true,bgiframe:false,buttons:[],draggable:true,height:200,minHeight:100,minWidth:150,modal:false,overlay:{},position:"center",resizable:true,width:300}});var A={$el:null,events:B.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(C){return C+".ui-dialog-overlay"}).join(" "),show:function(F,E){if(this.$el){return }this.dialog=F;this.selects=this.ie6&&B("select:visible").css("visibility","hidden");var G=this.width();var C=this.height();this.$el=B("<div/>").appendTo(document.body).addClass("ui-dialog-overlay").css(B.extend({borderWidth:0,margin:0,padding:0,position:"absolute",top:0,left:0,width:G,height:C},E));B("a, :input").bind(this.events,function(){if(B(this).parents(".ui-dialog").length==0){F.uiDialogTitlebarClose.focus();return false}});B(document).bind("keydown.ui-dialog-overlay",function(H){var I=27;H.keyCode&&H.keyCode==I&&F.close()});$overlay=this.$el;function D(){$overlay.css({width:G,height:C}).css({width:A.width(),height:A.height()})}B(window).bind("resize.ui-dialog-overlay",D);F.uiDialog.is(".ui-draggable")&&F.uiDialog.data("stop.draggable",D);F.uiDialog.is(".ui-resizable")&&F.uiDialog.data("stop.resizable",D)},hide:function(){B("a, :input").add([document,window]).unbind(".ui-dialog-overlay");this.ie6&&this.selects.css("visibility","visible");this.$el=null;B(".ui-dialog-overlay").remove()},height:function(){var C;if(this.ie6&&(B(document.body).height()<B(window).height())&&!(document.documentElement.scrollTop||(this.dialog.uiDialog.offset().top+this.dialog.uiDialog.height())>B(window).height())){C=B(window).height()}else{C=B(document).height()}return C+"px"},width:function(){var C;if(this.ie6&&(B(document.body).width()<B(window).width())&&!(document.documentElement.scrollLeft||(this.dialog.uiDialog.offset().left+this.dialog.uiDialog.width())>B(window).width())){C=B(window).width()}else{C=B(document).width()}return C+"px"},ie6:B.browser.msie&&B.browser.version<7,selects:null}})(jQuery);(function(A){A.fn.extend({draggable:function(C){var B=Array.prototype.slice.call(arguments,1);return this.each(function(){if(typeof C=="string"){var D=A.data(this,"draggable");if(D){D[C].apply(D,B)}}else{if(!A.data(this,"draggable")){new A.ui.draggable(this,C)}}})}});A.ui.draggable=function(D,C){var B=this;this.element=A(D);A.data(D,"draggable",this);this.element.addClass("ui-draggable");this.options=A.extend({},C);var E=this.options;A.extend(E,{helper:E.ghosting==true?"clone":(E.helper||"original"),handle:E.handle?(A(E.handle,D)[0]?A(E.handle,D):this.element):this.element,appendTo:E.appendTo||"parent"});A(D).bind("setData.draggable",function(G,F,H){B.options[F]=H}).bind("getData.draggable",function(G,F){return B.options[F]});A(E.handle).mouseInteraction({executor:this,delay:E.delay,distance:E.distance||1,dragPrevention:E.cancel||E.cancel===""?E.cancel.toLowerCase().split(","):["input","textarea","button","select","option"],start:this.start,stop:this.stop,drag:this.drag,condition:function(F){return !(F.target.className.indexOf("ui-resizable-handle")!=-1||this.options.disabled)}});if(E.helper=="original"&&(this.element.css("position")=="static"||this.element.css("position")=="")){this.element.css("position","relative")}if(E.cursorAt&&E.cursorAt.constructor==Array){E.cursorAt={left:E.cursorAt[0],top:E.cursorAt[1]}}};A.extend(A.ui.draggable.prototype,{plugins:{},ui:function(B){return{helper:this.helper,position:this.position,absolutePosition:this.positionAbs,instance:this,options:this.options,element:this.element}},propagate:function(C,B){A.ui.plugin.call(this,C,[B,this.ui()]);return this.element.triggerHandler(C=="drag"?C:"drag"+C,[B,this.ui()],this.options[C])},destroy:function(){if(!A.data(this.element[0],"draggable")){return }this.options.handle.removeMouseInteraction();this.element.removeClass("ui-draggable ui-draggable-disabled").removeData("draggable").unbind(".draggable")},enable:function(){this.element.removeClass("ui-draggable-disabled");this.options.disabled=false},disable:function(){this.element.addClass("ui-draggable-disabled");this.options.disabled=true},setContrains:function(B,C,E,D){this.minLeft=B;this.maxLeft=C;this.minTop=E;this.maxTop=D;this.constrainsSet=true},checkConstrains:function(){if(!this.constrainsSet){return }if(this.position.left<this.minLeft){this.position.left=this.minLeft}if(this.position.left>this.maxLeft-this.helperProportions.width){this.position.left=this.maxLeft-this.helperProportions.width}if(this.position.top<this.minTop){this.position.top=this.minTop}if(this.position.top>this.maxTop-this.helperProportions.height){this.position.top=this.maxTop-this.helperProportions.height}},recallOffset:function(D){var C={left:this.elementOffset.left-this.offsetParentOffset.left,top:this.elementOffset.top-this.offsetParentOffset.top};var B=this.helper.css("position")=="relative";this.originalPosition={left:(B?parseInt(this.helper.css("left"),10)||0:C.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft)),top:(B?parseInt(this.helper.css("top"),10)||0:C.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop))};this.offset={left:this._pageX-this.originalPosition.left,top:this._pageY-this.originalPosition.top}},start:function(D){var E=this.options;if(A.ui.ddmanager){A.ui.ddmanager.current=this}this.helper=typeof E.helper=="function"?A(E.helper.apply(this.element[0],[D])):(E.helper=="clone"?this.element.clone().appendTo((E.appendTo=="parent"?this.element[0].parentNode:E.appendTo)):this.element);if(this.helper[0]!=this.element[0]){this.helper.css("position","absolute")}if(!this.helper.parents("body").length){this.helper.appendTo((E.appendTo=="parent"?this.element[0].parentNode:E.appendTo))}this.offsetParent=(function(F){while(F){if(F.style&&(/(absolute|relative|fixed)/).test(A.css(F,"position"))){return A(F)}F=F.parentNode?F.parentNode:null}return A("body")})(this.helper[0].parentNode);this.elementOffset=this.element.offset();this.offsetParentOffset=this.offsetParent.offset();var C={left:this.elementOffset.left-this.offsetParentOffset.left,top:this.elementOffset.top-this.offsetParentOffset.top};this._pageX=D.pageX;this._pageY=D.pageY;this.clickOffset={left:D.pageX-this.elementOffset.left,top:D.pageY-this.elementOffset.top};var B=this.helper.css("position")=="relative";this.originalPosition={left:(B?parseInt(this.helper.css("left"),10)||0:C.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft)),top:(B?parseInt(this.helper.css("top"),10)||0:C.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop))};if(this.element.css("position")=="fixed"){this.originalPosition.top-=this.offsetParent[0]==document.body?A(document).scrollTop():this.offsetParent[0].scrollTop;this.originalPosition.left-=this.offsetParent[0]==document.body?A(document).scrollLeft():this.offsetParent[0].scrollLeft}this.offset={left:D.pageX-this.originalPosition.left,top:D.pageY-this.originalPosition.top};if(this.element[0]!=this.helper[0]){this.offset.left+=parseInt(this.element.css("marginLeft"),10)||0;this.offset.top+=parseInt(this.element.css("marginTop"),10)||0}this.propagate("start",D);this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()};if(A.ui.ddmanager&&!E.dropBehaviour){A.ui.ddmanager.prepareOffsets(this,D)}if(E.cursorAt){if(E.cursorAt.top!=undefined||E.cursorAt.bottom!=undefined){this.offset.top-=this.clickOffset.top-(E.cursorAt.top!=undefined?E.cursorAt.top:(this.helperProportions.height-E.cursorAt.bottom));this.clickOffset.top=(E.cursorAt.top!=undefined?E.cursorAt.top:(this.helperProportions.height-E.cursorAt.bottom))}if(E.cursorAt.left!=undefined||E.cursorAt.right!=undefined){this.offset.left-=this.clickOffset.left-(E.cursorAt.left!=undefined?E.cursorAt.left:(this.helperProportions.width-E.cursorAt.right));this.clickOffset.left=(E.cursorAt.left!=undefined?E.cursorAt.left:(this.helperProportions.width-E.cursorAt.right))}}return false},clear:function(){if(A.ui.ddmanager){A.ui.ddmanager.current=null}this.helper=null},stop:function(B){if(A.ui.ddmanager&&!this.options.dropBehaviour){A.ui.ddmanager.drop(this,B)}this.propagate("stop",B);if(this.cancelHelperRemoval){return false}if(this.options.helper!="original"){this.helper.remove()}this.clear();return false},drag:function(B){this.position={top:B.pageY-this.offset.top,left:B.pageX-this.offset.left};this.positionAbs={left:B.pageX-this.clickOffset.left,top:B.pageY-this.clickOffset.top};this.checkConstrains();this.position=this.propagate("drag",B)||this.position;this.checkConstrains();A(this.helper).css({left:this.position.left+"px",top:this.position.top+"px"});if(A.ui.ddmanager){A.ui.ddmanager.drag(this,B)}return false}});A.ui.plugin.add("draggable","cursor",{start:function(D,C){var B=A("body");if(B.css("cursor")){C.options._cursor=B.css("cursor")}B.css("cursor",C.options.cursor)},stop:function(C,B){if(B.options._cursor){A("body").css("cursor",B.options._cursor)}}});A.ui.plugin.add("draggable","zIndex",{start:function(D,C){var B=A(C.helper);if(B.css("zIndex")){C.options._zIndex=B.css("zIndex")}B.css("zIndex",C.options.zIndex)},stop:function(C,B){if(B.options._zIndex){A(B.helper).css("zIndex",B.options._zIndex)}}});A.ui.plugin.add("draggable","opacity",{start:function(D,C){var B=A(C.helper);if(B.css("opacity")){C.options._opacity=B.css("opacity")}B.css("opacity",C.options.opacity)},stop:function(C,B){if(B.options._opacity){A(B.helper).css("opacity",B.options._opacity)}}});A.ui.plugin.add("draggable","revert",{stop:function(E,D){var B=D.instance,C=A(B.helper);B.cancelHelperRemoval=true;A(D.helper).animate({left:B.originalPosition.left,top:B.originalPosition.top},parseInt(D.options.revert,10)||500,function(){if(D.options.helper!="original"){C.remove()}if(!C){B.clear()}})}});A.ui.plugin.add("draggable","iframeFix",{start:function(D,C){var F=C.options;if(C.instance.slowMode){return }if(F.iframeFix.constructor==Array){for(var B=0;B<F.iframeFix.length;B++){var E=A(F.iframeFix[B]).offset({border:false});A('<div class="DragDropIframeFix"" style="background: #fff;"></div>').css("width",A(F.iframeFix[B])[0].offsetWidth+"px").css("height",A(F.iframeFix[B])[0].offsetHeight+"px").css("position","absolute").css("opacity","0.001").css("z-index","1000").css("top",E.top+"px").css("left",E.left+"px").appendTo("body")}}else{A("iframe").each(function(){var G=A(this).offset({border:false});A('<div class="DragDropIframeFix" style="background: #fff;"></div>').css("width",this.offsetWidth+"px").css("height",this.offsetHeight+"px").css("position","absolute").css("opacity","0.001").css("z-index","1000").css("top",G.top+"px").css("left",G.left+"px").appendTo("body")})}},stop:function(C,B){if(B.options.iframeFix){A("div.DragDropIframeFix").each(function(){this.parentNode.removeChild(this)})}}});A.ui.plugin.add("draggable","containment",{start:function(E,C){var G=C.options;var B=C.instance;if((G.containment.left!=undefined||G.containment.constructor==Array)&&!G._containment){return }if(!G._containment){G._containment=G.containment}if(G._containment=="parent"){G._containment=this[0].parentNode}if(G._containment=="document"){G.containment=[0,0,A(document).width(),(A(document).height()||document.body.parentNode.scrollHeight)]}else{var D=A(G._containment)[0];var F=A(G._containment).offset();G.containment=[F.left,F.top,F.left+(D.offsetWidth||D.scrollWidth),F.top+(D.offsetHeight||D.scrollHeight)]}var H=G.containment;C.instance.setContrains(H[0]-(B.offset.left-B.clickOffset.left),H[2]-(B.offset.left-B.clickOffset.left),H[1]-(B.offset.top-B.clickOffset.top),H[3]-(B.offset.top-B.clickOffset.top))}});A.ui.plugin.add("draggable","grid",{drag:function(E,D){var F=D.options;var C=D.instance.originalPosition.left+Math.round((E.pageX-D.instance._pageX)/F.grid[0])*F.grid[0];var B=D.instance.originalPosition.top+Math.round((E.pageY-D.instance._pageY)/F.grid[1])*F.grid[1];D.instance.position.left=C;D.instance.position.top=B}});A.ui.plugin.add("draggable","axis",{drag:function(C,B){var D=B.options;if(D.constraint){D.axis=D.constraint}switch(D.axis){case"x":B.instance.position.top=B.instance.originalPosition.top;break;case"y":B.instance.position.left=B.instance.originalPosition.left;break}}});A.ui.plugin.add("draggable","scroll",{start:function(C,B){var D=B.options;D.scrollSensitivity=D.scrollSensitivity||20;D.scrollSpeed=D.scrollSpeed||20;B.instance.overflowY=function(E){do{if(/auto|scroll/.test(E.css("overflow"))||(/auto|scroll/).test(E.css("overflow-y"))){return E}E=E.parent()}while(E[0].parentNode);return A(document)}(this);B.instance.overflowX=function(E){do{if(/auto|scroll/.test(E.css("overflow"))||(/auto|scroll/).test(E.css("overflow-x"))){return E}E=E.parent()}while(E[0].parentNode);return A(document)}(this)},drag:function(D,C){var E=C.options;var B=C.instance;if(B.overflowY[0]!=document&&B.overflowY[0].tagName!="HTML"){if(B.overflowY[0].offsetHeight-(C.position.top-B.overflowY[0].scrollTop+B.clickOffset.top)<E.scrollSensitivity){B.overflowY[0].scrollTop=B.overflowY[0].scrollTop+E.scrollSpeed}if((C.position.top-B.overflowY[0].scrollTop+B.clickOffset.top)<E.scrollSensitivity){B.overflowY[0].scrollTop=B.overflowY[0].scrollTop-E.scrollSpeed}}else{if(D.pageY-A(document).scrollTop()<E.scrollSensitivity){A(document).scrollTop(A(document).scrollTop()-E.scrollSpeed)}if(A(window).height()-(D.pageY-A(document).scrollTop())<E.scrollSensitivity){A(document).scrollTop(A(document).scrollTop()+E.scrollSpeed)}}if(B.overflowX[0]!=document&&B.overflowX[0].tagName!="HTML"){if(B.overflowX[0].offsetWidth-(C.position.left-B.overflowX[0].scrollLeft+B.clickOffset.left)<E.scrollSensitivity){B.overflowX[0].scrollLeft=B.overflowX[0].scrollLeft+E.scrollSpeed}if((C.position.top-B.overflowX[0].scrollLeft+B.clickOffset.left)<E.scrollSensitivity){B.overflowX[0].scrollLeft=B.overflowX[0].scrollLeft-E.scrollSpeed}}else{if(D.pageX-A(document).scrollLeft()<E.scrollSensitivity){A(document).scrollLeft(A(document).scrollLeft()-E.scrollSpeed)}if(A(window).width()-(D.pageX-A(document).scrollLeft())<E.scrollSensitivity){A(document).scrollLeft(A(document).scrollLeft()+E.scrollSpeed)}}C.instance.recallOffset(D)}});A.ui.plugin.add("draggable","snap",{start:function(C,B){B.instance.snapElements=[];A(B.options.snap===true?".ui-draggable":B.options.snap).each(function(){var E=A(this);var D=E.offset();if(this!=B.instance.element[0]){B.instance.snapElements.push({item:this,width:E.outerWidth(),height:E.outerHeight(),top:D.top,left:D.left})}})},drag:function(I,M){var K=M.options.snapTolerance||20;var D=M.absolutePosition.left,C=D+M.instance.helperProportions.width,O=M.absolutePosition.top,N=O+M.instance.helperProportions.height;for(var H=M.instance.snapElements.length-1;H>=0;H--){var E=M.instance.snapElements[H].left,B=E+M.instance.snapElements[H].width,Q=M.instance.snapElements[H].top,L=Q+M.instance.snapElements[H].height;if(!((E-K<D&&D<B+K&&Q-K<O&&O<L+K)||(E-K<D&&D<B+K&&Q-K<N&&N<L+K)||(E-K<C&&C<B+K&&Q-K<O&&O<L+K)||(E-K<C&&C<B+K&&Q-K<N&&N<L+K))){continue}if(M.options.snapMode!="inner"){var J=Math.abs(Q-N)<=20;var P=Math.abs(L-O)<=20;var G=Math.abs(E-C)<=20;var F=Math.abs(B-D)<=20;if(J){M.position.top=Q-M.instance.offset.top+M.instance.clickOffset.top-M.instance.helperProportions.height}if(P){M.position.top=L-M.instance.offset.top+M.instance.clickOffset.top}if(G){M.position.left=E-M.instance.offset.left+M.instance.clickOffset.left-M.instance.helperProportions.width}if(F){M.position.left=B-M.instance.offset.left+M.instance.clickOffset.left}}if(M.options.snapMode!="outer"){var J=Math.abs(Q-O)<=20;var P=Math.abs(L-N)<=20;var G=Math.abs(E-D)<=20;var F=Math.abs(B-C)<=20;if(J){M.position.top=Q-M.instance.offset.top+M.instance.clickOffset.top}if(P){M.position.top=L-M.instance.offset.top+M.instance.clickOffset.top-M.instance.helperProportions.height}if(G){M.position.left=E-M.instance.offset.left+M.instance.clickOffset.left}if(F){M.position.left=B-M.instance.offset.left+M.instance.clickOffset.left-M.instance.helperProportions.width}}}}})})(jQuery);(function(A){A.fn.extend({droppable:function(C){var B=Array.prototype.slice.call(arguments,1);return this.each(function(){if(typeof C=="string"){var D=A.data(this,"droppable");if(D){D[C].apply(D,B)}}else{if(!A.data(this,"droppable")){new A.ui.droppable(this,C)}}})}});A.ui.droppable=function(D,B){this.element=A(D);A.data(D,"droppable",this);this.element.addClass("ui-droppable");var E=this.options=B=A.extend({},A.ui.droppable.defaults,B);var C=E.accept;E=A.extend(E,{accept:E.accept&&E.accept.constructor==Function?E.accept:function(F){return A(F).is(C)}});A(D).bind("setData.droppable",function(G,F,H){E[F]=H}).bind("getData.droppable",function(G,F){return E[F]});this.proportions={width:this.element.outerWidth(),height:this.element.outerHeight()};A.ui.ddmanager.droppables.push({item:this,over:0,out:1})};A.extend(A.ui.droppable,{defaults:{disabled:false,tolerance:"intersect"}});A.extend(A.ui.droppable.prototype,{plugins:{},ui:function(B){return{instance:this,draggable:(B.currentItem||B.element),helper:B.helper,position:B.position,absolutePosition:B.positionAbs,options:this.options,element:this.element}},destroy:function(){var B=A.ui.ddmanager.droppables;for(var C=0;C<B.length;C++){if(B[C].item==this){B.splice(C,1)}}this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable")},enable:function(){this.element.removeClass("ui-droppable-disabled");this.options.disabled=false},disable:function(){this.element.addClass("ui-droppable-disabled");this.options.disabled=true},over:function(C){var B=A.ui.ddmanager.current;if(!B||(B.currentItem||B.element)[0]==this.element[0]){return }if(this.options.accept.call(this.element,(B.currentItem||B.element))){A.ui.plugin.call(this,"over",[C,this.ui(B)]);this.element.triggerHandler("dropover",[C,this.ui(B)],this.options.over)}},out:function(C){var B=A.ui.ddmanager.current;if(!B||(B.currentItem||B.element)[0]==this.element[0]){return }if(this.options.accept.call(this.element,(B.currentItem||B.element))){A.ui.plugin.call(this,"out",[C,this.ui(B)]);this.element.triggerHandler("dropout",[C,this.ui(B)],this.options.out)}},drop:function(D,C){var B=C||A.ui.ddmanager.current;if(!B||(B.currentItem||B.element)[0]==this.element[0]){return }var E=false;this.element.find(".ui-droppable").each(function(){var F=A.data(this,"droppable");if(F.options.greedy&&A.ui.intersect(B,{item:F,offset:F.element.offset()},F.options.tolerance)){E=true;return false}});if(E){return }if(this.options.accept.call(this.element,(B.currentItem||B.element))){A.ui.plugin.call(this,"drop",[D,this.ui(B)]);this.element.triggerHandler("drop",[D,this.ui(B)],this.options.drop)}},activate:function(C){var B=A.ui.ddmanager.current;A.ui.plugin.call(this,"activate",[C,this.ui(B)]);if(B){this.element.triggerHandler("dropactivate",[C,this.ui(B)],this.options.activate)}},deactivate:function(C){var B=A.ui.ddmanager.current;A.ui.plugin.call(this,"deactivate",[C,this.ui(B)]);if(B){this.element.triggerHandler("dropdeactivate",[C,this.ui(B)],this.options.deactivate)}}});A.ui.intersect=function(L,F,J){if(!F.offset){return false}var D=L.positionAbs.left,C=D+L.helperProportions.width,I=L.positionAbs.top,H=I+L.helperProportions.height;var E=F.offset.left,B=E+F.item.proportions.width,K=F.offset.top,G=K+F.item.proportions.height;switch(J){case"fit":if(!((H-(L.helperProportions.height/2)>K&&I<K)||(I<G&&H>G)||(C>E&&D<E)||(D<B&&C>B))){return false}if(H-(L.helperProportions.height/2)>K&&I<K){return 1}if(I<G&&H>G){return 2}if(C>E&&D<E){return 1}if(D<B&&C>B){return 2}break;case"intersect":return(E<D+(L.helperProportions.width/2)&&C-(L.helperProportions.width/2)<B&&K<I+(L.helperProportions.height/2)&&H-(L.helperProportions.height/2)<G);break;case"pointer":return(E<(L.positionAbs.left+L.clickOffset.left)&&(L.positionAbs.left+L.clickOffset.left)<B&&K<(L.positionAbs.top+L.clickOffset.top)&&(L.positionAbs.top+L.clickOffset.top)<G);break;case"touch":return((I>=K&&I<=G)||(H>=K&&H<=G)||(I<K&&H>G))&&((D>=E&&D<=B)||(C>=E&&C<=B)||(D<E&&C>B));break;default:return false;break}};A.ui.ddmanager={current:null,droppables:[],prepareOffsets:function(D,F){var B=A.ui.ddmanager.droppables;var E=F?F.type:null;for(var C=0;C<B.length;C++){if(B[C].item.options.disabled||(D&&!B[C].item.options.accept.call(B[C].item.element,(D.currentItem||D.element)))){continue}B[C].offset=A(B[C].item.element).offset();B[C].item.proportions={width:B[C].item.element.outerWidth(),height:B[C].item.element.outerHeight()};if(E=="dragstart"){B[C].item.activate.call(B[C].item,F)}}},drop:function(B,C){A.each(A.ui.ddmanager.droppables,function(){if(!this.item.options.disabled&&A.ui.intersect(B,this,this.item.options.tolerance)){this.item.drop.call(this.item,C)}if(!this.item.options.disabled&&this.item.options.accept.call(this.item.element,(B.currentItem||B.element))){this.out=1;this.over=0;this.item.deactivate.call(this.item,C)}})},drag:function(B,C){if(B.options.refreshPositions){A.ui.ddmanager.prepareOffsets(B,C)}A.each(A.ui.ddmanager.droppables,function(){if(this.item.disabled||this.greedyChild){return }var E=A.ui.intersect(B,this,this.item.options.tolerance);var F=!E&&this.over==1?"out":(E&&this.over==0?"over":null);if(!F){return }var D=A.data(this.item.element[0],"droppable");if(D.options.greedy){this.item.element.parents(".ui-droppable").each(function(){var G=this;A.each(A.ui.ddmanager.droppables,function(){if(this.item.element[0]!=G){return }this[F]=0;this[F=="out"?"over":"out"]=1;this.greedyChild=(F=="over"?1:0);this.item[F=="out"?"over":"out"].call(this.item,C);return false})})}this[F]=1;this[F=="out"?"over":"out"]=0;this.item[F].call(this.item,C)})}};A.ui.plugin.add("droppable","activeClass",{activate:function(C,B){A(this).addClass(B.options.activeClass)},deactivate:function(C,B){A(this).removeClass(B.options.activeClass)},drop:function(C,B){A(this).removeClass(B.options.activeClass)}});A.ui.plugin.add("droppable","hoverClass",{over:function(C,B){A(this).addClass(B.options.hoverClass)},out:function(C,B){A(this).removeClass(B.options.hoverClass)},drop:function(C,B){A(this).removeClass(B.options.hoverClass)}})})(jQuery);var fluid=fluid||{};(function(B,A){A.keys={TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,META:19,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,i:73,j:74,k:75,m:77};A.roles={GRID:{container:"grid",item:"gridcell"},LIST:{container:"list",item:"listitem"}};A.orientation={HORIZONTAL:"horiz",VERTICAL:"vert"};A.position={BEFORE:0,AFTER:1,INSIDE:2,NO_TARGET:-1};A.direction={NEXT:1,PREVIOUS:-1};A.defaultKeysets=[{modifier:function(C){return C.ctrlKey},up:A.keys.UP,down:A.keys.DOWN,right:A.keys.RIGHT,left:A.keys.LEFT},{modifier:function(C){return C.ctrlKey},up:A.keys.i,down:A.keys.m,right:A.keys.k,left:A.keys.j}];A.mixin=function(E,D){for(var C in D){if(D.hasOwnProperty(C)){E[C]=D[C]}}};A.wrap=function(C){return((!C||C.jquery)?C:B(C))};A.utils={};A.utils.seekNodesById=function(G,I,E){var C=G.getElementsByTagName(I);var H=[];for(var F=0;F<C.length;++F){var D=C[F];var J=D.id;if(J&&J.match(E)){H.push(D)}}return H};A.utils.escapeSelector=function(C){return C.replace(/\:/g,"\\:")};A.utils.findForm=function(C){while(C){if(C.nodeName.toLowerCase()==="form"){return C}C=C.parentNode}};A.utils.adaptFindItems=function(D){var E=function(){};var C={};if(typeof D==="function"){E=D}else{C=D}C.movables=C.movables||E;C.selectables=C.selectables||C.movables;C.dropTargets=C.dropTargets||C.movables;C.grabHandle=C.grabHandle||function(F){return F};return C};A.utils.jById=function(C){return B("[id="+C+"]")}})(jQuery,fluid);var fluid=fluid||{};(function(L,F){var D=F.roles.LIST;var B="message-bundle:";var I={defaultStyle:"orderable-default",selected:"orderable-selected",dragging:"orderable-dragging",hover:"orderable-hover",dropMarker:"orderable-drop-marker",avatar:"orderable-avatar"};var A=function(N){var M=L(N).clone();M.removeAttr("id");L("[id]",M).removeAttr("id");L(":hidden",M).remove();L("input",M).attr("disabled","true");M.removeClass("ui-droppable");return M};function G(N){var M=F.wrap(N.selectables());if(M.length<=0){return null}return M[0]}function H(N,O,P,Q,M){N.focus(O);N.keydown(P);N.keyup(Q);N.mousemove(M);if(L.browser.msie){N[0].ondrag=function(){return false};N[0].onselectstart=function(){return false}}}function K(M,N,P){var O=G(N);if(O){M.ariaState("activedescendent",O.id)}M.ariaRole(P.container);M.ariaState("multiselectable","false");M.ariaState("readonly","false");M.ariaState("disabled","false")}function J(M,N){M.removeClass(N.selected);M.addClass(N.defaultStyle);M.ariaState("selected","false")}var E={};E.findTarget=function(N,S,P,R){var M=function(T){return(T&&T.id===P)};var Q=function(T){return((S.index(T)>-1)||M(T))};var O=Q(N)?N:L.grep(L(N).parents(),Q)[0];if(M(O)){O=R?R[0]:null}return O};E.createAvatarId=function(M){return M+"_avatar"};var C=function(N,M){if(M&&!(M instanceof Array)){M=[M]}return M||N};F.Reorderer=function(b,Z,U,R){var Q=this;this.domNode=L(b);this.activeItem=undefined;Z=F.utils.adaptFindItems(Z);R=R||{};var h=R.role||D;var a=R.instructionMessageId||B;var P=C(F.defaultKeysets,R.keysets);this.cssClasses=R.cssClassNames||I;var O=R.avatarCreator||A;this.focusActiveItem=function(i){if(!Q.activeItem){var j=G(Z);if(!j){return i.stopPropagation()}L(j).focus()}else{L(Q.activeItem).focus()}return i.stopPropagation()};var d=function(j){var k=0;for(k;k<P.length;k++){if(P[k].modifier(j)){return true}}return false};var N=function(){return(L.inArray(Q.activeItem,Z.movables())>=0)};this.handleKeyDown=function(i){if(!Q.activeItem||(Q.activeItem!==i.target)){return true}var j=L(Q.activeItem);if(!j.hasClass(Q.cssClasses.dragging)&&d(i)){if(N()){j.removeClass(Q.cssClasses.selected);j.addClass(Q.cssClasses.dragging);j.ariaState("grab","true")}return false}return Q.handleDirectionKeyDown(i)};this.handleKeyUp=function(i){if(!Q.activeItem||(Q.activeItem!==i.target)){return true}var j=L(Q.activeItem);if(j.hasClass(Q.cssClasses.dragging)&&!d(i)){if(N()){j.removeClass(Q.cssClasses.dragging);j.addClass(Q.cssClasses.selected);j.ariaState("grab","supported");return false}}};var e=function(i){if(N()){i(Q.activeItem);Q.activeItem.focus();L(Q.activeItem).removeClass(Q.cssClasses.selected)}};var Y=function(i){return(!i.ctrlKey&&!i.altKey&&!i.shiftKey&&!i.metaKey)};var X=function(l,j,i){var k=false;switch(l){case j.up:e(i.moveItemUp);k=true;break;case j.down:e(i.moveItemDown);k=true;break;case j.left:e(i.moveItemLeft);k=true;break;case j.right:e(i.moveItemRight);k=true;break}return k};var g=function(m,k,j,n){var i=false;var l;switch(m){case k.up:l=j.getItemAbove(n);i=true;break;case k.down:l=j.getItemBelow(n);i=true;break;case k.left:l=j.getLeftSibling(n);i=true;break;case k.right:l=j.getRightSibling(n);i=true;break}L(l).focus();return i};this.handleDirectionKeyDown=function(j){if(!Q.activeItem){return true}for(var k=0;k<P.length;k++){var l=P[k];var m=false;if(l.modifier(j)){m=X(j.keyCode,l,U)}else{if(Y(j)){m=g(j.keyCode,l,U,Q.activeItem)}}if(m){return false}}return true};var S;var M;var T=function(j){j=F.wrap(j);var i=E.createAvatarId(Q.domNode.id);return function(l){if(M){var m=E.findTarget(l.target,j,i,M);if(m){var k=U.dropPosition(m,Q.activeItem,l.clientX,l.pageY);if(k===F.position.BEFORE){L(m).before(S);S.show()}else{if(k===F.position.AFTER){L(m).after(S);S.show()}else{if(k===F.position.INSIDE){L(m).append(S);S.show()}else{S.hide()}}}}else{S.hide()}}}};function W(i){i.addClass(Q.cssClasses.defaultStyle);i.ariaState("grab","supported");i.mouseover(function(){var j=L(Z.grabHandle(i[0]));j.addClass(Q.cssClasses.hover)});i.mouseout(function(){var j=L(Z.grabHandle(i[0]));j.removeClass(Q.cssClasses.hover)});i.draggable({refreshPositions:true,scroll:true,helper:function(){var j=L(O(i[0]));j.addClass(Q.cssClasses.avatar);j.attr("id",E.createAvatarId(Q.domNode.id));return j},start:function(k,j){i.focus();i.removeClass(Q.cssClasses.selected);i.addClass(Q.cssClasses.dragging);i.ariaState("grab","true");S=L(document.createElement(i[0].tagName));S.addClass(Q.cssClasses.dropMarker);S.hide()},stop:function(k,j){i.removeClass(Q.cssClasses.dragging);i.addClass(Q.cssClasses.selected);L(Q.activeItem).ariaState("grab","supported");S.remove();j.helper=null;M=null},handle:Z.grabHandle(i[0])})}function f(j,i){j.ariaState("dropeffect","move");j.droppable({accept:i,greedy:true,tolerance:"pointer",over:function(l,k){M=k.element},drop:function(l,k){U.mouseMoveItem(k.draggable[0],j[0],l.clientX,l.pageY);Q.activeItem.focus()}})}var c=function(j){var m=function(i){J(L(this),Q.cssClasses);return i.stopPropagation()};var n=function(i){Q.selectItem(this);return i.stopPropagation()};for(var k=0;k<j.length;k++){var l=L(j[k]);l.tabindex("-1");l.blur(m);l.focus(n);l.ariaRole(h.item);l.ariaState("selected","false");l.ariaState("disabled","false")}};var V=function(){var j;var n=F.wrap(Z.movables());var m=F.wrap(Z.dropTargets());c(F.wrap(Z.selectables()));for(j=0;j<n.length;j++){var l=n[j];W(L(l))}var k=function(i){return(n.index(i[0])>-1)};for(j=0;j<m.length;j++){f(L(m[j]),k)}};if(this.domNode){H(this.domNode,Q.focusActiveItem,Q.handleKeyDown,Q.handleKeyUp,T(Z.dropTargets()));K(this.domNode,Z,h);if(!this.domNode.hasTabindex()||(this.domNode.tabindex()<0)){this.domNode.tabindex("0")}V()}};F.Reorderer.prototype.selectItem=function(N){if(this.activeItem&&this.activeItem!==N){J(L(this.activeItem),this.cssClasses)}this.activeItem=N;var M=L(N);M.removeClass(this.cssClasses.defaultStyle);M.addClass(this.cssClasses.selected);M.ariaState("selected","true");this.domNode.ariaState("activedescendent",N.id)}})(jQuery,fluid);(function(D,C){var B=function(H,G,F,J){var I=F;if(G.hasWrapped){I=J}if(I===C.position.AFTER){D(G.item).after(H)}else{D(G.item).before(H)}};var E=function(K,G,F,J){var H;var I;if(G===C.orientation.VERTICAL){H=D(K).offset().top+(K.offsetHeight/2);I=J<H}else{H=D(K).offset().left+(K.offsetWidth/2);I=F<H}return(I?C.position.BEFORE:C.position.AFTER)};var A={getSiblingInfo:function(H,G,J){var F=D(G).index(H)+J;var I=false;if(F===-1){F=G.length-1;I=true}else{if(F===G.length){F=0;I=true}else{if(F<-1||F>G.length){F=0}}}return{item:G[F],hasWrapped:I}},getRightSiblingInfo:function(G,F){return this.getSiblingInfo(G,F,C.direction.NEXT)},getLeftSiblingInfo:function(G,F){return this.getSiblingInfo(G,F,C.direction.PREVIOUS)},getItemInfoBelow:function(L,F){var J=D(L).offset();var H,I;var K,G;for(H=0;H<F.length;H++){G=F[H];I=D(F[H]).offset();if(I.left===J.left){K=K||G;if(I.top>J.top){return{item:G,hasWrapped:false}}}}K=K||F[0];return{item:K,hasWrapped:true}},getItemInfoAbove:function(L,G){var K=D(L).offset();var I,J;var F,H;for(I=G.length-1;I>-1;I--){H=G[I];J=D(G[I]).offset();if(J.left===K.left){F=F||H;if(K.top>J.top){return{item:H,hasWrapped:false}}}}F=F||G[0];return{item:F,hasWrapped:true}}};C.ListLayoutHandler=function(H,I){H=C.utils.adaptFindItems(H);var G=function(){};var F=C.orientation.VERTICAL;if(I){G=I.orderChangedCallback||G;F=I.orientation||F}this.getRightSibling=function(J){return A.getRightSiblingInfo(J,H.selectables()).item};this.moveItemRight=function(K){var J=A.getRightSiblingInfo(K,H.movables());B(K,J,C.position.AFTER,C.position.BEFORE);G()};this.getLeftSibling=function(J){return A.getLeftSiblingInfo(J,H.selectables()).item};this.moveItemLeft=function(K){var J=A.getLeftSiblingInfo(K,H.movables());B(K,J,C.position.BEFORE,C.position.AFTER);G()};this.getItemBelow=this.getRightSibling;this.getItemAbove=this.getLeftSibling;this.moveItemUp=this.moveItemLeft;this.moveItemDown=this.moveItemRight;this.dropPosition=function(L,K,J,M){return E(L,F,J,M)};this.mouseMoveItem=function(K,M,J,N){var L=this.dropPosition(M,K,J,N);if(L===C.position.BEFORE){D(M).before(K)}else{if(L===C.position.AFTER){D(M).after(K)}}G()}};C.GridLayoutHandler=function(H,I){C.ListLayoutHandler.call(this,H,I);H=C.utils.adaptFindItems(H);var G=function(){};if(I){G=I.orderChangedCallback||G}var F=C.orientation.HORIZONTAL;this.getItemBelow=function(J){return A.getItemInfoBelow(J,H.selectables()).item};this.moveItemDown=function(K){var J=A.getItemInfoBelow(K,H.movables());B(K,J,C.position.AFTER,C.position.BEFORE);G()};this.getItemAbove=function(J){return A.getItemInfoAbove(J,H.selectables()).item};this.moveItemUp=function(K){var J=A.getItemInfoAbove(K,H.movables());B(K,J,C.position.BEFORE,C.position.AFTER);G()};this.dropPosition=function(L,K,J,M){return E(L,F,J,M)}};C.ModuleLayoutHandler=function(L,J,O){var G=C.orientation.VERTICAL;var N=function(){};if(O){if(O.orderChangedCallbackUrl){N=function(){D.post(O.orderChangedCallbackUrl,JSON.stringify(L),function(P,Q){J=P},"json")}}}var K=function(P,R){var Q=C.moduleLayout.itemAboveBelow(P.id,R,L);return C.utils.jById(Q)[0]};var M=function(P,Q){var R=C.moduleLayout.firstItemInAdjacentColumn(P.id,Q,L);return C.utils.jById(R)[0]};var I=function(R,Q,P){if(!R||!Q||!C.moduleLayout.canMove(R.id,Q.id,P,L,J)){return }if(P===C.position.BEFORE){D(Q).before(R)}else{if(P===C.position.AFTER){D(Q).after(R)}else{D(Q).append(R)}}C.moduleLayout.updateLayout(R.id,Q.id,P,L);N()};var H=function(P,R){var S=C.moduleLayout.findTarget(P.id,R,L,J);var Q=C.utils.jById(S.id)[0];I(P,Q,S.position)};var F=function(P,S){var R=C.moduleLayout.nearestMoveableTarget(P.id,S,L,J);var Q=C.utils.jById(R.id)[0];I(P,Q,R.position)};this.getRightSibling=function(P){return M(P,C.direction.NEXT)};this.moveItemRight=function(P){H(P,C.direction.NEXT)};this.getLeftSibling=function(P){return M(P,C.direction.PREVIOUS)};this.moveItemLeft=function(P){H(P,C.direction.PREVIOUS)};this.getItemAbove=function(P){return K(P,C.direction.PREVIOUS)};this.moveItemUp=function(P){F(P,C.direction.PREVIOIUS)};this.getItemBelow=function(P){return K(P,C.direction.NEXT)};this.moveItemDown=function(P){F(P,C.direction.NEXT)};this.dropPosition=function(T,R,Q,U){if(C.moduleLayout.isColumn(T.id,L)){return C.position.INSIDE}var P=E(T,G,Q,U);var S=C.moduleLayout.canMove(R.id,T.id,P,L,J);if(S){return P}else{return C.position.NO_TARGET}};this.mouseMoveItem=function(Q,R,P,T){var S=this.dropPosition(R,Q,P,T);if(S!==C.position.NO_TARGET){I(Q,R,S)}}}})(jQuery,fluid);fluid.moduleLayout=function(C,B){var A={layoutWalker:function(G,H){for(var E=0;E<H.columns.length;E++){var I=H.columns[E].children;for(var F=0;F<I.length;F++){var D=G(I,F,E);if(D){return D}}}},findColumnAndItemIndices:function(G,E){var D=function(J,I,H){if(J[I]===G){return{columnIndex:H,itemIndex:I}}};var F=A.layoutWalker(D,E);return F||{columnIndex:-1,itemIndex:-1}},findColIndex:function(F,E){for(var D=0;D<E.columns.length;D++){if(F===E.columns[D].id){return D}}return -1},findItemIndex:function(E,D){return A.findColumnAndItemIndices(E,D).itemIndex},numColumns:function(D){return D.columns.length},isColumnIndex:function(D,E){return(D<E.columns.length)&&(D>=0)},findItemAndTargetIndices:function(L,M,H,K){var D=K.columns;var J={itemIndex:-1,targetIndex:-1};if(!L||!M){return J}var F=0;var O=H;for(var G=0;G<D.length;G++){var N=D[G].children;for(var E=0;E<N.length;E++){var I=N[E];if(I===L){J.itemIndex=F}if(I===M){J.targetIndex=O}if(J.itemIndex>=0&&J.targetIndex>=0){return J}F++;O++}O++}return J},nearestNextMoveableTarget:function(H,G,J){var E={id:H,position:B.position.AFTER};var K=false;var I=A.findColumnAndItemIndices(H,G);if(I.columnIndex<0){K=true}if(!K){var L=G.columns[I.columnIndex].children;for(var F=I.itemIndex+1;(F<L.length)&&!K;F++){var D=L[F];if((K=B.moduleLayout.canMove(H,D,B.position.AFTER,G,J))){E.id=D}}}return E},nearestPreviousMoveableTarget:function(H,G,J){var E={id:H,position:B.position.BEFORE};var K=false;var I=A.findColumnAndItemIndices(H,G);if(I.columnIndex<0){K=true}if(!K){var L=G.columns[I.columnIndex].children;for(var F=I.itemIndex-1;(F>-1)&&!K;F--){var D=L[F];if((K=B.moduleLayout.canMove(H,D,B.position.BEFORE,G,J))){E.id=D}}}return E},getItemAt:function(E,D,F){var I=null;var H=F.columns;if(E>=0&&E<H.length){var G=H[E].children;if(D>=0&&D<G.length){I=G[D]}}return I},canItemMove:function(F,E){var G=E[F];for(var D=0;D<G.length;D++){if(G[D]===1){return true}}return false},isDropTarget:function(F,E){for(var D=0;D<E.length;D++){if(E[D][F]===1||E[D][F+1]===1){return true}}return false}};return{internals:A,isColumn:function(F,E){var D=A.findColIndex(F,E);return(D>-1)},canMove:function(I,H,D,F,E){if(D===B.position.NO_TARGET){return false}if(D===B.position.INSIDE){return true}var G=A.findItemAndTargetIndices(I,H,D,F);return(!!E[G.itemIndex][G.targetIndex])},firstItemInAdjacentColumn:function(G,F,D){var E=function(K,I,H){var M=K[I];if(M===G){var J=H+F;var L=A.getItemAt(J,0,D);while(!L){J=J+F;if(A.isColumnIndex(J,D)){L=A.getItemAt(J,0,D)}else{L=G}}return L}};return A.layoutWalker(E,D)||G},itemAboveBelow:function(G,F,E){var D=function(I,H){if(I[H]===G){var J=H+F;if((J<0)||(J>=I.length)){return G}else{return I[J]}}};return A.layoutWalker(D,E)||G},updateLayout:function(H,F,E,G){if(!H||!F||H===F){return }var D=A.findColumnAndItemIndices(H,G);G.columns[D.columnIndex].children.splice(D.itemIndex,1);var J;if(E===B.position.INSIDE){J=G.columns[A.findColIndex(F,G)].children;J.splice(J.length,0,H)}else{var I=A.findColumnAndItemIndices(F,G);J=G.columns[I.columnIndex].children;J.splice(I.itemIndex+E,0,H)}},findTarget:function(G,I,F,J){var H=A.findColumnAndItemIndices(G,F).columnIndex+I;var D=F.columns[H];if(H<0||H>=A.numColumns(F)){return{id:G,position:B.position.BEFORE}}var L=D.children;for(var E=0;(E<L.length);E++){var K=L[E];if(B.moduleLayout.canMove(G,K,B.position.BEFORE,F,J)){return{id:K,position:B.position.BEFORE}}else{if(B.moduleLayout.canMove(G,K,B.position.AFTER,F,J)){return{id:K,position:B.position.AFTER}}}}return{id:D.id,position:B.position.INSIDE}},nearestMoveableTarget:function(G,F,E,D){if(F===B.direction.NEXT){return A.nearestNextMoveableTarget(G,E,D)}else{return A.nearestPreviousMoveableTarget(G,E,D)}},createFindItems:function(K,O,R){var F={};F.grabHandle=R;var I;var D;var M;var N=K.columns;for(var J=0;J<N.length;J++){var Q=N[J].children;for(var H=0;H<Q.length;H++){var L=Q[H];var G="[id="+L+"]";I=I?I+","+G:G;var P=A.findItemAndTargetIndices(L,L,B.position.BEFORE,K);if(A.canItemMove(P.itemIndex,O)){D=D?D+","+G:G}if(A.isDropTarget(P.targetIndex,O)){M=M?M+","+G:G}}var E="[id="+N[J].id+"]";M=M?M+","+E:E}F.selectables=function(){return C(I)};F.movables=function(){return C(D)};F.dropTargets=function(){return C(M)};return F},containerId:function(D){return D.id}}}(jQuery,fluid);var fluid=fluid||{};(function(A){A.initLayoutCustomizer=function(C,G,J,D){var H=A.utils.jById(A.moduleLayout.containerId(C));var F=A.moduleLayout.createFindItems(C,G,J);var E;if(D){E={orderChangedCallbackUrl:D}}var I=new A.ModuleLayoutHandler(C,G,E);var B={role:A.roles.GRID,avatarCreator:function(K){return document.createElement("div")}};return new A.Reorderer(H,F,I,B)}})(fluid);var fluid=fluid||{};(function(D,A){var B=function(F,G){return F+"lightbox-cell:"+G+":"};var E=function(G){var F=function(H){if(H.which===fluid.keys.ENTER){var I=D("a",H.target);A.location=I.attr("href")}};D(G).keypress(F)};var C=function(F,G){var H="^"+B(G,"[0-9]+")+"$";return function(){return fluid.utils.seekNodesById(F,"div",H)}};fluid.lightbox={defaultOrderChangedCallback:function(G){var F=fluid.utils.findForm(G);return function(){var H=fluid.utils.seekNodesById(F,"input","^"+B(G.id,"[^:]*")+"reorder-index$");for(var I=0;I<H.length;I=I+1){H[I].value=I}if(F&&F.action){D.post(F.action,D(F).serialize(),function(K,L,J){})}}},createLightbox:function(G,F,K,J,I){D("a",G).tabindex(-1);E(G);var H=new fluid.GridLayoutHandler(F,{orderChangedCallback:K});var L={instructionMessageId:J,role:fluid.roles.GRID};fluid.mixin(L,I);return new fluid.Reorderer(G,F,H,L)},createLightboxFromIds:function(G,I){var F=A.getElementById(G);var J=C(F,G);var H=fluid.lightbox.defaultOrderChangedCallback(F);return fluid.lightbox.createLightbox(F,J,H,I)}}})(jQuery,document);var fluid=fluid||{};var swfObj={};(function(g,c){var j={};var Z=Z||{};var V={uploadUrl:"",flashUrl:"",fileSizeLimit:"20480",fileTypes:"*.*",fileTypesText:"image files",fileUploadLimit:0,fileQueueLimit:0,elmUploader:"#single-inline-fluid-uploader",elmUploaderControl:"",whenDone:"",whenCancel:"",postParams:{},httpUploadElm:"",continueAfterUpload:true,dialogDisplay:false,queueListMaxHeight:200,debug:false};var D={elmUploadContainer:".fluid-uploader",elmUpload:".fluid-uploader-upload",elmPause:".fluid-uploader-pause",elmBrowse:".fluid-uploader-browse",elmDone:".fluid-uploader-done",elmCancel:".fluid-uploader-cancel",elmFileQueue:".fluid-uploader-queue",elmEmptyRow:".fluid-uploader-row-placeholder",txtTotalFiles:".fluid-uploader-totalFiles",txtTotalBytes:".fluid-uploader-totalBytes",osModifierKey:".fluid-uploader-modifierKey",txtFileStatus:".fileStatus",progress:".fluid-progress",fileProgress:".file-progress",totalProgress:".total-progress"};var f={totalBytes:0,totalCount:0,currCount:0,currTotalBytes:0,currError:"",stop:false};var b={macControlKey:"Command",browseText:"Browse"+unescape("%u2026"),addMoreText:"Browse"+unescape("%u2026"),fileUploaded:"File Uploaded"};var O=function(p){p.fadeOut("fast",function(){var q=p.attr("id");var r=swfObj.getFile(q);k(-r.size);f.totalCount--;swfObj.cancelUpload(q);p.remove();G();n();Q();S()});return p};var G=function(){g(D.txtTotalFiles).text(T())};var Q=function(){g(D.txtTotalBytes).text(a(k()))};var n=function(p){if(p===undefined){p=(o()>0)?"loaded":"empty"}g(Z.elmUploader+" > div").attr("className",p)};var S=function(){if(f.totalCount>0){g(D.elmBrowse).text(b.addMoreText)}else{g(D.elmBrowse).text(b.browseText)}};var U=function(p){p.addClass("dim");I(p,b.fileUploaded)};var I=function(q,p){g(q).children(D.txtFileStatus).text(p)};var Y=function(p){if(p!==undefined){if(typeof p==="function"){p()}else{location.href=p}}};var F=function(){swfObj.startUpload()};function R(q){try{k(q.size);var r=g('<tr id="'+q.id+'"><td class="fileName">'+q.name+'</td><td class="fileSize">'+a(q.size)+'</td><td class="fileStatus">Ready to Upload</td><td class="fileRemove"><button type="button" class="removeFileBtn" /></td></tr>');g(r).css("display","none").hover(function(){if(!g(this).hasClass("dim")){g(this).addClass("hover")}},function(){if(!g(this).hasClass("dim")){g(this).removeClass("hover")}});g(r).insertBefore(D.elmEmptyRow);g("#"+q.id+" .removeFileBtn").click(function(){O(g(this).parents("tr"))});g("#"+q.id).fadeIn("slow");if(g(".fluid-uploader-queue tbody").height()>Z.queueListMaxHeight){g(".fluid-uploader-queue tbody").height(Z.queueListMaxHeight)}n();G();Q()}catch(p){this.debug(p)}}function A(){try{}catch(p){this.debug(p)}}function X(r,q){try{f.currCount=0;f.currTotalBytes=0;f.totalCount=T();S();l()}catch(p){this.debug(p)}}function d(r,p,s){try{var u="";switch(p){case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED:u="QUEUE LIMIT EXCEEDED";break;case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:u="FILE EXCEEDS SIZE LIMIT";break;case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:u="ZERO BYTE FILE";break;case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:u="INVALID FILE TYPE";break;default:u="UNKNOWN";break}var t=u+":File ID: "+(typeof (r)==="object"&&r!==null?r.id:"na")+":"+s;debug("error_string = "+t)}catch(q){this.debug(q)}}var H=function(p){f.currError="";f.currCount++;L(0,p.name,0,f.currCount,f.totalCount);debug("Starting Upload: "+f.currCount+" ("+p.id+") ["+p.size+"] "+p.name+"")};var M=function(r,p,s){f.currError="";try{switch(p){case SWFUpload.UPLOAD_ERROR.HTTP_ERROR:f.currError="Error Code: HTTP Error, File name: "+r.name+", Message: "+s;break;case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED:f.currError="Error Code: Upload Failed, File name: "+r.name+", File size: "+r.size+", Message: "+s;break;case SWFUpload.UPLOAD_ERROR.IO_ERROR:f.currError="Error Code: IO Error, File name: "+r.name+", Message: "+s;break;case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR:f.currError="Error Code: Security Error, File name: "+r.name+", Message: "+s;break;case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:f.currError="Error Code: Upload Limit Exceeded, File name: "+r.name+", File size: "+r.size+", Message: "+s;break;case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED:f.currError="Error Code: File Validation Failed, File name: "+r.name+", File size: "+r.size+", Message: "+s;break;case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:if(this.getStats().files_queued===0){document.getElementById(this.customSettings.cancelButtonId).disabled=true}progress.SetStatus("Cancelled");progress.SetCancelled();break;case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:f.currError="Upload Stopped by user input";progress.SetStatus("Stopped");h(true);break;default:progress.SetStatus("Unhandled Error: "+p);f.currError="Error Code: "+p+", File name: "+r.name+", File size: "+r.size+", Message: "+s;break}debug(f.currError)}catch(q){this.debug(q)}};var P=function(q,p,r){debug("File Status :: bytes = "+p+" :: totalBytes = "+r);debug("Total Status :: currBytes = "+(f.currTotalBytes+p)+" :: totalBytes = "+k());L(N(p,r),q.name,N(f.currTotalBytes+p,k()),f.currCount,f.totalCount)};var C=function(p){if(!f.currError){if((p.index+1)==f.totalCount){L(100,p.name,100,f.totalCount,f.totalCount);E()}else{f.currTotalBytes+=p.size;L(100,p.name);swfObj.startUpload()}U(g("tr#"+p.id))}else{debug(f.currError);h(true)}};var E=function(){n("done");h(false);if(Z.continueAfterUpload){Y(Z.whenDone)}};var k=function(p){if(typeof p=="number"){f.totalBytes+=p}return f.totalBytes};var J=function(){if(navigator.appVersion.indexOf("Win")!=-1){return"Windows"}if(navigator.appVersion.indexOf("Mac")!=-1){return"MacOS"}if(navigator.appVersion.indexOf("X11")!=-1){return"UNIX"}if(navigator.appVersion.indexOf("Linux")!=-1){return"Linux"}else{return"unknown"}};function T(){return o()-B()}function o(){return g('.fluid-uploader-queue tbody tr:not(".fluid-uploader-row-placeholder")').length}function B(){return g(".fluid-uploader-queue tbody tr.dim").length}function N(p,q){return Math.round((p*100)/q)}function a(p){return Math.round(p/1028)+" KB"}var L=function(u,v,p,r,s){var q='<span class="file_name">'+v+'</span> :: <span class="percent">'+u+"</span>% complete";c.Progress.update(D.progress,D.fileProgress,u,q);if(p){var t='Total Progress: <span class="percent">'+p+'</span>% [<span class="file_index">'+r+'</span> of <span class="total_file_num">'+s+"</span> files]";c.Progress.update(D.progress,D.totalProgress,p,t)}};var h=function(p){p=(p)?true:false;c.Progress.hide(D.progress,p)};function l(){debug("\n status.totalBytes = "+k()+"\n status.totalCount = "+f.totalCount+"\n status.currCount = "+f.currCount+"\n status.currTotalBytes = "+f.currTotalBytes+"\n status.currError = "+f.currError)}var W={};var e=function(){debug(T());if(f.stop===true){k(-f.currTotalBytes);Q();G();K()}else{if(T()){W.bytes=0;W.byteChunk=200000;W.row=g('.fluid-uploader-queue tbody tr:not(".fluid-uploader-placeholder"):not(".dim)').eq(0);W.fileId=jQuery(W.row).attr("id");W.fileObj=swfObj.getFile(W.fileId);W.bytes=0;W.totalBytes=W.fileObj.size;W.numChunks=Math.ceil(W.totalBytes/W.byteChunk);debug("DEMO :: "+W.fileId+" :: totalBytes = "+W.totalBytes+" numChunks = "+W.numChunks);H(W.fileObj);m()}else{E()}}};var m=function(){if(f.stop===true){K()}else{var p=Math.floor(Math.random()*5000+1)>1;var q=(W.bytes+W.byteChunk);if(q<W.totalBytes){debug("tmpBytes = "+q+" totalBytes = "+W.totalBytes);P(W.fileObj,q,W.totalBytes);W.bytes=q;var r=setTimeout(m,p)}else{P(W.fileObj,W.totalBytes,W.totalBytes);var s=setTimeout(i,p)}}};function i(){var q=g("tr#"+W.fileObj.id);U(q);f.currTotalBytes+=W.fileObj.size;G();Q();var p=setTimeout(e,1200)}function K(){h(true);f.stop=false;f.currCount=0;f.currTotalBytes=0;f.totalCount=T()}c.uploader={};c.uploader.init=function(q){Z=g.extend({},V,q);var p={upload_url:Z.uploadUrl,flash_url:Z.flashUrl,post_params:Z.postParams,file_size_limit:Z.fileSizeLimit,file_types:Z.fileTypes,file_types_description:Z.fileTypesDescription,file_upload_limit:Z.fileUploadLimit,file_queue_limit:Z.fileQueueLimit,file_dialog_start_handler:A,file_queued_handler:R,file_queue_error_handler:d,file_dialog_complete_handler:X,upload_start_handler:H,upload_progress_handler:P,upload_complete_handler:C,upload_error_handler:M,debug:Z.debug};if(typeof (SWFUpload)==="undefined"){return }swfObj=new SWFUpload(p);if(J()=="MacOS"){g(D.osModifierKey).text(b.macControlKey)}g(D.elmBrowse).click(function(){if(Z.fileQueueLimit===1){return swfObj.selectFile()}else{return swfObj.selectFiles()}});g(D.elmUpload).click(function(){if(f.totalCount>0){F()}});g(D.elmPause).click(function(){swfObj.stopUpload()});g(D.elmDone).click(function(){Y(Z.whenDone)});g(D.elmCancel).click(function(){Y(Z.whenCancel)});if(Z.uploadUrl===""){swfObj.startUpload=function(){e()};swfObj.stopUpload=function(){f.stop=true}}};c.uploader.test=function(){var p="";for(key in Z){p+=key+" = "+Z[key]+"\n"}for(key in D){p+=key+" = "+D[key]+"\n"}debug(p)}})(jQuery,fluid);fluid.Progress=function(C){var A=0;C(document).ready(function(){C(".progress-mask").css("opacity",0.8);C(".progress-mask-btm").height(C(".fluid-progress").height()-14)});function B(E,D){E.animate({width:D,queue:false},200)}return{update:function(F,J,H,I,K){var E=H+"%";var D=C(F+" "+J+" .progress-label");var G=C(F+" "+J+" .progress-indicator");if(K){var L=C(F+" "+J+" .progress-text");L.html(K)}if(C(F).css("display")==="none"){C(F).fadeIn("slow")}debug("percent = "+H+" lastPercent = "+A);D.html(I);G.queue("fx",[]);if(H===0){G.width(1)}else{if(H<A){G.width(E)}else{G.animate({width:E,queue:false},200)}}A=H},hide:function(G,D){var F=1600;if(D){C(G).fadeOut("slow")}else{var E=setTimeout("fluid.Progress.hide('"+G+"',"+true+")",F)}},show:function(D){C(D).fadeIn("slow")}}}(jQuery);function debug(A){if(window.console){console.log(A)}}if(!this.JSON){JSON=function(){function f(n){return n<10?"0"+n:n}Date.prototype.toJSON=function(){return this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z"};var m={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};function stringify(value,whitelist){var a,i,k,l,r=/["\\\x00-\x1f\x7f-\x9f]/g,v;switch(typeof value){case"string":return r.test(value)?'"'+value.replace(r,function(a){var c=m[a];if(c){return c}c=a.charCodeAt();return"\\u00"+Math.floor(c/16).toString(16)+(c%16).toString(16)})+'"':'"'+value+'"';case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}if(typeof value.toJSON==="function"){return stringify(value.toJSON())}a=[];if(typeof value.length==="number"&&!(value.propertyIsEnumerable("length"))){l=value.length;for(i=0;i<l;i+=1){a.push(stringify(value[i],whitelist)||"null")}return"["+a.join(",")+"]"}if(whitelist){l=whitelist.length;for(i=0;i<l;i+=1){k=whitelist[i];if(typeof k==="string"){v=stringify(value[k],whitelist);if(v){a.push(stringify(k)+":"+v)}}}}else{for(k in value){if(typeof k==="string"){v=stringify(value[k],whitelist);if(v){a.push(stringify(k)+":"+v)}}}}return"{"+a.join(",")+"}"}}return{stringify:stringify,parse:function(text,filter){var j;function walk(k,v){var i,n;if(v&&typeof v==="object"){for(i in v){if(Object.prototype.hasOwnProperty.apply(v,[i])){n=walk(i,v[i]);if(n!==undefined){v[i]=n}}}}return filter(k,v)}if(/^[\],:{}\s]*$/.test(text.replace(/\\./g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof filter==="function"?walk("",j):j}throw new SyntaxError("parseJSON")}}}()};
\ No newline at end of file
diff --git a/jscripts/fluid-atutor.js b/jscripts/fluid-atutor.js
new file mode 100644 (file)
index 0000000..e505db6
--- /dev/null
@@ -0,0 +1,28 @@
+var demo = demo || {};
+
+demo.initMyLayout = function (basepath) {
+       var myLayoutContainer = fluid.utils.jById ("contentwrapper");
+       
+       var myOrderableFinder = function () {
+       return jQuery ("div[id^=atutor]", myLayoutContainer);
+       };
+       
+       var myGrabHandleFinder = function (item) {
+               return jQuery ("[id='toolbar." + item.id.split(".")[1] + "']");
+       };      
+       
+       var findItems = {movables: myOrderableFinder, 
+               grabHandle: myGrabHandleFinder
+       }
+       var layoutHandler = new fluid.GridLayoutHandler (myOrderableFinder, { 
+               orderChangedCallback : function(){ 
+                       //save the state to the db
+                       var myDivs = jQuery ("div[id^=atutor]", myLayoutContainer);
+                       jQuery.post(basepath+"themes/fluid/save_state.php", { 'left':myDivs[0].id },
+                               function(data) { 
+                                       //alert(data);
+                               });     
+               } });
+       
+       return new fluid.Reorderer (myLayoutContainer, findItems, layoutHandler);
+};
diff --git a/jscripts/fluid/Fluid.js b/jscripts/fluid/Fluid.js
new file mode 100644 (file)
index 0000000..53b8479
--- /dev/null
@@ -0,0 +1 @@
+var fluid=fluid||{};(function(B,A){A.keys={TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,META:19,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,i:73,j:74,k:75,m:77};A.roles={GRID:{container:"grid",item:"gridcell"},LIST:{container:"list",item:"listitem"}};A.orientation={HORIZONTAL:"horiz",VERTICAL:"vert"};A.position={BEFORE:0,AFTER:1,INSIDE:2,NO_TARGET:-1};A.direction={NEXT:1,PREVIOUS:-1};A.defaultKeysets=[{modifier:function(C){return C.ctrlKey},up:A.keys.UP,down:A.keys.DOWN,right:A.keys.RIGHT,left:A.keys.LEFT},{modifier:function(C){return C.ctrlKey},up:A.keys.i,down:A.keys.m,right:A.keys.k,left:A.keys.j}];A.mixin=function(E,D){for(var C in D){if(D.hasOwnProperty(C)){E[C]=D[C]}}};A.wrap=function(C){return((!C||C.jquery)?C:B(C))};A.utils={};A.utils.seekNodesById=function(G,I,E){var C=G.getElementsByTagName(I);var H=[];for(var F=0;F<C.length;++F){var D=C[F];var J=D.id;if(J&&J.match(E)){H.push(D)}}return H};A.utils.escapeSelector=function(C){return C.replace(/\:/g,"\\:")};A.utils.findForm=function(C){while(C){if(C.nodeName.toLowerCase()==="form"){return C}C=C.parentNode}};A.utils.adaptFindItems=function(D){var E=function(){};var C={};if(typeof D==="function"){E=D}else{C=D}C.movables=C.movables||E;C.selectables=C.selectables||C.movables;C.dropTargets=C.dropTargets||C.movables;C.grabHandle=C.grabHandle||function(F){return F};return C};A.utils.jById=function(C){return B("[id="+C+"]")}})(jQuery,fluid);
\ No newline at end of file
diff --git a/jscripts/fluid/LayoutCustomizer.js b/jscripts/fluid/LayoutCustomizer.js
new file mode 100644 (file)
index 0000000..4b8e9e3
--- /dev/null
@@ -0,0 +1 @@
+var fluid=fluid||{};(function(A){A.initLayoutCustomizer=function(C,G,J,D){var H=A.utils.jById(A.moduleLayout.containerId(C));var F=A.moduleLayout.createFindItems(C,G,J);var E;if(D){E={orderChangedCallbackUrl:D}}var I=new A.ModuleLayoutHandler(C,G,E);var B={role:A.roles.GRID,avatarCreator:function(K){return document.createElement("div")}};return new A.Reorderer(H,F,I,B)}})(fluid);
\ No newline at end of file
diff --git a/jscripts/fluid/Lightbox.js b/jscripts/fluid/Lightbox.js
new file mode 100644 (file)
index 0000000..bfef791
--- /dev/null
@@ -0,0 +1 @@
+var fluid=fluid||{};(function(D,A){var B=function(F,G){return F+"lightbox-cell:"+G+":"};var E=function(G){var F=function(H){if(H.which===fluid.keys.ENTER){var I=D("a",H.target);A.location=I.attr("href")}};D(G).keypress(F)};var C=function(F,G){var H="^"+B(G,"[0-9]+")+"$";return function(){return fluid.utils.seekNodesById(F,"div",H)}};fluid.lightbox={defaultOrderChangedCallback:function(G){var F=fluid.utils.findForm(G);return function(){var H=fluid.utils.seekNodesById(F,"input","^"+B(G.id,"[^:]*")+"reorder-index$");for(var I=0;I<H.length;I=I+1){H[I].value=I}if(F&&F.action){D.post(F.action,D(F).serialize(),function(K,L,J){})}}},createLightbox:function(G,F,K,J,I){D("a",G).tabindex(-1);E(G);var H=new fluid.GridLayoutHandler(F,{orderChangedCallback:K});var L={instructionMessageId:J,role:fluid.roles.GRID};fluid.mixin(L,I);return new fluid.Reorderer(G,F,H,L)},createLightboxFromIds:function(G,I){var F=A.getElementById(G);var J=C(F,G);var H=fluid.lightbox.defaultOrderChangedCallback(F);return fluid.lightbox.createLightbox(F,J,H,I)}}})(jQuery,document);
\ No newline at end of file
diff --git a/jscripts/fluid/MultiFileUpload.js b/jscripts/fluid/MultiFileUpload.js
new file mode 100644 (file)
index 0000000..b0d8d45
--- /dev/null
@@ -0,0 +1 @@
+var fluid=fluid||{};var swfObj={};(function(g,c){var j={};var Z=Z||{};var V={uploadUrl:"",flashUrl:"",fileSizeLimit:"20480",fileTypes:"*.*",fileTypesText:"image files",fileUploadLimit:0,fileQueueLimit:0,elmUploader:"#single-inline-fluid-uploader",elmUploaderControl:"",whenDone:"",whenCancel:"",postParams:{},httpUploadElm:"",continueAfterUpload:true,dialogDisplay:false,queueListMaxHeight:200,debug:false};var D={elmUploadContainer:".fluid-uploader",elmUpload:".fluid-uploader-upload",elmPause:".fluid-uploader-pause",elmBrowse:".fluid-uploader-browse",elmDone:".fluid-uploader-done",elmCancel:".fluid-uploader-cancel",elmFileQueue:".fluid-uploader-queue",elmEmptyRow:".fluid-uploader-row-placeholder",txtTotalFiles:".fluid-uploader-totalFiles",txtTotalBytes:".fluid-uploader-totalBytes",osModifierKey:".fluid-uploader-modifierKey",txtFileStatus:".fileStatus",progress:".fluid-progress",fileProgress:".file-progress",totalProgress:".total-progress"};var f={totalBytes:0,totalCount:0,currCount:0,currTotalBytes:0,currError:"",stop:false};var b={macControlKey:"Command",browseText:"Browse"+unescape("%u2026"),addMoreText:"Browse"+unescape("%u2026"),fileUploaded:"File Uploaded"};var O=function(p){p.fadeOut("fast",function(){var q=p.attr("id");var r=swfObj.getFile(q);k(-r.size);f.totalCount--;swfObj.cancelUpload(q);p.remove();G();n();Q();S()});return p};var G=function(){g(D.txtTotalFiles).text(T())};var Q=function(){g(D.txtTotalBytes).text(a(k()))};var n=function(p){if(p===undefined){p=(o()>0)?"loaded":"empty"}g(Z.elmUploader+" > div").attr("className",p)};var S=function(){if(f.totalCount>0){g(D.elmBrowse).text(b.addMoreText)}else{g(D.elmBrowse).text(b.browseText)}};var U=function(p){p.addClass("dim");I(p,b.fileUploaded)};var I=function(q,p){g(q).children(D.txtFileStatus).text(p)};var Y=function(p){if(p!==undefined){if(typeof p==="function"){p()}else{location.href=p}}};var F=function(){swfObj.startUpload()};function R(q){try{k(q.size);var r=g('<tr id="'+q.id+'"><td class="fileName">'+q.name+'</td><td class="fileSize">'+a(q.size)+'</td><td class="fileStatus">Ready to Upload</td><td class="fileRemove"><button type="button" class="removeFileBtn" /></td></tr>');g(r).css("display","none").hover(function(){if(!g(this).hasClass("dim")){g(this).addClass("hover")}},function(){if(!g(this).hasClass("dim")){g(this).removeClass("hover")}});g(r).insertBefore(D.elmEmptyRow);g("#"+q.id+" .removeFileBtn").click(function(){O(g(this).parents("tr"))});g("#"+q.id).fadeIn("slow");if(g(".fluid-uploader-queue tbody").height()>Z.queueListMaxHeight){g(".fluid-uploader-queue tbody").height(Z.queueListMaxHeight)}n();G();Q()}catch(p){this.debug(p)}}function A(){try{}catch(p){this.debug(p)}}function X(r,q){try{f.currCount=0;f.currTotalBytes=0;f.totalCount=T();S();l()}catch(p){this.debug(p)}}function d(r,p,s){try{var u="";switch(p){case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED:u="QUEUE LIMIT EXCEEDED";break;case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:u="FILE EXCEEDS SIZE LIMIT";break;case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:u="ZERO BYTE FILE";break;case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:u="INVALID FILE TYPE";break;default:u="UNKNOWN";break}var t=u+":File ID: "+(typeof (r)==="object"&&r!==null?r.id:"na")+":"+s;debug("error_string = "+t)}catch(q){this.debug(q)}}var H=function(p){f.currError="";f.currCount++;L(0,p.name,0,f.currCount,f.totalCount);debug("Starting Upload: "+f.currCount+" ("+p.id+") ["+p.size+"] "+p.name+"")};var M=function(r,p,s){f.currError="";try{switch(p){case SWFUpload.UPLOAD_ERROR.HTTP_ERROR:f.currError="Error Code: HTTP Error, File name: "+r.name+", Message: "+s;break;case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED:f.currError="Error Code: Upload Failed, File name: "+r.name+", File size: "+r.size+", Message: "+s;break;case SWFUpload.UPLOAD_ERROR.IO_ERROR:f.currError="Error Code: IO Error, File name: "+r.name+", Message: "+s;break;case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR:f.currError="Error Code: Security Error, File name: "+r.name+", Message: "+s;break;case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:f.currError="Error Code: Upload Limit Exceeded, File name: "+r.name+", File size: "+r.size+", Message: "+s;break;case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED:f.currError="Error Code: File Validation Failed, File name: "+r.name+", File size: "+r.size+", Message: "+s;break;case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:if(this.getStats().files_queued===0){document.getElementById(this.customSettings.cancelButtonId).disabled=true}progress.SetStatus("Cancelled");progress.SetCancelled();break;case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:f.currError="Upload Stopped by user input";progress.SetStatus("Stopped");h(true);break;default:progress.SetStatus("Unhandled Error: "+p);f.currError="Error Code: "+p+", File name: "+r.name+", File size: "+r.size+", Message: "+s;break}debug(f.currError)}catch(q){this.debug(q)}};var P=function(q,p,r){debug("File Status :: bytes = "+p+" :: totalBytes = "+r);debug("Total Status :: currBytes = "+(f.currTotalBytes+p)+" :: totalBytes = "+k());L(N(p,r),q.name,N(f.currTotalBytes+p,k()),f.currCount,f.totalCount)};var C=function(p){if(!f.currError){if((p.index+1)==f.totalCount){L(100,p.name,100,f.totalCount,f.totalCount);E()}else{f.currTotalBytes+=p.size;L(100,p.name);swfObj.startUpload()}U(g("tr#"+p.id))}else{debug(f.currError);h(true)}};var E=function(){n("done");h(false);if(Z.continueAfterUpload){Y(Z.whenDone)}};var k=function(p){if(typeof p=="number"){f.totalBytes+=p}return f.totalBytes};var J=function(){if(navigator.appVersion.indexOf("Win")!=-1){return"Windows"}if(navigator.appVersion.indexOf("Mac")!=-1){return"MacOS"}if(navigator.appVersion.indexOf("X11")!=-1){return"UNIX"}if(navigator.appVersion.indexOf("Linux")!=-1){return"Linux"}else{return"unknown"}};function T(){return o()-B()}function o(){return g('.fluid-uploader-queue tbody tr:not(".fluid-uploader-row-placeholder")').length}function B(){return g(".fluid-uploader-queue tbody tr.dim").length}function N(p,q){return Math.round((p*100)/q)}function a(p){return Math.round(p/1028)+" KB"}var L=function(u,v,p,r,s){var q='<span class="file_name">'+v+'</span> :: <span class="percent">'+u+"</span>% complete";c.Progress.update(D.progress,D.fileProgress,u,q);if(p){var t='Total Progress: <span class="percent">'+p+'</span>% [<span class="file_index">'+r+'</span> of <span class="total_file_num">'+s+"</span> files]";c.Progress.update(D.progress,D.totalProgress,p,t)}};var h=function(p){p=(p)?true:false;c.Progress.hide(D.progress,p)};function l(){debug("\n status.totalBytes = "+k()+"\n status.totalCount = "+f.totalCount+"\n status.currCount = "+f.currCount+"\n status.currTotalBytes = "+f.currTotalBytes+"\n status.currError = "+f.currError)}var W={};var e=function(){debug(T());if(f.stop===true){k(-f.currTotalBytes);Q();G();K()}else{if(T()){W.bytes=0;W.byteChunk=200000;W.row=g('.fluid-uploader-queue tbody tr:not(".fluid-uploader-placeholder"):not(".dim)').eq(0);W.fileId=jQuery(W.row).attr("id");W.fileObj=swfObj.getFile(W.fileId);W.bytes=0;W.totalBytes=W.fileObj.size;W.numChunks=Math.ceil(W.totalBytes/W.byteChunk);debug("DEMO :: "+W.fileId+" :: totalBytes = "+W.totalBytes+" numChunks = "+W.numChunks);H(W.fileObj);m()}else{E()}}};var m=function(){if(f.stop===true){K()}else{var p=Math.floor(Math.random()*5000+1)>1;var q=(W.bytes+W.byteChunk);if(q<W.totalBytes){debug("tmpBytes = "+q+" totalBytes = "+W.totalBytes);P(W.fileObj,q,W.totalBytes);W.bytes=q;var r=setTimeout(m,p)}else{P(W.fileObj,W.totalBytes,W.totalBytes);var s=setTimeout(i,p)}}};function i(){var q=g("tr#"+W.fileObj.id);U(q);f.currTotalBytes+=W.fileObj.size;G();Q();var p=setTimeout(e,1200)}function K(){h(true);f.stop=false;f.currCount=0;f.currTotalBytes=0;f.totalCount=T()}c.uploader={};c.uploader.init=function(q){Z=g.extend({},V,q);var p={upload_url:Z.uploadUrl,flash_url:Z.flashUrl,post_params:Z.postParams,file_size_limit:Z.fileSizeLimit,file_types:Z.fileTypes,file_types_description:Z.fileTypesDescription,file_upload_limit:Z.fileUploadLimit,file_queue_limit:Z.fileQueueLimit,file_dialog_start_handler:A,file_queued_handler:R,file_queue_error_handler:d,file_dialog_complete_handler:X,upload_start_handler:H,upload_progress_handler:P,upload_complete_handler:C,upload_error_handler:M,debug:Z.debug};if(typeof (SWFUpload)==="undefined"){return }swfObj=new SWFUpload(p);if(J()=="MacOS"){g(D.osModifierKey).text(b.macControlKey)}g(D.elmBrowse).click(function(){if(Z.fileQueueLimit===1){return swfObj.selectFile()}else{return swfObj.selectFiles()}});g(D.elmUpload).click(function(){if(f.totalCount>0){F()}});g(D.elmPause).click(function(){swfObj.stopUpload()});g(D.elmDone).click(function(){Y(Z.whenDone)});g(D.elmCancel).click(function(){Y(Z.whenCancel)});if(Z.uploadUrl===""){swfObj.startUpload=function(){e()};swfObj.stopUpload=function(){f.stop=true}}};c.uploader.test=function(){var p="";for(key in Z){p+=key+" = "+Z[key]+"\n"}for(key in D){p+=key+" = "+D[key]+"\n"}debug(p)}})(jQuery,fluid);fluid.Progress=function(C){var A=0;C(document).ready(function(){C(".progress-mask").css("opacity",0.8);C(".progress-mask-btm").height(C(".fluid-progress").height()-14)});function B(E,D){E.animate({width:D,queue:false},200)}return{update:function(F,J,H,I,K){var E=H+"%";var D=C(F+" "+J+" .progress-label");var G=C(F+" "+J+" .progress-indicator");if(K){var L=C(F+" "+J+" .progress-text");L.html(K)}if(C(F).css("display")==="none"){C(F).fadeIn("slow")}debug("percent = "+H+" lastPercent = "+A);D.html(I);G.queue("fx",[]);if(H===0){G.width(1)}else{if(H<A){G.width(E)}else{G.animate({width:E,queue:false},200)}}A=H},hide:function(G,D){var F=1600;if(D){C(G).fadeOut("slow")}else{var E=setTimeout("fluid.Progress.hide('"+G+"',"+true+")",F)}},show:function(D){C(D).fadeIn("slow")}}}(jQuery);function debug(A){if(window.console){console.log(A)}};
\ No newline at end of file
diff --git a/jscripts/fluid/Reorderer.js b/jscripts/fluid/Reorderer.js
new file mode 100644 (file)
index 0000000..be6db53
--- /dev/null
@@ -0,0 +1 @@
+var fluid=fluid||{};(function(L,F){var D=F.roles.LIST;var B="message-bundle:";var I={defaultStyle:"orderable-default",selected:"orderable-selected",dragging:"orderable-dragging",hover:"orderable-hover",dropMarker:"orderable-drop-marker",avatar:"orderable-avatar"};var A=function(N){var M=L(N).clone();M.removeAttr("id");L("[id]",M).removeAttr("id");L(":hidden",M).remove();L("input",M).attr("disabled","true");M.removeClass("ui-droppable");return M};function G(N){var M=F.wrap(N.selectables());if(M.length<=0){return null}return M[0]}function H(N,O,P,Q,M){N.focus(O);N.keydown(P);N.keyup(Q);N.mousemove(M);if(L.browser.msie){N[0].ondrag=function(){return false};N[0].onselectstart=function(){return false}}}function K(M,N,P){var O=G(N);if(O){M.ariaState("activedescendent",O.id)}M.ariaRole(P.container);M.ariaState("multiselectable","false");M.ariaState("readonly","false");M.ariaState("disabled","false")}function J(M,N){M.removeClass(N.selected);M.addClass(N.defaultStyle);M.ariaState("selected","false")}var E={};E.findTarget=function(N,S,P,R){var M=function(T){return(T&&T.id===P)};var Q=function(T){return((S.index(T)>-1)||M(T))};var O=Q(N)?N:L.grep(L(N).parents(),Q)[0];if(M(O)){O=R?R[0]:null}return O};E.createAvatarId=function(M){return M+"_avatar"};var C=function(N,M){if(M&&!(M instanceof Array)){M=[M]}return M||N};F.Reorderer=function(b,Z,U,R){var Q=this;this.domNode=L(b);this.activeItem=undefined;Z=F.utils.adaptFindItems(Z);R=R||{};var h=R.role||D;var a=R.instructionMessageId||B;var P=C(F.defaultKeysets,R.keysets);this.cssClasses=R.cssClassNames||I;var O=R.avatarCreator||A;this.focusActiveItem=function(i){if(!Q.activeItem){var j=G(Z);if(!j){return i.stopPropagation()}L(j).focus()}else{L(Q.activeItem).focus()}return i.stopPropagation()};var d=function(j){var k=0;for(k;k<P.length;k++){if(P[k].modifier(j)){return true}}return false};var N=function(){return(L.inArray(Q.activeItem,Z.movables())>=0)};this.handleKeyDown=function(i){if(!Q.activeItem||(Q.activeItem!==i.target)){return true}var j=L(Q.activeItem);if(!j.hasClass(Q.cssClasses.dragging)&&d(i)){if(N()){j.removeClass(Q.cssClasses.selected);j.addClass(Q.cssClasses.dragging);j.ariaState("grab","true")}return false}return Q.handleDirectionKeyDown(i)};this.handleKeyUp=function(i){if(!Q.activeItem||(Q.activeItem!==i.target)){return true}var j=L(Q.activeItem);if(j.hasClass(Q.cssClasses.dragging)&&!d(i)){if(N()){j.removeClass(Q.cssClasses.dragging);j.addClass(Q.cssClasses.selected);j.ariaState("grab","supported");return false}}};var e=function(i){if(N()){i(Q.activeItem);Q.activeItem.focus();L(Q.activeItem).removeClass(Q.cssClasses.selected)}};var Y=function(i){return(!i.ctrlKey&&!i.altKey&&!i.shiftKey&&!i.metaKey)};var X=function(l,j,i){var k=false;switch(l){case j.up:e(i.moveItemUp);k=true;break;case j.down:e(i.moveItemDown);k=true;break;case j.left:e(i.moveItemLeft);k=true;break;case j.right:e(i.moveItemRight);k=true;break}return k};var g=function(m,k,j,n){var i=false;var l;switch(m){case k.up:l=j.getItemAbove(n);i=true;break;case k.down:l=j.getItemBelow(n);i=true;break;case k.left:l=j.getLeftSibling(n);i=true;break;case k.right:l=j.getRightSibling(n);i=true;break}L(l).focus();return i};this.handleDirectionKeyDown=function(j){if(!Q.activeItem){return true}for(var k=0;k<P.length;k++){var l=P[k];var m=false;if(l.modifier(j)){m=X(j.keyCode,l,U)}else{if(Y(j)){m=g(j.keyCode,l,U,Q.activeItem)}}if(m){return false}}return true};var S;var M;var T=function(j){j=F.wrap(j);var i=E.createAvatarId(Q.domNode.id);return function(l){if(M){var m=E.findTarget(l.target,j,i,M);if(m){var k=U.dropPosition(m,Q.activeItem,l.clientX,l.pageY);if(k===F.position.BEFORE){L(m).before(S);S.show()}else{if(k===F.position.AFTER){L(m).after(S);S.show()}else{if(k===F.position.INSIDE){L(m).append(S);S.show()}else{S.hide()}}}}else{S.hide()}}}};function W(i){i.addClass(Q.cssClasses.defaultStyle);i.ariaState("grab","supported");i.mouseover(function(){var j=L(Z.grabHandle(i[0]));j.addClass(Q.cssClasses.hover)});i.mouseout(function(){var j=L(Z.grabHandle(i[0]));j.removeClass(Q.cssClasses.hover)});i.draggable({refreshPositions:true,scroll:true,helper:function(){var j=L(O(i[0]));j.addClass(Q.cssClasses.avatar);j.attr("id",E.createAvatarId(Q.domNode.id));return j},start:function(k,j){i.focus();i.removeClass(Q.cssClasses.selected);i.addClass(Q.cssClasses.dragging);i.ariaState("grab","true");S=L(document.createElement(i[0].tagName));S.addClass(Q.cssClasses.dropMarker);S.hide()},stop:function(k,j){i.removeClass(Q.cssClasses.dragging);i.addClass(Q.cssClasses.selected);L(Q.activeItem).ariaState("grab","supported");S.remove();j.helper=null;M=null},handle:Z.grabHandle(i[0])})}function f(j,i){j.ariaState("dropeffect","move");j.droppable({accept:i,greedy:true,tolerance:"pointer",over:function(l,k){M=k.element},drop:function(l,k){U.mouseMoveItem(k.draggable[0],j[0],l.clientX,l.pageY);Q.activeItem.focus()}})}var c=function(j){var m=function(i){J(L(this),Q.cssClasses);return i.stopPropagation()};var n=function(i){Q.selectItem(this);return i.stopPropagation()};for(var k=0;k<j.length;k++){var l=L(j[k]);l.tabindex("-1");l.blur(m);l.focus(n);l.ariaRole(h.item);l.ariaState("selected","false");l.ariaState("disabled","false")}};var V=function(){var j;var n=F.wrap(Z.movables());var m=F.wrap(Z.dropTargets());c(F.wrap(Z.selectables()));for(j=0;j<n.length;j++){var l=n[j];W(L(l))}var k=function(i){return(n.index(i[0])>-1)};for(j=0;j<m.length;j++){f(L(m[j]),k)}};if(this.domNode){H(this.domNode,Q.focusActiveItem,Q.handleKeyDown,Q.handleKeyUp,T(Z.dropTargets()));K(this.domNode,Z,h);if(!this.domNode.hasTabindex()||(this.domNode.tabindex()<0)){this.domNode.tabindex("0")}V()}};F.Reorderer.prototype.selectItem=function(N){if(this.activeItem&&this.activeItem!==N){J(L(this.activeItem),this.cssClasses)}this.activeItem=N;var M=L(N);M.removeClass(this.cssClasses.defaultStyle);M.addClass(this.cssClasses.selected);M.ariaState("selected","true");this.domNode.ariaState("activedescendent",N.id)}})(jQuery,fluid);(function(D,C){var B=function(H,G,F,J){var I=F;if(G.hasWrapped){I=J}if(I===C.position.AFTER){D(G.item).after(H)}else{D(G.item).before(H)}};var E=function(K,G,F,J){var H;var I;if(G===C.orientation.VERTICAL){H=D(K).offset().top+(K.offsetHeight/2);I=J<H}else{H=D(K).offset().left+(K.offsetWidth/2);I=F<H}return(I?C.position.BEFORE:C.position.AFTER)};var A={getSiblingInfo:function(H,G,J){var F=D(G).index(H)+J;var I=false;if(F===-1){F=G.length-1;I=true}else{if(F===G.length){F=0;I=true}else{if(F<-1||F>G.length){F=0}}}return{item:G[F],hasWrapped:I}},getRightSiblingInfo:function(G,F){return this.getSiblingInfo(G,F,C.direction.NEXT)},getLeftSiblingInfo:function(G,F){return this.getSiblingInfo(G,F,C.direction.PREVIOUS)},getItemInfoBelow:function(L,F){var J=D(L).offset();var H,I;var K,G;for(H=0;H<F.length;H++){G=F[H];I=D(F[H]).offset();if(I.left===J.left){K=K||G;if(I.top>J.top){return{item:G,hasWrapped:false}}}}K=K||F[0];return{item:K,hasWrapped:true}},getItemInfoAbove:function(L,G){var K=D(L).offset();var I,J;var F,H;for(I=G.length-1;I>-1;I--){H=G[I];J=D(G[I]).offset();if(J.left===K.left){F=F||H;if(K.top>J.top){return{item:H,hasWrapped:false}}}}F=F||G[0];return{item:F,hasWrapped:true}}};C.ListLayoutHandler=function(H,I){H=C.utils.adaptFindItems(H);var G=function(){};var F=C.orientation.VERTICAL;if(I){G=I.orderChangedCallback||G;F=I.orientation||F}this.getRightSibling=function(J){return A.getRightSiblingInfo(J,H.selectables()).item};this.moveItemRight=function(K){var J=A.getRightSiblingInfo(K,H.movables());B(K,J,C.position.AFTER,C.position.BEFORE);G()};this.getLeftSibling=function(J){return A.getLeftSiblingInfo(J,H.selectables()).item};this.moveItemLeft=function(K){var J=A.getLeftSiblingInfo(K,H.movables());B(K,J,C.position.BEFORE,C.position.AFTER);G()};this.getItemBelow=this.getRightSibling;this.getItemAbove=this.getLeftSibling;this.moveItemUp=this.moveItemLeft;this.moveItemDown=this.moveItemRight;this.dropPosition=function(L,K,J,M){return E(L,F,J,M)};this.mouseMoveItem=function(K,M,J,N){var L=this.dropPosition(M,K,J,N);if(L===C.position.BEFORE){D(M).before(K)}else{if(L===C.position.AFTER){D(M).after(K)}}G()}};C.GridLayoutHandler=function(H,I){C.ListLayoutHandler.call(this,H,I);H=C.utils.adaptFindItems(H);var G=function(){};if(I){G=I.orderChangedCallback||G}var F=C.orientation.HORIZONTAL;this.getItemBelow=function(J){return A.getItemInfoBelow(J,H.selectables()).item};this.moveItemDown=function(K){var J=A.getItemInfoBelow(K,H.movables());B(K,J,C.position.AFTER,C.position.BEFORE);G()};this.getItemAbove=function(J){return A.getItemInfoAbove(J,H.selectables()).item};this.moveItemUp=function(K){var J=A.getItemInfoAbove(K,H.movables());B(K,J,C.position.BEFORE,C.position.AFTER);G()};this.dropPosition=function(L,K,J,M){return E(L,F,J,M)}};C.ModuleLayoutHandler=function(L,J,O){var G=C.orientation.VERTICAL;var N=function(){};if(O){if(O.orderChangedCallbackUrl){N=function(){D.post(O.orderChangedCallbackUrl,JSON.stringify(L),function(P,Q){J=P},"json")}}}var K=function(P,R){var Q=C.moduleLayout.itemAboveBelow(P.id,R,L);return C.utils.jById(Q)[0]};var M=function(P,Q){var R=C.moduleLayout.firstItemInAdjacentColumn(P.id,Q,L);return C.utils.jById(R)[0]};var I=function(R,Q,P){if(!R||!Q||!C.moduleLayout.canMove(R.id,Q.id,P,L,J)){return }if(P===C.position.BEFORE){D(Q).before(R)}else{if(P===C.position.AFTER){D(Q).after(R)}else{D(Q).append(R)}}C.moduleLayout.updateLayout(R.id,Q.id,P,L);N()};var H=function(P,R){var S=C.moduleLayout.findTarget(P.id,R,L,J);var Q=C.utils.jById(S.id)[0];I(P,Q,S.position)};var F=function(P,S){var R=C.moduleLayout.nearestMoveableTarget(P.id,S,L,J);var Q=C.utils.jById(R.id)[0];I(P,Q,R.position)};this.getRightSibling=function(P){return M(P,C.direction.NEXT)};this.moveItemRight=function(P){H(P,C.direction.NEXT)};this.getLeftSibling=function(P){return M(P,C.direction.PREVIOUS)};this.moveItemLeft=function(P){H(P,C.direction.PREVIOUS)};this.getItemAbove=function(P){return K(P,C.direction.PREVIOUS)};this.moveItemUp=function(P){F(P,C.direction.PREVIOIUS)};this.getItemBelow=function(P){return K(P,C.direction.NEXT)};this.moveItemDown=function(P){F(P,C.direction.NEXT)};this.dropPosition=function(T,R,Q,U){if(C.moduleLayout.isColumn(T.id,L)){return C.position.INSIDE}var P=E(T,G,Q,U);var S=C.moduleLayout.canMove(R.id,T.id,P,L,J);if(S){return P}else{return C.position.NO_TARGET}};this.mouseMoveItem=function(Q,R,P,T){var S=this.dropPosition(R,Q,P,T);if(S!==C.position.NO_TARGET){I(Q,R,S)}}}})(jQuery,fluid);fluid.moduleLayout=function(C,B){var A={layoutWalker:function(G,H){for(var E=0;E<H.columns.length;E++){var I=H.columns[E].children;for(var F=0;F<I.length;F++){var D=G(I,F,E);if(D){return D}}}},findColumnAndItemIndices:function(G,E){var D=function(J,I,H){if(J[I]===G){return{columnIndex:H,itemIndex:I}}};var F=A.layoutWalker(D,E);return F||{columnIndex:-1,itemIndex:-1}},findColIndex:function(F,E){for(var D=0;D<E.columns.length;D++){if(F===E.columns[D].id){return D}}return -1},findItemIndex:function(E,D){return A.findColumnAndItemIndices(E,D).itemIndex},numColumns:function(D){return D.columns.length},isColumnIndex:function(D,E){return(D<E.columns.length)&&(D>=0)},findItemAndTargetIndices:function(L,M,H,K){var D=K.columns;var J={itemIndex:-1,targetIndex:-1};if(!L||!M){return J}var F=0;var O=H;for(var G=0;G<D.length;G++){var N=D[G].children;for(var E=0;E<N.length;E++){var I=N[E];if(I===L){J.itemIndex=F}if(I===M){J.targetIndex=O}if(J.itemIndex>=0&&J.targetIndex>=0){return J}F++;O++}O++}return J},nearestNextMoveableTarget:function(H,G,J){var E={id:H,position:B.position.AFTER};var K=false;var I=A.findColumnAndItemIndices(H,G);if(I.columnIndex<0){K=true}if(!K){var L=G.columns[I.columnIndex].children;for(var F=I.itemIndex+1;(F<L.length)&&!K;F++){var D=L[F];if((K=B.moduleLayout.canMove(H,D,B.position.AFTER,G,J))){E.id=D}}}return E},nearestPreviousMoveableTarget:function(H,G,J){var E={id:H,position:B.position.BEFORE};var K=false;var I=A.findColumnAndItemIndices(H,G);if(I.columnIndex<0){K=true}if(!K){var L=G.columns[I.columnIndex].children;for(var F=I.itemIndex-1;(F>-1)&&!K;F--){var D=L[F];if((K=B.moduleLayout.canMove(H,D,B.position.BEFORE,G,J))){E.id=D}}}return E},getItemAt:function(E,D,F){var I=null;var H=F.columns;if(E>=0&&E<H.length){var G=H[E].children;if(D>=0&&D<G.length){I=G[D]}}return I},canItemMove:function(F,E){var G=E[F];for(var D=0;D<G.length;D++){if(G[D]===1){return true}}return false},isDropTarget:function(F,E){for(var D=0;D<E.length;D++){if(E[D][F]===1||E[D][F+1]===1){return true}}return false}};return{internals:A,isColumn:function(F,E){var D=A.findColIndex(F,E);return(D>-1)},canMove:function(I,H,D,F,E){if(D===B.position.NO_TARGET){return false}if(D===B.position.INSIDE){return true}var G=A.findItemAndTargetIndices(I,H,D,F);return(!!E[G.itemIndex][G.targetIndex])},firstItemInAdjacentColumn:function(G,F,D){var E=function(K,I,H){var M=K[I];if(M===G){var J=H+F;var L=A.getItemAt(J,0,D);while(!L){J=J+F;if(A.isColumnIndex(J,D)){L=A.getItemAt(J,0,D)}else{L=G}}return L}};return A.layoutWalker(E,D)||G},itemAboveBelow:function(G,F,E){var D=function(I,H){if(I[H]===G){var J=H+F;if((J<0)||(J>=I.length)){return G}else{return I[J]}}};return A.layoutWalker(D,E)||G},updateLayout:function(H,F,E,G){if(!H||!F||H===F){return }var D=A.findColumnAndItemIndices(H,G);G.columns[D.columnIndex].children.splice(D.itemIndex,1);var J;if(E===B.position.INSIDE){J=G.columns[A.findColIndex(F,G)].children;J.splice(J.length,0,H)}else{var I=A.findColumnAndItemIndices(F,G);J=G.columns[I.columnIndex].children;J.splice(I.itemIndex+E,0,H)}},findTarget:function(G,I,F,J){var H=A.findColumnAndItemIndices(G,F).columnIndex+I;var D=F.columns[H];if(H<0||H>=A.numColumns(F)){return{id:G,position:B.position.BEFORE}}var L=D.children;for(var E=0;(E<L.length);E++){var K=L[E];if(B.moduleLayout.canMove(G,K,B.position.BEFORE,F,J)){return{id:K,position:B.position.BEFORE}}else{if(B.moduleLayout.canMove(G,K,B.position.AFTER,F,J)){return{id:K,position:B.position.AFTER}}}}return{id:D.id,position:B.position.INSIDE}},nearestMoveableTarget:function(G,F,E,D){if(F===B.direction.NEXT){return A.nearestNextMoveableTarget(G,E,D)}else{return A.nearestPreviousMoveableTarget(G,E,D)}},createFindItems:function(K,O,R){var F={};F.grabHandle=R;var I;var D;var M;var N=K.columns;for(var J=0;J<N.length;J++){var Q=N[J].children;for(var H=0;H<Q.length;H++){var L=Q[H];var G="[id="+L+"]";I=I?I+","+G:G;var P=A.findItemAndTargetIndices(L,L,B.position.BEFORE,K);if(A.canItemMove(P.itemIndex,O)){D=D?D+","+G:G}if(A.isDropTarget(P.targetIndex,O)){M=M?M+","+G:G}}var E="[id="+N[J].id+"]";M=M?M+","+E:E}F.selectables=function(){return C(I)};F.movables=function(){return C(D)};F.dropTargets=function(){return C(M)};return F},containerId:function(D){return D.id}}}(jQuery,fluid);
\ No newline at end of file
diff --git a/jscripts/help.js b/jscripts/help.js
new file mode 100644 (file)
index 0000000..1e92548
--- /dev/null
@@ -0,0 +1,25 @@
+function toggleToc() {\r
+       //var tocmain = document.getElementById('help');\r
+       var toc = document.getElementById('help');\r
+       var showlink=document.getElementById('showlink');\r
+       var hidelink=document.getElementById('hidelink');\r
+       if(toc.style.display == 'none') {\r
+               toc.style.display = tocWas;\r
+               hidelink.style.display='';\r
+               showlink.style.display='none';\r
+               //tocmain.className = '';\r
+\r
+               var help = document.getElementById('help-title');\r
+               help.className = '';\r
+\r
+       } else {\r
+               tocWas = toc.style.display;\r
+               toc.style.display = 'none';\r
+               hidelink.style.display='none';\r
+               showlink.style.display='';\r
+               //tocmain.className = 'tochidden';\r
+\r
+               var help = document.getElementById('help-title');\r
+               help.className = 'line';\r
+       }\r
+}\r
diff --git a/jscripts/interface.js b/jscripts/interface.js
new file mode 100644 (file)
index 0000000..eb5dfa9
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * Interface elements for jQuery - http://interface.eyecon.ro
+ *
+ * Copyright (c) 2006 Stefan Petre
+ * Dual licensed under the MIT (MIT-LICENSE.txt) 
+ * and GPL (GPL-LICENSE.txt) licenses.
+ */
+ eval(function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('6.M={4Z:z(e,s){J l=0;J t=0;J 26=0;J 22=0;J w=6.C(e,\'1S\');J h=6.C(e,\'1T\');J 10=e.3c;J R=e.3d;3b(e.3a){l+=e.2b+(e.16?A(e.16.2H)||0:0);t+=e.2k+(e.16?A(e.16.2E)||0:0);9(s){26+=e.1r.1A||0;22+=e.1r.1n||0}e=e.3a}l+=e.2b+(e.16?A(e.16.2H)||0:0);t+=e.2k+(e.16?A(e.16.2E)||0:0);22=t-22;26=l-26;v{x:l,y:t,4A:26,4B:22,w:w,h:h,10:10,R:R}},1C:z(e){J x=0;J y=0;J 35=n;O=e.L;9(6(e).C(\'N\')==\'15\'){2e=O.1M;2n=O.1b;O.1M=\'36\';O.N=\'2L\';O.1b=\'2v\';35=D}u=e;3b(u){x+=u.2b+(u.16&&!6.1t.2c?A(u.16.2H)||0:0);y+=u.2k+(u.16&&!6.1t.2c?A(u.16.2E)||0:0);u=u.3a}u=e;3b(u&&u.4C.4D()!=\'Y\'){x-=u.1A||0;y-=u.1n||0;u=u.1r}9(35){O.N=\'15\';O.1b=2n;O.1M=2e}v{x:x,y:y}},1u:z(e){J w=6.C(e,\'1S\');J h=6.C(e,\'1T\');J 10=0;J R=0;O=e.L;9(6(e).C(\'N\')!=\'15\'){10=e.3c;R=e.3d}P{2e=O.1M;2n=O.1b;O.1M=\'36\';O.N=\'2L\';O.1b=\'2v\';10=e.3c;R=e.3d;O.N=\'15\';O.1b=2n;O.1M=2e}v{w:w,h:h,10:10,R:R}},3v:z(e){9(e){w=e.27;h=e.2a}P{1U=E.18;w=1H.2Z||2J.2Z||(1U&&1U.27)||E.Y.27;h=1H.3h||2J.3h||(1U&&1U.2a)||E.Y.2a}v{w:w,h:h}},4G:z(e){9(e){t=e.1n;l=e.1A;w=e.3e;h=e.2V;2I=0;2G=0}P{9(E.18&&E.18.1n){t=E.18.1n;l=E.18.1A;w=E.18.3e;h=E.18.2V}P 9(E.Y){t=E.Y.1n;l=E.Y.1A;w=E.Y.3e;h=E.Y.2V}2I=2J.2Z||E.18.27||E.Y.27||0;2G=2J.3h||E.18.2a||E.Y.2a||0}v{t:t,l:l,w:w,h:h,2I:2I,2G:2G}},4J:z(e,1I){u=6(e);t=u.C(\'3l\')||\'\';r=u.C(\'2M\')||\'\';b=u.C(\'2W\')||\'\';l=u.C(\'2N\')||\'\';9(1I)v{t:A(t)||0,r:A(r)||0,b:A(b)||0,l:A(l)};P v{t:t,r:r,b:b,l:l}},4K:z(e,1I){u=6(e);t=u.C(\'4S\')||\'\';r=u.C(\'4L\')||\'\';b=u.C(\'4M\')||\'\';l=u.C(\'4N\')||\'\';9(1I)v{t:A(t)||0,r:A(r)||0,b:A(b)||0,l:A(l)};P v{t:t,r:r,b:b,l:l}},2d:z(e,1I){u=6(e);t=u.C(\'2E\')||\'\';r=u.C(\'4O\')||\'\';b=u.C(\'4P\')||\'\';l=u.C(\'2H\')||\'\';9(1I)v{t:A(t)||0,r:A(r)||0,b:A(b)||0,l:A(l)||0};P v{t:t,r:r,b:b,l:l}},2Y:z(23){x=23.4R||(23.4T+(E.18.1A||E.Y.1A))||0;y=23.4V||(23.4X+(E.18.1n||E.Y.1n))||0;v{x:x,y:y}}};6.g={H:Z,8:Z,2K:z(){v j.2o(z(){9(j.2O){j.1V=Z;6(j).34(\'3r\',6.g.30)}})},3s:z(e){9(6.g.8!=Z){6.g.2w(e);v n}J 7=j.1V;6(E).2S(\'3A\',6.g.2X).2S(\'3B\',6.g.2w);7.5.T=6.M.2Y(e);7.5.17=7.5.T;7.5.2g=n;7.5.4Y=j!=j.1V;6.g.8=7;9(7.5.1y&&j!=j.1V){3m=6.M.1C(7.1r);3n=6.M.1u(7);3o={x:A(6.C(7,\'19\'))||0,y:A(6.C(7,\'1a\'))||0};F=7.5.17.x-3m.x-3n.10/2-3o.x;G=7.5.17.y-3m.y-3n.R/2-3o.y;6.31.50(7,[F,G])}v n},30:z(e){7=6.g.8;7.5.2g=D;2i=7.L;7.5.1G=6.C(7,\'N\');7.5.24=6.C(7,\'1b\');9(!7.5.47)7.5.47=7.5.24;7.5.S={x:A(6.C(7,\'19\'))||0,y:A(6.C(7,\'1a\'))||0};7.5.2q=0;7.5.2r=0;9(6.1t.3q){3p=6.M.2d(7,D);7.5.2q=3p.l||0;7.5.2r=3p.t||0}7.5.B=6.1x(6.M.1C(7),6.M.1u(7));9(7.5.24!=\'48\'&&7.5.24!=\'2v\'){2i.1b=\'48\'}6.g.H.3w();14=7.51(D);6(14).C({N:\'2L\',19:\'1E\',1a:\'1E\'});14.L.3l=\'0\';14.L.2M=\'0\';14.L.2W=\'0\';14.L.2N=\'0\';6.g.H.20(14);9(7.5.1O)7.5.1O.1w(7,[14]);12=6.g.H.W(0).L;9(7.5.3f){12.1S=\'49\';12.1T=\'49\'}P{12.1T=7.5.B.R+\'1e\';12.1S=7.5.B.10+\'1e\'}12.N=\'2L\';12.3l=\'1E\';12.2M=\'1E\';12.2W=\'1E\';12.2N=\'1E\';6.1x(7.5.B,6.M.1u(14));9(7.5.V){9(7.5.V.19){7.5.S.x+=7.5.T.x-7.5.B.x-7.5.V.19;7.5.B.x=7.5.T.x-7.5.V.19}9(7.5.V.1a){7.5.S.y+=7.5.T.y-7.5.B.y-7.5.V.1a;7.5.B.y=7.5.T.y-7.5.V.1a}9(7.5.V.2P){7.5.S.x+=7.5.T.x-7.5.B.x-7.5.B.R+7.5.V.2P;7.5.B.x=7.5.T.x-7.5.B.10+7.5.V.2P}9(7.5.V.2Q){7.5.S.y+=7.5.T.y-7.5.B.y-7.5.B.R+7.5.V.2Q;7.5.B.y=7.5.T.y-7.5.B.R+7.5.V.2Q}}7.5.1q=7.5.S.x;7.5.1p=7.5.S.y;9(7.5.21||7.5.K==\'2F\'){1R=6.M.2d(7.1r,D);7.5.B.x=7.2b+(6.1t.3q?0:6.1t.2c?-1R.l:1R.l);7.5.B.y=7.2k+(6.1t.3q?0:6.1t.2c?-1R.t:1R.t);6(7.1r).20(6.g.H.W(0))}9(7.5.K){6.g.3t(7);7.5.1j.K=6.g.3K}9(7.5.1y){6.31.4a(7)}12.19=7.5.B.x-7.5.2q+\'1e\';12.1a=7.5.B.y-7.5.2r+\'1e\';12.1S=7.5.B.10+\'1e\';12.1T=7.5.B.R+\'1e\';6.g.8.5.2l=n;9(7.5.1P){7.5.1j.1m=6.g.3H}9(7.5.1K!=n){6.g.H.C(\'1K\',7.5.1K)}9(7.5.1c){6.g.H.C(\'1c\',7.5.1c);9(1H.2z){6.g.H.C(\'3x\',\'3y(1c=\'+7.5.1c*3z+\')\')}}9(7.5.1J==n){2i.N=\'15\'}9(6.q&&6.q.1W>0){6.q.3C(7)}v n},3t:z(7){9(7.5.K.1d==41){9(7.5.K==\'2F\'){7.5.Q=6.1x({x:0,y:0},6.M.1u(7.1r));25=6.M.2d(7.1r,D);7.5.Q.w=7.5.Q.10-25.l-25.r;7.5.Q.h=7.5.Q.R-25.t-25.b}P 9(7.5.K==\'E\'){3j=6.M.3v();7.5.Q={x:0,y:0,w:3j.w,h:3j.h}}}P 9(7.5.K.1d==42){7.5.Q={x:A(7.5.K[0])||0,y:A(7.5.K[1])||0,w:A(7.5.K[2])||0,h:A(7.5.K[3])||0}}7.5.Q.F=7.5.Q.x-7.5.B.x;7.5.Q.G=7.5.Q.y-7.5.B.y},2j:z(8){9(8.5.21||8.5.K==\'2F\'){6(\'Y\',E).20(6.g.H.W(0))}6.g.H.3w().4d().C(\'1c\',1);9(1H.2z){6.g.H.C(\'3x\',\'3y(1c=3z)\')}},2w:z(e){6(E).34(\'3A\',6.g.2X).34(\'3B\',6.g.2w);9(6.g.8==Z){v}8=6.g.8;6.g.8=Z;9(8.5.2g==n){v n}9(8.5.2A==D){6(8).C(\'1b\',8.5.24)}2i=8.L;9(8.1y){6.g.H.C(\'3R\',\'3S\')}9(8.5.38==n){9(8.5.11>0){9(!8.5.X||8.5.X==\'2x\'){x=3D 6.11(8,8.5.11,\'19\');x.3E(8.5.S.x,8.5.29)}9(!8.5.X||8.5.X==\'2B\'){y=3D 6.11(8,8.5.11,\'1a\');y.3E(8.5.S.y,8.5.1X)}}P{9(!8.5.X||8.5.X==\'2x\')8.L.19=8.5.29+\'1e\';9(!8.5.X||8.5.X==\'2B\')8.L.1a=8.5.1X+\'1e\'}6.g.2j(8);9(8.5.1J==n){6(8).C(\'N\',8.5.1G)}}P 9(8.5.11>0){8.5.2l=D;9(6.q&&6.q.1i&&6.I){1B=6.M.1C(6.I.H.W(0))}P{1B=n}6.g.H.4i({19:1B?1B.x:8.5.B.x,1a:1B?1B.y:8.5.B.y},8.5.11,z(){8.5.2l=n;9(8.5.1J==n){8.L.N=8.5.1G}6.g.2j(8)})}P{6.g.2j(8);9(8.5.1J==n){6(8).C(\'N\',8.5.1G)}}9(6.q&&6.q.1W>0){6.q.3Z(8)}9(6.I&&6.q.1i){6.I.4j(8)}9(8.5.1z&&(8.5.29!=8.5.S.x||8.5.1X!=8.5.S.y)){8.5.1z.1w(8,8.5.4k||[0,0,8.5.29,8.5.1X])}9(8.5.1N)8.5.1N.1w(8);v n},3H:z(x,y,F,G){9(F!=0)F=A((F+(j.5.1P*F/1f.3I(F))/2)/j.5.1P)*j.5.1P;9(G!=0)G=A((G+(j.5.1Z*G/1f.3I(G))/2)/j.5.1Z)*j.5.1Z;v{F:F,G:G,x:0,y:0}},3K:z(x,y,F,G){F=1f.3L(1f.3M(F,j.5.Q.F),j.5.Q.w+j.5.Q.F-j.5.B.10);G=1f.3L(1f.3M(G,j.5.Q.G),j.5.Q.h+j.5.Q.G-j.5.B.R);v{F:F,G:G,x:0,y:0}},2X:z(e){9(6.g.8==Z||6.g.8.5.2l==D){v}J 8=6.g.8;8.5.17=6.M.2Y(e);9(8.5.2g==n){3O=1f.4o(1f.3N(8.5.T.x-8.5.17.x,2)+1f.3N(8.5.T.y-8.5.17.y,2));9(3O<8.5.2C){v}P{6.g.30(e)}}F=8.5.17.x-8.5.T.x;G=8.5.17.y-8.5.T.y;28(i 1Q 8.5.1j){1s=8.5.1j[i].1w(8,[8.5.S.x+F,8.5.S.y+G,F,G]);9(1s&&1s.1d==4p){F=i!=\'3g\'?1s.F:(1s.x-8.5.S.x);G=i!=\'3g\'?1s.G:(1s.y-8.5.S.y)}}8.5.1q=8.5.B.x+F-8.5.2q;8.5.1p=8.5.B.y+G-8.5.2r;9(8.5.1y&&(8.5.1F||8.5.1z)){6.31.1F(8,8.5.1q,8.5.1p)}9(!8.5.X||8.5.X==\'2x\'){8.5.29=8.5.S.x+F;6.g.H.W(0).L.19=8.5.1q+\'1e\'}9(!8.5.X||8.5.X==\'2B\'){8.5.1X=8.5.S.y+G;6.g.H.W(0).L.1a=8.5.1p+\'1e\'}9(6.q&&6.q.1W>0){6.q.33(8,14)}v n},2p:z(o){9(!6.g.H){6(\'Y\',E).20(\'<3P 1o="3Q"></3P>\');6.g.H=6(\'#3Q\');u=6.g.H.W(0);1l=u.L;1l.1b=\'2v\';1l.N=\'15\';1l.3R=\'3S\';1l.4u=\'15\';1l.4v=\'36\';9(1H.2z){u.3W=z(){v n};u.3X=z(){v n}}P{1l.4w=\'15\';1l.4x=\'15\'}}9(!o){o={}}v j.2o(z(){9(j.2O||!6.M)v;9(1H.2z){j.3W=z(){v n};j.3X=z(){v n}}J 2R=o.3Y?6(j).4y(o.3Y):6(j);j.5={38:o.38?D:n,1J:o.1J?D:n,2A:o.2A?o.2A:n,1y:o.1y?o.1y:n,21:o.21?o.21:n,1K:o.1K?A(o.1K)||0:n,1c:o.1c?4z(o.1c):n,11:A(o.11)||Z,39:o.39?o.39:n,1j:{},T:{},1O:o.1O&&o.1O.1d==1Y?o.1O:n,1N:o.1N&&o.1N.1d==1Y?o.1N:n,1z:o.1z&&o.1z.1d==1Y?o.1z:n,X:/2B|2x/.4E(o.X)?o.X:n,2C:o.2C?A(o.2C)||0:0,V:o.V?o.V:n,3f:o.3f?D:n};9(o.1j&&o.1j.1d==1Y)j.5.1j.3g=o.1j;9(o.K&&((o.K.1d==41&&(o.K==\'2F\'||o.K==\'E\'))||(o.K.1d==42&&o.K.3i==4))){j.5.K=o.K}9(o.3k){j.5.3k=o.3k}9(o.1m){9(4U o.1m==\'4W\'){j.5.1P=A(o.1m)||1;j.5.1Z=A(o.1m)||1}P 9(o.1m.3i==2){j.5.1P=A(o.1m[0])||1;j.5.1Z=A(o.1m[1])||1}}9(o.1F&&o.1F.1d==1Y){j.5.1F=o.1F}j.2O=D;2R.W(0).1V=j;2R.2S(\'3r\',6.g.3s)})}};6.3U.1x({46:6.g.2K,4b:6.g.2p});6.q={3T:z(1k,1g,1D,1L){v 1k<=6.g.8.5.1q&&(1k+1D)>=(6.g.8.5.1q+6.g.8.5.B.w)&&1g<=6.g.8.5.1p&&(1g+1L)>=(6.g.8.5.1p+6.g.8.5.B.h)?D:n},3V:z(1k,1g,1D,1L){v!(1k>(6.g.8.5.1q+6.g.8.5.B.w)||(1k+1D)<6.g.8.5.1q||1g>(6.g.8.5.1p+6.g.8.5.B.h)||(1g+1L)<6.g.8.5.1p)?D:n},T:z(1k,1g,1D,1L){v 1k<6.g.8.5.17.x&&(1k+1D)>6.g.8.5.17.x&&1g<6.g.8.5.17.y&&(1g+1L)>6.g.8.5.17.y?D:n},1i:n,U:{},1W:0,13:{},3C:z(7){9(6.g.8==Z){v}J i;6.q.U={};2f=n;28(i 1Q 6.q.13){9(6.q.13[i]!=Z){c=6.q.13[i].W(0);9(6.32.3F(6.g.8,c.k.a)){9(c.k.m==n){c.k.p=6.1x(6.M.1C(c),6.M.1u(c));c.k.m=D}9(c.k.1h){6.q.13[i].2t(c.k.1h)}6.q.U[i]=6.q.13[i];9(6.I&&c.k.s==D){c.k.u=6(\'.\'+c.k.a,c);7.L.N=\'15\';6.I.3J(c);7.L.N=7.5.1G;2f=D}}}}9(2f){6.I.4f()}},45:z(){6.q.U={};28(i 1Q 6.q.13){9(6.q.13[i]!=Z){c=6.q.13[i].W(0);9(6.32.3F(6.g.8,c.k.a)){c.k.p=6.1x(6.M.1C(c),6.M.1u(c));9(c.k.1h){6.q.13[i].2t(c.k.1h)}6.q.U[i]=6.q.13[i];9(6.I&&c.k.s==D){c.k.u=6(\'.\'+c.k.a,c);7.L.N=\'15\';6.I.3J(c);7.L.N=7.5.1G;2f=D}}}}},33:z(e){9(6.g.8==Z){v}6.q.1i=n;J i;37=n;28(i 1Q 6.q.U){c=6.q.U[i].W(0);9(6.q.1i==n&&6.q[c.k.t](c.k.p.x,c.k.p.y,c.k.p.10,c.k.p.R)){9(c.k.1v&&c.k.h==n){6.q.U[i].2D(c.k.1h);6.q.U[i].2t(c.k.1v)}9(c.k.h==n&&c.k.2h){37=D}c.k.h=D;6.q.1i=c;9(6.I&&c.k.s==D){6.I.H.W(0).32=c.k.3G;6.I.33(c)}}P{9(c.k.2s&&c.k.h==D){c.k.2s.1w(c,[e,14,c.k.11])}9(c.k.1v){6.q.U[i].2D(c.k.1v);6.q.U[i].2t(c.k.1h)}c.k.h=n}}9(6.I&&6.q.1i==n){6.I.H.W(0).L.N=\'15\';6(\'Y\').20(6.I.H.W(0))}9(37){6.q.1i.k.2h.1w(6.q.1i,[e,14])}},3Z:z(e){J i;28(i 1Q 6.q.U){c=6.q.U[i].W(0);9(c.k.1h){6.q.U[i].2D(c.k.1h)}9(c.k.1v){6.q.U[i].2D(c.k.1v)}9(c.k.s){6.I.40[6.I.40.3i]=i}9(c.k.2m&&c.k.h==D){c.k.h=n;c.k.2m.1w(c,[e,c.k.11])}c.k.m=n;c.k.h=n}6.q.U={}},2K:z(){v j.2o(z(){9(j.2u){9(j.k.s){1o=6.44(j,\'1o\');6.I.43[1o]=Z;6(\'.\'+j.k.a,j).46()}6.q.13[\'d\'+j.2U]=Z;j.2u=n;j.f=Z}})},2p:z(o){v j.2o(z(){9(j.2u==D||!o.3u||!6.M||!6.g){v}j.k={a:o.3u,1h:o.4e,1v:o.4g,3G:o.4l,2m:o.4m||o.2m,2h:o.2h||o.4q,2s:o.2s||o.4s,t:o.2y&&(o.2y==\'3T\'||o.2y==\'3V\')?o.2y:\'T\',11:o.11?o.11:n,m:n,h:n};9(o.4H==D&&6.I){1o=6.44(j,\'1o\');6.I.43[1o]=j.k.a;j.k.s=D;9(o.2T){j.k.2T=o.2T;j.k.4h=6.I.4n(1o).4r}}j.2u=D;j.2U=A(1f.4F()*4Q);6.q.13[\'d\'+j.2U]=6(j);6.q.1W++})}};6.3U.1x({4I:6.q.2K,4c:6.q.2p});6.4t=6.q.45;',62,312,'|||||dragCfg|jQuery|elm|dragged|if|||iEL||||iDrag|||this|dropCfg|||false|||iDrop||||el|return||||function|parseInt|oC|css|true|document|dx|dy|helper|iSort|var|containment|style|iUtil|display|es|else|cont|hb|oR|pointer|highlighted|cursorAt|get|axis|body|null|wb|fx|dhs|zones|clonedEl|none|currentStyle|currentPointer|documentElement|left|top|position|opacity|constructor|px|Math|zoney|ac|overzone|onDrag|zonex|els|grid|scrollTop|id|ny|nx|parentNode|newCoords|browser|getSize|hc|apply|extend|si|onChange|scrollLeft|dh|getPosition|zonew|0px|onSlide|oD|window|toInteger|ghosting|zIndex|zoneh|visibility|onStop|onStart|gx|in|parentBorders|width|height|de|dragElem|count|nRy|Function|gy|append|insideParent|st|event|oP|contBorders|sl|clientWidth|for|nRx|clientHeight|offsetLeft|opera|getBorder|oldVisibility|oneIsSortable|init|onHover|dEs|hidehelper|offsetTop|prot|onDrop|oldPosition|each|build|diffX|diffY|onOut|addClass|isDroppable|absolute|dragstop|horizontally|tolerance|ActiveXObject|so|vertically|snapDistance|removeClass|borderTopWidth|parent|ih|borderLeftWidth|iw|self|destroy|block|marginRight|marginLeft|isDraggable|right|bottom|dhe|bind|onchange|idsa|scrollHeight|marginBottom|dragmove|getPointer|innerWidth|dragstart|iSlider|className|checkhover|unbind|restoreStyle|hidden|applyOnHover|revert|hpc|offsetParent|while|offsetWidth|offsetHeight|scrollWidth|autoSize|user|innerHeight|length|clnt|fractions|marginTop|parentPos|sliderSize|sliderPos|oldBorder|msie|mousedown|draginit|getContainment|accept|getClient|empty|filter|alpha|100|mousemove|mouseup|highlight|new|custom|has|shc|snapToGrid|abs|measure|fitToContainer|min|max|pow|distance|div|dragHelper|cursor|move|fit|fn|intersect|onselectstart|ondragstart|handle|checkdrop|changed|String|Array|collected|attr|remeasure|DraggableDestroy|initialPosition|relative|auto|modifyContainer|Draggable|Droppable|hide|activeclass|start|hoverclass|os|animate|check|lastSi|helperclass|ondrop|serialize|sqrt|Object|onhover|hash|onout|recallDroppables|listStyle|overflow|mozUserSelect|userSelect|find|parseFloat|sx|sy|tagName|toLowerCase|test|random|getScroll|sortable|DroppableDestroy|getMargins|getPadding|paddingRight|paddingBottom|paddingLeft|borderRightWidth|borderBottomWidth|10000|pageX|paddingTop|clientX|typeof|pageY|number|clientY|fromHandler|getPos|dragmoveBy|cloneNode'.split('|'),0,{}))\r
diff --git a/jscripts/jquery.js b/jscripts/jquery.js
new file mode 100644 (file)
index 0000000..6e3d8c1
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * jQuery 1.1.4 - New Wave Javascript
+ *
+ * Copyright (c) 2007 John Resig (jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Date: 2007-08-23 21:49:27 -0400 (Thu, 23 Aug 2007) $
+ * $Rev: 2862 $
+ */
+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(9(){6(1f C!="Q")E v=C;E C=19.16=9(a,c){6(19==7||!7.4a)F 1s C(a,c);F 7.4a(a,c)};6(1f $!="Q")E B=$;19.$=C;E q=/^[^<]*(<(.|\\s)+>)[^>]*$|^#(\\w+)$/;C.15=C.3v={4a:9(a,c){a=a||R;6(1f a=="1E"){E m=q.2d(a);6(m&&(m[1]||!c)){6(m[1])a=C.3c([m[1]]);G{E b=R.37(m[3]);6(b)6(b.2j!=m[3])F C().1F(a);G{7[0]=b;7.H=1;F 7}G a=[]}}G F 1s C(c).1F(a)}G 6(C.1g(a))F 1s C(R)[C.15.1L?"1L":"2f"](a);F 7.5J(a.1b==1K&&a||(a.3w||a.H&&a!=19&&!a.1t&&a[0]!=Q&&a[0].1t)&&C.2V(a)||[a])},3w:"1.1.4",7K:9(){F 7.H},H:0,21:9(a){F a==Q?C.2V(7):7[a]},1O:9(a){E b=C(a);b.5c=7;F b},5J:9(a){7.H=0;1K.3v.Y.T(7,a);F 7},J:9(a,b){F C.J(7,a,b)},45:9(a){E b=-1;7.J(9(i){6(7==a)b=i});F b},1j:9(f,d,e){E c=f;6(f.1b==3n)6(d==Q)F 7.H&&C[e||"1j"](7[0],f)||Q;G{c={};c[f]=d}F 7.J(9(a){I(E b 17 c)C.1j(e?7.S:7,b,C.4Q(7,c[b],e,a,b))})},1h:9(b,a){F 7.1j(b,a,"34")},2Q:9(e){6(1f e!="4P"&&e!=K)F 7.3K().3H(R.60(e));E t="";C.J(e||7,9(){C.J(7.2Z,9(){6(7.1t!=8)t+=7.1t!=1?7.5S:C.15.2Q([7])})});F t},82:9(){E a,2e=1a;F 7.J(9(){6(!a)a=C.3c(2e,7.2I);E b=a[0].3B(O);7.P.2p(b,7);20(b.1k)b=b.1k;b.4p(7)})},3H:9(){F 7.2J(1a,O,1,9(a){7.4p(a)})},5v:9(){F 7.2J(1a,O,-1,9(a){7.2p(a,7.1k)})},5u:9(){F 7.2J(1a,M,1,9(a){7.P.2p(a,7)})},5t:9(){F 7.2J(1a,M,-1,9(a){7.P.2p(a,7.2a)})},3L:9(){F 7.5c||C([])},1F:9(t){E b=C.3M(7,9(a){F C.1F(t,a)});F 7.1O(/[^+>] [^+>]/.1d(t)||t.U("..")>-1?C.4d(b):b)},7o:9(e){e=e!=Q?e:O;E d=7.1r(7.1F("*"));6(C.N.12){d.J(9(){7.2l$1i={};I(E a 17 7.$1i)7.2l$1i[a]=C.14({},7.$1i[a])}).49()}E r=7.1O(C.3M(7,9(a){F a.3B(e)}));6(C.N.12){d.J(9(){E c=7.2l$1i;I(E a 17 c)I(E b 17 c[a])C.1c.1r(7,a,c[a][b],c[a][b].V);7.2l$1i=K})}6(e){E f=r.1r(r.1F(\'*\')).1l(\'2b,39[@L=3i]\');d.1l(\'2b,39[@L=3i]\').J(9(i){6(7.3j)f[i].3j=7.3j;6(7.27)f[i].27=O})}F r},1l:9(t){F 7.1O(C.1g(t)&&C.2B(7,9(b,a){F t.T(b,[a])})||C.2R(t,7))},5l:9(t){F 7.1O(t.1b==3n&&C.2R(t,7,O)||C.2B(7,9(a){F(t.1b==1K||t.3w)?C.4K(a,t)<0:a!=t}))},1r:9(t){F 7.1O(C.29(7.21(),t.1b==3n?C(t).21():t.H!=Q&&(!t.W||t.W=="6s")?t:[t]))},3y:9(a){F a?C.2R(a,7).H>0:M},2G:9(a){F a==Q?(7.H?7[0].2A:K):7.1j("2A",a)},5W:9(a){F a==Q?(7.H?7[0].2W:K):7.3K().3H(a)},3S:9(){F 7.1O(1K.3v.3S.T(7,1a))},2J:9(f,d,g,e){E c=7.H>1,a;F 7.J(9(){6(!a){a=C.3c(f,7.2I);6(g<0)a.8E()}E b=7;6(d&&C.W(7,"1A")&&C.W(a[0],"3O"))b=7.4L("1w")[0]||7.4p(R.6a("1w"));C.J(a,9(){6(C.W(7,"33")){6(7.32)C.31({1G:7.32,2w:M,3G:"33"});G C.4E(7.2Q||7.5Z||7.2W||"")}G e.T(b,[c?7.3B(O):7])})})}};C.14=C.15.14=9(){E c=1a[0]||{},a=1,1M=1a.H,4D=M;6(c.1b==8d){4D=c;c=1a[1]||{}}6(1M==1){c=7;a=0}E b;I(;a<1M;a++)6((b=1a[a])!=K)I(E i 17 b){6(c==b[i])5X;6(4D&&1f b[i]==\'4P\'&&c[i])C.14(c[i],b[i]);G 6(b[i]!=Q)c[i]=b[i]}F c};C.14({8a:9(a){19.$=B;6(a)19.16=v;F C},1g:9(a){F!!a&&1f a!="1E"&&!a.W&&a.1b!=1K&&/9/i.1d(a+"")},3E:9(a){F a.3D&&!a.4z||a.4y&&a.2I&&!a.2I.4z},4E:9(a){a=C.2s(a);6(a){6(19.5N)19.5N(a);G 6(C.N.1H)19.4x(a,0);G 2T.2S(19,a)}},W:9(b,a){F b.W&&b.W.1I()==a.1I()},J:9(a,b,c){6(c){6(a.H==Q)I(E i 17 a)b.T(a[i],c);G I(E i=0,3A=a.H;i<3A;i++)6(b.T(a[i],c)===M)1J}G{6(a.H==Q)I(E i 17 a)b.2S(a[i],i,a[i]);G I(E i=0,3A=a.H,2G=a[0];i<3A&&b.2S(2G,i,2G)!==M;2G=a[++i]){}}F a},4Q:9(c,b,d,e,a){6(C.1g(b))b=b.2S(c,[e]);E f=/z-?45|7S-?7Q|1e|5y|7O-?1u/i;F b&&b.1b==3x&&d=="34"&&!f.1d(a)?b+"4t":b},18:{1r:9(b,c){C.J((c||"").2M(/\\s+/),9(i,a){6(!C.18.2N(b.18,a))b.18+=(b.18?" ":"")+a})},23:9(b,c){b.18=c!=Q?C.2B(b.18.2M(/\\s+/),9(a){F!C.18.2N(c,a)}).5w(" "):""},2N:9(t,c){F C.4K(c,(t.18||t).3s().2M(/\\s+/))>-1}},1V:9(e,o,f){I(E i 17 o){e.S["2U"+i]=e.S[i];e.S[i]=o[i]}f.T(e,[]);I(E i 17 o)e.S[i]=e.S["2U"+i]},1h:9(e,p){6(p=="1u"||p=="24"){E b={},3p,3o,d=["7J","7G","7F","7B"];C.J(d,9(){b["7A"+7]=0;b["7x"+7+"7u"]=0});C.1V(e,b,9(){6(C(e).3y(\':4N\')){3p=e.7t;3o=e.7q}G{e=C(e.3B(O)).1F(":4e").5d("27").3L().1h({3V:"1C",3k:"7n",11:"2m",7h:"0",7e:"0"}).57(e.P)[0];E a=C.1h(e.P,"3k")||"3g";6(a=="3g")e.P.S.3k="76";3p=e.74;3o=e.71;6(a=="3g")e.P.S.3k="3g";e.P.3e(e)}});F p=="1u"?3p:3o}F C.34(e,p)},34:9(h,d,g){E i,1R=[],1V=[];9 2E(a){6(!C.N.1H)F M;E b=R.2L.3b(a,K);F!b||b.44("2E")==""}6(d=="1e"&&C.N.12){i=C.1j(h.S,"1e");F i==""?"1":i}6(d.2k(/3a/i))d=x;6(!g&&h.S[d])i=h.S[d];G 6(R.2L&&R.2L.3b){6(d.2k(/3a/i))d="3a";d=d.1v(/([A-Z])/g,"-$1").2D();E e=R.2L.3b(h,K);6(e&&!2E(h))i=e.44(d);G{I(E a=h;a&&2E(a);a=a.P)1R.42(a);I(a=0;a<1R.H;a++)6(2E(1R[a])){1V[a]=1R[a].S.11;1R[a].S.11="2m"}i=d=="11"&&1V[1R.H-1]!=K?"1T":R.2L.3b(h,K).44(d)||"";I(a=0;a<1V.H;a++)6(1V[a]!=K)1R[a].S.11=1V[a]}6(d=="1e"&&i=="")i="1"}G 6(h.41){E f=d.1v(/\\-(\\w)/g,9(m,c){F c.1I()});i=h.41[d]||h.41[f]}F i},3c:9(a,c){E r=[];c=c||R;C.J(a,9(i,b){6(!b)F;6(b.1b==3x)b=b.3s();6(1f b=="1E"){E s=C.2s(b).2D(),1m=c.6a("1m"),1P=[];E a=!s.U("<1Z")&&[1,"<2b>","</2b>"]||!s.U("<6L")&&[1,"<4V>","</4V>"]||s.2k(/^<(6I|1w|6H|6F|6D)/)&&[1,"<1A>","</1A>"]||!s.U("<3O")&&[2,"<1A><1w>","</1w></1A>"]||(!s.U("<6A")||!s.U("<6y"))&&[3,"<1A><1w><3O>","</3O></1w></1A>"]||!s.U("<6x")&&[2,"<1A><1w></1w><4T>","</4T></1A>"]||C.N.12&&[1,"1m<1m>","</1m>"]||[0,"",""];1m.2W=a[1]+b+a[2];20(a[0]--)1m=1m.3Y;6(C.N.12){6(!s.U("<1A")&&s.U("<1w")<0)1P=1m.1k&&1m.1k.2Z;G 6(a[1]=="<1A>"&&s.U("<1w")<0)1P=1m.2Z;I(E n=1P.H-1;n>=0;--n)6(C.W(1P[n],"1w")&&!1P[n].2Z.H)1P[n].P.3e(1P[n]);6(/^\\s/.1d(b))1m.2p(c.60(b.2k(/^\\s*/)[0]),1m.1k)}b=C.2V(1m.2Z)}6(0===b.H&&(!C.W(b,"38")&&!C.W(b,"2b")))F;6(b[0]==Q||C.W(b,"38")||b.6u)r.Y(b);G r=C.29(r,b)});F r},1j:9(c,d,a){E e=C.3E(c)?{}:C.4q;6(d=="28"&&C.N.1H)c.P.3j;6(e[d]){6(a!=Q)c[e[d]]=a;F c[e[d]]}G 6(C.N.12&&d=="S")F C.1j(c.S,"6p",a);G 6(a==Q&&C.N.12&&C.W(c,"38")&&(d=="6n"||d=="6m"))F c.6k(d).5S;G 6(c.4y){6(a!=Q)c.6j(d,a);6(C.N.12&&/5R|32/.1d(d)&&!C.3E(c))F c.3F(d,2);F c.3F(d)}G{6(d=="1e"&&C.N.12){6(a!=Q){c.5y=1;c.1l=(c.1l||"").1v(/5T\\([^)]*\\)/,"")+(3m(a).3s()=="6d"?"":"5T(1e="+a*6c+")")}F c.1l?(3m(c.1l.2k(/1e=([^)]*)/)[1])/6c).3s():""}d=d.1v(/-([a-z])/8I,9(z,b){F b.1I()});6(a!=Q)c[d]=a;F c[d]}},2s:9(t){F(t||"").1v(/^\\s+|\\s+$/g,"")},2V:9(a){E r=[];6(1f a!="8H")I(E i=0,1M=a.H;i<1M;i++)r.Y(a[i]);G r=a.3S(0);F r},4K:9(b,a){I(E i=0,1M=a.H;i<1M;i++)6(a[i]==b)F i;F-1},29:9(a,b){6(C.N.12){I(E i=0;b[i];i++)6(b[i].1t!=8)a.Y(b[i])}G I(E i=0;b[i];i++)a.Y(b[i]);F a},4d:9(a){E r=[],4O=C.1q++;2g{I(E i=0,69=a.H;i<69;i++)6(4O!=a[i].1q){a[i].1q=4O;r.Y(a[i])}}2h(e){r=a}F r},1q:0,2B:9(b,a,c){6(1f a=="1E")a=2T("M||9(a,i){F "+a+"}");E d=[];I(E i=0,3P=b.H;i<3P;i++)6(!c&&a(b[i],i)||c&&!a(b[i],i))d.Y(b[i]);F d},3M:9(c,b){6(1f b=="1E")b=2T("M||9(a){F "+b+"}");E d=[];I(E i=0,3P=c.H;i<3P;i++){E a=b(c[i],i);6(a!==K&&a!=Q){6(a.1b!=1K)a=[a];d=d.8x(a)}}F d}});E u=8w.8u.2D();C.N={6b:(u.2k(/.+(?:8s|8q|8p|8o)[\\/: ]([\\d.]+)/)||[])[1],1H:/61/.1d(u),2t:/2t/.1d(u),12:/12/.1d(u)&&!/2t/.1d(u),3J:/3J/.1d(u)&&!/(8n|61)/.1d(u)};E x=C.N.12?"3I":"4G";C.14({8m:!C.N.12||R.8l=="8k",3I:C.N.12?"3I":"4G",4q:{"I":"8j","8i":"18","3a":x,4G:x,3I:x,2W:"2W",18:"18",2A:"2A",30:"30",27:"27",8h:"8g",28:"28",8f:"8e"}});C.J({5Y:"a.P",4C:"16.4C(a)",8c:"16.25(a,2,\'2a\')",8b:"16.25(a,2,\'4B\')",88:"16.4A(a.P.1k,a)",87:"16.4A(a.1k)"},9(i,n){C.15[i]=9(a){E b=C.3M(7,n);6(a&&1f a=="1E")b=C.2R(a,b);F 7.1O(C.4d(b))}});C.J({57:"3H",86:"5v",2p:"5u",85:"5t"},9(i,n){C.15[i]=9(){E a=1a;F 7.J(9(){I(E j=0,1M=a.H;j<1M;j++)C(a[j])[n](7)})}});C.J({5d:9(a){C.1j(7,a,"");7.84(a)},83:9(c){C.18.1r(7,c)},81:9(c){C.18.23(7,c)},80:9(c){C.18[C.18.2N(7,c)?"23":"1r"](7,c)},23:9(a){6(!a||C.1l(a,[7]).r.H)7.P.3e(7)},3K:9(){20(7.1k)7.3e(7.1k)}},9(i,n){C.15[i]=9(){F 7.J(n,1a)}});C.J(["5Q","5P","5M","5L"],9(i,n){C.15[n]=9(a,b){F 7.1l(":"+n+"("+a+")",b)}});C.J(["1u","24"],9(i,n){C.15[n]=9(h){F h==Q?(7.H?C.1h(7[0],n):K):7.1h(n,h.1b==3n?h:h+"4t")}});E A=C.N.1H&&5K(C.N.6b)<7Z?"(?:[\\\\w*2l-]|\\\\\\\\.)":"(?:[\\\\w\\7Y-\\7V*2l-]|\\\\\\\\.)",5I=1s 3C("^[/>]\\\\s*("+A+"+)"),5H=1s 3C("^("+A+"+)(#)("+A+"+)"),5G=1s 3C("^([#.]?)("+A+"*)");C.14({4w:{"":"m[2]==\'*\'||16.W(a,m[2])","#":"a.3F(\'2j\')==m[2]",":":{5P:"i<m[3]-0",5M:"i>m[3]-0",25:"m[3]-0==i",5Q:"m[3]-0==i",2H:"i==0",2P:"i==r.H-1",5E:"i%2==0",5D:"i%2","2H-3z":"a.P.4L(\'*\')[0]==a","2P-3z":"16.25(a.P.3Y,1,\'4B\')==a","7U-3z":"!16.25(a.P.3Y,2,\'4B\')",5Y:"a.1k",3K:"!a.1k",5L:"(a.5Z||a.7T||\'\').U(m[3])>=0",4N:\'"1C"!=a.L&&16.1h(a,"11")!="1T"&&16.1h(a,"3V")!="1C"\',1C:\'"1C"==a.L||16.1h(a,"11")=="1T"||16.1h(a,"3V")=="1C"\',7R:"!a.30",30:"a.30",27:"a.27",28:"a.28||16.1j(a,\'28\')",2Q:"\'2Q\'==a.L",4e:"\'4e\'==a.L",3i:"\'3i\'==a.L",4v:"\'4v\'==a.L",5C:"\'5C\'==a.L",4u:"\'4u\'==a.L",5B:"\'5B\'==a.L",5A:"\'5A\'==a.L",1X:\'"1X"==a.L||16.W(a,"1X")\',39:"/39|2b|7P|1X/i.1d(a.W)",2N:"16.1F(m[3],a).H"},"[":"16.1F(m[2],a).H"},5x:[/^\\[ *(@)([\\w-]+) *([!*$^~=]*) *(\'?"?)(.*?)\\4 *\\]/,/^(\\[)\\s*(.*?(\\[.*?\\])?[^[]*?)\\s*\\]/,/^(:)([\\w-]+)\\("?\'?(.*?(\\(.*?\\))?[^(]*?)"?\'?\\)/,1s 3C("^([:.#]*)("+A+"+)")],2R:9(a,c,b){E d,1Y=[];20(a&&a!=d){d=a;E f=C.1l(a,c,b);a=f.t.1v(/^\\s*,\\s*/,"");1Y=b?c=f.r:C.29(1Y,f.r)}F 1Y},1F:9(t,l){6(1f t!="1E")F[t];6(l&&!l.1t)l=K;l=l||R;6(!t.U("//")){t=t.2K(2,t.H)}G 6(!t.U("/")&&!l.2I){l=l.3D;t=t.2K(1,t.H);6(t.U("/")>=1)t=t.2K(t.U("/"),t.H)}E d=[l],2q=[],2P;20(t&&2P!=t){E r=[];2P=t;t=C.2s(t).1v(/^\\/\\//,"");E k=M;E g=5I;E m=g.2d(t);6(m){E o=m[1].1I();I(E i=0;d[i];i++)I(E c=d[i].1k;c;c=c.2a)6(c.1t==1&&(o=="*"||c.W.1I()==o.1I()))r.Y(c);d=r;t=t.1v(g,"");6(t.U(" ")==0)5X;k=O}G{g=/^((\\/?\\.\\.)|([>\\/+~]))\\s*(\\w*)/i;6((m=g.2d(t))!=K){r=[];E o=m[4],1q=C.1q++;m=m[1];I(E j=0,2o=d.H;j<2o;j++)6(m.U("..")<0){E n=m=="~"||m=="+"?d[j].2a:d[j].1k;I(;n;n=n.2a)6(n.1t==1){6(m=="~"&&n.1q==1q)1J;6(!o||n.W.1I()==o.1I()){6(m=="~")n.1q=1q;r.Y(n)}6(m=="+")1J}}G r.Y(d[j].P);d=r;t=C.2s(t.1v(g,""));k=O}}6(t&&!k){6(!t.U(",")){6(l==d[0])d.4s();2q=C.29(2q,d);r=d=[l];t=" "+t.2K(1,t.H)}G{E h=5H;E m=h.2d(t);6(m){m=[0,m[2],m[3],m[1]]}G{h=5G;m=h.2d(t)}m[2]=m[2].1v(/\\\\/g,"");E f=d[d.H-1];6(m[1]=="#"&&f&&f.37&&!C.3E(f)){E p=f.37(m[2]);6((C.N.12||C.N.2t)&&p&&1f p.2j=="1E"&&p.2j!=m[2])p=C(\'[@2j="\'+m[2]+\'"]\',f)[0];d=r=p&&(!m[3]||C.W(p,m[3]))?[p]:[]}G{I(E i=0;d[i];i++){E a=m[1]!=""||m[0]==""?"*":m[2];6(a=="*"&&d[i].W.2D()=="4P")a="2O";r=C.29(r,d[i].4L(a))}6(m[1]==".")r=C.4r(r,m[2]);6(m[1]=="#"){E e=[];I(E i=0;r[i];i++)6(r[i].3F("2j")==m[2]){e=[r[i]];1J}r=e}d=r}t=t.1v(h,"")}}6(t){E b=C.1l(t,r);d=r=b.r;t=C.2s(b.t)}}6(t)d=[];6(d&&l==d[0])d.4s();2q=C.29(2q,d);F 2q},4r:9(r,m,a){m=" "+m+" ";E c=[];I(E i=0;r[i];i++){E b=(" "+r[i].18+" ").U(m)>=0;6(!a&&b||a&&!b)c.Y(r[i])}F c},1l:9(t,r,h){E d;20(t&&t!=d){d=t;E p=C.5x,m;I(E i=0;p[i];i++){m=p[i].2d(t);6(m){t=t.7N(m[0].H);m[2]=m[2].1v(/\\\\/g,"");1J}}6(!m)1J;6(m[1]==":"&&m[2]=="5l")r=C.1l(m[3],r,O).r;G 6(m[1]==".")r=C.4r(r,m[2],h);G 6(m[1]=="@"){E g=[],L=m[3];I(E i=0,2o=r.H;i<2o;i++){E a=r[i],z=a[C.4q[m[2]]||m[2]];6(z==K||/5R|32|28/.1d(m[2]))z=C.1j(a,m[2])||\'\';6((L==""&&!!z||L=="="&&z==m[5]||L=="!="&&z!=m[5]||L=="^="&&z&&!z.U(m[5])||L=="$="&&z.2K(z.H-m[5].H)==m[5]||(L=="*="||L=="~=")&&z.U(m[5])>=0)^h)g.Y(a)}r=g}G 6(m[1]==":"&&m[2]=="25-3z"){E e=C.1q++,g=[],1d=/(\\d*)n\\+?(\\d*)/.2d(m[3]=="5E"&&"2n"||m[3]=="5D"&&"2n+1"||!/\\D/.1d(m[3])&&"n+"+m[3]||m[3]),2H=(1d[1]||1)-0,d=1d[2]-0;I(E i=0,2o=r.H;i<2o;i++){E j=r[i],P=j.P;6(e!=P.1q){E c=1;I(E n=P.1k;n;n=n.2a)6(n.1t==1)n.4o=c++;P.1q=e}E b=M;6(2H==1){6(d==0||j.4o==d)b=O}G 6((j.4o+d)%2H==0)b=O;6(b^h)g.Y(j)}r=g}G{E f=C.4w[m[1]];6(1f f!="1E")f=C.4w[m[1]][m[2]];f=2T("M||9(a,i){F "+f+"}");r=C.2B(r,f,h)}}F{r:r,t:t}},4C:9(c){E b=[];E a=c.P;20(a&&a!=R){b.Y(a);a=a.P}F b},25:9(a,e,c,b){e=e||1;E d=0;I(;a;a=a[c])6(a.1t==1&&++d==e)1J;F a},4A:9(n,a){E r=[];I(;n;n=n.2a){6(n.1t==1&&(!a||n!=a))r.Y(n)}F r}});C.1c={1r:9(f,d,c,b){6(C.N.12&&f.3t!=Q)f=19;6(!c.22)c.22=7.22++;6(b!=Q){E e=c;c=9(){F e.T(7,1a)};c.V=b;c.22=e.22}6(!f.$1i)f.$1i={};6(!f.$1y)f.$1y=9(){E a;6(1f C=="Q"||C.1c.4n)F a;a=C.1c.1y.T(f,1a);F a};E g=f.$1i[d];6(!g){g=f.$1i[d]={};6(f.4m)f.4m(d,f.$1y,M);G f.7M("3r"+d,f.$1y)}g[c.22]=c;7.1D[d]=O},22:1,1D:{},23:9(c,b,a){E d=c.$1i,2c,45;6(d){6(b&&b.L){a=b.4l;b=b.L}6(!b){I(b 17 d)7.23(c,b)}G 6(d[b]){6(a)4k d[b][a.22];G I(a 17 c.$1i[b])4k d[b][a];I(2c 17 d[b])1J;6(!2c){6(c.4j)c.4j(b,c.$1y,M);G c.7L("3r"+b,c.$1y);2c=K;4k d[b]}}I(2c 17 d)1J;6(!2c)c.$1y=c.$1i=K}},1z:9(c,b,d){b=C.2V(b||[]);6(!d){6(7.1D[c])C("*").1r([19,R]).1z(c,b)}G{E a,2c,15=C.1g(d[c]||K);b.42(7.4i({L:c,1S:d}));6(C.1g(d.$1y))a=d.$1y.T(d,b);6(!15&&d["3r"+c]&&d["3r"+c].T(d,b)===M)a=M;6(15&&a!==M&&!(C.W(d,\'a\')&&c=="4h")){7.4n=O;d[c]()}7.4n=M}},1y:9(b){E a;b=C.1c.4i(b||19.1c||{});E c=7.$1i&&7.$1i[b.L],2e=1K.3v.3S.2S(1a,1);2e.42(b);I(E j 17 c){2e[0].4l=c[j];2e[0].V=c[j].V;6(c[j].T(7,2e)===M){b.2u();b.2X();a=M}}6(C.N.12)b.1S=b.2u=b.2X=b.4l=b.V=K;F a},4i:9(c){E a=c;c=C.14({},a);c.2u=9(){6(a.2u)a.2u();a.7I=M};c.2X=9(){6(a.2X)a.2X();a.7H=O};6(!c.1S&&c.5r)c.1S=c.5r;6(C.N.1H&&c.1S.1t==3)c.1S=a.1S.P;6(!c.4g&&c.4F)c.4g=c.4F==c.1S?c.7C:c.4F;6(c.5p==K&&c.66!=K){E e=R.3D,b=R.4z;c.5p=c.66+(e&&e.5o||b.5o||0);c.7z=c.7v+(e&&e.5m||b.5m||0)}6(!c.3Q&&(c.5k||c.5j))c.3Q=c.5k||c.5j;6(!c.5i&&c.5g)c.5i=c.5g;6(!c.3Q&&c.1X)c.3Q=(c.1X&1?1:(c.1X&2?3:(c.1X&4?2:0)));F c}};C.15.14({3l:9(c,a,b){F c=="5f"?7.5e(c,a,b):7.J(9(){C.1c.1r(7,c,b||a,b&&a)})},5e:9(d,b,c){F 7.J(9(){C.1c.1r(7,d,9(a){C(7).49(a);F(c||b).T(7,1a)},c&&b)})},49:9(a,b){F 7.J(9(){C.1c.23(7,a,b)})},1z:9(a,b){F 7.J(9(){C.1c.1z(a,b,7)})},1W:9(){E a=1a;F 7.4h(9(e){7.3T=0==7.3T?1:0;e.2u();F a[7.3T].T(7,[e])||M})},7p:9(f,g){9 3U(e){E p=e.4g;20(p&&p!=7)2g{p=p.P}2h(e){p=7};6(p==7)F M;F(e.L=="3W"?f:g).T(7,[e])}F 7.3W(3U).5b(3U)},1L:9(f){5a();6(C.36)f.T(R,[C]);G C.2C.Y(9(){F f.T(7,[C])});F 7}});C.14({36:M,2C:[],1L:9(){6(!C.36){C.36=O;6(C.2C){C.J(C.2C,9(){7.T(R)});C.2C=K}6(C.N.3J||C.N.2t)R.4j("59",C.1L,M);6(!19.7m.H)C(19).2f(9(){C("#4b").23()})}}});C.J(("7l,7k,2f,7j,7i,5f,4h,7g,"+"7f,7d,7c,3W,5b,7b,2b,"+"4u,7a,79,78,3f").2M(","),9(i,o){C.15[o]=9(f){F f?7.3l(o,f):7.1z(o)}});E w=M;9 5a(){6(w)F;w=O;6(C.N.3J||C.N.2t)R.4m("59",C.1L,M);G 6(C.N.12){R.75("<73"+"72 2j=4b 70=O "+"32=//:><\\/33>");E a=R.37("4b");6(a)a.6Z=9(){6(R.3d!="1x")F;C.1L()};a=K}G 6(C.N.1H)C.48=3t(9(){6(R.3d=="6Y"||R.3d=="1x"){47(C.48);C.48=K;C.1L()}},10);C.1c.1r(19,"2f",C.1L)}C.15.14({6X:9(c,b,a){7.2f(c,b,a,1)},2f:9(g,e,c,d){6(C.1g(g))F 7.3l("2f",g);c=c||9(){};E f="46";6(e)6(C.1g(e)){c=e;e=K}G{e=C.2O(e);f="55"}E h=7;C.31({1G:g,L:f,V:e,2F:d,1x:9(a,b){6(b=="1U"||!d&&b=="54")h.5W(a.43);4x(9(){h.J(c,[a.43,b,a])},13)}});F 7},6W:9(){F C.2O(7)},6V:9(){}});C.J("53,52,51,50,4Z,5h".2M(","),9(i,o){C.15[o]=9(f){F 7.3l(o,f)}});C.14({21:9(e,c,a,d,b){6(C.1g(c)){a=c;c=K}F C.31({L:"46",1G:e,V:c,1U:a,3G:d,2F:b})},6U:9(d,b,a,c){F C.21(d,b,a,c,1)},6T:9(b,a){F C.21(b,K,a,"33")},77:9(c,b,a){F C.21(c,b,a,"56")},6S:9(d,b,a,c){6(C.1g(b)){a=b;b={}}F C.31({L:"55",1G:d,V:b,1U:a,3G:c})},6R:9(a){C.3u.1Q=a},6Q:9(a){C.14(C.3u,a)},3u:{1D:O,L:"46",1Q:0,4Y:"6P/x-6O-38-6N",4X:O,2w:O,V:K},3h:{},31:9(s){s=C.14(O,s,C.14(O,{},C.3u,s));6(s.V){6(s.4X&&1f s.V!="1E")s.V=C.2O(s.V);6(s.L.2D()=="21"){s.1G+=(s.1G.U("?")>-1?"&":"?")+s.V;s.V=K}}6(s.1D&&!C.40++)C.1c.1z("53");E f=M;E h=19.4W?1s 4W("6M.6K"):1s 58();h.6J(s.L,s.1G,s.2w);6(s.V)h.4c("7r-7s",s.4Y);6(s.2F)h.4c("6G-3Z-6E",C.3h[s.1G]||"7w, 6C 7y 6B 4J:4J:4J 6z");h.4c("X-7D-7E","58");6(s.4U)s.4U(h);6(s.1D)C.1c.1z("5h",[h,s]);E g=9(d){6(!f&&h&&(h.3d==4||d=="1Q")){f=O;6(i){47(i);i=K}E c=d=="1Q"&&"1Q"||!C.5n(h)&&"3f"||s.2F&&C.5s(h,s.1G)&&"54"||"1U";6(c=="1U"){2g{E a=C.5q(h,s.3G)}2h(e){c="4I"}}6(c=="1U"){E b;2g{b=h.4f("4S-3Z")}2h(e){}6(s.2F&&b)C.3h[s.1G]=b;6(s.1U)s.1U(a,c);6(s.1D)C.1c.1z("4Z",[h,s])}G C.3X(s,h,c);6(s.1D)C.1c.1z("51",[h,s]);6(s.1D&&!--C.40)C.1c.1z("52");6(s.1x)s.1x(h,c);6(s.2w)h=K}};6(s.2w){E i=3t(g,13);6(s.1Q>0)4x(9(){6(h){h.6w();6(!f)g("1Q")}},s.1Q)}2g{h.6v(s.V)}2h(e){C.3X(s,h,K,e)}6(!s.2w)g();F h},3X:9(s,a,b,e){6(s.3f)s.3f(a,b,e);6(s.1D)C.1c.1z("50",[a,s,e])},40:0,5n:9(r){2g{F!r.26&&6t.6r=="4v:"||(r.26>=4R&&r.26<6q)||r.26==5z||C.N.1H&&r.26==Q}2h(e){}F M},5s:9(a,c){2g{E b=a.4f("4S-3Z");F a.26==5z||b==C.3h[c]||C.N.1H&&a.26==Q}2h(e){}F M},5q:9(r,a){E b=r.4f("6o-L");E c=a=="5F"||!a&&b&&b.U("5F")>=0;V=c?r.7W:r.43;6(c&&V.3D.4y=="4I")7X"4I";6(a=="33")C.4E(V);6(a=="56")V=2T("("+V+")");F V},2O:9(a){E s=[];6(a.1b==1K||a.3w)C.J(a,9(){s.Y(2y(7.6l)+"="+2y(7.2A))});G I(E j 17 a)6(a[j]&&a[j].1b==1K)C.J(a[j],9(){s.Y(2y(j)+"="+2y(7))});G s.Y(2y(j)+"="+2y(a[j]));F s.5w("&")}});C.15.14({1o:9(b,a){F b?7.1B({1u:"1o",24:"1o",1e:"1o"},b,a):7.1l(":1C").J(9(){7.S.11=7.2r?7.2r:"";6(C.1h(7,"11")=="1T")7.S.11="2m"}).3L()},1p:9(b,a){F b?7.1B({1u:"1p",24:"1p",1e:"1p"},b,a):7.1l(":4N").J(9(){7.2r=7.2r||C.1h(7,"11");6(7.2r=="1T")7.2r="2m";7.S.11="1T"}).3L()},5O:C.15.1W,1W:9(a,b){F C.1g(a)&&C.1g(b)?7.5O(a,b):a?7.1B({1u:"1W",24:"1W",1e:"1W"},a,b):7.J(9(){C(7)[C(7).3y(":1C")?"1o":"1p"]()})},6i:9(b,a){F 7.1B({1u:"1o"},b,a)},6h:9(b,a){F 7.1B({1u:"1p"},b,a)},6g:9(b,a){F 7.1B({1u:"1W"},b,a)},6f:9(b,a){F 7.1B({1e:"1o"},b,a)},89:9(b,a){F 7.1B({1e:"1p"},b,a)},6e:9(c,a,b){F 7.1B({1e:a},c,b)},1B:9(d,h,f,g){F 7.1n(9(){E c=C(7).3y(":1C"),1Z=C.5V(h,f,g),5U=7;I(E p 17 d){6(d[p]=="1p"&&c||d[p]=="1o"&&!c)F C.1g(1Z.1x)&&1Z.1x.T(7);6(p=="1u"||p=="24"){1Z.11=C.1h(7,"11");1Z.2z=7.S.2z}}6(1Z.2z!=K)7.S.2z="1C";7.2v=C.14({},d);C.J(d,9(a,b){E e=1s C.2Y(5U,1Z,a);6(b.1b==3x)e.3R(e.1Y()||0,b);G e[b=="1W"?c?"1o":"1p":b](d)});F O})},1n:9(a,b){6(!b){b=a;a="2Y"}F 7.J(9(){6(!7.1n)7.1n={};6(!7.1n[a])7.1n[a]=[];7.1n[a].Y(b);6(7.1n[a].H==1)b.T(7)})}});C.14({5V:9(b,a,c){E d=b&&b.1b==8G?b:{1x:c||!c&&a||C.1g(b)&&b,1N:b,35:c&&a||a&&a.1b!=8F&&a};d.1N=(d.1N&&d.1N.1b==3x?d.1N:{8D:8C,8B:4R}[d.1N])||8A;d.2U=d.1x;d.1x=9(){C.68(7,"2Y");6(C.1g(d.2U))d.2U.T(7)};F d},35:{62:9(p,n,b,a){F b+a*p},4H:9(p,n,b,a){F((-67.8z(p*67.8y)/2)+0.5)*a+b}},1n:{},68:9(b,a){a=a||"2Y";6(b.1n&&b.1n[a]){b.1n[a].4s();E f=b.1n[a][0];6(f)f.T(b)}},3N:[],2Y:9(f,e,g){E z=7;E y=f.S;z.a=9(){6(e.3q)e.3q.T(f,[z.2x]);6(g=="1e")C.1j(y,"1e",z.2x);G{y[g]=5K(z.2x)+"4t";6(g=="1u"||g=="24")y.11="2m"}};z.65=9(){F 3m(C.1h(f,g))};z.1Y=9(){E r=3m(C.34(f,g));F r&&r>-8v?r:z.65()};z.3R=9(c,b){z.4M=(1s 64()).63();z.2x=c;z.a();C.3N.Y(9(){F z.3q(c,b)});6(C.3N.H==1){E d=3t(9(){E a=C.3N;I(E i=0;i<a.H;i++)6(!a[i]())a.8t(i--,1);6(!a.H)47(d)},13)}};z.1o=9(){6(!f.2i)f.2i={};f.2i[g]=C.1j(f.S,g);e.1o=O;z.3R(0,7.1Y());6(g!="1e")y[g]="8r";C(f).1o()};z.1p=9(){6(!f.2i)f.2i={};f.2i[g]=C.1j(f.S,g);e.1p=O;z.3R(7.1Y(),0)};z.3q=9(a,c){E t=(1s 64()).63();6(t>e.1N+z.4M){z.2x=c;z.a();6(f.2v)f.2v[g]=O;E b=O;I(E i 17 f.2v)6(f.2v[i]!==O)b=M;6(b){6(e.11!=K){y.2z=e.2z;y.11=e.11;6(C.1h(f,"11")=="1T")y.11="2m"}6(e.1p)y.11="1T";6(e.1p||e.1o)I(E p 17 f.2v)C.1j(y,p,f.2i[p])}6(b&&C.1g(e.1x))e.1x.T(f);F M}G{E n=t-7.4M;E p=n/e.1N;z.2x=C.35[e.35||(C.35.4H?"4H":"62")](p,n,a,(c-a),e.1N);z.a()}F O}}})})();',62,541,'||||||if|this||function|||||||||||||||||||||||||||||||var|return|else|length|for|each|null|type|false|browser|true|parentNode|undefined|document|style|apply|indexOf|data|nodeName||push|||display|msie||extend|fn|jQuery|in|className|window|arguments|constructor|event|test|opacity|typeof|isFunction|css|events|attr|firstChild|filter|div|queue|show|hide|mergeNum|add|new|nodeType|height|replace|tbody|complete|handle|trigger|table|animate|hidden|global|string|find|url|safari|toUpperCase|break|Array|ready|al|duration|pushStack|tb|timeout|stack|target|none|success|swap|toggle|button|cur|opt|while|get|guid|remove|width|nth|status|checked|selected|merge|nextSibling|select|ret|exec|args|load|try|catch|orig|id|match|_|block||rl|insertBefore|done|oldblock|trim|opera|preventDefault|curAnim|async|now|encodeURIComponent|overflow|value|grep|readyList|toLowerCase|color|ifModified|val|first|ownerDocument|domManip|substr|defaultView|split|has|param|last|text|multiFilter|call|eval|old|makeArray|innerHTML|stopPropagation|fx|childNodes|disabled|ajax|src|script|curCSS|easing|isReady|getElementById|form|input|float|getComputedStyle|clean|readyState|removeChild|error|static|lastModified|checkbox|selectedIndex|position|bind|parseFloat|String|oWidth|oHeight|step|on|toString|setInterval|ajaxSettings|prototype|jquery|Number|is|child|ol|cloneNode|RegExp|documentElement|isXMLDoc|getAttribute|dataType|append|styleFloat|mozilla|empty|end|map|timers|tr|el|which|custom|slice|lastToggle|handleHover|visibility|mouseover|handleError|lastChild|Modified|active|currentStyle|unshift|responseText|getPropertyValue|index|GET|clearInterval|safariTimer|unbind|init|__ie_init|setRequestHeader|unique|radio|getResponseHeader|relatedTarget|click|fix|removeEventListener|delete|handler|addEventListener|triggered|nodeIndex|appendChild|props|classFilter|shift|px|submit|file|expr|setTimeout|tagName|body|sibling|previousSibling|parents|deep|globalEval|fromElement|cssFloat|swing|parsererror|00|inArray|getElementsByTagName|startTime|visible|num|object|prop|200|Last|colgroup|beforeSend|fieldset|ActiveXObject|processData|contentType|ajaxSuccess|ajaxError|ajaxComplete|ajaxStop|ajaxStart|notmodified|POST|json|appendTo|XMLHttpRequest|DOMContentLoaded|bindReady|mouseout|prevObject|removeAttr|one|unload|ctrlKey|ajaxSend|metaKey|keyCode|charCode|not|scrollTop|httpSuccess|scrollLeft|pageX|httpData|srcElement|httpNotModified|after|before|prepend|join|parse|zoom|304|reset|image|password|odd|even|xml|quickClass|quickID|quickChild|setArray|parseInt|contains|gt|execScript|_toggle|lt|eq|href|nodeValue|alpha|self|speed|html|continue|parent|textContent|createTextNode|webkit|linear|getTime|Date|max|clientX|Math|dequeue|fl|createElement|version|100|NaN|fadeTo|fadeIn|slideToggle|slideUp|slideDown|setAttribute|getAttributeNode|name|method|action|content|cssText|300|protocol|FORM|location|options|send|abort|col|th|GMT|td|1970|01|cap|Since|colg|If|tfoot|thead|open|XMLHTTP|leg|Microsoft|urlencoded|www|application|ajaxSetup|ajaxTimeout|post|getScript|getIfModified|evalScripts|serialize|loadIfModified|loaded|onreadystatechange|defer|clientWidth|ipt|scr|clientHeight|write|relative|getJSON|keyup|keypress|keydown|change|mousemove|mouseup|left|mousedown|dblclick|right|scroll|resize|focus|blur|frames|absolute|clone|hover|offsetWidth|Content|Type|offsetHeight|Width|clientY|Thu|border|Jan|pageY|padding|Left|toElement|Requested|With|Right|Bottom|cancelBubble|returnValue|Top|size|detachEvent|attachEvent|substring|line|textarea|weight|enabled|font|innerText|only|uFFFF|responseXML|throw|u0128|417|toggleClass|removeClass|wrap|addClass|removeAttribute|insertAfter|prependTo|children|siblings|fadeOut|noConflict|prev|next|Boolean|maxLength|maxlength|readOnly|readonly|class|htmlFor|CSS1Compat|compatMode|boxModel|compatible|ie|ra|it|1px|rv|splice|userAgent|10000|navigator|concat|PI|cos|400|fast|600|slow|reverse|Function|Object|array|ig'.split('|'),0,{}))
\ No newline at end of file
diff --git a/jscripts/jquery/GPL-LICENSE.txt b/jscripts/jquery/GPL-LICENSE.txt
new file mode 100644 (file)
index 0000000..11dddd0
--- /dev/null
@@ -0,0 +1,278 @@
+        GNU GENERAL PUBLIC LICENSE
+           Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+          Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+        GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+          NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
diff --git a/jscripts/jquery/MIT-LICENSE.txt b/jscripts/jquery/MIT-LICENSE.txt
new file mode 100644 (file)
index 0000000..965a831
--- /dev/null
@@ -0,0 +1,20 @@
+Copyright (c) 2007 John Resig, http://jquery.com/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/jscripts/jquery/jARIA.js b/jscripts/jquery/jARIA.js
new file mode 100644 (file)
index 0000000..cd48686
--- /dev/null
@@ -0,0 +1 @@
+(function(E){var C="http://www.w3.org/2005/07/aaa";var F=["main","secondary","navigation","banner","contentinfo","statements","note","seealso","search"];var A=new RegExp("^"+F.join("|")+"$");var D=E.browser.mozilla&&(parseFloat(E.browser.version)<1.9);var B=(function(){if(D){return function(I,G,H){if(typeof H!="undefined"){I.each(function(J,K){K.setAttributeNS(C,G,H)})}else{return I.get(0).getAttributeNS(C,G)}}}else{return function(I,G,H){if(typeof H!="undefined"){I.each(function(J,K){E(K).attr("aria-"+G,H)})}else{return I.attr("aria-"+G)}}}})();E.fn.extend({ariaRole:function(H){var G=this;if(H){H=(A.test(H)||!D)?H:"wairole:"+H;G.each(function(I,J){E(J).attr("role",H)});return G}else{var H=G.eq(0).attr("role");if(H){H=H.replace(/^wairole:/,"")}return H}},ariaState:function(){var G=arguments;var H=this;if(G.length==2){H.each(function(I,J){B(E(J),G[0],G[1])});return H}else{if(typeof G[0]=="string"){return B(H.eq(0),G[0])}else{H.each(function(I,J){E.each(G[0],function(K,L){E(J).ariaState(K,L)})});return H}}}});E.extend(E.expr[":"],{ariaRole:"jQuery(a).ariaRole()==m[3]",ariaState:"jQuery(a).ariaState(m[3].split(/=/)[0])==(/=/.test(m[3])?m[3].split(/=/)[1]:'true')"})})(jQuery);
\ No newline at end of file
diff --git a/jscripts/jquery/jquery-1.2.3.js b/jscripts/jquery/jquery-1.2.3.js
new file mode 100644 (file)
index 0000000..5899bd4
--- /dev/null
@@ -0,0 +1 @@
+(function(){if(window.jQuery){var _jQuery=window.jQuery}var jQuery=window.jQuery=function(selector,context){return new jQuery.prototype.init(selector,context)};if(window.$){var _$=window.$}window.$=jQuery;var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;var isSimple=/^.[^:#\[\.]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this}else{if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1]){selector=jQuery.clean([match[1]],context)}else{var elem=document.getElementById(match[3]);if(elem){if(elem.id!=match[3]){return jQuery().find(selector)}else{this[0]=elem;this.length=1;return this}}else{selector=[]}}}else{return new jQuery(context).find(selector)}}else{if(jQuery.isFunction(selector)){return new jQuery(document)[jQuery.fn.ready?"ready":"load"](selector)}}}return this.setArray(selector.constructor==Array&&selector||(selector.jquery||selector.length&&selector!=window&&!selector.nodeType&&selector[0]!=undefined&&selector[0].nodeType)&&jQuery.makeArray(selector)||[selector])},jquery:"1.2.3",size:function(){return this.length},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num]},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this},each:function(callback,args){return jQuery.each(this,callback,args)},index:function(elem){var ret=-1;this.each(function(i){if(this==elem){ret=i}});return ret},attr:function(name,value,type){var options=name;if(name.constructor==String){if(value==undefined){return this.length&&jQuery[type||"attr"](this[0],name)||undefined}else{options={};options[name]=value}}return this.each(function(i){for(name in options){jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name))}})},css:function(key,value){if((key=="width"||key=="height")&&parseFloat(value)<0){value=undefined}return this.attr(key,value,"curCSS")},text:function(text){if(typeof text!="object"&&text!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text))}var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8){ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this])}})});return ret},wrapAll:function(html){if(this[0]){jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild){elem=elem.firstChild}return elem}).append(this)}return this},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html)})},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html)})},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1){this.appendChild(elem)}})},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1){this.insertBefore(elem,this.firstChild)}})},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this)})},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling)})},end:function(){return this.prevObject||jQuery([])},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem)});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems)},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0]}else{return this.cloneNode(true)}});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined){this[expando]=null}});if(events===true){this.find("*").andSelf().each(function(i){if(this.nodeType==3){return }var events=jQuery.data(this,"events");for(var type in events){for(var handler in events[type]){jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data)}}})}return ret},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i)})||jQuery.multiFilter(selector,this))},not:function(selector){if(selector.constructor==String){if(isSimple.test(selector)){return this.pushStack(jQuery.multiFilter(selector,this,true))}else{selector=jQuery.multiFilter(selector,this)}}var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector})},add:function(selector){return !selector?this:this.pushStack(jQuery.merge(this.get(),selector.constructor==String?jQuery(selector).get():selector.length!=undefined&&(!selector.nodeName||jQuery.nodeName(selector,"form"))?selector:[selector]))},is:function(selector){return selector?jQuery.multiFilter(selector,this).length>0:false},hasClass:function(selector){return this.is("."+selector)},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0){return null}for(var i=one?index:0,max=one?index+1:options.length;i<max;i++){var option=options[i];if(option.selected){value=jQuery.browser.msie&&!option.attributes.value.specified?option.text:option.value;if(one){return value}values.push(value)}}return values}else{return(this[0].value||"").replace(/\r/g,"")}}return undefined}return this.each(function(){if(this.nodeType!=1){return }if(value.constructor==Array&&/radio|checkbox/.test(this.type)){this.checked=(jQuery.inArray(this.value,value)>=0||jQuery.inArray(this.name,value)>=0)}else{if(jQuery.nodeName(this,"select")){var values=value.constructor==Array?value:[value];jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0)});if(!values.length){this.selectedIndex=-1}}else{this.value=value}}})},html:function(value){return value==undefined?(this.length?this[0].innerHTML:null):this.empty().append(value)},replaceWith:function(value){return this.after(value).remove()},eq:function(i){return this.slice(i,i+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments))},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem)}))},andSelf:function(){return this.add(this.prevObject)},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value==null){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data==undefined&&this.length){data=jQuery.data(this[0],key)}return data==null&&parts[1]?this.data(parts[0]):data}else{return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value)})}},removeData:function(key){return this.each(function(){jQuery.removeData(this,key)})},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse){elems.reverse()}}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr")){obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"))}var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script")){scripts=scripts.add(elem)}else{if(elem.nodeType==1){scripts=scripts.add(jQuery("script",elem).remove())}callback.call(obj,elem)}});scripts.each(evalScript)})}};jQuery.prototype.init.prototype=jQuery.prototype;function evalScript(i,elem){if(elem.src){jQuery.ajax({url:elem.src,async:false,dataType:"script"})}else{jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"")}if(elem.parentNode){elem.parentNode.removeChild(elem)}}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2}if(typeof target!="object"&&typeof target!="function"){target={}}if(length==1){target=this;i=0}for(;i<length;i++){if((options=arguments[i])!=null){for(var name in options){if(target===options[name]){continue}if(deep&&options[name]&&typeof options[name]=="object"&&target[name]&&!options[name].nodeType){target[name]=jQuery.extend(target[name],options[name])}else{if(options[name]!=undefined){target[name]=options[name]}}}}}return target};var expando="jQuery"+(new Date()).getTime(),uuid=0,windowData={};var exclude=/z-?index|font-?weight|opacity|zoom|line-?height/i;jQuery.extend({noConflict:function(deep){window.$=_$;if(deep){window.jQuery=_jQuery}return jQuery},isFunction:function(fn){return !!fn&&typeof fn!="string"&&!fn.nodeName&&fn.constructor!=Array&&/function/i.test(fn+"")},isXMLDoc:function(elem){return elem.documentElement&&!elem.body||elem.tagName&&elem.ownerDocument&&!elem.ownerDocument.body},globalEval:function(data){data=jQuery.trim(data);if(data){var head=document.getElementsByTagName("head")[0]||document.documentElement,script=document.createElement("script");script.type="text/javascript";if(jQuery.browser.msie){script.text=data}else{script.appendChild(document.createTextNode(data))}head.appendChild(script);head.removeChild(script)}},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toUpperCase()==name.toUpperCase()},cache:{},data:function(elem,name,data){elem=elem==window?windowData:elem;var id=elem[expando];if(!id){id=elem[expando]=++uuid}if(name&&!jQuery.cache[id]){jQuery.cache[id]={}}if(data!=undefined){jQuery.cache[id][name]=data}return name?jQuery.cache[id][name]:id},removeData:function(elem,name){elem=elem==window?windowData:elem;var id=elem[expando];if(name){if(jQuery.cache[id]){delete jQuery.cache[id][name];name="";for(name in jQuery.cache[id]){break}if(!name){jQuery.removeData(elem)}}}else{try{delete elem[expando]}catch(e){if(elem.removeAttribute){elem.removeAttribute(expando)}}delete jQuery.cache[id]}},each:function(object,callback,args){if(args){if(object.length==undefined){for(var name in object){if(callback.apply(object[name],args)===false){break}}}else{for(var i=0,length=object.length;i<length;i++){if(callback.apply(object[i],args)===false){break}}}}else{if(object.length==undefined){for(var name in object){if(callback.call(object[name],name,object[name])===false){break}}}else{for(var i=0,length=object.length,value=object[0];i<length&&callback.call(value,i,value)!==false;value=object[++i]){}}}return object},prop:function(elem,value,type,i,name){if(jQuery.isFunction(value)){value=value.call(elem,i)}return value&&value.constructor==Number&&type=="curCSS"&&!exclude.test(name)?value+"px":value},className:{add:function(elem,classNames){jQuery.each((classNames||"").split(/\s+/),function(i,className){if(elem.nodeType==1&&!jQuery.className.has(elem.className,className)){elem.className+=(elem.className?" ":"")+className}})},remove:function(elem,classNames){if(elem.nodeType==1){elem.className=classNames!=undefined?jQuery.grep(elem.className.split(/\s+/),function(className){return !jQuery.className.has(classNames,className)}).join(" "):""}},has:function(elem,className){return jQuery.inArray(className,(elem.className||elem).toString().split(/\s+/))>-1}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name]}callback.call(elem);for(var name in options){elem.style[name]=old[name]}},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0});val-=Math.round(padding+border)}if(jQuery(elem).is(":visible")){getWH()}else{jQuery.swap(elem,props,getWH)}return Math.max(0,val)}return jQuery.curCSS(elem,name,force)},curCSS:function(elem,name,force){var ret;function color(elem){if(!jQuery.browser.safari){return false}var ret=document.defaultView.getComputedStyle(elem,null);return !ret||ret.getPropertyValue("color")==""}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(elem.style,"opacity");return ret==""?"1":ret}if(jQuery.browser.opera&&name=="display"){var save=elem.style.outline;elem.style.outline="0 solid black";elem.style.outline=save}if(name.match(/float/i)){name=styleFloat}if(!force&&elem.style&&elem.style[name]){ret=elem.style[name]}else{if(document.defaultView&&document.defaultView.getComputedStyle){if(name.match(/float/i)){name="float"}name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var getComputedStyle=document.defaultView.getComputedStyle(elem,null);if(getComputedStyle&&!color(elem)){ret=getComputedStyle.getPropertyValue(name)}else{var swap=[],stack=[];for(var a=elem;a&&color(a);a=a.parentNode){stack.unshift(a)}for(var i=0;i<stack.length;i++){if(color(stack[i])){swap[i]=stack[i].style.display;stack[i].style.display="block"}}ret=name=="display"&&swap[stack.length-1]!=null?"none":(getComputedStyle&&getComputedStyle.getPropertyValue(name))||"";for(var i=0;i<swap.length;i++){if(swap[i]!=null){stack[i].style.display=swap[i]}}}if(name=="opacity"&&ret==""){ret="1"}}else{if(elem.currentStyle){var camelCase=name.replace(/\-(\w)/g,function(all,letter){return letter.toUpperCase()});ret=elem.currentStyle[name]||elem.currentStyle[camelCase];if(!/^\d+(px)?$/i.test(ret)&&/^\d/.test(ret)){var style=elem.style.left,runtimeStyle=elem.runtimeStyle.left;elem.runtimeStyle.left=elem.currentStyle.left;elem.style.left=ret||0;ret=elem.style.pixelLeft+"px";elem.style.left=style;elem.runtimeStyle.left=runtimeStyle}}}}return ret},clean:function(elems,context){var ret=[];context=context||document;if(typeof context.createElement=="undefined"){context=context.ownerDocument||context[0]&&context[0].ownerDocument||document}jQuery.each(elems,function(i,elem){if(!elem){return }if(elem.constructor==Number){elem=elem.toString()}if(typeof elem=="string"){elem=elem.replace(/(<(\w+)[^>]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+"></"+tag+">"});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!tags.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!tags.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!tags.indexOf("<td")||!tags.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!tags.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||jQuery.browser.msie&&[1,"div<div>","</div>"]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--){div=div.lastChild}if(jQuery.browser.msie){var tbody=!tags.indexOf("<table")&&tags.indexOf("<tbody")<0?div.firstChild&&div.firstChild.childNodes:wrap[1]=="<table>"&&tags.indexOf("<tbody")<0?div.childNodes:[];for(var j=tbody.length-1;j>=0;--j){if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length){tbody[j].parentNode.removeChild(tbody[j])}}if(/^\s/.test(elem)){div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild)}}elem=jQuery.makeArray(div.childNodes)}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select"))){return }if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options){ret.push(elem)}else{ret=jQuery.merge(ret,elem)}});return ret},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8){return undefined}var fix=jQuery.isXMLDoc(elem)?{}:jQuery.props;if(name=="selected"&&jQuery.browser.safari){elem.parentNode.selectedIndex}if(fix[name]){if(value!=undefined){elem[fix[name]]=value}return elem[fix[name]]}else{if(jQuery.browser.msie&&name=="style"){return jQuery.attr(elem.style,"cssText",value)}else{if(value==undefined&&jQuery.browser.msie&&jQuery.nodeName(elem,"form")&&(name=="action"||name=="method")){return elem.getAttributeNode(name).nodeValue}else{if(elem.tagName){if(value!=undefined){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode){throw"type property can't be changed"}elem.setAttribute(name,""+value)}if(jQuery.browser.msie&&/href|src/.test(name)&&!jQuery.isXMLDoc(elem)){return elem.getAttribute(name,2)}return elem.getAttribute(name)}else{if(name=="opacity"&&jQuery.browser.msie){if(value!=undefined){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseFloat(value).toString()=="NaN"?"":"alpha(opacity="+value*100+")")}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100).toString():""}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase()});if(value!=undefined){elem[name]=value}return elem[name]}}}}},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"")},makeArray:function(array){var ret=[];if(typeof array!="array"){for(var i=0,length=array.length;i<length;i++){ret.push(array[i])}}else{ret=array.slice(0)}return ret},inArray:function(elem,array){for(var i=0,length=array.length;i<length;i++){if(array[i]==elem){return i}}return -1},merge:function(first,second){if(jQuery.browser.msie){for(var i=0;second[i];i++){if(second[i].nodeType!=8){first.push(second[i])}}}else{for(var i=0;second[i];i++){first.push(second[i])}}return first},unique:function(array){var ret=[],done={};try{for(var i=0,length=array.length;i<length;i++){var id=jQuery.data(array[i]);if(!done[id]){done[id]=true;ret.push(array[i])}}}catch(e){ret=array}return ret},grep:function(elems,callback,inv){var ret=[];for(var i=0,length=elems.length;i<length;i++){if(!inv&&callback(elems[i],i)||inv&&!callback(elems[i],i)){ret.push(elems[i])}}return ret},map:function(elems,callback){var ret=[];for(var i=0,length=elems.length;i<length;i++){var value=callback(elems[i],i);if(value!==null&&value!=undefined){if(value.constructor!=Array){value=[value]}ret=ret.concat(value)}}return ret}});var userAgent=navigator.userAgent.toLowerCase();jQuery.browser={version:(userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1],safari:/webkit/.test(userAgent),opera:/opera/.test(userAgent),msie:/msie/.test(userAgent)&&!/opera/.test(userAgent),mozilla:/mozilla/.test(userAgent)&&!/(compatible|webkit)/.test(userAgent)};var styleFloat=jQuery.browser.msie?"styleFloat":"cssFloat";jQuery.extend({boxModel:!jQuery.browser.msie||document.compatMode=="CSS1Compat",props:{"for":"htmlFor","class":"className","float":styleFloat,cssFloat:styleFloat,styleFloat:styleFloat,innerHTML:"innerHTML",className:"className",value:"value",disabled:"disabled",checked:"checked",readonly:"readOnly",selected:"selected",maxlength:"maxLength",selectedIndex:"selectedIndex",defaultValue:"defaultValue",tagName:"tagName",nodeName:"nodeName"}});jQuery.each({parent:function(elem){return elem.parentNode},parents:function(elem){return jQuery.dir(elem,"parentNode")},next:function(elem){return jQuery.nth(elem,2,"nextSibling")},prev:function(elem){return jQuery.nth(elem,2,"previousSibling")},nextAll:function(elem){return jQuery.dir(elem,"nextSibling")},prevAll:function(elem){return jQuery.dir(elem,"previousSibling")},siblings:function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem)},children:function(elem){return jQuery.sibling(elem.firstChild)},contents:function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes)}},function(name,fn){jQuery.fn[name]=function(selector){var ret=jQuery.map(this,fn);if(selector&&typeof selector=="string"){ret=jQuery.multiFilter(selector,ret)}return this.pushStack(jQuery.unique(ret))}});jQuery.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(name,original){jQuery.fn[name]=function(){var args=arguments;return this.each(function(){for(var i=0,length=args.length;i<length;i++){jQuery(args[i])[original](this)}})}});jQuery.each({removeAttr:function(name){jQuery.attr(this,name,"");if(this.nodeType==1){this.removeAttribute(name)}},addClass:function(classNames){jQuery.className.add(this,classNames)},removeClass:function(classNames){jQuery.className.remove(this,classNames)},toggleClass:function(classNames){jQuery.className[jQuery.className.has(this,classNames)?"remove":"add"](this,classNames)},remove:function(selector){if(!selector||jQuery.filter(selector,[this]).r.length){jQuery("*",this).add(this).each(function(){jQuery.event.remove(this);jQuery.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){jQuery(">*",this).remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments)}});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px")}});var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2])},"#":function(a,i,m){return a.getAttribute("id")==m[2]},":":{lt:function(a,i,m){return i<m[3]-0},gt:function(a,i,m){return i>m[3]-0},nth:function(a,i,m){return m[3]-0==i},eq:function(a,i,m){return m[3]-0==i},first:function(a,i){return i==0},last:function(a,i,m,r){return i==r.length-1},even:function(a,i){return i%2==0},odd:function(a,i){return i%2},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a},"only-child":function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling")},parent:function(a){return a.firstChild},empty:function(a){return !a.firstChild},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden"},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden"},enabled:function(a){return !a.disabled},disabled:function(a){return a.disabled},checked:function(a){return a.checked},selected:function(a){return a.selected||jQuery.attr(a,"selected")},text:function(a){return"text"==a.type},radio:function(a){return"radio"==a.type},checkbox:function(a){return"checkbox"==a.type},file:function(a){return"file"==a.type},password:function(a){return"password"==a.type},submit:function(a){return"submit"==a.type},image:function(a){return"image"==a.type},reset:function(a){return"reset"==a.type},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button")},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},has:function(a,i,m){return jQuery.find(m[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem}).length}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r)}return cur},find:function(t,context){if(typeof t!="string"){return[t]}if(context&&context.nodeType!=1&&context.nodeType!=9){return[]}context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false;var re=quickChild;var m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++){for(var c=ret[i].firstChild;c;c=c.nextSibling){if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName)){r.push(c)}}}ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0){continue}foundToken=true}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j<rl;j++){var n=m=="~"||m=="+"?ret[j].nextSibling:ret[j].firstChild;for(;n;n=n.nextSibling){if(n.nodeType==1){var id=jQuery.data(n);if(m=="~"&&merge[id]){break}if(!nodeName||n.nodeName.toUpperCase()==nodeName){if(m=="~"){merge[id]=true}r.push(n)}if(m=="+"){break}}}}ret=r;t=jQuery.trim(t.replace(re,""));foundToken=true}}if(t&&!foundToken){if(!t.indexOf(",")){if(context==ret[0]){ret.shift()}done=jQuery.merge(done,ret);r=ret=[context];t=" "+t.substr(1,t.length)}else{var re2=quickID;var m=re2.exec(t);if(m){m=[0,m[2],m[3],m[1]]}else{re2=quickClass;m=re2.exec(t)}m[2]=m[2].replace(/\\/g,"");var elem=ret[ret.length-1];if(m[1]=="#"&&elem&&elem.getElementById&&!jQuery.isXMLDoc(elem)){var oid=elem.getElementById(m[2]);if((jQuery.browser.msie||jQuery.browser.opera)&&oid&&typeof oid.id=="string"&&oid.id!=m[2]){oid=jQuery('[@id="'+m[2]+'"]',elem)[0]}ret=r=oid&&(!m[3]||jQuery.nodeName(oid,m[3]))?[oid]:[]}else{for(var i=0;ret[i];i++){var tag=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];if(tag=="*"&&ret[i].nodeName.toLowerCase()=="object"){tag="param"}r=jQuery.merge(r,ret[i].getElementsByTagName(tag))}if(m[1]=="."){r=jQuery.classFilter(r,m[2])}if(m[1]=="#"){var tmp=[];for(var i=0;r[i];i++){if(r[i].getAttribute("id")==m[2]){tmp=[r[i]];break}}r=tmp}ret=r}t=t.replace(re2,"")}}if(t){var val=jQuery.filter(t,r);ret=r=val.r;t=jQuery.trim(val.t)}}if(t){ret=[]}if(ret&&context==ret[0]){ret.shift()}done=jQuery.merge(done,ret);return done},classFilter:function(r,m,not){m=" "+m+" ";var tmp=[];for(var i=0;r[i];i++){var pass=(" "+r[i].className+" ").indexOf(m)>=0;if(!not&&pass||not&&!pass){tmp.push(r[i])}}return tmp},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break}}if(!m){break}if(m[1]==":"&&m[2]=="not"){r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3])}else{if(m[1]=="."){r=jQuery.classFilter(r,m[2],not)}else{if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i<rl;i++){var a=r[i],z=a[jQuery.props[m[2]]||m[2]];if(z==null||/href|src|selected/.test(m[2])){z=jQuery.attr(a,m[2])||""}if((type==""&&!!z||type=="="&&z==m[5]||type=="!="&&z!=m[5]||type=="^="&&z&&!z.indexOf(m[5])||type=="$="&&z.substr(z.length-m[5].length)==m[5]||(type=="*="||type=="~=")&&z.indexOf(m[5])>=0)^not){tmp.push(a)}}r=tmp}else{if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i<rl;i++){var node=r[i],parentNode=node.parentNode,id=jQuery.data(parentNode);if(!merge[id]){var c=1;for(var n=parentNode.firstChild;n;n=n.nextSibling){if(n.nodeType==1){n.nodeIndex=c++}}merge[id]=true}var add=false;if(first==0){if(node.nodeIndex==last){add=true}}else{if((node.nodeIndex-last)%first==0&&(node.nodeIndex-last)/first>=0){add=true}}if(add^not){tmp.push(node)}}r=tmp}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object"){fn=fn[m[2]]}if(typeof fn=="string"){fn=eval("false||function(a,i){return "+fn+";}")}r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r)},not)}}}}}return{r:r,t:t}},dir:function(elem,dir){var matched=[];var cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1){matched.push(cur)}cur=cur[dir]}return matched},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir]){if(cur.nodeType==1&&++num==result){break}}return cur},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&(!elem||n!=elem)){r.push(n)}}return r}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8){return }if(jQuery.browser.msie&&elem.setInterval!=undefined){elem=window}if(!handler.guid){handler.guid=this.guid++}if(data!=undefined){var fn=handler;handler=function(){return fn.apply(this,arguments)};handler.data=data;handler.guid=fn.guid}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){var val;if(typeof jQuery=="undefined"||jQuery.event.triggered){return val}val=jQuery.event.handle.apply(arguments.callee.elem,arguments);return val});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener){elem.addEventListener(type,handle,false)}else{if(elem.attachEvent){elem.attachEvent("on"+type,handle)}}}}handlers[handler.guid]=handler;jQuery.event.global[type]=true});elem=null},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8){return }var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)==".")){for(var type in events){this.remove(elem,type+(types||""))}}else{if(types.type){handler=types.handler;types=types.type}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler){delete events[type][handler.guid]}else{for(handler in events[type]){if(!parts[1]||events[type][handler].type==parts[1]){delete events[type][handler]}}}for(ret in events[type]){break}if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener){elem.removeEventListener(type,jQuery.data(elem,"handle"),false)}else{if(elem.detachEvent){elem.detachEvent("on"+type,jQuery.data(elem,"handle"))}}}ret=null;delete events[type]}}})}for(ret in events){break}if(!ret){var handle=jQuery.data(elem,"handle");if(handle){handle.elem=null}jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle")}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data||[]);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true}if(!elem){if(this.global[type]){jQuery("*").add([window,document]).trigger(type,data)}}else{if(elem.nodeType==3||elem.nodeType==8){return undefined}var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event){data.unshift(this.fix({type:type,target:elem}))}data[0].type=type;if(exclusive){data[0].exclusive=true}if(jQuery.isFunction(jQuery.data(elem,"handle"))){val=jQuery.data(elem,"handle").apply(elem,data)}if(!fn&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false){val=false}if(event){data.shift()}if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined){val=ret}}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,"a")&&type=="click")){this.triggered=true;try{elem[type]()}catch(e){}}this.triggered=false}return val},handle:function(event){var val;event=jQuery.event.fix(event||window.event||{});var parts=event.type.split(".");event.type=parts[0];var handlers=jQuery.data(this,"events")&&jQuery.data(this,"events")[event.type],args=Array.prototype.slice.call(arguments,1);args.unshift(event);for(var j in handlers){var handler=handlers[j];args[0].handler=handler;args[0].data=handler.data;if(!parts[1]&&!event.exclusive||handler.type==parts[1]){var ret=handler.apply(this,args);if(val!==false){val=ret}if(ret===false){event.preventDefault();event.stopPropagation()}}}if(jQuery.browser.msie){event.target=event.preventDefault=event.stopPropagation=event.handler=event.data=null}return val},fix:function(event){var originalEvent=event;event=jQuery.extend({},originalEvent);event.preventDefault=function(){if(originalEvent.preventDefault){originalEvent.preventDefault()}originalEvent.returnValue=false};event.stopPropagation=function(){if(originalEvent.stopPropagation){originalEvent.stopPropagation()}originalEvent.cancelBubble=true};if(!event.target){event.target=event.srcElement||document}if(event.target.nodeType==3){event.target=originalEvent.target.parentNode}if(!event.relatedTarget&&event.fromElement){event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement}if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0)}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode)){event.which=event.charCode||event.keyCode}if(!event.metaKey&&event.ctrlKey){event.metaKey=event.ctrlKey}if(!event.which&&event.button){event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)))}return event},special:{ready:{setup:function(){bindReady();return },teardown:function(){return }},mouseenter:{setup:function(){if(jQuery.browser.msie){return false}jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true},teardown:function(){if(jQuery.browser.msie){return false}jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true},handler:function(event){if(withinElement(event,this)){return true}arguments[0].type="mouseenter";return jQuery.event.handle.apply(this,arguments)}},mouseleave:{setup:function(){if(jQuery.browser.msie){return false}jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true},teardown:function(){if(jQuery.browser.msie){return false}jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true},handler:function(event){if(withinElement(event,this)){return true}arguments[0].type="mouseleave";return jQuery.event.handle.apply(this,arguments)}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data)})},one:function(type,data,fn){return this.each(function(){jQuery.event.add(this,type,function(event){jQuery(this).unbind(event);return(fn||data).apply(this,arguments)},fn&&data)})},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn)})},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn)})},triggerHandler:function(type,data,fn){if(this[0]){return jQuery.event.trigger(type,data,this[0],false,fn)}return undefined},toggle:function(){var args=arguments;return this.click(function(event){this.lastToggle=0==this.lastToggle?1:0;event.preventDefault();return args[this.lastToggle].apply(this,arguments)||false})},hover:function(fnOver,fnOut){return this.bind("mouseenter",fnOver).bind("mouseleave",fnOut)},ready:function(fn){bindReady();if(jQuery.isReady){fn.call(document,jQuery)}else{jQuery.readyList.push(function(){return fn.call(this,jQuery)})}return this}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.apply(document)});jQuery.readyList=null}jQuery(document).triggerHandler("ready")}}});var readyBound=false;function bindReady(){if(readyBound){return }readyBound=true;if(document.addEventListener&&!jQuery.browser.opera){document.addEventListener("DOMContentLoaded",jQuery.ready,false)}if(jQuery.browser.msie&&window==top){(function(){if(jQuery.isReady){return }try{document.documentElement.doScroll("left")}catch(error){setTimeout(arguments.callee,0);return }jQuery.ready()})()}if(jQuery.browser.opera){document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady){return }for(var i=0;i<document.styleSheets.length;i++){if(document.styleSheets[i].disabled){setTimeout(arguments.callee,0);return }}jQuery.ready()},false)}if(jQuery.browser.safari){var numStyles;(function(){if(jQuery.isReady){return }if(document.readyState!="loaded"&&document.readyState!="complete"){setTimeout(arguments.callee,0);return }if(numStyles===undefined){numStyles=jQuery("style, link[rel=stylesheet]").length}if(document.styleSheets.length!=numStyles){setTimeout(arguments.callee,0);return }jQuery.ready()})()}jQuery.event.add(window,"load",jQuery.ready)}jQuery.each(("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,change,select,submit,keydown,keypress,keyup,error").split(","),function(i,name){jQuery.fn[name]=function(fn){return fn?this.bind(name,fn):this.trigger(name)}});var withinElement=function(event,elem){var parent=event.relatedTarget;while(parent&&parent!=elem){try{parent=parent.parentNode}catch(error){parent=elem}}return parent==elem};jQuery(window).bind("unload",function(){jQuery("*").add(document).unbind()});jQuery.fn.extend({load:function(url,params,callback){if(jQuery.isFunction(url)){return this.bind("load",url)}var off=url.indexOf(" ");if(off>=0){var selector=url.slice(off,url.length);url=url.slice(0,off)}callback=callback||function(){};var type="GET";if(params){if(jQuery.isFunction(params)){callback=params;params=null}else{params=jQuery.param(params);type="POST"}}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified"){self.html(selector?jQuery("<div/>").append(res.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(selector):res.responseText)}self.each(callback,[res.responseText,status,res])}});return this},serialize:function(){return jQuery.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type))}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val}}):{name:elem.name,value:val}}).get()}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f)}});var jsc=(new Date).getTime();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type})},getScript:function(url,callback){return jQuery.get(url,null,callback,"script")},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json")},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={}}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type})},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings)},ajaxSettings:{global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){var jsonp,jsre=/=\?(&|$)/g,status,data;s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));if(s.data&&s.processData&&typeof s.data!="string"){s.data=jQuery.param(s.data)}if(s.dataType=="jsonp"){if(s.type.toLowerCase()=="get"){if(!s.url.match(jsre)){s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?"}}else{if(!s.data||!s.data.match(jsre)){s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?"}}s.dataType="json"}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data){s.data=(s.data+"").replace(jsre,"="+jsonp+"$1")}s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp]}catch(e){}if(head){head.removeChild(script)}}}if(s.dataType=="script"&&s.cache==null){s.cache=false}if(s.cache===false&&s.type.toLowerCase()=="get"){var ts=(new Date()).getTime();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"")}if(s.data&&s.type.toLowerCase()=="get"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null}if(s.global&&!jQuery.active++){jQuery.event.trigger("ajaxStart")}if((!s.url.indexOf("http")||!s.url.indexOf("//"))&&s.dataType=="script"&&s.type.toLowerCase()=="get"){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset){script.charset=s.scriptCharset}if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script)}}}head.appendChild(script);return undefined}var requestDone=false;var xml=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();xml.open(s.type,s.url,s.async,s.username,s.password);try{if(s.data){xml.setRequestHeader("Content-Type",s.contentType)}if(s.ifModified){xml.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}xml.setRequestHeader("X-Requested-With","XMLHttpRequest");xml.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default)}catch(e){}if(s.beforeSend){s.beforeSend(xml)}if(s.global){jQuery.event.trigger("ajaxSend",[xml,s])}var onreadystatechange=function(isTimeout){if(!requestDone&&xml&&(xml.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xml)&&"error"||s.ifModified&&jQuery.httpNotModified(xml,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xml,s.dataType)}catch(e){status="parsererror"}}if(status=="success"){var modRes;try{modRes=xml.getResponseHeader("Last-Modified")}catch(e){}if(s.ifModified&&modRes){jQuery.lastModified[s.url]=modRes}if(!jsonp){success()}}else{jQuery.handleError(s,xml,status)}complete();if(s.async){xml=null}}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0){setTimeout(function(){if(xml){xml.abort();if(!requestDone){onreadystatechange("timeout")}}},s.timeout)}}try{xml.send(s.data)}catch(e){jQuery.handleError(s,xml,null,e)}if(!s.async){onreadystatechange()}function success(){if(s.success){s.success(data,status)}if(s.global){jQuery.event.trigger("ajaxSuccess",[xml,s])}}function complete(){if(s.complete){s.complete(xml,status)}if(s.global){jQuery.event.trigger("ajaxComplete",[xml,s])}if(s.global&&!--jQuery.active){jQuery.event.trigger("ajaxStop")}}return xml},handleError:function(s,xml,status,e){if(s.error){s.error(xml,status,e)}if(s.global){jQuery.event.trigger("ajaxError",[xml,s,e])}},active:0,httpSuccess:function(r){try{return !r.status&&location.protocol=="file:"||(r.status>=200&&r.status<300)||r.status==304||r.status==1223||jQuery.browser.safari&&r.status==undefined}catch(e){}return false},httpNotModified:function(xml,url){try{var xmlRes=xml.getResponseHeader("Last-Modified");return xml.status==304||xmlRes==jQuery.lastModified[url]||jQuery.browser.safari&&xml.status==undefined}catch(e){}return false},httpData:function(r,type){var ct=r.getResponseHeader("content-type");var xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0;var data=xml?r.responseXML:r.responseText;if(xml&&data.documentElement.tagName=="parsererror"){throw"parsererror"}if(type=="script"){jQuery.globalEval(data)}if(type=="json"){data=eval("("+data+")")}return data},param:function(a){var s=[];if(a.constructor==Array||a.jquery){jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value))})}else{for(var j in a){if(a[j]&&a[j].constructor==Array){jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this))})}else{s.push(encodeURIComponent(j)+"="+encodeURIComponent(a[j]))}}}return s.join("&").replace(/%20/g,"+")}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none"){this.style.display="block"}elem.remove()}}).end()},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none"}).end()},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle(fn,fn2):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]()})},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback)},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback)},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback)},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback)},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback)},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback)},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1){return false}var opt=jQuery.extend({},optall);var hidden=jQuery(this).is(":hidden"),self=this;for(var p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden){return jQuery.isFunction(opt.complete)&&opt.complete.apply(this)}if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow}}if(opt.overflow!=null){this.style.overflow="hidden"}opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val)){e[val=="toggle"?hidden?"show":"hide":val](prop)}else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit}if(parts[1]){end=((parts[1]=="-="?-1:1)*end)+start}e.custom(start,end,unit)}else{e.custom(start,val,"")}}});return true})},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx"}if(!type||(typeof type=="string"&&!fn)){return queue(this[0],type)}return this.each(function(){if(fn.constructor==Array){queue(this,type,fn)}else{queue(this,type).push(fn);if(queue(this,type).length==1){fn.apply(this)}}})},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue){this.queue([])}this.each(function(){for(var i=timers.length-1;i>=0;i--){if(timers[i].elem==this){if(gotoEnd){timers[i](true)}timers.splice(i,1)}}});if(!gotoEnd){this.dequeue()}return this}});var queue=function(elem,type,array){if(!elem){return undefined}type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array){q=jQuery.data(elem,type+"queue",array?jQuery.makeArray(array):[])}return q};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length){q[0].apply(this)}})};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:{slow:600,fast:200}[opt.duration])||400;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false){jQuery(this).dequeue()}if(jQuery.isFunction(opt.old)){opt.old.apply(this)}};return opt},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig){options.orig={}}}});jQuery.fx.prototype={update:function(){if(this.options.step){this.options.step.apply(this.elem,[this.now,this])}(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width"){this.elem.style.display="block"}},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null){return this.elem[this.prop]}var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0},custom:function(from,to,unit){this.startTime=(new Date()).getTime();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd)}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;i<timers.length;i++){if(!timers[i]()){timers.splice(i--,1)}}if(!timers.length){clearInterval(jQuery.timerId);jQuery.timerId=null}},13)}},show:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.show=true;this.custom(0,this.cur());if(this.prop=="width"||this.prop=="height"){this.elem.style[this.prop]="1px"}jQuery(this.elem).show()},hide:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(gotoEnd){var t=(new Date()).getTime();if(gotoEnd||t>this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim){if(this.options.curAnim[i]!==true){done=false}}if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){this.elem.style.display="none"}if(this.options.hide||this.options.show){for(var p in this.options.curAnim){jQuery.attr(this.elem.style,p,this.options.orig[p])}}}if(done&&jQuery.isFunction(this.options.complete)){this.options.complete.apply(this.elem)}return false}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};jQuery.fx.step={scrollLeft:function(fx){fx.elem.scrollLeft=fx.now},scrollTop:function(fx){fx.elem.scrollTop=fx.now},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now)},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit}};jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem){with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),fixed=jQuery.css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop)}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2){border(offsetParent)}if(!fixed&&jQuery.css(offsetParent,"position")=="fixed"){fixed=true}offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(jQuery.css(parent,"display"))){add(-parent.scrollLeft,-parent.scrollTop)}if(mozilla&&jQuery.css(parent,"overflow")!="visible"){border(parent)}parent=parent.parentNode}if((safari2&&(fixed||jQuery.css(offsetChild,"position")=="absolute"))||(mozilla&&jQuery.css(offsetChild,"position")!="absolute")){add(-doc.body.offsetLeft,-doc.body.offsetTop)}if(fixed){add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop))}}results={top:top,left:left}}}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true))}function add(l,t){left+=parseInt(l)||0;top+=parseInt(t)||0}return results}})();
\ No newline at end of file
diff --git a/jscripts/jquery/jquery.dimensions.js b/jscripts/jquery/jquery.dimensions.js
new file mode 100644 (file)
index 0000000..b52ff25
--- /dev/null
@@ -0,0 +1 @@
+(function(B){B.dimensions={version:"@VERSION"};B.each(["Height","Width"],function(D,C){B.fn["inner"+C]=function(){if(!this[0]){return }var F=C=="Height"?"Top":"Left",E=C=="Height"?"Bottom":"Right";return this.css("display")!="none"?this[0]["client"+C]:A(this,C.toLowerCase())+A(this,"padding"+F)+A(this,"padding"+E)};B.fn["outer"+C]=function(F){if(!this[0]){return }var H=C=="Height"?"Top":"Left",E=C=="Height"?"Bottom":"Right";F=B.extend({margin:false},F||{});var G=this.css("display")!="none"?this[0]["offset"+C]:A(this,C.toLowerCase())+A(this,"border"+H+"Width")+A(this,"border"+E+"Width")+A(this,"padding"+H)+A(this,"padding"+E);return G+(F.margin?(A(this,"margin"+H)+A(this,"margin"+E)):0)}});B.each(["Left","Top"],function(D,C){B.fn["scroll"+C]=function(E){if(!this[0]){return }return E!=undefined?this.each(function(){this==window||this==document?window.scrollTo(C=="Left"?E:B(window)["scrollLeft"](),C=="Top"?E:B(window)["scrollTop"]()):this["scroll"+C]=E}):this[0]==window||this[0]==document?self[(C=="Left"?"pageXOffset":"pageYOffset")]||B.boxModel&&document.documentElement["scroll"+C]||document.body["scroll"+C]:this[0]["scroll"+C]}});B.fn.extend({position:function(){var H=0,G=0,F=this[0],I,C,E,D;if(F){E=this.offsetParent();I=this.offset();C=E.offset();I.top-=A(F,"marginTop");I.left-=A(F,"marginLeft");C.top+=A(E,"borderTopWidth");C.left+=A(E,"borderLeftWidth");D={top:I.top-C.top,left:I.left-C.left}}return D},offsetParent:function(){var C=this[0].offsetParent;while(C&&(!/^body|html$/i.test(C.tagName)&&B.css(C,"position")=="static")){C=C.offsetParent}return B(C)}});function A(C,D){return parseInt(B.curCSS(C.jquery?C[0]:C,D,true))||0}})(jQuery);
\ No newline at end of file
diff --git a/jscripts/jquery/jquery.keyboard-a11y.js b/jscripts/jquery/jquery.keyboard-a11y.js
new file mode 100644 (file)
index 0000000..c719d1b
--- /dev/null
@@ -0,0 +1 @@
+(function(J){J.a11y=J.a11y||{};J.a11y.keys={UP:38,DOWN:40,LEFT:37,RIGHT:39,SPACE:32,ENTER:13,TAB:9,CTRL:17,SHIFT:16,ALT:18};J.a11y.orientation={HORIZONTAL:0,VERTICAL:1,BOTH:2};var T="keyboard-a11y";var N="selectionContext";var P="userHandlers";var c="defaultActivate";var U={next:J.a11y.keys.DOWN,previous:J.a11y.keys.UP};var B={next:J.a11y.keys.RIGHT,previous:J.a11y.keys.LEFT};var Z=function(e){return(e.jquery)?e[0]:e};var O=function(f,e,g){if(f.willLeaveContainer){f.willLeaveContainer(e.activeItem)}else{if(f.willUnselect){f.willUnselect(e.activeItem)}}if(!g){e.activeItem=null}};var A=function(j,f){if(!j.modifier){return true}var g=j.modifier;var h=(g&&f.ctrlKey);var e=(g&&f.altKey);var i=(g&&f.shiftKey);return(h||e||i)};var F=function(e){return function(f){if(f.which===e.key&&e.activateHandler&&A(e,f)){e.activateHandler(f.target,f);f.preventDefault()}}};var M=function(e,f){if(f){f(e)}};var W=function(f,e){if(e){e(f)}};var E=function(g,e,f){W(g,f.willUnselect)};var X=function(e,f,g){if(f.activeItem){E(f.activeItem,f,g)}e=Z(e);if(f.selectables.index(e)===-1){return }f.activeItem=e;M(e,g.willSelect)};var d=function(e,f){return function(g){X(g.target,e,f);return g.stopPropagation()}};var G=function(e,f){return function(g){E(g.target,e,f);return g.stopPropagation()}};var a=function(f){var g=f.selectables;var i=f.activeItem;var h=(!i)?-1:g.index(i);var e=h+1;e=(e>=g.length)?e=0:e;g.eq(e).focus()};var L=function(e){var f=e.selectables;var i=e.activeItem;var h=(!i)?0:f.index(i);var g=h-1;g=(g<0)?f.length-1:g;f.eq(g).focus()};var I=function(e,g,f){return function(h){if(h.which===g.next){a(e);h.preventDefault()}else{if(h.which===g.previous){L(e);h.preventDefault()}}}};var S=function(e){var f;if(e===J.a11y.orientation.HORIZONTAL){f=B}else{f=U}return f};var Q=function(f,e,g){return function(h){var i=(g.constructor===Function)?g():g;if(f.focusIsLeavingContainer){i=false}if(i&&h.target===e.get(0)){if(!f.activeItem){a(f)}else{jQuery(f.activeItem).focus()}}return h.stopPropagation()}};var Y=function(e){return function(f){e.focusIsLeavingContainer=false;return f.stopPropagation()}};var V=function(e){e.each(function(f,g){g=J(g);if(!g.hasTabindex()||(g.tabindex()<0)){g.tabindex(0)}})};var b=function(h,l,e,f){var k=[];J(e).each(function(i,m){k.push({modifier:null,key:m,activateHandler:l})});if(f&&f.additionalBindings){k=k.concat(f.additionalBindings)}for(var g=0;g<k.length;g=g+1){var j=k[g];h.keydown(F(j))}};var C=function(f,e,g){return function(h){if(h.which!==J.a11y.keys.TAB){return }O(f,e,g);if(h.shiftKey){e.focusIsLeavingContainer=true}}};var D=function(g,e,h,j,i){h=h||{};var l=J.extend({},j,i);var k=S(l.direction);var f={activeItem:undefined,selectables:e,focusIsLeavingContainer:false};g.keydown(I(f,k,h));g.keydown(C(h,f,l.rememberSelectionState));g.focus(Q(f,g,l.shouldSelectOnFocus));g.blur(Y(f));e.tabindex(-1);e.focus(d(f,h));e.blur(G(f,h));return f};var K=function(f,e){return function(g){if(!e){return }g=Z(g);if(f.index(g)===-1){return }e(g)}};var R=function(f,e){var g=f.data(T);return g?g[e]:undefined};var H=function(f,e,h){var g=f.data(T)||{};g[e]=h;f.data(T,g)};J.fn.tabbable=function(){V(this);return this};J.fn.selectable=function(f,g,h){var e=D(J(f),this,g,this.selectable.defaults,h);H(this,N,e);H(this,P,g);return this};J.fn.activatable=function(f,e){b(this,f,this.activatable.defaults.keys,e);H(this,c,K(this,f));return this};J.fn.select=function(e){e.focus();return this};J.fn.selectNext=function(){a(R(this,N));return this};J.fn.selectPrevious=function(){L(R(this,N));return this};J.fn.currentSelection=function(){return J(R(this,N).activeItem)};J.fn.activate=function(f){var e=R(this,c);e(f);return this};J.fn.activatable.defaults={keys:[J.a11y.keys.ENTER,J.a11y.keys.SPACE]};J.fn.selectable.defaults={direction:this.VERTICAL,shouldSelectOnFocus:true,rememberSelectionState:true}})(jQuery);
\ No newline at end of file
diff --git a/jscripts/jquery/jquery.tabindex.js b/jscripts/jquery/jquery.tabindex.js
new file mode 100644 (file)
index 0000000..bda3e75
--- /dev/null
@@ -0,0 +1 @@
+(function(C){var E=function(){return C.browser.msie?"tabIndex":"tabindex"};var B=function(G){if(G.length<=0){return undefined}if(!G.hasTabindexAttr()){return A(G)?Number(0):undefined}var F=G[0].getAttribute(E());return Number(F)};var D=function(F,G){return F.each(function(H,I){C(I).attr(E(),G)})};var A=function(F){if(F.length<=0){return false}return jQuery(F[0]).is("a, input, button, select, area, textarea, object")};C.fn.tabindex=function(F){if(F!==null&&F!==undefined){return D(this,F)}else{return B(this)}};C.fn.removeTabindex=function(){return this.each(function(F,G){C(G).removeAttr(E())})};C.fn.hasTabindexAttr=function(){if(this.length<=0){return false}var F=this[0].getAttributeNode(E());return F?F.specified:false};C.fn.hasTabindex=function(){return this.hasTabindexAttr()||A(this)}})(jQuery);
\ No newline at end of file
diff --git a/jscripts/jquery/ui.base.js b/jscripts/jquery/ui.base.js
new file mode 100644 (file)
index 0000000..0f0af4e
--- /dev/null
@@ -0,0 +1 @@
+(function(C){C.ui=C.ui||{};C.extend(C.ui,{plugin:{add:function(E,F,H){var G=C.ui[E].prototype;for(var D in H){G.plugins[D]=G.plugins[D]||[];G.plugins[D].push([F,H[D]])}},call:function(D,E,G){var H=D.plugins[E];if(!H){return }for(var F=0;F<H.length;F++){if(D.options[H[F][0]]){H[F][1].apply(D.element,G)}}}},cssCache:{},css:function(D){if(C.ui.cssCache[D]){return C.ui.cssCache[D]}var E=C('<div class="ui-resizable-gen">').addClass(D).css({position:"absolute",top:"-5000px",left:"-5000px",display:"block"}).appendTo("body");C.ui.cssCache[D]=!!((!/auto|default/.test(E.css("cursor"))||(/^[1-9]/).test(E.css("height"))||(/^[1-9]/).test(E.css("width"))||!(/none/).test(E.css("backgroundImage"))||!(/transparent|rgba\(0, 0, 0, 0\)/).test(E.css("backgroundColor"))));try{C("body").get(0).removeChild(E.get(0))}catch(F){}return C.ui.cssCache[D]},disableSelection:function(D){D.unselectable="on";D.onselectstart=function(){return false};if(D.style){D.style.MozUserSelect="none"}},enableSelection:function(D){D.unselectable="off";D.onselectstart=function(){return true};if(D.style){D.style.MozUserSelect=""}},hasScroll:function(G,E){var D=/top/.test(E||"top")?"scrollTop":"scrollLeft",F=false;if(G[D]>0){return true}G[D]=1;F=G[D]>0?true:false;G[D]=0;return F}});C.each(["Left","Top"],function(E,D){if(!C.fn["scroll"+D]){C.fn["scroll"+D]=function(F){return F!=undefined?this.each(function(){this==window||this==document?window.scrollTo(D=="Left"?F:C(window)["scrollLeft"](),D=="Top"?F:C(window)["scrollTop"]()):this["scroll"+D]=F}):this[0]==window||this[0]==document?self[(D=="Left"?"pageXOffset":"pageYOffset")]||C.boxModel&&document.documentElement["scroll"+D]||document.body["scroll"+D]:this[0]["scroll"+D]}}});var B=C.fn.remove;C.fn.extend({position:function(){var F=this.offset();var E=this.offsetParent();var D=E.offset();return{top:F.top-A(this[0],"marginTop")-D.top-A(E,"borderTopWidth"),left:F.left-A(this[0],"marginLeft")-D.left-A(E,"borderLeftWidth")}},offsetParent:function(){var D=this[0].offsetParent;while(D&&(!/^body|html$/i.test(D.tagName)&&C.css(D,"position")=="static")){D=D.offsetParent}return C(D)},mouseInteraction:function(D){return this.each(function(){new C.ui.mouseInteraction(this,D)})},removeMouseInteraction:function(D){return this.each(function(){if(C.data(this,"ui-mouse")){C.data(this,"ui-mouse").destroy()}})},remove:function(){this.trigger("remove");return B.apply(this,arguments)}});function A(D,E){return parseInt(C.curCSS(D.jquery?D[0]:D,E,true))||0}C.ui.mouseInteraction=function(F,E){var D=this;this.element=F;C.data(this.element,"ui-mouse",this);this.options=C.extend({},E);C(F).bind("mousedown.draggable",function(){return D.click.apply(D,arguments)});if(C.browser.msie){C(F).attr("unselectable","on")}C(F).mouseup(function(){if(D.timer){clearInterval(D.timer)}})};C.extend(C.ui.mouseInteraction.prototype,{destroy:function(){C(this.element).unbind("mousedown.draggable")},trigger:function(){return this.click.apply(this,arguments)},click:function(F){if(F.which!=1||C.inArray(F.target.nodeName.toLowerCase(),this.options.dragPrevention||[])!=-1||(this.options.condition&&!this.options.condition.apply(this.options.executor||this,[F,this.element]))){return true}var E=this;var D=function(){E._MP={left:F.pageX,top:F.pageY};C(document).bind("mouseup.draggable",function(){return E.stop.apply(E,arguments)});C(document).bind("mousemove.draggable",function(){return E.drag.apply(E,arguments)});if(!E.initalized&&Math.abs(E._MP.left-F.pageX)>=E.options.distance||Math.abs(E._MP.top-F.pageY)>=E.options.distance){if(E.options.start){E.options.start.call(E.options.executor||E,F,E.element)}if(E.options.drag){E.options.drag.call(E.options.executor||E,F,this.element)}E.initialized=true}};if(this.options.delay){if(this.timer){clearInterval(this.timer)}this.timer=setTimeout(D,this.options.delay)}else{D()}return false},stop:function(D){var E=this.options;if(!this.initialized){return C(document).unbind("mouseup.draggable").unbind("mousemove.draggable")}if(this.options.stop){this.options.stop.call(this.options.executor||this,D,this.element)}C(document).unbind("mouseup.draggable").unbind("mousemove.draggable");this.initialized=false;return false},drag:function(D){var E=this.options;if(C.browser.msie&&!D.button){return this.stop.apply(this,[D])}if(!this.initialized&&(Math.abs(this._MP.left-D.pageX)>=E.distance||Math.abs(this._MP.top-D.pageY)>=E.distance)){if(this.options.start){this.options.start.call(this.options.executor||this,D,this.element)}this.initialized=true}else{if(!this.initialized){return false}}if(E.drag){E.drag.call(this.options.executor||this,D,this.element)}return false}})})(jQuery);
\ No newline at end of file
diff --git a/jscripts/jquery/ui.dialog.js b/jscripts/jquery/ui.dialog.js
new file mode 100644 (file)
index 0000000..89e55d0
--- /dev/null
@@ -0,0 +1 @@
+(function(B){B.ui=B.ui||{};B.fn.extend({dialog:function(D,E){var C=Array.prototype.slice.call(arguments,1);return this.each(function(){if(typeof D=="string"){var F=B.data(this,"ui-dialog")||B.data(B(this).parents(".ui-dialog:first").find(".ui-dialog-content")[0],"ui-dialog");F[D].apply(F,C)}else{if(!B(this).is(".ui-dialog-content")){new B.ui.dialog(this,D)}}})}});B.ui.dialog=function(E,M){this.options=M=B.extend({},B.ui.dialog.defaults,M&&M.modal?{resizable:false}:{},M);this.element=E;var L=this;B.data(this.element,"ui-dialog",this);B(E).bind("setData.dialog",function(O,N,P){M[N]=P}).bind("getData.dialog",function(O,N){return M[N]});var F=B(E).addClass("ui-dialog-content");if(!F.parent().length){F.appendTo("body")}F.wrap(document.createElement("div")).wrap(document.createElement("div"));var I=F.parent().addClass("ui-dialog-container").css({position:"relative"});var K=this.uiDialog=I.parent().hide().addClass("ui-dialog").css({position:"absolute",width:M.width,height:M.height,overflow:"hidden"});var C=F.attr("className").split(" ");B.each(C,function(N,O){if(O!="ui-dialog-content"){K.addClass(O)}});if(M.resizable&&B.fn.resizable){K.append('<div class="ui-resizable-n ui-resizable-handle"></div>').append('<div class="ui-resizable-s ui-resizable-handle"></div>').append('<div class="ui-resizable-e ui-resizable-handle"></div>').append('<div class="ui-resizable-w ui-resizable-handle"></div>').append('<div class="ui-resizable-ne ui-resizable-handle"></div>').append('<div class="ui-resizable-se ui-resizable-handle"></div>').append('<div class="ui-resizable-sw ui-resizable-handle"></div>').append('<div class="ui-resizable-nw ui-resizable-handle"></div>');K.resizable({maxWidth:M.maxWidth,maxHeight:M.maxHeight,minWidth:M.minWidth,minHeight:M.minHeight})}I.prepend('<div class="ui-dialog-titlebar"></div>');var D=B(".ui-dialog-titlebar",I);var J=(M.title)?M.title:(F.attr("title"))?F.attr("title"):"";D.append('<span class="ui-dialog-title">'+J+"</span>");D.append('<a href="#" class="ui-dialog-titlebar-close"><span>X</span></a>');this.uiDialogTitlebarClose=B(".ui-dialog-titlebar-close",D).hover(function(){B(this).addClass("ui-dialog-titlebar-close-hover")},function(){B(this).removeClass("ui-dialog-titlebar-close-hover")}).mousedown(function(N){N.stopPropagation()}).click(function(){L.close();return false}).keydown(function(N){var O=27;N.keyCode&&N.keyCode==O&&L.close()});var G=0;B.each(M.buttons,function(){G=1;return false});if(G==1){K.append('<div class="ui-dialog-buttonpane"></div>');var H=B(".ui-dialog-buttonpane",K);B.each(M.buttons,function(N,P){var O=B(document.createElement("button")).text(N).click(P);H.append(O)})}if(M.draggable&&B.fn.draggable){K.draggable({handle:".ui-dialog-titlebar",start:function(){L.activate()}})}K.mousedown(function(){L.activate()});D.click(function(){L.activate()});M.bgiframe&&B.fn.bgiframe&&K.bgiframe();this.open=function(){M.modal&&A.show(L,M.overlay);K.appendTo("body");var P=B(window),S=B(document),R=S.scrollTop(),Q=S.scrollLeft();if(M.position.constructor==Array){R+=M.position[1];Q+=M.position[0]}else{switch(M.position){case"center":R+=(P.height()/2)-(K.height()/2);Q+=(P.width()/2)-(K.width()/2);break;case"top":R+=0;Q+=(P.width()/2)-(K.width()/2);break;case"right":R+=(P.height()/2)-(K.height()/2);Q+=(P.width())-(K.width());break;case"bottom":R+=(P.height())-(K.height());Q+=(P.width()/2)-(K.width()/2);break;case"left":R+=(P.height()/2)-(K.height()/2);Q+=0;break;default:R+=(P.height()/2)-(K.height()/2);Q+=(P.width()/2)-(K.width()/2)}}R=R<S.scrollTop()?S.scrollTop():R;K.css({top:R,left:Q});K.show();L.activate();var N=null;var O={options:M};this.uiDialogTitlebarClose.focus();B(this.element).triggerHandler("dialogopen",[N,O],M.open)};this.activate=function(){var N=0;B(".ui-dialog:visible").each(function(){N=Math.max(N,parseInt(B(this).css("z-index"),10))});A.$el&&A.$el.css("z-index",++N);K.css("z-index",++N)};this.close=function(){M.modal&&A.hide();K.hide();var O=null;var N={options:M};B(this.element).triggerHandler("dialogclose",[O,N],M.close)};if(M.autoOpen){this.open()}};B.extend(B.ui.dialog,{defaults:{autoOpen:true,bgiframe:false,buttons:[],draggable:true,height:200,minHeight:100,minWidth:150,modal:false,overlay:{},position:"center",resizable:true,width:300}});var A={$el:null,events:B.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(C){return C+".ui-dialog-overlay"}).join(" "),show:function(F,E){if(this.$el){return }this.dialog=F;this.selects=this.ie6&&B("select:visible").css("visibility","hidden");var G=this.width();var C=this.height();this.$el=B("<div/>").appendTo(document.body).addClass("ui-dialog-overlay").css(B.extend({borderWidth:0,margin:0,padding:0,position:"absolute",top:0,left:0,width:G,height:C},E));B("a, :input").bind(this.events,function(){if(B(this).parents(".ui-dialog").length==0){F.uiDialogTitlebarClose.focus();return false}});B(document).bind("keydown.ui-dialog-overlay",function(H){var I=27;H.keyCode&&H.keyCode==I&&F.close()});$overlay=this.$el;function D(){$overlay.css({width:G,height:C}).css({width:A.width(),height:A.height()})}B(window).bind("resize.ui-dialog-overlay",D);F.uiDialog.is(".ui-draggable")&&F.uiDialog.data("stop.draggable",D);F.uiDialog.is(".ui-resizable")&&F.uiDialog.data("stop.resizable",D)},hide:function(){B("a, :input").add([document,window]).unbind(".ui-dialog-overlay");this.ie6&&this.selects.css("visibility","visible");this.$el=null;B(".ui-dialog-overlay").remove()},height:function(){var C;if(this.ie6&&(B(document.body).height()<B(window).height())&&!(document.documentElement.scrollTop||(this.dialog.uiDialog.offset().top+this.dialog.uiDialog.height())>B(window).height())){C=B(window).height()}else{C=B(document).height()}return C+"px"},width:function(){var C;if(this.ie6&&(B(document.body).width()<B(window).width())&&!(document.documentElement.scrollLeft||(this.dialog.uiDialog.offset().left+this.dialog.uiDialog.width())>B(window).width())){C=B(window).width()}else{C=B(document).width()}return C+"px"},ie6:B.browser.msie&&B.browser.version<7,selects:null}})(jQuery);
\ No newline at end of file
diff --git a/jscripts/jquery/ui.draggable.js b/jscripts/jquery/ui.draggable.js
new file mode 100644 (file)
index 0000000..60e8470
--- /dev/null
@@ -0,0 +1 @@
+(function(A){A.fn.extend({draggable:function(C){var B=Array.prototype.slice.call(arguments,1);return this.each(function(){if(typeof C=="string"){var D=A.data(this,"draggable");if(D){D[C].apply(D,B)}}else{if(!A.data(this,"draggable")){new A.ui.draggable(this,C)}}})}});A.ui.draggable=function(D,C){var B=this;this.element=A(D);A.data(D,"draggable",this);this.element.addClass("ui-draggable");this.options=A.extend({},C);var E=this.options;A.extend(E,{helper:E.ghosting==true?"clone":(E.helper||"original"),handle:E.handle?(A(E.handle,D)[0]?A(E.handle,D):this.element):this.element,appendTo:E.appendTo||"parent"});A(D).bind("setData.draggable",function(G,F,H){B.options[F]=H}).bind("getData.draggable",function(G,F){return B.options[F]});A(E.handle).mouseInteraction({executor:this,delay:E.delay,distance:E.distance||1,dragPrevention:E.cancel||E.cancel===""?E.cancel.toLowerCase().split(","):["input","textarea","button","select","option"],start:this.start,stop:this.stop,drag:this.drag,condition:function(F){return !(F.target.className.indexOf("ui-resizable-handle")!=-1||this.options.disabled)}});if(E.helper=="original"&&(this.element.css("position")=="static"||this.element.css("position")=="")){this.element.css("position","relative")}if(E.cursorAt&&E.cursorAt.constructor==Array){E.cursorAt={left:E.cursorAt[0],top:E.cursorAt[1]}}};A.extend(A.ui.draggable.prototype,{plugins:{},ui:function(B){return{helper:this.helper,position:this.position,absolutePosition:this.positionAbs,instance:this,options:this.options,element:this.element}},propagate:function(C,B){A.ui.plugin.call(this,C,[B,this.ui()]);return this.element.triggerHandler(C=="drag"?C:"drag"+C,[B,this.ui()],this.options[C])},destroy:function(){if(!A.data(this.element[0],"draggable")){return }this.options.handle.removeMouseInteraction();this.element.removeClass("ui-draggable ui-draggable-disabled").removeData("draggable").unbind(".draggable")},enable:function(){this.element.removeClass("ui-draggable-disabled");this.options.disabled=false},disable:function(){this.element.addClass("ui-draggable-disabled");this.options.disabled=true},setContrains:function(B,C,E,D){this.minLeft=B;this.maxLeft=C;this.minTop=E;this.maxTop=D;this.constrainsSet=true},checkConstrains:function(){if(!this.constrainsSet){return }if(this.position.left<this.minLeft){this.position.left=this.minLeft}if(this.position.left>this.maxLeft-this.helperProportions.width){this.position.left=this.maxLeft-this.helperProportions.width}if(this.position.top<this.minTop){this.position.top=this.minTop}if(this.position.top>this.maxTop-this.helperProportions.height){this.position.top=this.maxTop-this.helperProportions.height}},recallOffset:function(D){var C={left:this.elementOffset.left-this.offsetParentOffset.left,top:this.elementOffset.top-this.offsetParentOffset.top};var B=this.helper.css("position")=="relative";this.originalPosition={left:(B?parseInt(this.helper.css("left"),10)||0:C.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft)),top:(B?parseInt(this.helper.css("top"),10)||0:C.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop))};this.offset={left:this._pageX-this.originalPosition.left,top:this._pageY-this.originalPosition.top}},start:function(D){var E=this.options;if(A.ui.ddmanager){A.ui.ddmanager.current=this}this.helper=typeof E.helper=="function"?A(E.helper.apply(this.element[0],[D])):(E.helper=="clone"?this.element.clone().appendTo((E.appendTo=="parent"?this.element[0].parentNode:E.appendTo)):this.element);if(this.helper[0]!=this.element[0]){this.helper.css("position","absolute")}if(!this.helper.parents("body").length){this.helper.appendTo((E.appendTo=="parent"?this.element[0].parentNode:E.appendTo))}this.offsetParent=(function(F){while(F){if(F.style&&(/(absolute|relative|fixed)/).test(A.css(F,"position"))){return A(F)}F=F.parentNode?F.parentNode:null}return A("body")})(this.helper[0].parentNode);this.elementOffset=this.element.offset();this.offsetParentOffset=this.offsetParent.offset();var C={left:this.elementOffset.left-this.offsetParentOffset.left,top:this.elementOffset.top-this.offsetParentOffset.top};this._pageX=D.pageX;this._pageY=D.pageY;this.clickOffset={left:D.pageX-this.elementOffset.left,top:D.pageY-this.elementOffset.top};var B=this.helper.css("position")=="relative";this.originalPosition={left:(B?parseInt(this.helper.css("left"),10)||0:C.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft)),top:(B?parseInt(this.helper.css("top"),10)||0:C.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop))};if(this.element.css("position")=="fixed"){this.originalPosition.top-=this.offsetParent[0]==document.body?A(document).scrollTop():this.offsetParent[0].scrollTop;this.originalPosition.left-=this.offsetParent[0]==document.body?A(document).scrollLeft():this.offsetParent[0].scrollLeft}this.offset={left:D.pageX-this.originalPosition.left,top:D.pageY-this.originalPosition.top};if(this.element[0]!=this.helper[0]){this.offset.left+=parseInt(this.element.css("marginLeft"),10)||0;this.offset.top+=parseInt(this.element.css("marginTop"),10)||0}this.propagate("start",D);this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()};if(A.ui.ddmanager&&!E.dropBehaviour){A.ui.ddmanager.prepareOffsets(this,D)}if(E.cursorAt){if(E.cursorAt.top!=undefined||E.cursorAt.bottom!=undefined){this.offset.top-=this.clickOffset.top-(E.cursorAt.top!=undefined?E.cursorAt.top:(this.helperProportions.height-E.cursorAt.bottom));this.clickOffset.top=(E.cursorAt.top!=undefined?E.cursorAt.top:(this.helperProportions.height-E.cursorAt.bottom))}if(E.cursorAt.left!=undefined||E.cursorAt.right!=undefined){this.offset.left-=this.clickOffset.left-(E.cursorAt.left!=undefined?E.cursorAt.left:(this.helperProportions.width-E.cursorAt.right));this.clickOffset.left=(E.cursorAt.left!=undefined?E.cursorAt.left:(this.helperProportions.width-E.cursorAt.right))}}return false},clear:function(){if(A.ui.ddmanager){A.ui.ddmanager.current=null}this.helper=null},stop:function(B){if(A.ui.ddmanager&&!this.options.dropBehaviour){A.ui.ddmanager.drop(this,B)}this.propagate("stop",B);if(this.cancelHelperRemoval){return false}if(this.options.helper!="original"){this.helper.remove()}this.clear();return false},drag:function(B){this.position={top:B.pageY-this.offset.top,left:B.pageX-this.offset.left};this.positionAbs={left:B.pageX-this.clickOffset.left,top:B.pageY-this.clickOffset.top};this.checkConstrains();this.position=this.propagate("drag",B)||this.position;this.checkConstrains();A(this.helper).css({left:this.position.left+"px",top:this.position.top+"px"});if(A.ui.ddmanager){A.ui.ddmanager.drag(this,B)}return false}});A.ui.plugin.add("draggable","cursor",{start:function(D,C){var B=A("body");if(B.css("cursor")){C.options._cursor=B.css("cursor")}B.css("cursor",C.options.cursor)},stop:function(C,B){if(B.options._cursor){A("body").css("cursor",B.options._cursor)}}});A.ui.plugin.add("draggable","zIndex",{start:function(D,C){var B=A(C.helper);if(B.css("zIndex")){C.options._zIndex=B.css("zIndex")}B.css("zIndex",C.options.zIndex)},stop:function(C,B){if(B.options._zIndex){A(B.helper).css("zIndex",B.options._zIndex)}}});A.ui.plugin.add("draggable","opacity",{start:function(D,C){var B=A(C.helper);if(B.css("opacity")){C.options._opacity=B.css("opacity")}B.css("opacity",C.options.opacity)},stop:function(C,B){if(B.options._opacity){A(B.helper).css("opacity",B.options._opacity)}}});A.ui.plugin.add("draggable","revert",{stop:function(E,D){var B=D.instance,C=A(B.helper);B.cancelHelperRemoval=true;A(D.helper).animate({left:B.originalPosition.left,top:B.originalPosition.top},parseInt(D.options.revert,10)||500,function(){if(D.options.helper!="original"){C.remove()}if(!C){B.clear()}})}});A.ui.plugin.add("draggable","iframeFix",{start:function(D,C){var F=C.options;if(C.instance.slowMode){return }if(F.iframeFix.constructor==Array){for(var B=0;B<F.iframeFix.length;B++){var E=A(F.iframeFix[B]).offset({border:false});A('<div class="DragDropIframeFix"" style="background: #fff;"></div>').css("width",A(F.iframeFix[B])[0].offsetWidth+"px").css("height",A(F.iframeFix[B])[0].offsetHeight+"px").css("position","absolute").css("opacity","0.001").css("z-index","1000").css("top",E.top+"px").css("left",E.left+"px").appendTo("body")}}else{A("iframe").each(function(){var G=A(this).offset({border:false});A('<div class="DragDropIframeFix" style="background: #fff;"></div>').css("width",this.offsetWidth+"px").css("height",this.offsetHeight+"px").css("position","absolute").css("opacity","0.001").css("z-index","1000").css("top",G.top+"px").css("left",G.left+"px").appendTo("body")})}},stop:function(C,B){if(B.options.iframeFix){A("div.DragDropIframeFix").each(function(){this.parentNode.removeChild(this)})}}});A.ui.plugin.add("draggable","containment",{start:function(E,C){var G=C.options;var B=C.instance;if((G.containment.left!=undefined||G.containment.constructor==Array)&&!G._containment){return }if(!G._containment){G._containment=G.containment}if(G._containment=="parent"){G._containment=this[0].parentNode}if(G._containment=="document"){G.containment=[0,0,A(document).width(),(A(document).height()||document.body.parentNode.scrollHeight)]}else{var D=A(G._containment)[0];var F=A(G._containment).offset();G.containment=[F.left,F.top,F.left+(D.offsetWidth||D.scrollWidth),F.top+(D.offsetHeight||D.scrollHeight)]}var H=G.containment;C.instance.setContrains(H[0]-(B.offset.left-B.clickOffset.left),H[2]-(B.offset.left-B.clickOffset.left),H[1]-(B.offset.top-B.clickOffset.top),H[3]-(B.offset.top-B.clickOffset.top))}});A.ui.plugin.add("draggable","grid",{drag:function(E,D){var F=D.options;var C=D.instance.originalPosition.left+Math.round((E.pageX-D.instance._pageX)/F.grid[0])*F.grid[0];var B=D.instance.originalPosition.top+Math.round((E.pageY-D.instance._pageY)/F.grid[1])*F.grid[1];D.instance.position.left=C;D.instance.position.top=B}});A.ui.plugin.add("draggable","axis",{drag:function(C,B){var D=B.options;if(D.constraint){D.axis=D.constraint}switch(D.axis){case"x":B.instance.position.top=B.instance.originalPosition.top;break;case"y":B.instance.position.left=B.instance.originalPosition.left;break}}});A.ui.plugin.add("draggable","scroll",{start:function(C,B){var D=B.options;D.scrollSensitivity=D.scrollSensitivity||20;D.scrollSpeed=D.scrollSpeed||20;B.instance.overflowY=function(E){do{if(/auto|scroll/.test(E.css("overflow"))||(/auto|scroll/).test(E.css("overflow-y"))){return E}E=E.parent()}while(E[0].parentNode);return A(document)}(this);B.instance.overflowX=function(E){do{if(/auto|scroll/.test(E.css("overflow"))||(/auto|scroll/).test(E.css("overflow-x"))){return E}E=E.parent()}while(E[0].parentNode);return A(document)}(this)},drag:function(D,C){var E=C.options;var B=C.instance;if(B.overflowY[0]!=document&&B.overflowY[0].tagName!="HTML"){if(B.overflowY[0].offsetHeight-(C.position.top-B.overflowY[0].scrollTop+B.clickOffset.top)<E.scrollSensitivity){B.overflowY[0].scrollTop=B.overflowY[0].scrollTop+E.scrollSpeed}if((C.position.top-B.overflowY[0].scrollTop+B.clickOffset.top)<E.scrollSensitivity){B.overflowY[0].scrollTop=B.overflowY[0].scrollTop-E.scrollSpeed}}else{if(D.pageY-A(document).scrollTop()<E.scrollSensitivity){A(document).scrollTop(A(document).scrollTop()-E.scrollSpeed)}if(A(window).height()-(D.pageY-A(document).scrollTop())<E.scrollSensitivity){A(document).scrollTop(A(document).scrollTop()+E.scrollSpeed)}}if(B.overflowX[0]!=document&&B.overflowX[0].tagName!="HTML"){if(B.overflowX[0].offsetWidth-(C.position.left-B.overflowX[0].scrollLeft+B.clickOffset.left)<E.scrollSensitivity){B.overflowX[0].scrollLeft=B.overflowX[0].scrollLeft+E.scrollSpeed}if((C.position.top-B.overflowX[0].scrollLeft+B.clickOffset.left)<E.scrollSensitivity){B.overflowX[0].scrollLeft=B.overflowX[0].scrollLeft-E.scrollSpeed}}else{if(D.pageX-A(document).scrollLeft()<E.scrollSensitivity){A(document).scrollLeft(A(document).scrollLeft()-E.scrollSpeed)}if(A(window).width()-(D.pageX-A(document).scrollLeft())<E.scrollSensitivity){A(document).scrollLeft(A(document).scrollLeft()+E.scrollSpeed)}}C.instance.recallOffset(D)}});A.ui.plugin.add("draggable","snap",{start:function(C,B){B.instance.snapElements=[];A(B.options.snap===true?".ui-draggable":B.options.snap).each(function(){var E=A(this);var D=E.offset();if(this!=B.instance.element[0]){B.instance.snapElements.push({item:this,width:E.outerWidth(),height:E.outerHeight(),top:D.top,left:D.left})}})},drag:function(I,M){var K=M.options.snapTolerance||20;var D=M.absolutePosition.left,C=D+M.instance.helperProportions.width,O=M.absolutePosition.top,N=O+M.instance.helperProportions.height;for(var H=M.instance.snapElements.length-1;H>=0;H--){var E=M.instance.snapElements[H].left,B=E+M.instance.snapElements[H].width,Q=M.instance.snapElements[H].top,L=Q+M.instance.snapElements[H].height;if(!((E-K<D&&D<B+K&&Q-K<O&&O<L+K)||(E-K<D&&D<B+K&&Q-K<N&&N<L+K)||(E-K<C&&C<B+K&&Q-K<O&&O<L+K)||(E-K<C&&C<B+K&&Q-K<N&&N<L+K))){continue}if(M.options.snapMode!="inner"){var J=Math.abs(Q-N)<=20;var P=Math.abs(L-O)<=20;var G=Math.abs(E-C)<=20;var F=Math.abs(B-D)<=20;if(J){M.position.top=Q-M.instance.offset.top+M.instance.clickOffset.top-M.instance.helperProportions.height}if(P){M.position.top=L-M.instance.offset.top+M.instance.clickOffset.top}if(G){M.position.left=E-M.instance.offset.left+M.instance.clickOffset.left-M.instance.helperProportions.width}if(F){M.position.left=B-M.instance.offset.left+M.instance.clickOffset.left}}if(M.options.snapMode!="outer"){var J=Math.abs(Q-O)<=20;var P=Math.abs(L-N)<=20;var G=Math.abs(E-D)<=20;var F=Math.abs(B-C)<=20;if(J){M.position.top=Q-M.instance.offset.top+M.instance.clickOffset.top}if(P){M.position.top=L-M.instance.offset.top+M.instance.clickOffset.top-M.instance.helperProportions.height}if(G){M.position.left=E-M.instance.offset.left+M.instance.clickOffset.left}if(F){M.position.left=B-M.instance.offset.left+M.instance.clickOffset.left-M.instance.helperProportions.width}}}}})})(jQuery);
\ No newline at end of file
diff --git a/jscripts/jquery/ui.droppable.js b/jscripts/jquery/ui.droppable.js
new file mode 100644 (file)
index 0000000..ac60ad2
--- /dev/null
@@ -0,0 +1 @@
+(function(A){A.fn.extend({droppable:function(C){var B=Array.prototype.slice.call(arguments,1);return this.each(function(){if(typeof C=="string"){var D=A.data(this,"droppable");if(D){D[C].apply(D,B)}}else{if(!A.data(this,"droppable")){new A.ui.droppable(this,C)}}})}});A.ui.droppable=function(D,B){this.element=A(D);A.data(D,"droppable",this);this.element.addClass("ui-droppable");var E=this.options=B=A.extend({},A.ui.droppable.defaults,B);var C=E.accept;E=A.extend(E,{accept:E.accept&&E.accept.constructor==Function?E.accept:function(F){return A(F).is(C)}});A(D).bind("setData.droppable",function(G,F,H){E[F]=H}).bind("getData.droppable",function(G,F){return E[F]});this.proportions={width:this.element.outerWidth(),height:this.element.outerHeight()};A.ui.ddmanager.droppables.push({item:this,over:0,out:1})};A.extend(A.ui.droppable,{defaults:{disabled:false,tolerance:"intersect"}});A.extend(A.ui.droppable.prototype,{plugins:{},ui:function(B){return{instance:this,draggable:(B.currentItem||B.element),helper:B.helper,position:B.position,absolutePosition:B.positionAbs,options:this.options,element:this.element}},destroy:function(){var B=A.ui.ddmanager.droppables;for(var C=0;C<B.length;C++){if(B[C].item==this){B.splice(C,1)}}this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable")},enable:function(){this.element.removeClass("ui-droppable-disabled");this.options.disabled=false},disable:function(){this.element.addClass("ui-droppable-disabled");this.options.disabled=true},over:function(C){var B=A.ui.ddmanager.current;if(!B||(B.currentItem||B.element)[0]==this.element[0]){return }if(this.options.accept.call(this.element,(B.currentItem||B.element))){A.ui.plugin.call(this,"over",[C,this.ui(B)]);this.element.triggerHandler("dropover",[C,this.ui(B)],this.options.over)}},out:function(C){var B=A.ui.ddmanager.current;if(!B||(B.currentItem||B.element)[0]==this.element[0]){return }if(this.options.accept.call(this.element,(B.currentItem||B.element))){A.ui.plugin.call(this,"out",[C,this.ui(B)]);this.element.triggerHandler("dropout",[C,this.ui(B)],this.options.out)}},drop:function(D,C){var B=C||A.ui.ddmanager.current;if(!B||(B.currentItem||B.element)[0]==this.element[0]){return }var E=false;this.element.find(".ui-droppable").each(function(){var F=A.data(this,"droppable");if(F.options.greedy&&A.ui.intersect(B,{item:F,offset:F.element.offset()},F.options.tolerance)){E=true;return false}});if(E){return }if(this.options.accept.call(this.element,(B.currentItem||B.element))){A.ui.plugin.call(this,"drop",[D,this.ui(B)]);this.element.triggerHandler("drop",[D,this.ui(B)],this.options.drop)}},activate:function(C){var B=A.ui.ddmanager.current;A.ui.plugin.call(this,"activate",[C,this.ui(B)]);if(B){this.element.triggerHandler("dropactivate",[C,this.ui(B)],this.options.activate)}},deactivate:function(C){var B=A.ui.ddmanager.current;A.ui.plugin.call(this,"deactivate",[C,this.ui(B)]);if(B){this.element.triggerHandler("dropdeactivate",[C,this.ui(B)],this.options.deactivate)}}});A.ui.intersect=function(L,F,J){if(!F.offset){return false}var D=L.positionAbs.left,C=D+L.helperProportions.width,I=L.positionAbs.top,H=I+L.helperProportions.height;var E=F.offset.left,B=E+F.item.proportions.width,K=F.offset.top,G=K+F.item.proportions.height;switch(J){case"fit":if(!((H-(L.helperProportions.height/2)>K&&I<K)||(I<G&&H>G)||(C>E&&D<E)||(D<B&&C>B))){return false}if(H-(L.helperProportions.height/2)>K&&I<K){return 1}if(I<G&&H>G){return 2}if(C>E&&D<E){return 1}if(D<B&&C>B){return 2}break;case"intersect":return(E<D+(L.helperProportions.width/2)&&C-(L.helperProportions.width/2)<B&&K<I+(L.helperProportions.height/2)&&H-(L.helperProportions.height/2)<G);break;case"pointer":return(E<(L.positionAbs.left+L.clickOffset.left)&&(L.positionAbs.left+L.clickOffset.left)<B&&K<(L.positionAbs.top+L.clickOffset.top)&&(L.positionAbs.top+L.clickOffset.top)<G);break;case"touch":return((I>=K&&I<=G)||(H>=K&&H<=G)||(I<K&&H>G))&&((D>=E&&D<=B)||(C>=E&&C<=B)||(D<E&&C>B));break;default:return false;break}};A.ui.ddmanager={current:null,droppables:[],prepareOffsets:function(D,F){var B=A.ui.ddmanager.droppables;var E=F?F.type:null;for(var C=0;C<B.length;C++){if(B[C].item.options.disabled||(D&&!B[C].item.options.accept.call(B[C].item.element,(D.currentItem||D.element)))){continue}B[C].offset=A(B[C].item.element).offset();B[C].item.proportions={width:B[C].item.element.outerWidth(),height:B[C].item.element.outerHeight()};if(E=="dragstart"){B[C].item.activate.call(B[C].item,F)}}},drop:function(B,C){A.each(A.ui.ddmanager.droppables,function(){if(!this.item.options.disabled&&A.ui.intersect(B,this,this.item.options.tolerance)){this.item.drop.call(this.item,C)}if(!this.item.options.disabled&&this.item.options.accept.call(this.item.element,(B.currentItem||B.element))){this.out=1;this.over=0;this.item.deactivate.call(this.item,C)}})},drag:function(B,C){if(B.options.refreshPositions){A.ui.ddmanager.prepareOffsets(B,C)}A.each(A.ui.ddmanager.droppables,function(){if(this.item.disabled||this.greedyChild){return }var E=A.ui.intersect(B,this,this.item.options.tolerance);var F=!E&&this.over==1?"out":(E&&this.over==0?"over":null);if(!F){return }var D=A.data(this.item.element[0],"droppable");if(D.options.greedy){this.item.element.parents(".ui-droppable").each(function(){var G=this;A.each(A.ui.ddmanager.droppables,function(){if(this.item.element[0]!=G){return }this[F]=0;this[F=="out"?"over":"out"]=1;this.greedyChild=(F=="over"?1:0);this.item[F=="out"?"over":"out"].call(this.item,C);return false})})}this[F]=1;this[F=="out"?"over":"out"]=0;this.item[F].call(this.item,C)})}};A.ui.plugin.add("droppable","activeClass",{activate:function(C,B){A(this).addClass(B.options.activeClass)},deactivate:function(C,B){A(this).removeClass(B.options.activeClass)},drop:function(C,B){A(this).removeClass(B.options.activeClass)}});A.ui.plugin.add("droppable","hoverClass",{over:function(C,B){A(this).addClass(B.options.hoverClass)},out:function(C,B){A(this).removeClass(B.options.hoverClass)},drop:function(C,B){A(this).removeClass(B.options.hoverClass)}})})(jQuery);
\ No newline at end of file
diff --git a/jscripts/json/json2.js b/jscripts/json/json2.js
new file mode 100644 (file)
index 0000000..4e7f7bd
--- /dev/null
@@ -0,0 +1 @@
+if(!this.JSON){JSON=function(){function f(n){return n<10?"0"+n:n}Date.prototype.toJSON=function(){return this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z"};var m={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};function stringify(value,whitelist){var a,i,k,l,r=/["\\\x00-\x1f\x7f-\x9f]/g,v;switch(typeof value){case"string":return r.test(value)?'"'+value.replace(r,function(a){var c=m[a];if(c){return c}c=a.charCodeAt();return"\\u00"+Math.floor(c/16).toString(16)+(c%16).toString(16)})+'"':'"'+value+'"';case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}if(typeof value.toJSON==="function"){return stringify(value.toJSON())}a=[];if(typeof value.length==="number"&&!(value.propertyIsEnumerable("length"))){l=value.length;for(i=0;i<l;i+=1){a.push(stringify(value[i],whitelist)||"null")}return"["+a.join(",")+"]"}if(whitelist){l=whitelist.length;for(i=0;i<l;i+=1){k=whitelist[i];if(typeof k==="string"){v=stringify(value[k],whitelist);if(v){a.push(stringify(k)+":"+v)}}}}else{for(k in value){if(typeof k==="string"){v=stringify(value[k],whitelist);if(v){a.push(stringify(k)+":"+v)}}}}return"{"+a.join(",")+"}"}}return{stringify:stringify,parse:function(text,filter){var j;function walk(k,v){var i,n;if(v&&typeof v==="object"){for(i in v){if(Object.prototype.hasOwnProperty.apply(v,[i])){n=walk(i,v[i]);if(n!==undefined){v[i]=n}}}}return filter(k,v)}if(/^[\],:{}\s]*$/.test(text.replace(/\\./g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof filter==="function"?walk("",j):j}throw new SyntaxError("parseJSON")}}}()};
\ No newline at end of file
diff --git a/jscripts/tiny_mce/langs/en.js b/jscripts/tiny_mce/langs/en.js
new file mode 100644 (file)
index 0000000..246e141
--- /dev/null
@@ -0,0 +1,157 @@
+tinyMCE.addI18n({en:{\r
+common:{\r
+edit_confirm:"Do you want to use the WYSIWYG mode for this textarea?",\r
+apply:"Apply",\r
+insert:"Insert",\r
+update:"Update",\r
+cancel:"Cancel",\r
+close:"Close",\r
+browse:"Browse",\r
+class_name:"Class",\r
+not_set:"-- Not set --",\r
+clipboard_msg:"Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?",\r
+clipboard_no_support:"Currently not supported by your browser, use keyboard shortcuts instead.",\r
+popup_blocked:"Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.",\r
+invalid_data:"Error: Invalid values entered, these are marked in red.",\r
+more_colors:"More colors"\r
+},\r
+contextmenu:{\r
+align:"Alignment",\r
+left:"Left",\r
+center:"Center",\r
+right:"Right",\r
+full:"Full"\r
+},\r
+insertdatetime:{\r
+date_fmt:"%Y-%m-%d",\r
+time_fmt:"%H:%M:%S",\r
+insertdate_desc:"Insert date",\r
+inserttime_desc:"Insert time",\r
+months_long:"January,February,March,April,May,June,July,August,September,October,November,December",\r
+months_short:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",\r
+day_long:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday",\r
+day_short:"Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun"\r
+},\r
+print:{\r
+print_desc:"Print"\r
+},\r
+preview:{\r
+preview_desc:"Preview"\r
+},\r
+directionality:{\r
+ltr_desc:"Direction left to right",\r
+rtl_desc:"Direction right to left"\r
+},\r
+layer:{\r
+insertlayer_desc:"Insert new layer",\r
+forward_desc:"Move forward",\r
+backward_desc:"Move backward",\r
+absolute_desc:"Toggle absolute positioning",\r
+content:"New layer..."\r
+},\r
+save:{\r
+save_desc:"Save",\r
+cancel_desc:"Cancel all changes"\r
+},\r
+nonbreaking:{\r
+nonbreaking_desc:"Insert non-breaking space character"\r
+},\r
+iespell:{\r
+iespell_desc:"Run spell checking",\r
+download:"ieSpell not detected. Do you want to install it now?"\r
+},\r
+advhr:{\r
+advhr_desc:"Horizontale rule"\r
+},\r
+acheck:{\r
+acheck_desc:"Check Accessibility"\r
+},\r
+emotions:{\r
+emotions_desc:"Emotions"\r
+},\r
+searchreplace:{\r
+search_desc:"Find",\r
+replace_desc:"Find/Replace"\r
+},\r
+advimage:{\r
+image_desc:"Insert/edit image"\r
+},\r
+advlink:{\r
+link_desc:"Insert/edit link"\r
+},\r
+xhtmlxtras:{\r
+cite_desc:"Citation",\r
+abbr_desc:"Abbreviation",\r
+acronym_desc:"Acronym",\r
+del_desc:"Deletion",\r
+ins_desc:"Insertion",\r
+attribs_desc:"Insert/Edit Attributes"\r
+},\r
+style:{\r
+desc:"Edit CSS Style"\r
+},\r
+paste:{\r
+paste_text_desc:"Paste as Plain Text",\r
+paste_word_desc:"Paste from Word",\r
+selectall_desc:"Select All"\r
+},\r
+paste_dlg:{\r
+text_title:"Use CTRL+V on your keyboard to paste the text into the window.",\r
+text_linebreaks:"Keep linebreaks",\r
+word_title:"Use CTRL+V on your keyboard to paste the text into the window."\r
+},\r
+table:{\r
+desc:"Inserts a new table",\r
+row_before_desc:"Insert row before",\r
+row_after_desc:"Insert row after",\r
+delete_row_desc:"Delete row",\r
+col_before_desc:"Insert column before",\r
+col_after_desc:"Insert column after",\r
+delete_col_desc:"Remove column",\r
+split_cells_desc:"Split merged table cells",\r
+merge_cells_desc:"Merge table cells",\r
+row_desc:"Table row properties",\r
+cell_desc:"Table cell properties",\r
+props_desc:"Table properties",\r
+paste_row_before_desc:"Paste table row before",\r
+paste_row_after_desc:"Paste table row after",\r
+cut_row_desc:"Cut table row",\r
+copy_row_desc:"Copy table row",\r
+del:"Delete table",\r
+row:"Row",\r
+col:"Column",\r
+cell:"Cell"\r
+},\r
+autosave:{\r
+unload_msg:"The changes you made will be lost if you navigate away from this page."\r
+},\r
+fullscreen:{\r
+desc:"Toggle fullscreen mode"\r
+},\r
+media:{\r
+desc:"Insert / edit embedded media",\r
+edit:"Edit embedded media"\r
+},\r
+fullpage:{\r
+desc:"Document properties"\r
+},\r
+template:{\r
+desc:"Insert predefined template content"\r
+},\r
+visualchars:{\r
+desc:"Visual control characters on/off."\r
+},\r
+spellchecker:{\r
+desc:"Toggle spellchecker",\r
+menu:"Spellchecker settings",\r
+ignore_word:"Ignore word",\r
+ignore_words:"Ignore all",\r
+langs:"Languages",\r
+wait:"Please wait...",\r
+sug:"Suggestions",\r
+no_sug:"No suggestions",\r
+no_mpell:"No misspellings found."\r
+},\r
+pagebreak:{\r
+desc:"Insert page break."\r
+}}});
\ No newline at end of file
diff --git a/jscripts/tiny_mce/license.txt b/jscripts/tiny_mce/license.txt
new file mode 100644 (file)
index 0000000..60d6d4c
--- /dev/null
@@ -0,0 +1,504 @@
+                 GNU LESSER GENERAL PUBLIC LICENSE\r
+                      Version 2.1, February 1999\r
+\r
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.\r
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
+ Everyone is permitted to copy and distribute verbatim copies\r
+ of this license document, but changing it is not allowed.\r
+\r
+[This is the first released version of the Lesser GPL.  It also counts\r
+ as the successor of the GNU Library Public License, version 2, hence\r
+ the version number 2.1.]\r
+\r
+                           Preamble\r
+\r
+  The licenses for most software are designed to take away your\r
+freedom to share and change it.  By contrast, the GNU General Public\r
+Licenses are intended to guarantee your freedom to share and change\r
+free software--to make sure the software is free for all its users.\r
+\r
+  This license, the Lesser General Public License, applies to some\r
+specially designated software packages--typically libraries--of the\r
+Free Software Foundation and other authors who decide to use it.  You\r
+can use it too, but we suggest you first think carefully about whether\r
+this license or the ordinary General Public License is the better\r
+strategy to use in any particular case, based on the explanations below.\r
+\r
+  When we speak of free software, we are referring to freedom of use,\r
+not price.  Our General Public Licenses are designed to make sure that\r
+you have the freedom to distribute copies of free software (and charge\r
+for this service if you wish); that you receive source code or can get\r
+it if you want it; that you can change the software and use pieces of\r
+it in new free programs; and that you are informed that you can do\r
+these things.\r
+\r
+  To protect your rights, we need to make restrictions that forbid\r
+distributors to deny you these rights or to ask you to surrender these\r
+rights.  These restrictions translate to certain responsibilities for\r
+you if you distribute copies of the library or if you modify it.\r
+\r
+  For example, if you distribute copies of the library, whether gratis\r
+or for a fee, you must give the recipients all the rights that we gave\r
+you.  You must make sure that they, too, receive or can get the source\r
+code.  If you link other code with the library, you must provide\r
+complete object files to the recipients, so that they can relink them\r
+with the library after making changes to the library and recompiling\r
+it.  And you must show them these terms so they know their rights.\r
+\r
+  We protect your rights with a two-step method: (1) we copyright the\r
+library, and (2) we offer you this license, which gives you legal\r
+permission to copy, distribute and/or modify the library.\r
+\r
+  To protect each distributor, we want to make it very clear that\r
+there is no warranty for the free library.  Also, if the library is\r
+modified by someone else and passed on, the recipients should know\r
+that what they have is not the original version, so that the original\r
+author's reputation will not be affected by problems that might be\r
+introduced by others.\r
+\r
+  Finally, software patents pose a constant threat to the existence of\r
+any free program.  We wish to make sure that a company cannot\r
+effectively restrict the users of a free program by obtaining a\r
+restrictive license from a patent holder.  Therefore, we insist that\r
+any patent license obtained for a version of the library must be\r
+consistent with the full freedom of use specified in this license.\r
+\r
+  Most GNU software, including some libraries, is covered by the\r
+ordinary GNU General Public License.  This license, the GNU Lesser\r
+General Public License, applies to certain designated libraries, and\r
+is quite different from the ordinary General Public License.  We use\r
+this license for certain libraries in order to permit linking those\r
+libraries into non-free programs.\r
+\r
+  When a program is linked with a library, whether statically or using\r
+a shared library, the combination of the two is legally speaking a\r
+combined work, a derivative of the original library.  The ordinary\r
+General Public License therefore permits such linking only if the\r
+entire combination fits its criteria of freedom.  The Lesser General\r
+Public License permits more lax criteria for linking other code with\r
+the library.\r
+\r
+  We call this license the "Lesser" General Public License because it\r
+does Less to protect the user's freedom than the ordinary General\r
+Public License.  It also provides other free software developers Less\r
+of an advantage over competing non-free programs.  These disadvantages\r
+are the reason we use the ordinary General Public License for many\r
+libraries.  However, the Lesser license provides advantages in certain\r
+special circumstances.\r
+\r
+  For example, on rare occasions, there may be a special need to\r
+encourage the widest possible use of a certain library, so that it becomes\r
+a de-facto standard.  To achieve this, non-free programs must be\r
+allowed to use the library.  A more frequent case is that a free\r
+library does the same job as widely used non-free libraries.  In this\r
+case, there is little to gain by limiting the free library to free\r
+software only, so we use the Lesser General Public License.\r
+\r
+  In other cases, permission to use a particular library in non-free\r
+programs enables a greater number of people to use a large body of\r
+free software.  For example, permission to use the GNU C Library in\r
+non-free programs enables many more people to use the whole GNU\r
+operating system, as well as its variant, the GNU/Linux operating\r
+system.\r
+\r
+  Although the Lesser General Public License is Less protective of the\r
+users' freedom, it does ensure that the user of a program that is\r
+linked with the Library has the freedom and the wherewithal to run\r
+that program using a modified version of the Library.\r
+\r
+  The precise terms and conditions for copying, distribution and\r
+modification follow.  Pay close attention to the difference between a\r
+"work based on the library" and a "work that uses the library".  The\r
+former contains code derived from the library, whereas the latter must\r
+be combined with the library in order to run.\r
+\r
+                 GNU LESSER GENERAL PUBLIC LICENSE\r
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\r
+\r
+  0. This License Agreement applies to any software library or other\r
+program which contains a notice placed by the copyright holder or\r
+other authorized party saying it may be distributed under the terms of\r
+this Lesser General Public License (also called "this License").\r
+Each licensee is addressed as "you".\r
+\r
+  A "library" means a collection of software functions and/or data\r
+prepared so as to be conveniently linked with application programs\r
+(which use some of those functions and data) to form executables.\r
+\r
+  The "Library", below, refers to any such software library or work\r
+which has been distributed under these terms.  A "work based on the\r
+Library" means either the Library or any derivative work under\r
+copyright law: that is to say, a work containing the Library or a\r
+portion of it, either verbatim or with modifications and/or translated\r
+straightforwardly into another language.  (Hereinafter, translation is\r
+included without limitation in the term "modification".)\r
+\r
+  "Source code" for a work means the preferred form of the work for\r
+making modifications to it.  For a library, complete source code means\r
+all the source code for all modules it contains, plus any associated\r
+interface definition files, plus the scripts used to control compilation\r
+and installation of the library.\r
+\r
+  Activities other than copying, distribution and modification are not\r
+covered by this License; they are outside its scope.  The act of\r
+running a program using the Library is not restricted, and output from\r
+such a program is covered only if its contents constitute a work based\r
+on the Library (independent of the use of the Library in a tool for\r
+writing it).  Whether that is true depends on what the Library does\r
+and what the program that uses the Library does.\r
+  \r
+  1. You may copy and distribute verbatim copies of the Library's\r
+complete source code as you receive it, in any medium, provided that\r
+you conspicuously and appropriately publish on each copy an\r
+appropriate copyright notice and disclaimer of warranty; keep intact\r
+all the notices that refer to this License and to the absence of any\r
+warranty; and distribute a copy of this License along with the\r
+Library.\r
+\r
+  You may charge a fee for the physical act of transferring a copy,\r
+and you may at your option offer warranty protection in exchange for a\r
+fee.\r
+\r
+  2. You may modify your copy or copies of the Library or any portion\r
+of it, thus forming a work based on the Library, and copy and\r
+distribute such modifications or work under the terms of Section 1\r
+above, provided that you also meet all of these conditions:\r
+\r
+    a) The modified work must itself be a software library.\r
+\r
+    b) You must cause the files modified to carry prominent notices\r
+    stating that you changed the files and the date of any change.\r
+\r
+    c) You must cause the whole of the work to be licensed at no\r
+    charge to all third parties under the terms of this License.\r
+\r
+    d) If a facility in the modified Library refers to a function or a\r
+    table of data to be supplied by an application program that uses\r
+    the facility, other than as an argument passed when the facility\r
+    is invoked, then you must make a good faith effort to ensure that,\r
+    in the event an application does not supply such function or\r
+    table, the facility still operates, and performs whatever part of\r
+    its purpose remains meaningful.\r
+\r
+    (For example, a function in a library to compute square roots has\r
+    a purpose that is entirely well-defined independent of the\r
+    application.  Therefore, Subsection 2d requires that any\r
+    application-supplied function or table used by this function must\r
+    be optional: if the application does not supply it, the square\r
+    root function must still compute square roots.)\r
+\r
+These requirements apply to the modified work as a whole.  If\r
+identifiable sections of that work are not derived from the Library,\r
+and can be reasonably considered independent and separate works in\r
+themselves, then this License, and its terms, do not apply to those\r
+sections when you distribute them as separate works.  But when you\r
+distribute the same sections as part of a whole which is a work based\r
+on the Library, the distribution of the whole must be on the terms of\r
+this License, whose permissions for other licensees extend to the\r
+entire whole, and thus to each and every part regardless of who wrote\r
+it.\r
+\r
+Thus, it is not the intent of this section to claim rights or contest\r
+your rights to work written entirely by you; rather, the intent is to\r
+exercise the right to control the distribution of derivative or\r
+collective works based on the Library.\r
+\r
+In addition, mere aggregation of another work not based on the Library\r
+with the Library (or with a work based on the Library) on a volume of\r
+a storage or distribution medium does not bring the other work under\r
+the scope of this License.\r
+\r
+  3. You may opt to apply the terms of the ordinary GNU General Public\r
+License instead of this License to a given copy of the Library.  To do\r
+this, you must alter all the notices that refer to this License, so\r
+that they refer to the ordinary GNU General Public License, version 2,\r
+instead of to this License.  (If a newer version than version 2 of the\r
+ordinary GNU General Public License has appeared, then you can specify\r
+that version instead if you wish.)  Do not make any other change in\r
+these notices.\r
+\r
+  Once this change is made in a given copy, it is irreversible for\r
+that copy, so the ordinary GNU General Public License applies to all\r
+subsequent copies and derivative works made from that copy.\r
+\r
+  This option is useful when you wish to copy part of the code of\r
+the Library into a program that is not a library.\r
+\r
+  4. You may copy and distribute the Library (or a portion or\r
+derivative of it, under Section 2) in object code or executable form\r
+under the terms of Sections 1 and 2 above provided that you accompany\r
+it with the complete corresponding machine-readable source code, which\r
+must be distributed under the terms of Sections 1 and 2 above on a\r
+medium customarily used for software interchange.\r
+\r
+  If distribution of object code is made by offering access to copy\r
+from a designated place, then offering equivalent access to copy the\r
+source code from the same place satisfies the requirement to\r
+distribute the source code, even though third parties are not\r
+compelled to copy the source along with the object code.\r
+\r
+  5. A program that contains no derivative of any portion of the\r
+Library, but is designed to work with the Library by being compiled or\r
+linked with it, is called a "work that uses the Library".  Such a\r
+work, in isolation, is not a derivative work of the Library, and\r
+therefore falls outside the scope of this License.\r
+\r
+  However, linking a "work that uses the Library" with the Library\r
+creates an executable that is a derivative of the Library (because it\r
+contains portions of the Library), rather than a "work that uses the\r
+library".  The executable is therefore covered by this License.\r
+Section 6 states terms for distribution of such executables.\r
+\r
+  When a "work that uses the Library" uses material from a header file\r
+that is part of the Library, the object code for the work may be a\r
+derivative work of the Library even though the source code is not.\r
+Whether this is true is especially significant if the work can be\r
+linked without the Library, or if the work is itself a library.  The\r
+threshold for this to be true is not precisely defined by law.\r
+\r
+  If such an object file uses only numerical parameters, data\r
+structure layouts and accessors, and small macros and small inline\r
+functions (ten lines or less in length), then the use of the object\r
+file is unrestricted, regardless of whether it is legally a derivative\r
+work.  (Executables containing this object code plus portions of the\r
+Library will still fall under Section 6.)\r
+\r
+  Otherwise, if the work is a derivative of the Library, you may\r
+distribute the object code for the work under the terms of Section 6.\r
+Any executables containing that work also fall under Section 6,\r
+whether or not they are linked directly with the Library itself.\r
+\r
+  6. As an exception to the Sections above, you may also combine or\r
+link a "work that uses the Library" with the Library to produce a\r
+work containing portions of the Library, and distribute that work\r
+under terms of your choice, provided that the terms permit\r
+modification of the work for the customer's own use and reverse\r
+engineering for debugging such modifications.\r
+\r
+  You must give prominent notice with each copy of the work that the\r
+Library is used in it and that the Library and its use are covered by\r
+this License.  You must supply a copy of this License.  If the work\r
+during execution displays copyright notices, you must include the\r
+copyright notice for the Library among them, as well as a reference\r
+directing the user to the copy of this License.  Also, you must do one\r
+of these things:\r
+\r
+    a) Accompany the work with the complete corresponding\r
+    machine-readable source code for the Library including whatever\r
+    changes were used in the work (which must be distributed under\r
+    Sections 1 and 2 above); and, if the work is an executable linked\r
+    with the Library, with the complete machine-readable "work that\r
+    uses the Library", as object code and/or source code, so that the\r
+    user can modify the Library and then relink to produce a modified\r
+    executable containing the modified Library.  (It is understood\r
+    that the user who changes the contents of definitions files in the\r
+    Library will not necessarily be able to recompile the application\r
+    to use the modified definitions.)\r
+\r
+    b) Use a suitable shared library mechanism for linking with the\r
+    Library.  A suitable mechanism is one that (1) uses at run time a\r
+    copy of the library already present on the user's computer system,\r
+    rather than copying library functions into the executable, and (2)\r
+    will operate properly with a modified version of the library, if\r
+    the user installs one, as long as the modified version is\r
+    interface-compatible with the version that the work was made with.\r
+\r
+    c) Accompany the work with a written offer, valid for at\r
+    least three years, to give the same user the materials\r
+    specified in Subsection 6a, above, for a charge no more\r
+    than the cost of performing this distribution.\r
+\r
+    d) If distribution of the work is made by offering access to copy\r
+    from a designated place, offer equivalent access to copy the above\r
+    specified materials from the same place.\r
+\r
+    e) Verify that the user has already received a copy of these\r
+    materials or that you have already sent this user a copy.\r
+\r
+  For an executable, the required form of the "work that uses the\r
+Library" must include any data and utility programs needed for\r
+reproducing the executable from it.  However, as a special exception,\r
+the materials to be distributed need not include anything that is\r
+normally distributed (in either source or binary form) with the major\r
+components (compiler, kernel, and so on) of the operating system on\r
+which the executable runs, unless that component itself accompanies\r
+the executable.\r
+\r
+  It may happen that this requirement contradicts the license\r
+restrictions of other proprietary libraries that do not normally\r
+accompany the operating system.  Such a contradiction means you cannot\r
+use both them and the Library together in an executable that you\r
+distribute.\r
+\r
+  7. You may place library facilities that are a work based on the\r
+Library side-by-side in a single library together with other library\r
+facilities not covered by this License, and distribute such a combined\r
+library, provided that the separate distribution of the work based on\r
+the Library and of the other library facilities is otherwise\r
+permitted, and provided that you do these two things:\r
+\r
+    a) Accompany the combined library with a copy of the same work\r
+    based on the Library, uncombined with any other library\r
+    facilities.  This must be distributed under the terms of the\r
+    Sections above.\r
+\r
+    b) Give prominent notice with the combined library of the fact\r
+    that part of it is a work based on the Library, and explaining\r
+    where to find the accompanying uncombined form of the same work.\r
+\r
+  8. You may not copy, modify, sublicense, link with, or distribute\r
+the Library except as expressly provided under this License.  Any\r
+attempt otherwise to copy, modify, sublicense, link with, or\r
+distribute the Library is void, and will automatically terminate your\r
+rights under this License.  However, parties who have received copies,\r
+or rights, from you under this License will not have their licenses\r
+terminated so long as such parties remain in full compliance.\r
+\r
+  9. You are not required to accept this License, since you have not\r
+signed it.  However, nothing else grants you permission to modify or\r
+distribute the Library or its derivative works.  These actions are\r
+prohibited by law if you do not accept this License.  Therefore, by\r
+modifying or distributing the Library (or any work based on the\r
+Library), you indicate your acceptance of this License to do so, and\r
+all its terms and conditions for copying, distributing or modifying\r
+the Library or works based on it.\r
+\r
+  10. Each time you redistribute the Library (or any work based on the\r
+Library), the recipient automatically receives a license from the\r
+original licensor to copy, distribute, link with or modify the Library\r
+subject to these terms and conditions.  You may not impose any further\r
+restrictions on the recipients' exercise of the rights granted herein.\r
+You are not responsible for enforcing compliance by third parties with\r
+this License.\r
+\r
+  11. If, as a consequence of a court judgment or allegation of patent\r
+infringement or for any other reason (not limited to patent issues),\r
+conditions are imposed on you (whether by court order, agreement or\r
+otherwise) that contradict the conditions of this License, they do not\r
+excuse you from the conditions of this License.  If you cannot\r
+distribute so as to satisfy simultaneously your obligations under this\r
+License and any other pertinent obligations, then as a consequence you\r
+may not distribute the Library at all.  For example, if a patent\r
+license would not permit royalty-free redistribution of the Library by\r
+all those who receive copies directly or indirectly through you, then\r
+the only way you could satisfy both it and this License would be to\r
+refrain entirely from distribution of the Library.\r
+\r
+If any portion of this section is held invalid or unenforceable under any\r
+particular circumstance, the balance of the section is intended to apply,\r
+and the section as a whole is intended to apply in other circumstances.\r
+\r
+It is not the purpose of this section to induce you to infringe any\r
+patents or other property right claims or to contest validity of any\r
+such claims; this section has the sole purpose of protecting the\r
+integrity of the free software distribution system which is\r
+implemented by public license practices.  Many people have made\r
+generous contributions to the wide range of software distributed\r
+through that system in reliance on consistent application of that\r
+system; it is up to the author/donor to decide if he or she is willing\r
+to distribute software through any other system and a licensee cannot\r
+impose that choice.\r
+\r
+This section is intended to make thoroughly clear what is believed to\r
+be a consequence of the rest of this License.\r
+\r
+  12. If the distribution and/or use of the Library is restricted in\r
+certain countries either by patents or by copyrighted interfaces, the\r
+original copyright holder who places the Library under this License may add\r
+an explicit geographical distribution limitation excluding those countries,\r
+so that distribution is permitted only in or among countries not thus\r
+excluded.  In such case, this License incorporates the limitation as if\r
+written in the body of this License.\r
+\r
+  13. The Free Software Foundation may publish revised and/or new\r
+versions of the Lesser General Public License from time to time.\r
+Such new versions will be similar in spirit to the present version,\r
+but may differ in detail to address new problems or concerns.\r
+\r
+Each version is given a distinguishing version number.  If the Library\r
+specifies a version number of this License which applies to it and\r
+"any later version", you have the option of following the terms and\r
+conditions either of that version or of any later version published by\r
+the Free Software Foundation.  If the Library does not specify a\r
+license version number, you may choose any version ever published by\r
+the Free Software Foundation.\r
+\r
+  14. If you wish to incorporate parts of the Library into other free\r
+programs whose distribution conditions are incompatible with these,\r
+write to the author to ask for permission.  For software which is\r
+copyrighted by the Free Software Foundation, write to the Free\r
+Software Foundation; we sometimes make exceptions for this.  Our\r
+decision will be guided by the two goals of preserving the free status\r
+of all derivatives of our free software and of promoting the sharing\r
+and reuse of software generally.\r
+\r
+                           NO WARRANTY\r
+\r
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO\r
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\r
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR\r
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY\r
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE\r
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE\r
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME\r
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\r
+\r
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN\r
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY\r
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU\r
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR\r
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE\r
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING\r
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A\r
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF\r
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+DAMAGES.\r
+\r
+                    END OF TERMS AND CONDITIONS\r
+\r
+           How to Apply These Terms to Your New Libraries\r
+\r
+  If you develop a new library, and you want it to be of the greatest\r
+possible use to the public, we recommend making it free software that\r
+everyone can redistribute and change.  You can do so by permitting\r
+redistribution under these terms (or, alternatively, under the terms of the\r
+ordinary General Public License).\r
+\r
+  To apply these terms, attach the following notices to the library.  It is\r
+safest to attach them to the start of each source file to most effectively\r
+convey the exclusion of warranty; and each file should have at least the\r
+"copyright" line and a pointer to where the full notice is found.\r
+\r
+    <one line to give the library's name and a brief idea of what it does.>\r
+    Copyright (C) <year>  <name of author>\r
+\r
+    This library is free software; you can redistribute it and/or\r
+    modify it under the terms of the GNU Lesser General Public\r
+    License as published by the Free Software Foundation; either\r
+    version 2.1 of the License, or (at your option) any later version.\r
+\r
+    This library is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+    Lesser General Public License for more details.\r
+\r
+    You should have received a copy of the GNU Lesser General Public\r
+    License along with this library; if not, write to the Free Software\r
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
+\r
+Also add information on how to contact you by electronic and paper mail.\r
+\r
+You should also get your employer (if you work as a programmer) or your\r
+school, if any, to sign a "copyright disclaimer" for the library, if\r
+necessary.  Here is a sample; alter the names:\r
+\r
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the\r
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.\r
+\r
+  <signature of Ty Coon>, 1 April 1990\r
+  Ty Coon, President of Vice\r
+\r
+That's all there is to it!\r
+\r
+\r
diff --git a/jscripts/tiny_mce/plugins/acheck/editor_plugin.js b/jscripts/tiny_mce/plugins/acheck/editor_plugin.js
new file mode 100644 (file)
index 0000000..aaae37c
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.PluginManager.requireLangPack('acheck');tinymce.create('tinymce.plugins.AcheckPlugin',{init:function(ed,url){ed.addCommand('mceACheck',function(){var theCode='<html><body onLoad="document.accessform.submit();"> \n';theCode+='<h1>Submitting Code for Accessibility Checking.....</h1>\n';theCode+='<form action="http://checker.atrc.utoronto.ca/servlet/Checkacc" name="accessform" method="post"> \n';theCode+='<input type="hidden" name="guide" value="wcag-2-0-aaa.xml" /> \n';theCode+='<input type="hidden" name="type" value="form" /> \n';theCode+='<textarea name="edittext">'+tinyMCE.activeEditor.getContent({format:'raw'})+'</textarea>\n';theCode+='<input type="submit" /></form> \n';theCode+='</body></html> \n';accessWin=window.open('','accessWin','');accessWin.document.writeln(theCode);accessWin.document.close()});ed.addButton('acheck',{title:'acheck.desc',cmd:'mceACheck',image:url+'/img/acheck.gif'});ed.onNodeChange.add(function(ed,cm,n){cm.setActive('acheck',n.nodeName=='acheck')})},createControl:function(n,cm){return null},getInfo:function(){return{longname:'ACheck Plugin',author:'ATutor',authorurl:'http://www.atutor.ca',infourl:'http://www.atutor.ca',version:"1.0"}}});tinymce.PluginManager.add('acheck',tinymce.plugins.AcheckPlugin)})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/acheck/editor_plugin_src.js b/jscripts/tiny_mce/plugins/acheck/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..262b6ab
--- /dev/null
@@ -0,0 +1,84 @@
+/**\r
+ * $Id: editor_plugin_src.js 201 2008-04-17 15:56:56Z cindy $\r
+ *\r
+ * @author Cindy Li\r
+ * @copyright Copyright © 2008, ATutor, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       // Load plugin specific language pack\r
+       tinymce.PluginManager.requireLangPack('acheck');\r
+\r
+       tinymce.create('tinymce.plugins.AcheckPlugin', {\r
+               /**\r
+                * Initializes the plugin, this will be executed after the plugin has been created.\r
+                * This call is done before the editor instance has finished it's initialization so use the onInit event\r
+                * of the editor instance to intercept that event.\r
+                *\r
+                * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.\r
+                * @param {string} url Absolute URL to where the plugin is located.\r
+                */\r
+               init : function(ed, url) {\r
+                       // Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceACheck');\r
+                       ed.addCommand('mceACheck', function() {\r
+\r
+                                       var theCode = '<html><body onLoad="document.accessform.submit();"> \n';\r
+                                       theCode += '<h1>Submitting Code for Accessibility Checking.....</h1>\n';\r
+                                       theCode += '<form action="http://checker.atrc.utoronto.ca/servlet/Checkacc" name="accessform" method="post"> \n';\r
+                                       theCode += '<input type="hidden" name="guide" value="wcag-2-0-aaa.xml" /> \n';\r
+                                       theCode += '<input type="hidden" name="type" value="form" /> \n';\r
+                                       theCode += '<textarea name="edittext">' + tinyMCE.activeEditor.getContent({format : 'raw'}) + '</textarea>\n';\r
+                                       theCode += '<input type="submit" /></form> \n';  \r
+                                       theCode += '</body></html> \n';\r
+                                       accessWin = window.open('', 'accessWin',  '');\r
+                                       accessWin.document.writeln(theCode);\r
+                                       accessWin.document.close();\r
+                       });\r
+\r
+                       // Register ACheck button\r
+                       ed.addButton('acheck', {\r
+                               title : 'acheck.desc',\r
+                               cmd : 'mceACheck',\r
+                               image : url + '/img/acheck.gif'\r
+                       });\r
+\r
+                       // Add a node change handler, selects the button in the UI when a image is selected\r
+                       ed.onNodeChange.add(function(ed, cm, n) {\r
+                               cm.setActive('acheck', n.nodeName == 'acheck');\r
+                       });\r
+               },\r
+\r
+               /**\r
+                * Creates control instances based in the incomming name. This method is normally not\r
+                * needed since the addButton method of the tinymce.Editor class is a more easy way of adding buttons\r
+                * but you sometimes need to create more complex controls like listboxes, split buttons etc then this\r
+                * method can be used to create those.\r
+                *\r
+                * @param {String} n Name of the control to create.\r
+                * @param {tinymce.ControlManager} cm Control manager to use inorder to create new control.\r
+                * @return {tinymce.ui.Control} New control instance or null if no control was created.\r
+                */\r
+               createControl : function(n, cm) {\r
+                       return null;\r
+               },\r
+\r
+               /**\r
+                * Returns information about the plugin as a name/value array.\r
+                * The current keys are longname, author, authorurl, infourl and version.\r
+                *\r
+                * @return {Object} Name/value array containing information about the plugin.\r
+                */\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'ACheck Plugin',\r
+                               author   : 'ATutor',\r
+                               authorurl : 'http://www.atutor.ca',\r
+                               infourl : 'http://www.atutor.ca',\r
+                               version : "1.0"\r
+                       };\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('acheck', tinymce.plugins.AcheckPlugin);\r
+})();\r
diff --git a/jscripts/tiny_mce/plugins/acheck/img/acheck.gif b/jscripts/tiny_mce/plugins/acheck/img/acheck.gif
new file mode 100644 (file)
index 0000000..76f3a7d
Binary files /dev/null and b/jscripts/tiny_mce/plugins/acheck/img/acheck.gif differ
diff --git a/jscripts/tiny_mce/plugins/acheck/js/dialog.js b/jscripts/tiny_mce/plugins/acheck/js/dialog.js
new file mode 100644 (file)
index 0000000..fa83411
--- /dev/null
@@ -0,0 +1,19 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+var ExampleDialog = {\r
+       init : function() {\r
+               var f = document.forms[0];\r
+\r
+               // Get the selected contents as text and place it in the input\r
+               f.someval.value = tinyMCEPopup.editor.selection.getContent({format : 'text'});\r
+               f.somearg.value = tinyMCEPopup.getWindowArg('some_custom_arg');\r
+       },\r
+\r
+       insert : function() {\r
+               // Insert the contents from the input into the document\r
+               tinyMCEPopup.editor.execCommand('mceInsertContent', false, document.forms[0].someval.value);\r
+               tinyMCEPopup.close();\r
+       }\r
+};\r
+\r
+tinyMCEPopup.onInit.add(ExampleDialog.init, ExampleDialog);\r
diff --git a/jscripts/tiny_mce/plugins/acheck/langs/en.js b/jscripts/tiny_mce/plugins/acheck/langs/en.js
new file mode 100644 (file)
index 0000000..7bce9e9
--- /dev/null
@@ -0,0 +1,3 @@
+tinyMCE.addI18n('en.acheck',{\r
+       desc : 'Check Accessibility'\r
+});\r
diff --git a/jscripts/tiny_mce/plugins/acheck/langs/en_dlg.js b/jscripts/tiny_mce/plugins/acheck/langs/en_dlg.js
new file mode 100644 (file)
index 0000000..54826f8
--- /dev/null
@@ -0,0 +1,3 @@
+tinyMCE.addI18n('en.acheck_dlg',{\r
+       title : 'ATRC Accessibility Checker'\r
+});\r
diff --git a/jscripts/tiny_mce/plugins/advhr/css/advhr.css b/jscripts/tiny_mce/plugins/advhr/css/advhr.css
new file mode 100644 (file)
index 0000000..0e22834
--- /dev/null
@@ -0,0 +1,5 @@
+input.radio {border:1px none #000; background:transparent; vertical-align:middle;}\r
+.panel_wrapper div.current {height:80px;}\r
+#width {width:50px; vertical-align:middle;}\r
+#width2 {width:50px; vertical-align:middle;}\r
+#size {width:100px;}\r
diff --git a/jscripts/tiny_mce/plugins/advhr/editor_plugin.js b/jscripts/tiny_mce/plugins/advhr/editor_plugin.js
new file mode 100644 (file)
index 0000000..f335004
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.AdvancedHRPlugin',{init:function(ed,url){ed.addCommand('mceAdvancedHr',function(){ed.windowManager.open({file:url+'/rule.htm',width:250+parseInt(ed.getLang('advhr.delta_width',0)),height:160+parseInt(ed.getLang('advhr.delta_height',0)),inline:1},{plugin_url:url});});ed.addButton('advhr',{title:'advhr.advhr_desc',cmd:'mceAdvancedHr'});ed.onNodeChange.add(function(ed,cm,n){cm.setActive('advhr',n.nodeName=='HR');});ed.onClick.add(function(ed,e){e=e.target;if(e.nodeName==='HR')ed.selection.select(e);});},getInfo:function(){return{longname:'Advanced HR',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advhr',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('advhr',tinymce.plugins.AdvancedHRPlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/advhr/editor_plugin_src.js b/jscripts/tiny_mce/plugins/advhr/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..8a84753
--- /dev/null
@@ -0,0 +1,54 @@
+/**\r
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.AdvancedHRPlugin', {\r
+               init : function(ed, url) {\r
+                       // Register commands\r
+                       ed.addCommand('mceAdvancedHr', function() {\r
+                               ed.windowManager.open({\r
+                                       file : url + '/rule.htm',\r
+                                       width : 250 + parseInt(ed.getLang('advhr.delta_width', 0)),\r
+                                       height : 160 + parseInt(ed.getLang('advhr.delta_height', 0)),\r
+                                       inline : 1\r
+                               }, {\r
+                                       plugin_url : url\r
+                               });\r
+                       });\r
+\r
+                       // Register buttons\r
+                       ed.addButton('advhr', {\r
+                               title : 'advhr.advhr_desc',\r
+                               cmd : 'mceAdvancedHr'\r
+                       });\r
+\r
+                       ed.onNodeChange.add(function(ed, cm, n) {\r
+                               cm.setActive('advhr', n.nodeName == 'HR');\r
+                       });\r
+\r
+                       ed.onClick.add(function(ed, e) {\r
+                               e = e.target;\r
+\r
+                               if (e.nodeName === 'HR')\r
+                                       ed.selection.select(e);\r
+                       });\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Advanced HR',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advhr',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('advhr', tinymce.plugins.AdvancedHRPlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/advhr/js/rule.js b/jscripts/tiny_mce/plugins/advhr/js/rule.js
new file mode 100644 (file)
index 0000000..73ee618
--- /dev/null
@@ -0,0 +1,34 @@
+var AdvHRDialog = {\r
+       init : function(ed) {\r
+               var dom = ed.dom, f = document.forms[0], n = ed.selection.getNode(), w;\r
+\r
+               w = dom.getAttrib(n, 'width');\r
+               f.width.value = w ? parseInt(w) : '';\r
+               f.size.value = dom.getAttrib(n, 'size');\r
+               f.noshade.checked = !!dom.getAttrib(n, 'noshade');\r
+               selectByValue(f, 'width2', w.indexOf('%') != -1 ? '%' : 'px');\r
+       },\r
+\r
+       update : function() {\r
+               var ed = tinyMCEPopup.editor, h, f = document.forms[0];\r
+\r
+               h = '<hr';\r
+\r
+               if (f.size.value)\r
+                       h += ' size="' + f.size.value + '"';\r
+\r
+               if (f.width.value)\r
+                       h += ' width="' + f.width.value + (f.width2.value == '%' ? '%' : '') + '"';\r
+\r
+               if (f.noshade.checked)\r
+                       h += ' noshade="noshade"';\r
+\r
+               h += ' />';\r
+\r
+               ed.execCommand("mceInsertContent", false, h);\r
+               tinyMCEPopup.close();\r
+       }\r
+};\r
+\r
+tinyMCEPopup.requireLangPack();\r
+tinyMCEPopup.onInit.add(AdvHRDialog.init, AdvHRDialog);\r
diff --git a/jscripts/tiny_mce/plugins/advhr/langs/en_dlg.js b/jscripts/tiny_mce/plugins/advhr/langs/en_dlg.js
new file mode 100644 (file)
index 0000000..873bfd8
--- /dev/null
@@ -0,0 +1,5 @@
+tinyMCE.addI18n('en.advhr_dlg',{\r
+width:"Width",\r
+size:"Height",\r
+noshade:"No shadow"\r
+});
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/advhr/rule.htm b/jscripts/tiny_mce/plugins/advhr/rule.htm
new file mode 100644 (file)
index 0000000..8d2efa7
--- /dev/null
@@ -0,0 +1,63 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#advhr.advhr_desc}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="js/rule.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>\r
+       <link href="css/advhr.css?v=307" rel="stylesheet" type="text/css" />\r
+       <base target="_self" />\r
+</head>\r
+<body>\r
+<form onsubmit="AdvHRDialog.update();return false;" action="#">\r
+       <div class="tabs">\r
+               <ul>\r
+                       <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advhr.advhr_desc}</a></span></li>\r
+               </ul>\r
+       </div>\r
+\r
+       <div class="panel_wrapper">\r
+               <div id="general_panel" class="panel current">\r
+                       <table border="0" cellpadding="4" cellspacing="0">\r
+                    <tr>\r
+                        <td><label for="width">{#advhr_dlg.width}</label></td>\r
+                        <td nowrap="nowrap">\r
+                            <input id="width" name="width" type="text" value="" class="mceFocus" />\r
+                            <select name="width2" id="width2">\r
+                                <option value="">px</option>\r
+                                <option value="%">%</option>\r
+                            </select>\r
+                        </td>\r
+                    </tr>\r
+                    <tr>\r
+                        <td><label for="size">{#advhr_dlg.size}</label></td>\r
+                        <td><select id="size" name="size">\r
+                            <option value="">Normal</option>\r
+                            <option value="1">1</option>\r
+                            <option value="2">2</option>\r
+                            <option value="3">3</option>\r
+                            <option value="4">4</option>\r
+                            <option value="5">5</option>\r
+                        </select></td>\r
+                    </tr>\r
+                    <tr>\r
+                        <td><label for="noshade">{#advhr_dlg.noshade}</label></td>\r
+                        <td><input type="checkbox" name="noshade" id="noshade" class="radio" /></td>\r
+                    </tr>\r
+            </table>\r
+               </div>\r
+       </div>\r
+\r
+       <div class="mceActionPanel">\r
+               <div style="float: left">\r
+                       <input type="submit" id="insert" name="insert" value="{#insert}" />\r
+               </div>\r
+\r
+               <div style="float: right">\r
+                       <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+               </div>\r
+       </div>\r
+</form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/advimage/css/advimage.css b/jscripts/tiny_mce/plugins/advimage/css/advimage.css
new file mode 100644 (file)
index 0000000..4d549a5
--- /dev/null
@@ -0,0 +1,13 @@
+#src_list, #over_list, #out_list {width:280px;}\r
+.mceActionPanel {margin-top:7px;}\r
+.alignPreview {border:1px solid #000; width:140px; height:140px; overflow:hidden; padding:5px;}\r
+.checkbox {border:0;}\r
+.panel_wrapper div.current {height:305px;}\r
+#prev {margin:0; border:1px solid #000; width:99%; height:150px; overflow:auto;}\r
+#align, #classlist {width:150px;}\r
+#width, #height {vertical-align:middle; width:50px; text-align:center;}\r
+#vspace, #hspace, #border {vertical-align:middle; width:30px; text-align:center;}\r
+#class_list {width:180px;}\r
+input {width: 280px;}\r
+#constrain, #onmousemovecheck {width:auto;}\r
+#id, #dir, #lang, #usemap, #longdesc {width:200px;}\r
diff --git a/jscripts/tiny_mce/plugins/advimage/editor_plugin.js b/jscripts/tiny_mce/plugins/advimage/editor_plugin.js
new file mode 100644 (file)
index 0000000..3af5057
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.AdvancedImagePlugin',{init:function(ed,url){ed.addCommand('mceAdvImage',function(){if(ed.dom.getAttrib(ed.selection.getNode(),'class').indexOf('mceItem')!=-1)return;ed.windowManager.open({file:url+'/image.htm',width:480+parseInt(ed.getLang('advimage.delta_width',0)),height:385+parseInt(ed.getLang('advimage.delta_height',0)),inline:1},{plugin_url:url});});ed.addButton('image',{title:'advimage.image_desc',cmd:'mceAdvImage'});},getInfo:function(){return{longname:'Advanced image',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advimage',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('advimage',tinymce.plugins.AdvancedImagePlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/advimage/editor_plugin_src.js b/jscripts/tiny_mce/plugins/advimage/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..f526842
--- /dev/null
@@ -0,0 +1,47 @@
+/**\r
+ * $Id: editor_plugin_src.js 677 2008-03-07 13:52:41Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.AdvancedImagePlugin', {\r
+               init : function(ed, url) {\r
+                       // Register commands\r
+                       ed.addCommand('mceAdvImage', function() {\r
+                               // Internal image object like a flash placeholder\r
+                               if (ed.dom.getAttrib(ed.selection.getNode(), 'class').indexOf('mceItem') != -1)\r
+                                       return;\r
+\r
+                               ed.windowManager.open({\r
+                                       file : url + '/image.htm',\r
+                                       width : 480 + parseInt(ed.getLang('advimage.delta_width', 0)),\r
+                                       height : 385 + parseInt(ed.getLang('advimage.delta_height', 0)),\r
+                                       inline : 1\r
+                               }, {\r
+                                       plugin_url : url\r
+                               });\r
+                       });\r
+\r
+                       // Register buttons\r
+                       ed.addButton('image', {\r
+                               title : 'advimage.image_desc',\r
+                               cmd : 'mceAdvImage'\r
+                       });\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Advanced image',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advimage',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('advimage', tinymce.plugins.AdvancedImagePlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/advimage/image.htm b/jscripts/tiny_mce/plugins/advimage/image.htm
new file mode 100644 (file)
index 0000000..56d3238
--- /dev/null
@@ -0,0 +1,238 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#advimage_dlg.dialog_title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/validate.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/editable_selects.js?v=307"></script>\r
+       <script type="text/javascript" src="js/image.js?v=307"></script>\r
+       <link href="css/advimage.css?v=307" rel="stylesheet" type="text/css" />\r
+       <base target="_self" />\r
+</head>\r
+<body id="advimage" style="display: none">\r
+    <form onsubmit="ImageDialog.insert();return false;" action="#"> \r
+               <div class="tabs">\r
+                       <ul>\r
+                               <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advimage_dlg.tab_general}</a></span></li>\r
+                               <li id="appearance_tab"><span><a href="javascript:mcTabs.displayTab('appearance_tab','appearance_panel');" onmousedown="return false;">{#advimage_dlg.tab_appearance}</a></span></li>\r
+                               <li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#advimage_dlg.tab_advanced}</a></span></li>\r
+                       </ul>\r
+               </div>\r
+\r
+               <div class="panel_wrapper">\r
+                       <div id="general_panel" class="panel current">\r
+                               <fieldset>\r
+                                               <legend>{#advimage_dlg.general}</legend>\r
+\r
+                                               <table class="properties">\r
+                                                       <tr>\r
+                                                               <td class="column1"><label id="srclabel" for="src">{#advimage_dlg.src}</label></td>\r
+                                                               <td colspan="2"><table border="0" cellspacing="0" cellpadding="0">\r
+                                                                       <tr> \r
+                                                                         <td><input name="src" type="text" id="src" value="" class="mceFocus" onchange="ImageDialog.showPreviewImage(this.value);" /></td> \r
+                                                                         <td id="srcbrowsercontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                                 </table></td>\r
+                                                       </tr>\r
+                                                       <tr>\r
+                                                               <td><label for="src_list">{#advimage_dlg.image_list}</label></td>\r
+                                                               <td><select id="src_list" name="src_list" onchange="document.getElementById('src').value=this.options[this.selectedIndex].value;document.getElementById('alt').value=this.options[this.selectedIndex].text;document.getElementById('title').value=this.options[this.selectedIndex].text;ImageDialog.showPreviewImage(this.options[this.selectedIndex].value);"></select></td>\r
+                                                       </tr>\r
+                                                       <tr> \r
+                                                               <td class="column1"><label id="altlabel" for="alt">{#advimage_dlg.alt}</label></td> \r
+                                                               <td colspan="2"><input id="alt" name="alt" type="text" value="" /></td> \r
+                                                       </tr> \r
+                                                       <tr> \r
+                                                               <td class="column1"><label id="titlelabel" for="title">{#advimage_dlg.title}</label></td> \r
+                                                               <td colspan="2"><input id="title" name="title" type="text" value="" /></td> \r
+                                                       </tr>\r
+                                               </table>\r
+                               </fieldset>\r
+\r
+                               <fieldset>\r
+                                       <legend>{#advimage_dlg.preview}</legend>\r
+                                       <div id="prev"></div>\r
+                               </fieldset>\r
+                       </div>\r
+\r
+                       <div id="appearance_panel" class="panel">\r
+                               <fieldset>\r
+                                       <legend>{#advimage_dlg.tab_appearance}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr> \r
+                                                       <td class="column1"><label id="alignlabel" for="align">{#advimage_dlg.align}</label></td> \r
+                                                       <td><select id="align" name="align" onchange="ImageDialog.updateStyle('align');ImageDialog.changeAppearance();"> \r
+                                                                       <option value="">{#not_set}</option> \r
+                                                                       <option value="baseline">{#advimage_dlg.align_baseline}</option>\r
+                                                                       <option value="top">{#advimage_dlg.align_top}</option>\r
+                                                                       <option value="middle">{#advimage_dlg.align_middle}</option>\r
+                                                                       <option value="bottom">{#advimage_dlg.align_bottom}</option>\r
+                                                                       <option value="text-top">{#advimage_dlg.align_texttop}</option>\r
+                                                                       <option value="text-bottom">{#advimage_dlg.align_textbottom}</option>\r
+                                                                       <option value="left">{#advimage_dlg.align_left}</option>\r
+                                                                       <option value="right">{#advimage_dlg.align_right}</option>\r
+                                                               </select> \r
+                                                       </td>\r
+                                                       <td rowspan="6" valign="top">\r
+                                                               <div class="alignPreview">\r
+                                                                       <img id="alignSampleImg" src="img/sample.gif" alt="{#advimage_dlg.example_img}" />\r
+                                                                       Lorem ipsum, Dolor sit amet, consectetuer adipiscing loreum ipsum edipiscing elit, sed diam\r
+                                                                       nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.Loreum ipsum\r
+                                                                       edipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam\r
+                                                                       erat volutpat.\r
+                                                               </div>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label id="widthlabel" for="width">{#advimage_dlg.dimensions}</label></td>\r
+                                                       <td nowrap="nowrap">\r
+                                                               <input name="width" type="text" id="width" value="" size="5" maxlength="5" class="size" onchange="ImageDialog.changeHeight();" /> x \r
+                                                               <input name="height" type="text" id="height" value="" size="5" maxlength="5" class="size" onchange="ImageDialog.changeWidth();" /> px\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td>&nbsp;</td>\r
+                                                       <td><table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="constrain" type="checkbox" name="constrain" class="checkbox" /></td>\r
+                                                                               <td><label id="constrainlabel" for="constrain">{#advimage_dlg.constrain_proportions}</label></td>\r
+                                                                       </tr>\r
+                                                               </table></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label id="vspacelabel" for="vspace">{#advimage_dlg.vspace}</label></td> \r
+                                                       <td><input name="vspace" type="text" id="vspace" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('vspace');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('vspace');ImageDialog.changeAppearance();" />\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr> \r
+                                                       <td class="column1"><label id="hspacelabel" for="hspace">{#advimage_dlg.hspace}</label></td> \r
+                                                       <td><input name="hspace" type="text" id="hspace" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('hspace');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('hspace');ImageDialog.changeAppearance();" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label id="borderlabel" for="border">{#advimage_dlg.border}</label></td> \r
+                                                       <td><input id="border" name="border" type="text" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('border');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('border');ImageDialog.changeAppearance();" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="class_list">{#class_name}</label></td>\r
+                                                       <td colspan="2"><select id="class_list" name="class_list" class="mceEditableSelect"></select></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label id="stylelabel" for="style">{#advimage_dlg.style}</label></td> \r
+                                                       <td colspan="2"><input id="style" name="style" type="text" value="" onchange="ImageDialog.changeAppearance();" /></td> \r
+                                               </tr>\r
+\r
+                                               <!-- <tr>\r
+                                                       <td class="column1"><label id="classeslabel" for="classes">{#advimage_dlg.classes}</label></td> \r
+                                                       <td colspan="2"><input id="classes" name="classes" type="text" value="" onchange="selectByValue(this.form,'classlist',this.value,true);" /></td> \r
+                                               </tr> -->\r
+                                       </table>\r
+                               </fieldset>\r
+                       </div>\r
+\r
+                       <div id="advanced_panel" class="panel">\r
+                               <fieldset>\r
+                                       <legend>{#advimage_dlg.swap_image}</legend>\r
+\r
+                                       <input type="checkbox" id="onmousemovecheck" name="onmousemovecheck" class="checkbox" onclick="ImageDialog.setSwapImage(this.checked);" />\r
+                                       <label id="onmousemovechecklabel" for="onmousemovecheck">{#advimage_dlg.alt_image}</label>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0" width="100%">\r
+                                                       <tr>\r
+                                                               <td class="column1"><label id="onmouseoversrclabel" for="onmouseoversrc">{#advimage_dlg.mouseover}</label></td> \r
+                                                               <td><table border="0" cellspacing="0" cellpadding="0"> \r
+                                                                       <tr> \r
+                                                                         <td><input id="onmouseoversrc" name="onmouseoversrc" type="text" value="" /></td> \r
+                                                                         <td id="onmouseoversrccontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                                 </table></td>\r
+                                                       </tr>\r
+                                                       <tr>\r
+                                                               <td><label for="over_list">{#advimage_dlg.image_list}</label></td>\r
+                                                               <td><select id="over_list" name="over_list" onchange="document.getElementById('onmouseoversrc').value=this.options[this.selectedIndex].value;"></select></td>\r
+                                                       </tr>\r
+                                                       <tr> \r
+                                                               <td class="column1"><label id="onmouseoutsrclabel" for="onmouseoutsrc">{#advimage_dlg.mouseout}</label></td> \r
+                                                               <td class="column2"><table border="0" cellspacing="0" cellpadding="0"> \r
+                                                                       <tr> \r
+                                                                         <td><input id="onmouseoutsrc" name="onmouseoutsrc" type="text" value="" /></td> \r
+                                                                         <td id="onmouseoutsrccontainer">&nbsp;</td>\r
+                                                                       </tr> \r
+                                                                 </table></td> \r
+                                                       </tr>\r
+                                                       <tr>\r
+                                                               <td><label for="out_list">{#advimage_dlg.image_list}</label></td>\r
+                                                               <td><select id="out_list" name="out_list" onchange="document.getElementById('onmouseoutsrc').value=this.options[this.selectedIndex].value;"></select></td>\r
+                                                       </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+\r
+                               <fieldset>\r
+                                       <legend>{#advimage_dlg.misc}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td class="column1"><label id="idlabel" for="id">{#advimage_dlg.id}</label></td> \r
+                                                       <td><input id="id" name="id" type="text" value="" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label id="dirlabel" for="dir">{#advimage_dlg.langdir}</label></td> \r
+                                                       <td>\r
+                                                               <select id="dir" name="dir" onchange="ImageDialog.changeAppearance();"> \r
+                                                                               <option value="">{#not_set}</option> \r
+                                                                               <option value="ltr">{#advimage_dlg.ltr}</option> \r
+                                                                               <option value="rtl">{#advimage_dlg.rtl}</option> \r
+                                                               </select>\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label id="langlabel" for="lang">{#advimage_dlg.langcode}</label></td> \r
+                                                       <td>\r
+                                                               <input id="lang" name="lang" type="text" value="" />\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label id="usemaplabel" for="usemap">{#advimage_dlg.map}</label></td> \r
+                                                       <td>\r
+                                                               <input id="usemap" name="usemap" type="text" value="" />\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label id="longdesclabel" for="longdesc">{#advimage_dlg.long_desc}</label></td>\r
+                                                       <td><table border="0" cellspacing="0" cellpadding="0">\r
+                                                                       <tr>\r
+                                                                         <td><input id="longdesc" name="longdesc" type="text" value="" /></td>\r
+                                                                         <td id="longdesccontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table></td> \r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+                       </div>\r
+               </div>\r
+\r
+               <div class="mceActionPanel">\r
+                       <div style="float: left">\r
+                               <input type="submit" id="insert" name="insert" value="{#insert}" />\r
+                       </div>\r
+\r
+                       <div style="float: right">\r
+                               <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+                       </div>\r
+               </div>\r
+    </form>\r
+</body> \r
+</html> \r
diff --git a/jscripts/tiny_mce/plugins/advimage/img/sample.gif b/jscripts/tiny_mce/plugins/advimage/img/sample.gif
new file mode 100644 (file)
index 0000000..53bf689
Binary files /dev/null and b/jscripts/tiny_mce/plugins/advimage/img/sample.gif differ
diff --git a/jscripts/tiny_mce/plugins/advimage/js/image.js b/jscripts/tiny_mce/plugins/advimage/js/image.js
new file mode 100644 (file)
index 0000000..73a6e89
--- /dev/null
@@ -0,0 +1,441 @@
+var ImageDialog = {\r
+       preInit : function() {\r
+               var url;\r
+\r
+               tinyMCEPopup.requireLangPack();\r
+\r
+               if (url = tinyMCEPopup.getParam("external_image_list_url"))\r
+                       document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>');\r
+       },\r
+\r
+       init : function(ed) {\r
+               var f = document.forms[0], nl = f.elements, ed = tinyMCEPopup.editor, dom = ed.dom, n = ed.selection.getNode();\r
+\r
+               tinyMCEPopup.resizeToInnerSize();\r
+               this.fillClassList('class_list');\r
+               this.fillFileList('src_list', 'tinyMCEImageList');\r
+               this.fillFileList('over_list', 'tinyMCEImageList');\r
+               this.fillFileList('out_list', 'tinyMCEImageList');\r
+               TinyMCE_EditableSelects.init();\r
+\r
+               if (n.nodeName == 'IMG') {\r
+                       nl.src.value = dom.getAttrib(n, 'src');\r
+                       nl.width.value = dom.getAttrib(n, 'width');\r
+                       nl.height.value = dom.getAttrib(n, 'height');\r
+                       nl.alt.value = dom.getAttrib(n, 'alt');\r
+                       nl.title.value = dom.getAttrib(n, 'title');\r
+                       nl.vspace.value = this.getAttrib(n, 'vspace');\r
+                       nl.hspace.value = this.getAttrib(n, 'hspace');\r
+                       nl.border.value = this.getAttrib(n, 'border');\r
+                       selectByValue(f, 'align', this.getAttrib(n, 'align'));\r
+                       selectByValue(f, 'class_list', dom.getAttrib(n, 'class'), true, true);\r
+                       nl.style.value = dom.getAttrib(n, 'style');\r
+                       nl.id.value = dom.getAttrib(n, 'id');\r
+                       nl.dir.value = dom.getAttrib(n, 'dir');\r
+                       nl.lang.value = dom.getAttrib(n, 'lang');\r
+                       nl.usemap.value = dom.getAttrib(n, 'usemap');\r
+                       nl.longdesc.value = dom.getAttrib(n, 'longdesc');\r
+                       nl.insert.value = ed.getLang('update');\r
+\r
+                       if (/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/.test(dom.getAttrib(n, 'onmouseover')))\r
+                               nl.onmouseoversrc.value = dom.getAttrib(n, 'onmouseover').replace(/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/, '$1');\r
+\r
+                       if (/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/.test(dom.getAttrib(n, 'onmouseout')))\r
+                               nl.onmouseoutsrc.value = dom.getAttrib(n, 'onmouseout').replace(/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/, '$1');\r
+\r
+                       if (ed.settings.inline_styles) {\r
+                               // Move attribs to styles\r
+                               if (dom.getAttrib(n, 'align'))\r
+                                       this.updateStyle('align');\r
+\r
+                               if (dom.getAttrib(n, 'hspace'))\r
+                                       this.updateStyle('hspace');\r
+\r
+                               if (dom.getAttrib(n, 'border'))\r
+                                       this.updateStyle('border');\r
+\r
+                               if (dom.getAttrib(n, 'vspace'))\r
+                                       this.updateStyle('vspace');\r
+                       }\r
+               }\r
+\r
+               // Setup browse button\r
+               document.getElementById('srcbrowsercontainer').innerHTML = getBrowserHTML('srcbrowser','src','image','theme_advanced_image');\r
+               if (isVisible('srcbrowser'))\r
+                       document.getElementById('src').style.width = '260px';\r
+\r
+               // Setup browse button\r
+               document.getElementById('onmouseoversrccontainer').innerHTML = getBrowserHTML('overbrowser','onmouseoversrc','image','theme_advanced_image');\r
+               if (isVisible('overbrowser'))\r
+                       document.getElementById('onmouseoversrc').style.width = '260px';\r
+\r
+               // Setup browse button\r
+               document.getElementById('onmouseoutsrccontainer').innerHTML = getBrowserHTML('outbrowser','onmouseoutsrc','image','theme_advanced_image');\r
+               if (isVisible('outbrowser'))\r
+                       document.getElementById('onmouseoutsrc').style.width = '260px';\r
+\r
+               // If option enabled default contrain proportions to checked\r
+               if (ed.getParam("advimage_constrain_proportions", true))\r
+                       f.constrain.checked = true;\r
+\r
+               // Check swap image if valid data\r
+               if (nl.onmouseoversrc.value || nl.onmouseoutsrc.value)\r
+                       this.setSwapImage(true);\r
+               else\r
+                       this.setSwapImage(false);\r
+\r
+               this.changeAppearance();\r
+               this.showPreviewImage(nl.src.value, 1);\r
+       },\r
+\r
+       insert : function(file, title) {\r
+               var ed = tinyMCEPopup.editor, t = this, f = document.forms[0];\r
+\r
+               if (f.src.value === '') {\r
+                       if (ed.selection.getNode().nodeName == 'IMG') {\r
+                               ed.dom.remove(ed.selection.getNode());\r
+                               ed.execCommand('mceRepaint');\r
+                       }\r
+\r
+                       tinyMCEPopup.close();\r
+                       return;\r
+               }\r
+\r
+               if (tinyMCEPopup.getParam("accessibility_warnings", 1)) {\r
+                       if (!f.alt.value) {\r
+                               tinyMCEPopup.editor.windowManager.confirm(tinyMCEPopup.getLang('advimage_dlg.missing_alt'), function(s) {\r
+                                       if (s)\r
+                                               t.insertAndClose();\r
+                               });\r
+\r
+                               return;\r
+                       }\r
+               }\r
+\r
+               t.insertAndClose();\r
+       },\r
+\r
+       insertAndClose : function() {\r
+               var ed = tinyMCEPopup.editor, f = document.forms[0], nl = f.elements, v, args = {}, el;\r
+\r
+               tinyMCEPopup.restoreSelection();\r
+\r
+               // Fixes crash in Safari\r
+               if (tinymce.isWebKit)\r
+                       ed.getWin().focus();\r
+\r
+               if (!ed.settings.inline_styles) {\r
+                       args = {\r
+                               vspace : nl.vspace.value,\r
+                               hspace : nl.hspace.value,\r
+                               border : nl.border.value,\r
+                               align : getSelectValue(f, 'align')\r
+                       };\r
+               } else {\r
+                       // Remove deprecated values\r
+                       args = {\r
+                               vspace : '',\r
+                               hspace : '',\r
+                               border : '',\r
+                               align : ''\r
+                       };\r
+               }\r
+\r
+               tinymce.extend(args, {\r
+                       src : nl.src.value,\r
+                       width : nl.width.value,\r
+                       height : nl.height.value,\r
+                       alt : nl.alt.value,\r
+                       title : nl.title.value,\r
+                       'class' : getSelectValue(f, 'class_list'),\r
+                       style : nl.style.value,\r
+                       id : nl.id.value,\r
+                       dir : nl.dir.value,\r
+                       lang : nl.lang.value,\r
+                       usemap : nl.usemap.value,\r
+                       longdesc : nl.longdesc.value\r
+               });\r
+\r
+               args.onmouseover = args.onmouseout = '';\r
+\r
+               if (f.onmousemovecheck.checked) {\r
+                       if (nl.onmouseoversrc.value)\r
+                               args.onmouseover = "this.src='" + nl.onmouseoversrc.value + "';";\r
+\r
+                       if (nl.onmouseoutsrc.value)\r
+                               args.onmouseout = "this.src='" + nl.onmouseoutsrc.value + "';";\r
+               }\r
+\r
+               el = ed.selection.getNode();\r
+\r
+               if (el && el.nodeName == 'IMG') {\r
+                       ed.dom.setAttribs(el, args);\r
+               } else {\r
+                       ed.execCommand('mceInsertContent', false, '<img id="__mce_tmp" src="javascript:;" />', {skip_undo : 1});\r
+                       ed.dom.setAttribs('__mce_tmp', args);\r
+                       ed.dom.setAttrib('__mce_tmp', 'id', '');\r
+                       ed.undoManager.add();\r
+               }\r
+\r
+               tinyMCEPopup.close();\r
+       },\r
+\r
+       getAttrib : function(e, at) {\r
+               var ed = tinyMCEPopup.editor, dom = ed.dom, v, v2;\r
+\r
+               if (ed.settings.inline_styles) {\r
+                       switch (at) {\r
+                               case 'align':\r
+                                       if (v = dom.getStyle(e, 'float'))\r
+                                               return v;\r
+\r
+                                       if (v = dom.getStyle(e, 'vertical-align'))\r
+                                               return v;\r
+\r
+                                       break;\r
+\r
+                               case 'hspace':\r
+                                       v = dom.getStyle(e, 'margin-left')\r
+                                       v2 = dom.getStyle(e, 'margin-right');\r
+\r
+                                       if (v && v == v2)\r
+                                               return parseInt(v.replace(/[^0-9]/g, ''));\r
+\r
+                                       break;\r
+\r
+                               case 'vspace':\r
+                                       v = dom.getStyle(e, 'margin-top')\r
+                                       v2 = dom.getStyle(e, 'margin-bottom');\r
+                                       if (v && v == v2)\r
+                                               return parseInt(v.replace(/[^0-9]/g, ''));\r
+\r
+                                       break;\r
+\r
+                               case 'border':\r
+                                       v = 0;\r
+\r
+                                       tinymce.each(['top', 'right', 'bottom', 'left'], function(sv) {\r
+                                               sv = dom.getStyle(e, 'border-' + sv + '-width');\r
+\r
+                                               // False or not the same as prev\r
+                                               if (!sv || (sv != v && v !== 0)) {\r
+                                                       v = 0;\r
+                                                       return false;\r
+                                               }\r
+\r
+                                               if (sv)\r
+                                                       v = sv;\r
+                                       });\r
+\r
+                                       if (v)\r
+                                               return parseInt(v.replace(/[^0-9]/g, ''));\r
+\r
+                                       break;\r
+                       }\r
+               }\r
+\r
+               if (v = dom.getAttrib(e, at))\r
+                       return v;\r
+\r
+               return '';\r
+       },\r
+\r
+       setSwapImage : function(st) {\r
+               var f = document.forms[0];\r
+\r
+               f.onmousemovecheck.checked = st;\r
+               setBrowserDisabled('overbrowser', !st);\r
+               setBrowserDisabled('outbrowser', !st);\r
+\r
+               if (f.over_list)\r
+                       f.over_list.disabled = !st;\r
+\r
+               if (f.out_list)\r
+                       f.out_list.disabled = !st;\r
+\r
+               f.onmouseoversrc.disabled = !st;\r
+               f.onmouseoutsrc.disabled  = !st;\r
+       },\r
+\r
+       fillClassList : function(id) {\r
+               var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl;\r
+\r
+               if (v = tinyMCEPopup.getParam('theme_advanced_styles')) {\r
+                       cl = [];\r
+\r
+                       tinymce.each(v.split(';'), function(v) {\r
+                               var p = v.split('=');\r
+\r
+                               cl.push({'title' : p[0], 'class' : p[1]});\r
+                       });\r
+               } else\r
+                       cl = tinyMCEPopup.editor.dom.getClasses();\r
+\r
+               if (cl.length > 0) {\r
+                       lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('not_set'), '');\r
+\r
+                       tinymce.each(cl, function(o) {\r
+                               lst.options[lst.options.length] = new Option(o.title || o['class'], o['class']);\r
+                       });\r
+               } else\r
+                       dom.remove(dom.getParent(id, 'tr'));\r
+       },\r
+\r
+       fillFileList : function(id, l) {\r
+               var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl;\r
+\r
+               l = window[l];\r
+\r
+               if (l && l.length > 0) {\r
+                       lst.options[lst.options.length] = new Option('', '');\r
+\r
+                       tinymce.each(l, function(o) {\r
+                               lst.options[lst.options.length] = new Option(o[0], o[1]);\r
+                       });\r
+               } else\r
+                       dom.remove(dom.getParent(id, 'tr'));\r
+       },\r
+\r
+       resetImageData : function() {\r
+               var f = document.forms[0];\r
+\r
+               f.elements.width.value = f.elements.height.value = '';\r
+       },\r
+\r
+       updateImageData : function(img, st) {\r
+               var f = document.forms[0];\r
+\r
+               if (!st) {\r
+                       f.elements.width.value = img.width;\r
+                       f.elements.height.value = img.height;\r
+               }\r
+\r
+               this.preloadImg = img;\r
+       },\r
+\r
+       changeAppearance : function() {\r
+               var ed = tinyMCEPopup.editor, f = document.forms[0], img = document.getElementById('alignSampleImg');\r
+\r
+               if (img) {\r
+                       if (ed.getParam('inline_styles')) {\r
+                               ed.dom.setAttrib(img, 'style', f.style.value);\r
+                       } else {\r
+                               img.align = f.align.value;\r
+                               img.border = f.border.value;\r
+                               img.hspace = f.hspace.value;\r
+                               img.vspace = f.vspace.value;\r
+                       }\r
+               }\r
+       },\r
+\r
+       changeHeight : function() {\r
+               var f = document.forms[0], tp, t = this;\r
+\r
+               if (!f.constrain.checked || !t.preloadImg) {\r
+                       return;\r
+               }\r
+\r
+               if (f.width.value == "" || f.height.value == "")\r
+                       return;\r
+\r
+               tp = (parseInt(f.width.value) / parseInt(t.preloadImg.width)) * t.preloadImg.height;\r
+               f.height.value = tp.toFixed(0);\r
+       },\r
+\r
+       changeWidth : function() {\r
+               var f = document.forms[0], tp, t = this;\r
+\r
+               if (!f.constrain.checked || !t.preloadImg) {\r
+                       return;\r
+               }\r
+\r
+               if (f.width.value == "" || f.height.value == "")\r
+                       return;\r
+\r
+               tp = (parseInt(f.height.value) / parseInt(t.preloadImg.height)) * t.preloadImg.width;\r
+               f.width.value = tp.toFixed(0);\r
+       },\r
+\r
+       updateStyle : function(ty) {\r
+               var dom = tinyMCEPopup.dom, st, v, f = document.forms[0], img = dom.create('img', {style : dom.get('style').value});\r
+\r
+               if (tinyMCEPopup.editor.settings.inline_styles) {\r
+                       // Handle align\r
+                       if (ty == 'align') {\r
+                               dom.setStyle(img, 'float', '');\r
+                               dom.setStyle(img, 'vertical-align', '');\r
+\r
+                               v = getSelectValue(f, 'align');\r
+                               if (v) {\r
+                                       if (v == 'left' || v == 'right')\r
+                                               dom.setStyle(img, 'float', v);\r
+                                       else\r
+                                               img.style.verticalAlign = v;\r
+                               }\r
+                       }\r
+\r
+                       // Handle border\r
+                       if (ty == 'border') {\r
+                               dom.setStyle(img, 'border', '');\r
+\r
+                               v = f.border.value;\r
+                               if (v || v == '0') {\r
+                                       if (v == '0')\r
+                                               img.style.border = '';\r
+                                       else\r
+                                               img.style.border = v + 'px solid black';\r
+                               }\r
+                       }\r
+\r
+                       // Handle hspace\r
+                       if (ty == 'hspace') {\r
+                               dom.setStyle(img, 'marginLeft', '');\r
+                               dom.setStyle(img, 'marginRight', '');\r
+\r
+                               v = f.hspace.value;\r
+                               if (v) {\r
+                                       img.style.marginLeft = v + 'px';\r
+                                       img.style.marginRight = v + 'px';\r
+                               }\r
+                       }\r
+\r
+                       // Handle vspace\r
+                       if (ty == 'vspace') {\r
+                               dom.setStyle(img, 'marginTop', '');\r
+                               dom.setStyle(img, 'marginBottom', '');\r
+\r
+                               v = f.vspace.value;\r
+                               if (v) {\r
+                                       img.style.marginTop = v + 'px';\r
+                                       img.style.marginBottom = v + 'px';\r
+                               }\r
+                       }\r
+\r
+                       // Merge\r
+                       dom.get('style').value = dom.serializeStyle(dom.parseStyle(img.style.cssText));\r
+               }\r
+       },\r
+\r
+       changeMouseMove : function() {\r
+       },\r
+\r
+       showPreviewImage : function(u, st) {\r
+               if (!u) {\r
+                       tinyMCEPopup.dom.setHTML('prev', '');\r
+                       return;\r
+               }\r
+\r
+               if (!st && tinyMCEPopup.getParam("advimage_update_dimensions_onchange", true))\r
+                       this.resetImageData();\r
+\r
+               u = tinyMCEPopup.editor.documentBaseURI.toAbsolute(u);\r
+\r
+               if (!st)\r
+                       tinyMCEPopup.dom.setHTML('prev', '<img id="previewImg" src="' + u + '" border="0" onload="ImageDialog.updateImageData(this);" onerror="ImageDialog.resetImageData();" />');\r
+               else\r
+                       tinyMCEPopup.dom.setHTML('prev', '<img id="previewImg" src="' + u + '" border="0" onload="ImageDialog.updateImageData(this, 1);" />');\r
+       }\r
+};\r
+\r
+ImageDialog.preInit();\r
+tinyMCEPopup.onInit.add(ImageDialog.init, ImageDialog);\r
diff --git a/jscripts/tiny_mce/plugins/advimage/langs/en_dlg.js b/jscripts/tiny_mce/plugins/advimage/langs/en_dlg.js
new file mode 100644 (file)
index 0000000..f493d19
--- /dev/null
@@ -0,0 +1,43 @@
+tinyMCE.addI18n('en.advimage_dlg',{\r
+tab_general:"General",\r
+tab_appearance:"Appearance",\r
+tab_advanced:"Advanced",\r
+general:"General",\r
+title:"Title",\r
+preview:"Preview",\r
+constrain_proportions:"Constrain proportions",\r
+langdir:"Language direction",\r
+langcode:"Language code",\r
+long_desc:"Long description link",\r
+style:"Style",\r
+classes:"Classes",\r
+ltr:"Left to right",\r
+rtl:"Right to left",\r
+id:"Id",\r
+map:"Image map",\r
+swap_image:"Swap image",\r
+alt_image:"Alternative image",\r
+mouseover:"for mouse over",\r
+mouseout:"for mouse out",\r
+misc:"Miscellaneous",\r
+example_img:"Appearance preview image",\r
+missing_alt:"Are you sure you want to continue without including an Image Description? Without it the image may not be accessible to some users with disabilities, or to those using a text browser, or browsing the Web with images turned off.",\r
+dialog_title:"Insert/edit image",\r
+src:"Image URL",\r
+alt:"Image description",\r
+list:"Image list",\r
+border:"Border",\r
+dimensions:"Dimensions",\r
+vspace:"Vertical space",\r
+hspace:"Horizontal space",\r
+align:"Alignment",\r
+align_baseline:"Baseline",\r
+align_top:"Top",\r
+align_middle:"Middle",\r
+align_bottom:"Bottom",\r
+align_texttop:"Text top",\r
+align_textbottom:"Text bottom",\r
+align_left:"Left",\r
+align_right:"Right",\r
+image_list:"Image list"\r
+});
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/advlink/css/advlink.css b/jscripts/tiny_mce/plugins/advlink/css/advlink.css
new file mode 100644 (file)
index 0000000..1436431
--- /dev/null
@@ -0,0 +1,8 @@
+.mceLinkList, .mceAnchorList, #targetlist {width:280px;}\r
+.mceActionPanel {margin-top:7px;}\r
+.panel_wrapper div.current {height:320px;}\r
+#classlist, #title, #href {width:280px;}\r
+#popupurl, #popupname {width:200px;}\r
+#popupwidth, #popupheight, #popupleft, #popuptop {width:30px;vertical-align:middle;text-align:center;}\r
+#id, #style, #classes, #target, #dir, #hreflang, #lang, #charset, #type, #rel, #rev, #tabindex, #accesskey {width:200px;}\r
+#events_panel input {width:200px;}\r
diff --git a/jscripts/tiny_mce/plugins/advlink/editor_plugin.js b/jscripts/tiny_mce/plugins/advlink/editor_plugin.js
new file mode 100644 (file)
index 0000000..4899f7b
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.AdvancedLinkPlugin',{init:function(ed,url){this.editor=ed;ed.addCommand('mceAdvLink',function(){var se=ed.selection;if(se.isCollapsed()&&!ed.dom.getParent(se.getNode(),'A'))return;ed.windowManager.open({file:url+'/link.htm',width:480+parseInt(ed.getLang('advlink.delta_width',0)),height:400+parseInt(ed.getLang('advlink.delta_height',0)),inline:1},{plugin_url:url});});ed.addButton('link',{title:'advlink.link_desc',cmd:'mceAdvLink'});ed.addShortcut('ctrl+k','advlink.advlink_desc','mceAdvLink');ed.onNodeChange.add(function(ed,cm,n,co){cm.setDisabled('link',co&&n.nodeName!='A');cm.setActive('link',n.nodeName=='A'&&!n.name);});},getInfo:function(){return{longname:'Advanced link',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advlink',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('advlink',tinymce.plugins.AdvancedLinkPlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/advlink/editor_plugin_src.js b/jscripts/tiny_mce/plugins/advlink/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..fc5325a
--- /dev/null
@@ -0,0 +1,58 @@
+/**\r
+ * $Id: editor_plugin_src.js 539 2008-01-14 19:08:58Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.AdvancedLinkPlugin', {\r
+               init : function(ed, url) {\r
+                       this.editor = ed;\r
+\r
+                       // Register commands\r
+                       ed.addCommand('mceAdvLink', function() {\r
+                               var se = ed.selection;\r
+\r
+                               // No selection and not in link\r
+                               if (se.isCollapsed() && !ed.dom.getParent(se.getNode(), 'A'))\r
+                                       return;\r
+\r
+                               ed.windowManager.open({\r
+                                       file : url + '/link.htm',\r
+                                       width : 480 + parseInt(ed.getLang('advlink.delta_width', 0)),\r
+                                       height : 400 + parseInt(ed.getLang('advlink.delta_height', 0)),\r
+                                       inline : 1\r
+                               }, {\r
+                                       plugin_url : url\r
+                               });\r
+                       });\r
+\r
+                       // Register buttons\r
+                       ed.addButton('link', {\r
+                               title : 'advlink.link_desc',\r
+                               cmd : 'mceAdvLink'\r
+                       });\r
+\r
+                       ed.addShortcut('ctrl+k', 'advlink.advlink_desc', 'mceAdvLink');\r
+\r
+                       ed.onNodeChange.add(function(ed, cm, n, co) {\r
+                               cm.setDisabled('link', co && n.nodeName != 'A');\r
+                               cm.setActive('link', n.nodeName == 'A' && !n.name);\r
+                       });\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Advanced link',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advlink',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('advlink', tinymce.plugins.AdvancedLinkPlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/advlink/js/advlink.js b/jscripts/tiny_mce/plugins/advlink/js/advlink.js
new file mode 100644 (file)
index 0000000..2efc1b7
--- /dev/null
@@ -0,0 +1,528 @@
+/* Functions for the advlink plugin popup */\r
+\r
+tinyMCEPopup.requireLangPack();\r
+\r
+var templates = {\r
+       "window.open" : "window.open('${url}','${target}','${options}')"\r
+};\r
+\r
+function preinit() {\r
+       var url;\r
+\r
+       if (url = tinyMCEPopup.getParam("external_link_list_url"))\r
+               document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>');\r
+}\r
+\r
+function changeClass() {\r
+       var f = document.forms[0];\r
+\r
+       f.classes.value = getSelectValue(f, 'classlist');\r
+}\r
+\r
+function init() {\r
+       tinyMCEPopup.resizeToInnerSize();\r
+\r
+       var formObj = document.forms[0];\r
+       var inst = tinyMCEPopup.editor;\r
+       var elm = inst.selection.getNode();\r
+       var action = "insert";\r
+       var html;\r
+\r
+       document.getElementById('hrefbrowsercontainer').innerHTML = getBrowserHTML('hrefbrowser','href','file','advlink');\r
+       document.getElementById('popupurlbrowsercontainer').innerHTML = getBrowserHTML('popupurlbrowser','popupurl','file','advlink');\r
+       document.getElementById('linklisthrefcontainer').innerHTML = getLinkListHTML('linklisthref','href');\r
+       document.getElementById('anchorlistcontainer').innerHTML = getAnchorListHTML('anchorlist','href');\r
+       document.getElementById('targetlistcontainer').innerHTML = getTargetListHTML('targetlist','target');\r
+\r
+       // Link list\r
+       html = getLinkListHTML('linklisthref','href');\r
+       if (html == "")\r
+               document.getElementById("linklisthrefrow").style.display = 'none';\r
+       else\r
+               document.getElementById("linklisthrefcontainer").innerHTML = html;\r
+\r
+       // Resize some elements\r
+       if (isVisible('hrefbrowser'))\r
+               document.getElementById('href').style.width = '260px';\r
+\r
+       if (isVisible('popupurlbrowser'))\r
+               document.getElementById('popupurl').style.width = '180px';\r
+\r
+       elm = inst.dom.getParent(elm, "A");\r
+       if (elm != null && elm.nodeName == "A")\r
+               action = "update";\r
+\r
+       formObj.insert.value = tinyMCEPopup.getLang(action, 'Insert', true); \r
+\r
+       setPopupControlsDisabled(true);\r
+\r
+       if (action == "update") {\r
+               var href = inst.dom.getAttrib(elm, 'href');\r
+               var onclick = inst.dom.getAttrib(elm, 'onclick');\r
+\r
+               // Setup form data\r
+               setFormValue('href', href);\r
+               setFormValue('title', inst.dom.getAttrib(elm, 'title'));\r
+               setFormValue('id', inst.dom.getAttrib(elm, 'id'));\r
+               setFormValue('style', inst.dom.getAttrib(elm, "style"));\r
+               setFormValue('rel', inst.dom.getAttrib(elm, 'rel'));\r
+               setFormValue('rev', inst.dom.getAttrib(elm, 'rev'));\r
+               setFormValue('charset', inst.dom.getAttrib(elm, 'charset'));\r
+               setFormValue('hreflang', inst.dom.getAttrib(elm, 'hreflang'));\r
+               setFormValue('dir', inst.dom.getAttrib(elm, 'dir'));\r
+               setFormValue('lang', inst.dom.getAttrib(elm, 'lang'));\r
+               setFormValue('tabindex', inst.dom.getAttrib(elm, 'tabindex', typeof(elm.tabindex) != "undefined" ? elm.tabindex : ""));\r
+               setFormValue('accesskey', inst.dom.getAttrib(elm, 'accesskey', typeof(elm.accesskey) != "undefined" ? elm.accesskey : ""));\r
+               setFormValue('type', inst.dom.getAttrib(elm, 'type'));\r
+               setFormValue('onfocus', inst.dom.getAttrib(elm, 'onfocus'));\r
+               setFormValue('onblur', inst.dom.getAttrib(elm, 'onblur'));\r
+               setFormValue('onclick', onclick);\r
+               setFormValue('ondblclick', inst.dom.getAttrib(elm, 'ondblclick'));\r
+               setFormValue('onmousedown', inst.dom.getAttrib(elm, 'onmousedown'));\r
+               setFormValue('onmouseup', inst.dom.getAttrib(elm, 'onmouseup'));\r
+               setFormValue('onmouseover', inst.dom.getAttrib(elm, 'onmouseover'));\r
+               setFormValue('onmousemove', inst.dom.getAttrib(elm, 'onmousemove'));\r
+               setFormValue('onmouseout', inst.dom.getAttrib(elm, 'onmouseout'));\r
+               setFormValue('onkeypress', inst.dom.getAttrib(elm, 'onkeypress'));\r
+               setFormValue('onkeydown', inst.dom.getAttrib(elm, 'onkeydown'));\r
+               setFormValue('onkeyup', inst.dom.getAttrib(elm, 'onkeyup'));\r
+               setFormValue('target', inst.dom.getAttrib(elm, 'target'));\r
+               setFormValue('classes', inst.dom.getAttrib(elm, 'class'));\r
+\r
+               // Parse onclick data\r
+               if (onclick != null && onclick.indexOf('window.open') != -1)\r
+                       parseWindowOpen(onclick);\r
+               else\r
+                       parseFunction(onclick);\r
+\r
+               // Select by the values\r
+               selectByValue(formObj, 'dir', inst.dom.getAttrib(elm, 'dir'));\r
+               selectByValue(formObj, 'rel', inst.dom.getAttrib(elm, 'rel'));\r
+               selectByValue(formObj, 'rev', inst.dom.getAttrib(elm, 'rev'));\r
+               selectByValue(formObj, 'linklisthref', href);\r
+\r
+               if (href.charAt(0) == '#')\r
+                       selectByValue(formObj, 'anchorlist', href);\r
+\r
+               addClassesToList('classlist', 'advlink_styles');\r
+\r
+               selectByValue(formObj, 'classlist', inst.dom.getAttrib(elm, 'class'), true);\r
+               selectByValue(formObj, 'targetlist', inst.dom.getAttrib(elm, 'target'), true);\r
+       } else\r
+               addClassesToList('classlist', 'advlink_styles');\r
+}\r
+\r
+function checkPrefix(n) {\r
+       if (n.value && Validator.isEmail(n) && !/^\s*mailto:/i.test(n.value) && confirm(tinyMCEPopup.getLang('advlink_dlg.is_email')))\r
+               n.value = 'mailto:' + n.value;\r
+\r
+       if (/^\s*www./i.test(n.value) && confirm(tinyMCEPopup.getLang('advlink_dlg.is_external')))\r
+               n.value = 'http://' + n.value;\r
+}\r
+\r
+function setFormValue(name, value) {\r
+       document.forms[0].elements[name].value = value;\r
+}\r
+\r
+function parseWindowOpen(onclick) {\r
+       var formObj = document.forms[0];\r
+\r
+       // Preprocess center code\r
+       if (onclick.indexOf('return false;') != -1) {\r
+               formObj.popupreturn.checked = true;\r
+               onclick = onclick.replace('return false;', '');\r
+       } else\r
+               formObj.popupreturn.checked = false;\r
+\r
+       var onClickData = parseLink(onclick);\r
+\r
+       if (onClickData != null) {\r
+               formObj.ispopup.checked = true;\r
+               setPopupControlsDisabled(false);\r
+\r
+               var onClickWindowOptions = parseOptions(onClickData['options']);\r
+               var url = onClickData['url'];\r
+\r
+               formObj.popupname.value = onClickData['target'];\r
+               formObj.popupurl.value = url;\r
+               formObj.popupwidth.value = getOption(onClickWindowOptions, 'width');\r
+               formObj.popupheight.value = getOption(onClickWindowOptions, 'height');\r
+\r
+               formObj.popupleft.value = getOption(onClickWindowOptions, 'left');\r
+               formObj.popuptop.value = getOption(onClickWindowOptions, 'top');\r
+\r
+               if (formObj.popupleft.value.indexOf('screen') != -1)\r
+                       formObj.popupleft.value = "c";\r
+\r
+               if (formObj.popuptop.value.indexOf('screen') != -1)\r
+                       formObj.popuptop.value = "c";\r
+\r
+               formObj.popuplocation.checked = getOption(onClickWindowOptions, 'location') == "yes";\r
+               formObj.popupscrollbars.checked = getOption(onClickWindowOptions, 'scrollbars') == "yes";\r
+               formObj.popupmenubar.checked = getOption(onClickWindowOptions, 'menubar') == "yes";\r
+               formObj.popupresizable.checked = getOption(onClickWindowOptions, 'resizable') == "yes";\r
+               formObj.popuptoolbar.checked = getOption(onClickWindowOptions, 'toolbar') == "yes";\r
+               formObj.popupstatus.checked = getOption(onClickWindowOptions, 'status') == "yes";\r
+               formObj.popupdependent.checked = getOption(onClickWindowOptions, 'dependent') == "yes";\r
+\r
+               buildOnClick();\r
+       }\r
+}\r
+\r
+function parseFunction(onclick) {\r
+       var formObj = document.forms[0];\r
+       var onClickData = parseLink(onclick);\r
+\r
+       // TODO: Add stuff here\r
+}\r
+\r
+function getOption(opts, name) {\r
+       return typeof(opts[name]) == "undefined" ? "" : opts[name];\r
+}\r
+\r
+function setPopupControlsDisabled(state) {\r
+       var formObj = document.forms[0];\r
+\r
+       formObj.popupname.disabled = state;\r
+       formObj.popupurl.disabled = state;\r
+       formObj.popupwidth.disabled = state;\r
+       formObj.popupheight.disabled = state;\r
+       formObj.popupleft.disabled = state;\r
+       formObj.popuptop.disabled = state;\r
+       formObj.popuplocation.disabled = state;\r
+       formObj.popupscrollbars.disabled = state;\r
+       formObj.popupmenubar.disabled = state;\r
+       formObj.popupresizable.disabled = state;\r
+       formObj.popuptoolbar.disabled = state;\r
+       formObj.popupstatus.disabled = state;\r
+       formObj.popupreturn.disabled = state;\r
+       formObj.popupdependent.disabled = state;\r
+\r
+       setBrowserDisabled('popupurlbrowser', state);\r
+}\r
+\r
+function parseLink(link) {\r
+       link = link.replace(new RegExp('&#39;', 'g'), "'");\r
+\r
+       var fnName = link.replace(new RegExp("\\s*([A-Za-z0-9\.]*)\\s*\\(.*", "gi"), "$1");\r
+\r
+       // Is function name a template function\r
+       var template = templates[fnName];\r
+       if (template) {\r
+               // Build regexp\r
+               var variableNames = template.match(new RegExp("'?\\$\\{[A-Za-z0-9\.]*\\}'?", "gi"));\r
+               var regExp = "\\s*[A-Za-z0-9\.]*\\s*\\(";\r
+               var replaceStr = "";\r
+               for (var i=0; i<variableNames.length; i++) {\r
+                       // Is string value\r
+                       if (variableNames[i].indexOf("'${") != -1)\r
+                               regExp += "'(.*)'";\r
+                       else // Number value\r
+                               regExp += "([0-9]*)";\r
+\r
+                       replaceStr += "$" + (i+1);\r
+\r
+                       // Cleanup variable name\r
+                       variableNames[i] = variableNames[i].replace(new RegExp("[^A-Za-z0-9]", "gi"), "");\r
+\r
+                       if (i != variableNames.length-1) {\r
+                               regExp += "\\s*,\\s*";\r
+                               replaceStr += "<delim>";\r
+                       } else\r
+                               regExp += ".*";\r
+               }\r
+\r
+               regExp += "\\);?";\r
+\r
+               // Build variable array\r
+               var variables = [];\r
+               variables["_function"] = fnName;\r
+               var variableValues = link.replace(new RegExp(regExp, "gi"), replaceStr).split('<delim>');\r
+               for (var i=0; i<variableNames.length; i++)\r
+                       variables[variableNames[i]] = variableValues[i];\r
+\r
+               return variables;\r
+       }\r
+\r
+       return null;\r
+}\r
+\r
+function parseOptions(opts) {\r
+       if (opts == null || opts == "")\r
+               return [];\r
+\r
+       // Cleanup the options\r
+       opts = opts.toLowerCase();\r
+       opts = opts.replace(/;/g, ",");\r
+       opts = opts.replace(/[^0-9a-z=,]/g, "");\r
+\r
+       var optionChunks = opts.split(',');\r
+       var options = [];\r
+\r
+       for (var i=0; i<optionChunks.length; i++) {\r
+               var parts = optionChunks[i].split('=');\r
+\r
+               if (parts.length == 2)\r
+                       options[parts[0]] = parts[1];\r
+       }\r
+\r
+       return options;\r
+}\r
+\r
+function buildOnClick() {\r
+       var formObj = document.forms[0];\r
+\r
+       if (!formObj.ispopup.checked) {\r
+               formObj.onclick.value = "";\r
+               return;\r
+       }\r
+\r
+       var onclick = "window.open('";\r
+       var url = formObj.popupurl.value;\r
+\r
+       onclick += url + "','";\r
+       onclick += formObj.popupname.value + "','";\r
+\r
+       if (formObj.popuplocation.checked)\r
+               onclick += "location=yes,";\r
+\r
+       if (formObj.popupscrollbars.checked)\r
+               onclick += "scrollbars=yes,";\r
+\r
+       if (formObj.popupmenubar.checked)\r
+               onclick += "menubar=yes,";\r
+\r
+       if (formObj.popupresizable.checked)\r
+               onclick += "resizable=yes,";\r
+\r
+       if (formObj.popuptoolbar.checked)\r
+               onclick += "toolbar=yes,";\r
+\r
+       if (formObj.popupstatus.checked)\r
+               onclick += "status=yes,";\r
+\r
+       if (formObj.popupdependent.checked)\r
+               onclick += "dependent=yes,";\r
+\r
+       if (formObj.popupwidth.value != "")\r
+               onclick += "width=" + formObj.popupwidth.value + ",";\r
+\r
+       if (formObj.popupheight.value != "")\r
+               onclick += "height=" + formObj.popupheight.value + ",";\r
+\r
+       if (formObj.popupleft.value != "") {\r
+               if (formObj.popupleft.value != "c")\r
+                       onclick += "left=" + formObj.popupleft.value + ",";\r
+               else\r
+                       onclick += "left='+(screen.availWidth/2-" + (formObj.popupwidth.value/2) + ")+',";\r
+       }\r
+\r
+       if (formObj.popuptop.value != "") {\r
+               if (formObj.popuptop.value != "c")\r
+                       onclick += "top=" + formObj.popuptop.value + ",";\r
+               else\r
+                       onclick += "top='+(screen.availHeight/2-" + (formObj.popupheight.value/2) + ")+',";\r
+       }\r
+\r
+       if (onclick.charAt(onclick.length-1) == ',')\r
+               onclick = onclick.substring(0, onclick.length-1);\r
+\r
+       onclick += "');";\r
+\r
+       if (formObj.popupreturn.checked)\r
+               onclick += "return false;";\r
+\r
+       // tinyMCE.debug(onclick);\r
+\r
+       formObj.onclick.value = onclick;\r
+\r
+       if (formObj.href.value == "")\r
+               formObj.href.value = url;\r
+}\r
+\r
+function setAttrib(elm, attrib, value) {\r
+       var formObj = document.forms[0];\r
+       var valueElm = formObj.elements[attrib.toLowerCase()];\r
+       var dom = tinyMCEPopup.editor.dom;\r
+\r
+       if (typeof(value) == "undefined" || value == null) {\r
+               value = "";\r
+\r
+               if (valueElm)\r
+                       value = valueElm.value;\r
+       }\r
+\r
+       // Clean up the style\r
+       if (attrib == 'style')\r
+               value = dom.serializeStyle(dom.parseStyle(value));\r
+\r
+       dom.setAttrib(elm, attrib, value);\r
+}\r
+\r
+function getAnchorListHTML(id, target) {\r
+       var inst = tinyMCEPopup.editor;\r
+       var nodes = inst.dom.select('a.mceItemAnchor,img.mceItemAnchor'), name, i;\r
+       var html = "";\r
+\r
+       html += '<select id="' + id + '" name="' + id + '" class="mceAnchorList" o2nfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.' + target + '.value=';\r
+       html += 'this.options[this.selectedIndex].value;">';\r
+       html += '<option value="">---</option>';\r
+\r
+       for (i=0; i<nodes.length; i++) {\r
+               if ((name = inst.dom.getAttrib(nodes[i], "name")) != "")\r
+                       html += '<option value="#' + name + '">' + name + '</option>';\r
+       }\r
+\r
+       html += '</select>';\r
+\r
+       return html;\r
+}\r
+\r
+function insertAction() {\r
+       var inst = tinyMCEPopup.editor;\r
+       var elm, elementArray, i;\r
+\r
+       elm = inst.selection.getNode();\r
+       checkPrefix(document.forms[0].href);\r
+\r
+       elm = inst.dom.getParent(elm, "A");\r
+\r
+       // Remove element if there is no href\r
+       if (!document.forms[0].href.value) {\r
+               tinyMCEPopup.execCommand("mceBeginUndoLevel");\r
+               i = inst.selection.getBookmark();\r
+               inst.dom.remove(elm, 1);\r
+               inst.selection.moveToBookmark(i);\r
+               tinyMCEPopup.execCommand("mceEndUndoLevel");\r
+               tinyMCEPopup.close();\r
+               return;\r
+       }\r
+\r
+       tinyMCEPopup.execCommand("mceBeginUndoLevel");\r
+\r
+       // Create new anchor elements\r
+       if (elm == null) {\r
+               tinyMCEPopup.execCommand("CreateLink", false, "#mce_temp_url#", {skip_undo : 1});\r
+\r
+               elementArray = tinymce.grep(inst.dom.select("a"), function(n) {return inst.dom.getAttrib(n, 'href') == '#mce_temp_url#';});\r
+               for (i=0; i<elementArray.length; i++)\r
+                       setAllAttribs(elm = elementArray[i]);\r
+       } else\r
+               setAllAttribs(elm);\r
+\r
+       // Don't move caret if selection was image\r
+       if (elm.childNodes.length != 1 || elm.firstChild.nodeName != 'IMG') {\r
+               inst.focus();\r
+               inst.selection.select(elm);\r
+               inst.selection.collapse(0);\r
+               tinyMCEPopup.storeSelection();\r
+       }\r
+\r
+       tinyMCEPopup.execCommand("mceEndUndoLevel");\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function setAllAttribs(elm) {\r
+       var formObj = document.forms[0];\r
+       var href = formObj.href.value;\r
+       var target = getSelectValue(formObj, 'targetlist');\r
+\r
+       setAttrib(elm, 'href', href);\r
+       setAttrib(elm, 'mce_href', href);\r
+       setAttrib(elm, 'title');\r
+       setAttrib(elm, 'target', target == '_self' ? '' : target);\r
+       setAttrib(elm, 'id');\r
+       setAttrib(elm, 'style');\r
+       setAttrib(elm, 'class', getSelectValue(formObj, 'classlist'));\r
+       setAttrib(elm, 'rel');\r
+       setAttrib(elm, 'rev');\r
+       setAttrib(elm, 'charset');\r
+       setAttrib(elm, 'hreflang');\r
+       setAttrib(elm, 'dir');\r
+       setAttrib(elm, 'lang');\r
+       setAttrib(elm, 'tabindex');\r
+       setAttrib(elm, 'accesskey');\r
+       setAttrib(elm, 'type');\r
+       setAttrib(elm, 'onfocus');\r
+       setAttrib(elm, 'onblur');\r
+       setAttrib(elm, 'onclick');\r
+       setAttrib(elm, 'ondblclick');\r
+       setAttrib(elm, 'onmousedown');\r
+       setAttrib(elm, 'onmouseup');\r
+       setAttrib(elm, 'onmouseover');\r
+       setAttrib(elm, 'onmousemove');\r
+       setAttrib(elm, 'onmouseout');\r
+       setAttrib(elm, 'onkeypress');\r
+       setAttrib(elm, 'onkeydown');\r
+       setAttrib(elm, 'onkeyup');\r
+\r
+       // Refresh in old MSIE\r
+       if (tinyMCE.isMSIE5)\r
+               elm.outerHTML = elm.outerHTML;\r
+}\r
+\r
+function getSelectValue(form_obj, field_name) {\r
+       var elm = form_obj.elements[field_name];\r
+\r
+       if (elm == null || elm.options == null)\r
+               return "";\r
+\r
+       return elm.options[elm.selectedIndex].value;\r
+}\r
+\r
+function getLinkListHTML(elm_id, target_form_element, onchange_func) {\r
+       if (typeof(tinyMCELinkList) == "undefined" || tinyMCELinkList.length == 0)\r
+               return "";\r
+\r
+       var html = "";\r
+\r
+       html += '<select id="' + elm_id + '" name="' + elm_id + '"';\r
+       html += ' class="mceLinkList" onfoc2us="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.' + target_form_element + '.value=';\r
+       html += 'this.options[this.selectedIndex].value;';\r
+\r
+       if (typeof(onchange_func) != "undefined")\r
+               html += onchange_func + '(\'' + target_form_element + '\',this.options[this.selectedIndex].text,this.options[this.selectedIndex].value);';\r
+\r
+       html += '"><option value="">---</option>';\r
+\r
+       for (var i=0; i<tinyMCELinkList.length; i++)\r
+               html += '<option value="' + tinyMCELinkList[i][1] + '">' + tinyMCELinkList[i][0] + '</option>';\r
+\r
+       html += '</select>';\r
+\r
+       return html;\r
+\r
+       // tinyMCE.debug('-- image list start --', html, '-- image list end --');\r
+}\r
+\r
+function getTargetListHTML(elm_id, target_form_element) {\r
+       var targets = tinyMCEPopup.getParam('theme_advanced_link_targets', '').split(';');\r
+       var html = '';\r
+\r
+       html += '<select id="' + elm_id + '" name="' + elm_id + '" onf2ocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.' + target_form_element + '.value=';\r
+       html += 'this.options[this.selectedIndex].value;">';\r
+       html += '<option value="_self">' + tinyMCEPopup.getLang('advlink_dlg.target_same') + '</option>';\r
+       html += '<option value="_blank">' + tinyMCEPopup.getLang('advlink_dlg.target_blank') + ' (_blank)</option>';\r
+       html += '<option value="_parent">' + tinyMCEPopup.getLang('advlink_dlg.target_parent') + ' (_parent)</option>';\r
+       html += '<option value="_top">' + tinyMCEPopup.getLang('advlink_dlg.target_top') + ' (_top)</option>';\r
+\r
+       for (var i=0; i<targets.length; i++) {\r
+               var key, value;\r
+\r
+               if (targets[i] == "")\r
+                       continue;\r
+\r
+               key = targets[i].split('=')[0];\r
+               value = targets[i].split('=')[1];\r
+\r
+               html += '<option value="' + key + '">' + value + ' (' + key + ')</option>';\r
+       }\r
+\r
+       html += '</select>';\r
+\r
+       return html;\r
+}\r
+\r
+// While loading\r
+preinit();\r
+tinyMCEPopup.onInit.add(init);\r
diff --git a/jscripts/tiny_mce/plugins/advlink/langs/en_dlg.js b/jscripts/tiny_mce/plugins/advlink/langs/en_dlg.js
new file mode 100644 (file)
index 0000000..c71ffbd
--- /dev/null
@@ -0,0 +1,52 @@
+tinyMCE.addI18n('en.advlink_dlg',{\r
+title:"Insert/edit link",\r
+url:"Link URL",\r
+target:"Target",\r
+titlefield:"Title",\r
+is_email:"The URL you entered seems to be an email address, do you want to add the required mailto: prefix?",\r
+is_external:"The URL you entered seems to external link, do you want to add the required http:// prefix?",\r
+list:"Link list",\r
+general_tab:"General",\r
+popup_tab:"Popup",\r
+events_tab:"Events",\r
+advanced_tab:"Advanced",\r
+general_props:"General properties",\r
+popup_props:"Popup properties",\r
+event_props:"Events",\r
+advanced_props:"Advanced properties",\r
+popup_opts:"Options",\r
+anchor_names:"Anchors",\r
+target_same:"Open in this window / frame",\r
+target_parent:"Open in parent window / frame",\r
+target_top:"Open in top frame (replaces all frames)",\r
+target_blank:"Open in new window",\r
+popup:"Javascript popup",\r
+popup_url:"Popup URL",\r
+popup_name:"Window name",\r
+popup_return:"Insert 'return false'",\r
+popup_scrollbars:"Show scrollbars",\r
+popup_statusbar:"Show status bar",\r
+popup_toolbar:"Show toolbars",\r
+popup_menubar:"Show menu bar",\r
+popup_location:"Show location bar",\r
+popup_resizable:"Make window resizable",\r
+popup_dependent:"Dependent (Mozilla/Firefox only)",\r
+popup_size:"Size",\r
+popup_position:"Position (X/Y)",\r
+id:"Id",\r
+style:"Style",\r
+classes:"Classes",\r
+target_name:"Target name",\r
+langdir:"Language direction",\r
+target_langcode:"Target language",\r
+langcode:"Language code",\r
+encoding:"Target character encoding",\r
+mime:"Target MIME type",\r
+rel:"Relationship page to target",\r
+rev:"Relationship target to page",\r
+tabindex:"Tabindex",\r
+accesskey:"Accesskey",\r
+ltr:"Left to right",\r
+rtl:"Right to left",\r
+link_list:"Link list"\r
+});
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/advlink/link.htm b/jscripts/tiny_mce/plugins/advlink/link.htm
new file mode 100644 (file)
index 0000000..0e60d58
--- /dev/null
@@ -0,0 +1,339 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#advlink_dlg.title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/validate.js?v=307"></script>\r
+       <script type="text/javascript" src="js/advlink.js?v=307"></script>\r
+       <link href="css/advlink.css?v=307" rel="stylesheet" type="text/css" />\r
+       <base target="_self" />\r
+</head>\r
+<body id="advlink" style="display: none">\r
+    <form onsubmit="insertAction();return false;" action="#">\r
+               <div class="tabs">\r
+                       <ul>\r
+                               <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advlink_dlg.general_tab}</a></span></li>\r
+                               <li id="popup_tab"><span><a href="javascript:mcTabs.displayTab('popup_tab','popup_panel');" onmousedown="return false;">{#advlink_dlg.popup_tab}</a></span></li>\r
+                               <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#advlink_dlg.events_tab}</a></span></li>\r
+                               <li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#advlink_dlg.advanced_tab}</a></span></li>\r
+                       </ul>\r
+               </div>\r
+\r
+               <div class="panel_wrapper">\r
+                       <div id="general_panel" class="panel current">\r
+                               <fieldset>\r
+                                       <legend>{#advlink_dlg.general_props}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                 <td nowrap="nowrap"><label id="hreflabel" for="href">{#advlink_dlg.url}</label></td>\r
+                                                 <td><table border="0" cellspacing="0" cellpadding="0">\r
+                                                               <tr>\r
+                                                                 <td><input id="href" name="href" type="text" class="mceFocus" value="" onchange="selectByValue(this.form,'linklisthref',this.value);" /></td>\r
+                                                                 <td id="hrefbrowsercontainer">&nbsp;</td>\r
+                                                               </tr>\r
+                                                         </table></td>\r
+                                               </tr>\r
+                                               <tr id="linklisthrefrow">\r
+                                                       <td class="column1"><label for="linklisthref">{#advlink_dlg.list}</label></td>\r
+                                                       <td colspan="2" id="linklisthrefcontainer">&nbsp;</td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="anchorlist">{#advlink_dlg.anchor_names}</label></td>\r
+                                                       <td colspan="2" id="anchorlistcontainer">&nbsp;</td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td><label id="targetlistlabel" for="targetlist">{#advlink_dlg.target}</label></td>\r
+                                                       <td id="targetlistcontainer">&nbsp;</td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td nowrap="nowrap"><label id="titlelabel" for="title">{#advlink_dlg.titlefield}</label></td>\r
+                                                       <td><input id="title" name="title" type="text" value="" /></td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td><label id="classlabel" for="classlist">{#class_name}</label></td>\r
+                                                       <td>\r
+                                                                <select id="classlist" name="classlist" onchange="changeClass();">\r
+                                                                       <option value="" selected>{#not_set}</option>\r
+                                                                </select>\r
+                                                       </td>\r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+                       </div>\r
+\r
+                       <div id="popup_panel" class="panel">\r
+                               <fieldset>\r
+                                       <legend>{#advlink_dlg.popup_props}</legend>\r
+\r
+                                       <input type="checkbox" id="ispopup" name="ispopup" class="radio" onclick="setPopupControlsDisabled(!this.checked);buildOnClick();" />\r
+                                       <label id="ispopuplabel" for="ispopup">{#advlink_dlg.popup}</label>\r
+\r
+                                       <table border="0" cellpadding="0" cellspacing="4">\r
+                                               <tr>\r
+                                                       <td nowrap="nowrap"><label for="popupurl">{#advlink_dlg.popup_url}</label>&nbsp;</td>\r
+                                                       <td>\r
+                                                               <table border="0" cellspacing="0" cellpadding="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="text" name="popupurl" id="popupurl" value="" onchange="buildOnClick();" /></td>\r
+                                                                               <td id="popupurlbrowsercontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td nowrap="nowrap"><label for="popupname">{#advlink_dlg.popup_name}</label>&nbsp;</td>\r
+                                                       <td><input type="text" name="popupname" id="popupname" value="" onchange="buildOnClick();" /></td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td nowrap="nowrap"><label>{#advlink_dlg.popup_size}</label>&nbsp;</td>\r
+                                                       <td nowrap="nowrap">\r
+                                                               <input type="text" id="popupwidth" name="popupwidth" value="" onchange="buildOnClick();" /> x\r
+                                                               <input type="text" id="popupheight" name="popupheight" value="" onchange="buildOnClick();" /> px\r
+                                                       </td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td nowrap="nowrap" id="labelleft"><label>{#advlink_dlg.popup_position}</label>&nbsp;</td>\r
+                                                       <td nowrap="nowrap">\r
+                                                               <input type="text" id="popupleft" name="popupleft" value="" onchange="buildOnClick();" /> /                                \r
+                                                               <input type="text" id="popuptop" name="popuptop" value="" onchange="buildOnClick();" /> (c /c = center)\r
+                                                       </td>\r
+                                               </tr>\r
+                                       </table>\r
+\r
+                                       <fieldset>\r
+                                               <legend>{#advlink_dlg.popup_opts}</legend>\r
+\r
+                                               <table border="0" cellpadding="0" cellspacing="4">\r
+                                                       <tr>\r
+                                                               <td><input type="checkbox" id="popuplocation" name="popuplocation" class="checkbox" onchange="buildOnClick();" /></td>\r
+                                                               <td nowrap="nowrap"><label id="popuplocationlabel" for="popuplocation">{#advlink_dlg.popup_location}</label></td>\r
+                                                               <td><input type="checkbox" id="popupscrollbars" name="popupscrollbars" class="checkbox" onchange="buildOnClick();" /></td>\r
+                                                               <td nowrap="nowrap"><label id="popupscrollbarslabel" for="popupscrollbars">{#advlink_dlg.popup_scrollbars}</label></td>\r
+                                                       </tr>\r
+                                                       <tr>\r
+                                                               <td><input type="checkbox" id="popupmenubar" name="popupmenubar" class="checkbox" onchange="buildOnClick();" /></td>\r
+                                                               <td nowrap="nowrap"><label id="popupmenubarlabel" for="popupmenubar">{#advlink_dlg.popup_menubar}</label></td>\r
+                                                               <td><input type="checkbox" id="popupresizable" name="popupresizable" class="checkbox" onchange="buildOnClick();" /></td>\r
+                                                               <td nowrap="nowrap"><label id="popupresizablelabel" for="popupresizable">{#advlink_dlg.popup_resizable}</label></td>\r
+                                                       </tr>\r
+                                                       <tr>\r
+                                                               <td><input type="checkbox" id="popuptoolbar" name="popuptoolbar" class="checkbox" onchange="buildOnClick();" /></td>\r
+                                                               <td nowrap="nowrap"><label id="popuptoolbarlabel" for="popuptoolbar">{#advlink_dlg.popup_toolbar}</label></td>\r
+                                                               <td><input type="checkbox" id="popupdependent" name="popupdependent" class="checkbox" onchange="buildOnClick();" /></td>\r
+                                                               <td nowrap="nowrap"><label id="popupdependentlabel" for="popupdependent">{#advlink_dlg.popup_dependent}</label></td>\r
+                                                       </tr>\r
+                                                       <tr>\r
+                                                               <td><input type="checkbox" id="popupstatus" name="popupstatus" class="checkbox" onchange="buildOnClick();" /></td>\r
+                                                               <td nowrap="nowrap"><label id="popupstatuslabel" for="popupstatus">{#advlink_dlg.popup_statusbar}</label></td>\r
+                                                               <td><input type="checkbox" id="popupreturn" name="popupreturn" class="checkbox" onchange="buildOnClick();" checked="checked" /></td>\r
+                                                               <td nowrap="nowrap"><label id="popupreturnlabel" for="popupreturn">{#advlink_dlg.popup_return}</label></td>\r
+                                                       </tr>\r
+                                               </table>\r
+                                       </fieldset>\r
+                               </fieldset>\r
+                       </div>\r
+\r
+                       <div id="advanced_panel" class="panel">\r
+                       <fieldset>\r
+                                       <legend>{#advlink_dlg.advanced_props}</legend>\r
+\r
+                                       <table border="0" cellpadding="0" cellspacing="4">\r
+                                               <tr>\r
+                                                       <td class="column1"><label id="idlabel" for="id">{#advlink_dlg.id}</label></td> \r
+                                                       <td><input id="id" name="id" type="text" value="" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label id="stylelabel" for="style">{#advlink_dlg.style}</label></td>\r
+                                                       <td><input type="text" id="style" name="style" value="" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label id="classeslabel" for="classes">{#advlink_dlg.classes}</label></td>\r
+                                                       <td><input type="text" id="classes" name="classes" value="" onchange="selectByValue(this.form,'classlist',this.value,true);" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label id="targetlabel" for="target">{#advlink_dlg.target_name}</label></td>\r
+                                                       <td><input type="text" id="target" name="target" value="" onchange="selectByValue(this.form,'targetlist',this.value,true);" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label id="dirlabel" for="dir">{#advlink_dlg.langdir}</label></td> \r
+                                                       <td>\r
+                                                               <select id="dir" name="dir"> \r
+                                                                               <option value="">{#not_set}</option> \r
+                                                                               <option value="ltr">{#advlink_dlg.ltr}</option> \r
+                                                                               <option value="rtl">{#advlink_dlg.rtl}</option> \r
+                                                               </select>\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label id="hreflanglabel" for="hreflang">{#advlink_dlg.target_langcode}</label></td>\r
+                                                       <td><input type="text" id="hreflang" name="hreflang" value="" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label id="langlabel" for="lang">{#advlink_dlg.langcode}</label></td> \r
+                                                       <td>\r
+                                                               <input id="lang" name="lang" type="text" value="" />\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label id="charsetlabel" for="charset">{#advlink_dlg.encoding}</label></td>\r
+                                                       <td><input type="text" id="charset" name="charset" value="" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label id="typelabel" for="type">{#advlink_dlg.mime}</label></td>\r
+                                                       <td><input type="text" id="type" name="type" value="" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label id="rellabel" for="rel">{#advlink_dlg.rel}</label></td>\r
+                                                       <td><select id="rel" name="rel"> \r
+                                                                       <option value="">{#not_set}</option> \r
+                                                                       <option value="lightbox">Lightbox</option> \r
+                                                                       <option value="alternate">Alternate</option> \r
+                                                                       <option value="designates">Designates</option> \r
+                                                                       <option value="stylesheet">Stylesheet</option> \r
+                                                                       <option value="start">Start</option> \r
+                                                                       <option value="next">Next</option> \r
+                                                                       <option value="prev">Prev</option> \r
+                                                                       <option value="contents">Contents</option> \r
+                                                                       <option value="index">Index</option> \r
+                                                                       <option value="glossary">Glossary</option> \r
+                                                                       <option value="copyright">Copyright</option> \r
+                                                                       <option value="chapter">Chapter</option> \r
+                                                                       <option value="subsection">Subsection</option> \r
+                                                                       <option value="appendix">Appendix</option> \r
+                                                                       <option value="help">Help</option> \r
+                                                                       <option value="bookmark">Bookmark</option>\r
+                                                                       <option value="nofollow">No Follow</option>\r
+                                                                       <option value="tag">Tag</option>\r
+                                                               </select> \r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label id="revlabel" for="rev">{#advlink_dlg.rev}</label></td>\r
+                                                       <td><select id="rev" name="rev"> \r
+                                                                       <option value="">{#not_set}</option> \r
+                                                                       <option value="alternate">Alternate</option> \r
+                                                                       <option value="designates">Designates</option> \r
+                                                                       <option value="stylesheet">Stylesheet</option> \r
+                                                                       <option value="start">Start</option> \r
+                                                                       <option value="next">Next</option> \r
+                                                                       <option value="prev">Prev</option> \r
+                                                                       <option value="contents">Contents</option> \r
+                                                                       <option value="index">Index</option> \r
+                                                                       <option value="glossary">Glossary</option> \r
+                                                                       <option value="copyright">Copyright</option> \r
+                                                                       <option value="chapter">Chapter</option> \r
+                                                                       <option value="subsection">Subsection</option> \r
+                                                                       <option value="appendix">Appendix</option> \r
+                                                                       <option value="help">Help</option> \r
+                                                                       <option value="bookmark">Bookmark</option> \r
+                                                               </select> \r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label id="tabindexlabel" for="tabindex">{#advlink_dlg.tabindex}</label></td>\r
+                                                       <td><input type="text" id="tabindex" name="tabindex" value="" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label id="accesskeylabel" for="accesskey">{#advlink_dlg.accesskey}</label></td>\r
+                                                       <td><input type="text" id="accesskey" name="accesskey" value="" /></td>\r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+                       </div>\r
+\r
+                       <div id="events_panel" class="panel">\r
+                       <fieldset>\r
+                                       <legend>{#advlink_dlg.event_props}</legend>\r
+\r
+                                       <table border="0" cellpadding="0" cellspacing="4">\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="onfocus">onfocus</label></td> \r
+                                                       <td><input id="onfocus" name="onfocus" type="text" value="" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="onblur">onblur</label></td> \r
+                                                       <td><input id="onblur" name="onblur" type="text" value="" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="onclick">onclick</label></td> \r
+                                                       <td><input id="onclick" name="onclick" type="text" value="" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="ondblclick">ondblclick</label></td> \r
+                                                       <td><input id="ondblclick" name="ondblclick" type="text" value="" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="onmousedown">onmousedown</label></td> \r
+                                                       <td><input id="onmousedown" name="onmousedown" type="text" value="" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="onmouseup">onmouseup</label></td> \r
+                                                       <td><input id="onmouseup" name="onmouseup" type="text" value="" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="onmouseover">onmouseover</label></td> \r
+                                                       <td><input id="onmouseover" name="onmouseover" type="text" value="" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="onmousemove">onmousemove</label></td> \r
+                                                       <td><input id="onmousemove" name="onmousemove" type="text" value="" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="onmouseout">onmouseout</label></td> \r
+                                                       <td><input id="onmouseout" name="onmouseout" type="text" value="" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="onkeypress">onkeypress</label></td> \r
+                                                       <td><input id="onkeypress" name="onkeypress" type="text" value="" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="onkeydown">onkeydown</label></td> \r
+                                                       <td><input id="onkeydown" name="onkeydown" type="text" value="" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="onkeyup">onkeyup</label></td> \r
+                                                       <td><input id="onkeyup" name="onkeyup" type="text" value="" /></td> \r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+                       </div>\r
+               </div>\r
+\r
+               <div class="mceActionPanel">\r
+                       <div style="float: left">\r
+                               <input type="submit" id="insert" name="insert" value="{#insert}" />\r
+                       </div>\r
+\r
+                       <div style="float: right">\r
+                               <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+                       </div>\r
+               </div>\r
+    </form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/autosave/editor_plugin.js b/jscripts/tiny_mce/plugins/autosave/editor_plugin.js
new file mode 100644 (file)
index 0000000..01a994e
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.AutoSavePlugin',{init:function(ed,url){var t=this;t.editor=ed;window.onbeforeunload=tinymce.plugins.AutoSavePlugin._beforeUnloadHandler;},getInfo:function(){return{longname:'Auto save',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autosave',version:tinymce.majorVersion+"."+tinymce.minorVersion};},'static':{_beforeUnloadHandler:function(){var msg;tinymce.each(tinyMCE.editors,function(ed){if(ed.getParam("fullscreen_is_enabled"))return;if(ed.isDirty()){msg=ed.getLang("autosave.unload_msg");return false;}});return msg;}}});tinymce.PluginManager.add('autosave',tinymce.plugins.AutoSavePlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/autosave/editor_plugin_src.js b/jscripts/tiny_mce/plugins/autosave/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..3c4325a
--- /dev/null
@@ -0,0 +1,51 @@
+/**\r
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.AutoSavePlugin', {\r
+               init : function(ed, url) {\r
+                       var t = this;\r
+\r
+                       t.editor = ed;\r
+\r
+                       window.onbeforeunload = tinymce.plugins.AutoSavePlugin._beforeUnloadHandler;\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Auto save',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autosave',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               },\r
+\r
+               // Private plugin internal methods\r
+\r
+               'static' : {\r
+                       _beforeUnloadHandler : function() {\r
+                               var msg;\r
+\r
+                               tinymce.each(tinyMCE.editors, function(ed) {\r
+                                       if (ed.getParam("fullscreen_is_enabled"))\r
+                                               return;\r
+\r
+                                       if (ed.isDirty()) {\r
+                                               msg = ed.getLang("autosave.unload_msg");\r
+                                               return false;\r
+                                       }\r
+                               });\r
+\r
+                               return msg;\r
+                       }\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('autosave', tinymce.plugins.AutoSavePlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/bbcode/editor_plugin.js b/jscripts/tiny_mce/plugins/bbcode/editor_plugin.js
new file mode 100644 (file)
index 0000000..c56cdfd
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.BBCodePlugin',{init:function(ed,url){var t=this,dialect=ed.getParam('bbcode_dialect','punbb').toLowerCase();ed.onBeforeSetContent.add(function(ed,o){o.content=t['_'+dialect+'_bbcode2html'](o.content);});ed.onPostProcess.add(function(ed,o){if(o.set)o.content=t['_'+dialect+'_bbcode2html'](o.content);if(o.get)o.content=t['_'+dialect+'_html2bbcode'](o.content);});},getInfo:function(){return{longname:'BBCode Plugin',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/bbcode',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_punbb_html2bbcode:function(s){s=tinymce.trim(s);function rep(re,str){s=s.replace(re,str);};rep(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]");rep(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");rep(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");rep(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");rep(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");rep(/<span style=\"color: ?(.*?);\">(.*?)<\/span>/gi,"[color=$1]$2[/color]");rep(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[color=$1]$2[/color]");rep(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi,"[size=$1]$2[/size]");rep(/<font>(.*?)<\/font>/gi,"$1");rep(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]");rep(/<span class=\"codeStyle\">(.*?)<\/span>/gi,"[code]$1[/code]");rep(/<span class=\"quoteStyle\">(.*?)<\/span>/gi,"[quote]$1[/quote]");rep(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]");rep(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]");rep(/<em class=\"codeStyle\">(.*?)<\/em>/gi,"[code][i]$1[/i][/code]");rep(/<em class=\"quoteStyle\">(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]");rep(/<u class=\"codeStyle\">(.*?)<\/u>/gi,"[code][u]$1[/u][/code]");rep(/<u class=\"quoteStyle\">(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]");rep(/<\/(strong|b)>/gi,"[/b]");rep(/<(strong|b)>/gi,"[b]");rep(/<\/(em|i)>/gi,"[/i]");rep(/<(em|i)>/gi,"[i]");rep(/<\/u>/gi,"[/u]");rep(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi,"[u]$1[/u]");rep(/<u>/gi,"[u]");rep(/<br \/>/gi,"\n");rep(/<br\/>/gi,"\n");rep(/<br>/gi,"\n");rep(/<p>/gi,"");rep(/<\/p>/gi,"\n");rep(/&nbsp;/gi," ");rep(/&quot;/gi,"\"");rep(/&lt;/gi,"<");rep(/&gt;/gi,">");rep(/&amp;/gi,"&");return s;},_punbb_bbcode2html:function(s){s=tinymce.trim(s);function rep(re,str){s=s.replace(re,str);};rep(/\n/gi,"<br />");rep(/\[b\]/gi,"<strong>");rep(/\[\/b\]/gi,"</strong>");rep(/\[i\]/gi,"<em>");rep(/\[\/i\]/gi,"</em>");rep(/\[u\]/gi,"<u>");rep(/\[\/u\]/gi,"</u>");rep(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,"<a href=\"$1\">$2</a>");rep(/\[url\](.*?)\[\/url\]/gi,"<a href=\"$1\">$1</a>");rep(/\[img\](.*?)\[\/img\]/gi,"<img src=\"$1\" />");rep(/\[color=(.*?)\](.*?)\[\/color\]/gi,"<font color=\"$1\">$2</font>");rep(/\[code\](.*?)\[\/code\]/gi,"<span class=\"codeStyle\">$1</span>&nbsp;");rep(/\[quote.*?\](.*?)\[\/quote\]/gi,"<span class=\"quoteStyle\">$1</span>&nbsp;");return s;}});tinymce.PluginManager.add('bbcode',tinymce.plugins.BBCodePlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/bbcode/editor_plugin_src.js b/jscripts/tiny_mce/plugins/bbcode/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..c7fd262
--- /dev/null
@@ -0,0 +1,115 @@
+/**\r
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.BBCodePlugin', {\r
+               init : function(ed, url) {\r
+                       var t = this, dialect = ed.getParam('bbcode_dialect', 'punbb').toLowerCase();\r
+\r
+                       ed.onBeforeSetContent.add(function(ed, o) {\r
+                               o.content = t['_' + dialect + '_bbcode2html'](o.content);\r
+                       });\r
+\r
+                       ed.onPostProcess.add(function(ed, o) {\r
+                               if (o.set)\r
+                                       o.content = t['_' + dialect + '_bbcode2html'](o.content);\r
+\r
+                               if (o.get)\r
+                                       o.content = t['_' + dialect + '_html2bbcode'](o.content);\r
+                       });\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'BBCode Plugin',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/bbcode',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               },\r
+\r
+               // Private methods\r
+\r
+               // HTML -> BBCode in PunBB dialect\r
+               _punbb_html2bbcode : function(s) {\r
+                       s = tinymce.trim(s);\r
+\r
+                       function rep(re, str) {\r
+                               s = s.replace(re, str);\r
+                       };\r
+\r
+                       // example: <strong> to [b]\r
+                       rep(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]");\r
+                       rep(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");\r
+                       rep(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");\r
+                       rep(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");\r
+                       rep(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");\r
+                       rep(/<span style=\"color: ?(.*?);\">(.*?)<\/span>/gi,"[color=$1]$2[/color]");\r
+                       rep(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[color=$1]$2[/color]");\r
+                       rep(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi,"[size=$1]$2[/size]");\r
+                       rep(/<font>(.*?)<\/font>/gi,"$1");\r
+                       rep(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]");\r
+                       rep(/<span class=\"codeStyle\">(.*?)<\/span>/gi,"[code]$1[/code]");\r
+                       rep(/<span class=\"quoteStyle\">(.*?)<\/span>/gi,"[quote]$1[/quote]");\r
+                       rep(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]");\r
+                       rep(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]");\r
+                       rep(/<em class=\"codeStyle\">(.*?)<\/em>/gi,"[code][i]$1[/i][/code]");\r
+                       rep(/<em class=\"quoteStyle\">(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]");\r
+                       rep(/<u class=\"codeStyle\">(.*?)<\/u>/gi,"[code][u]$1[/u][/code]");\r
+                       rep(/<u class=\"quoteStyle\">(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]");\r
+                       rep(/<\/(strong|b)>/gi,"[/b]");\r
+                       rep(/<(strong|b)>/gi,"[b]");\r
+                       rep(/<\/(em|i)>/gi,"[/i]");\r
+                       rep(/<(em|i)>/gi,"[i]");\r
+                       rep(/<\/u>/gi,"[/u]");\r
+                       rep(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi,"[u]$1[/u]");\r
+                       rep(/<u>/gi,"[u]");\r
+                       rep(/<br \/>/gi,"\n");\r
+                       rep(/<br\/>/gi,"\n");\r
+                       rep(/<br>/gi,"\n");\r
+                       rep(/<p>/gi,"");\r
+                       rep(/<\/p>/gi,"\n");\r
+                       rep(/&nbsp;/gi," ");\r
+                       rep(/&quot;/gi,"\"");\r
+                       rep(/&lt;/gi,"<");\r
+                       rep(/&gt;/gi,">");\r
+                       rep(/&amp;/gi,"&");\r
+\r
+                       return s; \r
+               },\r
+\r
+               // BBCode -> HTML from PunBB dialect\r
+               _punbb_bbcode2html : function(s) {\r
+                       s = tinymce.trim(s);\r
+\r
+                       function rep(re, str) {\r
+                               s = s.replace(re, str);\r
+                       };\r
+\r
+                       // example: [b] to <strong>\r
+                       rep(/\n/gi,"<br />");\r
+                       rep(/\[b\]/gi,"<strong>");\r
+                       rep(/\[\/b\]/gi,"</strong>");\r
+                       rep(/\[i\]/gi,"<em>");\r
+                       rep(/\[\/i\]/gi,"</em>");\r
+                       rep(/\[u\]/gi,"<u>");\r
+                       rep(/\[\/u\]/gi,"</u>");\r
+                       rep(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,"<a href=\"$1\">$2</a>");\r
+                       rep(/\[url\](.*?)\[\/url\]/gi,"<a href=\"$1\">$1</a>");\r
+                       rep(/\[img\](.*?)\[\/img\]/gi,"<img src=\"$1\" />");\r
+                       rep(/\[color=(.*?)\](.*?)\[\/color\]/gi,"<font color=\"$1\">$2</font>");\r
+                       rep(/\[code\](.*?)\[\/code\]/gi,"<span class=\"codeStyle\">$1</span>&nbsp;");\r
+                       rep(/\[quote.*?\](.*?)\[\/quote\]/gi,"<span class=\"quoteStyle\">$1</span>&nbsp;");\r
+\r
+                       return s; \r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('bbcode', tinymce.plugins.BBCodePlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/compat2x/editor_plugin.js b/jscripts/tiny_mce/plugins/compat2x/editor_plugin.js
new file mode 100644 (file)
index 0000000..090c94b
--- /dev/null
@@ -0,0 +1 @@
+(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,each=tinymce.each,is=tinymce.is;tinymce.create('tinymce.plugins.Compat2x',{getInfo:function(){return{longname:'Compat2x',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/compat2x',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion};}});(function(){tinymce.extend(tinyMCE,{addToLang:function(p,l){each(l,function(v,k){tinyMCE.i18n[(tinyMCE.settings.language||'en')+'.'+(p?p+'_':'')+k]=v;});},getInstanceById:function(n){return this.get(n);}});})();(function(){var EditorManager=tinymce.EditorManager;tinyMCE.instances={};tinyMCE.plugins={};tinymce.PluginManager.onAdd.add(function(pm,n,p){tinyMCE.plugins[n]=p;});tinyMCE.majorVersion=tinymce.majorVersion;tinyMCE.minorVersion=tinymce.minorVersion;tinyMCE.releaseDate=tinymce.releaseDate;tinyMCE.baseURL=tinymce.baseURL;tinyMCE.isIE=tinyMCE.isMSIE=tinymce.isIE||tinymce.isOpera;tinyMCE.isMSIE5=tinymce.isIE;tinyMCE.isMSIE5_0=tinymce.isIE;tinyMCE.isMSIE7=tinymce.isIE;tinyMCE.isGecko=tinymce.isGecko;tinyMCE.isSafari=tinymce.isWebKit;tinyMCE.isOpera=tinymce.isOpera;tinyMCE.isMac=false;tinyMCE.isNS7=false;tinyMCE.isNS71=false;tinyMCE.compat=true;TinyMCE_Engine=tinyMCE;tinymce.extend(tinyMCE,{getParam:function(n,dv){return this.activeEditor.getParam(n,dv);},addEvent:function(e,na,f,sc){tinymce.dom.Event.add(e,na,f,sc||this);},getControlHTML:function(n){return EditorManager.activeEditor.controlManager.createControl(n);},loadCSS:function(u){tinymce.DOM.loadCSS(u);},importCSS:function(doc,u){if(doc==document)this.loadCSS(u);else new tinymce.dom.DOMUtils(doc).loadCSS(u);},log:function(){console.debug.apply(console,arguments);},getLang:function(n,dv){var v=EditorManager.activeEditor.getLang(n.replace(/^lang_/g,''),dv);if(/^[0-9\-.]+$/g.test(v))return parseInt(v);return v;},isInstance:function(o){return o!=null&&typeof(o)=="object"&&o.execCommand;},triggerNodeChange:function(){EditorManager.activeEditor.nodeChanged();},regexpReplace:function(in_str,reg_exp,replace_str,opts){var re;if(in_str==null)return in_str;if(typeof(opts)=="undefined")opts='g';re=new RegExp(reg_exp,opts);return in_str.replace(re,replace_str);},trim:function(s){return tinymce.trim(s);},xmlEncode:function(s){return tinymce.DOM.encode(s);},explode:function(s,d){var o=[];tinymce.each(s.split(d),function(v){if(v!='')o.push(v);});return o;},switchClass:function(id,cls){var b;if(/^mceButton/.test(cls)){b=EditorManager.activeEditor.controlManager.get(id);if(!b)return;switch(cls){case"mceButtonNormal":b.setDisabled(false);b.setActive(false);return;case"mceButtonDisabled":b.setDisabled(true);return;case"mceButtonSelected":b.setActive(true);b.setDisabled(false);return;}}},addCSSClass:function(e,n,b){return tinymce.DOM.addClass(e,n,b);},hasCSSClass:function(e,n){return tinymce.DOM.hasClass(e,n);},removeCSSClass:function(e,n){return tinymce.DOM.removeClass(e,n);},getCSSClasses:function(){var cl=EditorManager.activeEditor.dom.getClasses(),o=[];each(cl,function(c){o.push(c['class']);});return o;},setWindowArg:function(n,v){EditorManager.activeEditor.windowManager.params[n]=v;},getWindowArg:function(n,dv){var wm=EditorManager.activeEditor.windowManager,v;v=wm.getParam(n);if(v==='')return'';return v||wm.getFeature(n)||dv;},getParentNode:function(n,f){return this._getDOM().getParent(n,f);},selectElements:function(n,na,f){var i,a=[],nl,x;for(x=0,na=na.split(',');x<na.length;x++)for(i=0,nl=n.getElementsByTagName(na[x]);i<nl.length;i++)(!f||f(nl[i]))&&a.push(nl[i]);return a;},getNodeTree:function(n,na,t,nn){return this.selectNodes(n,function(n){return(!t||n.nodeType==t)&&(!nn||n.nodeName==nn);},na?na:[]);},getAttrib:function(e,n,dv){return this._getDOM().getAttrib(e,n,dv);},setAttrib:function(e,n,v){return this._getDOM().setAttrib(e,n,v);},getElementsByAttributeValue:function(n,e,a,v){var i,nl=n.getElementsByTagName(e),o=[];for(i=0;i<nl.length;i++){if(tinyMCE.getAttrib(nl[i],a).indexOf(v)!=-1)o[o.length]=nl[i];}return o;},selectNodes:function(n,f,a){var i;if(!a)a=[];if(f(n))a[a.length]=n;if(n.hasChildNodes()){for(i=0;i<n.childNodes.length;i++)tinyMCE.selectNodes(n.childNodes[i],f,a);}return a;},getContent:function(){return EditorManager.activeEditor.getContent();},getParentElement:function(n,na,f){if(na)na=new RegExp('^('+na.toUpperCase().replace(/,/g,'|')+')$','g');return this._getDOM().getParent(n,function(n){return n.nodeType==1&&(!na||na.test(n.nodeName))&&(!f||f(n));},this.activeEditor.getBody());},importPluginLanguagePack:function(n){tinymce.PluginManager.requireLangPack(n);},getButtonHTML:function(cn,lang,img,c,u,v){var ed=EditorManager.activeEditor;img=img.replace(/\{\$pluginurl\}/g,tinyMCE.pluginURL);img=img.replace(/\{\$themeurl\}/g,tinyMCE.themeURL);lang=lang.replace(/^lang_/g,'');return ed.controlManager.createButton(cn,{title:lang,command:c,ui:u,value:v,scope:this,'class':'compat',image:img});},addSelectAccessibility:function(e,s,w){if(!s._isAccessible){s.onkeydown=tinyMCE.accessibleEventHandler;s.onblur=tinyMCE.accessibleEventHandler;s._isAccessible=true;s._win=w;}return false;},accessibleEventHandler:function(e){var elm,win=this._win;e=tinymce.isIE?win.event:e;elm=tinymce.isIE?e.srcElement:e.target;if(e.type=="blur"){if(elm.oldonchange){elm.onchange=elm.oldonchange;elm.oldonchange=null;}return true;}if(elm.nodeName=="SELECT"&&!elm.oldonchange){elm.oldonchange=elm.onchange;elm.onchange=null;}if(e.keyCode==13||e.keyCode==32){elm.onchange=elm.oldonchange;elm.onchange();elm.oldonchange=null;tinyMCE.cancelEvent(e);return false;}return true;},cancelEvent:function(e){return tinymce.dom.Event.cancel(e);},handleVisualAid:function(e){EditorManager.activeEditor.addVisual(e);},getAbsPosition:function(n,r){return tinymce.DOM.getPos(n,r);},cleanupEventStr:function(s){s=""+s;s=s.replace('function anonymous()\n{\n','');s=s.replace('\n}','');s=s.replace(/^return true;/gi,'');return s;},getVisualAidClass:function(s){return s;},parseStyle:function(s){return this._getDOM().parseStyle(s);},serializeStyle:function(s){return this._getDOM().serializeStyle(s);},openWindow:function(tpl,args){var ed=EditorManager.activeEditor,o={},n;for(n in tpl)o[n]=tpl[n];tpl=o;args=args||{};tpl.url=new tinymce.util.URI(tinymce.ThemeManager.themeURLs[ed.settings.theme]).toAbsolute(tpl.file);tpl.inline=tpl.inline||args.inline;ed.windowManager.open(tpl,args);},closeWindow:function(win){EditorManager.activeEditor.windowManager.close(win);},getOuterHTML:function(e){return tinymce.DOM.getOuterHTML(e);},setOuterHTML:function(e,h,d){return tinymce.DOM.setOuterHTML(e,h,d);},hasPlugin:function(n){return tinymce.PluginManager.get(n)!=null;},_setEventsEnabled:function(){},addPlugin:function(pn,f){var t=this;function PluginWrapper(ed){tinyMCE.selectedInstance=ed;ed.onInit.add(function(){t.settings=ed.settings;t.settings['base_href']=tinyMCE.documentBasePath;tinyMCE.settings=t.settings;tinyMCE.documentBasePath=ed.documentBasePath;if(f.initInstance)f.initInstance(ed);ed.contentDocument=ed.getDoc();ed.contentWindow=ed.getWin();ed.undoRedo=ed.undoManager;ed.startContent=ed.getContent({format:'raw'});tinyMCE.instances[ed.id]=ed;tinyMCE.loadedFiles=[];});ed.onActivate.add(function(){tinyMCE.settings=ed.settings;tinyMCE.selectedInstance=ed;});if(f.handleNodeChange){ed.onNodeChange.add(function(ed,cm,n){f.handleNodeChange(ed.id,n,0,0,false,!ed.selection.isCollapsed());});}if(f.onChange){ed.onChange.add(function(ed,n){return f.onChange(ed);});}if(f.cleanup){ed.onGetContent.add(function(){});}this.getInfo=function(){return f.getInfo();};this.createControl=function(n){tinyMCE.pluginURL=tinymce.baseURL+'/plugins/'+pn;tinyMCE.themeURL=tinymce.baseURL+'/themes/'+tinyMCE.activeEditor.settings.theme;if(f.getControlHTML)return f.getControlHTML(n);return null;};this.execCommand=function(cmd,ui,val){if(f.execCommand)return f.execCommand(ed.id,ed.getBody(),cmd,ui,val);return false;};};tinymce.PluginManager.add(pn,PluginWrapper);},_getDOM:function(){return tinyMCE.activeEditor?tinyMCE.activeEditor.dom:tinymce.DOM;},convertRelativeToAbsoluteURL:function(b,u){return new tinymce.util.URI(b).toAbsolute(u);},convertAbsoluteURLToRelativeURL:function(b,u){return new tinymce.util.URI(b).toRelative(u);}});tinymce.extend(tinymce.Editor.prototype,{getFocusElement:function(){return this.selection.getNode();},getData:function(n){if(!this.data)this.data=[];if(!this.data[n])this.data[n]=[];return this.data[n];},hasPlugin:function(n){return this.plugins[n]!=null;},getContainerWin:function(){return window;},getHTML:function(raw){return this.getContent({format:raw?'raw':'html'});},setHTML:function(h){this.setContent(h);},getSel:function(){return this.selection.getSel();},getRng:function(){return this.selection.getRng();},isHidden:function(){var s;if(!tinymce.isGecko)return false;s=this.getSel();return(!s||!s.rangeCount||s.rangeCount==0);},translate:function(s){var c=this.settings.language,o;o=tinymce.EditorManager.i18n[c+'.'+s]||s.replace(/{\#([^}]+)\}/g,function(a,b){return tinymce.EditorManager.i18n[c+'.'+b]||'{#'+b+'}';});o=o.replace(/{\$lang_([^}]+)\}/g,function(a,b){return tinymce.EditorManager.i18n[c+'.'+b]||'{$lang_'+b+'}';});return o;},repaint:function(){this.execCommand('mceRepaint');}});tinymce.extend(tinymce.dom.Selection.prototype,{getSelectedText:function(){return this.getContent({format:'text'});},getSelectedHTML:function(){return this.getContent({format:'html'});},getFocusElement:function(){return this.getNode();},selectNode:function(node,collapse,select_text_node,to_start){var t=this;t.select(node,select_text_node||0);if(!is(collapse))collapse=true;if(collapse){if(!is(to_start))to_start=true;t.collapse(to_start);}}});}).call(this);tinymce.PluginManager.add('compat2x',tinymce.plugins.Compat2x);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/compat2x/editor_plugin_src.js b/jscripts/tiny_mce/plugins/compat2x/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..afad77c
--- /dev/null
@@ -0,0 +1,613 @@
+/**\r
+ * $Id: editor_plugin_src.js 264 2007-04-26 20:53:09Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, is = tinymce.is;\r
+\r
+       tinymce.create('tinymce.plugins.Compat2x', {\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Compat2x',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/compat2x',\r
+                               version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion\r
+                       };\r
+               }\r
+       });\r
+\r
+       (function() {\r
+               // Extend tinyMCE/EditorManager\r
+               tinymce.extend(tinyMCE, {\r
+                       addToLang : function(p, l) {\r
+                               each(l, function(v, k) {\r
+                                       tinyMCE.i18n[(tinyMCE.settings.language || 'en') + '.' + (p ? p + '_' : '') + k] = v;\r
+                               });\r
+                       },\r
+\r
+                       getInstanceById : function(n) {\r
+                               return this.get(n);\r
+                       }\r
+               });\r
+       })();\r
+\r
+       (function() {\r
+               var EditorManager = tinymce.EditorManager;\r
+\r
+               tinyMCE.instances = {};\r
+               tinyMCE.plugins = {};\r
+               tinymce.PluginManager.onAdd.add(function(pm, n, p) {\r
+                       tinyMCE.plugins[n] = p;\r
+               });\r
+\r
+               tinyMCE.majorVersion = tinymce.majorVersion;\r
+               tinyMCE.minorVersion = tinymce.minorVersion;\r
+               tinyMCE.releaseDate = tinymce.releaseDate;\r
+               tinyMCE.baseURL = tinymce.baseURL;\r
+               tinyMCE.isIE = tinyMCE.isMSIE = tinymce.isIE || tinymce.isOpera;\r
+               tinyMCE.isMSIE5 = tinymce.isIE;\r
+               tinyMCE.isMSIE5_0 = tinymce.isIE;\r
+               tinyMCE.isMSIE7 = tinymce.isIE;\r
+               tinyMCE.isGecko = tinymce.isGecko;\r
+               tinyMCE.isSafari = tinymce.isWebKit;\r
+               tinyMCE.isOpera = tinymce.isOpera;\r
+               tinyMCE.isMac = false;\r
+               tinyMCE.isNS7 = false;\r
+               tinyMCE.isNS71 = false;\r
+               tinyMCE.compat = true;\r
+\r
+               // Extend tinyMCE class\r
+               TinyMCE_Engine = tinyMCE;\r
+               tinymce.extend(tinyMCE, {\r
+                       getParam : function(n, dv) {\r
+                               return this.activeEditor.getParam(n, dv);\r
+                       },\r
+\r
+                       addEvent : function(e, na, f, sc) {\r
+                               tinymce.dom.Event.add(e, na, f, sc || this);\r
+                       },\r
+\r
+                       getControlHTML : function(n) {\r
+                               return EditorManager.activeEditor.controlManager.createControl(n);\r
+                       },\r
+\r
+                       loadCSS : function(u) {\r
+                               tinymce.DOM.loadCSS(u);\r
+                       },\r
+\r
+                       importCSS : function(doc, u) {\r
+                               if (doc == document)\r
+                                       this.loadCSS(u);\r
+                               else\r
+                                       new tinymce.dom.DOMUtils(doc).loadCSS(u);\r
+                       },\r
+\r
+                       log : function() {\r
+                               console.debug.apply(console, arguments);\r
+                       },\r
+\r
+                       getLang : function(n, dv) {\r
+                               var v = EditorManager.activeEditor.getLang(n.replace(/^lang_/g, ''), dv);\r
+\r
+                               // Is number\r
+                               if (/^[0-9\-.]+$/g.test(v))\r
+                                       return parseInt(v);\r
+\r
+                               return v;\r
+                       },\r
+\r
+                       isInstance : function(o) {\r
+                               return o != null && typeof(o) == "object" && o.execCommand;\r
+                       },\r
+\r
+                       triggerNodeChange : function() {\r
+                               EditorManager.activeEditor.nodeChanged();\r
+                       },\r
+\r
+                       regexpReplace : function(in_str, reg_exp, replace_str, opts) {\r
+                               var re;\r
+\r
+                               if (in_str == null)\r
+                                       return in_str;\r
+\r
+                               if (typeof(opts) == "undefined")\r
+                                       opts = 'g';\r
+\r
+                               re = new RegExp(reg_exp, opts);\r
+\r
+                               return in_str.replace(re, replace_str);\r
+                       },\r
+\r
+                       trim : function(s) {\r
+                               return tinymce.trim(s);\r
+                       },\r
+\r
+                       xmlEncode : function(s) {\r
+                               return tinymce.DOM.encode(s);\r
+                       },\r
+\r
+                       explode : function(s, d) {\r
+                               var o = [];\r
+\r
+                               tinymce.each(s.split(d), function(v) {\r
+                                       if (v != '')\r
+                                               o.push(v);\r
+                               });\r
+\r
+                               return o;\r
+                       },\r
+\r
+                       switchClass : function(id, cls) {\r
+                               var b;\r
+\r
+                               if (/^mceButton/.test(cls)) {\r
+                                       b = EditorManager.activeEditor.controlManager.get(id);\r
+\r
+                                       if (!b)\r
+                                               return;\r
+\r
+                                       switch (cls) {\r
+                                               case "mceButtonNormal":\r
+                                                       b.setDisabled(false);\r
+                                                       b.setActive(false);\r
+                                                       return;\r
+\r
+                                               case "mceButtonDisabled":\r
+                                                       b.setDisabled(true);\r
+                                                       return;\r
+\r
+                                               case "mceButtonSelected":\r
+                                                       b.setActive(true);\r
+                                                       b.setDisabled(false);\r
+                                                       return;\r
+                                       }\r
+                               }\r
+                       },\r
+\r
+                       addCSSClass : function(e, n, b) {\r
+                               return tinymce.DOM.addClass(e, n, b);\r
+                       },\r
+\r
+                       hasCSSClass : function(e, n) {\r
+                               return tinymce.DOM.hasClass(e, n);\r
+                       },\r
+\r
+                       removeCSSClass : function(e, n) {\r
+                               return tinymce.DOM.removeClass(e, n);\r
+                       },\r
+\r
+                       getCSSClasses : function() {\r
+                               var cl = EditorManager.activeEditor.dom.getClasses(), o = [];\r
+\r
+                               each(cl, function(c) {\r
+                                       o.push(c['class']);\r
+                               });\r
+\r
+                               return o;\r
+                       },\r
+\r
+                       setWindowArg : function(n, v) {\r
+                               EditorManager.activeEditor.windowManager.params[n] = v;\r
+                       },\r
+\r
+                       getWindowArg : function(n, dv) {\r
+                               var wm = EditorManager.activeEditor.windowManager, v;\r
+\r
+                               v = wm.getParam(n);\r
+                               if (v === '')\r
+                                       return '';\r
+\r
+                               return v || wm.getFeature(n) || dv;\r
+                       },\r
+\r
+                       getParentNode : function(n, f) {\r
+                               return this._getDOM().getParent(n, f);\r
+                       },\r
+\r
+                       selectElements : function(n, na, f) {\r
+                               var i, a = [], nl, x;\r
+\r
+                               for (x=0, na = na.split(','); x<na.length; x++)\r
+                                       for (i=0, nl = n.getElementsByTagName(na[x]); i<nl.length; i++)\r
+                                               (!f || f(nl[i])) && a.push(nl[i]);\r
+\r
+                               return a;\r
+                       },\r
+\r
+                       getNodeTree : function(n, na, t, nn) {\r
+                               return this.selectNodes(n, function(n) {\r
+                                       return (!t || n.nodeType == t) && (!nn || n.nodeName == nn);\r
+                               }, na ? na : []);\r
+                       },\r
+\r
+                       getAttrib : function(e, n, dv) {\r
+                               return this._getDOM().getAttrib(e, n, dv);\r
+                       },\r
+\r
+                       setAttrib : function(e, n, v) {\r
+                               return this._getDOM().setAttrib(e, n, v);\r
+                       },\r
+\r
+                       getElementsByAttributeValue : function(n, e, a, v) {\r
+                               var i, nl = n.getElementsByTagName(e), o = [];\r
+\r
+                               for (i=0; i<nl.length; i++) {\r
+                                       if (tinyMCE.getAttrib(nl[i], a).indexOf(v) != -1)\r
+                                               o[o.length] = nl[i];\r
+                               }\r
+\r
+                               return o;\r
+                       },\r
+\r
+                       selectNodes : function(n, f, a) {\r
+                               var i;\r
+\r
+                               if (!a)\r
+                                       a = [];\r
+\r
+                               if (f(n))\r
+                                       a[a.length] = n;\r
+\r
+                               if (n.hasChildNodes()) {\r
+                                       for (i=0; i<n.childNodes.length; i++)\r
+                                               tinyMCE.selectNodes(n.childNodes[i], f, a);\r
+                               }\r
+\r
+                               return a;\r
+                       },\r
+\r
+                       getContent : function() {\r
+                               return EditorManager.activeEditor.getContent();\r
+                       },\r
+\r
+                       getParentElement : function(n, na, f) {\r
+                               if (na)\r
+                                       na = new RegExp('^(' + na.toUpperCase().replace(/,/g, '|') + ')$', 'g');\r
+\r
+                               return this._getDOM().getParent(n, function(n) {\r
+                                       return n.nodeType == 1 && (!na || na.test(n.nodeName)) && (!f || f(n));\r
+                               }, this.activeEditor.getBody());\r
+                       },\r
+\r
+                       importPluginLanguagePack : function(n) {\r
+                               tinymce.PluginManager.requireLangPack(n);\r
+                       },\r
+\r
+                       getButtonHTML : function(cn, lang, img, c, u, v) {\r
+                               var ed = EditorManager.activeEditor;\r
+\r
+                               img = img.replace(/\{\$pluginurl\}/g, tinyMCE.pluginURL);\r
+                               img = img.replace(/\{\$themeurl\}/g, tinyMCE.themeURL);\r
+                               lang = lang.replace(/^lang_/g, '');\r
+\r
+                               return ed.controlManager.createButton(cn, {\r
+                                       title : lang,\r
+                                       command : c,\r
+                                       ui : u,\r
+                                       value : v,\r
+                                       scope : this,\r
+                                       'class' : 'compat',\r
+                                       image : img\r
+                               });\r
+                       },\r
+\r
+                       addSelectAccessibility : function(e, s, w) {\r
+                               // Add event handlers \r
+                               if (!s._isAccessible) {\r
+                                       s.onkeydown = tinyMCE.accessibleEventHandler;\r
+                                       s.onblur = tinyMCE.accessibleEventHandler;\r
+                                       s._isAccessible = true;\r
+                                       s._win = w;\r
+                               }\r
+\r
+                               return false;\r
+                       },\r
+\r
+                       accessibleEventHandler : function(e) {\r
+                               var elm, win = this._win;\r
+\r
+                               e = tinymce.isIE ? win.event : e;\r
+                               elm = tinymce.isIE ? e.srcElement : e.target;\r
+\r
+                               // Unpiggyback onchange on blur\r
+                               if (e.type == "blur") {\r
+                                       if (elm.oldonchange) {\r
+                                               elm.onchange = elm.oldonchange;\r
+                                               elm.oldonchange = null;\r
+                                       }\r
+\r
+                                       return true;\r
+                               }\r
+\r
+                               // Piggyback onchange\r
+                               if (elm.nodeName == "SELECT" && !elm.oldonchange) {\r
+                                       elm.oldonchange = elm.onchange;\r
+                                       elm.onchange = null;\r
+                               }\r
+\r
+                               // Execute onchange and remove piggyback\r
+                               if (e.keyCode == 13 || e.keyCode == 32) {\r
+                                       elm.onchange = elm.oldonchange;\r
+                                       elm.onchange();\r
+                                       elm.oldonchange = null;\r
+\r
+                                       tinyMCE.cancelEvent(e);\r
+                                       return false;\r
+                               }\r
+\r
+                               return true;\r
+                       },\r
+\r
+                       cancelEvent : function(e) {\r
+                               return tinymce.dom.Event.cancel(e);\r
+                       },\r
+\r
+                       handleVisualAid : function(e) {\r
+                               EditorManager.activeEditor.addVisual(e);\r
+                       },\r
+\r
+                       getAbsPosition : function(n, r) {\r
+                               return tinymce.DOM.getPos(n, r);\r
+                       },\r
+\r
+                       cleanupEventStr : function(s) {\r
+                               s = "" + s;\r
+                               s = s.replace('function anonymous()\n{\n', '');\r
+                               s = s.replace('\n}', '');\r
+                               s = s.replace(/^return true;/gi, ''); // Remove event blocker\r
+\r
+                               return s;\r
+                       },\r
+\r
+                       getVisualAidClass : function(s) {\r
+                               // TODO: Implement\r
+                               return s;\r
+                       },\r
+\r
+                       parseStyle : function(s) {\r
+                               return this._getDOM().parseStyle(s);\r
+                       },\r
+\r
+                       serializeStyle : function(s) {\r
+                               return this._getDOM().serializeStyle(s);\r
+                       },\r
+\r
+                       openWindow : function(tpl, args) {\r
+                               var ed = EditorManager.activeEditor, o = {}, n;\r
+\r
+                               // Convert name/value array to object\r
+                               for (n in tpl)\r
+                                       o[n] = tpl[n];\r
+\r
+                               tpl = o;\r
+\r
+                               args = args || {};\r
+                               tpl.url = new tinymce.util.URI(tinymce.ThemeManager.themeURLs[ed.settings.theme]).toAbsolute(tpl.file);\r
+                               tpl.inline = tpl.inline || args.inline;\r
+\r
+                               ed.windowManager.open(tpl, args);\r
+                       },\r
+\r
+                       closeWindow : function(win) {\r
+                               EditorManager.activeEditor.windowManager.close(win);\r
+                       },\r
+\r
+                       getOuterHTML : function(e) {\r
+                               return tinymce.DOM.getOuterHTML(e);\r
+                       },\r
+\r
+                       setOuterHTML : function(e, h, d) {\r
+                               return tinymce.DOM.setOuterHTML(e, h, d);\r
+                       },\r
+\r
+                       hasPlugin : function(n) {\r
+                               return tinymce.PluginManager.get(n) != null;\r
+                       },\r
+\r
+                       _setEventsEnabled : function() {\r
+                               // Ignore it!!\r
+                       },\r
+\r
+                       addPlugin : function(pn, f) {\r
+                               var t = this;\r
+\r
+                               function PluginWrapper(ed) {\r
+                                       tinyMCE.selectedInstance = ed;\r
+\r
+                                       ed.onInit.add(function() {\r
+                                               t.settings = ed.settings;\r
+                                               t.settings['base_href'] = tinyMCE.documentBasePath;\r
+                                               tinyMCE.settings = t.settings;\r
+                                               tinyMCE.documentBasePath = ed.documentBasePath;\r
+                                               //ed.formElement = DOM.get(ed.id);\r
+\r
+                                               if (f.initInstance)\r
+                                                       f.initInstance(ed);\r
+\r
+                                               ed.contentDocument = ed.getDoc();\r
+                                               ed.contentWindow = ed.getWin();\r
+                                               ed.undoRedo = ed.undoManager;\r
+                                               ed.startContent = ed.getContent({format : 'raw'});\r
+\r
+                                               tinyMCE.instances[ed.id] = ed;\r
+                                               tinyMCE.loadedFiles = [];\r
+                                       });\r
+\r
+                                       ed.onActivate.add(function() {\r
+                                               tinyMCE.settings = ed.settings;\r
+                                               tinyMCE.selectedInstance = ed;\r
+                                       });\r
+\r
+                               /*      if (f.removeInstance) {\r
+                                               ed.onDestroy.add(function() {\r
+                                                       return f.removeInstance(ed.id);\r
+                                               });\r
+                                       }*/\r
+\r
+                                       if (f.handleNodeChange) {\r
+                                               ed.onNodeChange.add(function(ed, cm, n) {\r
+                                                       f.handleNodeChange(ed.id, n, 0, 0, false, !ed.selection.isCollapsed());\r
+                                               });\r
+                                       }\r
+\r
+                                       if (f.onChange) {\r
+                                               ed.onChange.add(function(ed, n) {\r
+                                                       return f.onChange(ed);\r
+                                               });\r
+                                       }\r
+\r
+                                       if (f.cleanup) {\r
+                                               ed.onGetContent.add(function() {\r
+                                                       //f.cleanup(type, content, inst);\r
+                                               });\r
+                                       }\r
+\r
+                                       this.getInfo = function() {\r
+                                               return f.getInfo();\r
+                                       };\r
+\r
+                                       this.createControl = function(n) {\r
+                                               tinyMCE.pluginURL = tinymce.baseURL + '/plugins/' + pn;\r
+                                               tinyMCE.themeURL = tinymce.baseURL + '/themes/' + tinyMCE.activeEditor.settings.theme;\r
+\r
+                                               if (f.getControlHTML)\r
+                                                       return f.getControlHTML(n);\r
+\r
+                                               return null;\r
+                                       };\r
+\r
+                                       this.execCommand = function(cmd, ui, val) {\r
+                                               if (f.execCommand)\r
+                                                       return f.execCommand(ed.id, ed.getBody(), cmd, ui, val);\r
+\r
+                                               return false;\r
+                                       };\r
+                               };\r
+\r
+                               tinymce.PluginManager.add(pn, PluginWrapper);\r
+                       },\r
+\r
+                       _getDOM : function() {\r
+                               return tinyMCE.activeEditor ? tinyMCE.activeEditor.dom : tinymce.DOM;\r
+                       },\r
+\r
+                       convertRelativeToAbsoluteURL : function(b, u) {\r
+                               return new tinymce.util.URI(b).toAbsolute(u);\r
+                       },\r
+\r
+                       convertAbsoluteURLToRelativeURL : function(b, u) {\r
+                               return new tinymce.util.URI(b).toRelative(u);\r
+                       }\r
+               });\r
+\r
+               // Extend Editor class\r
+               tinymce.extend(tinymce.Editor.prototype, {\r
+                       getFocusElement : function() {\r
+                               return this.selection.getNode();\r
+                       },\r
+\r
+                       getData : function(n) {\r
+                               if (!this.data)\r
+                                       this.data = [];\r
+\r
+                               if (!this.data[n])\r
+                                       this.data[n] = [];\r
+\r
+                               return this.data[n];\r
+                       },\r
+\r
+                       hasPlugin : function(n) {\r
+                               return this.plugins[n] != null;\r
+                       },\r
+\r
+                       getContainerWin : function() {\r
+                               return window;\r
+                       },\r
+\r
+                       getHTML : function(raw) {\r
+                               return this.getContent({ format : raw ? 'raw' : 'html'});\r
+                       },\r
+\r
+                       setHTML : function(h) {\r
+                               this.setContent(h);\r
+                       },\r
+\r
+                       getSel : function() {\r
+                               return this.selection.getSel();\r
+                       },\r
+\r
+                       getRng : function() {\r
+                               return this.selection.getRng();\r
+                       },\r
+\r
+                       isHidden : function() {\r
+                               var s;\r
+\r
+                               if (!tinymce.isGecko)\r
+                                       return false;\r
+\r
+                               s = this.getSel();\r
+\r
+                               // Weird, wheres that cursor selection?\r
+                               return (!s || !s.rangeCount || s.rangeCount == 0);\r
+                       },\r
+\r
+                       translate : function(s) {\r
+                               var c = this.settings.language, o;\r
+\r
+                               o = tinymce.EditorManager.i18n[c + '.' + s] || s.replace(/{\#([^}]+)\}/g, function(a, b) {\r
+                                       return tinymce.EditorManager.i18n[c + '.' + b] || '{#' + b + '}';\r
+                               });\r
+\r
+                               o = o.replace(/{\$lang_([^}]+)\}/g, function(a, b) {\r
+                                       return tinymce.EditorManager.i18n[c + '.' + b] || '{$lang_' + b + '}';\r
+                               });\r
+\r
+                               return o;\r
+                       },\r
+\r
+                       repaint : function() {\r
+                               this.execCommand('mceRepaint');\r
+                       }\r
+               });\r
+\r
+               // Extend selection\r
+               tinymce.extend(tinymce.dom.Selection.prototype, {\r
+                       getSelectedText : function() {\r
+                               return this.getContent({format : 'text'});\r
+                       },\r
+\r
+                       getSelectedHTML : function() {\r
+                               return this.getContent({format : 'html'});\r
+                       },\r
+\r
+                       getFocusElement : function() {\r
+                               return this.getNode();\r
+                       },\r
+\r
+                       selectNode : function(node, collapse, select_text_node, to_start) {\r
+                               var t = this;\r
+\r
+                               t.select(node, select_text_node || 0);\r
+\r
+                               if (!is(collapse))\r
+                                       collapse = true;\r
+\r
+                               if (collapse) {\r
+                                       if (!is(to_start))\r
+                                               to_start = true;\r
+\r
+                                       t.collapse(to_start);\r
+                               }\r
+                       }\r
+               });\r
+       }).call(this);\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('compat2x', tinymce.plugins.Compat2x);\r
+})();\r
+\r
diff --git a/jscripts/tiny_mce/plugins/contextmenu/editor_plugin.js b/jscripts/tiny_mce/plugins/contextmenu/editor_plugin.js
new file mode 100644 (file)
index 0000000..7dc3438
--- /dev/null
@@ -0,0 +1 @@
+(function(){var Event=tinymce.dom.Event,each=tinymce.each,DOM=tinymce.DOM;tinymce.create('tinymce.plugins.ContextMenu',{init:function(ed){var t=this;t.editor=ed;t.onContextMenu=new tinymce.util.Dispatcher(this);ed.onContextMenu.add(function(ed,e){if(!e.ctrlKey){t._getMenu(ed).showMenu(e.clientX,e.clientY);Event.add(document,'click',hide);Event.cancel(e);}});function hide(){if(t._menu){t._menu.removeAll();t._menu.destroy();Event.remove(document,'click',hide);}};ed.onMouseDown.add(hide);ed.onKeyDown.add(hide);},getInfo:function(){return{longname:'Contextmenu',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/contextmenu',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_getMenu:function(ed){var t=this,m=t._menu,se=ed.selection,col=se.isCollapsed(),el=se.getNode()||ed.getBody(),am,p1,p2;if(m){m.removeAll();m.destroy();}p1=DOM.getPos(ed.getContentAreaContainer());p2=DOM.getPos(ed.getContainer());m=ed.controlManager.createDropMenu('contextmenu',{offset_x:p1.x,offset_y:p1.y,constrain:1});t._menu=m;m.add({title:'advanced.cut_desc',icon:'cut',cmd:'Cut'}).setDisabled(col);m.add({title:'advanced.copy_desc',icon:'copy',cmd:'Copy'}).setDisabled(col);m.add({title:'advanced.paste_desc',icon:'paste',cmd:'Paste'});if((el.nodeName=='A'&&!ed.dom.getAttrib(el,'name'))||!col){m.addSeparator();m.add({title:'advanced.link_desc',icon:'link',cmd:ed.plugins.advlink?'mceAdvLink':'mceLink',ui:true});m.add({title:'advanced.unlink_desc',icon:'unlink',cmd:'UnLink'});}m.addSeparator();m.add({title:'advanced.image_desc',icon:'image',cmd:ed.plugins.advimage?'mceAdvImage':'mceImage',ui:true});m.addSeparator();am=m.addMenu({title:'contextmenu.align'});am.add({title:'contextmenu.left',icon:'justifyleft',cmd:'JustifyLeft'});am.add({title:'contextmenu.center',icon:'justifycenter',cmd:'JustifyCenter'});am.add({title:'contextmenu.right',icon:'justifyright',cmd:'JustifyRight'});am.add({title:'contextmenu.full',icon:'justifyfull',cmd:'JustifyFull'});t.onContextMenu.dispatch(t,m,el,col);return m;}});tinymce.PluginManager.add('contextmenu',tinymce.plugins.ContextMenu);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/contextmenu/editor_plugin_src.js b/jscripts/tiny_mce/plugins/contextmenu/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..6492641
--- /dev/null
@@ -0,0 +1,97 @@
+/**\r
+ * $Id: editor_plugin_src.js 755 2008-03-29 19:14:42Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       var Event = tinymce.dom.Event, each = tinymce.each, DOM = tinymce.DOM;\r
+\r
+       tinymce.create('tinymce.plugins.ContextMenu', {\r
+               init : function(ed) {\r
+                       var t = this;\r
+\r
+                       t.editor = ed;\r
+                       t.onContextMenu = new tinymce.util.Dispatcher(this);\r
+\r
+                       ed.onContextMenu.add(function(ed, e) {\r
+                               if (!e.ctrlKey) {\r
+                                       t._getMenu(ed).showMenu(e.clientX, e.clientY);\r
+                                       Event.add(document, 'click', hide);\r
+                                       Event.cancel(e);\r
+                               }\r
+                       });\r
+\r
+                       function hide() {\r
+                               if (t._menu) {\r
+                                       t._menu.removeAll();\r
+                                       t._menu.destroy();\r
+                                       Event.remove(document, 'click', hide);\r
+                               }\r
+                       };\r
+\r
+                       ed.onMouseDown.add(hide);\r
+                       ed.onKeyDown.add(hide);\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Contextmenu',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/contextmenu',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               },\r
+\r
+               _getMenu : function(ed) {\r
+                       var t = this, m = t._menu, se = ed.selection, col = se.isCollapsed(), el = se.getNode() || ed.getBody(), am, p1, p2;\r
+\r
+                       if (m) {\r
+                               m.removeAll();\r
+                               m.destroy();\r
+                       }\r
+\r
+                       p1 = DOM.getPos(ed.getContentAreaContainer());\r
+                       p2 = DOM.getPos(ed.getContainer());\r
+\r
+                       m = ed.controlManager.createDropMenu('contextmenu', {\r
+                               offset_x : p1.x,\r
+                               offset_y : p1.y,\r
+/*                             vp_offset_x : p2.x,\r
+                               vp_offset_y : p2.y,*/\r
+                               constrain : 1\r
+                       });\r
+\r
+                       t._menu = m;\r
+\r
+                       m.add({title : 'advanced.cut_desc', icon : 'cut', cmd : 'Cut'}).setDisabled(col);\r
+                       m.add({title : 'advanced.copy_desc', icon : 'copy', cmd : 'Copy'}).setDisabled(col);\r
+                       m.add({title : 'advanced.paste_desc', icon : 'paste', cmd : 'Paste'});\r
+\r
+                       if ((el.nodeName == 'A' && !ed.dom.getAttrib(el, 'name')) || !col) {\r
+                               m.addSeparator();\r
+                               m.add({title : 'advanced.link_desc', icon : 'link', cmd : ed.plugins.advlink ? 'mceAdvLink' : 'mceLink', ui : true});\r
+                               m.add({title : 'advanced.unlink_desc', icon : 'unlink', cmd : 'UnLink'});\r
+                       }\r
+\r
+                       m.addSeparator();\r
+                       m.add({title : 'advanced.image_desc', icon : 'image', cmd : ed.plugins.advimage ? 'mceAdvImage' : 'mceImage', ui : true});\r
+\r
+                       m.addSeparator();\r
+                       am = m.addMenu({title : 'contextmenu.align'});\r
+                       am.add({title : 'contextmenu.left', icon : 'justifyleft', cmd : 'JustifyLeft'});\r
+                       am.add({title : 'contextmenu.center', icon : 'justifycenter', cmd : 'JustifyCenter'});\r
+                       am.add({title : 'contextmenu.right', icon : 'justifyright', cmd : 'JustifyRight'});\r
+                       am.add({title : 'contextmenu.full', icon : 'justifyfull', cmd : 'JustifyFull'});\r
+\r
+                       t.onContextMenu.dispatch(t, m, el, col);\r
+\r
+                       return m;\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('contextmenu', tinymce.plugins.ContextMenu);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/directionality/editor_plugin.js b/jscripts/tiny_mce/plugins/directionality/editor_plugin.js
new file mode 100644 (file)
index 0000000..6966d80
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.Directionality',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mceDirectionLTR',function(){var e=ed.dom.getParent(ed.selection.getNode(),ed.dom.isBlock);if(e){if(ed.dom.getAttrib(e,"dir")!="ltr")ed.dom.setAttrib(e,"dir","ltr");else ed.dom.setAttrib(e,"dir","");}ed.nodeChanged();});ed.addCommand('mceDirectionRTL',function(){var e=ed.dom.getParent(ed.selection.getNode(),ed.dom.isBlock);if(e){if(ed.dom.getAttrib(e,"dir")!="rtl")ed.dom.setAttrib(e,"dir","rtl");else ed.dom.setAttrib(e,"dir","");}ed.nodeChanged();});ed.addButton('ltr',{title:'directionality.ltr_desc',cmd:'mceDirectionLTR'});ed.addButton('rtl',{title:'directionality.rtl_desc',cmd:'mceDirectionRTL'});ed.onNodeChange.add(t._nodeChange,t);},getInfo:function(){return{longname:'Directionality',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/directionality',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_nodeChange:function(ed,cm,n){var dom=ed.dom,dir;n=dom.getParent(n,dom.isBlock);if(!n){cm.setDisabled('ltr',1);cm.setDisabled('rtl',1);return;}dir=dom.getAttrib(n,'dir');cm.setActive('ltr',dir=="ltr");cm.setDisabled('ltr',0);cm.setActive('rtl',dir=="rtl");cm.setDisabled('rtl',0);}});tinymce.PluginManager.add('directionality',tinymce.plugins.Directionality);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/directionality/editor_plugin_src.js b/jscripts/tiny_mce/plugins/directionality/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..81818e3
--- /dev/null
@@ -0,0 +1,79 @@
+/**\r
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.Directionality', {\r
+               init : function(ed, url) {\r
+                       var t = this;\r
+\r
+                       t.editor = ed;\r
+\r
+                       ed.addCommand('mceDirectionLTR', function() {\r
+                               var e = ed.dom.getParent(ed.selection.getNode(), ed.dom.isBlock);\r
+\r
+                               if (e) {\r
+                                       if (ed.dom.getAttrib(e, "dir") != "ltr")\r
+                                               ed.dom.setAttrib(e, "dir", "ltr");\r
+                                       else\r
+                                               ed.dom.setAttrib(e, "dir", "");\r
+                               }\r
+\r
+                               ed.nodeChanged();\r
+                       });\r
+\r
+                       ed.addCommand('mceDirectionRTL', function() {\r
+                               var e = ed.dom.getParent(ed.selection.getNode(), ed.dom.isBlock);\r
+\r
+                               if (e) {\r
+                                       if (ed.dom.getAttrib(e, "dir") != "rtl")\r
+                                               ed.dom.setAttrib(e, "dir", "rtl");\r
+                                       else\r
+                                               ed.dom.setAttrib(e, "dir", "");\r
+                               }\r
+\r
+                               ed.nodeChanged();\r
+                       });\r
+\r
+                       ed.addButton('ltr', {title : 'directionality.ltr_desc', cmd : 'mceDirectionLTR'});\r
+                       ed.addButton('rtl', {title : 'directionality.rtl_desc', cmd : 'mceDirectionRTL'});\r
+\r
+                       ed.onNodeChange.add(t._nodeChange, t);\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Directionality',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/directionality',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               },\r
+\r
+               // Private methods\r
+\r
+               _nodeChange : function(ed, cm, n) {\r
+                       var dom = ed.dom, dir;\r
+\r
+                       n = dom.getParent(n, dom.isBlock);\r
+                       if (!n) {\r
+                               cm.setDisabled('ltr', 1);\r
+                               cm.setDisabled('rtl', 1);\r
+                               return;\r
+                       }\r
+\r
+                       dir = dom.getAttrib(n, 'dir');\r
+                       cm.setActive('ltr', dir == "ltr");\r
+                       cm.setDisabled('ltr', 0);\r
+                       cm.setActive('rtl', dir == "rtl");\r
+                       cm.setDisabled('rtl', 0);\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('directionality', tinymce.plugins.Directionality);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/emotions/editor_plugin.js b/jscripts/tiny_mce/plugins/emotions/editor_plugin.js
new file mode 100644 (file)
index 0000000..87fac10
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.EmotionsPlugin',{init:function(ed,url){ed.addCommand('mceEmotion',function(){ed.windowManager.open({file:url+'/emotions.htm',width:250+parseInt(ed.getLang('emotions.delta_width',0)),height:160+parseInt(ed.getLang('emotions.delta_height',0)),inline:1},{plugin_url:url});});ed.addButton('emotions',{title:'emotions.emotions_desc',cmd:'mceEmotion'});},getInfo:function(){return{longname:'Emotions',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/emotions',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('emotions',tinymce.plugins.EmotionsPlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/emotions/editor_plugin_src.js b/jscripts/tiny_mce/plugins/emotions/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..df0d370
--- /dev/null
@@ -0,0 +1,40 @@
+/**\r
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.EmotionsPlugin', {\r
+               init : function(ed, url) {\r
+                       // Register commands\r
+                       ed.addCommand('mceEmotion', function() {\r
+                               ed.windowManager.open({\r
+                                       file : url + '/emotions.htm',\r
+                                       width : 250 + parseInt(ed.getLang('emotions.delta_width', 0)),\r
+                                       height : 160 + parseInt(ed.getLang('emotions.delta_height', 0)),\r
+                                       inline : 1\r
+                               }, {\r
+                                       plugin_url : url\r
+                               });\r
+                       });\r
+\r
+                       // Register buttons\r
+                       ed.addButton('emotions', {title : 'emotions.emotions_desc', cmd : 'mceEmotion'});\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Emotions',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/emotions',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('emotions', tinymce.plugins.EmotionsPlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/emotions/emotions.htm b/jscripts/tiny_mce/plugins/emotions/emotions.htm
new file mode 100644 (file)
index 0000000..ee90ffe
--- /dev/null
@@ -0,0 +1,41 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#emotions_dlg.title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="js/emotions.js?v=307"></script>\r
+       <base target="_self" />\r
+</head>\r
+<body style="display: none">\r
+       <div align="center">\r
+               <div class="title">{#emotions_dlg.title}:<br /><br /></div>\r
+\r
+               <table border="0" cellspacing="0" cellpadding="4">\r
+                 <tr>\r
+                       <td><a href="javascript:EmotionsDialog.insert('smiley-cool.gif','emotions_dlg.cool');"><img src="img/smiley-cool.gif" width="18" height="18" border="0" alt="{#emotions_dlg.cool}" title="{#emotions_dlg.cool}" /></a></td>\r
+                       <td><a href="javascript:EmotionsDialog.insert('smiley-cry.gif','emotions_dlg.cry');"><img src="img/smiley-cry.gif" width="18" height="18" border="0" alt="{#emotions_dlg.cry}" title="{#emotions_dlg.cry}" /></a></td>\r
+                       <td><a href="javascript:EmotionsDialog.insert('smiley-embarassed.gif','emotions_dlg.embarassed');"><img src="img/smiley-embarassed.gif" width="18" height="18" border="0" alt="{#emotions_dlg.embarassed}" title="{#emotions_dlg.embarassed}" /></a></td>\r
+                       <td><a href="javascript:EmotionsDialog.insert('smiley-foot-in-mouth.gif','emotions_dlg.foot_in_mouth');"><img src="img/smiley-foot-in-mouth.gif" width="18" height="18" border="0" alt="{#emotions_dlg.foot_in_mouth}" title="{#emotions_dlg.foot_in_mouth}" /></a></td>\r
+                 </tr>\r
+                 <tr>\r
+                       <td><a href="javascript:EmotionsDialog.insert('smiley-frown.gif','emotions_dlg.frown');"><img src="img/smiley-frown.gif" width="18" height="18" border="0" alt="{#emotions_dlg.frown}" title="{#emotions_dlg.frown}" /></a></td>\r
+                       <td><a href="javascript:EmotionsDialog.insert('smiley-innocent.gif','emotions_dlg.innocent');"><img src="img/smiley-innocent.gif" width="18" height="18" border="0" alt="{#emotions_dlg.innocent}" title="{#emotions_dlg.innocent}" /></a></td>\r
+                       <td><a href="javascript:EmotionsDialog.insert('smiley-kiss.gif','emotions_dlg.kiss');"><img src="img/smiley-kiss.gif" width="18" height="18" border="0" alt="{#emotions_dlg.kiss}" title="{#emotions_dlg.kiss}" /></a></td>\r
+                       <td><a href="javascript:EmotionsDialog.insert('smiley-laughing.gif','emotions_dlg.laughing');"><img src="img/smiley-laughing.gif" width="18" height="18" border="0" alt="{#emotions_dlg.laughing}" title="{#emotions_dlg.laughing}" /></a></td>\r
+                 </tr>\r
+                 <tr>\r
+                       <td><a href="javascript:EmotionsDialog.insert('smiley-money-mouth.gif','emotions_dlg.money_mouth');"><img src="img/smiley-money-mouth.gif" width="18" height="18" border="0" alt="{#emotions_dlg.money_mouth}" title="{#emotions_dlg.money_mouth}" /></a></td>\r
+                       <td><a href="javascript:EmotionsDialog.insert('smiley-sealed.gif','emotions_dlg.sealed');"><img src="img/smiley-sealed.gif" width="18" height="18" border="0" alt="{#emotions_dlg.sealed}" title="{#emotions_dlg.sealed}" /></a></td>\r
+                       <td><a href="javascript:EmotionsDialog.insert('smiley-smile.gif','emotions_dlg.smile');"><img src="img/smiley-smile.gif" width="18" height="18" border="0" alt="{#emotions_dlg.smile}" title="{#emotions_dlg.smile}" /></a></td>\r
+                       <td><a href="javascript:EmotionsDialog.insert('smiley-surprised.gif','emotions_dlg.surprised');"><img src="img/smiley-surprised.gif" width="18" height="18" border="0" alt="{#emotions_dlg.surprised}" title="{#emotions_dlg.surprised}" /></a></td>\r
+                 </tr>\r
+                 <tr>\r
+                       <td><a href="javascript:EmotionsDialog.insert('smiley-tongue-out.gif','emotions_dlg.tongue_out');"><img src="img/smiley-tongue-out.gif" width="18" height="18" border="0" alt="{#emotions_dlg.tongue-out}" title="{#emotions_dlg.tongue_out}" /></a></td>\r
+                       <td><a href="javascript:EmotionsDialog.insert('smiley-undecided.gif','emotions_dlg.undecided');"><img src="img/smiley-undecided.gif" width="18" height="18" border="0" alt="{#emotions_dlg.undecided}" title="{#emotions_dlg.undecided}" /></a></td>\r
+                       <td><a href="javascript:EmotionsDialog.insert('smiley-wink.gif','emotions_dlg.wink');"><img src="img/smiley-wink.gif" width="18" height="18" border="0" alt="{#emotions_dlg.wink}" title="{#emotions_dlg.wink}" /></a></td>\r
+                       <td><a href="javascript:EmotionsDialog.insert('smiley-yell.gif','emotions_dlg.yell');"><img src="img/smiley-yell.gif" width="18" height="18" border="0" alt="{#emotions_dlg.yell}" title="{#emotions_dlg.yell}" /></a></td>\r
+                 </tr>\r
+               </table>\r
+       </div>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/emotions/img/smiley-cool.gif b/jscripts/tiny_mce/plugins/emotions/img/smiley-cool.gif
new file mode 100644 (file)
index 0000000..ba90cc3
Binary files /dev/null and b/jscripts/tiny_mce/plugins/emotions/img/smiley-cool.gif differ
diff --git a/jscripts/tiny_mce/plugins/emotions/img/smiley-cry.gif b/jscripts/tiny_mce/plugins/emotions/img/smiley-cry.gif
new file mode 100644 (file)
index 0000000..74d897a
Binary files /dev/null and b/jscripts/tiny_mce/plugins/emotions/img/smiley-cry.gif differ
diff --git a/jscripts/tiny_mce/plugins/emotions/img/smiley-embarassed.gif b/jscripts/tiny_mce/plugins/emotions/img/smiley-embarassed.gif
new file mode 100644 (file)
index 0000000..963a96b
Binary files /dev/null and b/jscripts/tiny_mce/plugins/emotions/img/smiley-embarassed.gif differ
diff --git a/jscripts/tiny_mce/plugins/emotions/img/smiley-foot-in-mouth.gif b/jscripts/tiny_mce/plugins/emotions/img/smiley-foot-in-mouth.gif
new file mode 100644 (file)
index 0000000..16f68cc
Binary files /dev/null and b/jscripts/tiny_mce/plugins/emotions/img/smiley-foot-in-mouth.gif differ
diff --git a/jscripts/tiny_mce/plugins/emotions/img/smiley-frown.gif b/jscripts/tiny_mce/plugins/emotions/img/smiley-frown.gif
new file mode 100644 (file)
index 0000000..716f55e
Binary files /dev/null and b/jscripts/tiny_mce/plugins/emotions/img/smiley-frown.gif differ
diff --git a/jscripts/tiny_mce/plugins/emotions/img/smiley-innocent.gif b/jscripts/tiny_mce/plugins/emotions/img/smiley-innocent.gif
new file mode 100644 (file)
index 0000000..334d49e
Binary files /dev/null and b/jscripts/tiny_mce/plugins/emotions/img/smiley-innocent.gif differ
diff --git a/jscripts/tiny_mce/plugins/emotions/img/smiley-kiss.gif b/jscripts/tiny_mce/plugins/emotions/img/smiley-kiss.gif
new file mode 100644 (file)
index 0000000..4efd549
Binary files /dev/null and b/jscripts/tiny_mce/plugins/emotions/img/smiley-kiss.gif differ
diff --git a/jscripts/tiny_mce/plugins/emotions/img/smiley-laughing.gif b/jscripts/tiny_mce/plugins/emotions/img/smiley-laughing.gif
new file mode 100644 (file)
index 0000000..1606c11
Binary files /dev/null and b/jscripts/tiny_mce/plugins/emotions/img/smiley-laughing.gif differ
diff --git a/jscripts/tiny_mce/plugins/emotions/img/smiley-money-mouth.gif b/jscripts/tiny_mce/plugins/emotions/img/smiley-money-mouth.gif
new file mode 100644 (file)
index 0000000..ca2451e
Binary files /dev/null and b/jscripts/tiny_mce/plugins/emotions/img/smiley-money-mouth.gif differ
diff --git a/jscripts/tiny_mce/plugins/emotions/img/smiley-sealed.gif b/jscripts/tiny_mce/plugins/emotions/img/smiley-sealed.gif
new file mode 100644 (file)
index 0000000..b33d3cc
Binary files /dev/null and b/jscripts/tiny_mce/plugins/emotions/img/smiley-sealed.gif differ
diff --git a/jscripts/tiny_mce/plugins/emotions/img/smiley-smile.gif b/jscripts/tiny_mce/plugins/emotions/img/smiley-smile.gif
new file mode 100644 (file)
index 0000000..e6a9e60
Binary files /dev/null and b/jscripts/tiny_mce/plugins/emotions/img/smiley-smile.gif differ
diff --git a/jscripts/tiny_mce/plugins/emotions/img/smiley-surprised.gif b/jscripts/tiny_mce/plugins/emotions/img/smiley-surprised.gif
new file mode 100644 (file)
index 0000000..cb99cdd
Binary files /dev/null and b/jscripts/tiny_mce/plugins/emotions/img/smiley-surprised.gif differ
diff --git a/jscripts/tiny_mce/plugins/emotions/img/smiley-tongue-out.gif b/jscripts/tiny_mce/plugins/emotions/img/smiley-tongue-out.gif
new file mode 100644 (file)
index 0000000..2075dc1
Binary files /dev/null and b/jscripts/tiny_mce/plugins/emotions/img/smiley-tongue-out.gif differ
diff --git a/jscripts/tiny_mce/plugins/emotions/img/smiley-undecided.gif b/jscripts/tiny_mce/plugins/emotions/img/smiley-undecided.gif
new file mode 100644 (file)
index 0000000..bef7e25
Binary files /dev/null and b/jscripts/tiny_mce/plugins/emotions/img/smiley-undecided.gif differ
diff --git a/jscripts/tiny_mce/plugins/emotions/img/smiley-wink.gif b/jscripts/tiny_mce/plugins/emotions/img/smiley-wink.gif
new file mode 100644 (file)
index 0000000..9faf1af
Binary files /dev/null and b/jscripts/tiny_mce/plugins/emotions/img/smiley-wink.gif differ
diff --git a/jscripts/tiny_mce/plugins/emotions/img/smiley-yell.gif b/jscripts/tiny_mce/plugins/emotions/img/smiley-yell.gif
new file mode 100644 (file)
index 0000000..648e6e8
Binary files /dev/null and b/jscripts/tiny_mce/plugins/emotions/img/smiley-yell.gif differ
diff --git a/jscripts/tiny_mce/plugins/emotions/js/emotions.js b/jscripts/tiny_mce/plugins/emotions/js/emotions.js
new file mode 100644 (file)
index 0000000..c549367
--- /dev/null
@@ -0,0 +1,22 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+var EmotionsDialog = {\r
+       init : function(ed) {\r
+               tinyMCEPopup.resizeToInnerSize();\r
+       },\r
+\r
+       insert : function(file, title) {\r
+               var ed = tinyMCEPopup.editor, dom = ed.dom;\r
+\r
+               tinyMCEPopup.execCommand('mceInsertContent', false, dom.createHTML('img', {\r
+                       src : tinyMCEPopup.getWindowArg('plugin_url') + '/img/' + file,\r
+                       alt : ed.getLang(title),\r
+                       title : ed.getLang(title),\r
+                       border : 0\r
+               }));\r
+\r
+               tinyMCEPopup.close();\r
+       }\r
+};\r
+\r
+tinyMCEPopup.onInit.add(EmotionsDialog.init, EmotionsDialog);\r
diff --git a/jscripts/tiny_mce/plugins/emotions/langs/en_dlg.js b/jscripts/tiny_mce/plugins/emotions/langs/en_dlg.js
new file mode 100644 (file)
index 0000000..3b57ad9
--- /dev/null
@@ -0,0 +1,20 @@
+tinyMCE.addI18n('en.emotions_dlg',{\r
+title:"Insert emotion",\r
+desc:"Emotions",\r
+cool:"Cool",\r
+cry:"Cry",\r
+embarassed:"Embarassed",\r
+foot_in_mouth:"Foot in mouth",\r
+frown:"Frown",\r
+innocent:"Innocent",\r
+kiss:"Kiss",\r
+laughing:"Laughing",\r
+money_mouth:"Money mouth",\r
+sealed:"Sealed",\r
+smile:"Smile",\r
+surprised:"Surprised",\r
+tongue_out:"Tongue out",\r
+undecided:"Undecided",\r
+wink:"Wink",\r
+yell:"Yell"\r
+});
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/example/dialog.htm b/jscripts/tiny_mce/plugins/example/dialog.htm
new file mode 100644 (file)
index 0000000..7c4247c
--- /dev/null
@@ -0,0 +1,27 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#example_dlg.title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="js/dialog.js?v=307"></script>\r
+</head>\r
+<body>\r
+\r
+<form onsubmit="ExampleDialog.insert();return false;" action="#">\r
+       <p>Here is a example dialog.</p>\r
+       <p>Selected text: <input id="someval" name="someval" type="text" class="text" /></p>\r
+       <p>Custom arg: <input id="somearg" name="somearg" type="text" class="text" /></p>\r
+\r
+       <div class="mceActionPanel">\r
+               <div style="float: left">\r
+                       <input type="button" id="insert" name="insert" value="{#insert}" onclick="ExampleDialog.insert();" />\r
+               </div>\r
+\r
+               <div style="float: right">\r
+                       <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+               </div>\r
+       </div>\r
+</form>\r
+\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/example/editor_plugin.js b/jscripts/tiny_mce/plugins/example/editor_plugin.js
new file mode 100644 (file)
index 0000000..cb7010d
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.PluginManager.requireLangPack('example');tinymce.create('tinymce.plugins.ExamplePlugin',{init:function(ed,url){ed.addCommand('mceExample',function(){ed.windowManager.open({file:url+'/dialog.htm',width:320+parseInt(ed.getLang('example.delta_width',0)),height:120+parseInt(ed.getLang('example.delta_height',0)),inline:1},{plugin_url:url,some_custom_arg:'custom arg'});});ed.addButton('example',{title:'example.desc',cmd:'mceExample',image:url+'/img/example.gif'});ed.onNodeChange.add(function(ed,cm,n){cm.setActive('example',n.nodeName=='IMG');});},createControl:function(n,cm){return null;},getInfo:function(){return{longname:'Example plugin',author:'Some author',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/example',version:"1.0"};}});tinymce.PluginManager.add('example',tinymce.plugins.ExamplePlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/example/editor_plugin_src.js b/jscripts/tiny_mce/plugins/example/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..5050550
--- /dev/null
@@ -0,0 +1,81 @@
+/**\r
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       // Load plugin specific language pack\r
+       tinymce.PluginManager.requireLangPack('example');\r
+\r
+       tinymce.create('tinymce.plugins.ExamplePlugin', {\r
+               /**\r
+                * Initializes the plugin, this will be executed after the plugin has been created.\r
+                * This call is done before the editor instance has finished it's initialization so use the onInit event\r
+                * of the editor instance to intercept that event.\r
+                *\r
+                * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.\r
+                * @param {string} url Absolute URL to where the plugin is located.\r
+                */\r
+               init : function(ed, url) {\r
+                       // Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceExample');\r
+                       ed.addCommand('mceExample', function() {\r
+                               ed.windowManager.open({\r
+                                       file : url + '/dialog.htm',\r
+                                       width : 320 + parseInt(ed.getLang('example.delta_width', 0)),\r
+                                       height : 120 + parseInt(ed.getLang('example.delta_height', 0)),\r
+                                       inline : 1\r
+                               }, {\r
+                                       plugin_url : url, // Plugin absolute URL\r
+                                       some_custom_arg : 'custom arg' // Custom argument\r
+                               });\r
+                       });\r
+\r
+                       // Register example button\r
+                       ed.addButton('example', {\r
+                               title : 'example.desc',\r
+                               cmd : 'mceExample',\r
+                               image : url + '/img/example.gif'\r
+                       });\r
+\r
+                       // Add a node change handler, selects the button in the UI when a image is selected\r
+                       ed.onNodeChange.add(function(ed, cm, n) {\r
+                               cm.setActive('example', n.nodeName == 'IMG');\r
+                       });\r
+               },\r
+\r
+               /**\r
+                * Creates control instances based in the incomming name. This method is normally not\r
+                * needed since the addButton method of the tinymce.Editor class is a more easy way of adding buttons\r
+                * but you sometimes need to create more complex controls like listboxes, split buttons etc then this\r
+                * method can be used to create those.\r
+                *\r
+                * @param {String} n Name of the control to create.\r
+                * @param {tinymce.ControlManager} cm Control manager to use inorder to create new control.\r
+                * @return {tinymce.ui.Control} New control instance or null if no control was created.\r
+                */\r
+               createControl : function(n, cm) {\r
+                       return null;\r
+               },\r
+\r
+               /**\r
+                * Returns information about the plugin as a name/value array.\r
+                * The current keys are longname, author, authorurl, infourl and version.\r
+                *\r
+                * @return {Object} Name/value array containing information about the plugin.\r
+                */\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Example plugin',\r
+                               author : 'Some author',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/example',\r
+                               version : "1.0"\r
+                       };\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('example', tinymce.plugins.ExamplePlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/example/img/example.gif b/jscripts/tiny_mce/plugins/example/img/example.gif
new file mode 100644 (file)
index 0000000..1ab5da4
Binary files /dev/null and b/jscripts/tiny_mce/plugins/example/img/example.gif differ
diff --git a/jscripts/tiny_mce/plugins/example/js/dialog.js b/jscripts/tiny_mce/plugins/example/js/dialog.js
new file mode 100644 (file)
index 0000000..fa83411
--- /dev/null
@@ -0,0 +1,19 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+var ExampleDialog = {\r
+       init : function() {\r
+               var f = document.forms[0];\r
+\r
+               // Get the selected contents as text and place it in the input\r
+               f.someval.value = tinyMCEPopup.editor.selection.getContent({format : 'text'});\r
+               f.somearg.value = tinyMCEPopup.getWindowArg('some_custom_arg');\r
+       },\r
+\r
+       insert : function() {\r
+               // Insert the contents from the input into the document\r
+               tinyMCEPopup.editor.execCommand('mceInsertContent', false, document.forms[0].someval.value);\r
+               tinyMCEPopup.close();\r
+       }\r
+};\r
+\r
+tinyMCEPopup.onInit.add(ExampleDialog.init, ExampleDialog);\r
diff --git a/jscripts/tiny_mce/plugins/example/langs/en.js b/jscripts/tiny_mce/plugins/example/langs/en.js
new file mode 100644 (file)
index 0000000..e0784f8
--- /dev/null
@@ -0,0 +1,3 @@
+tinyMCE.addI18n('en.example',{\r
+       desc : 'This is just a template button'\r
+});\r
diff --git a/jscripts/tiny_mce/plugins/example/langs/en_dlg.js b/jscripts/tiny_mce/plugins/example/langs/en_dlg.js
new file mode 100644 (file)
index 0000000..ebcf948
--- /dev/null
@@ -0,0 +1,3 @@
+tinyMCE.addI18n('en.example_dlg',{\r
+       title : 'This is just a example title'\r
+});\r
diff --git a/jscripts/tiny_mce/plugins/fullpage/css/fullpage.css b/jscripts/tiny_mce/plugins/fullpage/css/fullpage.css
new file mode 100644 (file)
index 0000000..c39c359
--- /dev/null
@@ -0,0 +1,178 @@
+/* Hide the advanced tab */\r
+#advanced_tab {\r
+       display: none;\r
+}\r
+\r
+#metatitle, #metakeywords, #metadescription, #metaauthor, #metacopyright {\r
+       width: 280px;\r
+}\r
+\r
+#doctype, #docencoding {\r
+       width: 200px;\r
+}\r
+\r
+#langcode {\r
+       width: 30px;\r
+}\r
+\r
+#bgimage {\r
+       width: 220px;   \r
+}\r
+\r
+#fontface {\r
+       width: 240px;\r
+}\r
+\r
+#leftmargin, #rightmargin, #topmargin, #bottommargin {\r
+       width: 50px;\r
+}\r
+\r
+.panel_wrapper div.current {\r
+       height: 400px;\r
+}\r
+\r
+#stylesheet, #style {\r
+       width: 240px;\r
+}\r
+\r
+/* Head list classes */\r
+\r
+.headlistwrapper {\r
+       width: 100%;\r
+}\r
+\r
+.addbutton, .removebutton, .moveupbutton, .movedownbutton {\r
+       border-top: 1px solid;\r
+       border-left: 1px solid;\r
+       border-bottom: 1px solid;\r
+       border-right: 1px solid;\r
+       border-color: #F0F0EE;\r
+       cursor: default;\r
+       display: block;\r
+       width: 20px;\r
+       height: 20px;\r
+}\r
+\r
+.addbutton:hover, .removebutton:hover, .moveupbutton:hover, .movedownbutton:hover {\r
+       border: 1px solid #0A246A;\r
+       background-color: #B6BDD2;\r
+}\r
+\r
+.addbutton {\r
+       background-image: url('../images/add.gif');\r
+       float: left;\r
+       margin-right: 3px;\r
+}\r
+\r
+.removebutton {\r
+       background-image: url('../images/remove.gif');\r
+       float: left;\r
+}\r
+\r
+.moveupbutton {\r
+       background-image: url('../images/move_up.gif');\r
+       float: left;\r
+       margin-right: 3px;\r
+}\r
+\r
+.movedownbutton {\r
+       background-image: url('../images/move_down.gif');\r
+       float: left;\r
+}\r
+\r
+.selected {\r
+       border: 1px solid #0A246A;\r
+       background-color: #B6BDD2;\r
+}\r
+\r
+.toolbar {\r
+       width: 100%;\r
+}\r
+\r
+#headlist {\r
+       width: 100%;\r
+       margin-top: 3px;\r
+       font-size: 11px;\r
+}\r
+\r
+#info, #title_element, #meta_element, #script_element, #style_element, #base_element, #link_element, #comment_element, #unknown_element {\r
+       display: none;\r
+}\r
+\r
+#addmenu {\r
+       position: absolute;\r
+       border: 1px solid gray;\r
+       display: none;\r
+       z-index: 100;\r
+       background-color: white;\r
+}\r
+\r
+#addmenu a {\r
+       display: block;\r
+       width: 100%;\r
+       line-height: 20px;\r
+       text-decoration: none;\r
+       background-color: white;\r
+}\r
+\r
+#addmenu a:hover {\r
+       background-color: #B6BDD2;\r
+       color: black;\r
+}\r
+\r
+#addmenu span {\r
+       padding-left: 10px;\r
+       padding-right: 10px;\r
+}\r
+\r
+#updateElementPanel {\r
+       display: none;\r
+}\r
+\r
+#script_element .panel_wrapper div.current {\r
+       height: 108px;\r
+}\r
+\r
+#style_element .panel_wrapper div.current {\r
+       height: 108px;\r
+}\r
+\r
+#link_element  .panel_wrapper div.current {\r
+       height: 140px;\r
+}\r
+\r
+#element_script_value {\r
+       width: 100%;\r
+       height: 100px;\r
+}\r
+\r
+#element_comment_value {\r
+       width: 100%;\r
+       height: 120px;\r
+}\r
+\r
+#element_style_value {\r
+       width: 100%;\r
+       height: 100px;\r
+}\r
+\r
+#element_title, #element_script_src, #element_meta_name, #element_meta_content, #element_base_href, #element_link_href, #element_link_title {\r
+       width: 250px;\r
+}\r
+\r
+.updateElementButton {\r
+       margin-top: 3px;\r
+}\r
+\r
+/* MSIE specific styles */\r
+\r
+* html .addbutton, * html .removebutton, * html .moveupbutton, * html .movedownbutton {\r
+       width: 22px;\r
+       height: 22px;\r
+}\r
+\r
+textarea {\r
+       height: 55px;\r
+}\r
+\r
+.panel_wrapper div.current {height:420px;}
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/fullpage/editor_plugin.js b/jscripts/tiny_mce/plugins/fullpage/editor_plugin.js
new file mode 100644 (file)
index 0000000..fe133a5
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.FullPagePlugin',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mceFullPageProperties',function(){ed.windowManager.open({file:url+'/fullpage.htm',width:430+parseInt(ed.getLang('fullpage.delta_width',0)),height:495+parseInt(ed.getLang('fullpage.delta_height',0)),inline:1},{plugin_url:url,head_html:t.head});});ed.addButton('fullpage',{title:'fullpage.desc',cmd:'mceFullPageProperties'});ed.onBeforeSetContent.add(t._setContent,t);ed.onSetContent.add(t._setBodyAttribs,t);ed.onGetContent.add(t._getContent,t);},getInfo:function(){return{longname:'Fullpage',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullpage',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_setBodyAttribs:function(ed,o){var bdattr,i,len,kv,k,v,t,attr=this.head.match(/body(.*?)>/i);if(attr&&attr[1]){bdattr=attr[1].match(/\s*(\w+\s*=\s*".*?"|\w+\s*=\s*'.*?'|\w+\s*=\s*\w+|\w+)\s*/g);for(i=0,len=bdattr.length;i<len;i++){kv=bdattr[i].split('=');k=kv[0].replace(/\s/,'');v=kv[1];if(v){v=v.replace(/^\s+/,'').replace(/\s+$/,'');t=v.match(/^["'](.*)["']$/);if(t)v=t[1];}else v=k;ed.dom.setAttrib(ed.getBody(),'style',v);}}},_createSerializer:function(){return new tinymce.dom.Serializer({dom:this.editor.dom,apply_source_formatting:true});},_setContent:function(ed,o){var t=this,sp,ep,c=o.content;c=c.replace(/<(\/?)BODY/gi,'<$1body');sp=c.indexOf('<body');if(sp!=-1){sp=c.indexOf('>',sp);t.head=c.substring(0,sp+1);ep=c.indexOf('</body',sp);if(ep==-1)ep=c.indexOf('</body',ep);o.content=c.substring(sp+1,ep);t.foot=c.substring(ep);function low(s){return s.replace(/<\/?[A-Z]+/g,function(a){return a.toLowerCase();})};t.head=low(t.head);t.foot=low(t.foot);}else{t.head='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';t.head+='\n<html>\n<head>\n<title>Untitled document</title>\n</head>\n<body>\n';t.foot='\n</body>\n</html>';}},_getContent:function(ed,o){var t=this;o.content=tinymce.trim(t.head)+'\n'+tinymce.trim(o.content)+'\n'+tinymce.trim(t.foot);}});tinymce.PluginManager.add('fullpage',tinymce.plugins.FullPagePlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/fullpage/editor_plugin_src.js b/jscripts/tiny_mce/plugins/fullpage/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..fb3b229
--- /dev/null
@@ -0,0 +1,122 @@
+/**\r
+ * $Id: editor_plugin_src.js 593 2008-02-13 13:00:12Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.FullPagePlugin', {\r
+               init : function(ed, url) {\r
+                       var t = this;\r
+\r
+                       t.editor = ed;\r
+\r
+                       // Register commands\r
+                       ed.addCommand('mceFullPageProperties', function() {\r
+                               ed.windowManager.open({\r
+                                       file : url + '/fullpage.htm',\r
+                                       width : 430 + parseInt(ed.getLang('fullpage.delta_width', 0)),\r
+                                       height : 495 + parseInt(ed.getLang('fullpage.delta_height', 0)),\r
+                                       inline : 1\r
+                               }, {\r
+                                       plugin_url : url,\r
+                                       head_html : t.head\r
+                               });\r
+                       });\r
+\r
+                       // Register buttons\r
+                       ed.addButton('fullpage', {title : 'fullpage.desc', cmd : 'mceFullPageProperties'});\r
+\r
+                       ed.onBeforeSetContent.add(t._setContent, t);\r
+                       ed.onSetContent.add(t._setBodyAttribs, t);\r
+                       ed.onGetContent.add(t._getContent, t);\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Fullpage',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullpage',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               },\r
+\r
+               // Private plugin internal methods\r
+\r
+               _setBodyAttribs : function(ed, o) {\r
+                       var bdattr, i, len, kv, k, v, t, attr = this.head.match(/body(.*?)>/i);\r
+\r
+                       if (attr && attr[1]) {\r
+                               bdattr = attr[1].match(/\s*(\w+\s*=\s*".*?"|\w+\s*=\s*'.*?'|\w+\s*=\s*\w+|\w+)\s*/g);\r
+\r
+                               for(i = 0, len = bdattr.length; i < len; i++) {\r
+                                       kv = bdattr[i].split('=');\r
+                                       k = kv[0].replace(/\s/,'');\r
+                                       v = kv[1];\r
+\r
+                                       if (v) {\r
+                                               v = v.replace(/^\s+/,'').replace(/\s+$/,'');\r
+                                               t = v.match(/^["'](.*)["']$/);\r
+\r
+                                               if (t)\r
+                                                       v = t[1];\r
+                                       } else\r
+                                               v = k;\r
+\r
+                                       ed.dom.setAttrib(ed.getBody(), 'style', v);\r
+                               }\r
+                       }\r
+               },\r
+\r
+               _createSerializer : function() {\r
+                       return new tinymce.dom.Serializer({\r
+                               dom : this.editor.dom,\r
+                               apply_source_formatting : true\r
+                       });\r
+               },\r
+\r
+               _setContent : function(ed, o) {\r
+                       var t = this, sp, ep, c = o.content;\r
+\r
+                       // Parse out head, body and footer\r
+                       c = c.replace(/<(\/?)BODY/gi, '<$1body');\r
+                       sp = c.indexOf('<body');\r
+\r
+                       if (sp != -1) {\r
+                               sp = c.indexOf('>', sp);\r
+                               t.head = c.substring(0, sp + 1);\r
+\r
+                               ep = c.indexOf('</body', sp);\r
+                               if (ep == -1)\r
+                                       ep = c.indexOf('</body', ep);\r
+\r
+                               o.content = c.substring(sp + 1, ep);\r
+                               t.foot = c.substring(ep);\r
+\r
+                               function low(s) {\r
+                                       return s.replace(/<\/?[A-Z]+/g, function(a) {\r
+                                               return a.toLowerCase();\r
+                                       })\r
+                               };\r
+\r
+                               t.head = low(t.head);\r
+                               t.foot = low(t.foot);\r
+                       } else {\r
+                               t.head = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';\r
+                               t.head += '\n<html>\n<head>\n<title>Untitled document</title>\n</head>\n<body>\n';\r
+                               t.foot = '\n</body>\n</html>';\r
+                       }\r
+               },\r
+\r
+               _getContent : function(ed, o) {\r
+                       var t = this;\r
+\r
+                       o.content = tinymce.trim(t.head) + '\n' + tinymce.trim(o.content) + '\n' + tinymce.trim(t.foot);\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('fullpage', tinymce.plugins.FullPagePlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/fullpage/fullpage.htm b/jscripts/tiny_mce/plugins/fullpage/fullpage.htm
new file mode 100644 (file)
index 0000000..d84d611
--- /dev/null
@@ -0,0 +1,577 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#fullpage_dlg.title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>\r
+       <script type="text/javascript" src="js/fullpage.js?v=307"></script>\r
+       <link href="css/fullpage.css?v=307" rel="stylesheet" type="text/css" />\r
+       <base target="_self" />\r
+</head>\r
+<body id="advlink" style="display: none">\r
+    <form onsubmit="updateAction();return false;" name="fullpage" action="#">\r
+               <div class="tabs">\r
+                       <ul>\r
+                               <li id="meta_tab" class="current"><span><a href="javascript:mcTabs.displayTab('meta_tab','meta_panel');" onmousedown="return false;">{#fullpage_dlg.meta_tab}</a></span></li>\r
+                               <li id="appearance_tab"><span><a href="javascript:mcTabs.displayTab('appearance_tab','appearance_panel');" onmousedown="return false;">{#fullpage_dlg.appearance_tab}</a></span></li>\r
+                               <li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#fullpage_dlg.advanced_tab}</a></span></li>\r
+                       </ul>\r
+               </div>\r
+\r
+               <div class="panel_wrapper">\r
+                       <div id="meta_panel" class="panel current">\r
+                               <fieldset>\r
+                                       <legend>{#fullpage_dlg.meta_props}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td nowrap="nowrap"><label for="metatitle">{#fullpage_dlg.meta_title}</label>&nbsp;</td>\r
+                                                       <td><input type="text" id="metatitle" name="metatitle" value="" class="mceFocus" /></td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td nowrap="nowrap"><label for="metakeywords">{#fullpage_dlg.meta_keywords}</label>&nbsp;</td>\r
+                                                       <td><textarea id="metakeywords" name="metakeywords" rows="4"></textarea></td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td nowrap="nowrap"><label for="metadescription">{#fullpage_dlg.meta_description}</label>&nbsp;</td>\r
+                                                       <td><textarea id="metadescription" name="metadescription" rows="4"></textarea></td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td nowrap="nowrap"><label for="metaauthor">{#fullpage_dlg.author}</label>&nbsp;</td>\r
+                                                       <td><input type="text" id="metaauthor" name="metaauthor" value="" /></td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td nowrap="nowrap"><label for="metacopyright">{#fullpage_dlg.copyright}</label>&nbsp;</td>\r
+                                                       <td><input type="text" id="metacopyright" name="metacopyright" value="" /></td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td nowrap="nowrap"><label for="metarobots">{#fullpage_dlg.meta_robots}</label>&nbsp;</td>\r
+                                                       <td>\r
+                                                               <select id="metarobots" name="metarobots">\r
+                                                                                       <option value="">{#not_set}</option> \r
+                                                                                       <option value="index,follow">{#fullpage_dlg.meta_index_follow}</option>\r
+                                                                                       <option value="index,nofollow">{#fullpage_dlg.meta_index_nofollow}</option>\r
+                                                                                       <option value="noindex,follow">{#fullpage_dlg.meta_noindex_follow}</option>\r
+                                                                                       <option value="noindex,nofollow">{#fullpage_dlg.meta_noindex_nofollow}</option>\r
+                                                               </select>\r
+                                                       </td>\r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+\r
+                               <fieldset>\r
+                                       <legend>{#fullpage_dlg.langprops}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="docencoding">{#fullpage_dlg.encoding}</label></td> \r
+                                                       <td>\r
+                                                               <select id="docencoding" name="docencoding"> \r
+                                                                               <option value="">{#not_set}</option>\r
+                                                               </select>\r
+                                                       </td> \r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td nowrap="nowrap"><label for="doctypes">{#fullpage_dlg.doctypes}</label>&nbsp;</td>\r
+                                                       <td>\r
+                                                               <select id="doctypes" name="doctypes">\r
+                                                                               <option value="">{#not_set}</option>\r
+                                                               </select>\r
+                                                       </td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td nowrap="nowrap"><label for="langcode">{#fullpage_dlg.langcode}</label>&nbsp;</td>\r
+                                                       <td><input type="text" id="langcode" name="langcode" value="" /></td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="langdir">{#fullpage_dlg.langdir}</label></td> \r
+                                                       <td>\r
+                                                               <select id="langdir" name="langdir"> \r
+                                                                               <option value="">{#not_set}</option> \r
+                                                                               <option value="ltr">{#fullpage_dlg.ltr}</option> \r
+                                                                               <option value="rtl">{#fullpage_dlg.rtl}</option> \r
+                                                               </select>\r
+                                                       </td> \r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td nowrap="nowrap"><label for="xml_pi">{#fullpage_dlg.xml_pi}</label>&nbsp;</td>\r
+                                                       <td><input type="checkbox" id="xml_pi" name="xml_pi" class="checkbox" /></td>\r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+                       </div>\r
+\r
+                       <div id="appearance_panel" class="panel">\r
+                               <fieldset>\r
+                                       <legend>{#fullpage_dlg.appearance_textprops}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="fontface">{#fullpage_dlg.fontface}</label></td> \r
+                                                       <td>\r
+                                                               <select id="fontface" name="fontface" onchange="changedStyleField(this);">\r
+                                                                               <option value="">{#not_set}</option>\r
+                                                               </select>\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="fontsize">{#fullpage_dlg.fontsize}</label></td> \r
+                                                       <td>\r
+                                                               <select id="fontsize" name="fontsize" onchange="changedStyleField(this);">\r
+                                                                               <option value="">{#not_set}</option>\r
+                                                               </select>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="textcolor">{#fullpage_dlg.textcolor}</label></td> \r
+                                                       <td>\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="textcolor" name="textcolor" type="text" value="" size="9" onchange="updateColor('textcolor_pick','textcolor');changedStyleField(this);" /></td>\r
+                                                                               <td id="textcolor_pickcontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+\r
+                               <fieldset>\r
+                                       <legend>{#fullpage_dlg.appearance_bgprops}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="bgimage">{#fullpage_dlg.bgimage}</label></td> \r
+                                                       <td>\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="bgimage" name="bgimage" type="text" value="" onchange="changedStyleField(this);" /></td>\r
+                                                                               <td id="bgimage_pickcontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="bgcolor">{#fullpage_dlg.bgcolor}</label></td> \r
+                                                       <td>\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="bgcolor" name="bgcolor" type="text" value="" size="9" onchange="updateColor('bgcolor_pick','bgcolor');changedStyleField(this);" /></td>\r
+                                                                               <td id="bgcolor_pickcontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td> \r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+\r
+                               <fieldset>\r
+                                       <legend>{#fullpage_dlg.appearance_marginprops}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="leftmargin">{#fullpage_dlg.left_margin}</label></td> \r
+                                                       <td><input id="leftmargin" name="leftmargin" type="text" value="" onchange="changedStyleField(this);" /></td>\r
+                                                       <td class="column1"><label for="rightmargin">{#fullpage_dlg.right_margin}</label></td> \r
+                                                       <td><input id="rightmargin" name="rightmargin" type="text" value="" onchange="changedStyleField(this);" /></td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="topmargin">{#fullpage_dlg.top_margin}</label></td> \r
+                                                       <td><input id="topmargin" name="topmargin" type="text" value="" onchange="changedStyleField(this);" /></td>\r
+                                                       <td class="column1"><label for="bottommargin">{#fullpage_dlg.bottom_margin}</label></td> \r
+                                                       <td><input id="bottommargin" name="bottommargin" type="text" value="" onchange="changedStyleField(this);" /></td>\r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+\r
+                               <fieldset>\r
+                                       <legend>{#fullpage_dlg.appearance_linkprops}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="link_color">{#fullpage_dlg.link_color}</label></td> \r
+                                                       <td>\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="link_color" name="link_color" type="text" value="" size="9" onchange="updateColor('link_color_pick','link_color');changedStyleField(this);" /></td>\r
+                                                                               <td id="link_color_pickcontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td class="column1"><label for="visited_color">{#fullpage_dlg.visited_color}</label></td> \r
+                                                       <td>\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="visited_color" name="visited_color" type="text" value="" size="9" onchange="updateColor('visited_color_pick','visited_color');changedStyleField(this);" /></td>\r
+                                                                               <td id="visited_color_pickcontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="active_color">{#fullpage_dlg.active_color}</label></td> \r
+                                                       <td>\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="active_color" name="active_color" type="text" value="" size="9" onchange="updateColor('active_color_pick','active_color');changedStyleField(this);" /></td>\r
+                                                                               <td id="active_color_pickcontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td>&nbsp;</td>\r
+                                                       <td>&nbsp;</td>\r
+\r
+<!--                                                   <td class="column1"><label for="hover_color">{#fullpage_dlg.hover_color}</label></td> \r
+                                                       <td>\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="hover_color" name="hover_color" type="text" value="" size="9" onchange="changedStyleField(this);" /></td>\r
+                                                                               <td id="hover_color_pickcontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td> -->\r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+\r
+                               <fieldset>\r
+                                       <legend>{#fullpage_dlg.appearance_style}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="stylesheet">{#fullpage_dlg.stylesheet}</label></td> \r
+                                                       <td><table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="stylesheet" name="stylesheet" type="text" value="" /></td>\r
+                                                                               <td id="stylesheet_browsercontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table></td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="style">{#fullpage_dlg.style}</label></td> \r
+                                                       <td><input id="style" name="style" type="text" value="" onchange="changedStyleField(this);" /></td>\r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+                       </div>\r
+\r
+                       <div id="advanced_panel" class="panel">\r
+                               <div id="addmenu">\r
+                                       <table border="0" cellpadding="0" cellspacing="0">\r
+                                               <tr><td><a href="javascript:addHeadElm('title');" onmousedown="return false;"><span>{#fullpage_dlg.add_title}</span></a></td></tr>\r
+                                               <tr><td><a href="javascript:addHeadElm('meta');" onmousedown="return false;"><span>{#fullpage_dlg.add_meta}</span></a></td></tr>\r
+                                               <tr><td><a href="javascript:addHeadElm('script');" onmousedown="return false;"><span>{#fullpage_dlg.add_script}</span></a></td></tr>\r
+                                               <tr><td><a href="javascript:addHeadElm('style');" onmousedown="return false;"><span>{#fullpage_dlg.add_style}</span></a></td></tr>\r
+                                               <tr><td><a href="javascript:addHeadElm('link');" onmousedown="return false;"><span>{#fullpage_dlg.add_link}</span></a></td></tr>\r
+                                               <tr><td><a href="javascript:addHeadElm('base');" onmousedown="return false;"><span>{#fullpage_dlg.add_base}</span></a></td></tr>\r
+                                               <tr><td><a href="javascript:addHeadElm('comment');" onmousedown="return false;"><span>{#fullpage_dlg.add_comment}</span></a></td></tr>\r
+                                       </table>\r
+                               </div>\r
+\r
+                               <fieldset>\r
+                                       <legend>{#fullpage_dlg.head_elements}</legend>\r
+\r
+                                       <div class="headlistwrapper">\r
+                                               <div class="toolbar">\r
+                                                       <div style="float: left">\r
+                                                               <a id="addbutton" href="javascript:showAddMenu();" onmousedown="return false;" class="addbutton" title="{#fullpage_dlg.add}"></a>\r
+                                                               <a href="#" onmousedown="return false;" class="removebutton" title="{#fullpage_dlg.remove}"></a>\r
+                                                       </div>\r
+                                                       <div style="float: right">\r
+                                                               <a href="#" onmousedown="return false;" class="moveupbutton" title="{#fullpage_dlg.moveup}"></a>\r
+                                                               <a href="#" onmousedown="return false;" class="movedownbutton" title="{#fullpage_dlg.movedown}"></a>\r
+                                                       </div>\r
+                                                       <br style="clear: both" />\r
+                                               </div>\r
+                                               <select id="headlist" size="26" onchange="updateHeadElm(this.options[this.selectedIndex].value);">\r
+                                                       <option value="title_0">&lt;title&gt;Some title bla bla bla&lt;/title&gt;</option>\r
+                                                       <option value="meta_1">&lt;meta name="keywords"&gt;Some bla bla bla&lt;/meta&gt;</option>\r
+                                                       <option value="meta_2">&lt;meta name="description"&gt;Some bla bla bla bla bla bla bla bla bla&lt;/meta&gt;</option>\r
+                                                       <option value="script_3">&lt;script language=&quot;javascript&quot;&gt;...&lt;/script&gt;</option>\r
+                                                       <option value="style_4">&lt;style&gt;...&lt;/style&gt;</option>\r
+                                                       <option value="base_5">&lt;base href="." /&gt;</option>\r
+                                                       <option value="comment_6">&lt;!-- ... --&gt;</option>\r
+                                                       <option value="link_7">&lt;link href="." /&gt;</option>\r
+                                               </select>\r
+                                       </div>\r
+                               </fieldset>\r
+\r
+                               <fieldset id="meta_element">\r
+                                       <legend>{#fullpage_dlg.meta_element}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="element_meta_type">{#fullpage_dlg.type}</label></td> \r
+                                                       <td><select id="element_meta_type">\r
+                                                                               <option value="name">name</option>\r
+                                                                               <option value="http-equiv">http-equiv</option>\r
+                                                               </select></td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="element_meta_name">{#fullpage_dlg.name}</label></td> \r
+                                                       <td><input id="element_meta_name" name="element_meta_name" type="text" value="" /></td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="element_meta_content">{#fullpage_dlg.content}</label></td> \r
+                                                       <td><input id="element_meta_content" name="element_meta_content" type="text" value="" /></td>\r
+                                               </tr>\r
+                                       </table>\r
+\r
+                                       <input type="button" id="meta_updateelement" class="updateElementButton" name="update" value="{#update}" onclick="updateElement();" />\r
+                               </fieldset>\r
+\r
+                               <fieldset id="title_element">\r
+                                       <legend>{#fullpage_dlg.title_element}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="element_title">{#fullpage_dlg.meta_title}</label></td> \r
+                                                       <td><input id="element_title" name="element_title" type="text" value="" /></td>\r
+                                               </tr>\r
+                                       </table>\r
+\r
+                                       <input type="button" id="title_updateelement" class="updateElementButton" name="update" value="{#update}" onclick="updateElement();" />\r
+                               </fieldset>\r
+\r
+                               <fieldset id="script_element">\r
+                                       <legend>{#fullpage_dlg.script_element}</legend>\r
+\r
+                                       <div class="tabs">\r
+                                               <ul>\r
+                                                       <li id="script_props_tab" class="current"><span><a href="javascript:mcTabs.displayTab('script_props_tab','script_props_panel');" onmousedown="return false;">{#fullpage_dlg.properties}</a></span></li>\r
+                                                       <li id="script_value_tab"><span><a href="javascript:mcTabs.displayTab('script_value_tab','script_value_panel');" onmousedown="return false;">{#fullpage_dlg.value}</a></span></li>\r
+                                               </ul>\r
+                                       </div>\r
+\r
+                                       <br style="clear: both" />\r
+\r
+                                       <div class="panel_wrapper">\r
+                                               <div id="script_props_panel" class="panel current">\r
+                                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                                               <tr>\r
+                                                                       <td class="column1"><label for="element_script_type">{#fullpage_dlg.type}</label></td> \r
+                                                                       <td><select id="element_script_type">\r
+                                                                               <option value="text/javascript">text/javascript</option>\r
+                                                                               <option value="text/jscript">text/jscript</option>\r
+                                                                               <option value="text/vbscript">text/vbscript</option>\r
+                                                                               <option value="text/vbs">text/vbs</option>\r
+                                                                               <option value="text/ecmascript">text/ecmascript</option>\r
+                                                                               <option value="text/xml">text/xml</option>\r
+                                                                       </select></td>\r
+                                                               </tr>\r
+                                                               <tr>\r
+                                                                       <td class="column1"><label for="element_script_src">{#fullpage_dlg.src}</label></td> \r
+                                                                       <td><table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="element_script_src" name="element_script_src" type="text" value="" /></td>\r
+                                                                               <td id="script_src_pickcontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table></td>\r
+                                                               </tr>\r
+                                                               <tr>\r
+                                                                       <td class="column1"><label for="element_script_charset">{#fullpage_dlg.charset}</label></td> \r
+                                                                       <td><select id="element_script_charset"><option value="">{#not_set}</option></select></td>\r
+                                                               </tr>\r
+                                                               <tr>\r
+                                                                       <td class="column1"><label for="element_script_defer">{#fullpage_dlg.defer}</label></td> \r
+                                                                       <td><input type="checkbox" id="element_script_defer" name="element_script_defer" class="checkbox" /></td>\r
+                                                               </tr>\r
+                                                       </table>\r
+                                               </div>\r
+\r
+                                               <div id="script_value_panel" class="panel">\r
+                                                       <textarea id="element_script_value"></textarea>\r
+                                               </div>\r
+                                       </div>\r
+\r
+                                       <input type="button" id="script_updateelement" class="updateElementButton" name="update" value="{#update}" onclick="updateElement();" />\r
+                               </fieldset>\r
+\r
+                               <fieldset id="style_element">\r
+                                       <legend>{#fullpage_dlg.style_element}</legend>\r
+\r
+                                       <div class="tabs">\r
+                                               <ul>\r
+                                                       <li id="style_props_tab" class="current"><span><a href="javascript:mcTabs.displayTab('style_props_tab','style_props_panel');" onmousedown="return false;">{#fullpage_dlg.properties}</a></span></li>\r
+                                                       <li id="style_value_tab"><span><a href="javascript:mcTabs.displayTab('style_value_tab','style_value_panel');" onmousedown="return false;">{#fullpage_dlg.value}</a></span></li>\r
+                                               </ul>\r
+                                       </div>\r
+\r
+                                       <br style="clear: both" />\r
+\r
+                                       <div class="panel_wrapper">\r
+                                               <div id="style_props_panel" class="panel current">\r
+                                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                                               <tr>\r
+                                                                       <td class="column1"><label for="element_style_type">{#fullpage_dlg.type}</label></td> \r
+                                                                       <td><select id="element_style_type">\r
+                                                                               <option value="text/css">text/css</option>\r
+                                                                       </select></td>\r
+                                                               </tr>\r
+                                                               <tr>\r
+                                                                       <td class="column1"><label for="element_style_media">{#fullpage_dlg.media}</label></td> \r
+                                                                       <td><select id="element_style_media"></select></td>\r
+                                                               </tr>\r
+                                                       </table>\r
+                                               </div>\r
+\r
+                                               <div id="style_value_panel" class="panel">\r
+                                                       <textarea id="element_style_value"></textarea>\r
+                                               </div>\r
+                                       </div>\r
+\r
+                                       <input type="button" id="style_updateelement" class="updateElementButton" name="update" value="{#update}" onclick="updateElement();" />\r
+                               </fieldset>\r
+\r
+                               <fieldset id="base_element">\r
+                                       <legend>{#fullpage_dlg.base_element}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="element_base_href">{#fullpage_dlg.href}</label></td> \r
+                                                       <td><input id="element_base_href" name="element_base_href" type="text" value="" /></td>\r
+                                               </tr>\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="element_base_target">{#fullpage_dlg.target}</label></td> \r
+                                                       <td><input id="element_base_target" name="element_base_target" type="text" value="" /></td>\r
+                                               </tr>\r
+                                       </table>\r
+\r
+                                       <input type="button" id="base_updateelement" class="updateElementButton" name="update" value="{#update}" onclick="updateElement();" />\r
+                               </fieldset>\r
+\r
+                               <fieldset id="link_element">\r
+                                       <legend>{#fullpage_dlg.link_element}</legend>\r
+\r
+                                       <div class="tabs">\r
+                                               <ul>\r
+                                                       <li id="link_general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('link_general_tab','link_general_panel');" onmousedown="return false;">{#fullpage_dlg.general_props}</a></span></li>\r
+                                                       <li id="link_advanced_tab"><span><a href="javascript:mcTabs.displayTab('link_advanced_tab','link_advanced_panel');" onmousedown="return false;">{#fullpage_dlg.advanced_props}</a></span></li>\r
+                                               </ul>\r
+                                       </div>\r
+\r
+                                       <br style="clear: both" />\r
+\r
+                                       <div class="panel_wrapper">\r
+                                               <div id="link_general_panel" class="panel current">\r
+                                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                                               <tr>\r
+                                                                       <td class="column1"><label for="element_link_href">{#fullpage_dlg.href}</label></td> \r
+                                                                       <td><table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="element_link_href" name="element_link_href" type="text" value="" /></td>\r
+                                                                               <td id="link_href_pickcontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table></td>\r
+                                                               </tr>\r
+                                                               <tr>\r
+                                                                       <td class="column1"><label for="element_link_title">{#fullpage_dlg.meta_title}</label></td> \r
+                                                                       <td><input id="element_link_title" name="element_link_title" type="text" value="" /></td>\r
+                                                               </tr>\r
+                                                               <tr>\r
+                                                                       <td class="column1"><label for="element_link_type">{#fullpage_dlg.type}</label></td> \r
+                                                                       <td><select id="element_link_type" name="element_link_type">\r
+                                                                               <option value="text/css">text/css</option>\r
+                                                                               <option value="text/javascript">text/javascript</option>\r
+                                                                       </select></td>\r
+                                                               </tr>\r
+                                                               <tr>\r
+                                                                       <td class="column1"><label for="element_link_media">{#fullpage_dlg.media}</label></td> \r
+                                                                       <td><select id="element_link_media" name="element_link_media"></select></td>\r
+                                                               </tr>\r
+                                                               <tr>\r
+                                                                       <td><label for="element_style_rel">{#fullpage_dlg.rel}</label></td>\r
+                                                                       <td><select id="element_style_rel" name="element_style_rel"> \r
+                                                                                       <option value="">{#not_set}</option> \r
+                                                                                       <option value="stylesheet">Stylesheet</option>\r
+                                                                                       <option value="alternate">Alternate</option>\r
+                                                                                       <option value="designates">Designates</option>\r
+                                                                                       <option value="start">Start</option>\r
+                                                                                       <option value="next">Next</option>\r
+                                                                                       <option value="prev">Prev</option>\r
+                                                                                       <option value="contents">Contents</option>\r
+                                                                                       <option value="index">Index</option>\r
+                                                                                       <option value="glossary">Glossary</option>\r
+                                                                                       <option value="copyright">Copyright</option>\r
+                                                                                       <option value="chapter">Chapter</option>\r
+                                                                                       <option value="subsection">Subsection</option>\r
+                                                                                       <option value="appendix">Appendix</option>\r
+                                                                                       <option value="help">Help</option>\r
+                                                                                       <option value="bookmark">Bookmark</option>\r
+                                                                               </select> \r
+                                                                       </td>\r
+                                                               </tr>\r
+                                                       </table>\r
+                                               </div>\r
+\r
+                                               <div id="link_advanced_panel" class="panel">\r
+                                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                                               <tr>\r
+                                                                       <td class="column1"><label for="element_link_charset">{#fullpage_dlg.charset}</label></td> \r
+                                                                       <td><select id="element_link_charset"><option value="">{#not_set}</option></select></td>\r
+                                                               </tr>\r
+                                                               <tr>\r
+                                                                       <td class="column1"><label for="element_link_hreflang">{#fullpage_dlg.hreflang}</label></td> \r
+                                                                       <td><input id="element_link_hreflang" name="element_link_hreflang" type="text" value="" /></td>\r
+                                                               </tr>\r
+                                                               <tr>\r
+                                                                       <td class="column1"><label for="element_link_target">{#fullpage_dlg.target}</label></td> \r
+                                                                       <td><input id="element_link_target" name="element_link_target" type="text" value="" /></td>\r
+                                                               </tr>\r
+                                                               <tr>\r
+                                                                       <td><label for="element_style_rev">{#fullpage_dlg.rev}</label></td>\r
+                                                                       <td><select id="element_style_rev" name="element_style_rev"> \r
+                                                                                       <option value="">{#not_set}</option> \r
+                                                                                       <option value="alternate">Alternate</option> \r
+                                                                                       <option value="designates">Designates</option> \r
+                                                                                       <option value="stylesheet">Stylesheet</option> \r
+                                                                                       <option value="start">Start</option> \r
+                                                                                       <option value="next">Next</option> \r
+                                                                                       <option value="prev">Prev</option> \r
+                                                                                       <option value="contents">Contents</option> \r
+                                                                                       <option value="index">Index</option> \r
+                                                                                       <option value="glossary">Glossary</option> \r
+                                                                                       <option value="copyright">Copyright</option> \r
+                                                                                       <option value="chapter">Chapter</option> \r
+                                                                                       <option value="subsection">Subsection</option> \r
+                                                                                       <option value="appendix">Appendix</option> \r
+                                                                                       <option value="help">Help</option> \r
+                                                                                       <option value="bookmark">Bookmark</option> \r
+                                                                               </select> \r
+                                                                       </td>\r
+                                                               </tr>\r
+                                                       </table>\r
+                                               </div>\r
+                                       </div>\r
+\r
+                                       <input type="button" id="link_updateelement" class="updateElementButton" name="update" value="{#update}" onclick="updateElement();" />\r
+                               </fieldset>\r
+\r
+                               <fieldset id="comment_element">\r
+                                       <legend>{#fullpage_dlg.comment_element}</legend>\r
+\r
+                                       <textarea id="element_comment_value"></textarea>\r
+\r
+                                       <input type="button" id="comment_updateelement" class="updateElementButton" name="update" value="{#update}" onclick="updateElement();" />\r
+                               </fieldset>\r
+                       </div>\r
+               </div>\r
+\r
+               <div class="mceActionPanel">\r
+                       <div style="float: left">\r
+                               <input type="submit" id="insert" name="update" value="{#update}" />\r
+                       </div>\r
+\r
+                       <div style="float: right">\r
+                               <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+                       </div>\r
+               </div>\r
+    </form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/fullpage/js/fullpage.js b/jscripts/tiny_mce/plugins/fullpage/js/fullpage.js
new file mode 100644 (file)
index 0000000..b22d288
--- /dev/null
@@ -0,0 +1,462 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+var doc;\r
+\r
+var defaultDocTypes = \r
+       'XHTML 1.0 Transitional=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">,' +\r
+       'XHTML 1.0 Frameset=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">,' +\r
+       'XHTML 1.0 Strict=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">,' +\r
+       'XHTML 1.1=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">,' +\r
+       'HTML 4.01 Transitional=<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">,' +\r
+       'HTML 4.01 Strict=<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">,' +\r
+       'HTML 4.01 Frameset=<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">';\r
+\r
+var defaultEncodings = \r
+       'Western european (iso-8859-1)=iso-8859-1,' +\r
+       'Central European (iso-8859-2)=iso-8859-2,' +\r
+       'Unicode (UTF-8)=utf-8,' +\r
+       'Chinese traditional (Big5)=big5,' +\r
+       'Cyrillic (iso-8859-5)=iso-8859-5,' +\r
+       'Japanese (iso-2022-jp)=iso-2022-jp,' +\r
+       'Greek (iso-8859-7)=iso-8859-7,' +\r
+       'Korean (iso-2022-kr)=iso-2022-kr,' +\r
+       'ASCII (us-ascii)=us-ascii';\r
+\r
+var defaultMediaTypes = \r
+       'all=all,' +\r
+       'screen=screen,' +\r
+       'print=print,' +\r
+       'tty=tty,' +\r
+       'tv=tv,' +\r
+       'projection=projection,' +\r
+       'handheld=handheld,' +\r
+       'braille=braille,' +\r
+       'aural=aural';\r
+\r
+var defaultFontNames = 'Arial=arial,helvetica,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,times new roman,times,serif;Tahoma=tahoma,arial,helvetica,sans-serif;Times New Roman=times new roman,times,serif;Verdana=verdana,arial,helvetica,sans-serif;Impact=impact;WingDings=wingdings';\r
+var defaultFontSizes = '10px,11px,12px,13px,14px,15px,16px';\r
+\r
+function init() {\r
+       var f = document.forms['fullpage'], el = f.elements, e, i, p, doctypes, encodings, mediaTypes, fonts, ed = tinyMCEPopup.editor, dom = tinyMCEPopup.dom, style;\r
+\r
+       // Setup doctype select box\r
+       doctypes = ed.getParam("fullpage_doctypes", defaultDocTypes).split(',');\r
+       for (i=0; i<doctypes.length; i++) {\r
+               p = doctypes[i].split('=');\r
+\r
+               if (p.length > 1)\r
+                       addSelectValue(f, 'doctypes', p[0], p[1]);\r
+       }\r
+\r
+       // Setup fonts select box\r
+       fonts = ed.getParam("fullpage_fonts", defaultFontNames).split(';');\r
+       for (i=0; i<fonts.length; i++) {\r
+               p = fonts[i].split('=');\r
+\r
+               if (p.length > 1)\r
+                       addSelectValue(f, 'fontface', p[0], p[1]);\r
+       }\r
+\r
+       // Setup fontsize select box\r
+       fonts = ed.getParam("fullpage_fontsizes", defaultFontSizes).split(',');\r
+       for (i=0; i<fonts.length; i++)\r
+               addSelectValue(f, 'fontsize', fonts[i], fonts[i]);\r
+\r
+       // Setup mediatype select boxs\r
+       mediaTypes = ed.getParam("fullpage_media_types", defaultMediaTypes).split(',');\r
+       for (i=0; i<mediaTypes.length; i++) {\r
+               p = mediaTypes[i].split('=');\r
+\r
+               if (p.length > 1) {\r
+                       addSelectValue(f, 'element_style_media', p[0], p[1]);\r
+                       addSelectValue(f, 'element_link_media', p[0], p[1]);\r
+               }\r
+       }\r
+\r
+       // Setup encodings select box\r
+       encodings = ed.getParam("fullpage_encodings", defaultEncodings).split(',');\r
+       for (i=0; i<encodings.length; i++) {\r
+               p = encodings[i].split('=');\r
+\r
+               if (p.length > 1) {\r
+                       addSelectValue(f, 'docencoding', p[0], p[1]);\r
+                       addSelectValue(f, 'element_script_charset', p[0], p[1]);\r
+                       addSelectValue(f, 'element_link_charset', p[0], p[1]);\r
+               }\r
+       }\r
+\r
+       document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor');\r
+       document.getElementById('link_color_pickcontainer').innerHTML = getColorPickerHTML('link_color_pick','link_color');\r
+       //document.getElementById('hover_color_pickcontainer').innerHTML = getColorPickerHTML('hover_color_pick','hover_color');\r
+       document.getElementById('visited_color_pickcontainer').innerHTML = getColorPickerHTML('visited_color_pick','visited_color');\r
+       document.getElementById('active_color_pickcontainer').innerHTML = getColorPickerHTML('active_color_pick','active_color');\r
+       document.getElementById('textcolor_pickcontainer').innerHTML = getColorPickerHTML('textcolor_pick','textcolor');\r
+       document.getElementById('stylesheet_browsercontainer').innerHTML = getBrowserHTML('stylesheetbrowser','stylesheet','file','fullpage');\r
+       document.getElementById('link_href_pickcontainer').innerHTML = getBrowserHTML('link_href_browser','element_link_href','file','fullpage');\r
+       document.getElementById('script_src_pickcontainer').innerHTML = getBrowserHTML('script_src_browser','element_script_src','file','fullpage');\r
+       document.getElementById('bgimage_pickcontainer').innerHTML = getBrowserHTML('bgimage_browser','bgimage','image','fullpage');\r
+\r
+       // Resize some elements\r
+       if (isVisible('stylesheetbrowser'))\r
+               document.getElementById('stylesheet').style.width = '220px';\r
+\r
+       if (isVisible('link_href_browser'))\r
+               document.getElementById('element_link_href').style.width = '230px';\r
+\r
+       if (isVisible('bgimage_browser'))\r
+               document.getElementById('bgimage').style.width = '210px';\r
+\r
+       // Add iframe\r
+       dom.add(document.body, 'iframe', {id : 'documentIframe', src : 'javascript:""', style : {display : 'none'}});\r
+       doc = dom.get('documentIframe').contentWindow.document;\r
+       h = tinyMCEPopup.getWindowArg('head_html');\r
+\r
+       // Preprocess the HTML disable scripts and urls\r
+       h = h.replace(/<script>/gi, '<script type="text/javascript">');\r
+       h = h.replace(/type=([\"\'])?/gi, 'type=$1-mce-');\r
+       h = h.replace(/(src=|href=)/g, 'mce_$1');\r
+\r
+       // Write in the content in the iframe\r
+       doc.write(h + '</body></html>');\r
+       doc.close();\r
+\r
+       // Parse xml and doctype\r
+       xmlVer = getReItem(/<\?\s*?xml.*?version\s*?=\s*?"(.*?)".*?\?>/gi, h, 1);\r
+       xmlEnc = getReItem(/<\?\s*?xml.*?encoding\s*?=\s*?"(.*?)".*?\?>/gi, h, 1);\r
+       docType = getReItem(/<\!DOCTYPE.*?>/gi, h, 0);\r
+       f.langcode.value = getReItem(/lang="(.*?)"/gi, h, 1);\r
+\r
+       // Parse title\r
+       if (e = doc.getElementsByTagName('title')[0])\r
+               el.metatitle.value = e.textContent || e.text;\r
+\r
+       // Parse meta\r
+       tinymce.each(doc.getElementsByTagName('meta'), function(n) {\r
+               var na = (n.getAttribute('name', 2) || '').toLowerCase(), va = n.getAttribute('content', 2), eq = n.getAttribute('httpEquiv', 2) || '';\r
+\r
+               e = el['meta' + na];\r
+\r
+               if (na == 'robots') {\r
+                       selectByValue(f, 'metarobots', tinymce.trim(va), true, true);\r
+                       return;\r
+               }\r
+\r
+               switch (eq.toLowerCase()) {\r
+                       case "content-type":\r
+                               tmp = getReItem(/charset\s*=\s*(.*)\s*/gi, value, 1);\r
+\r
+                               // Override XML encoding\r
+                               if (tmp != "")\r
+                                       xmlEnc = tmp;\r
+\r
+                               return;\r
+               }\r
+\r
+               if (e)\r
+                       e.value = va;\r
+       });\r
+\r
+       selectByValue(f, 'doctypes', docType, true, true);\r
+       selectByValue(f, 'docencoding', xmlEnc, true, true);\r
+       selectByValue(f, 'langdir', doc.body.getAttribute('dir', 2) || '', true, true);\r
+\r
+       if (xmlVer != '')\r
+               el.xml_pi.checked = true;\r
+\r
+       // Parse appearance\r
+\r
+       // Parse primary stylesheet\r
+       tinymce.each(doc.getElementsByTagName("link"), function(l) {\r
+               var m = l.getAttribute('media', 2) || '', t = l.getAttribute('type', 2) || '';\r
+\r
+               if (t == "-mce-text/css" && (m == "" || m == "screen" || m == "all") && (l.getAttribute('rel', 2) || '') == "stylesheet") {\r
+                       f.stylesheet.value = l.getAttribute('mce_href', 2) || '';\r
+                       return false;\r
+               }\r
+       });\r
+\r
+       // Get from style elements\r
+       tinymce.each(doc.getElementsByTagName("style"), function(st) {\r
+               var tmp = parseStyleElement(st);\r
+\r
+               for (x=0; x<tmp.length; x++) {\r
+                       if (tmp[x].rule.indexOf('a:visited') != -1 && tmp[x].data['color'])\r
+                               f.visited_color.value = tmp[x].data['color'];\r
+\r
+                       if (tmp[x].rule.indexOf('a:link') != -1 && tmp[x].data['color'])\r
+                               f.link_color.value = tmp[x].data['color'];\r
+\r
+                       if (tmp[x].rule.indexOf('a:active') != -1 && tmp[x].data['color'])\r
+                               f.active_color.value = tmp[x].data['color'];\r
+               }\r
+       });\r
+\r
+       f.textcolor.value = tinyMCEPopup.dom.getAttrib(doc.body, "text");\r
+       f.active_color.value = tinyMCEPopup.dom.getAttrib(doc.body, "alink");\r
+       f.link_color.value = tinyMCEPopup.dom.getAttrib(doc.body, "link");\r
+       f.visited_color.value = tinyMCEPopup.dom.getAttrib(doc.body, "vlink");\r
+       f.bgcolor.value = tinyMCEPopup.dom.getAttrib(doc.body, "bgcolor");\r
+       f.bgimage.value = tinyMCEPopup.dom.getAttrib(doc.body, "background");\r
+\r
+       // Get from style info\r
+       style = tinyMCEPopup.dom.parseStyle(tinyMCEPopup.dom.getAttrib(doc.body, 'style'));\r
+\r
+       if (style['font-family'])\r
+               selectByValue(f, 'fontface', style['font-family'], true, true);\r
+       else\r
+               selectByValue(f, 'fontface', ed.getParam("fullpage_default_fontface", ""), true, true);\r
+\r
+       if (style['font-size'])\r
+               selectByValue(f, 'fontsize', style['font-size'], true, true);\r
+       else\r
+               selectByValue(f, 'fontsize', ed.getParam("fullpage_default_fontsize", ""), true, true);\r
+\r
+       if (style['color'])\r
+               f.textcolor.value = convertRGBToHex(style['color']);\r
+\r
+       if (style['background-image'])\r
+               f.bgimage.value = style['background-image'].replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");\r
+\r
+       if (style['background-color'])\r
+               f.bgcolor.value = style['background-color'];\r
+\r
+       if (style['margin']) {\r
+               tmp = style['margin'].replace(/[^0-9 ]/g, '');\r
+               tmp = tmp.split(/ +/);\r
+               f.topmargin.value = tmp.length > 0 ? tmp[0] : '';\r
+               f.rightmargin.value = tmp.length > 1 ? tmp[1] : tmp[0];\r
+               f.bottommargin.value = tmp.length > 2 ? tmp[2] : tmp[0];\r
+               f.leftmargin.value = tmp.length > 3 ? tmp[3] : tmp[0];\r
+       }\r
+\r
+       if (style['margin-left'])\r
+               f.leftmargin.value = style['margin-left'].replace(/[^0-9]/g, '');\r
+\r
+       if (style['margin-right'])\r
+               f.rightmargin.value = style['margin-right'].replace(/[^0-9]/g, '');\r
+\r
+       if (style['margin-top'])\r
+               f.topmargin.value = style['margin-top'].replace(/[^0-9]/g, '');\r
+\r
+       if (style['margin-bottom'])\r
+               f.bottommargin.value = style['margin-bottom'].replace(/[^0-9]/g, '');\r
+\r
+       f.style.value = tinyMCEPopup.dom.serializeStyle(style);\r
+\r
+       // Update colors\r
+       updateColor('textcolor_pick', 'textcolor');\r
+       updateColor('bgcolor_pick', 'bgcolor');\r
+       updateColor('visited_color_pick', 'visited_color');\r
+       updateColor('active_color_pick', 'active_color');\r
+       updateColor('link_color_pick', 'link_color');\r
+}\r
+\r
+function getReItem(r, s, i) {\r
+       var c = r.exec(s);\r
+\r
+       if (c && c.length > i)\r
+               return c[i];\r
+\r
+       return '';\r
+}\r
+\r
+function updateAction() {\r
+       var f = document.forms[0], nl, i, h, v, s, head, html, l, tmp, addlink = true, ser;\r
+\r
+       head = doc.getElementsByTagName('head')[0];\r
+\r
+       // Fix scripts without a type\r
+       nl = doc.getElementsByTagName('script');\r
+       for (i=0; i<nl.length; i++) {\r
+               if (tinyMCEPopup.dom.getAttrib(nl[i], 'mce_type') == '')\r
+                       nl[i].setAttribute('mce_type', 'text/javascript');\r
+       }\r
+\r
+       // Get primary stylesheet\r
+       nl = doc.getElementsByTagName("link");\r
+       for (i=0; i<nl.length; i++) {\r
+               l = nl[i];\r
+\r
+               tmp = tinyMCEPopup.dom.getAttrib(l, 'media');\r
+\r
+               if (tinyMCEPopup.dom.getAttrib(l, 'mce_type') == "text/css" && (tmp == "" || tmp == "screen" || tmp == "all") && tinyMCEPopup.dom.getAttrib(l, 'rel') == "stylesheet") {\r
+                       addlink = false;\r
+\r
+                       if (f.stylesheet.value == '')\r
+                               l.parentNode.removeChild(l);\r
+                       else\r
+                               l.setAttribute('mce_href', f.stylesheet.value);\r
+\r
+                       break;\r
+               }\r
+       }\r
+\r
+       // Add new link\r
+       if (f.stylesheet.value != '') {\r
+               l = doc.createElement('link');\r
+\r
+               l.setAttribute('type', 'text/css');\r
+               l.setAttribute('mce_href', f.stylesheet.value);\r
+               l.setAttribute('rel', 'stylesheet');\r
+\r
+               head.appendChild(l);\r
+       }\r
+\r
+       setMeta(head, 'keywords', f.metakeywords.value);\r
+       setMeta(head, 'description', f.metadescription.value);\r
+       setMeta(head, 'author', f.metaauthor.value);\r
+       setMeta(head, 'copyright', f.metacopyright.value);\r
+       setMeta(head, 'robots', getSelectValue(f, 'metarobots'));\r
+       setMeta(head, 'Content-Type', getSelectValue(f, 'docencoding'));\r
+\r
+       doc.body.dir = getSelectValue(f, 'langdir');\r
+       doc.body.style.cssText = f.style.value;\r
+\r
+       doc.body.setAttribute('vLink', f.visited_color.value);\r
+       doc.body.setAttribute('link', f.link_color.value);\r
+       doc.body.setAttribute('text', f.textcolor.value);\r
+       doc.body.setAttribute('aLink', f.active_color.value);\r
+\r
+       doc.body.style.fontFamily = getSelectValue(f, 'fontface');\r
+       doc.body.style.fontSize = getSelectValue(f, 'fontsize');\r
+       doc.body.style.backgroundColor = f.bgcolor.value;\r
+\r
+       if (f.leftmargin.value != '')\r
+               doc.body.style.marginLeft = f.leftmargin.value + 'px';\r
+\r
+       if (f.rightmargin.value != '')\r
+               doc.body.style.marginRight = f.rightmargin.value + 'px';\r
+\r
+       if (f.bottommargin.value != '')\r
+               doc.body.style.marginBottom = f.bottommargin.value + 'px';\r
+\r
+       if (f.topmargin.value != '')\r
+               doc.body.style.marginTop = f.topmargin.value + 'px';\r
+\r
+       html = doc.getElementsByTagName('html')[0];\r
+       html.setAttribute('lang', f.langcode.value);\r
+       html.setAttribute('xml:lang', f.langcode.value);\r
+\r
+       if (f.bgimage.value != '')\r
+               doc.body.style.backgroundImage = "url('" + f.bgimage.value + "')";\r
+       else\r
+               doc.body.style.backgroundImage = '';\r
+\r
+       ser = tinyMCEPopup.editor.plugins.fullpage._createSerializer();\r
+       ser.setRules('-title,meta[http-equiv|name|content],base[href|target],link[href|rel|type|title|media],style[type],script[type|language|src],html[lang|xml::lang|xmlns],body[style|dir|vlink|link|text|alink],head');\r
+\r
+       h = ser.serialize(doc.documentElement);\r
+       h = h.substring(0, h.lastIndexOf('</body>'));\r
+\r
+       if (h.indexOf('<title>') == -1)\r
+               h = h.replace(/<head.*?>/, '$&\n' + '<title>' + tinyMCEPopup.dom.encode(f.metatitle.value) + '</title>');\r
+       else\r
+               h = h.replace(/<title>(.*?)<\/title>/, '<title>' + tinyMCEPopup.dom.encode(f.metatitle.value) + '</title>');\r
+\r
+       if ((v = getSelectValue(f, 'doctypes')) != '')\r
+               h = v + '\n' + h;\r
+\r
+       if (f.xml_pi.checked) {\r
+               s = '<?xml version="1.0"';\r
+\r
+               if ((v = getSelectValue(f, 'docencoding')) != '')\r
+                       s += ' encoding="' + v + '"';\r
+\r
+               s += '?>\n';\r
+               h = s + h;\r
+       }\r
+\r
+       h = h.replace(/type=\"\-mce\-/gi, 'type="');\r
+\r
+       tinyMCEPopup.editor.plugins.fullpage.head = h;\r
+       tinyMCEPopup.editor.plugins.fullpage._setBodyAttribs(tinyMCEPopup.editor, {});\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function changedStyleField(field) {\r
+       //alert(field.id);\r
+}\r
+\r
+function setMeta(he, k, v) {\r
+       var nl, i, m;\r
+\r
+       nl = he.getElementsByTagName('meta');\r
+       for (i=0; i<nl.length; i++) {\r
+               if (k == 'Content-Type' && tinyMCEPopup.dom.getAttrib(nl[i], 'http-equiv') == k) {\r
+                       if (v == '')\r
+                               nl[i].parentNode.removeChild(nl[i]);\r
+                       else\r
+                               nl[i].setAttribute('content', "text/html; charset=" + v);\r
+\r
+                       return;\r
+               }\r
+\r
+               if (tinyMCEPopup.dom.getAttrib(nl[i], 'name') == k) {\r
+                       if (v == '')\r
+                               nl[i].parentNode.removeChild(nl[i]);\r
+                       else\r
+                               nl[i].setAttribute('content', v);\r
+                       return;\r
+               }\r
+       }\r
+\r
+       if (v == '')\r
+               return;\r
+\r
+       m = doc.createElement('meta');\r
+\r
+       if (k == 'Content-Type')\r
+               m.httpEquiv = k;\r
+       else\r
+               m.setAttribute('name', k);\r
+\r
+       m.setAttribute('content', v);\r
+       he.appendChild(m);\r
+}\r
+\r
+function parseStyleElement(e) {\r
+       var v = e.innerHTML;\r
+       var p, i, r;\r
+\r
+       v = v.replace(/<!--/gi, '');\r
+       v = v.replace(/-->/gi, '');\r
+       v = v.replace(/[\n\r]/gi, '');\r
+       v = v.replace(/\s+/gi, ' ');\r
+\r
+       r = [];\r
+       p = v.split(/{|}/);\r
+\r
+       for (i=0; i<p.length; i+=2) {\r
+               if (p[i] != "")\r
+                       r[r.length] = {rule : tinymce.trim(p[i]), data : tinyMCEPopup.dom.parseStyle(p[i+1])};\r
+       }\r
+\r
+       return r;\r
+}\r
+\r
+function serializeStyleElement(d) {\r
+       var i, s, st;\r
+\r
+       s = '<!--\n';\r
+\r
+       for (i=0; i<d.length; i++) {\r
+               s += d[i].rule + ' {\n';\r
+\r
+               st = tinyMCE.serializeStyle(d[i].data);\r
+\r
+               if (st != '')\r
+                       st += ';';\r
+\r
+               s += st.replace(/;/g, ';\n');\r
+               s += '}\n';\r
+\r
+               if (i != d.length - 1)\r
+                       s += '\n';\r
+       }\r
+\r
+       s += '\n-->';\r
+\r
+       return s;\r
+}\r
+\r
+tinyMCEPopup.onInit.add(init);\r
diff --git a/jscripts/tiny_mce/plugins/fullpage/langs/en_dlg.js b/jscripts/tiny_mce/plugins/fullpage/langs/en_dlg.js
new file mode 100644 (file)
index 0000000..f5801b8
--- /dev/null
@@ -0,0 +1,85 @@
+tinyMCE.addI18n('en.fullpage_dlg',{\r
+title:"Document properties",\r
+meta_tab:"General",\r
+appearance_tab:"Appearance",\r
+advanced_tab:"Advanced",\r
+meta_props:"Meta information",\r
+langprops:"Language and encoding",\r
+meta_title:"Title",\r
+meta_keywords:"Keywords",\r
+meta_description:"Description",\r
+meta_robots:"Robots",\r
+doctypes:"Doctype",\r
+langcode:"Language code",\r
+langdir:"Language direction",\r
+ltr:"Left to right",\r
+rtl:"Right to left",\r
+xml_pi:"XML declaration",\r
+encoding:"Character encoding",\r
+appearance_bgprops:"Background properties",\r
+appearance_marginprops:"Body margins",\r
+appearance_linkprops:"Link colors",\r
+appearance_textprops:"Text properties",\r
+bgcolor:"Background color",\r
+bgimage:"Background image",\r
+left_margin:"Left margin",\r
+right_margin:"Right margin",\r
+top_margin:"Top margin",\r
+bottom_margin:"Bottom margin",\r
+text_color:"Text color",\r
+font_size:"Font size",\r
+font_face:"Font face",\r
+link_color:"Link color",\r
+hover_color:"Hover color",\r
+visited_color:"Visited color",\r
+active_color:"Active color",\r
+textcolor:"Color",\r
+fontsize:"Font size",\r
+fontface:"Font family",\r
+meta_index_follow:"Index and follow the links",\r
+meta_index_nofollow:"Index and don't follow the links",\r
+meta_noindex_follow:"Do not index but follow the links",\r
+meta_noindex_nofollow:"Do not index and don\'t follow the links",\r
+appearance_style:"Stylesheet and style properties",\r
+stylesheet:"Stylesheet",\r
+style:"Style",\r
+author:"Author",\r
+copyright:"Copyright",\r
+add:"Add new element",\r
+remove:"Remove selected element",\r
+moveup:"Move selected element up",\r
+movedown:"Move selected element down",\r
+head_elements:"Head elements",\r
+info:"Information",\r
+add_title:"Title element",\r
+add_meta:"Meta element",\r
+add_script:"Script element",\r
+add_style:"Style element",\r
+add_link:"Link element",\r
+add_base:"Base element",\r
+add_comment:"Comment node",\r
+title_element:"Title element",\r
+script_element:"Script element",\r
+style_element:"Style element",\r
+base_element:"Base element",\r
+link_element:"Link element",\r
+meta_element:"Meta element",\r
+comment_element:"Comment",\r
+src:"Src",\r
+language:"Language",\r
+href:"Href",\r
+target:"Target",\r
+type:"Type",\r
+charset:"Charset",\r
+defer:"Defer",\r
+media:"Media",\r
+properties:"Properties",\r
+name:"Name",\r
+value:"Value",\r
+content:"Content",\r
+rel:"Rel",\r
+rev:"Rev",\r
+hreflang:"Href lang",\r
+general_props:"General",\r
+advanced_props:"Advanced"\r
+});
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/fullscreen/editor_plugin.js b/jscripts/tiny_mce/plugins/fullscreen/editor_plugin.js
new file mode 100644 (file)
index 0000000..7b848f1
--- /dev/null
@@ -0,0 +1 @@
+(function(){var DOM=tinymce.DOM;tinymce.create('tinymce.plugins.FullScreenPlugin',{init:function(ed,url){var t=this,s={},vp;t.editor=ed;ed.addCommand('mceFullScreen',function(){var win,de=DOM.doc.documentElement;if(ed.getParam('fullscreen_is_enabled')){if(ed.getParam('fullscreen_new_window'))closeFullscreen();else{DOM.win.setTimeout(function(){tinymce.dom.Event.remove(DOM.win,'resize',t.resizeFunc);tinyMCE.get(ed.getParam('fullscreen_editor_id')).setContent(ed.getContent({format:'raw'}),{format:'raw'});tinyMCE.remove(ed);DOM.remove('mce_fullscreen_container');de.style.overflow=ed.getParam('fullscreen_html_overflow');DOM.setStyle(DOM.doc.body,'overflow',ed.getParam('fullscreen_overflow'));DOM.win.scrollTo(ed.getParam('fullscreen_scrollx'),ed.getParam('fullscreen_scrolly'));tinyMCE.settings=tinyMCE.oldSettings;},10);}return;}if(ed.getParam('fullscreen_new_window')){win=DOM.win.open(url+"/fullscreen.htm","mceFullScreenPopup","fullscreen=yes,menubar=no,toolbar=no,scrollbars=no,resizable=yes,left=0,top=0,width="+screen.availWidth+",height="+screen.availHeight);try{win.resizeTo(screen.availWidth,screen.availHeight);}catch(e){}}else{tinyMCE.oldSettings=tinyMCE.settings;s.fullscreen_overflow=DOM.getStyle(DOM.doc.body,'overflow',1)||'auto';s.fullscreen_html_overflow=DOM.getStyle(de,'overflow',1);vp=DOM.getViewPort();s.fullscreen_scrollx=vp.x;s.fullscreen_scrolly=vp.y;if(tinymce.isOpera&&s.fullscreen_overflow=='visible')s.fullscreen_overflow='auto';if(tinymce.isIE&&s.fullscreen_overflow=='scroll')s.fullscreen_overflow='auto';if(s.fullscreen_overflow=='0px')s.fullscreen_overflow='';DOM.setStyle(DOM.doc.body,'overflow','hidden');de.style.overflow='hidden';vp=DOM.getViewPort();DOM.win.scrollTo(0,0);if(tinymce.isIE)vp.h-=1;n=DOM.add(DOM.doc.body,'div',{id:'mce_fullscreen_container',style:'position:absolute;top:0;left:0;width:'+vp.w+'px;height:'+vp.h+'px;z-index:200000;'});DOM.add(n,'div',{id:'mce_fullscreen'});tinymce.each(ed.settings,function(v,n){s[n]=v;});s.id='mce_fullscreen';s.width=n.clientWidth;s.height=n.clientHeight-15;s.fullscreen_is_enabled=true;s.fullscreen_editor_id=ed.id;s.theme_advanced_resizing=false;s.save_onsavecallback=function(){ed.setContent(tinyMCE.get(s.id).getContent({format:'raw'}),{format:'raw'});ed.execCommand('mceSave');};tinymce.each(ed.getParam('fullscreen_settings'),function(v,k){s[k]=v;});if(s.theme_advanced_toolbar_location==='external')s.theme_advanced_toolbar_location='top';t.fullscreenEditor=new tinymce.Editor('mce_fullscreen',s);t.fullscreenEditor.onInit.add(function(){t.fullscreenEditor.setContent(ed.getContent());t.fullscreenEditor.focus();});t.fullscreenEditor.render();tinyMCE.add(t.fullscreenEditor);t.fullscreenElement=new tinymce.dom.Element('mce_fullscreen_container');t.fullscreenElement.update();t.resizeFunc=tinymce.dom.Event.add(DOM.win,'resize',function(){var vp=tinymce.DOM.getViewPort();t.fullscreenEditor.theme.resizeTo(vp.w,vp.h);});}});ed.addButton('fullscreen',{title:'fullscreen.desc',cmd:'mceFullScreen'});ed.onNodeChange.add(function(ed,cm){cm.setActive('fullscreen',ed.getParam('fullscreen_is_enabled'));});},getInfo:function(){return{longname:'Fullscreen',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullscreen',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('fullscreen',tinymce.plugins.FullScreenPlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/fullscreen/editor_plugin_src.js b/jscripts/tiny_mce/plugins/fullscreen/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..ba43f27
--- /dev/null
@@ -0,0 +1,141 @@
+/**\r
+ * $Id: editor_plugin_src.js 766 2008-04-03 20:37:06Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       var DOM = tinymce.DOM;\r
+\r
+       tinymce.create('tinymce.plugins.FullScreenPlugin', {\r
+               init : function(ed, url) {\r
+                       var t = this, s = {}, vp;\r
+\r
+                       t.editor = ed;\r
+\r
+                       // Register commands\r
+                       ed.addCommand('mceFullScreen', function() {\r
+                               var win, de = DOM.doc.documentElement;\r
+\r
+                               if (ed.getParam('fullscreen_is_enabled')) {\r
+                                       if (ed.getParam('fullscreen_new_window'))\r
+                                               closeFullscreen(); // Call to close in new window\r
+                                       else {\r
+                                               DOM.win.setTimeout(function() {\r
+                                                       tinymce.dom.Event.remove(DOM.win, 'resize', t.resizeFunc);\r
+                                                       tinyMCE.get(ed.getParam('fullscreen_editor_id')).setContent(ed.getContent({format : 'raw'}), {format : 'raw'});\r
+                                                       tinyMCE.remove(ed);\r
+                                                       DOM.remove('mce_fullscreen_container');\r
+                                                       de.style.overflow = ed.getParam('fullscreen_html_overflow');\r
+                                                       DOM.setStyle(DOM.doc.body, 'overflow', ed.getParam('fullscreen_overflow'));\r
+                                                       DOM.win.scrollTo(ed.getParam('fullscreen_scrollx'), ed.getParam('fullscreen_scrolly'));\r
+                                                       tinyMCE.settings = tinyMCE.oldSettings; // Restore old settings\r
+                                               }, 10);\r
+                                       }\r
+\r
+                                       return;\r
+                               }\r
+\r
+                               if (ed.getParam('fullscreen_new_window')) {\r
+                                       win = DOM.win.open(url + "/fullscreen.htm", "mceFullScreenPopup", "fullscreen=yes,menubar=no,toolbar=no,scrollbars=no,resizable=yes,left=0,top=0,width=" + screen.availWidth + ",height=" + screen.availHeight);\r
+                                       try {\r
+                                               win.resizeTo(screen.availWidth, screen.availHeight);\r
+                                       } catch (e) {\r
+                                               // Ignore\r
+                                       }\r
+                               } else {\r
+                                       tinyMCE.oldSettings = tinyMCE.settings; // Store old settings\r
+                                       s.fullscreen_overflow = DOM.getStyle(DOM.doc.body, 'overflow', 1) || 'auto';\r
+                                       s.fullscreen_html_overflow = DOM.getStyle(de, 'overflow', 1);\r
+                                       vp = DOM.getViewPort();\r
+                                       s.fullscreen_scrollx = vp.x;\r
+                                       s.fullscreen_scrolly = vp.y;\r
+\r
+                                       // Fixes an Opera bug where the scrollbars doesn't reappear\r
+                                       if (tinymce.isOpera && s.fullscreen_overflow == 'visible')\r
+                                               s.fullscreen_overflow = 'auto';\r
+\r
+                                       // Fixes an IE bug where horizontal scrollbars would appear\r
+                                       if (tinymce.isIE && s.fullscreen_overflow == 'scroll')\r
+                                               s.fullscreen_overflow = 'auto';\r
+\r
+                                       if (s.fullscreen_overflow == '0px')\r
+                                               s.fullscreen_overflow = '';\r
+\r
+                                       DOM.setStyle(DOM.doc.body, 'overflow', 'hidden');\r
+                                       de.style.overflow = 'hidden'; //Fix for IE6/7\r
+                                       vp = DOM.getViewPort();\r
+                                       DOM.win.scrollTo(0, 0);\r
+\r
+                                       if (tinymce.isIE)\r
+                                               vp.h -= 1;\r
+\r
+                                       n = DOM.add(DOM.doc.body, 'div', {id : 'mce_fullscreen_container', style : 'position:absolute;top:0;left:0;width:' + vp.w + 'px;height:' + vp.h + 'px;z-index:200000;'});\r
+                                       DOM.add(n, 'div', {id : 'mce_fullscreen'});\r
+\r
+                                       tinymce.each(ed.settings, function(v, n) {\r
+                                               s[n] = v;\r
+                                       });\r
+\r
+                                       s.id = 'mce_fullscreen';\r
+                                       s.width = n.clientWidth;\r
+                                       s.height = n.clientHeight - 15;\r
+                                       s.fullscreen_is_enabled = true;\r
+                                       s.fullscreen_editor_id = ed.id;\r
+                                       s.theme_advanced_resizing = false;\r
+                                       s.save_onsavecallback = function() {\r
+                                               ed.setContent(tinyMCE.get(s.id).getContent({format : 'raw'}), {format : 'raw'});\r
+                                               ed.execCommand('mceSave');\r
+                                       };\r
+\r
+                                       tinymce.each(ed.getParam('fullscreen_settings'), function(v, k) {\r
+                                               s[k] = v;\r
+                                       });\r
+\r
+                                       if (s.theme_advanced_toolbar_location === 'external')\r
+                                               s.theme_advanced_toolbar_location = 'top';\r
+\r
+                                       t.fullscreenEditor = new tinymce.Editor('mce_fullscreen', s);\r
+                                       t.fullscreenEditor.onInit.add(function() {\r
+                                               t.fullscreenEditor.setContent(ed.getContent());\r
+                                               t.fullscreenEditor.focus();\r
+                                       });\r
+\r
+                                       t.fullscreenEditor.render();\r
+                                       tinyMCE.add(t.fullscreenEditor);\r
+\r
+                                       t.fullscreenElement = new tinymce.dom.Element('mce_fullscreen_container');\r
+                                       t.fullscreenElement.update();\r
+                                       //document.body.overflow = 'hidden';\r
+\r
+                                       t.resizeFunc = tinymce.dom.Event.add(DOM.win, 'resize', function() {\r
+                                               var vp = tinymce.DOM.getViewPort();\r
+\r
+                                               t.fullscreenEditor.theme.resizeTo(vp.w, vp.h);\r
+                                       });\r
+                               }\r
+                       });\r
+\r
+                       // Register buttons\r
+                       ed.addButton('fullscreen', {title : 'fullscreen.desc', cmd : 'mceFullScreen'});\r
+\r
+                       ed.onNodeChange.add(function(ed, cm) {\r
+                               cm.setActive('fullscreen', ed.getParam('fullscreen_is_enabled'));\r
+                       });\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Fullscreen',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullscreen',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('fullscreen', tinymce.plugins.FullScreenPlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/fullscreen/fullscreen.htm b/jscripts/tiny_mce/plugins/fullscreen/fullscreen.htm
new file mode 100644 (file)
index 0000000..8fe3151
--- /dev/null
@@ -0,0 +1,111 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title></title>\r
+       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />\r
+       <script type="text/javascript" src="../../tiny_mce.js?v=307"></script>\r
+       <script type="text/javascript">\r
+               function patchCallback(settings, key) {\r
+                       if (settings[key])\r
+                               settings[key] = "window.opener." + settings[key];\r
+               }\r
+\r
+               var settings = {}, paSe = window.opener.tinyMCE.activeEditor.settings;\r
+\r
+               // Clone array\r
+               for (var n in paSe)\r
+                       settings[n] = paSe[n];\r
+\r
+               // Override options for fullscreen\r
+               for (var n in paSe.fullscreen_settings)\r
+                       settings[n] = paSe.fullscreen_settings[n];\r
+\r
+               // Patch callbacks, make them point to window.opener\r
+               patchCallback(settings, 'urlconverter_callback');\r
+               patchCallback(settings, 'insertlink_callback');\r
+               patchCallback(settings, 'insertimage_callback');\r
+               patchCallback(settings, 'setupcontent_callback');\r
+               patchCallback(settings, 'save_callback');\r
+               patchCallback(settings, 'onchange_callback');\r
+               patchCallback(settings, 'init_instance_callback');\r
+               patchCallback(settings, 'file_browser_callback');\r
+               patchCallback(settings, 'cleanup_callback');\r
+               patchCallback(settings, 'execcommand_callback');\r
+               patchCallback(settings, 'oninit');\r
+\r
+               // Set options\r
+               delete settings.id;\r
+               settings['mode'] = 'exact';\r
+               settings['elements'] = 'fullscreenarea';\r
+               settings['add_unload_trigger'] = false;\r
+               settings['ask'] = false;\r
+               settings['document_base_url'] = window.opener.tinyMCE.activeEditor.documentBaseURI.getURI();\r
+               settings['fullscreen_is_enabled'] = true;\r
+               settings['fullscreen_editor_id'] = window.opener.tinyMCE.activeEditor.id;\r
+               settings['theme_advanced_resizing'] = false;\r
+               settings['strict_loading_mode'] = true;\r
+\r
+               settings.save_onsavecallback = function() {\r
+                       window.opener.tinyMCE.activeEditor.setContent(tinyMCE.get('fullscreenarea').getContent({format : 'raw'}), {format : 'raw'});\r
+                       window.opener.tinyMCE.activeEditor.execCommand('mceSave');\r
+                       window.close();\r
+               };\r
+\r
+               function unloadHandler(e) {\r
+                       moveContent();\r
+               }\r
+\r
+               function moveContent() {\r
+                       window.opener.tinyMCE.activeEditor.setContent(tinyMCE.activeEditor.getContent());\r
+               }\r
+\r
+               function closeFullscreen() {\r
+                       moveContent();\r
+                       window.close();\r
+               }\r
+\r
+               function doParentSubmit() {\r
+                       moveContent();\r
+\r
+                       if (window.opener.tinyMCE.selectedInstance.formElement.form)\r
+                               window.opener.tinyMCE.selectedInstance.formElement.form.submit();\r
+\r
+                       window.close();\r
+\r
+                       return false;\r
+               }\r
+\r
+               function render() {\r
+                       var e = document.getElementById('fullscreenarea'), vp, ed, ow, oh, dom = tinymce.DOM;\r
+\r
+                       e.value = window.opener.tinyMCE.activeEditor.getContent();\r
+\r
+                       vp = dom.getViewPort();\r
+                       settings.width = vp.w;\r
+                       settings.height = vp.h - 15;\r
+\r
+                       tinymce.dom.Event.add(window, 'resize', function() {\r
+                               var vp = dom.getViewPort();\r
+\r
+                               tinyMCE.activeEditor.theme.resizeTo(vp.w, vp.h);\r
+                       });\r
+\r
+                       tinyMCE.init(settings);\r
+               }\r
+\r
+               // Add onunload\r
+               tinymce.dom.Event.add(window, "beforeunload", unloadHandler);\r
+       </script>\r
+       <base target="_self" />\r
+</head>\r
+<body style="margin:0;overflow:hidden;width:100%;height:100%" scrolling="no" scroll="no">\r
+<form onsubmit="doParentSubmit();">\r
+<textarea id="fullscreenarea" style="width:100%; height:100%"></textarea>\r
+</form>\r
+\r
+<script type="text/javascript">\r
+       render();\r
+</script>\r
+\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/iespell/editor_plugin.js b/jscripts/tiny_mce/plugins/iespell/editor_plugin.js
new file mode 100644 (file)
index 0000000..06dae75
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.IESpell',{init:function(ed,url){var t=this,sp;if(!tinymce.isIE)return;t.editor=ed;ed.addCommand('mceIESpell',function(){try{sp=new ActiveXObject("ieSpell.ieSpellExtension");sp.CheckDocumentNode(ed.getDoc().documentElement);}catch(e){if(e.number==-2146827859){ed.windowManager.confirm(ed.getLang("iespell.download"),function(s){if(s)window.open('http://www.iespell.com/download.php','ieSpellDownload','');});}else ed.windowManager.alert("Error Loading ieSpell: Exception "+e.number);}});ed.addButton('iespell',{title:'iespell.iespell_desc',cmd:'mceIESpell'});},getInfo:function(){return{longname:'IESpell (IE Only)',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/iespell',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('iespell',tinymce.plugins.IESpell);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/iespell/editor_plugin_src.js b/jscripts/tiny_mce/plugins/iespell/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..a68f69a
--- /dev/null
@@ -0,0 +1,51 @@
+/**\r
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.IESpell', {\r
+               init : function(ed, url) {\r
+                       var t = this, sp;\r
+\r
+                       if (!tinymce.isIE)\r
+                               return;\r
+\r
+                       t.editor = ed;\r
+\r
+                       // Register commands\r
+                       ed.addCommand('mceIESpell', function() {\r
+                               try {\r
+                                       sp = new ActiveXObject("ieSpell.ieSpellExtension");\r
+                                       sp.CheckDocumentNode(ed.getDoc().documentElement);\r
+                               } catch (e) {\r
+                                       if (e.number == -2146827859) {\r
+                                               ed.windowManager.confirm(ed.getLang("iespell.download"), function(s) {\r
+                                                       if (s)\r
+                                                               window.open('http://www.iespell.com/download.php', 'ieSpellDownload', '');\r
+                                               });\r
+                                       } else\r
+                                               ed.windowManager.alert("Error Loading ieSpell: Exception " + e.number);\r
+                               }\r
+                       });\r
+\r
+                       // Register buttons\r
+                       ed.addButton('iespell', {title : 'iespell.iespell_desc', cmd : 'mceIESpell'});\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'IESpell (IE Only)',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/iespell',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('iespell', tinymce.plugins.IESpell);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/inlinepopups/editor_plugin.js b/jscripts/tiny_mce/plugins/inlinepopups/editor_plugin.js
new file mode 100644 (file)
index 0000000..0766b49
--- /dev/null
@@ -0,0 +1 @@
+(function(){var DOM=tinymce.DOM,Element=tinymce.dom.Element,Event=tinymce.dom.Event,each=tinymce.each,is=tinymce.is;tinymce.create('tinymce.plugins.InlinePopups',{init:function(ed,url){ed.onBeforeRenderUI.add(function(){ed.windowManager=new tinymce.InlineWindowManager(ed);DOM.loadCSS(url+'/skins/'+(ed.settings.inlinepopups_skin||'clearlooks2')+"/window.css");});},getInfo:function(){return{longname:'InlinePopups',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/inlinepopups',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.create('tinymce.InlineWindowManager:tinymce.WindowManager',{InlineWindowManager:function(ed){var t=this;t.parent(ed);t.zIndex=300000;t.count=0;},open:function(f,p){var t=this,id,opt='',ed=t.editor,dw=0,dh=0,vp,po,mdf,clf,we,w,u;f=f||{};p=p||{};if(!f.inline)return t.parent(f,p);if(!f.type)t.bookmark=ed.selection.getBookmark('simple');id=DOM.uniqueId();vp=DOM.getViewPort();f.width=parseInt(f.width||320);f.height=parseInt(f.height||240)+(tinymce.isIE?8:0);f.min_width=parseInt(f.min_width||150);f.min_height=parseInt(f.min_height||100);f.max_width=parseInt(f.max_width||2000);f.max_height=parseInt(f.max_height||2000);f.left=f.left||Math.round(Math.max(vp.x,vp.x+(vp.w/ 2.0) - (f.width /2.0)));f.top=f.top||Math.round(Math.max(vp.y,vp.y+(vp.h/ 2.0) - (f.height /2.0)));f.movable=f.resizable=true;p.mce_width=f.width;p.mce_height=f.height;p.mce_inline=true;p.mce_window_id=id;p.mce_auto_focus=f.auto_focus;t.features=f;t.params=p;t.onOpen.dispatch(t,f,p);if(f.type){opt+=' mceModal';if(f.type)opt+=' mce'+f.type.substring(0,1).toUpperCase()+f.type.substring(1);f.resizable=false;}if(f.statusbar)opt+=' mceStatusbar';if(f.resizable)opt+=' mceResizable';if(f.minimizable)opt+=' mceMinimizable';if(f.maximizable)opt+=' mceMaximizable';if(f.movable)opt+=' mceMovable';t._addAll(DOM.doc.body,['div',{id:id,'class':ed.settings.inlinepopups_skin||'clearlooks2',style:'width:100px;height:100px'},['div',{id:id+'_wrapper','class':'mceWrapper'+opt},['div',{id:id+'_top','class':'mceTop'},['div',{'class':'mceLeft'}],['div',{'class':'mceCenter'}],['div',{'class':'mceRight'}],['span',{id:id+'_title'},f.title||'']],['div',{id:id+'_middle','class':'mceMiddle'},['div',{id:id+'_left','class':'mceLeft'}],['span',{id:id+'_content'}],['div',{id:id+'_right','class':'mceRight'}]],['div',{id:id+'_bottom','class':'mceBottom'},['div',{'class':'mceLeft'}],['div',{'class':'mceCenter'}],['div',{'class':'mceRight'}],['span',{id:id+'_status'},'Content']],['a',{'class':'mceMove',tabindex:'-1',href:'javascript:;'}],['a',{'class':'mceMin',tabindex:'-1',href:'javascript:;',onmousedown:'return false;'}],['a',{'class':'mceMax',tabindex:'-1',href:'javascript:;',onmousedown:'return false;'}],['a',{'class':'mceMed',tabindex:'-1',href:'javascript:;',onmousedown:'return false;'}],['a',{'class':'mceClose',tabindex:'-1',href:'javascript:;',onmousedown:'return false;'}],['a',{id:id+'_resize_n','class':'mceResize mceResizeN',tabindex:'-1',href:'javascript:;'}],['a',{id:id+'_resize_s','class':'mceResize mceResizeS',tabindex:'-1',href:'javascript:;'}],['a',{id:id+'_resize_w','class':'mceResize mceResizeW',tabindex:'-1',href:'javascript:;'}],['a',{id:id+'_resize_e','class':'mceResize mceResizeE',tabindex:'-1',href:'javascript:;'}],['a',{id:id+'_resize_nw','class':'mceResize mceResizeNW',tabindex:'-1',href:'javascript:;'}],['a',{id:id+'_resize_ne','class':'mceResize mceResizeNE',tabindex:'-1',href:'javascript:;'}],['a',{id:id+'_resize_sw','class':'mceResize mceResizeSW',tabindex:'-1',href:'javascript:;'}],['a',{id:id+'_resize_se','class':'mceResize mceResizeSE',tabindex:'-1',href:'javascript:;'}]]]);DOM.setStyles(id,{top:-10000,left:-10000});if(tinymce.isGecko)DOM.setStyle(id,'overflow','auto');if(!f.type){dw+=DOM.get(id+'_left').clientWidth;dw+=DOM.get(id+'_right').clientWidth;dh+=DOM.get(id+'_top').clientHeight;dh+=DOM.get(id+'_bottom').clientHeight;}DOM.setStyles(id,{top:f.top,left:f.left,width:f.width+dw,height:f.height+dh});u=f.url||f.file;if(u){if(tinymce.relaxedDomain)u+=(u.indexOf('?')==-1?'?':'&')+'mce_rdomain='+tinymce.relaxedDomain;u=tinymce._addVer(u);}if(!f.type){DOM.add(id+'_content','iframe',{id:id+'_ifr',src:'javascript:""',frameBorder:0,style:'border:0;width:10px;height:10px'});DOM.setStyles(id+'_ifr',{width:f.width,height:f.height});DOM.setAttrib(id+'_ifr','src',u);}else{DOM.add(id+'_wrapper','a',{id:id+'_ok','class':'mceButton mceOk',href:'javascript:;',onmousedown:'return false;'},'Ok');if(f.type=='confirm')DOM.add(id+'_wrapper','a',{'class':'mceButton mceCancel',href:'javascript:;',onmousedown:'return false;'},'Cancel');DOM.add(id+'_middle','div',{'class':'mceIcon'});DOM.setHTML(id+'_content',f.content.replace('\n','<br />'));}mdf=Event.add(id,'mousedown',function(e){var n=e.target,w,vp;w=t.windows[id];t.focus(id);if(n.nodeName=='A'||n.nodeName=='a'){if(n.className=='mceMax'){w.oldPos=w.element.getXY();w.oldSize=w.element.getSize();vp=DOM.getViewPort();vp.w-=2;vp.h-=2;w.element.moveTo(vp.x,vp.y);w.element.resizeTo(vp.w,vp.h);DOM.setStyles(id+'_ifr',{width:vp.w-w.deltaWidth,height:vp.h-w.deltaHeight});DOM.addClass(id+'_wrapper','mceMaximized');}else if(n.className=='mceMed'){w.element.moveTo(w.oldPos.x,w.oldPos.y);w.element.resizeTo(w.oldSize.w,w.oldSize.h);w.iframeElement.resizeTo(w.oldSize.w-w.deltaWidth,w.oldSize.h-w.deltaHeight);DOM.removeClass(id+'_wrapper','mceMaximized');}else if(n.className=='mceMove')return t._startDrag(id,e,n.className);else if(DOM.hasClass(n,'mceResize'))return t._startDrag(id,e,n.className.substring(13));}});clf=Event.add(id,'click',function(e){var n=e.target;t.focus(id);if(n.nodeName=='A'||n.nodeName=='a'){switch(n.className){case'mceClose':t.close(null,id);return Event.cancel(e);case'mceButton mceOk':case'mceButton mceCancel':f.button_func(n.className=='mceButton mceOk');return Event.cancel(e);}}});t.windows=t.windows||{};w=t.windows[id]={id:id,mousedown_func:mdf,click_func:clf,element:new Element(id,{blocker:1,container:ed.getContainer()}),iframeElement:new Element(id+'_ifr'),features:f,deltaWidth:dw,deltaHeight:dh};w.iframeElement.on('focus',function(){t.focus(id);});if(t.count==0&&t.editor.getParam('dialog_type')=='modal'){DOM.add(DOM.doc.body,'div',{id:'mceModalBlocker','class':(t.editor.settings.inlinepopups_skin||'clearlooks2')+'_modalBlocker',style:{left:vp.x,top:vp.y,zIndex:t.zIndex-1}});DOM.show('mceModalBlocker');}else DOM.setStyle('mceModalBlocker','z-index',t.zIndex-1);t.focus(id);t._fixIELayout(id,1);if(DOM.get(id+'_ok'))DOM.get(id+'_ok').focus();t.count++;return w;},focus:function(id){var t=this,w=t.windows[id];w.zIndex=this.zIndex++;w.element.setStyle('zIndex',w.zIndex);w.element.update();id=id+'_wrapper';DOM.removeClass(t.lastId,'mceFocus');DOM.addClass(id,'mceFocus');t.lastId=id;},_addAll:function(te,ne){var i,n,t=this,dom=tinymce.DOM;if(is(ne,'string'))te.appendChild(dom.doc.createTextNode(ne));else if(ne.length){te=te.appendChild(dom.create(ne[0],ne[1]));for(i=2;i<ne.length;i++)t._addAll(te,ne[i]);}},_startDrag:function(id,se,ac){var t=this,mu,mm,d=DOM.doc,eb,w=t.windows[id],we=w.element,sp=we.getXY(),p,sz,ph,cp,vp,sx,sy,sex,sey,dx,dy,dw,dh;cp={x:0,y:0};vp=DOM.getViewPort();vp.w-=2;vp.h-=2;sex=se.screenX;sey=se.screenY;dx=dy=dw=dh=0;mu=Event.add(d,'mouseup',function(e){Event.remove(d,'mouseup',mu);Event.remove(d,'mousemove',mm);if(eb)eb.remove();we.moveBy(dx,dy);we.resizeBy(dw,dh);sz=we.getSize();DOM.setStyles(id+'_ifr',{width:sz.w-w.deltaWidth,height:sz.h-w.deltaHeight});t._fixIELayout(id,1);return Event.cancel(e);});if(ac!='Move')startMove();function startMove(){if(eb)return;t._fixIELayout(id,0);DOM.add(d.body,'div',{id:'mceEventBlocker','class':'mceEventBlocker '+(t.editor.settings.inlinepopups_skin||'clearlooks2'),style:{left:vp.x,top:vp.y,zIndex:t.zIndex+1}});eb=new Element('mceEventBlocker');eb.update();p=we.getXY();sz=we.getSize();sx=cp.x+p.x-vp.x;sy=cp.y+p.y-vp.y;DOM.add(eb.get(),'div',{id:'mcePlaceHolder','class':'mcePlaceHolder',style:{left:sx,top:sy,width:sz.w,height:sz.h}});ph=new Element('mcePlaceHolder');};mm=Event.add(d,'mousemove',function(e){var x,y,v;startMove();x=e.screenX-sex;y=e.screenY-sey;switch(ac){case'ResizeW':dx=x;dw=0-x;break;case'ResizeE':dw=x;break;case'ResizeN':case'ResizeNW':case'ResizeNE':if(ac=="ResizeNW"){dx=x;dw=0-x;}else if(ac=="ResizeNE")dw=x;dy=y;dh=0-y;break;case'ResizeS':case'ResizeSW':case'ResizeSE':if(ac=="ResizeSW"){dx=x;dw=0-x;}else if(ac=="ResizeSE")dw=x;dh=y;break;case'mceMove':dx=x;dy=y;break;}if(dw<(v=w.features.min_width-sz.w)){if(dx!==0)dx+=dw-v;dw=v;}if(dh<(v=w.features.min_height-sz.h)){if(dy!==0)dy+=dh-v;dh=v;}dw=Math.min(dw,w.features.max_width-sz.w);dh=Math.min(dh,w.features.max_height-sz.h);dx=Math.max(dx,vp.x-(sx+vp.x));dy=Math.max(dy,vp.y-(sy+vp.y));dx=Math.min(dx,(vp.w+vp.x)-(sx+sz.w+vp.x));dy=Math.min(dy,(vp.h+vp.y)-(sy+sz.h+vp.y));if(dx+dy!==0){if(sx+dx<0)dx=0;if(sy+dy<0)dy=0;ph.moveTo(sx+dx,sy+dy);}if(dw+dh!==0)ph.resizeTo(sz.w+dw,sz.h+dh);return Event.cancel(e);});return Event.cancel(se);},resizeBy:function(dw,dh,id){var w=this.windows[id];if(w){w.element.resizeBy(dw,dh);w.iframeElement.resizeBy(dw,dh);}},close:function(win,id){var t=this,w,d=DOM.doc,ix=0,fw;t.count--;if(t.count==0)DOM.remove('mceModalBlocker');if(!id&&win){t.parent(win);return;}if(w=t.windows[id]){t.onClose.dispatch(t);Event.remove(d,'mousedown',w.mousedownFunc);Event.remove(d,'click',w.clickFunc);Event.clear(id);Event.clear(id+'_ifr');DOM.setAttrib(id+'_ifr','src','javascript:""');w.element.remove();delete t.windows[id];each(t.windows,function(w){if(w.zIndex>ix){fw=w;ix=w.zIndex;}});if(fw)t.focus(fw.id);}},setTitle:function(ti,id){var e;if(e=DOM.get(id+'_title'))e.innerHTML=DOM.encode(ti);},alert:function(txt,cb,s){var t=this,w;w=t.open({title:t,type:'alert',button_func:function(s){if(cb)cb.call(s||t,s);t.close(null,w.id);},content:DOM.encode(t.editor.getLang(txt,txt)),inline:1,width:400,height:130});},confirm:function(txt,cb,s){var t=this,w;w=t.open({title:t,type:'confirm',button_func:function(s){if(cb)cb.call(s||t,s);t.close(null,w.id);},content:DOM.encode(t.editor.getLang(txt,txt)),inline:1,width:400,height:130});},_fixIELayout:function(id,s){var w,img;if(!tinymce.isIE6)return;each(['n','s','w','e','nw','ne','sw','se'],function(v){var e=DOM.get(id+'_resize_'+v);DOM.setStyles(e,{width:s?e.clientWidth:'',height:s?e.clientHeight:'',cursor:DOM.getStyle(e,'cursor',1)});DOM.setStyle(id+"_bottom",'bottom','-1px');e=0;});if(w=this.windows[id]){w.element.hide();w.element.show();each(DOM.select('div,a',id),function(e,i){if(e.currentStyle.backgroundImage!='none'){img=new Image();img.src=e.currentStyle.backgroundImage.replace(/url\(\"(.+)\"\)/,'$1');}});DOM.get(id).style.filter='';}}});tinymce.PluginManager.add('inlinepopups',tinymce.plugins.InlinePopups);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/inlinepopups/editor_plugin_src.js b/jscripts/tiny_mce/plugins/inlinepopups/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..0ef2b7d
--- /dev/null
@@ -0,0 +1,601 @@
+/**\r
+ * $Id: editor_plugin_src.js 776 2008-04-08 17:00:39Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       var DOM = tinymce.DOM, Element = tinymce.dom.Element, Event = tinymce.dom.Event, each = tinymce.each, is = tinymce.is;\r
+\r
+       tinymce.create('tinymce.plugins.InlinePopups', {\r
+               init : function(ed, url) {\r
+                       // Replace window manager\r
+                       ed.onBeforeRenderUI.add(function() {\r
+                               ed.windowManager = new tinymce.InlineWindowManager(ed);\r
+                               DOM.loadCSS(url + '/skins/' + (ed.settings.inlinepopups_skin || 'clearlooks2') + "/window.css");\r
+                       });\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'InlinePopups',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/inlinepopups',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               }\r
+       });\r
+\r
+       tinymce.create('tinymce.InlineWindowManager:tinymce.WindowManager', {\r
+               InlineWindowManager : function(ed) {\r
+                       var t = this;\r
+\r
+                       t.parent(ed);\r
+                       t.zIndex = 300000;\r
+                       t.count = 0;\r
+               },\r
+\r
+               open : function(f, p) {\r
+                       var t = this, id, opt = '', ed = t.editor, dw = 0, dh = 0, vp, po, mdf, clf, we, w, u;\r
+\r
+                       f = f || {};\r
+                       p = p || {};\r
+\r
+                       // Run native windows\r
+                       if (!f.inline)\r
+                               return t.parent(f, p);\r
+\r
+                       // Only store selection if the type is a normal window\r
+                       if (!f.type)\r
+                               t.bookmark = ed.selection.getBookmark('simple');\r
+\r
+                       id = DOM.uniqueId();\r
+                       vp = DOM.getViewPort();\r
+                       f.width = parseInt(f.width || 320);\r
+                       f.height = parseInt(f.height || 240) + (tinymce.isIE ? 8 : 0);\r
+                       f.min_width = parseInt(f.min_width || 150);\r
+                       f.min_height = parseInt(f.min_height || 100);\r
+                       f.max_width = parseInt(f.max_width || 2000);\r
+                       f.max_height = parseInt(f.max_height || 2000);\r
+                       f.left = f.left || Math.round(Math.max(vp.x, vp.x + (vp.w / 2.0) - (f.width / 2.0)));\r
+                       f.top = f.top || Math.round(Math.max(vp.y, vp.y + (vp.h / 2.0) - (f.height / 2.0)));\r
+                       f.movable = f.resizable = true;\r
+                       p.mce_width = f.width;\r
+                       p.mce_height = f.height;\r
+                       p.mce_inline = true;\r
+                       p.mce_window_id = id;\r
+                       p.mce_auto_focus = f.auto_focus;\r
+\r
+                       // Transpose\r
+//                     po = DOM.getPos(ed.getContainer());\r
+//                     f.left -= po.x;\r
+//                     f.top -= po.y;\r
+\r
+                       t.features = f;\r
+                       t.params = p;\r
+                       t.onOpen.dispatch(t, f, p);\r
+\r
+                       if (f.type) {\r
+                               opt += ' mceModal';\r
+\r
+                               if (f.type)\r
+                                       opt += ' mce' + f.type.substring(0, 1).toUpperCase() + f.type.substring(1);\r
+\r
+                               f.resizable = false;\r
+                       }\r
+\r
+                       if (f.statusbar)\r
+                               opt += ' mceStatusbar';\r
+\r
+                       if (f.resizable)\r
+                               opt += ' mceResizable';\r
+\r
+                       if (f.minimizable)\r
+                               opt += ' mceMinimizable';\r
+\r
+                       if (f.maximizable)\r
+                               opt += ' mceMaximizable';\r
+\r
+                       if (f.movable)\r
+                               opt += ' mceMovable';\r
+\r
+                       // Create DOM objects\r
+                       t._addAll(DOM.doc.body, \r
+                               ['div', {id : id, 'class' : ed.settings.inlinepopups_skin || 'clearlooks2', style : 'width:100px;height:100px'}, \r
+                                       ['div', {id : id + '_wrapper', 'class' : 'mceWrapper' + opt},\r
+                                               ['div', {id : id + '_top', 'class' : 'mceTop'}, \r
+                                                       ['div', {'class' : 'mceLeft'}],\r
+                                                       ['div', {'class' : 'mceCenter'}],\r
+                                                       ['div', {'class' : 'mceRight'}],\r
+                                                       ['span', {id : id + '_title'}, f.title || '']\r
+                                               ],\r
+\r
+                                               ['div', {id : id + '_middle', 'class' : 'mceMiddle'}, \r
+                                                       ['div', {id : id + '_left', 'class' : 'mceLeft'}],\r
+                                                       ['span', {id : id + '_content'}],\r
+                                                       ['div', {id : id + '_right', 'class' : 'mceRight'}]\r
+                                               ],\r
+\r
+                                               ['div', {id : id + '_bottom', 'class' : 'mceBottom'},\r
+                                                       ['div', {'class' : 'mceLeft'}],\r
+                                                       ['div', {'class' : 'mceCenter'}],\r
+                                                       ['div', {'class' : 'mceRight'}],\r
+                                                       ['span', {id : id + '_status'}, 'Content']\r
+                                               ],\r
+\r
+                                               ['a', {'class' : 'mceMove', tabindex : '-1', href : 'javascript:;'}],\r
+                                               ['a', {'class' : 'mceMin', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}],\r
+                                               ['a', {'class' : 'mceMax', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}],\r
+                                               ['a', {'class' : 'mceMed', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}],\r
+                                               ['a', {'class' : 'mceClose', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}],\r
+                                               ['a', {id : id + '_resize_n', 'class' : 'mceResize mceResizeN', tabindex : '-1', href : 'javascript:;'}],\r
+                                               ['a', {id : id + '_resize_s', 'class' : 'mceResize mceResizeS', tabindex : '-1', href : 'javascript:;'}],\r
+                                               ['a', {id : id + '_resize_w', 'class' : 'mceResize mceResizeW', tabindex : '-1', href : 'javascript:;'}],\r
+                                               ['a', {id : id + '_resize_e', 'class' : 'mceResize mceResizeE', tabindex : '-1', href : 'javascript:;'}],\r
+                                               ['a', {id : id + '_resize_nw', 'class' : 'mceResize mceResizeNW', tabindex : '-1', href : 'javascript:;'}],\r
+                                               ['a', {id : id + '_resize_ne', 'class' : 'mceResize mceResizeNE', tabindex : '-1', href : 'javascript:;'}],\r
+                                               ['a', {id : id + '_resize_sw', 'class' : 'mceResize mceResizeSW', tabindex : '-1', href : 'javascript:;'}],\r
+                                               ['a', {id : id + '_resize_se', 'class' : 'mceResize mceResizeSE', tabindex : '-1', href : 'javascript:;'}]\r
+                                       ]\r
+                               ]\r
+                       );\r
+\r
+                       DOM.setStyles(id, {top : -10000, left : -10000});\r
+\r
+                       // Fix gecko rendering bug, where the editors iframe messed with window contents\r
+                       if (tinymce.isGecko)\r
+                               DOM.setStyle(id, 'overflow', 'auto');\r
+\r
+                       // Measure borders\r
+                       if (!f.type) {\r
+                               dw += DOM.get(id + '_left').clientWidth;\r
+                               dw += DOM.get(id + '_right').clientWidth;\r
+                               dh += DOM.get(id + '_top').clientHeight;\r
+                               dh += DOM.get(id + '_bottom').clientHeight;\r
+                       }\r
+\r
+                       // Resize window\r
+                       DOM.setStyles(id, {top : f.top, left : f.left, width : f.width + dw, height : f.height + dh});\r
+\r
+                       u = f.url || f.file;\r
+                       if (u) {\r
+                               if (tinymce.relaxedDomain)\r
+                                       u += (u.indexOf('?') == -1 ? '?' : '&') + 'mce_rdomain=' + tinymce.relaxedDomain;\r
+\r
+                               u = tinymce._addVer(u);\r
+                       }\r
+\r
+                       if (!f.type) {\r
+                               DOM.add(id + '_content', 'iframe', {id : id + '_ifr', src : 'javascript:""', frameBorder : 0, style : 'border:0;width:10px;height:10px'});\r
+                               DOM.setStyles(id + '_ifr', {width : f.width, height : f.height});\r
+                               DOM.setAttrib(id + '_ifr', 'src', u);\r
+                       } else {\r
+                               DOM.add(id + '_wrapper', 'a', {id : id + '_ok', 'class' : 'mceButton mceOk', href : 'javascript:;', onmousedown : 'return false;'}, 'Ok');\r
+\r
+                               if (f.type == 'confirm')\r
+                                       DOM.add(id + '_wrapper', 'a', {'class' : 'mceButton mceCancel', href : 'javascript:;', onmousedown : 'return false;'}, 'Cancel');\r
+\r
+                               DOM.add(id + '_middle', 'div', {'class' : 'mceIcon'});\r
+                               DOM.setHTML(id + '_content', f.content.replace('\n', '<br />'));\r
+                       }\r
+\r
+                       // Register events\r
+                       mdf = Event.add(id, 'mousedown', function(e) {\r
+                               var n = e.target, w, vp;\r
+\r
+                               w = t.windows[id];\r
+                               t.focus(id);\r
+\r
+                               if (n.nodeName == 'A' || n.nodeName == 'a') {\r
+                                       if (n.className == 'mceMax') {\r
+                                               w.oldPos = w.element.getXY();\r
+                                               w.oldSize = w.element.getSize();\r
+\r
+                                               vp = DOM.getViewPort();\r
+\r
+                                               // Reduce viewport size to avoid scrollbars\r
+                                               vp.w -= 2;\r
+                                               vp.h -= 2;\r
+\r
+                                               w.element.moveTo(vp.x, vp.y);\r
+                                               w.element.resizeTo(vp.w, vp.h);\r
+                                               DOM.setStyles(id + '_ifr', {width : vp.w - w.deltaWidth, height : vp.h - w.deltaHeight});\r
+                                               DOM.addClass(id + '_wrapper', 'mceMaximized');\r
+                                       } else if (n.className == 'mceMed') {\r
+                                               // Reset to old size\r
+                                               w.element.moveTo(w.oldPos.x, w.oldPos.y);\r
+                                               w.element.resizeTo(w.oldSize.w, w.oldSize.h);\r
+                                               w.iframeElement.resizeTo(w.oldSize.w - w.deltaWidth, w.oldSize.h - w.deltaHeight);\r
+\r
+                                               DOM.removeClass(id + '_wrapper', 'mceMaximized');\r
+                                       } else if (n.className == 'mceMove')\r
+                                               return t._startDrag(id, e, n.className);\r
+                                       else if (DOM.hasClass(n, 'mceResize'))\r
+                                               return t._startDrag(id, e, n.className.substring(13));\r
+                               }\r
+                       });\r
+\r
+                       clf = Event.add(id, 'click', function(e) {\r
+                               var n = e.target;\r
+\r
+                               t.focus(id);\r
+\r
+                               if (n.nodeName == 'A' || n.nodeName == 'a') {\r
+                                       switch (n.className) {\r
+                                               case 'mceClose':\r
+                                                       t.close(null, id);\r
+                                                       return Event.cancel(e);\r
+\r
+                                               case 'mceButton mceOk':\r
+                                               case 'mceButton mceCancel':\r
+                                                       f.button_func(n.className == 'mceButton mceOk');\r
+                                                       return Event.cancel(e);\r
+                                       }\r
+                               }\r
+                       });\r
+\r
+                       // Add window\r
+                       t.windows = t.windows || {};\r
+                       w = t.windows[id] = {\r
+                               id : id,\r
+                               mousedown_func : mdf,\r
+                               click_func : clf,\r
+                               element : new Element(id, {blocker : 1, container : ed.getContainer()}),\r
+                               iframeElement : new Element(id + '_ifr'),\r
+                               features : f,\r
+                               deltaWidth : dw,\r
+                               deltaHeight : dh\r
+                       };\r
+\r
+                       w.iframeElement.on('focus', function() {\r
+                               t.focus(id);\r
+                       });\r
+\r
+                       // Setup blocker\r
+                       if (t.count == 0 && t.editor.getParam('dialog_type') == 'modal') {\r
+                               DOM.add(DOM.doc.body, 'div', {\r
+                                       id : 'mceModalBlocker',\r
+                                       'class' : (t.editor.settings.inlinepopups_skin || 'clearlooks2') + '_modalBlocker',\r
+                                       style : {left : vp.x, top : vp.y, zIndex : t.zIndex - 1}\r
+                               });\r
+\r
+                               DOM.show('mceModalBlocker'); // Reduces flicker in IE\r
+                       } else\r
+                               DOM.setStyle('mceModalBlocker', 'z-index', t.zIndex - 1);\r
+\r
+                       t.focus(id);\r
+                       t._fixIELayout(id, 1);\r
+\r
+                       // Focus ok button\r
+                       if (DOM.get(id + '_ok'))\r
+                               DOM.get(id + '_ok').focus();\r
+\r
+                       t.count++;\r
+\r
+                       return w;\r
+               },\r
+\r
+               focus : function(id) {\r
+                       var t = this, w = t.windows[id];\r
+\r
+                       w.zIndex = this.zIndex++;\r
+                       w.element.setStyle('zIndex', w.zIndex);\r
+                       w.element.update();\r
+\r
+                       id = id + '_wrapper';\r
+                       DOM.removeClass(t.lastId, 'mceFocus');\r
+                       DOM.addClass(id, 'mceFocus');\r
+                       t.lastId = id;\r
+               },\r
+\r
+               _addAll : function(te, ne) {\r
+                       var i, n, t = this, dom = tinymce.DOM;\r
+\r
+                       if (is(ne, 'string'))\r
+                               te.appendChild(dom.doc.createTextNode(ne));\r
+                       else if (ne.length) {\r
+                               te = te.appendChild(dom.create(ne[0], ne[1]));\r
+\r
+                               for (i=2; i<ne.length; i++)\r
+                                       t._addAll(te, ne[i]);\r
+                       }\r
+               },\r
+\r
+               _startDrag : function(id, se, ac) {\r
+                       var t = this, mu, mm, d = DOM.doc, eb, w = t.windows[id], we = w.element, sp = we.getXY(), p, sz, ph, cp, vp, sx, sy, sex, sey, dx, dy, dw, dh;\r
+\r
+                       // Get positons and sizes\r
+//                     cp = DOM.getPos(t.editor.getContainer());\r
+                       cp = {x : 0, y : 0};\r
+                       vp = DOM.getViewPort();\r
+\r
+                       // Reduce viewport size to avoid scrollbars while dragging\r
+                       vp.w -= 2;\r
+                       vp.h -= 2;\r
+\r
+                       sex = se.screenX;\r
+                       sey = se.screenY;\r
+                       dx = dy = dw = dh = 0;\r
+\r
+                       // Handle mouse up\r
+                       mu = Event.add(d, 'mouseup', function(e) {\r
+                               Event.remove(d, 'mouseup', mu);\r
+                               Event.remove(d, 'mousemove', mm);\r
+\r
+                               if (eb)\r
+                                       eb.remove();\r
+\r
+                               we.moveBy(dx, dy);\r
+                               we.resizeBy(dw, dh);\r
+                               sz = we.getSize();\r
+                               DOM.setStyles(id + '_ifr', {width : sz.w - w.deltaWidth, height : sz.h - w.deltaHeight});\r
+                               t._fixIELayout(id, 1);\r
+\r
+                               return Event.cancel(e);\r
+                       });\r
+\r
+                       if (ac != 'Move')\r
+                               startMove();\r
+\r
+                       function startMove() {\r
+                               if (eb)\r
+                                       return;\r
+\r
+                               t._fixIELayout(id, 0);\r
+\r
+                               // Setup event blocker\r
+                               DOM.add(d.body, 'div', {\r
+                                       id : 'mceEventBlocker',\r
+                                       'class' : 'mceEventBlocker ' + (t.editor.settings.inlinepopups_skin || 'clearlooks2'),\r
+                                       style : {left : vp.x, top : vp.y, zIndex : t.zIndex + 1}\r
+                               });\r
+                               eb = new Element('mceEventBlocker');\r
+                               eb.update();\r
+\r
+                               // Setup placeholder\r
+                               p = we.getXY();\r
+                               sz = we.getSize();\r
+                               sx = cp.x + p.x - vp.x;\r
+                               sy = cp.y + p.y - vp.y;\r
+                               DOM.add(eb.get(), 'div', {id : 'mcePlaceHolder', 'class' : 'mcePlaceHolder', style : {left : sx, top : sy, width : sz.w, height : sz.h}});\r
+                               ph = new Element('mcePlaceHolder');\r
+                       };\r
+\r
+                       // Handle mouse move/drag\r
+                       mm = Event.add(d, 'mousemove', function(e) {\r
+                               var x, y, v;\r
+\r
+                               startMove();\r
+\r
+                               x = e.screenX - sex;\r
+                               y = e.screenY - sey;\r
+\r
+                               switch (ac) {\r
+                                       case 'ResizeW':\r
+                                               dx = x;\r
+                                               dw = 0 - x;\r
+                                               break;\r
+\r
+                                       case 'ResizeE':\r
+                                               dw = x;\r
+                                               break;\r
+\r
+                                       case 'ResizeN':\r
+                                       case 'ResizeNW':\r
+                                       case 'ResizeNE':\r
+                                               if (ac == "ResizeNW") {\r
+                                                       dx = x;\r
+                                                       dw = 0 - x;\r
+                                               } else if (ac == "ResizeNE")\r
+                                                       dw = x;\r
+\r
+                                               dy = y;\r
+                                               dh = 0 - y;\r
+                                               break;\r
+\r
+                                       case 'ResizeS':\r
+                                       case 'ResizeSW':\r
+                                       case 'ResizeSE':\r
+                                               if (ac == "ResizeSW") {\r
+                                                       dx = x;\r
+                                                       dw = 0 - x;\r
+                                               } else if (ac == "ResizeSE")\r
+                                                       dw = x;\r
+\r
+                                               dh = y;\r
+                                               break;\r
+\r
+                                       case 'mceMove':\r
+                                               dx = x;\r
+                                               dy = y;\r
+                                               break;\r
+                               }\r
+\r
+                               // Boundary check\r
+                               if (dw < (v = w.features.min_width - sz.w)) {\r
+                                       if (dx !== 0)\r
+                                               dx += dw - v;\r
+\r
+                                       dw = v;\r
+                               }\r
+       \r
+                               if (dh < (v = w.features.min_height - sz.h)) {\r
+                                       if (dy !== 0)\r
+                                               dy += dh - v;\r
+\r
+                                       dh = v;\r
+                               }\r
+\r
+                               dw = Math.min(dw, w.features.max_width - sz.w);\r
+                               dh = Math.min(dh, w.features.max_height - sz.h);\r
+                               dx = Math.max(dx, vp.x - (sx + vp.x));\r
+                               dy = Math.max(dy, vp.y - (sy + vp.y));\r
+                               dx = Math.min(dx, (vp.w + vp.x) - (sx + sz.w + vp.x));\r
+                               dy = Math.min(dy, (vp.h + vp.y) - (sy + sz.h + vp.y));\r
+\r
+                               // Move if needed\r
+                               if (dx + dy !== 0) {\r
+                                       if (sx + dx < 0)\r
+                                               dx = 0;\r
+       \r
+                                       if (sy + dy < 0)\r
+                                               dy = 0;\r
+\r
+                                       ph.moveTo(sx + dx, sy + dy);\r
+                               }\r
+\r
+                               // Resize if needed\r
+                               if (dw + dh !== 0)\r
+                                       ph.resizeTo(sz.w + dw, sz.h + dh);\r
+\r
+                               return Event.cancel(e);\r
+                       });\r
+\r
+                       return Event.cancel(se);\r
+               },\r
+\r
+               resizeBy : function(dw, dh, id) {\r
+                       var w = this.windows[id];\r
+\r
+                       if (w) {\r
+                               w.element.resizeBy(dw, dh);\r
+                               w.iframeElement.resizeBy(dw, dh);\r
+                       }\r
+               },\r
+\r
+               close : function(win, id) {\r
+                       var t = this, w, d = DOM.doc, ix = 0, fw;\r
+\r
+                       t.count--;\r
+\r
+                       if (t.count == 0)\r
+                               DOM.remove('mceModalBlocker');\r
+\r
+                       // Probably not inline\r
+                       if (!id && win) {\r
+                               t.parent(win);\r
+                               return;\r
+                       }\r
+\r
+                       if (w = t.windows[id]) {\r
+                               t.onClose.dispatch(t);\r
+                               Event.remove(d, 'mousedown', w.mousedownFunc);\r
+                               Event.remove(d, 'click', w.clickFunc);\r
+                               Event.clear(id);\r
+                               Event.clear(id + '_ifr');\r
+\r
+                               DOM.setAttrib(id + '_ifr', 'src', 'javascript:""'); // Prevent leak\r
+                               w.element.remove();\r
+                               delete t.windows[id];\r
+\r
+                               // Find front most window and focus that\r
+                               each (t.windows, function(w) {\r
+                                       if (w.zIndex > ix) {\r
+                                               fw = w;\r
+                                               ix = w.zIndex;\r
+                                       }\r
+                               });\r
+\r
+                               if (fw)\r
+                                       t.focus(fw.id);\r
+                       }\r
+               },\r
+\r
+               setTitle : function(ti, id) {\r
+                       var e;\r
+\r
+                       if (e = DOM.get(id + '_title'))\r
+                               e.innerHTML = DOM.encode(ti);\r
+               },\r
+\r
+               alert : function(txt, cb, s) {\r
+                       var t = this, w;\r
+\r
+                       w = t.open({\r
+                               title : t,\r
+                               type : 'alert',\r
+                               button_func : function(s) {\r
+                                       if (cb)\r
+                                               cb.call(s || t, s);\r
+\r
+                                       t.close(null, w.id);\r
+                               },\r
+                               content : DOM.encode(t.editor.getLang(txt, txt)),\r
+                               inline : 1,\r
+                               width : 400,\r
+                               height : 130\r
+                       });\r
+               },\r
+\r
+               confirm : function(txt, cb, s) {\r
+                       var t = this, w;\r
+\r
+                       w = t.open({\r
+                               title : t,\r
+                               type : 'confirm',\r
+                               button_func : function(s) {\r
+                                       if (cb)\r
+                                               cb.call(s || t, s);\r
+\r
+                                       t.close(null, w.id);\r
+                               },\r
+                               content : DOM.encode(t.editor.getLang(txt, txt)),\r
+                               inline : 1,\r
+                               width : 400,\r
+                               height : 130\r
+                       });\r
+               },\r
+\r
+               // Internal functions\r
+\r
+               _fixIELayout : function(id, s) {\r
+                       var w, img;\r
+\r
+                       if (!tinymce.isIE6)\r
+                               return;\r
+\r
+                       // Fixes the bug where hover flickers and does odd things in IE6\r
+                       each(['n','s','w','e','nw','ne','sw','se'], function(v) {\r
+                               var e = DOM.get(id + '_resize_' + v);\r
+\r
+                               DOM.setStyles(e, {\r
+                                       width : s ? e.clientWidth : '',\r
+                                       height : s ? e.clientHeight : '',\r
+                                       cursor : DOM.getStyle(e, 'cursor', 1)\r
+                               });\r
+\r
+                               DOM.setStyle(id + "_bottom", 'bottom', '-1px');\r
+\r
+                               e = 0;\r
+                       });\r
+\r
+                       // Fixes graphics glitch\r
+                       if (w = this.windows[id]) {\r
+                               // Fixes rendering bug after resize\r
+                               w.element.hide();\r
+                               w.element.show();\r
+\r
+                               // Forced a repaint of the window\r
+                               //DOM.get(id).style.filter = '';\r
+\r
+                               // IE has a bug where images used in CSS won't get loaded\r
+                               // sometimes when the cache in the browser is disabled\r
+                               // This fix tries to solve it by loading the images using the image object\r
+                               each(DOM.select('div,a', id), function(e, i) {\r
+                                       if (e.currentStyle.backgroundImage != 'none') {\r
+                                               img = new Image();\r
+                                               img.src = e.currentStyle.backgroundImage.replace(/url\(\"(.+)\"\)/, '$1');\r
+                                       }\r
+                               });\r
+\r
+                               DOM.get(id).style.filter = '';\r
+                       }\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('inlinepopups', tinymce.plugins.InlinePopups);\r
+})();\r
+\r
diff --git a/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif b/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif
new file mode 100644 (file)
index 0000000..94abd08
Binary files /dev/null and b/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif differ
diff --git a/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/button.gif b/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/button.gif
new file mode 100644 (file)
index 0000000..e671094
Binary files /dev/null and b/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/button.gif differ
diff --git a/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif b/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif
new file mode 100644 (file)
index 0000000..6baf64a
Binary files /dev/null and b/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif differ
diff --git a/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif b/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif
new file mode 100644 (file)
index 0000000..497307a
Binary files /dev/null and b/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif differ
diff --git a/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif b/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif
new file mode 100644 (file)
index 0000000..c894b2e
Binary files /dev/null and b/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif differ
diff --git a/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif b/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif
new file mode 100644 (file)
index 0000000..c2a2ad4
Binary files /dev/null and b/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif differ
diff --git a/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif b/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif
new file mode 100644 (file)
index 0000000..43a735f
Binary files /dev/null and b/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif differ
diff --git a/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/window.css b/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/window.css
new file mode 100644 (file)
index 0000000..4036922
--- /dev/null
@@ -0,0 +1,90 @@
+/* Clearlooks 2 */
+
+/* Reset */
+.clearlooks2, .clearlooks2 div, .clearlooks2 span, .clearlooks2 a {vertical-align:baseline; text-align:left; position:absolute; border:0; padding:0; margin:0; background:transparent; font-family:Arial,Verdana; font-size:11px; color:#000; text-decoration:none; font-weight:normal; width:auto; height:auto; overflow:hidden; display:block}
+
+/* General */
+.clearlooks2 {position:absolute; direction:ltr}
+.clearlooks2 .mceWrapper {position:static}
+.mceEventBlocker {position:absolute; left:0; top:0; background:url(img/horizontal.gif) no-repeat 0 -75px; width:100%; height:100%}
+.clearlooks2 .mcePlaceHolder {border:1px solid #000; background:#888; top:0; left:0; opacity:0.5; filter:alpha(opacity=50)}
+.clearlooks2_modalBlocker {position:absolute; left:0; top:0; width:100%; height:100%; background:#FFF; opacity:0.6; filter:alpha(opacity=60); display:none}
+
+/* Top */
+.clearlooks2 .mceTop, .clearlooks2 .mceTop div {top:0; width:100%; height:23px}
+.clearlooks2 .mceTop .mceLeft {width:6px; background:url(img/corners.gif)}
+.clearlooks2 .mceTop .mceCenter {right:6px; width:100%; height:23px; background:url(img/horizontal.gif) 12px 0; clip:rect(auto auto auto 12px)}
+.clearlooks2 .mceTop .mceRight {right:0; width:6px; height:23px; background:url(img/corners.gif) -12px 0}
+.clearlooks2 .mceTop span {width:100%; text-align:center; vertical-align:middle; line-height:23px; font-weight:bold}
+.clearlooks2 .mceFocus .mceTop .mceLeft {background:url(img/corners.gif) -6px 0}
+.clearlooks2 .mceFocus .mceTop .mceCenter {background:url(img/horizontal.gif) 0 -23px}
+.clearlooks2 .mceFocus .mceTop .mceRight {background:url(img/corners.gif) -18px 0}
+.clearlooks2 .mceFocus .mceTop span {color:#FFF}
+
+/* Middle */
+.clearlooks2 .mceMiddle, .clearlooks2 .mceMiddle div {top:0}
+.clearlooks2 .mceMiddle {width:100%; height:100%; clip:rect(23px auto auto auto)}
+.clearlooks2 .mceMiddle .mceLeft {left:0; width:5px; height:100%; background:url(img/vertical.gif) -5px 0}
+.clearlooks2 .mceMiddle span {top:23px; left:5px; width:100%; height:100%; background:#FFF}
+.clearlooks2 .mceMiddle .mceRight {right:0; width:5px; height:100%; background:url(img/vertical.gif)}
+
+/* Bottom */
+.clearlooks2 .mceBottom, .clearlooks2 .mceBottom div {height:6px}
+.clearlooks2 .mceBottom {left:0; bottom:0; width:100%}
+.clearlooks2 .mceBottom div {top:0}
+.clearlooks2 .mceBottom .mceLeft {left:0; width:5px; background:url(img/corners.gif) -34px -6px}
+.clearlooks2 .mceBottom .mceCenter {left:5px; width:100%; background:url(img/horizontal.gif) 0 -46px}
+.clearlooks2 .mceBottom .mceRight {right:0; width:5px; background: url(img/corners.gif) -34px 0}
+.clearlooks2 .mceBottom span {display:none}
+.clearlooks2 .mceStatusbar .mceBottom, .clearlooks2 .mceStatusbar .mceBottom div {height:23px}
+.clearlooks2 .mceStatusbar .mceBottom .mceLeft {background:url(img/corners.gif) -29px 0}
+.clearlooks2 .mceStatusbar .mceBottom .mceCenter {background:url(img/horizontal.gif) 0 -52px}
+.clearlooks2 .mceStatusbar .mceBottom .mceRight {background:url(img/corners.gif) -24px 0}
+.clearlooks2 .mceStatusbar .mceBottom span {display:block; left:7px; font-family:Arial, Verdana; font-size:11px; line-height:23px}
+
+/* Actions */
+.clearlooks2 a {width:29px; height:16px; top:3px;}
+.clearlooks2 .mceClose {right:6px; background:url(img/buttons.gif) -87px 0}
+.clearlooks2 .mceMin {display:none; right:68px; background:url(img/buttons.gif) 0 0}
+.clearlooks2 .mceMed {display:none; right:37px; background:url(img/buttons.gif) -29px 0}
+.clearlooks2 .mceMax {display:none; right:37px; background:url(img/buttons.gif) -58px 0}
+.clearlooks2 .mceMove {display:none;width:100%;cursor:move;background:url(img/corners.gif) no-repeat -100px -100px}
+.clearlooks2 .mceMovable .mceMove {display:block}
+.clearlooks2 .mceFocus .mceClose {right:6px; background:url(img/buttons.gif) -87px -16px}
+.clearlooks2 .mceFocus .mceMin {right:68px; background:url(img/buttons.gif) 0 -16px}
+.clearlooks2 .mceFocus .mceMed {right:37px; background:url(img/buttons.gif) -29px -16px}
+.clearlooks2 .mceFocus .mceMax {right:37px; background:url(img/buttons.gif) -58px -16px}
+.clearlooks2 .mceFocus .mceClose:hover {right:6px; background:url(img/buttons.gif) -87px -32px}
+.clearlooks2 .mceFocus .mceClose:hover {right:6px; background:url(img/buttons.gif) -87px -32px}
+.clearlooks2 .mceFocus .mceMin:hover {right:68px; background:url(img/buttons.gif) 0 -32px}
+.clearlooks2 .mceFocus .mceMed:hover {right:37px; background:url(img/buttons.gif) -29px -32px}
+.clearlooks2 .mceFocus .mceMax:hover {right:37px; background:url(img/buttons.gif) -58px -32px}
+
+/* Resize */
+.clearlooks2 .mceResize {top:auto; left:auto; display:none; width:5px; height:5px; background:url(img/horizontal.gif) no-repeat 0 -75px}
+.clearlooks2 .mceResizable .mceResize {display:block}
+.clearlooks2 .mceResizable .mceMin, .clearlooks2 .mceMax {display:none}
+.clearlooks2 .mceMinimizable .mceMin {display:block}
+.clearlooks2 .mceMaximizable .mceMax {display:block}
+.clearlooks2 .mceMaximized .mceMed {display:block}
+.clearlooks2 .mceMaximized .mceMax {display:none}
+.clearlooks2 a.mceResizeN {top:0; left:0; width:100%; cursor:n-resize}
+.clearlooks2 a.mceResizeNW {top:0; left:0; cursor:nw-resize}
+.clearlooks2 a.mceResizeNE {top:0; right:0; cursor:ne-resize}
+.clearlooks2 a.mceResizeW {top:0; left:0; height:100%; cursor:w-resize;}
+.clearlooks2 a.mceResizeE {top:0; right:0; height:100%; cursor:e-resize}
+.clearlooks2 a.mceResizeS {bottom:0; left:0; width:100%; cursor:s-resize}
+.clearlooks2 a.mceResizeSW {bottom:0; left:0; cursor:sw-resize}
+.clearlooks2 a.mceResizeSE {bottom:0; right:0; cursor:se-resize}
+
+/* Alert/Confirm */
+.clearlooks2 .mceButton {font-weight:bold; bottom:10px; width:80px; height:30px; background:url(img/button.gif); line-height:30px; vertical-align:middle; text-align:center; outline:0}
+.clearlooks2 .mceMiddle .mceIcon {left:15px; top:35px; width:32px; height:32px}
+.clearlooks2 .mceAlert .mceMiddle span, .clearlooks2 .mceConfirm .mceMiddle span {background:transparent;left:60px; top:35px; width:320px; height:50px; font-weight:bold; overflow:auto; white-space:normal}
+.clearlooks2 a:hover {font-weight:bold;}
+.clearlooks2 .mceAlert .mceMiddle, .clearlooks2 .mceConfirm .mceMiddle {background:#D6D7D5}
+.clearlooks2 .mceAlert .mceOk {left:50%; top:auto; margin-left: -40px}
+.clearlooks2 .mceAlert .mceIcon {background:url(img/alert.gif)}
+.clearlooks2 .mceConfirm .mceOk {left:50%; top:auto; margin-left: -90px}
+.clearlooks2 .mceConfirm .mceCancel {left:50%; top:auto}
+.clearlooks2 .mceConfirm .mceIcon {background:url(img/confirm.gif)} 
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/inlinepopups/template.htm b/jscripts/tiny_mce/plugins/inlinepopups/template.htm
new file mode 100644 (file)
index 0000000..b153821
--- /dev/null
@@ -0,0 +1,387 @@
+<!-- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -->\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<title>Template for dialogs</title>\r
+<link rel="stylesheet" type="text/css" href="skins/clearlooks2/window.css?v=307" />\r
+</head>\r
+<body>\r
+\r
+<div class="mceEditor">\r
+       <div class="clearlooks2" style="width:400px; height:100px; left:10px;">\r
+               <div class="mceWrapper">\r
+                       <div class="mceTop">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Blured</span>\r
+                       </div>\r
+\r
+                       <div class="mceMiddle">\r
+                               <div class="mceLeft"></div>\r
+                               <span>Content</span>\r
+                               <div class="mceRight"></div>\r
+                       </div>\r
+\r
+                       <div class="mceBottom">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Statusbar text.</span>\r
+                       </div>\r
+\r
+                       <a class="mceMove" href="#"></a>\r
+                       <a class="mceMin" href="#"></a>\r
+                       <a class="mceMax" href="#"></a>\r
+                       <a class="mceMed" href="#"></a>\r
+                       <a class="mceClose" href="#"></a>\r
+                       <a class="mceResize mceResizeN" href="#"></a>\r
+                       <a class="mceResize mceResizeS" href="#"></a>\r
+                       <a class="mceResize mceResizeW" href="#"></a>\r
+                       <a class="mceResize mceResizeE" href="#"></a>\r
+                       <a class="mceResize mceResizeNW" href="#"></a>\r
+                       <a class="mceResize mceResizeNE" href="#"></a>\r
+                       <a class="mceResize mceResizeSW" href="#"></a>\r
+                       <a class="mceResize mceResizeSE" href="#"></a>\r
+               </div>\r
+       </div>\r
+\r
+       <div class="clearlooks2" style="width:400px; height:100px; left:420px;">\r
+               <div class="mceWrapper mceMovable mceFocus">\r
+                       <div class="mceTop">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Focused</span>\r
+                       </div>\r
+\r
+                       <div class="mceMiddle">\r
+                               <div class="mceLeft"></div>\r
+                               <span>Content</span>\r
+                               <div class="mceRight"></div>\r
+                       </div>\r
+\r
+                       <div class="mceBottom">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Statusbar text.</span>\r
+                       </div>\r
+\r
+                       <a class="mceMove" href="#"></a>\r
+                       <a class="mceMin" href="#"></a>\r
+                       <a class="mceMax" href="#"></a>\r
+                       <a class="mceMed" href="#"></a>\r
+                       <a class="mceClose" href="#"></a>\r
+                       <a class="mceResize mceResizeN" href="#"></a>\r
+                       <a class="mceResize mceResizeS" href="#"></a>\r
+                       <a class="mceResize mceResizeW" href="#"></a>\r
+                       <a class="mceResize mceResizeE" href="#"></a>\r
+                       <a class="mceResize mceResizeNW" href="#"></a>\r
+                       <a class="mceResize mceResizeNE" href="#"></a>\r
+                       <a class="mceResize mceResizeSW" href="#"></a>\r
+                       <a class="mceResize mceResizeSE" href="#"></a>\r
+               </div>\r
+       </div>\r
+\r
+       <div class="clearlooks2" style="width:400px; height:100px; left:10px; top:120px;">\r
+               <div class="mceWrapper mceMovable mceFocus mceStatusbar">\r
+                       <div class="mceTop">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Statusbar</span>\r
+                       </div>\r
+\r
+                       <div class="mceMiddle">\r
+                               <div class="mceLeft"></div>\r
+                               <span>Content</span>\r
+                               <div class="mceRight"></div>\r
+                       </div>\r
+\r
+                       <div class="mceBottom">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Statusbar text.</span>\r
+                       </div>\r
+\r
+                       <a class="mceMove" href="#"></a>\r
+                       <a class="mceMin" href="#"></a>\r
+                       <a class="mceMax" href="#"></a>\r
+                       <a class="mceMed" href="#"></a>\r
+                       <a class="mceClose" href="#"></a>\r
+                       <a class="mceResize mceResizeN" href="#"></a>\r
+                       <a class="mceResize mceResizeS" href="#"></a>\r
+                       <a class="mceResize mceResizeW" href="#"></a>\r
+                       <a class="mceResize mceResizeE" href="#"></a>\r
+                       <a class="mceResize mceResizeNW" href="#"></a>\r
+                       <a class="mceResize mceResizeNE" href="#"></a>\r
+                       <a class="mceResize mceResizeSW" href="#"></a>\r
+                       <a class="mceResize mceResizeSE" href="#"></a>\r
+               </div>\r
+       </div>\r
+\r
+       <div class="clearlooks2" style="width:400px; height:100px; left:420px; top:120px;">\r
+               <div class="mceWrapper mceMovable mceFocus mceStatusbar mceResizable">\r
+                       <div class="mceTop">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Statusbar, Resizable</span>\r
+                       </div>\r
+\r
+                       <div class="mceMiddle">\r
+                               <div class="mceLeft"></div>\r
+                               <span>Content</span>\r
+                               <div class="mceRight"></div>\r
+                       </div>\r
+\r
+                       <div class="mceBottom">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Statusbar text.</span>\r
+                       </div>\r
+\r
+                       <a class="mceMove" href="#"></a>\r
+                       <a class="mceMin" href="#"></a>\r
+                       <a class="mceMax" href="#"></a>\r
+                       <a class="mceMed" href="#"></a>\r
+                       <a class="mceClose" href="#"></a>\r
+                       <a class="mceResize mceResizeN" href="#"></a>\r
+                       <a class="mceResize mceResizeS" href="#"></a>\r
+                       <a class="mceResize mceResizeW" href="#"></a>\r
+                       <a class="mceResize mceResizeE" href="#"></a>\r
+                       <a class="mceResize mceResizeNW" href="#"></a>\r
+                       <a class="mceResize mceResizeNE" href="#"></a>\r
+                       <a class="mceResize mceResizeSW" href="#"></a>\r
+                       <a class="mceResize mceResizeSE" href="#"></a>\r
+               </div>\r
+       </div>\r
+\r
+       <div class="clearlooks2" style="width:400px; height:100px; left:10px; top:230px;">\r
+               <div class="mceWrapper mceMovable mceFocus mceResizable mceMaximizable">\r
+                       <div class="mceTop">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Resizable, Maximizable</span>\r
+                       </div>\r
+\r
+                       <div class="mceMiddle">\r
+                               <div class="mceLeft"></div>\r
+                               <span>Content</span>\r
+                               <div class="mceRight"></div>\r
+                       </div>\r
+\r
+                       <div class="mceBottom">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Statusbar text.</span>\r
+                       </div>\r
+\r
+                       <a class="mceMove" href="#"></a>\r
+                       <a class="mceMin" href="#"></a>\r
+                       <a class="mceMax" href="#"></a>\r
+                       <a class="mceMed" href="#"></a>\r
+                       <a class="mceClose" href="#"></a>\r
+                       <a class="mceResize mceResizeN" href="#"></a>\r
+                       <a class="mceResize mceResizeS" href="#"></a>\r
+                       <a class="mceResize mceResizeW" href="#"></a>\r
+                       <a class="mceResize mceResizeE" href="#"></a>\r
+                       <a class="mceResize mceResizeNW" href="#"></a>\r
+                       <a class="mceResize mceResizeNE" href="#"></a>\r
+                       <a class="mceResize mceResizeSW" href="#"></a>\r
+                       <a class="mceResize mceResizeSE" href="#"></a>\r
+               </div>\r
+       </div>\r
+\r
+       <div class="clearlooks2" style="width:400px; height:100px; left:420px; top:230px;">\r
+               <div class="mceWrapper mceMovable mceStatusbar mceResizable mceMaximizable">\r
+                       <div class="mceTop">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Blurred, Maximizable, Statusbar, Resizable</span>\r
+                       </div>\r
+\r
+                       <div class="mceMiddle">\r
+                               <div class="mceLeft"></div>\r
+                               <span>Content</span>\r
+                               <div class="mceRight"></div>\r
+                       </div>\r
+\r
+                       <div class="mceBottom">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Statusbar text.</span>\r
+                       </div>\r
+\r
+                       <a class="mceMove" href="#"></a>\r
+                       <a class="mceMin" href="#"></a>\r
+                       <a class="mceMax" href="#"></a>\r
+                       <a class="mceMed" href="#"></a>\r
+                       <a class="mceClose" href="#"></a>\r
+                       <a class="mceResize mceResizeN" href="#"></a>\r
+                       <a class="mceResize mceResizeS" href="#"></a>\r
+                       <a class="mceResize mceResizeW" href="#"></a>\r
+                       <a class="mceResize mceResizeE" href="#"></a>\r
+                       <a class="mceResize mceResizeNW" href="#"></a>\r
+                       <a class="mceResize mceResizeNE" href="#"></a>\r
+                       <a class="mceResize mceResizeSW" href="#"></a>\r
+                       <a class="mceResize mceResizeSE" href="#"></a>\r
+               </div>\r
+       </div>\r
+\r
+       <div class="clearlooks2" style="width:400px; height:100px; left:10px; top:340px;">\r
+               <div class="mceWrapper mceMovable mceFocus mceResizable mceMaximized mceMinimizable mceMaximizable">\r
+                       <div class="mceTop">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Maximized, Maximizable, Minimizable</span>\r
+                       </div>\r
+\r
+                       <div class="mceMiddle">\r
+                               <div class="mceLeft"></div>\r
+                               <span>Content</span>\r
+                               <div class="mceRight"></div>\r
+                       </div>\r
+\r
+                       <div class="mceBottom">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Statusbar text.</span>\r
+                       </div>\r
+\r
+                       <a class="mceMove" href="#"></a>\r
+                       <a class="mceMin" href="#"></a>\r
+                       <a class="mceMax" href="#"></a>\r
+                       <a class="mceMed" href="#"></a>\r
+                       <a class="mceClose" href="#"></a>\r
+                       <a class="mceResize mceResizeN" href="#"></a>\r
+                       <a class="mceResize mceResizeS" href="#"></a>\r
+                       <a class="mceResize mceResizeW" href="#"></a>\r
+                       <a class="mceResize mceResizeE" href="#"></a>\r
+                       <a class="mceResize mceResizeNW" href="#"></a>\r
+                       <a class="mceResize mceResizeNE" href="#"></a>\r
+                       <a class="mceResize mceResizeSW" href="#"></a>\r
+                       <a class="mceResize mceResizeSE" href="#"></a>\r
+               </div>\r
+       </div>\r
+\r
+       <div class="clearlooks2" style="width:400px; height:100px; left:420px; top:340px;">\r
+               <div class="mceWrapper mceMovable mceStatusbar mceResizable mceMaximized mceMinimizable mceMaximizable">\r
+                       <div class="mceTop">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Blured</span>\r
+                       </div>\r
+\r
+                       <div class="mceMiddle">\r
+                               <div class="mceLeft"></div>\r
+                               <span>Content</span>\r
+                               <div class="mceRight"></div>\r
+                       </div>\r
+\r
+                       <div class="mceBottom">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Statusbar text.</span>\r
+                       </div>\r
+\r
+                       <a class="mceMove" href="#"></a>\r
+                       <a class="mceMin" href="#"></a>\r
+                       <a class="mceMax" href="#"></a>\r
+                       <a class="mceMed" href="#"></a>\r
+                       <a class="mceClose" href="#"></a>\r
+                       <a class="mceResize mceResizeN" href="#"></a>\r
+                       <a class="mceResize mceResizeS" href="#"></a>\r
+                       <a class="mceResize mceResizeW" href="#"></a>\r
+                       <a class="mceResize mceResizeE" href="#"></a>\r
+                       <a class="mceResize mceResizeNW" href="#"></a>\r
+                       <a class="mceResize mceResizeNE" href="#"></a>\r
+                       <a class="mceResize mceResizeSW" href="#"></a>\r
+                       <a class="mceResize mceResizeSE" href="#"></a>\r
+               </div>\r
+       </div>\r
+\r
+       <div class="clearlooks2" style="width:400px; height:130px; left:10px; top:450px;">\r
+               <div class="mceWrapper mceMovable mceFocus mceModal mceAlert">\r
+                       <div class="mceTop">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Alert</span>\r
+                       </div>\r
+\r
+                       <div class="mceMiddle">\r
+                               <div class="mceLeft"></div>\r
+                               <span>\r
+                                       This is a very long error message. This is a very long error message.\r
+                                       This is a very long error message. This is a very long error message.\r
+                                       This is a very long error message. This is a very long error message.\r
+                                       This is a very long error message. This is a very long error message.\r
+                                       This is a very long error message. This is a very long error message.\r
+                                       This is a very long error message. This is a very long error message.\r
+                               </span>\r
+                               <div class="mceRight"></div>\r
+                               <div class="mceIcon"></div>\r
+                       </div>\r
+\r
+                       <div class="mceBottom">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                       </div>\r
+\r
+                       <a class="mceMove" href="#"></a>\r
+                       <a class="mceButton mceOk" href="#">Ok</a>\r
+                       <a class="mceClose" href="#"></a>\r
+               </div>\r
+       </div>\r
+\r
+       <div class="clearlooks2" style="width:400px; height:130px; left:420px; top:450px;">\r
+               <div class="mceWrapper mceMovable mceFocus mceModal mceConfirm">\r
+                       <div class="mceTop">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                               <span>Confirm</span>\r
+                       </div>\r
+\r
+                       <div class="mceMiddle">\r
+                               <div class="mceLeft"></div>\r
+                               <span>\r
+                                       This is a very long error message. This is a very long error message.\r
+                                       This is a very long error message. This is a very long error message.\r
+                                       This is a very long error message. This is a very long error message.\r
+                                       This is a very long error message. This is a very long error message.\r
+                                       This is a very long error message. This is a very long error message.\r
+                                       This is a very long error message. This is a very long error message.\r
+                                       </span>\r
+                               <div class="mceRight"></div>\r
+                               <div class="mceIcon"></div>\r
+                       </div>\r
+\r
+                       <div class="mceBottom">\r
+                               <div class="mceLeft"></div>\r
+                               <div class="mceCenter"></div>\r
+                               <div class="mceRight"></div>\r
+                       </div>\r
+\r
+                       <a class="mceMove" href="#"></a>\r
+                       <a class="mceButton mceOk" href="#">Ok</a>\r
+                       <a class="mceButton mceCancel" href="#">Cancel</a>\r
+                       <a class="mceClose" href="#"></a>\r
+               </div>\r
+       </div>\r
+</div>\r
+\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/insertdatetime/editor_plugin.js b/jscripts/tiny_mce/plugins/insertdatetime/editor_plugin.js
new file mode 100644 (file)
index 0000000..34d4cec
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.InsertDateTime',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mceInsertDate',function(){var str=t._getDateTime(new Date(),ed.getParam("plugin_insertdate_dateFormat",ed.getLang('insertdatetime.date_fmt')));ed.execCommand('mceInsertContent',false,str);});ed.addCommand('mceInsertTime',function(){var str=t._getDateTime(new Date(),ed.getParam("plugin_insertdate_timeFormat",ed.getLang('insertdatetime.time_fmt')));ed.execCommand('mceInsertContent',false,str);});ed.addButton('insertdate',{title:'insertdatetime.insertdate_desc',cmd:'mceInsertDate'});ed.addButton('inserttime',{title:'insertdatetime.inserttime_desc',cmd:'mceInsertTime'});},getInfo:function(){return{longname:'Insert date/time',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/insertdatetime',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_getDateTime:function(d,fmt){var ed=this.editor;function addZeros(value,len){value=""+value;if(value.length<len){for(var i=0;i<(len-value.length);i++)value="0"+value;}return value;};fmt=fmt.replace("%D","%m/%d/%y");fmt=fmt.replace("%r","%I:%M:%S %p");fmt=fmt.replace("%Y",""+d.getFullYear());fmt=fmt.replace("%y",""+d.getYear());fmt=fmt.replace("%m",addZeros(d.getMonth()+1,2));fmt=fmt.replace("%d",addZeros(d.getDate(),2));fmt=fmt.replace("%H",""+addZeros(d.getHours(),2));fmt=fmt.replace("%M",""+addZeros(d.getMinutes(),2));fmt=fmt.replace("%S",""+addZeros(d.getSeconds(),2));fmt=fmt.replace("%I",""+((d.getHours()+11)%12+1));fmt=fmt.replace("%p",""+(d.getHours()<12?"AM":"PM"));fmt=fmt.replace("%B",""+ed.getLang("insertdatetime.months_long").split(',')[d.getMonth()]);fmt=fmt.replace("%b",""+ed.getLang("insertdatetime.months_short").split(',')[d.getMonth()]);fmt=fmt.replace("%A",""+ed.getLang("insertdatetime.day_long").split(',')[d.getDay()]);fmt=fmt.replace("%a",""+ed.getLang("insertdatetime.day_short").split(',')[d.getDay()]);fmt=fmt.replace("%%","%");return fmt;}});tinymce.PluginManager.add('insertdatetime',tinymce.plugins.InsertDateTime);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/insertdatetime/editor_plugin_src.js b/jscripts/tiny_mce/plugins/insertdatetime/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..9ab3135
--- /dev/null
@@ -0,0 +1,80 @@
+/**\r
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.InsertDateTime', {\r
+               init : function(ed, url) {\r
+                       var t = this;\r
+\r
+                       t.editor = ed;\r
+\r
+                       ed.addCommand('mceInsertDate', function() {\r
+                               var str = t._getDateTime(new Date(), ed.getParam("plugin_insertdate_dateFormat", ed.getLang('insertdatetime.date_fmt')));\r
+\r
+                               ed.execCommand('mceInsertContent', false, str);\r
+                       });\r
+\r
+                       ed.addCommand('mceInsertTime', function() {\r
+                               var str = t._getDateTime(new Date(), ed.getParam("plugin_insertdate_timeFormat", ed.getLang('insertdatetime.time_fmt')));\r
+\r
+                               ed.execCommand('mceInsertContent', false, str);\r
+                       });\r
+\r
+                       ed.addButton('insertdate', {title : 'insertdatetime.insertdate_desc', cmd : 'mceInsertDate'});\r
+                       ed.addButton('inserttime', {title : 'insertdatetime.inserttime_desc', cmd : 'mceInsertTime'});\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Insert date/time',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/insertdatetime',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               },\r
+\r
+               // Private methods\r
+\r
+               _getDateTime : function(d, fmt) {\r
+                       var ed = this.editor;\r
+\r
+                       function addZeros(value, len) {\r
+                               value = "" + value;\r
+\r
+                               if (value.length < len) {\r
+                                       for (var i=0; i<(len-value.length); i++)\r
+                                               value = "0" + value;\r
+                               }\r
+\r
+                               return value;\r
+                       };\r
+\r
+                       fmt = fmt.replace("%D", "%m/%d/%y");\r
+                       fmt = fmt.replace("%r", "%I:%M:%S %p");\r
+                       fmt = fmt.replace("%Y", "" + d.getFullYear());\r
+                       fmt = fmt.replace("%y", "" + d.getYear());\r
+                       fmt = fmt.replace("%m", addZeros(d.getMonth()+1, 2));\r
+                       fmt = fmt.replace("%d", addZeros(d.getDate(), 2));\r
+                       fmt = fmt.replace("%H", "" + addZeros(d.getHours(), 2));\r
+                       fmt = fmt.replace("%M", "" + addZeros(d.getMinutes(), 2));\r
+                       fmt = fmt.replace("%S", "" + addZeros(d.getSeconds(), 2));\r
+                       fmt = fmt.replace("%I", "" + ((d.getHours() + 11) % 12 + 1));\r
+                       fmt = fmt.replace("%p", "" + (d.getHours() < 12 ? "AM" : "PM"));\r
+                       fmt = fmt.replace("%B", "" + ed.getLang("insertdatetime.months_long").split(',')[d.getMonth()]);\r
+                       fmt = fmt.replace("%b", "" + ed.getLang("insertdatetime.months_short").split(',')[d.getMonth()]);\r
+                       fmt = fmt.replace("%A", "" + ed.getLang("insertdatetime.day_long").split(',')[d.getDay()]);\r
+                       fmt = fmt.replace("%a", "" + ed.getLang("insertdatetime.day_short").split(',')[d.getDay()]);\r
+                       fmt = fmt.replace("%%", "%");\r
+\r
+                       return fmt;\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('insertdatetime', tinymce.plugins.InsertDateTime);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/layer/editor_plugin.js b/jscripts/tiny_mce/plugins/layer/editor_plugin.js
new file mode 100644 (file)
index 0000000..4cd9427
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.Layer',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mceInsertLayer',t._insertLayer,t);ed.addCommand('mceMoveForward',function(){t._move(1);});ed.addCommand('mceMoveBackward',function(){t._move(-1);});ed.addCommand('mceMakeAbsolute',function(){t._toggleAbsolute();});ed.addButton('moveforward',{title:'layer.forward_desc',cmd:'mceMoveForward'});ed.addButton('movebackward',{title:'layer.backward_desc',cmd:'mceMoveBackward'});ed.addButton('absolute',{title:'layer.absolute_desc',cmd:'mceMakeAbsolute'});ed.addButton('insertlayer',{title:'layer.insertlayer_desc',cmd:'mceInsertLayer'});ed.onInit.add(function(){if(tinymce.isIE)ed.getDoc().execCommand('2D-Position',false,true);});ed.onNodeChange.add(t._nodeChange,t);ed.onVisualAid.add(t._visualAid,t);},getInfo:function(){return{longname:'Layer',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/layer',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_nodeChange:function(ed,cm,n){var le,p;le=this._getParentLayer(n);p=ed.dom.getParent(n,'DIV,P,IMG');if(!p){cm.setDisabled('absolute',1);cm.setDisabled('moveforward',1);cm.setDisabled('movebackward',1);}else{cm.setDisabled('absolute',0);cm.setDisabled('moveforward',!le);cm.setDisabled('movebackward',!le);cm.setActive('absolute',le&&le.style.position.toLowerCase()=="absolute");}},_visualAid:function(ed,e,s){var dom=ed.dom;tinymce.each(dom.select('div,p',e),function(e){if(/^(absolute|relative|static)$/i.test(e.style.position)){if(s)dom.addClass(e,'mceItemVisualAid');else dom.removeClass(e,'mceItemVisualAid');}});},_move:function(d){var ed=this.editor,i,z=[],le=this._getParentLayer(ed.selection.getNode()),ci=-1,fi=-1,nl;nl=[];tinymce.walk(ed.getBody(),function(n){if(n.nodeType==1&&/^(absolute|relative|static)$/i.test(n.style.position))nl.push(n);},'childNodes');for(i=0;i<nl.length;i++){z[i]=nl[i].style.zIndex?parseInt(nl[i].style.zIndex):0;if(ci<0&&nl[i]==le)ci=i;}if(d<0){for(i=0;i<z.length;i++){if(z[i]<z[ci]){fi=i;break;}}if(fi>-1){nl[ci].style.zIndex=z[fi];nl[fi].style.zIndex=z[ci];}else{if(z[ci]>0)nl[ci].style.zIndex=z[ci]-1;}}else{for(i=0;i<z.length;i++){if(z[i]>z[ci]){fi=i;break;}}if(fi>-1){nl[ci].style.zIndex=z[fi];nl[fi].style.zIndex=z[ci];}else nl[ci].style.zIndex=z[ci]+1;}ed.execCommand('mceRepaint');},_getParentLayer:function(n){return this.editor.dom.getParent(n,function(n){return n.nodeType==1&&/^(absolute|relative|static)$/i.test(n.style.position);});},_insertLayer:function(){var ed=this.editor,p=ed.dom.getPos(ed.dom.getParent(ed.selection.getNode(),'*'));ed.dom.add(ed.getBody(),'div',{style:{position:'absolute',left:p.x,top:(p.y>20?p.y:20),width:100,height:100},'class':'mceItemVisualAid'},ed.selection.getContent()||ed.getLang('layer.content'));},_toggleAbsolute:function(){var ed=this.editor,le=this._getParentLayer(ed.selection.getNode());if(!le)le=ed.dom.getParent(ed.selection.getNode(),'DIV,P,IMG');if(le){if(le.style.position.toLowerCase()=="absolute"){ed.dom.setStyles(le,{position:'',left:'',top:'',width:'',height:''});ed.dom.removeClass(le,'mceItemVisualAid');}else{if(le.style.left=="")le.style.left=20+'px';if(le.style.top=="")le.style.top=20+'px';if(le.style.width=="")le.style.width=le.width?(le.width+'px'):'100px';if(le.style.height=="")le.style.height=le.height?(le.height+'px'):'100px';le.style.position="absolute";ed.addVisual(ed.getBody());}ed.execCommand('mceRepaint');ed.nodeChanged();}}});tinymce.PluginManager.add('layer',tinymce.plugins.Layer);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/layer/editor_plugin_src.js b/jscripts/tiny_mce/plugins/layer/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..a72f6c3
--- /dev/null
@@ -0,0 +1,209 @@
+/**\r
+ * $Id: editor_plugin_src.js 652 2008-02-29 13:09:46Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.Layer', {\r
+               init : function(ed, url) {\r
+                       var t = this;\r
+\r
+                       t.editor = ed;\r
+\r
+                       // Register commands\r
+                       ed.addCommand('mceInsertLayer', t._insertLayer, t);\r
+\r
+                       ed.addCommand('mceMoveForward', function() {\r
+                               t._move(1);\r
+                       });\r
+\r
+                       ed.addCommand('mceMoveBackward', function() {\r
+                               t._move(-1);\r
+                       });\r
+\r
+                       ed.addCommand('mceMakeAbsolute', function() {\r
+                               t._toggleAbsolute();\r
+                       });\r
+\r
+                       // Register buttons\r
+                       ed.addButton('moveforward', {title : 'layer.forward_desc', cmd : 'mceMoveForward'});\r
+                       ed.addButton('movebackward', {title : 'layer.backward_desc', cmd : 'mceMoveBackward'});\r
+                       ed.addButton('absolute', {title : 'layer.absolute_desc', cmd : 'mceMakeAbsolute'});\r
+                       ed.addButton('insertlayer', {title : 'layer.insertlayer_desc', cmd : 'mceInsertLayer'});\r
+\r
+                       ed.onInit.add(function() {\r
+                               if (tinymce.isIE)\r
+                                       ed.getDoc().execCommand('2D-Position', false, true);\r
+                       });\r
+\r
+                       ed.onNodeChange.add(t._nodeChange, t);\r
+                       ed.onVisualAid.add(t._visualAid, t);\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Layer',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/layer',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               },\r
+\r
+               // Private methods\r
+\r
+               _nodeChange : function(ed, cm, n) {\r
+                       var le, p;\r
+\r
+                       le = this._getParentLayer(n);\r
+                       p = ed.dom.getParent(n, 'DIV,P,IMG');\r
+\r
+                       if (!p) {\r
+                               cm.setDisabled('absolute', 1);\r
+                               cm.setDisabled('moveforward', 1);\r
+                               cm.setDisabled('movebackward', 1);\r
+                       } else {\r
+                               cm.setDisabled('absolute', 0);\r
+                               cm.setDisabled('moveforward', !le);\r
+                               cm.setDisabled('movebackward', !le);\r
+                               cm.setActive('absolute', le && le.style.position.toLowerCase() == "absolute");\r
+                       }\r
+               },\r
+\r
+               // Private methods\r
+\r
+               _visualAid : function(ed, e, s) {\r
+                       var dom = ed.dom;\r
+\r
+                       tinymce.each(dom.select('div,p', e), function(e) {\r
+                               if (/^(absolute|relative|static)$/i.test(e.style.position)) {\r
+                                       if (s)\r
+                                               dom.addClass(e, 'mceItemVisualAid');\r
+                                       else\r
+                                               dom.removeClass(e, 'mceItemVisualAid'); \r
+                               }\r
+                       });\r
+               },\r
+\r
+               _move : function(d) {\r
+                       var ed = this.editor, i, z = [], le = this._getParentLayer(ed.selection.getNode()), ci = -1, fi = -1, nl;\r
+\r
+                       nl = [];\r
+                       tinymce.walk(ed.getBody(), function(n) {\r
+                               if (n.nodeType == 1 && /^(absolute|relative|static)$/i.test(n.style.position))\r
+                                       nl.push(n); \r
+                       }, 'childNodes');\r
+\r
+                       // Find z-indexes\r
+                       for (i=0; i<nl.length; i++) {\r
+                               z[i] = nl[i].style.zIndex ? parseInt(nl[i].style.zIndex) : 0;\r
+\r
+                               if (ci < 0 && nl[i] == le)\r
+                                       ci = i;\r
+                       }\r
+\r
+                       if (d < 0) {\r
+                               // Move back\r
+\r
+                               // Try find a lower one\r
+                               for (i=0; i<z.length; i++) {\r
+                                       if (z[i] < z[ci]) {\r
+                                               fi = i;\r
+                                               break;\r
+                                       }\r
+                               }\r
+\r
+                               if (fi > -1) {\r
+                                       nl[ci].style.zIndex = z[fi];\r
+                                       nl[fi].style.zIndex = z[ci];\r
+                               } else {\r
+                                       if (z[ci] > 0)\r
+                                               nl[ci].style.zIndex = z[ci] - 1;\r
+                               }\r
+                       } else {\r
+                               // Move forward\r
+\r
+                               // Try find a higher one\r
+                               for (i=0; i<z.length; i++) {\r
+                                       if (z[i] > z[ci]) {\r
+                                               fi = i;\r
+                                               break;\r
+                                       }\r
+                               }\r
+\r
+                               if (fi > -1) {\r
+                                       nl[ci].style.zIndex = z[fi];\r
+                                       nl[fi].style.zIndex = z[ci];\r
+                               } else\r
+                                       nl[ci].style.zIndex = z[ci] + 1;\r
+                       }\r
+\r
+                       ed.execCommand('mceRepaint');\r
+               },\r
+\r
+               _getParentLayer : function(n) {\r
+                       return this.editor.dom.getParent(n, function(n) {\r
+                               return n.nodeType == 1 && /^(absolute|relative|static)$/i.test(n.style.position);\r
+                       });\r
+               },\r
+\r
+               _insertLayer : function() {\r
+                       var ed = this.editor, p = ed.dom.getPos(ed.dom.getParent(ed.selection.getNode(), '*'));\r
+\r
+                       ed.dom.add(ed.getBody(), 'div', {\r
+                               style : {\r
+                                       position : 'absolute',\r
+                                       left : p.x,\r
+                                       top : (p.y > 20 ? p.y : 20),\r
+                                       width : 100,\r
+                                       height : 100\r
+                               },\r
+                               'class' : 'mceItemVisualAid'\r
+                       }, ed.selection.getContent() || ed.getLang('layer.content'));\r
+               },\r
+\r
+               _toggleAbsolute : function() {\r
+                       var ed = this.editor, le = this._getParentLayer(ed.selection.getNode());\r
+\r
+                       if (!le)\r
+                               le = ed.dom.getParent(ed.selection.getNode(), 'DIV,P,IMG');\r
+\r
+                       if (le) {\r
+                               if (le.style.position.toLowerCase() == "absolute") {\r
+                                       ed.dom.setStyles(le, {\r
+                                               position : '',\r
+                                               left : '',\r
+                                               top : '',\r
+                                               width : '',\r
+                                               height : ''\r
+                                       });\r
+\r
+                                       ed.dom.removeClass(le, 'mceItemVisualAid');\r
+                               } else {\r
+                                       if (le.style.left == "")\r
+                                               le.style.left = 20 + 'px';\r
+\r
+                                       if (le.style.top == "")\r
+                                               le.style.top = 20 + 'px';\r
+\r
+                                       if (le.style.width == "")\r
+                                               le.style.width = le.width ? (le.width + 'px') : '100px';\r
+\r
+                                       if (le.style.height == "")\r
+                                               le.style.height = le.height ? (le.height + 'px') : '100px';\r
+\r
+                                       le.style.position = "absolute";\r
+                                       ed.addVisual(ed.getBody());\r
+                               }\r
+\r
+                               ed.execCommand('mceRepaint');\r
+                               ed.nodeChanged();\r
+                       }\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('layer', tinymce.plugins.Layer);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/media/css/content.css b/jscripts/tiny_mce/plugins/media/css/content.css
new file mode 100644 (file)
index 0000000..1bf6a75
--- /dev/null
@@ -0,0 +1,6 @@
+.mceItemFlash, .mceItemShockWave, .mceItemQuickTime, .mceItemWindowsMedia, .mceItemRealMedia {border:1px dotted #cc0000; background-position:center; background-repeat:no-repeat; background-color:#ffffcc;}\r
+.mceItemShockWave {background-image: url(../img/shockwave.gif);}\r
+.mceItemFlash {background-image:url(../img/flash.gif);}\r
+.mceItemQuickTime {background-image:url(../img/quicktime.gif);}\r
+.mceItemWindowsMedia {background-image:url(../img/windowsmedia.gif);}\r
+.mceItemRealMedia {background-image:url(../img/realmedia.gif);}\r
diff --git a/jscripts/tiny_mce/plugins/media/css/media.css b/jscripts/tiny_mce/plugins/media/css/media.css
new file mode 100644 (file)
index 0000000..89c6bd5
--- /dev/null
@@ -0,0 +1,68 @@
+#id, #name, #hspace, #vspace, #class_name, #align {\r
+       width: 100px;\r
+}\r
+\r
+#hspace, #vspace {\r
+       width: 50px;\r
+}\r
+\r
+#flash_quality, #flash_align, #flash_scale, #flash_salign, #flash_wmode {\r
+       width: 100px;\r
+}\r
+\r
+#flash_base, #flash_flashvars {\r
+       width: 240px;\r
+}\r
+\r
+#width, #height {\r
+       width: 40px;\r
+}\r
+\r
+#src, #media_type {\r
+       width: 250px;\r
+}\r
+\r
+#class {\r
+       width: 120px;\r
+}\r
+\r
+#prev {\r
+       margin: 0;\r
+       border: 1px solid black;\r
+       width: 99%;\r
+       height: 230px;\r
+       overflow: auto;\r
+}\r
+\r
+.panel_wrapper div.current {\r
+       height: 390px;\r
+       overflow: auto;\r
+}\r
+\r
+#flash_options, #shockwave_options, #qt_options, #wmp_options, #rmp_options {\r
+       display: none;\r
+}\r
+\r
+.mceAddSelectValue {\r
+       background-color: #DDDDDD;\r
+}\r
+\r
+#qt_starttime, #qt_endtime, #qt_fov, #qt_href, #qt_moveid, #qt_moviename, #qt_node, #qt_pan, #qt_qtsrc, #qt_qtsrcchokespeed, #qt_target, #qt_tilt, #qt_urlsubstituten, #qt_volume {\r
+       width: 70px;\r
+}\r
+\r
+#wmp_balance, #wmp_baseurl, #wmp_captioningid, #wmp_currentmarker, #wmp_currentposition, #wmp_defaultframe, #wmp_playcount, #wmp_rate, #wmp_uimode, #wmp_volume {\r
+       width: 70px;\r
+}\r
+\r
+#rmp_console, #rmp_numloop, #rmp_controls, #rmp_scriptcallbacks {\r
+       width: 70px;\r
+}\r
+\r
+#shockwave_swvolume, #shockwave_swframe, #shockwave_swurl, #shockwave_swstretchvalign, #shockwave_swstretchhalign, #shockwave_swstretchstyle {\r
+       width: 90px;\r
+}\r
+\r
+#qt_qtsrc {\r
+       width: 200px;\r
+}\r
diff --git a/jscripts/tiny_mce/plugins/media/editor_plugin.js b/jscripts/tiny_mce/plugins/media/editor_plugin.js
new file mode 100644 (file)
index 0000000..4591be7
--- /dev/null
@@ -0,0 +1 @@
+(function(){var each=tinymce.each;tinymce.create('tinymce.plugins.MediaPlugin',{init:function(ed,url){var t=this;t.editor=ed;t.url=url;function isMediaElm(n){return/^(mceItemFlash|mceItemShockWave|mceItemWindowsMedia|mceItemQuickTime|mceItemRealMedia)$/.test(n.className);};ed.addCommand('mceMedia',function(){ed.windowManager.open({file:url+'/media.htm',width:430+parseInt(ed.getLang('media.delta_width',0)),height:470+parseInt(ed.getLang('media.delta_height',0)),inline:1},{plugin_url:url});});ed.addButton('media',{title:'media.desc',cmd:'mceMedia'});ed.onNodeChange.add(function(ed,cm,n){cm.setActive('media',n.nodeName=='IMG'&&isMediaElm(n));});ed.onInit.add(function(){var lo={mceItemFlash:'flash',mceItemShockWave:'shockwave',mceItemWindowsMedia:'windowsmedia',mceItemQuickTime:'quicktime',mceItemRealMedia:'realmedia'};if(ed.settings.content_css!==false)ed.dom.loadCSS(url+"/css/content.css");if(ed.theme.onResolveName){ed.theme.onResolveName.add(function(th,o){if(o.name=='img'){each(lo,function(v,k){if(ed.dom.hasClass(o.node,k)){o.name=v;o.title=ed.dom.getAttrib(o.node,'title');return false;}});}});}if(ed&&ed.plugins.contextmenu){ed.plugins.contextmenu.onContextMenu.add(function(th,m,e){if(e.nodeName=='IMG'&&/mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(e.className)){m.add({title:'media.edit',icon:'media',cmd:'mceMedia'});}});}});ed.onBeforeSetContent.add(function(ed,o){var h=o.content;h=h.replace(/<script[^>]*>\s*write(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)\(\{([^\)]*)\}\);\s*<\/script>/gi,function(a,b,c){var o=t._parse(c);return'<img class="mceItem'+b+'" title="'+ed.dom.encode(c)+'" src="'+url+'/img/trans.gif" width="'+o.width+'" height="'+o.height+'" />'});h=h.replace(/<object([^>]*)>/gi,'<span class="mceItemObject" $1>');h=h.replace(/<embed([^>]*)>/gi,'<span class="mceItemEmbed" $1>');h=h.replace(/<\/(object|embed)([^>]*)>/gi,'</span>');h=h.replace(/<param([^>]*)>/gi,function(a,b){return'<span '+b.replace(/value=/gi,'_value=')+' class="mceItemParam"></span>'});h=h.replace(/\/ class=\"mceItemParam\"><\/span>/gi,'class="mceItemParam"></span>');o.content=h;});ed.onSetContent.add(function(){t._spansToImgs(ed.getBody());});ed.onPreProcess.add(function(ed,o){var dom=ed.dom;if(o.set){t._spansToImgs(o.node);each(dom.select('IMG',o.node),function(n){var p;if(isMediaElm(n)){p=t._parse(n.title);dom.setAttrib(n,'width',dom.getAttrib(n,'width',p.width||100));dom.setAttrib(n,'height',dom.getAttrib(n,'height',p.height||100));}});}if(o.get){each(dom.select('IMG',o.node),function(n){var ci,cb,mt;if(ed.getParam('media_use_script')){if(isMediaElm(n))n.className=n.className.replace(/mceItem/g,'mceTemp');return;}switch(n.className){case'mceItemFlash':ci='d27cdb6e-ae6d-11cf-96b8-444553540000';cb='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0';mt='application/x-shockwave-flash';break;case'mceItemShockWave':ci='166b1bca-3f9c-11cf-8075-444553540000';cb='http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0';mt='application/x-director';break;case'mceItemWindowsMedia':ci=ed.getParam('media_wmp6_compatible')?'05589fa1-c356-11ce-bf01-00aa0055595a':'6bf52a52-394a-11d3-b153-00c04f79faa6';cb='http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701';mt='application/x-mplayer2';break;case'mceItemQuickTime':ci='02bf25d5-8c17-4b23-bc80-d3488abddc6b';cb='http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0';mt='video/quicktime';break;case'mceItemRealMedia':ci='cfcdaa03-8be4-11cf-b84b-0020afbbccfa';cb='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0';mt='audio/x-pn-realaudio-plugin';break;}if(ci){dom.replace(t._buildObj({classid:ci,codebase:cb,type:mt},n),n);}});}});ed.onPostProcess.add(function(ed,o){o.content=o.content.replace(/_value=/g,'value=');});if(ed.getParam('media_use_script')){function getAttr(s,n){n=new RegExp(n+'=\"([^\"]+)\"','g').exec(s);return n?ed.dom.decode(n[1]):'';};ed.onPostProcess.add(function(ed,o){o.content=o.content.replace(/<img[^>]+>/g,function(im){var cl=getAttr(im,'class');if(/^(mceTempFlash|mceTempShockWave|mceTempWindowsMedia|mceTempQuickTime|mceTempRealMedia)$/.test(cl)){at=t._parse(getAttr(im,'title'));at.width=getAttr(im,'width');at.height=getAttr(im,'height');im='<script type="text/javascript">write'+cl.substring(7)+'({'+t._serialize(at)+'});</script>';}return im;});});}},getInfo:function(){return{longname:'Media',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/media',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_buildObj:function(o,n){var ob,ed=this.editor,dom=ed.dom,p=this._parse(n.title);p.width=o.width=dom.getAttrib(n,'width')||100;p.height=o.height=dom.getAttrib(n,'height')||100;ob=dom.create('span',{mce_name:'object',classid:"clsid:"+o.classid,codebase:o.codebase,width:o.width,height:o.height});if(p.src)p.src=ed.convertURL(p.src,'src',n);each(p,function(v,k){if(!/^(width|height|codebase|classid)$/.test(k)){if(o.type=='application/x-mplayer2'&&k=='src')k='url';dom.add(ob,'span',{mce_name:'param',name:k,'_value':v});}});dom.add(ob,'span',tinymce.extend({mce_name:'embed',type:o.type},p));return ob;},_spansToImgs:function(p){var t=this,dom=t.editor.dom,im,ci;each(dom.select('span',p),function(n){if(dom.getAttrib(n,'class')=='mceItemObject'){ci=dom.getAttrib(n,"classid").toLowerCase().replace(/\s+/g,'');switch(ci){case'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000':dom.replace(t._createImg('mceItemFlash',n),n);break;case'clsid:166b1bca-3f9c-11cf-8075-444553540000':dom.replace(t._createImg('mceItemShockWave',n),n);break;case'clsid:6bf52a52-394a-11d3-b153-00c04f79faa6':case'clsid:22d6f312-b0f6-11d0-94ab-0080c74c7e95':case'clsid:05589fa1-c356-11ce-bf01-00aa0055595a':dom.replace(t._createImg('mceItemWindowsMedia',n),n);break;case'clsid:02bf25d5-8c17-4b23-bc80-d3488abddc6b':dom.replace(t._createImg('mceItemQuickTime',n),n);break;case'clsid:cfcdaa03-8be4-11cf-b84b-0020afbbccfa':dom.replace(t._createImg('mceItemRealMedia',n),n);break;default:dom.replace(t._createImg('mceItemFlash',n),n);}return;}if(dom.getAttrib(n,'class')=='mceItemEmbed'){switch(dom.getAttrib(n,'type')){case'application/x-shockwave-flash':dom.replace(t._createImg('mceItemFlash',n),n);break;case'application/x-director':dom.replace(t._createImg('mceItemShockWave',n),n);break;case'application/x-mplayer2':dom.replace(t._createImg('mceItemWindowsMedia',n),n);break;case'video/quicktime':dom.replace(t._createImg('mceItemQuickTime',n),n);break;case'audio/x-pn-realaudio-plugin':dom.replace(t._createImg('mceItemRealMedia',n),n);break;default:dom.replace(t._createImg('mceItemFlash',n),n);}}});},_createImg:function(cl,n){var im,dom=this.editor.dom,pa={},ti='';im=dom.create('img',{src:this.url+'/img/trans.gif',width:dom.getAttrib(n,'width')||100,height:dom.getAttrib(n,'height')||100,'class':cl});each(['id','name','width','height','bgcolor','align','flashvars','src','wmode'],function(na){var v=dom.getAttrib(n,na);if(v)pa[na]=v;});each(dom.select('span',n),function(n){if(dom.hasClass(n,'mceItemParam'))pa[dom.getAttrib(n,'name')]=dom.getAttrib(n,'_value');});if(pa.movie){pa.src=pa.movie;delete pa.movie;}delete pa.width;delete pa.height;im.title=this._serialize(pa);return im;},_parse:function(s){return tinymce.util.JSON.parse('{'+s+'}');},_serialize:function(o){return tinymce.util.JSON.serialize(o).replace(/[{}]/g,'');}});tinymce.PluginManager.add('media',tinymce.plugins.MediaPlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/media/editor_plugin_src.js b/jscripts/tiny_mce/plugins/media/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..d9df5b5
--- /dev/null
@@ -0,0 +1,359 @@
+/**\r
+ * $Id: editor_plugin_src.js 763 2008-04-03 13:25:45Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       var each = tinymce.each;\r
+\r
+       tinymce.create('tinymce.plugins.MediaPlugin', {\r
+               init : function(ed, url) {\r
+                       var t = this;\r
+                       \r
+                       t.editor = ed;\r
+                       t.url = url;\r
+\r
+                       function isMediaElm(n) {\r
+                               return /^(mceItemFlash|mceItemShockWave|mceItemWindowsMedia|mceItemQuickTime|mceItemRealMedia)$/.test(n.className);\r
+                       };\r
+\r
+                       // Register commands\r
+                       ed.addCommand('mceMedia', function() {\r
+                               ed.windowManager.open({\r
+                                       file : url + '/media.htm',\r
+                                       width : 430 + parseInt(ed.getLang('media.delta_width', 0)),\r
+                                       height : 470 + parseInt(ed.getLang('media.delta_height', 0)),\r
+                                       inline : 1\r
+                               }, {\r
+                                       plugin_url : url\r
+                               });\r
+                       });\r
+\r
+                       // Register buttons\r
+                       ed.addButton('media', {title : 'media.desc', cmd : 'mceMedia'});\r
+\r
+                       ed.onNodeChange.add(function(ed, cm, n) {\r
+                               cm.setActive('media', n.nodeName == 'IMG' && isMediaElm(n));\r
+                       });\r
+\r
+                       ed.onInit.add(function() {\r
+                               var lo = {\r
+                                       mceItemFlash : 'flash',\r
+                                       mceItemShockWave : 'shockwave',\r
+                                       mceItemWindowsMedia : 'windowsmedia',\r
+                                       mceItemQuickTime : 'quicktime',\r
+                                       mceItemRealMedia : 'realmedia'\r
+                               };\r
+\r
+                               if (ed.settings.content_css !== false)\r
+                                       ed.dom.loadCSS(url + "/css/content.css");\r
+\r
+                               if (ed.theme.onResolveName) {\r
+                                       ed.theme.onResolveName.add(function(th, o) {\r
+                                               if (o.name == 'img') {\r
+                                                       each(lo, function(v, k) {\r
+                                                               if (ed.dom.hasClass(o.node, k)) {\r
+                                                                       o.name = v;\r
+                                                                       o.title = ed.dom.getAttrib(o.node, 'title');\r
+                                                                       return false;\r
+                                                               }\r
+                                                       });\r
+                                               }\r
+                                       });\r
+                               }\r
+\r
+                               if (ed && ed.plugins.contextmenu) {\r
+                                       ed.plugins.contextmenu.onContextMenu.add(function(th, m, e) {\r
+                                               if (e.nodeName == 'IMG' && /mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(e.className)) {\r
+                                                       m.add({title : 'media.edit', icon : 'media', cmd : 'mceMedia'});\r
+                                               }\r
+                                       });\r
+                               }\r
+                       });\r
+\r
+                       ed.onBeforeSetContent.add(function(ed, o) {\r
+                               var h = o.content;\r
+\r
+                               h = h.replace(/<script[^>]*>\s*write(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)\(\{([^\)]*)\}\);\s*<\/script>/gi, function(a, b, c) {\r
+                                       var o = t._parse(c);\r
+\r
+                                       return '<img class="mceItem' + b + '" title="' + ed.dom.encode(c) + '" src="' + url + '/img/trans.gif" width="' + o.width + '" height="' + o.height + '" />'\r
+                               });\r
+\r
+                               h = h.replace(/<object([^>]*)>/gi, '<span class="mceItemObject" $1>');\r
+                               h = h.replace(/<embed([^>]*)>/gi, '<span class="mceItemEmbed" $1>');\r
+                               h = h.replace(/<\/(object|embed)([^>]*)>/gi, '</span>');\r
+                               h = h.replace(/<param([^>]*)>/gi, function(a, b) {return '<span ' + b.replace(/value=/gi, '_value=') + ' class="mceItemParam"></span>'});\r
+                               h = h.replace(/\/ class=\"mceItemParam\"><\/span>/gi, 'class="mceItemParam"></span>');\r
+\r
+                               o.content = h;\r
+                       });\r
+\r
+                       ed.onSetContent.add(function() {\r
+                               t._spansToImgs(ed.getBody());\r
+                       });\r
+\r
+                       ed.onPreProcess.add(function(ed, o) {\r
+                               var dom = ed.dom;\r
+\r
+                               if (o.set) {\r
+                                       t._spansToImgs(o.node);\r
+\r
+                                       each(dom.select('IMG', o.node), function(n) {\r
+                                               var p;\r
+\r
+                                               if (isMediaElm(n)) {\r
+                                                       p = t._parse(n.title);\r
+                                                       dom.setAttrib(n, 'width', dom.getAttrib(n, 'width', p.width || 100));\r
+                                                       dom.setAttrib(n, 'height', dom.getAttrib(n, 'height', p.height || 100));\r
+                                               }\r
+                                       });\r
+                               }\r
+\r
+                               if (o.get) {\r
+                                       each(dom.select('IMG', o.node), function(n) {\r
+                                               var ci, cb, mt;\r
+\r
+                                               if (ed.getParam('media_use_script')) {\r
+                                                       if (isMediaElm(n))\r
+                                                               n.className = n.className.replace(/mceItem/g, 'mceTemp');\r
+\r
+                                                       return;\r
+                                               }\r
+\r
+                                               switch (n.className) {\r
+                                                       case 'mceItemFlash':\r
+                                                               ci = 'd27cdb6e-ae6d-11cf-96b8-444553540000';\r
+                                                               cb = 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0';\r
+                                                               mt = 'application/x-shockwave-flash';\r
+                                                               break;\r
+\r
+                                                       case 'mceItemShockWave':\r
+                                                               ci = '166b1bca-3f9c-11cf-8075-444553540000';\r
+                                                               cb = 'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0';\r
+                                                               mt = 'application/x-director';\r
+                                                               break;\r
+\r
+                                                       case 'mceItemWindowsMedia':\r
+                                                               ci = ed.getParam('media_wmp6_compatible') ? '05589fa1-c356-11ce-bf01-00aa0055595a' : '6bf52a52-394a-11d3-b153-00c04f79faa6';\r
+                                                               cb = 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701';\r
+                                                               mt = 'application/x-mplayer2';\r
+                                                               break;\r
+\r
+                                                       case 'mceItemQuickTime':\r
+                                                               ci = '02bf25d5-8c17-4b23-bc80-d3488abddc6b';\r
+                                                               cb = 'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0';\r
+                                                               mt = 'video/quicktime';\r
+                                                               break;\r
+\r
+                                                       case 'mceItemRealMedia':\r
+                                                               ci = 'cfcdaa03-8be4-11cf-b84b-0020afbbccfa';\r
+                                                               cb = 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0';\r
+                                                               mt = 'audio/x-pn-realaudio-plugin';\r
+                                                               break;\r
+                                               }\r
+\r
+                                               if (ci) {\r
+                                                       dom.replace(t._buildObj({\r
+                                                               classid : ci,\r
+                                                               codebase : cb,\r
+                                                               type : mt\r
+                                                       }, n), n);\r
+                                               }\r
+                                       });\r
+                               }\r
+                       });\r
+\r
+                       ed.onPostProcess.add(function(ed, o) {\r
+                               o.content = o.content.replace(/_value=/g, 'value=');\r
+                       });\r
+\r
+                       if (ed.getParam('media_use_script')) {\r
+                               function getAttr(s, n) {\r
+                                       n = new RegExp(n + '=\"([^\"]+)\"', 'g').exec(s);\r
+\r
+                                       return n ? ed.dom.decode(n[1]) : '';\r
+                               };\r
+\r
+                               ed.onPostProcess.add(function(ed, o) {\r
+                                       o.content = o.content.replace(/<img[^>]+>/g, function(im) {\r
+                                               var cl = getAttr(im, 'class');\r
+\r
+                                               if (/^(mceTempFlash|mceTempShockWave|mceTempWindowsMedia|mceTempQuickTime|mceTempRealMedia)$/.test(cl)) {\r
+                                                       at = t._parse(getAttr(im, 'title'));\r
+                                                       at.width = getAttr(im, 'width');\r
+                                                       at.height = getAttr(im, 'height');\r
+                                                       im = '<script type="text/javascript">write' + cl.substring(7) + '({' + t._serialize(at) + '});</script>';\r
+                                               }\r
+\r
+                                               return im;\r
+                                       });\r
+                               });\r
+                       }\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Media',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/media',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               },\r
+\r
+               // Private methods\r
+\r
+               _buildObj : function(o, n) {\r
+                       var ob, ed = this.editor, dom = ed.dom, p = this._parse(n.title);\r
+\r
+                       p.width = o.width = dom.getAttrib(n, 'width') || 100;\r
+                       p.height = o.height = dom.getAttrib(n, 'height') || 100;\r
+\r
+                       ob = dom.create('span', {\r
+                               mce_name : 'object',\r
+                               classid : "clsid:" + o.classid,\r
+                               codebase : o.codebase,\r
+                               width : o.width,\r
+                               height : o.height\r
+                       });\r
+\r
+                       if (p.src)\r
+                               p.src = ed.convertURL(p.src, 'src', n);\r
+\r
+                       each (p, function(v, k) {\r
+                               if (!/^(width|height|codebase|classid)$/.test(k)) {\r
+                                       // Use url instead of src in IE for Windows media\r
+                                       if (o.type == 'application/x-mplayer2' && k == 'src')\r
+                                               k = 'url';\r
+\r
+                                       dom.add(ob, 'span', {mce_name : 'param', name : k, '_value' : v});\r
+                               }\r
+                       });\r
+\r
+                       dom.add(ob, 'span', tinymce.extend({mce_name : 'embed', type : o.type}, p));\r
+\r
+                       return ob;\r
+               },\r
+\r
+               _spansToImgs : function(p) {\r
+                       var t = this, dom = t.editor.dom, im, ci;\r
+\r
+                       each(dom.select('span', p), function(n) {\r
+                               // Convert object into image\r
+                               if (dom.getAttrib(n, 'class') == 'mceItemObject') {\r
+                                       ci = dom.getAttrib(n, "classid").toLowerCase().replace(/\s+/g, '');\r
+\r
+                                       switch (ci) {\r
+                                               case 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000':\r
+                                                       dom.replace(t._createImg('mceItemFlash', n), n);\r
+                                                       break;\r
+\r
+                                               case 'clsid:166b1bca-3f9c-11cf-8075-444553540000':\r
+                                                       dom.replace(t._createImg('mceItemShockWave', n), n);\r
+                                                       break;\r
+\r
+                                               case 'clsid:6bf52a52-394a-11d3-b153-00c04f79faa6':\r
+                                               case 'clsid:22d6f312-b0f6-11d0-94ab-0080c74c7e95':\r
+                                               case 'clsid:05589fa1-c356-11ce-bf01-00aa0055595a':\r
+                                                       dom.replace(t._createImg('mceItemWindowsMedia', n), n);\r
+                                                       break;\r
+\r
+                                               case 'clsid:02bf25d5-8c17-4b23-bc80-d3488abddc6b':\r
+                                                       dom.replace(t._createImg('mceItemQuickTime', n), n);\r
+                                                       break;\r
+\r
+                                               case 'clsid:cfcdaa03-8be4-11cf-b84b-0020afbbccfa':\r
+                                                       dom.replace(t._createImg('mceItemRealMedia', n), n);\r
+                                                       break;\r
+\r
+                                               default:\r
+                                                       dom.replace(t._createImg('mceItemFlash', n), n);\r
+                                       }\r
+                                       \r
+                                       return;\r
+                               }\r
+\r
+                               // Convert embed into image\r
+                               if (dom.getAttrib(n, 'class') == 'mceItemEmbed') {\r
+                                       switch (dom.getAttrib(n, 'type')) {\r
+                                               case 'application/x-shockwave-flash':\r
+                                                       dom.replace(t._createImg('mceItemFlash', n), n);\r
+                                                       break;\r
+\r
+                                               case 'application/x-director':\r
+                                                       dom.replace(t._createImg('mceItemShockWave', n), n);\r
+                                                       break;\r
+\r
+                                               case 'application/x-mplayer2':\r
+                                                       dom.replace(t._createImg('mceItemWindowsMedia', n), n);\r
+                                                       break;\r
+\r
+                                               case 'video/quicktime':\r
+                                                       dom.replace(t._createImg('mceItemQuickTime', n), n);\r
+                                                       break;\r
+\r
+                                               case 'audio/x-pn-realaudio-plugin':\r
+                                                       dom.replace(t._createImg('mceItemRealMedia', n), n);\r
+                                                       break;\r
+\r
+                                               default:\r
+                                                       dom.replace(t._createImg('mceItemFlash', n), n);\r
+                                       }\r
+                               }                       \r
+                       });\r
+               },\r
+\r
+               _createImg : function(cl, n) {\r
+                       var im, dom = this.editor.dom, pa = {}, ti = '';\r
+\r
+                       // Create image\r
+                       im = dom.create('img', {\r
+                               src : this.url + '/img/trans.gif',\r
+                               width : dom.getAttrib(n, 'width') || 100,\r
+                               height : dom.getAttrib(n, 'height') || 100,\r
+                               'class' : cl\r
+                       });\r
+\r
+                       // Setup base parameters\r
+                       each(['id', 'name', 'width', 'height', 'bgcolor', 'align', 'flashvars', 'src', 'wmode'], function(na) {\r
+                               var v = dom.getAttrib(n, na);\r
+\r
+                               if (v)\r
+                                       pa[na] = v;\r
+                       });\r
+\r
+                       // Add optional parameters\r
+                       each(dom.select('span', n), function(n) {\r
+                               if (dom.hasClass(n, 'mceItemParam'))\r
+                                       pa[dom.getAttrib(n, 'name')] = dom.getAttrib(n, '_value');\r
+                       });\r
+\r
+                       // Use src not movie\r
+                       if (pa.movie) {\r
+                               pa.src = pa.movie;\r
+                               delete pa.movie;\r
+                       }\r
+\r
+                       delete pa.width;\r
+                       delete pa.height;\r
+\r
+                       im.title = this._serialize(pa);\r
+\r
+                       return im;\r
+               },\r
+\r
+               _parse : function(s) {\r
+                       return tinymce.util.JSON.parse('{' + s + '}');\r
+               },\r
+\r
+               _serialize : function(o) {\r
+                       return tinymce.util.JSON.serialize(o).replace(/[{}]/g, '');\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('media', tinymce.plugins.MediaPlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/media/img/flash.gif b/jscripts/tiny_mce/plugins/media/img/flash.gif
new file mode 100644 (file)
index 0000000..cb192e6
Binary files /dev/null and b/jscripts/tiny_mce/plugins/media/img/flash.gif differ
diff --git a/jscripts/tiny_mce/plugins/media/img/flv_player.swf b/jscripts/tiny_mce/plugins/media/img/flv_player.swf
new file mode 100644 (file)
index 0000000..042c2ab
Binary files /dev/null and b/jscripts/tiny_mce/plugins/media/img/flv_player.swf differ
diff --git a/jscripts/tiny_mce/plugins/media/img/quicktime.gif b/jscripts/tiny_mce/plugins/media/img/quicktime.gif
new file mode 100644 (file)
index 0000000..3b04991
Binary files /dev/null and b/jscripts/tiny_mce/plugins/media/img/quicktime.gif differ
diff --git a/jscripts/tiny_mce/plugins/media/img/realmedia.gif b/jscripts/tiny_mce/plugins/media/img/realmedia.gif
new file mode 100644 (file)
index 0000000..fdfe0b9
Binary files /dev/null and b/jscripts/tiny_mce/plugins/media/img/realmedia.gif differ
diff --git a/jscripts/tiny_mce/plugins/media/img/shockwave.gif b/jscripts/tiny_mce/plugins/media/img/shockwave.gif
new file mode 100644 (file)
index 0000000..5f235df
Binary files /dev/null and b/jscripts/tiny_mce/plugins/media/img/shockwave.gif differ
diff --git a/jscripts/tiny_mce/plugins/media/img/trans.gif b/jscripts/tiny_mce/plugins/media/img/trans.gif
new file mode 100644 (file)
index 0000000..3884865
Binary files /dev/null and b/jscripts/tiny_mce/plugins/media/img/trans.gif differ
diff --git a/jscripts/tiny_mce/plugins/media/img/windowsmedia.gif b/jscripts/tiny_mce/plugins/media/img/windowsmedia.gif
new file mode 100644 (file)
index 0000000..ab50f2d
Binary files /dev/null and b/jscripts/tiny_mce/plugins/media/img/windowsmedia.gif differ
diff --git a/jscripts/tiny_mce/plugins/media/js/embed.js b/jscripts/tiny_mce/plugins/media/js/embed.js
new file mode 100644 (file)
index 0000000..f8dc810
--- /dev/null
@@ -0,0 +1,73 @@
+/**\r
+ * This script contains embed functions for common plugins. This scripts are complety free to use for any purpose.\r
+ */\r
+\r
+function writeFlash(p) {\r
+       writeEmbed(\r
+               'D27CDB6E-AE6D-11cf-96B8-444553540000',\r
+               'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0',\r
+               'application/x-shockwave-flash',\r
+               p\r
+       );\r
+}\r
+\r
+function writeShockWave(p) {\r
+       writeEmbed(\r
+       '166B1BCA-3F9C-11CF-8075-444553540000',\r
+       'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0',\r
+       'application/x-director',\r
+               p\r
+       );\r
+}\r
+\r
+function writeQuickTime(p) {\r
+       writeEmbed(\r
+               '02BF25D5-8C17-4B23-BC80-D3488ABDDC6B',\r
+               'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0',\r
+               'video/quicktime',\r
+               p\r
+       );\r
+}\r
+\r
+function writeRealMedia(p) {\r
+       writeEmbed(\r
+               'CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA',\r
+               'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0',\r
+               'audio/x-pn-realaudio-plugin',\r
+               p\r
+       );\r
+}\r
+\r
+function writeWindowsMedia(p) {\r
+       p.url = p.src;\r
+       writeEmbed(\r
+               '6BF52A52-394A-11D3-B153-00C04F79FAA6',\r
+               'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701',\r
+               'application/x-mplayer2',\r
+               p\r
+       );\r
+}\r
+\r
+function writeEmbed(cls, cb, mt, p) {\r
+       var h = '', n;\r
+\r
+       h += '<object classid="clsid:' + cls + '" codebase="' + cb + '"';\r
+       h += typeof(p.id) != "undefined" ? 'id="' + p.id + '"' : '';\r
+       h += typeof(p.name) != "undefined" ? 'name="' + p.name + '"' : '';\r
+       h += typeof(p.width) != "undefined" ? 'width="' + p.width + '"' : '';\r
+       h += typeof(p.height) != "undefined" ? 'height="' + p.height + '"' : '';\r
+       h += typeof(p.align) != "undefined" ? 'align="' + p.align + '"' : '';\r
+       h += '>';\r
+\r
+       for (n in p)\r
+               h += '<param name="' + n + '" value="' + p[n] + '">';\r
+\r
+       h += '<embed type="' + mt + '"';\r
+\r
+       for (n in p)\r
+               h += n + '="' + p[n] + '" ';\r
+\r
+       h += '></embed></object>';\r
+\r
+       document.write(h);\r
+}\r
diff --git a/jscripts/tiny_mce/plugins/media/js/media.js b/jscripts/tiny_mce/plugins/media/js/media.js
new file mode 100644 (file)
index 0000000..2877d16
--- /dev/null
@@ -0,0 +1,621 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+var oldWidth, oldHeight, ed, url;\r
+\r
+if (url = tinyMCEPopup.getParam("media_external_list_url"))\r
+       document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>');\r
+\r
+function init() {\r
+       var pl = "", f, val;\r
+       var type = "flash", fe, i;\r
+\r
+       ed = tinyMCEPopup.editor;\r
+\r
+       tinyMCEPopup.resizeToInnerSize();\r
+       f = document.forms[0]\r
+\r
+       fe = ed.selection.getNode();\r
+       if (/mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(ed.dom.getAttrib(fe, 'class'))) {\r
+               pl = fe.title;\r
+\r
+               switch (ed.dom.getAttrib(fe, 'class')) {\r
+                       case 'mceItemFlash':\r
+                               type = 'flash';\r
+                               break;\r
+\r
+                       case 'mceItemFlashVideo':\r
+                               type = 'flv';\r
+                               break;\r
+\r
+                       case 'mceItemShockWave':\r
+                               type = 'shockwave';\r
+                               break;\r
+\r
+                       case 'mceItemWindowsMedia':\r
+                               type = 'wmp';\r
+                               break;\r
+\r
+                       case 'mceItemQuickTime':\r
+                               type = 'qt';\r
+                               break;\r
+\r
+                       case 'mceItemRealMedia':\r
+                               type = 'rmp';\r
+                               break;\r
+               }\r
+\r
+               document.forms[0].insert.value = ed.getLang('update', 'Insert', true); \r
+       }\r
+\r
+       document.getElementById('filebrowsercontainer').innerHTML = getBrowserHTML('filebrowser','src','media','media');\r
+       document.getElementById('qtsrcfilebrowsercontainer').innerHTML = getBrowserHTML('qtsrcfilebrowser','qt_qtsrc','media','media');\r
+       document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor');\r
+\r
+       var html = getMediaListHTML('medialist','src','media','media');\r
+       if (html == "")\r
+               document.getElementById("linklistrow").style.display = 'none';\r
+       else\r
+               document.getElementById("linklistcontainer").innerHTML = html;\r
+\r
+       // Resize some elements\r
+       if (isVisible('filebrowser'))\r
+               document.getElementById('src').style.width = '230px';\r
+\r
+       // Setup form\r
+       if (pl != "") {\r
+               pl = tinyMCEPopup.editor.plugins.media._parse(pl);\r
+\r
+               switch (type) {\r
+                       case "flash":\r
+                               setBool(pl, 'flash', 'play');\r
+                               setBool(pl, 'flash', 'loop');\r
+                               setBool(pl, 'flash', 'menu');\r
+                               setBool(pl, 'flash', 'swliveconnect');\r
+                               setStr(pl, 'flash', 'quality');\r
+                               setStr(pl, 'flash', 'scale');\r
+                               setStr(pl, 'flash', 'salign');\r
+                               setStr(pl, 'flash', 'wmode');\r
+                               setStr(pl, 'flash', 'base');\r
+                               setStr(pl, 'flash', 'flashvars');\r
+                       break;\r
+\r
+                       case "qt":\r
+                               setBool(pl, 'qt', 'loop');\r
+                               setBool(pl, 'qt', 'autoplay');\r
+                               setBool(pl, 'qt', 'cache');\r
+                               setBool(pl, 'qt', 'controller');\r
+                               setBool(pl, 'qt', 'correction');\r
+                               setBool(pl, 'qt', 'enablejavascript');\r
+                               setBool(pl, 'qt', 'kioskmode');\r
+                               setBool(pl, 'qt', 'autohref');\r
+                               setBool(pl, 'qt', 'playeveryframe');\r
+                               setBool(pl, 'qt', 'tarsetcache');\r
+                               setStr(pl, 'qt', 'scale');\r
+                               setStr(pl, 'qt', 'starttime');\r
+                               setStr(pl, 'qt', 'endtime');\r
+                               setStr(pl, 'qt', 'tarset');\r
+                               setStr(pl, 'qt', 'qtsrcchokespeed');\r
+                               setStr(pl, 'qt', 'volume');\r
+                               setStr(pl, 'qt', 'qtsrc');\r
+                       break;\r
+\r
+                       case "shockwave":\r
+                               setBool(pl, 'shockwave', 'sound');\r
+                               setBool(pl, 'shockwave', 'progress');\r
+                               setBool(pl, 'shockwave', 'autostart');\r
+                               setBool(pl, 'shockwave', 'swliveconnect');\r
+                               setStr(pl, 'shockwave', 'swvolume');\r
+                               setStr(pl, 'shockwave', 'swstretchstyle');\r
+                               setStr(pl, 'shockwave', 'swstretchhalign');\r
+                               setStr(pl, 'shockwave', 'swstretchvalign');\r
+                       break;\r
+\r
+                       case "wmp":\r
+                               setBool(pl, 'wmp', 'autostart');\r
+                               setBool(pl, 'wmp', 'enabled');\r
+                               setBool(pl, 'wmp', 'enablecontextmenu');\r
+                               setBool(pl, 'wmp', 'fullscreen');\r
+                               setBool(pl, 'wmp', 'invokeurls');\r
+                               setBool(pl, 'wmp', 'mute');\r
+                               setBool(pl, 'wmp', 'stretchtofit');\r
+                               setBool(pl, 'wmp', 'windowlessvideo');\r
+                               setStr(pl, 'wmp', 'balance');\r
+                               setStr(pl, 'wmp', 'baseurl');\r
+                               setStr(pl, 'wmp', 'captioningid');\r
+                               setStr(pl, 'wmp', 'currentmarker');\r
+                               setStr(pl, 'wmp', 'currentposition');\r
+                               setStr(pl, 'wmp', 'defaultframe');\r
+                               setStr(pl, 'wmp', 'playcount');\r
+                               setStr(pl, 'wmp', 'rate');\r
+                               setStr(pl, 'wmp', 'uimode');\r
+                               setStr(pl, 'wmp', 'volume');\r
+                       break;\r
+\r
+                       case "rmp":\r
+                               setBool(pl, 'rmp', 'autostart');\r
+                               setBool(pl, 'rmp', 'loop');\r
+                               setBool(pl, 'rmp', 'autogotourl');\r
+                               setBool(pl, 'rmp', 'center');\r
+                               setBool(pl, 'rmp', 'imagestatus');\r
+                               setBool(pl, 'rmp', 'maintainaspect');\r
+                               setBool(pl, 'rmp', 'nojava');\r
+                               setBool(pl, 'rmp', 'prefetch');\r
+                               setBool(pl, 'rmp', 'shuffle');\r
+                               setStr(pl, 'rmp', 'console');\r
+                               setStr(pl, 'rmp', 'controls');\r
+                               setStr(pl, 'rmp', 'numloop');\r
+                               setStr(pl, 'rmp', 'scriptcallbacks');\r
+                       break;\r
+               }\r
+\r
+               setStr(pl, null, 'src');\r
+               setStr(pl, null, 'id');\r
+               setStr(pl, null, 'name');\r
+               setStr(pl, null, 'vspace');\r
+               setStr(pl, null, 'hspace');\r
+               setStr(pl, null, 'bgcolor');\r
+               setStr(pl, null, 'align');\r
+               setStr(pl, null, 'width');\r
+               setStr(pl, null, 'height');\r
+\r
+               if ((val = ed.dom.getAttrib(fe, "width")) != "")\r
+                       pl.width = f.width.value = val;\r
+\r
+               if ((val = ed.dom.getAttrib(fe, "height")) != "")\r
+                       pl.height = f.height.value = val;\r
+\r
+               oldWidth = pl.width ? parseInt(pl.width) : 0;\r
+               oldHeight = pl.height ? parseInt(pl.height) : 0;\r
+       } else\r
+               oldWidth = oldHeight = 0;\r
+\r
+       selectByValue(f, 'media_type', type);\r
+       changedType(type);\r
+       updateColor('bgcolor_pick', 'bgcolor');\r
+\r
+       TinyMCE_EditableSelects.init();\r
+       generatePreview();\r
+}\r
+\r
+function insertMedia() {\r
+       var fe, f = document.forms[0], h;\r
+\r
+       tinyMCEPopup.restoreSelection();\r
+\r
+       if (!AutoValidator.validate(f)) {\r
+               alert(ed.getLang('invalid_data'));\r
+               return false;\r
+       }\r
+\r
+       f.width.value = f.width.value == "" ? 100 : f.width.value;\r
+       f.height.value = f.height.value == "" ? 100 : f.height.value;\r
+\r
+       fe = ed.selection.getNode();\r
+       if (fe != null && /mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(ed.dom.getAttrib(fe, 'class'))) {\r
+               switch (f.media_type.options[f.media_type.selectedIndex].value) {\r
+                       case "flash":\r
+                               fe.className = "mceItemFlash";\r
+                               break;\r
+\r
+                       case "flv":\r
+                               fe.className = "mceItemFlashVideo";\r
+                               break;\r
+\r
+                       case "shockwave":\r
+                               fe.className = "mceItemShockWave";\r
+                               break;\r
+\r
+                       case "qt":\r
+                               fe.className = "mceItemQuickTime";\r
+                               break;\r
+\r
+                       case "wmp":\r
+                               fe.className = "mceItemWindowsMedia";\r
+                               break;\r
+\r
+                       case "rmp":\r
+                               fe.className = "mceItemRealMedia";\r
+                               break;\r
+               }\r
+\r
+               if (fe.width != f.width.value || fe.height != f.height.height)\r
+                       ed.execCommand('mceRepaint');\r
+\r
+               fe.title = serializeParameters();\r
+               fe.width = f.width.value;\r
+               fe.height = f.height.value;\r
+               fe.style.width = f.width.value + (f.width.value.indexOf('%') == -1 ? 'px' : '');\r
+               fe.style.height = f.height.value + (f.height.value.indexOf('%') == -1 ? 'px' : '');\r
+               fe.align = f.align.options[f.align.selectedIndex].value;\r
+       } else {\r
+               h = '<img src="' + tinyMCEPopup.getWindowArg("plugin_url") + '/img/trans.gif"' ;\r
+\r
+               switch (f.media_type.options[f.media_type.selectedIndex].value) {\r
+                       case "flash":\r
+                               h += ' class="mceItemFlash"';\r
+                               break;\r
+\r
+                       case "flv":\r
+                               h += ' class="mceItemFlashVideo"';\r
+                               break;\r
+\r
+                       case "shockwave":\r
+                               h += ' class="mceItemShockWave"';\r
+                               break;\r
+\r
+                       case "qt":\r
+                               h += ' class="mceItemQuickTime"';\r
+                               break;\r
+\r
+                       case "wmp":\r
+                               h += ' class="mceItemWindowsMedia"';\r
+                               break;\r
+\r
+                       case "rmp":\r
+                               h += ' class="mceItemRealMedia"';\r
+                               break;\r
+               }\r
+\r
+               h += ' title="' + serializeParameters() + '"';\r
+               h += ' width="' + f.width.value + '"';\r
+               h += ' height="' + f.height.value + '"';\r
+               h += ' align="' + f.align.options[f.align.selectedIndex].value + '"';\r
+\r
+               h += ' />';\r
+\r
+               ed.execCommand('mceInsertContent', false, h);\r
+       }\r
+\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function updatePreview() {\r
+       var f = document.forms[0], type;\r
+\r
+       f.width.value = f.width.value || '320';\r
+       f.height.value = f.height.value || '240';\r
+\r
+       type = getType(f.src.value);\r
+       selectByValue(f, 'media_type', type);\r
+       changedType(type);\r
+       generatePreview();\r
+}\r
+\r
+function getMediaListHTML() {\r
+       if (typeof(tinyMCEMediaList) != "undefined" && tinyMCEMediaList.length > 0) {\r
+               var html = "";\r
+\r
+               html += '<select id="linklist" name="linklist" style="width: 250px" onchange="this.form.src.value=this.options[this.selectedIndex].value;updatePreview();">';\r
+               html += '<option value="">---</option>';\r
+\r
+               for (var i=0; i<tinyMCEMediaList.length; i++)\r
+                       html += '<option value="' + tinyMCEMediaList[i][1] + '">' + tinyMCEMediaList[i][0] + '</option>';\r
+\r
+               html += '</select>';\r
+\r
+               return html;\r
+       }\r
+\r
+       return "";\r
+}\r
+\r
+function getType(v) {\r
+       var fo, i, c, el, x, f = document.forms[0];\r
+\r
+       fo = ed.getParam("media_types", "flash=swf;flv=flv;shockwave=dcr;qt=mov,qt,mpg,mp3,mp4,mpeg;shockwave=dcr;wmp=avi,wmv,wm,asf,asx,wmx,wvx;rmp=rm,ra,ram").split(';');\r
+\r
+       // YouTube\r
+       if (v.match(/watch\?v=(.+)(.*)/)) {\r
+               f.width.value = '425';\r
+               f.height.value = '350';\r
+               f.src.value = 'http://www.youtube.com/v/' + v.match(/v=(.*)(.*)/)[0].split('=')[1];\r
+               return 'flash';\r
+       }\r
+\r
+       // Google video\r
+       if (v.indexOf('http://video.google.com/videoplay?docid=') == 0) {\r
+               f.width.value = '425';\r
+               f.height.value = '326';\r
+               f.src.value = 'http://video.google.com/googleplayer.swf?docId=' + v.substring('http://video.google.com/videoplay?docid='.length) + '&hl=en';\r
+               return 'flash';\r
+       }\r
+\r
+       for (i=0; i<fo.length; i++) {\r
+               c = fo[i].split('=');\r
+\r
+               el = c[1].split(',');\r
+               for (x=0; x<el.length; x++)\r
+               if (v.indexOf('.' + el[x]) != -1)\r
+                       return c[0];\r
+       }\r
+\r
+       return null;\r
+}\r
+\r
+function switchType(v) {\r
+       var t = getType(v), d = document, f = d.forms[0];\r
+\r
+       if (!t)\r
+               return;\r
+\r
+       selectByValue(d.forms[0], 'media_type', t);\r
+       changedType(t);\r
+\r
+       // Update qtsrc also\r
+       if (t == 'qt' && f.src.value.toLowerCase().indexOf('rtsp://') != -1) {\r
+               alert(ed.getLang("media_qt_stream_warn"));\r
+\r
+               if (f.qt_qtsrc.value == '')\r
+                       f.qt_qtsrc.value = f.src.value;\r
+       }\r
+}\r
+\r
+function changedType(t) {\r
+       var d = document;\r
+\r
+       d.getElementById('flash_options').style.display = 'none';\r
+       d.getElementById('flv_options').style.display = 'none';\r
+       d.getElementById('qt_options').style.display = 'none';\r
+       d.getElementById('shockwave_options').style.display = 'none';\r
+       d.getElementById('wmp_options').style.display = 'none';\r
+       d.getElementById('rmp_options').style.display = 'none';\r
+       d.getElementById(t + '_options').style.display = 'block';\r
+}\r
+\r
+function serializeParameters() {\r
+       var d = document, f = d.forms[0], s = '';\r
+\r
+       switch (f.media_type.options[f.media_type.selectedIndex].value) {\r
+               case "flash":\r
+                       s += getBool('flash', 'play', true);\r
+                       s += getBool('flash', 'loop', true);\r
+                       s += getBool('flash', 'menu', true);\r
+                       s += getBool('flash', 'swliveconnect', false);\r
+                       s += getStr('flash', 'quality');\r
+                       s += getStr('flash', 'scale');\r
+                       s += getStr('flash', 'salign');\r
+                       s += getStr('flash', 'wmode');\r
+                       s += getStr('flash', 'base');\r
+                       s += getStr('flash', 'flashvars');\r
+               break;\r
+\r
+               case "qt":\r
+                       s += getBool('qt', 'loop', false);\r
+                       s += getBool('qt', 'autoplay', true);\r
+                       s += getBool('qt', 'cache', false);\r
+                       s += getBool('qt', 'controller', true);\r
+                       s += getBool('qt', 'correction', false, 'none', 'full');\r
+                       s += getBool('qt', 'enablejavascript', false);\r
+                       s += getBool('qt', 'kioskmode', false);\r
+                       s += getBool('qt', 'autohref', false);\r
+                       s += getBool('qt', 'playeveryframe', false);\r
+                       s += getBool('qt', 'targetcache', false);\r
+                       s += getStr('qt', 'scale');\r
+                       s += getStr('qt', 'starttime');\r
+                       s += getStr('qt', 'endtime');\r
+                       s += getStr('qt', 'target');\r
+                       s += getStr('qt', 'qtsrcchokespeed');\r
+                       s += getStr('qt', 'volume');\r
+                       s += getStr('qt', 'qtsrc');\r
+               break;\r
+\r
+               case "shockwave":\r
+                       s += getBool('shockwave', 'sound');\r
+                       s += getBool('shockwave', 'progress');\r
+                       s += getBool('shockwave', 'autostart');\r
+                       s += getBool('shockwave', 'swliveconnect');\r
+                       s += getStr('shockwave', 'swvolume');\r
+                       s += getStr('shockwave', 'swstretchstyle');\r
+                       s += getStr('shockwave', 'swstretchhalign');\r
+                       s += getStr('shockwave', 'swstretchvalign');\r
+               break;\r
+\r
+               case "wmp":\r
+                       s += getBool('wmp', 'autostart', true);\r
+                       s += getBool('wmp', 'enabled', false);\r
+                       s += getBool('wmp', 'enablecontextmenu', true);\r
+                       s += getBool('wmp', 'fullscreen', false);\r
+                       s += getBool('wmp', 'invokeurls', true);\r
+                       s += getBool('wmp', 'mute', false);\r
+                       s += getBool('wmp', 'stretchtofit', false);\r
+                       s += getBool('wmp', 'windowlessvideo', false);\r
+                       s += getStr('wmp', 'balance');\r
+                       s += getStr('wmp', 'baseurl');\r
+                       s += getStr('wmp', 'captioningid');\r
+                       s += getStr('wmp', 'currentmarker');\r
+                       s += getStr('wmp', 'currentposition');\r
+                       s += getStr('wmp', 'defaultframe');\r
+                       s += getStr('wmp', 'playcount');\r
+                       s += getStr('wmp', 'rate');\r
+                       s += getStr('wmp', 'uimode');\r
+                       s += getStr('wmp', 'volume');\r
+               break;\r
+\r
+               case "rmp":\r
+                       s += getBool('rmp', 'autostart', false);\r
+                       s += getBool('rmp', 'loop', false);\r
+                       s += getBool('rmp', 'autogotourl', true);\r
+                       s += getBool('rmp', 'center', false);\r
+                       s += getBool('rmp', 'imagestatus', true);\r
+                       s += getBool('rmp', 'maintainaspect', false);\r
+                       s += getBool('rmp', 'nojava', false);\r
+                       s += getBool('rmp', 'prefetch', false);\r
+                       s += getBool('rmp', 'shuffle', false);\r
+                       s += getStr('rmp', 'console');\r
+                       s += getStr('rmp', 'controls');\r
+                       s += getStr('rmp', 'numloop');\r
+                       s += getStr('rmp', 'scriptcallbacks');\r
+               break;\r
+       }\r
+\r
+       s += getStr(null, 'id');\r
+       s += getStr(null, 'name');\r
+       s += getStr(null, 'src');\r
+       s += getStr(null, 'align');\r
+       s += getStr(null, 'bgcolor');\r
+       s += getInt(null, 'vspace');\r
+       s += getInt(null, 'hspace');\r
+       s += getStr(null, 'width');\r
+       s += getStr(null, 'height');\r
+\r
+       s = s.length > 0 ? s.substring(0, s.length - 1) : s;\r
+\r
+       return s;\r
+}\r
+\r
+function setBool(pl, p, n) {\r
+       if (typeof(pl[n]) == "undefined")\r
+               return;\r
+\r
+       document.forms[0].elements[p + "_" + n].checked = pl[n];\r
+}\r
+\r
+function setStr(pl, p, n) {\r
+       var f = document.forms[0], e = f.elements[(p != null ? p + "_" : '') + n];\r
+\r
+       if (typeof(pl[n]) == "undefined")\r
+               return;\r
+\r
+       if (e.type == "text")\r
+               e.value = pl[n];\r
+       else\r
+               selectByValue(f, (p != null ? p + "_" : '') + n, pl[n]);\r
+}\r
+\r
+function getBool(p, n, d, tv, fv) {\r
+       var v = document.forms[0].elements[p + "_" + n].checked;\r
+\r
+       tv = typeof(tv) == 'undefined' ? 'true' : "'" + jsEncode(tv) + "'";\r
+       fv = typeof(fv) == 'undefined' ? 'false' : "'" + jsEncode(fv) + "'";\r
+\r
+       return (v == d) ? '' : n + (v ? ':' + tv + ',' : ':' + fv + ',');\r
+}\r
+\r
+function getStr(p, n, d) {\r
+       var e = document.forms[0].elements[(p != null ? p + "_" : "") + n];\r
+       var v = e.type == "text" ? e.value : e.options[e.selectedIndex].value;\r
+\r
+       if (n == 'src')\r
+               v = tinyMCEPopup.editor.convertURL(v, 'src', null);\r
+\r
+       return ((n == d || v == '') ? '' : n + ":'" + jsEncode(v) + "',");\r
+}\r
+\r
+function getInt(p, n, d) {\r
+       var e = document.forms[0].elements[(p != null ? p + "_" : "") + n];\r
+       var v = e.type == "text" ? e.value : e.options[e.selectedIndex].value;\r
+\r
+       return ((n == d || v == '') ? '' : n + ":" + v.replace(/[^0-9]+/g, '') + ",");\r
+}\r
+\r
+function jsEncode(s) {\r
+       s = s.replace(new RegExp('\\\\', 'g'), '\\\\');\r
+       s = s.replace(new RegExp('"', 'g'), '\\"');\r
+       s = s.replace(new RegExp("'", 'g'), "\\'");\r
+\r
+       return s;\r
+}\r
+\r
+function generatePreview(c) {\r
+       var f = document.forms[0], p = document.getElementById('prev'), h = '', cls, pl, n, type, codebase, wp, hp, nw, nh;\r
+\r
+       p.innerHTML = '<!-- x --->';\r
+\r
+       nw = parseInt(f.width.value);\r
+       nh = parseInt(f.height.value);\r
+\r
+       if (f.width.value != "" && f.height.value != "") {\r
+               if (f.constrain.checked) {\r
+                       if (c == 'width' && oldWidth != 0) {\r
+                               wp = nw / oldWidth;\r
+                               nh = Math.round(wp * nh);\r
+                               f.height.value = nh;\r
+                       } else if (c == 'height' && oldHeight != 0) {\r
+                               hp = nh / oldHeight;\r
+                               nw = Math.round(hp * nw);\r
+                               f.width.value = nw;\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (f.width.value != "")\r
+               oldWidth = nw;\r
+\r
+       if (f.height.value != "")\r
+               oldHeight = nh;\r
+\r
+       // After constrain\r
+       pl = serializeParameters();\r
+\r
+       switch (f.media_type.options[f.media_type.selectedIndex].value) {\r
+               case "flash":\r
+                       cls = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';\r
+                       codebase = 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0';\r
+                       type = 'application/x-shockwave-flash';\r
+                       break;\r
+\r
+               case "shockwave":\r
+                       cls = 'clsid:166B1BCA-3F9C-11CF-8075-444553540000';\r
+                       codebase = 'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0';\r
+                       type = 'application/x-director';\r
+                       break;\r
+\r
+               case "qt":\r
+                       cls = 'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B';\r
+                       codebase = 'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0';\r
+                       type = 'video/quicktime';\r
+                       break;\r
+\r
+               case "wmp":\r
+                       cls = ed.getParam('media_wmp6_compatible') ? 'clsid:05589FA1-C356-11CE-BF01-00AA0055595A' : 'clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6';\r
+                       codebase = 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701';\r
+                       type = 'application/x-mplayer2';\r
+                       break;\r
+\r
+               case "rmp":\r
+                       cls = 'clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA';\r
+                       codebase = 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701';\r
+                       type = 'audio/x-pn-realaudio-plugin';\r
+                       break;\r
+       }\r
+\r
+       if (pl == '') {\r
+               p.innerHTML = '';\r
+               return;\r
+       }\r
+\r
+       pl = tinyMCEPopup.editor.plugins.media._parse(pl);\r
+\r
+       if (!pl.src) {\r
+               p.innerHTML = '';\r
+               return;\r
+       }\r
+\r
+       pl.src = tinyMCEPopup.editor.documentBaseURI.toAbsolute(pl.src);\r
+       pl.width = !pl.width ? 100 : pl.width;\r
+       pl.height = !pl.height ? 100 : pl.height;\r
+       pl.id = !pl.id ? 'obj' : pl.id;\r
+       pl.name = !pl.name ? 'eobj' : pl.name;\r
+       pl.align = !pl.align ? '' : pl.align;\r
+\r
+       h += '<object classid="clsid:' + cls + '" codebase="' + codebase + '" width="' + pl.width + '" height="' + pl.height + '" id="' + pl.id + '" name="' + pl.name + '" align="' + pl.align + '">';\r
+\r
+       for (n in pl) {\r
+               h += '<param name="' + n + '" value="' + pl[n] + '">';\r
+\r
+               // Add extra url parameter if it's an absolute URL\r
+               if (n == 'src' && pl[n].indexOf('://') != -1)\r
+                       h += '<param name="url" value="' + pl[n] + '" />';\r
+       }\r
+\r
+       h += '<embed type="' + type + '" ';\r
+\r
+       for (n in pl)\r
+               h += n + '="' + pl[n] + '" ';\r
+\r
+       h += '></embed></object>';\r
+\r
+       p.innerHTML = "<!-- x --->" + h;\r
+}\r
+\r
+tinyMCEPopup.onInit.add(init);\r
diff --git a/jscripts/tiny_mce/plugins/media/langs/en_dlg.js b/jscripts/tiny_mce/plugins/media/langs/en_dlg.js
new file mode 100644 (file)
index 0000000..6d0a996
--- /dev/null
@@ -0,0 +1,103 @@
+tinyMCE.addI18n('en.media_dlg',{\r
+title:"Insert / edit embedded media",\r
+general:"General",\r
+advanced:"Advanced",\r
+file:"File/URL",\r
+list:"List",\r
+size:"Dimensions",\r
+preview:"Preview",\r
+constrain_proportions:"Constrain proportions",\r
+type:"Type",\r
+id:"Id",\r
+name:"Name",\r
+class_name:"Class",\r
+vspace:"V-Space",\r
+hspace:"H-Space",\r
+play:"Auto play",\r
+loop:"Loop",\r
+menu:"Show menu",\r
+quality:"Quality",\r
+scale:"Scale",\r
+align:"Align",\r
+salign:"SAlign",\r
+wmode:"WMode",\r
+bgcolor:"Background",\r
+base:"Base",\r
+flashvars:"Flashvars",\r
+liveconnect:"SWLiveConnect",\r
+autohref:"AutoHREF",\r
+cache:"Cache",\r
+hidden:"Hidden",\r
+controller:"Controller",\r
+kioskmode:"Kiosk mode",\r
+playeveryframe:"Play every frame",\r
+targetcache:"Target cache",\r
+correction:"No correction",\r
+enablejavascript:"Enable JavaScript",\r
+starttime:"Start time",\r
+endtime:"End time",\r
+href:"Href",\r
+qtsrcchokespeed:"Choke speed",\r
+target:"Target",\r
+volume:"Volume",\r
+autostart:"Auto start",\r
+enabled:"Enabled",\r
+fullscreen:"Fullscreen",\r
+invokeurls:"Invoke URLs",\r
+mute:"Mute",\r
+stretchtofit:"Stretch to fit",\r
+windowlessvideo:"Windowless video",\r
+balance:"Balance",\r
+baseurl:"Base URL",\r
+captioningid:"Captioning id",\r
+currentmarker:"Current marker",\r
+currentposition:"Current position",\r
+defaultframe:"Default frame",\r
+playcount:"Play count",\r
+rate:"Rate",\r
+uimode:"UI Mode",\r
+flash_options:"Flash options",\r
+qt_options:"Quicktime options",\r
+wmp_options:"Windows media player options",\r
+rmp_options:"Real media player options",\r
+shockwave_options:"Shockwave options",\r
+autogotourl:"Auto goto URL",\r
+center:"Center",\r
+imagestatus:"Image status",\r
+maintainaspect:"Maintain aspect",\r
+nojava:"No java",\r
+prefetch:"Prefetch",\r
+shuffle:"Shuffle",\r
+console:"Console",\r
+numloop:"Num loops",\r
+controls:"Controls",\r
+scriptcallbacks:"Script callbacks",\r
+swstretchstyle:"Stretch style",\r
+swstretchhalign:"Stretch H-Align",\r
+swstretchvalign:"Stretch V-Align",\r
+sound:"Sound",\r
+progress:"Progress",\r
+qtsrc:"QT Src",\r
+qt_stream_warn:"Streamed rtsp resources should be added to the QT Src field under the advanced tab.\nYou should also add a non streamed version to the Src field..",\r
+align_top:"Top",\r
+align_right:"Right",\r
+align_bottom:"Bottom",\r
+align_left:"Left",\r
+align_center:"Center",\r
+align_top_left:"Top left",\r
+align_top_right:"Top right",\r
+align_bottom_left:"Bottom left",\r
+align_bottom_right:"Bottom right",\r
+flv_options:"Flash video options",\r
+flv_scalemode:"Scale mode",\r
+flv_buffer:"Buffer",\r
+flv_startimage:"Start image",\r
+flv_starttime:"Start time",\r
+flv_defaultvolume:"Default volumne",\r
+flv_hiddengui:"Hidden GUI",\r
+flv_autostart:"Auto start",\r
+flv_loop:"Loop",\r
+flv_showscalemodes:"Show scale modes",\r
+flv_smoothvideo:"Smooth video",\r
+flv_jscallback:"JS Callback"\r
+});
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/media/media.htm b/jscripts/tiny_mce/plugins/media/media.htm
new file mode 100644 (file)
index 0000000..b54aabf
--- /dev/null
@@ -0,0 +1,824 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#media_dlg.title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="js/media.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/validate.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/editable_selects.js?v=307"></script>\r
+       <link href="css/media.css?v=307" rel="stylesheet" type="text/css" />\r
+       <base target="_self" />\r
+</head>\r
+<body style="display: none">\r
+    <form onsubmit="insertMedia();return false;" action="#">\r
+               <div class="tabs">\r
+                       <ul>\r
+                               <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');generatePreview();" onmousedown="return false;">{#media_dlg.general}</a></span></li>\r
+                               <li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#media_dlg.advanced}</a></span></li>\r
+                       </ul>\r
+               </div>\r
+\r
+               <div class="panel_wrapper">\r
+                       <div id="general_panel" class="panel current">\r
+                               <fieldset>\r
+                                       <legend>{#media_dlg.general}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                                       <tr>\r
+                                                               <td><label for="media_type">{#media_dlg.type}</label></td>\r
+                                                               <td>\r
+                                                                       <select id="media_type" name="media_type" onchange="changedType(this.value);generatePreview();">\r
+                                                                               <option value="flash">Flash</option>\r
+                                                                               <!-- <option value="flv">Flash video (FLV)</option> -->\r
+                                                                               <option value="qt">Quicktime</option>\r
+                                                                               <option value="shockwave">Shockwave</option>\r
+                                                                               <option value="wmp">Windows Media</option>\r
+                                                                               <option value="rmp">Real Media</option>\r
+                                                                       </select>\r
+                                                               </td>\r
+                                                       </tr>\r
+                                                       <tr>\r
+                                                       <td><label for="src">{#media_dlg.file}</label></td>\r
+                                                         <td>\r
+                                                                       <table border="0" cellspacing="0" cellpadding="0">\r
+                                                                         <tr>\r
+                                                                               <td><input id="src" name="src" type="text" value="" class="mceFocus" onchange="switchType(this.value);generatePreview();" /></td>\r
+                                                                               <td id="filebrowsercontainer">&nbsp;</td>\r
+                                                                         </tr>\r
+                                                                       </table>\r
+                                                               </td>\r
+                                                       </tr>\r
+                                                       <tr id="linklistrow">\r
+                                                               <td><label for="linklist">{#media_dlg.list}</label></td>\r
+                                                               <td id="linklistcontainer">&nbsp;</td>\r
+                                                       </tr>\r
+                                                       <tr>\r
+                                                               <td><label for="width">{#media_dlg.size}</label></td>\r
+                                                               <td>\r
+                                                                       <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                               <tr>\r
+                                                                                       <td><input type="text" id="width" name="width" value="" class="size" onchange="generatePreview('width');" /> x <input type="text" id="height" name="height" value="" class="size"  onchange="generatePreview('height');" /></td>\r
+                                                                                       <td>&nbsp;&nbsp;<input id="constrain" type="checkbox" name="constrain" class="checkbox" /></td>\r
+                                                                                       <td><label id="constrainlabel" for="constrain">{#media_dlg.constrain_proportions}</label></td>\r
+                                                                               </tr>\r
+                                                                       </table>\r
+                                                               </td>\r
+                                                       </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+\r
+                               <fieldset>\r
+                                       <legend>{#media_dlg.preview}</legend>\r
+                                       <div id="prev"></div>\r
+                               </fieldset>\r
+                       </div>\r
+\r
+                       <div id="advanced_panel" class="panel">\r
+                               <fieldset>\r
+                                       <legend>{#media_dlg.advanced}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0" width="100%">\r
+                                               <tr>\r
+                                                       <td><label for="id">{#media_dlg.id}</label></td>\r
+                                                       <td><input type="text" id="id" name="id" onchange="generatePreview();" /></td>\r
+                                                       <td><label for="name">{#media_dlg.name}</label></td>\r
+                                                       <td><input type="text" id="name" name="name" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="align">{#media_dlg.align}</label></td>\r
+                                                       <td>\r
+                                                               <select id="align" name="align" onchange="generatePreview();">\r
+                                                                       <option value="">{#not_set}</option> \r
+                                                                       <option value="top">{#media_dlg.align_top}</option>\r
+                                                                       <option value="right">{#media_dlg.align_right}</option>\r
+                                                                       <option value="bottom">{#media_dlg.align_bottom}</option>\r
+                                                                       <option value="left">{#media_dlg.align_left}</option>\r
+                                                               </select>\r
+                                                       </td>\r
+\r
+                                                       <td><label for="bgcolor">{#media_dlg.bgcolor}</label></td>\r
+                                                       <td>\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="bgcolor" name="bgcolor" type="text" value="" size="9" onchange="updateColor('bgcolor_pick','bgcolor');generatePreview();" /></td>\r
+                                                                               <td id="bgcolor_pickcontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="vspace">{#media_dlg.vspace}</label></td>\r
+                                                       <td><input type="text" id="vspace" name="vspace" class="number" onchange="generatePreview();" /></td>\r
+                                                       <td><label for="hspace">{#media_dlg.hspace}</label></td>\r
+                                                       <td><input type="text" id="hspace" name="hspace" class="number" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+\r
+                               <fieldset id="flash_options">\r
+                                       <legend>{#media_dlg.flash_options}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td><label for="flash_quality">{#media_dlg.quality}</label></td>\r
+                                                       <td>\r
+                                                               <select id="flash_quality" name="flash_quality" onchange="generatePreview();">\r
+                                                                       <option value="">{#not_set}</option> \r
+                                                                       <option value="high">high</option>\r
+                                                                       <option value="low">low</option>\r
+                                                                       <option value="autolow">autolow</option>\r
+                                                                       <option value="autohigh">autohigh</option>\r
+                                                                       <option value="best">best</option>\r
+                                                               </select>\r
+                                                       </td>\r
+\r
+                                                       <td><label for="flash_scale">{#media_dlg.scale}</label></td>\r
+                                                       <td>\r
+                                                               <select id="flash_scale" name="flash_scale" onchange="generatePreview();">\r
+                                                                       <option value="">{#not_set}</option> \r
+                                                                       <option value="showall">showall</option>\r
+                                                                       <option value="noborder">noborder</option>\r
+                                                                       <option value="exactfit">exactfit</option>\r
+                                                                       <option value="noscale">noscale</option>\r
+                                                               </select>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="flash_wmode">{#media_dlg.wmode}</label></td>\r
+                                                       <td>\r
+                                                               <select id="flash_wmode" name="flash_wmode" onchange="generatePreview();">\r
+                                                                       <option value="">{#not_set}</option> \r
+                                                                       <option value="window">window</option>\r
+                                                                       <option value="opaque">opaque</option>\r
+                                                                       <option value="transparent">transparent</option>\r
+                                                               </select>\r
+                                                       </td>\r
+\r
+                                                       <td><label for="flash_salign">{#media_dlg.salign}</label></td>\r
+                                                       <td>\r
+                                                               <select id="flash_salign" name="flash_salign" onchange="generatePreview();">\r
+                                                                       <option value="">{#not_set}</option> \r
+                                                                       <option value="l">{#media_dlg.align_left}</option>\r
+                                                                       <option value="t">{#media_dlg.align_top}</option>\r
+                                                                       <option value="r">{#media_dlg.align_right}</option>\r
+                                                                       <option value="b">{#media_dlg.align_bottom}</option>\r
+                                                                       <option value="tl">{#media_dlg.align_top_left}</option>\r
+                                                                       <option value="tr">{#media_dlg.align_top_right}</option>\r
+                                                                       <option value="bl">{#media_dlg.align_bottom_left}</option>\r
+                                                                       <option value="br">{#media_dlg.align_bottom_right}</option>\r
+                                                               </select>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="flash_play" name="flash_play" checked="checked" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="flash_play">{#media_dlg.play}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="flash_loop" name="flash_loop" checked="checked" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="flash_loop">{#media_dlg.loop}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="flash_menu" name="flash_menu" checked="checked" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="flash_menu">{#media_dlg.menu}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="flash_swliveconnect" name="flash_swliveconnect" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="flash_swliveconnect">{#media_dlg.liveconnect}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+                                       </table>\r
+\r
+                                       <table>\r
+                                               <tr>\r
+                                                       <td><label for="flash_base">{#media_dlg.base}</label></td>\r
+                                                       <td><input type="text" id="flash_base" name="flash_base" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="flash_flashvars">{#media_dlg.flashvars}</label></td>\r
+                                                       <td><input type="text" id="flash_flashvars" name="flash_flashvars" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+\r
+                               <fieldset id="flv_options">\r
+                                       <legend>{#media_dlg.flv_options}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td><label for="flv_scalemode">{#media_dlg.flv_scalemode}</label></td>\r
+                                                       <td>\r
+                                                               <select id="flv_scalemode" name="flv_scalemode" onchange="generatePreview();">\r
+                                                                       <option value="">{#not_set}</option> \r
+                                                                       <option value="none">none</option>\r
+                                                                       <option value="double">double</option>\r
+                                                                       <option value="full">full</option>\r
+                                                               </select>\r
+                                                       </td>\r
+\r
+                                                       <td><label for="flv_buffer">{#media_dlg.flv_buffer}</label></td>\r
+                                                       <td><input type="text" id="flv_buffer" name="flv_buffer" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="flv_startimage">{#media_dlg.flv_startimage}</label></td>\r
+                                                       <td><input type="text" id="flv_startimage" name="flv_startimage" onchange="generatePreview();" /></td>\r
+\r
+                                                       <td><label for="flv_starttime">{#media_dlg.flv_starttime}</label></td>\r
+                                                       <td><input type="text" id="flv_starttime" name="flv_starttime" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="flv_defaultvolume">{#media_dlg.flv_defaultvolume}</label></td>\r
+                                                       <td><input type="text" id="flv_defaultvolume" name="flv_defaultvolume" onchange="generatePreview();" /></td>\r
+\r
+                                                       <td><label for="flv_starttime">{#media_dlg.flv_starttime}</label></td>\r
+                                                       <td><input type="text" id="flv_starttime" name="flv_starttime" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="flv_hiddengui" name="flv_hiddengui" checked="checked" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="flv_hiddengui">{#media_dlg.flv_hiddengui}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="flv_autostart" name="flv_autostart" checked="checked" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="flv_autostart">{#media_dlg.flv_autostart}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="flv_loop" name="flv_loop" checked="checked" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="flv_loop">{#media_dlg.flv_loop}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="flv_showscalemodes" name="flv_showscalemodes" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="flv_showscalemodes">{#media_dlg.flv_showscalemodes}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="flv_smoothvideo" name="flash_flv_flv_smoothvideosmoothvideo" checked="checked" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="flv_smoothvideo">{#media_dlg.flv_smoothvideo}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="flv_jscallback" name="flv_jscallback" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="flv_jscallback">{#media_dlg.flv_jscallback}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+\r
+                               <fieldset id="qt_options">\r
+                                       <legend>{#media_dlg.qt_options}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="qt_loop" name="qt_loop" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="qt_loop">{#media_dlg.loop}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="qt_autoplay" name="qt_autoplay" checked="checked" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="qt_autoplay">{#media_dlg.play}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="qt_cache" name="qt_cache" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="qt_cache">{#media_dlg.cache}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="qt_controller" name="qt_controller" checked="checked" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="qt_controller">{#media_dlg.controller}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="qt_correction" name="qt_correction" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="qt_correction">{#media_dlg.correction}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="qt_enablejavascript" name="qt_enablejavascript" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="qt_enablejavascript">{#media_dlg.enablejavascript}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="qt_kioskmode" name="qt_kioskmode" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="qt_kioskmode">{#media_dlg.kioskmode}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="qt_autohref" name="qt_autohref" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="qt_autohref">{#media_dlg.autohref}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="qt_playeveryframe" name="qt_playeveryframe" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="qt_playeveryframe">{#media_dlg.playeveryframe}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="qt_targetcache" name="qt_targetcache" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="qt_targetcache">{#media_dlg.targetcache}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="qt_scale">{#media_dlg.scale}</label></td>\r
+                                                       <td><select id="qt_scale" name="qt_scale" class="mceEditableSelect" onchange="generatePreview();">\r
+                                                                       <option value="">{#not_set}</option> \r
+                                                                       <option value="tofit">tofit</option>\r
+                                                                       <option value="aspect">aspect</option>\r
+                                                               </select>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">&nbsp;</td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="qt_starttime">{#media_dlg.starttime}</label></td>\r
+                                                       <td><input type="text" id="qt_starttime" name="qt_starttime" onchange="generatePreview();" /></td>\r
+\r
+                                                       <td><label for="qt_endtime">{#media_dlg.endtime}</label></td>\r
+                                                       <td><input type="text" id="qt_endtime" name="qt_endtime" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="qt_target">{#media_dlg.target}</label></td>\r
+                                                       <td><input type="text" id="qt_target" name="qt_target" onchange="generatePreview();" /></td>\r
+\r
+                                                       <td><label for="qt_href">{#media_dlg.href}</label></td>\r
+                                                       <td><input type="text" id="qt_href" name="qt_href" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="qt_qtsrcchokespeed">{#media_dlg.qtsrcchokespeed}</label></td>\r
+                                                       <td><input type="text" id="qt_qtsrcchokespeed" name="qt_qtsrcchokespeed" onchange="generatePreview();" /></td>\r
+\r
+                                                       <td><label for="qt_volume">{#media_dlg.volume}</label></td>\r
+                                                       <td><input type="text" id="qt_volume" name="qt_volume" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="qt_qtsrc">{#media_dlg.qtsrc}</label></td>\r
+                                                       <td colspan="4">\r
+                                                       <table border="0" cellspacing="0" cellpadding="0">\r
+                                                                 <tr>\r
+                                                                       <td><input type="text" id="qt_qtsrc" name="qt_qtsrc" onchange="generatePreview();" /></td>\r
+                                                                       <td id="qtsrcfilebrowsercontainer">&nbsp;</td>\r
+                                                                 </tr>\r
+                                                       </table>\r
+                                                       </td>\r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+\r
+                               <fieldset id="wmp_options">\r
+                                       <legend>{#media_dlg.wmp_options}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="wmp_autostart" name="wmp_autostart" checked="checked" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="wmp_autostart">{#media_dlg.autostart}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="wmp_enabled" name="wmp_enabled" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="wmp_enabled">{#media_dlg.enabled}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="wmp_enablecontextmenu" name="wmp_enablecontextmenu" checked="checked" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="wmp_enablecontextmenu">{#media_dlg.menu}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="wmp_fullscreen" name="wmp_fullscreen" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="wmp_fullscreen">{#media_dlg.fullscreen}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="wmp_invokeurls" name="wmp_invokeurls" checked="checked" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="wmp_invokeurls">{#media_dlg.invokeurls}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="wmp_mute" name="wmp_mute" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="wmp_mute">{#media_dlg.mute}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="wmp_stretchtofit" name="wmp_stretchtofit" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="wmp_stretchtofit">{#media_dlg.stretchtofit}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="wmp_windowlessvideo" name="wmp_windowlessvideo" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="wmp_windowlessvideo">{#media_dlg.windowlessvideo}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="wmp_balance">{#media_dlg.balance}</label></td>\r
+                                                       <td><input type="text" id="wmp_balance" name="wmp_balance" onchange="generatePreview();" /></td>\r
+\r
+                                                       <td><label for="wmp_baseurl">{#media_dlg.baseurl}</label></td>\r
+                                                       <td><input type="text" id="wmp_baseurl" name="wmp_baseurl" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="wmp_captioningid">{#media_dlg.captioningid}</label></td>\r
+                                                       <td><input type="text" id="wmp_captioningid" name="wmp_captioningid" onchange="generatePreview();" /></td>\r
+\r
+                                                       <td><label for="wmp_currentmarker">{#media_dlg.currentmarker}</label></td>\r
+                                                       <td><input type="text" id="wmp_currentmarker" name="wmp_currentmarker" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="wmp_currentposition">{#media_dlg.currentposition}</label></td>\r
+                                                       <td><input type="text" id="wmp_currentposition" name="wmp_currentposition" onchange="generatePreview();" /></td>\r
+\r
+                                                       <td><label for="wmp_defaultframe">{#media_dlg.defaultframe}</label></td>\r
+                                                       <td><input type="text" id="wmp_defaultframe" name="wmp_defaultframe" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="wmp_playcount">{#media_dlg.playcount}</label></td>\r
+                                                       <td><input type="text" id="wmp_playcount" name="wmp_playcount" onchange="generatePreview();" /></td>\r
+\r
+                                                       <td><label for="wmp_rate">{#media_dlg.rate}</label></td>\r
+                                                       <td><input type="text" id="wmp_rate" name="wmp_rate" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="wmp_uimode">{#media_dlg.uimode}</label></td>\r
+                                                       <td><input type="text" id="wmp_uimode" name="wmp_uimode" onchange="generatePreview();" /></td>\r
+\r
+                                                       <td><label for="wmp_volume">{#media_dlg.volume}</label></td>\r
+                                                       <td><input type="text" id="wmp_volume" name="wmp_volume" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+\r
+                                       </table>\r
+                               </fieldset>\r
+\r
+                               <fieldset id="rmp_options">\r
+                                       <legend>{#media_dlg.rmp_options}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="rmp_autostart" name="rmp_autostart" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="rmp_autostart">{#media_dlg.autostart}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="rmp_loop" name="rmp_loop" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="rmp_loop">{#media_dlg.loop}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="rmp_autogotourl" name="rmp_autogotourl" checked="checked" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="rmp_autogotourl">{#media_dlg.autogotourl}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="rmp_center" name="rmp_center" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="rmp_center">{#media_dlg.center}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="rmp_imagestatus" name="rmp_imagestatus" checked="checked" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="rmp_imagestatus">{#media_dlg.imagestatus}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="rmp_maintainaspect" name="rmp_maintainaspect" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="rmp_maintainaspect">{#media_dlg.maintainaspect}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="rmp_nojava" name="rmp_nojava" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="rmp_nojava">{#media_dlg.nojava}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="rmp_prefetch" name="rmp_prefetch" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="rmp_prefetch">{#media_dlg.prefetch}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="rmp_shuffle" name="rmp_shuffle" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="rmp_shuffle">{#media_dlg.shuffle}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               &nbsp;\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="rmp_console">{#media_dlg.console}</label></td>\r
+                                                       <td><input type="text" id="rmp_console" name="rmp_console" onchange="generatePreview();" /></td>\r
+\r
+                                                       <td><label for="rmp_controls">{#media_dlg.controls}</label></td>\r
+                                                       <td><input type="text" id="rmp_controls" name="rmp_controls" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="rmp_numloop">{#media_dlg.numloop}</label></td>\r
+                                                       <td><input type="text" id="rmp_numloop" name="rmp_numloop" onchange="generatePreview();" /></td>\r
+\r
+                                                       <td><label for="rmp_scriptcallbacks">{#media_dlg.scriptcallbacks}</label></td>\r
+                                                       <td><input type="text" id="rmp_scriptcallbacks" name="rmp_scriptcallbacks" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+\r
+                               <fieldset id="shockwave_options">\r
+                                       <legend>{#media_dlg.shockwave_options}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td><label for="shockwave_swstretchstyle">{#media_dlg.swstretchstyle}</label></td>\r
+                                                       <td>\r
+                                                               <select id="shockwave_swstretchstyle" name="shockwave_swstretchstyle" onchange="generatePreview();">\r
+                                                                       <option value="none">{#not_set}</option>\r
+                                                                       <option value="meet">Meet</option>\r
+                                                                       <option value="fill">Fill</option>\r
+                                                                       <option value="stage">Stage</option>\r
+                                                               </select>\r
+                                                       </td>\r
+\r
+                                                       <td><label for="shockwave_swvolume">{#media_dlg.volume}</label></td>\r
+                                                       <td><input type="text" id="shockwave_swvolume" name="shockwave_swvolume" onchange="generatePreview();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="shockwave_swstretchhalign">{#media_dlg.swstretchhalign}</label></td>\r
+                                                       <td>\r
+                                                               <select id="shockwave_swstretchhalign" name="shockwave_swstretchhalign" onchange="generatePreview();">\r
+                                                                       <option value="none">{#not_set}</option>\r
+                                                                       <option value="left">{#media_dlg.align_left}</option>\r
+                                                                       <option value="center">{#media_dlg.align_center}</option>\r
+                                                                       <option value="right">{#media_dlg.align_right}</option>\r
+                                                               </select>\r
+                                                       </td>\r
+\r
+                                                       <td><label for="shockwave_swstretchvalign">{#media_dlg.swstretchvalign}</label></td>\r
+                                                       <td>\r
+                                                               <select id="shockwave_swstretchvalign" name="shockwave_swstretchvalign" onchange="generatePreview();">\r
+                                                                       <option value="none">{#not_set}</option>\r
+                                                                       <option value="meet">Meet</option>\r
+                                                                       <option value="fill">Fill</option>\r
+                                                                       <option value="stage">Stage</option>\r
+                                                               </select>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="shockwave_autostart" name="shockwave_autostart" onchange="generatePreview();" checked="checked" /></td>\r
+                                                                               <td><label for="shockwave_autostart">{#media_dlg.autostart}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="shockwave_sound" name="shockwave_sound" onchange="generatePreview();" checked="checked" /></td>\r
+                                                                               <td><label for="shockwave_sound">{#media_dlg.sound}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+\r
+                                               <tr>\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="shockwave_swliveconnect" name="shockwave_swliveconnect" onchange="generatePreview();" /></td>\r
+                                                                               <td><label for="shockwave_swliveconnect">{#media_dlg.liveconnect}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+\r
+                                                       <td colspan="2">\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input type="checkbox" class="checkbox" id="shockwave_progress" name="shockwave_progress" onchange="generatePreview();" checked="checked" /></td>\r
+                                                                               <td><label for="shockwave_progress">{#media_dlg.progress}</label></td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td>\r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+                       </div>\r
+               </div>\r
+\r
+               <div class="mceActionPanel">\r
+                       <div style="float: left">\r
+                               <input type="submit" id="insert" name="insert" value="{#insert}" />\r
+                       </div>\r
+\r
+                       <div style="float: right">\r
+                               <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+                       </div>\r
+               </div>\r
+       </form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/nonbreaking/editor_plugin.js b/jscripts/tiny_mce/plugins/nonbreaking/editor_plugin.js
new file mode 100644 (file)
index 0000000..4fce503
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.Nonbreaking',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mceNonBreaking',function(){ed.execCommand('mceInsertContent',false,(ed.plugins.visualchars&&ed.plugins.visualchars.state)?'<span class="mceItemHidden mceVisualNbsp">&middot;</span>':'&nbsp;');});ed.addButton('nonbreaking',{title:'nonbreaking.nonbreaking_desc',cmd:'mceNonBreaking'});if(ed.getParam('nonbreaking_force_tab')){ed.onKeyDown.add(function(ed,e){if(tinymce.isIE&&e.keyCode==9){ed.execCommand('mceNonBreaking');ed.execCommand('mceNonBreaking');ed.execCommand('mceNonBreaking');tinymce.dom.Event.cancel(e);}});}},getInfo:function(){return{longname:'Nonbreaking space',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/nonbreaking',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('nonbreaking',tinymce.plugins.Nonbreaking);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/nonbreaking/editor_plugin_src.js b/jscripts/tiny_mce/plugins/nonbreaking/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..b723756
--- /dev/null
@@ -0,0 +1,50 @@
+/**\r
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.Nonbreaking', {\r
+               init : function(ed, url) {\r
+                       var t = this;\r
+\r
+                       t.editor = ed;\r
+\r
+                       // Register commands\r
+                       ed.addCommand('mceNonBreaking', function() {\r
+                               ed.execCommand('mceInsertContent', false, (ed.plugins.visualchars && ed.plugins.visualchars.state) ? '<span class="mceItemHidden mceVisualNbsp">&middot;</span>' : '&nbsp;');\r
+                       });\r
+\r
+                       // Register buttons\r
+                       ed.addButton('nonbreaking', {title : 'nonbreaking.nonbreaking_desc', cmd : 'mceNonBreaking'});\r
+\r
+                       if (ed.getParam('nonbreaking_force_tab')) {\r
+                               ed.onKeyDown.add(function(ed, e) {\r
+                                       if (tinymce.isIE && e.keyCode == 9) {\r
+                                               ed.execCommand('mceNonBreaking');\r
+                                               ed.execCommand('mceNonBreaking');\r
+                                               ed.execCommand('mceNonBreaking');\r
+                                               tinymce.dom.Event.cancel(e);\r
+                                       }\r
+                               });\r
+                       }\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Nonbreaking space',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/nonbreaking',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               }\r
+\r
+               // Private methods\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('nonbreaking', tinymce.plugins.Nonbreaking);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/noneditable/editor_plugin.js b/jscripts/tiny_mce/plugins/noneditable/editor_plugin.js
new file mode 100644 (file)
index 0000000..8a1b8f0
--- /dev/null
@@ -0,0 +1 @@
+(function(){var Event=tinymce.dom.Event;tinymce.create('tinymce.plugins.NonEditablePlugin',{init:function(ed,url){var t=this,editClass,nonEditClass;t.editor=ed;editClass=ed.getParam("noneditable_editable_class","mceEditable");nonEditClass=ed.getParam("noneditable_noneditable_class","mceNonEditable");ed.onNodeChange.addToTop(function(ed,cm,n){var sc,ec;sc=ed.dom.getParent(ed.selection.getStart(),function(n){return ed.dom.hasClass(n,nonEditClass);});ec=ed.dom.getParent(ed.selection.getEnd(),function(n){return ed.dom.hasClass(n,nonEditClass);});if(sc||ec){t._setDisabled(1);return false;}else t._setDisabled(0);});},getInfo:function(){return{longname:'Non editable elements',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/noneditable',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_block:function(ed,e){var k=e.keyCode;if((k>32&&k<41)||(k>111&&k<124))return;return Event.cancel(e);},_setDisabled:function(s){var t=this,ed=t.editor;tinymce.each(ed.controlManager.controls,function(c){c.setDisabled(s);});if(s!==t.disabled){if(s){ed.onKeyDown.addToTop(t._block);ed.onKeyPress.addToTop(t._block);ed.onKeyUp.addToTop(t._block);ed.onPaste.addToTop(t._block);}else{ed.onKeyDown.remove(t._block);ed.onKeyPress.remove(t._block);ed.onKeyUp.remove(t._block);ed.onPaste.remove(t._block);}t.disabled=s;}}});tinymce.PluginManager.add('noneditable',tinymce.plugins.NonEditablePlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/noneditable/editor_plugin_src.js b/jscripts/tiny_mce/plugins/noneditable/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..77db577
--- /dev/null
@@ -0,0 +1,87 @@
+/**\r
+ * $Id: editor_plugin_src.js 743 2008-03-23 17:47:33Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       var Event = tinymce.dom.Event;\r
+\r
+       tinymce.create('tinymce.plugins.NonEditablePlugin', {\r
+               init : function(ed, url) {\r
+                       var t = this, editClass, nonEditClass;\r
+\r
+                       t.editor = ed;\r
+                       editClass = ed.getParam("noneditable_editable_class", "mceEditable");\r
+                       nonEditClass = ed.getParam("noneditable_noneditable_class", "mceNonEditable");\r
+\r
+                       ed.onNodeChange.addToTop(function(ed, cm, n) {\r
+                               var sc, ec;\r
+\r
+                               // Block if start or end is inside a non editable element\r
+                               sc = ed.dom.getParent(ed.selection.getStart(), function(n) {\r
+                                       return ed.dom.hasClass(n, nonEditClass);\r
+                               });\r
+\r
+                               ec = ed.dom.getParent(ed.selection.getEnd(), function(n) {\r
+                                       return ed.dom.hasClass(n, nonEditClass);\r
+                               });\r
+\r
+                               // Block or unblock\r
+                               if (sc || ec) {\r
+                                       t._setDisabled(1);\r
+                                       return false;\r
+                               } else\r
+                                       t._setDisabled(0);\r
+                       });\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Non editable elements',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/noneditable',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               },\r
+\r
+               _block : function(ed, e) {\r
+                       var k = e.keyCode;\r
+\r
+                       // Don't block arrow keys, pg up/down, and F1-F12\r
+                       if ((k > 32 && k < 41) || (k > 111 && k < 124))\r
+                               return;\r
+\r
+                       return Event.cancel(e);\r
+               },\r
+\r
+               _setDisabled : function(s) {\r
+                       var t = this, ed = t.editor;\r
+\r
+                       tinymce.each(ed.controlManager.controls, function(c) {\r
+                               c.setDisabled(s);\r
+                       });\r
+\r
+                       if (s !== t.disabled) {\r
+                               if (s) {\r
+                                       ed.onKeyDown.addToTop(t._block);\r
+                                       ed.onKeyPress.addToTop(t._block);\r
+                                       ed.onKeyUp.addToTop(t._block);\r
+                                       ed.onPaste.addToTop(t._block);\r
+                               } else {\r
+                                       ed.onKeyDown.remove(t._block);\r
+                                       ed.onKeyPress.remove(t._block);\r
+                                       ed.onKeyUp.remove(t._block);\r
+                                       ed.onPaste.remove(t._block);\r
+                               }\r
+\r
+                               t.disabled = s;\r
+                       }\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('noneditable', tinymce.plugins.NonEditablePlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/pagebreak/css/content.css b/jscripts/tiny_mce/plugins/pagebreak/css/content.css
new file mode 100644 (file)
index 0000000..c949d58
--- /dev/null
@@ -0,0 +1 @@
+.mcePageBreak {display:block;border:0;width:100%;height:12px;border-top:1px dotted #ccc;margin-top:15px;background:#fff url(../img/pagebreak.gif) no-repeat center top;}
diff --git a/jscripts/tiny_mce/plugins/pagebreak/editor_plugin.js b/jscripts/tiny_mce/plugins/pagebreak/editor_plugin.js
new file mode 100644 (file)
index 0000000..177ea95
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.PageBreakPlugin',{init:function(ed,url){var pb='<img src="'+url+'/img/trans.gif" class="mcePageBreak mceItemNoResize" />',cls='mcePageBreak',sep=ed.getParam('pagebreak_separator','<!-- pagebreak -->'),pbRE;pbRE=new RegExp(sep.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,function(a){return'\\'+a;}),'g');ed.addCommand('mcePageBreak',function(){ed.execCommand('mceInsertContent',0,pb);});ed.addButton('pagebreak',{title:'pagebreak.desc',cmd:cls});ed.onInit.add(function(){if(ed.settings.content_css!==false)ed.dom.loadCSS(url+"/css/content.css");if(ed.theme.onResolveName){ed.theme.onResolveName.add(function(th,o){if(o.node.nodeName=='IMG'&&ed.dom.hasClass(o.node,cls))o.name='pagebreak';});}});ed.onClick.add(function(ed,e){e=e.target;if(e.nodeName==='IMG'&&ed.dom.hasClass(e,cls))ed.selection.select(e);});ed.onNodeChange.add(function(ed,cm,n){cm.setActive('pagebreak',n.nodeName==='IMG'&&ed.dom.hasClass(n,cls));});ed.onBeforeSetContent.add(function(ed,o){o.content=o.content.replace(pbRE,pb);});ed.onPostProcess.add(function(ed,o){if(o.get)o.content=o.content.replace(/<img[^>]+>/g,function(im){if(im.indexOf('class="mcePageBreak')!==-1)im=sep;return im;});});},getInfo:function(){return{longname:'PageBreak',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/pagebreak',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('pagebreak',tinymce.plugins.PageBreakPlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/pagebreak/editor_plugin_src.js b/jscripts/tiny_mce/plugins/pagebreak/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..16f5748
--- /dev/null
@@ -0,0 +1,74 @@
+/**\r
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.PageBreakPlugin', {\r
+               init : function(ed, url) {\r
+                       var pb = '<img src="' + url + '/img/trans.gif" class="mcePageBreak mceItemNoResize" />', cls = 'mcePageBreak', sep = ed.getParam('pagebreak_separator', '<!-- pagebreak -->'), pbRE;\r
+\r
+                       pbRE = new RegExp(sep.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g, function(a) {return '\\' + a;}), 'g');\r
+\r
+                       // Register commands\r
+                       ed.addCommand('mcePageBreak', function() {\r
+                               ed.execCommand('mceInsertContent', 0, pb);\r
+                       });\r
+\r
+                       // Register buttons\r
+                       ed.addButton('pagebreak', {title : 'pagebreak.desc', cmd : cls});\r
+\r
+                       ed.onInit.add(function() {\r
+                               if (ed.settings.content_css !== false)\r
+                                       ed.dom.loadCSS(url + "/css/content.css");\r
+\r
+                               if (ed.theme.onResolveName) {\r
+                                       ed.theme.onResolveName.add(function(th, o) {\r
+                                               if (o.node.nodeName == 'IMG' && ed.dom.hasClass(o.node, cls))\r
+                                                       o.name = 'pagebreak';\r
+                                       });\r
+                               }\r
+                       });\r
+\r
+                       ed.onClick.add(function(ed, e) {\r
+                               e = e.target;\r
+\r
+                               if (e.nodeName === 'IMG' && ed.dom.hasClass(e, cls))\r
+                                       ed.selection.select(e);\r
+                       });\r
+\r
+                       ed.onNodeChange.add(function(ed, cm, n) {\r
+                               cm.setActive('pagebreak', n.nodeName === 'IMG' && ed.dom.hasClass(n, cls));\r
+                       });\r
+\r
+                       ed.onBeforeSetContent.add(function(ed, o) {\r
+                               o.content = o.content.replace(pbRE, pb);\r
+                       });\r
+\r
+                       ed.onPostProcess.add(function(ed, o) {\r
+                               if (o.get)\r
+                                       o.content = o.content.replace(/<img[^>]+>/g, function(im) {\r
+                                               if (im.indexOf('class="mcePageBreak') !== -1)\r
+                                                       im = sep;\r
+\r
+                                               return im;\r
+                                       });\r
+                       });\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'PageBreak',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/pagebreak',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('pagebreak', tinymce.plugins.PageBreakPlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/pagebreak/img/pagebreak.gif b/jscripts/tiny_mce/plugins/pagebreak/img/pagebreak.gif
new file mode 100644 (file)
index 0000000..acdf408
Binary files /dev/null and b/jscripts/tiny_mce/plugins/pagebreak/img/pagebreak.gif differ
diff --git a/jscripts/tiny_mce/plugins/pagebreak/img/trans.gif b/jscripts/tiny_mce/plugins/pagebreak/img/trans.gif
new file mode 100644 (file)
index 0000000..3884865
Binary files /dev/null and b/jscripts/tiny_mce/plugins/pagebreak/img/trans.gif differ
diff --git a/jscripts/tiny_mce/plugins/paste/blank.htm b/jscripts/tiny_mce/plugins/paste/blank.htm
new file mode 100644 (file)
index 0000000..fcf3217
--- /dev/null
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<title>blank_page</title>\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<link href="css/blank.css?v=307" rel="stylesheet" type="text/css" />\r
+<base target="_self" />\r
+<script type="text/javascript">\r
+function init() {\r
+       if (parent.tinymce.isIE)\r
+               document.body.contentEditable = true;\r
+       else\r
+               document.designMode = 'on';\r
+\r
+       parent.initIframe(document);\r
+       window.focus();\r
+}\r
+</script>\r
+</head>\r
+<body onload="init();">\r
+\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/paste/css/blank.css b/jscripts/tiny_mce/plugins/paste/css/blank.css
new file mode 100644 (file)
index 0000000..6b16bac
--- /dev/null
@@ -0,0 +1,14 @@
+html, body {height:98%}\r
+body {\r
+background-color: #FFFFFF;\r
+font-family: Verdana, Arial, Helvetica, sans-serif;\r
+font-size: 10px;\r
+scrollbar-3dlight-color: #F0F0EE;\r
+scrollbar-arrow-color: #676662;\r
+scrollbar-base-color: #F0F0EE;\r
+scrollbar-darkshadow-color: #DDDDDD;\r
+scrollbar-face-color: #E0E0DD;\r
+scrollbar-highlight-color: #F0F0EE;\r
+scrollbar-shadow-color: #F0F0EE;\r
+scrollbar-track-color: #F5F5F5;\r
+}\r
diff --git a/jscripts/tiny_mce/plugins/paste/css/pasteword.css b/jscripts/tiny_mce/plugins/paste/css/pasteword.css
new file mode 100644 (file)
index 0000000..b3be627
--- /dev/null
@@ -0,0 +1,3 @@
+.sourceIframe {\r
+       border: 1px solid #808080;\r
+}\r
diff --git a/jscripts/tiny_mce/plugins/paste/editor_plugin.js b/jscripts/tiny_mce/plugins/paste/editor_plugin.js
new file mode 100644 (file)
index 0000000..b317ed2
--- /dev/null
@@ -0,0 +1 @@
+(function(){var Event=tinymce.dom.Event;tinymce.create('tinymce.plugins.PastePlugin',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mcePasteText',function(ui,v){if(ui){if((ed.getParam('paste_use_dialog',true))||(!tinymce.isIE)){ed.windowManager.open({file:url+'/pastetext.htm',width:450,height:400,inline:1},{plugin_url:url});}else t._insertText(clipboardData.getData("Text"),true);}else t._insertText(v.html,v.linebreaks);});ed.addCommand('mcePasteWord',function(ui,v){if(ui){if((ed.getParam('paste_use_dialog',true))||(!tinymce.isIE)){ed.windowManager.open({file:url+'/pasteword.htm',width:450,height:400,inline:1},{plugin_url:url});}else t._insertText(t._clipboardHTML());}else t._insertWordContent(v);});ed.addCommand('mceSelectAll',function(){ed.execCommand('selectall');});ed.addButton('pastetext',{title:'paste.paste_text_desc',cmd:'mcePasteText',ui:true});ed.addButton('pasteword',{title:'paste.paste_word_desc',cmd:'mcePasteWord',ui:true});ed.addButton('selectall',{title:'paste.selectall_desc',cmd:'mceSelectAll'});if(ed.getParam("paste_auto_cleanup_on_paste",false)){ed.onPaste.add(function(ed,e){return t._handlePasteEvent(e)});}if(!tinymce.isIE&&ed.getParam("paste_auto_cleanup_on_paste",false)){ed.onKeyDown.add(function(ed,e){if(e.ctrlKey&&e.keyCode==86){window.setTimeout(function(){ed.execCommand("mcePasteText",true);},1);Event.cancel(e);}});}},getInfo:function(){return{longname:'Paste text/word',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_handlePasteEvent:function(e){var html=this._clipboardHTML(),ed=this.editor,sel=ed.selection,r;if(ed&&(r=sel.getRng())&&r.text.length>0)ed.execCommand('delete');if(html&&html.length>0)ed.execCommand('mcePasteWord',false,html);return Event.cancel(e);},_insertText:function(content,bLinebreaks){if(content&&content.length>0){if(bLinebreaks){if(this.editor.getParam("paste_create_paragraphs",true)){var rl=this.editor.getParam("paste_replace_list",'\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(',');for(var i=0;i<rl.length;i+=2)content=content.replace(new RegExp(rl[i],'gi'),rl[i+1]);content=content.replace(/\r\n\r\n/g,'</p><p>');content=content.replace(/\r\r/g,'</p><p>');content=content.replace(/\n\n/g,'</p><p>');if((pos=content.indexOf('</p><p>'))!=-1){this.editor.execCommand("Delete");var node=this.editor.selection.getNode();var breakElms=[];do{if(node.nodeType==1){if(node.nodeName=="TD"||node.nodeName=="BODY")break;breakElms[breakElms.length]=node;}}while(node=node.parentNode);var before="",after="</p>";before+=content.substring(0,pos);for(var i=0;i<breakElms.length;i++){before+="</"+breakElms[i].nodeName+">";after+="<"+breakElms[(breakElms.length-1)-i].nodeName+">";}before+="<p>";content=before+content.substring(pos+7)+after;}}if(this.editor.getParam("paste_create_linebreaks",true)){content=content.replace(/\r\n/g,'<br />');content=content.replace(/\r/g,'<br />');content=content.replace(/\n/g,'<br />');}}this.editor.execCommand("mceInsertRawHTML",false,content);}},_insertWordContent:function(content){var t=this,ed=t.editor;if(content&&content.length>0){var bull=String.fromCharCode(8226);var middot=String.fromCharCode(183);if(ed.getParam('paste_insert_word_content_callback'))content=ed.execCallback('paste_insert_word_content_callback','before',content);var rl=ed.getParam("paste_replace_list",'\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(',');for(var i=0;i<rl.length;i+=2)content=content.replace(new RegExp(rl[i],'gi'),rl[i+1]);if(this.editor.getParam("paste_convert_headers_to_strong",false)){content=content.replace(new RegExp('<p class=MsoHeading.*?>(.*?)<\/p>','gi'),'<p><b>$1</b></p>');}content=content.replace(new RegExp('tab-stops: list [0-9]+.0pt">','gi'),'">'+"--list--");content=content.replace(new RegExp(bull+"(.*?)<BR>","gi"),"<p>"+middot+"$1</p>");content=content.replace(new RegExp('<SPAN style="mso-list: Ignore">','gi'),"<span>"+bull);content=content.replace(/<o:p><\/o:p>/gi,"");content=content.replace(new RegExp('<br style="page-break-before: always;.*>','gi'),'-- page break --');content=content.replace(new RegExp('<(!--)([^>]*)(--)>','g'),"");if(this.editor.getParam("paste_remove_spans",true))content=content.replace(/<\/?span[^>]*>/gi,"");if(this.editor.getParam("paste_remove_styles",true))content=content.replace(new RegExp('<(\\w[^>]*) style="([^"]*)"([^>]*)','gi'),"<$1$3");content=content.replace(/<\/?font[^>]*>/gi,"");switch(this.editor.getParam("paste_strip_class_attributes","all")){case"all":content=content.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi,"<$1$3");break;case"mso":content=content.replace(new RegExp('<(\\w[^>]*) class="?mso([^ |>]*)([^>]*)','gi'),"<$1$3");break;}content=content.replace(new RegExp('href="?'+this._reEscape(""+document.location)+'','gi'),'href="'+this.editor.documentBaseURI.getURI());content=content.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi,"<$1$3");content=content.replace(/<\\?\?xml[^>]*>/gi,"");content=content.replace(/<\/?\w+:[^>]*>/gi,"");content=content.replace(/-- page break --\s*<p>&nbsp;<\/p>/gi,"");content=content.replace(/-- page break --/gi,"");if(!this.editor.getParam('force_p_newlines')){content=content.replace('','','gi');content=content.replace('</p>','<br /><br />','gi');}if(!tinymce.isIE&&!this.editor.getParam('force_p_newlines')){content=content.replace(/<\/?p[^>]*>/gi,"");}content=content.replace(/<\/?div[^>]*>/gi,"");if(this.editor.getParam("paste_convert_middot_lists",true)){var div=ed.dom.create("div",null,content);var className=this.editor.getParam("paste_unindented_list_class","unIndentedList");while(this._convertMiddots(div,"--list--"));while(this._convertMiddots(div,middot,className));while(this._convertMiddots(div,bull));content=div.innerHTML;}if(this.editor.getParam("paste_convert_headers_to_strong",false)){content=content.replace(/<h[1-6]>&nbsp;<\/h[1-6]>/gi,'<p>&nbsp;&nbsp;</p>');content=content.replace(/<h[1-6]>/gi,'<p><b>');content=content.replace(/<\/h[1-6]>/gi,'</b></p>');content=content.replace(/<b>&nbsp;<\/b>/gi,'<b>&nbsp;&nbsp;</b>');content=content.replace(/^(&nbsp;)*/gi,'');}content=content.replace(/--list--/gi,"");if(ed.getParam('paste_insert_word_content_callback'))content=ed.execCallback('paste_insert_word_content_callback','after',content);this.editor.execCommand("mceInsertContent",false,content);if(this.editor.getParam('paste_force_cleanup_wordpaste',true)){var ed=this.editor;window.setTimeout(function(){ed.execCommand("mceCleanup");},1);}}},_reEscape:function(s){var l="?.\\*[](){}+^$:";var o="";for(var i=0;i<s.length;i++){var c=s.charAt(i);if(l.indexOf(c)!=-1)o+='\\'+c;else o+=c;}return o;},_convertMiddots:function(div,search,class_name){var ed=this.editor,mdot=String.fromCharCode(183),bull=String.fromCharCode(8226);var nodes,prevul,i,p,ul,li,np,cp,li;nodes=div.getElementsByTagName("p");for(i=0;i<nodes.length;i++){p=nodes[i];if(p.innerHTML.indexOf(search)==0){ul=ed.dom.create("ul");if(class_name)ul.className=class_name;li=ed.dom.create("li");li.innerHTML=p.innerHTML.replace(new RegExp(''+mdot+'|'+bull+'|--list--|&nbsp;',"gi"),'');ul.appendChild(li);np=p.nextSibling;while(np){if(np.nodeType==3&&new RegExp('^\\s$','m').test(np.nodeValue)){np=np.nextSibling;continue;}if(search==mdot){if(np.nodeType==1&&new RegExp('^o(\\s+|&nbsp;)').test(np.innerHTML)){if(!prevul){prevul=ul;ul=ed.dom.create("ul");prevul.appendChild(ul);}np.innerHTML=np.innerHTML.replace(/^o/,'');}else{if(prevul){ul=prevul;prevul=null;}if(np.nodeType!=1||np.innerHTML.indexOf(search)!=0)break;}}else{if(np.nodeType!=1||np.innerHTML.indexOf(search)!=0)break;}cp=np.nextSibling;li=ed.dom.create("li");li.innerHTML=np.innerHTML.replace(new RegExp(''+mdot+'|'+bull+'|--list--|&nbsp;',"gi"),'');np.parentNode.removeChild(np);ul.appendChild(li);np=cp;}p.parentNode.replaceChild(ul,p);return true;}}return false;},_clipboardHTML:function(){var div=document.getElementById('_TinyMCE_clipboardHTML');if(!div){var div=document.createElement('DIV');div.id='_TinyMCE_clipboardHTML';with(div.style){visibility='hidden';overflow='hidden';position='absolute';width=1;height=1;}document.body.appendChild(div);}div.innerHTML='';var rng=document.body.createTextRange();rng.moveToElementText(div);rng.execCommand('Paste');var html=div.innerHTML;div.innerHTML='';return html;}});tinymce.PluginManager.add('paste',tinymce.plugins.PastePlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/paste/editor_plugin_src.js b/jscripts/tiny_mce/plugins/paste/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..b1e9632
--- /dev/null
@@ -0,0 +1,387 @@
+/**\r
+ * $Id: editor_plugin_src.js 738 2008-03-20 20:00:48Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       var Event = tinymce.dom.Event;\r
+\r
+       tinymce.create('tinymce.plugins.PastePlugin', {\r
+               init : function(ed, url) {\r
+                       var t = this;\r
+\r
+                       t.editor = ed; \r
+\r
+                       // Register commands\r
+                       ed.addCommand('mcePasteText', function(ui, v) {\r
+                               if (ui) {\r
+                                       if ((ed.getParam('paste_use_dialog', true)) || (!tinymce.isIE)) {\r
+                                               ed.windowManager.open({\r
+                                                       file : url + '/pastetext.htm',\r
+                                                       width : 450,\r
+                                                       height : 400,\r
+                                                       inline : 1\r
+                                               }, {\r
+                                                       plugin_url : url\r
+                                               });\r
+                                       } else\r
+                                               t._insertText(clipboardData.getData("Text"), true);\r
+                               } else\r
+                                       t._insertText(v.html, v.linebreaks);\r
+                       });\r
+\r
+                       ed.addCommand('mcePasteWord', function(ui, v) {\r
+                               if (ui) {\r
+                                       if ((ed.getParam('paste_use_dialog', true)) || (!tinymce.isIE)) {\r
+                                               ed.windowManager.open({\r
+                                                       file : url + '/pasteword.htm',\r
+                                                       width : 450,\r
+                                                       height : 400,\r
+                                                       inline : 1\r
+                                               }, {\r
+                                                       plugin_url : url\r
+                                               });\r
+                                       } else\r
+                                               t._insertText(t._clipboardHTML());\r
+                               } else\r
+                                       t._insertWordContent(v);\r
+                       });\r
+\r
+                       ed.addCommand('mceSelectAll', function() {\r
+                               ed.execCommand('selectall'); \r
+                       });\r
+\r
+                       // Register buttons\r
+                       ed.addButton('pastetext', {title : 'paste.paste_text_desc', cmd : 'mcePasteText', ui : true});\r
+                       ed.addButton('pasteword', {title : 'paste.paste_word_desc', cmd : 'mcePasteWord', ui : true});\r
+                       ed.addButton('selectall', {title : 'paste.selectall_desc', cmd : 'mceSelectAll'});\r
+\r
+                       if (ed.getParam("paste_auto_cleanup_on_paste", false)) {\r
+                               ed.onPaste.add(function(ed, e) {\r
+                                       return t._handlePasteEvent(e)\r
+                               });\r
+                       }\r
+\r
+                       if (!tinymce.isIE && ed.getParam("paste_auto_cleanup_on_paste", false)) {\r
+                               // Force paste dialog if non IE browser\r
+                               ed.onKeyDown.add(function(ed, e) {\r
+                                       if (e.ctrlKey && e.keyCode == 86) {\r
+                                               window.setTimeout(function() {\r
+                                                       ed.execCommand("mcePasteText", true);\r
+                                               }, 1);\r
+\r
+                                               Event.cancel(e);\r
+                                       }\r
+                               });\r
+                       }\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Paste text/word',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               },\r
+\r
+               // Private methods\r
+\r
+               _handlePasteEvent : function(e) {\r
+                       var html = this._clipboardHTML(), ed = this.editor, sel = ed.selection, r;\r
+\r
+                       // Removes italic, strong etc, the if was needed due to bug #1437114\r
+                       if (ed && (r = sel.getRng()) && r.text.length > 0)\r
+                               ed.execCommand('delete');\r
+\r
+                       if (html && html.length > 0)\r
+                               ed.execCommand('mcePasteWord', false, html);\r
+\r
+                       return Event.cancel(e);\r
+               },\r
+\r
+               _insertText : function(content, bLinebreaks) { \r
+                       if (content && content.length > 0) {\r
+                               if (bLinebreaks) { \r
+                                       // Special paragraph treatment \r
+                                       if (this.editor.getParam("paste_create_paragraphs", true)) {\r
+                                               var rl = this.editor.getParam("paste_replace_list", '\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(',');\r
+                                               for (var i=0; i<rl.length; i+=2)\r
+                                                       content = content.replace(new RegExp(rl[i], 'gi'), rl[i+1]);\r
+\r
+                                               content = content.replace(/\r\n\r\n/g, '</p><p>');\r
+                                               content = content.replace(/\r\r/g, '</p><p>');\r
+                                               content = content.replace(/\n\n/g, '</p><p>');\r
+\r
+                                               // Has paragraphs \r
+                                               if ((pos = content.indexOf('</p><p>')) != -1) { \r
+                                                       this.editor.execCommand("Delete"); \r
+\r
+                                                       var node = this.editor.selection.getNode(); \r
+\r
+                                                       // Get list of elements to break \r
+                                                       var breakElms = [];\r
+\r
+                                                       do { \r
+                                                               if (node.nodeType == 1) { \r
+                                                                       // Don't break tables and break at body \r
+                                                                       if (node.nodeName == "TD" || node.nodeName == "BODY") \r
+                                                                               break; \r
+                       \r
+                                                                       breakElms[breakElms.length] = node; \r
+                                                               } \r
+                                                       } while(node = node.parentNode); \r
+\r
+                                                       var before = "", after = "</p>"; \r
+                                                       before += content.substring(0, pos); \r
+\r
+                                                       for (var i=0; i<breakElms.length; i++) { \r
+                                                               before += "</" + breakElms[i].nodeName + ">"; \r
+                                                               after += "<" + breakElms[(breakElms.length-1)-i].nodeName + ">"; \r
+                                                       } \r
+\r
+                                                       before += "<p>"; \r
+                                                       content = before + content.substring(pos+7) + after; \r
+                                               } \r
+                                       } \r
+\r
+                                       if (this.editor.getParam("paste_create_linebreaks", true)) {\r
+                                               content = content.replace(/\r\n/g, '<br />');\r
+                                               content = content.replace(/\r/g, '<br />');\r
+                                               content = content.replace(/\n/g, '<br />');\r
+                                       }\r
+                               } \r
+                       \r
+                               this.editor.execCommand("mceInsertRawHTML", false, content); \r
+                       }\r
+               },\r
+\r
+               _insertWordContent : function(content) { \r
+                       var t = this, ed = t.editor;\r
+\r
+                       if (content && content.length > 0) {\r
+                               // Cleanup Word content\r
+                               var bull = String.fromCharCode(8226);\r
+                               var middot = String.fromCharCode(183);\r
+\r
+                               if (ed.getParam('paste_insert_word_content_callback'))\r
+                                       content = ed.execCallback('paste_insert_word_content_callback', 'before', content);\r
+\r
+                               var rl = ed.getParam("paste_replace_list", '\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(',');\r
+                               for (var i=0; i<rl.length; i+=2)\r
+                                       content = content.replace(new RegExp(rl[i], 'gi'), rl[i+1]);\r
+\r
+                               if (this.editor.getParam("paste_convert_headers_to_strong", false)) {\r
+                                       content = content.replace(new RegExp('<p class=MsoHeading.*?>(.*?)<\/p>', 'gi'), '<p><b>$1</b></p>');\r
+                               }\r
+\r
+                               content = content.replace(new RegExp('tab-stops: list [0-9]+.0pt">', 'gi'), '">' + "--list--");\r
+                               content = content.replace(new RegExp(bull + "(.*?)<BR>", "gi"), "<p>" + middot + "$1</p>");\r
+                               content = content.replace(new RegExp('<SPAN style="mso-list: Ignore">', 'gi'), "<span>" + bull); // Covert to bull list\r
+                               content = content.replace(/<o:p><\/o:p>/gi, "");\r
+                               content = content.replace(new RegExp('<br style="page-break-before: always;.*>', 'gi'), '-- page break --'); // Replace pagebreaks\r
+                               content = content.replace(new RegExp('<(!--)([^>]*)(--)>', 'g'), "");  // Word comments\r
+\r
+                               if (this.editor.getParam("paste_remove_spans", true))\r
+                                       content = content.replace(/<\/?span[^>]*>/gi, "");\r
+\r
+                               if (this.editor.getParam("paste_remove_styles", true))\r
+                                       content = content.replace(new RegExp('<(\\w[^>]*) style="([^"]*)"([^>]*)', 'gi'), "<$1$3");\r
+\r
+                               content = content.replace(/<\/?font[^>]*>/gi, "");\r
+\r
+                               // Strips class attributes.\r
+                               switch (this.editor.getParam("paste_strip_class_attributes", "all")) {\r
+                                       case "all":\r
+                                               content = content.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi, "<$1$3");\r
+                                               break;\r
+\r
+                                       case "mso":\r
+                                               content = content.replace(new RegExp('<(\\w[^>]*) class="?mso([^ |>]*)([^>]*)', 'gi'), "<$1$3");\r
+                                               break;\r
+                               }\r
+\r
+                               content = content.replace(new RegExp('href="?' + this._reEscape("" + document.location) + '', 'gi'), 'href="' + this.editor.documentBaseURI.getURI());\r
+                               content = content.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi, "<$1$3");\r
+                               content = content.replace(/<\\?\?xml[^>]*>/gi, "");\r
+                               content = content.replace(/<\/?\w+:[^>]*>/gi, "");\r
+                               content = content.replace(/-- page break --\s*<p>&nbsp;<\/p>/gi, ""); // Remove pagebreaks\r
+                               content = content.replace(/-- page break --/gi, ""); // Remove pagebreaks\r
+\r
+               //              content = content.replace(/\/?&nbsp;*/gi, ""); &nbsp;\r
+               //              content = content.replace(/<p>&nbsp;<\/p>/gi, '');\r
+\r
+                               if (!this.editor.getParam('force_p_newlines')) {\r
+                                       content = content.replace('', '' ,'gi');\r
+                                       content = content.replace('</p>', '<br /><br />' ,'gi');\r
+                               }\r
+\r
+                               if (!tinymce.isIE && !this.editor.getParam('force_p_newlines')) {\r
+                                       content = content.replace(/<\/?p[^>]*>/gi, "");\r
+                               }\r
+\r
+                               content = content.replace(/<\/?div[^>]*>/gi, "");\r
+\r
+                               // Convert all middlot lists to UL lists\r
+                               if (this.editor.getParam("paste_convert_middot_lists", true)) {\r
+                                       var div = ed.dom.create("div", null, content);\r
+\r
+                                       // Convert all middot paragraphs to li elements\r
+                                       var className = this.editor.getParam("paste_unindented_list_class", "unIndentedList");\r
+\r
+                                       while (this._convertMiddots(div, "--list--")) ; // bull\r
+                                       while (this._convertMiddots(div, middot, className)) ; // Middot\r
+                                       while (this._convertMiddots(div, bull)) ; // bull\r
+\r
+                                       content = div.innerHTML;\r
+                               }\r
+\r
+                               // Replace all headers with strong and fix some other issues\r
+                               if (this.editor.getParam("paste_convert_headers_to_strong", false)) {\r
+                                       content = content.replace(/<h[1-6]>&nbsp;<\/h[1-6]>/gi, '<p>&nbsp;&nbsp;</p>');\r
+                                       content = content.replace(/<h[1-6]>/gi, '<p><b>');\r
+                                       content = content.replace(/<\/h[1-6]>/gi, '</b></p>');\r
+                                       content = content.replace(/<b>&nbsp;<\/b>/gi, '<b>&nbsp;&nbsp;</b>');\r
+                                       content = content.replace(/^(&nbsp;)*/gi, '');\r
+                               }\r
+\r
+                               content = content.replace(/--list--/gi, ""); // Remove --list--\r
+\r
+                               if (ed.getParam('paste_insert_word_content_callback'))\r
+                                       content = ed.execCallback('paste_insert_word_content_callback', 'after', content);\r
+\r
+                               // Insert cleaned content\r
+                               this.editor.execCommand("mceInsertContent", false, content);\r
+\r
+                               if (this.editor.getParam('paste_force_cleanup_wordpaste', true)) {\r
+                                       var ed = this.editor;\r
+\r
+                                       window.setTimeout(function() {\r
+                                               ed.execCommand("mceCleanup");\r
+                                       }, 1); // Do normal cleanup detached from this thread\r
+                               }\r
+                       }\r
+               },\r
+\r
+               _reEscape : function(s) {\r
+                       var l = "?.\\*[](){}+^$:";\r
+                       var o = "";\r
+\r
+                       for (var i=0; i<s.length; i++) {\r
+                               var c = s.charAt(i);\r
+\r
+                               if (l.indexOf(c) != -1)\r
+                                       o += '\\' + c;\r
+                               else\r
+                                       o += c;\r
+                       }\r
+\r
+                       return o;\r
+               },\r
+\r
+               _convertMiddots : function(div, search, class_name) {\r
+                       var ed = this.editor, mdot = String.fromCharCode(183), bull = String.fromCharCode(8226);\r
+                       var nodes, prevul, i, p, ul, li, np, cp, li;\r
+\r
+                       nodes = div.getElementsByTagName("p");\r
+                       for (i=0; i<nodes.length; i++) {\r
+                               p = nodes[i];\r
+\r
+                               // Is middot\r
+                               if (p.innerHTML.indexOf(search) == 0) {\r
+                                       ul = ed.dom.create("ul");\r
+\r
+                                       if (class_name)\r
+                                               ul.className = class_name;\r
+\r
+                                       // Add the first one\r
+                                       li = ed.dom.create("li");\r
+                                       li.innerHTML = p.innerHTML.replace(new RegExp('' + mdot + '|' + bull + '|--list--|&nbsp;', "gi"), '');\r
+                                       ul.appendChild(li);\r
+\r
+                                       // Add the rest\r
+                                       np = p.nextSibling;\r
+                                       while (np) {\r
+                                               // If the node is whitespace, then\r
+                                               // ignore it and continue on.\r
+                                               if (np.nodeType == 3 && new RegExp('^\\s$', 'm').test(np.nodeValue)) {\r
+                                                               np = np.nextSibling;\r
+                                                               continue;\r
+                                               }\r
+\r
+                                               if (search == mdot) {\r
+                                                               if (np.nodeType == 1 && new RegExp('^o(\\s+|&nbsp;)').test(np.innerHTML)) {\r
+                                                                               // Second level of nesting\r
+                                                                               if (!prevul) {\r
+                                                                                               prevul = ul;\r
+                                                                                               ul = ed.dom.create("ul");\r
+                                                                                               prevul.appendChild(ul);\r
+                                                                               }\r
+                                                                               np.innerHTML = np.innerHTML.replace(/^o/, '');\r
+                                                               } else {\r
+                                                                               // Pop the stack if we're going back up to the first level\r
+                                                                               if (prevul) {\r
+                                                                                               ul = prevul;\r
+                                                                                               prevul = null;\r
+                                                                               }\r
+                                                                               // Not element or middot paragraph\r
+                                                                               if (np.nodeType != 1 || np.innerHTML.indexOf(search) != 0)\r
+                                                                                               break;\r
+                                                               }\r
+                                               } else {\r
+                                                               // Not element or middot paragraph\r
+                                                               if (np.nodeType != 1 || np.innerHTML.indexOf(search) != 0)\r
+                                                                               break;\r
+                                                       }\r
+\r
+                                               cp = np.nextSibling;\r
+                                               li = ed.dom.create("li");\r
+                                               li.innerHTML = np.innerHTML.replace(new RegExp('' + mdot + '|' + bull + '|--list--|&nbsp;', "gi"), '');\r
+                                               np.parentNode.removeChild(np);\r
+                                               ul.appendChild(li);\r
+                                               np = cp;\r
+                                       }\r
+\r
+                                       p.parentNode.replaceChild(ul, p);\r
+\r
+                                       return true;\r
+                               }\r
+                       }\r
+\r
+                       return false;\r
+               },\r
+\r
+               _clipboardHTML : function() {\r
+                       var div = document.getElementById('_TinyMCE_clipboardHTML');\r
+\r
+                       if (!div) {\r
+                               var div = document.createElement('DIV');\r
+                               div.id = '_TinyMCE_clipboardHTML';\r
+\r
+                               with (div.style) {\r
+                                       visibility = 'hidden';\r
+                                       overflow = 'hidden';\r
+                                       position = 'absolute';\r
+                                       width = 1;\r
+                                       height = 1;\r
+                               }\r
+\r
+                               document.body.appendChild(div);\r
+                       }\r
+\r
+                       div.innerHTML = '';\r
+                       var rng = document.body.createTextRange();\r
+                       rng.moveToElementText(div);\r
+                       rng.execCommand('Paste');\r
+                       var html = div.innerHTML;\r
+                       div.innerHTML = '';\r
+                       return html;\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('paste', tinymce.plugins.PastePlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/paste/js/pastetext.js b/jscripts/tiny_mce/plugins/paste/js/pastetext.js
new file mode 100644 (file)
index 0000000..326bb16
--- /dev/null
@@ -0,0 +1,42 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+function saveContent() {\r
+       if (document.forms[0].htmlSource.value == '') {\r
+               tinyMCEPopup.close();\r
+               return false;\r
+       }\r
+\r
+       tinyMCEPopup.execCommand('mcePasteText', false, {\r
+               html : document.forms[0].htmlSource.value,\r
+               linebreaks : document.forms[0].linebreaks.checked\r
+       });\r
+\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function onLoadInit() {\r
+       tinyMCEPopup.resizeToInnerSize();\r
+\r
+       // Remove Gecko spellchecking\r
+       if (tinymce.isGecko)\r
+               document.body.spellcheck = tinyMCEPopup.getParam("gecko_spellcheck");\r
+\r
+       resizeInputs();\r
+}\r
+\r
+var wHeight=0, wWidth=0, owHeight=0, owWidth=0;\r
+\r
+function resizeInputs() {\r
+       if (!tinymce.isIE) {\r
+               wHeight = self.innerHeight-80;\r
+               wWidth = self.innerWidth-17;\r
+       } else {\r
+               wHeight = document.body.clientHeight-80;\r
+               wWidth = document.body.clientWidth-17;\r
+       }\r
+\r
+       document.forms[0].htmlSource.style.height = Math.abs(wHeight) + 'px';\r
+       document.forms[0].htmlSource.style.width  = Math.abs(wWidth) + 'px';\r
+}\r
+\r
+tinyMCEPopup.onInit.add(onLoadInit);
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/paste/js/pasteword.js b/jscripts/tiny_mce/plugins/paste/js/pasteword.js
new file mode 100644 (file)
index 0000000..6701b99
--- /dev/null
@@ -0,0 +1,56 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+function saveContent() {\r
+       var html = document.getElementById("frmData").contentWindow.document.body.innerHTML;\r
+\r
+       if (html == ''){\r
+               tinyMCEPopup.close();\r
+               return false;\r
+       }\r
+\r
+       tinyMCEPopup.execCommand('mcePasteWord', false, html);\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function onLoadInit() {\r
+       tinyMCEPopup.resizeToInnerSize();\r
+\r
+       // Fix for endless reloading in FF\r
+       window.setTimeout(createIFrame, 10);\r
+}\r
+\r
+function createIFrame() {\r
+       document.getElementById('iframecontainer').innerHTML = '<iframe id="frmData" name="frmData" class="sourceIframe" src="blank.htm" height="280" width="400" frameborder="0" style="background-color:#FFFFFF; width:100%;" dir="ltr" wrap="soft"></iframe>';\r
+}\r
+\r
+var wHeight=0, wWidth=0, owHeight=0, owWidth=0;\r
+\r
+function initIframe(doc) {\r
+       var dir = tinyMCEPopup.editor.settings.directionality;\r
+\r
+       doc.body.dir = dir;\r
+\r
+       // Remove Gecko spellchecking\r
+       if (tinymce.isGecko)\r
+               doc.body.spellcheck = tinyMCEPopup.getParam("gecko_spellcheck");\r
+\r
+       resizeInputs();\r
+}\r
+\r
+function resizeInputs() {\r
+       if (!tinymce.isIE) {\r
+               wHeight = self.innerHeight - 80;\r
+               wWidth = self.innerWidth - 18;\r
+       } else {\r
+               wHeight = document.body.clientHeight - 80;\r
+               wWidth = document.body.clientWidth - 18;\r
+       }\r
+\r
+       var elm = document.getElementById('frmData');\r
+       if (elm) {\r
+               elm.style.height = Math.abs(wHeight) + 'px';\r
+               elm.style.width  = Math.abs(wWidth) + 'px';\r
+       }\r
+}\r
+\r
+tinyMCEPopup.onInit.add(onLoadInit);\r
diff --git a/jscripts/tiny_mce/plugins/paste/langs/en_dlg.js b/jscripts/tiny_mce/plugins/paste/langs/en_dlg.js
new file mode 100644 (file)
index 0000000..eeac778
--- /dev/null
@@ -0,0 +1,5 @@
+tinyMCE.addI18n('en.paste_dlg',{\r
+text_title:"Use CTRL+V on your keyboard to paste the text into the window.",\r
+text_linebreaks:"Keep linebreaks",\r
+word_title:"Use CTRL+V on your keyboard to paste the text into the window."\r
+});
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/paste/pastetext.htm b/jscripts/tiny_mce/plugins/paste/pastetext.htm
new file mode 100644 (file)
index 0000000..78cb0a1
--- /dev/null
@@ -0,0 +1,34 @@
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#paste.paste_text_desc}</title>\r
+       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="js/pastetext.js?v=307"></script>\r
+       <base target="_self" />\r
+</head>\r
+<body onresize="resizeInputs();" style="display:none; overflow:hidden;">\r
+<form name="source" onsubmit="saveContent();return false;" action="#">\r
+       <div style="float: left" class="title">{#paste.paste_text_desc}</div>\r
+\r
+       <div style="float: right">\r
+               <input type="checkbox" name="linebreaks" id="linebreaks" class="wordWrapCode" checked="checked" /><label for="linebreaks">{#paste_dlg.text_linebreaks}</label>\r
+       </div>\r
+\r
+       <br style="clear: both" />\r
+\r
+       <div>{#paste_dlg.text_title}</div>\r
+\r
+       <textarea name="htmlSource" id="htmlSource" rows="15" cols="100" style="width: 100%; height: 100%; font-family: 'Courier New',Courier,mono; font-size: 12px;" dir="ltr" wrap="soft" class="mceFocus"></textarea>\r
+\r
+       <div class="mceActionPanel">\r
+               <div style="float: left">\r
+                       <input type="submit" name="insert" value="{#insert}" id="insert" />\r
+               </div>\r
+\r
+               <div style="float: right">\r
+                       <input type="button" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" id="cancel" />\r
+               </div>\r
+       </div>\r
+</form>\r
+</body> \r
+</html>
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/paste/pasteword.htm b/jscripts/tiny_mce/plugins/paste/pasteword.htm
new file mode 100644 (file)
index 0000000..365f25d
--- /dev/null
@@ -0,0 +1,29 @@
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />\r
+       <title>{#paste.paste_word_desc}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="js/pasteword.js?v=307"></script>\r
+       <link href="css/pasteword.css?v=307" rel="stylesheet" type="text/css" />\r
+       <base target="_self" />\r
+</head>\r
+<body onresize="resizeInputs();" style="display:none; overflow:hidden;">\r
+       <form name="source" onsubmit="saveContent();" action="#">\r
+               <div class="title">{#paste.paste_word_desc}</div>\r
+\r
+               <div>{#paste_dlg.word_title}</div>\r
+\r
+               <div id="iframecontainer"></div>\r
+\r
+               <div class="mceActionPanel">\r
+                       <div style="float: left">\r
+                               <input type="button" id="insert" name="insert" value="{#insert}" onclick="saveContent();" />\r
+                       </div>\r
+\r
+                       <div style="float: right">\r
+                               <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+                       </div>\r
+               </div>\r
+       </form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/preview/editor_plugin.js b/jscripts/tiny_mce/plugins/preview/editor_plugin.js
new file mode 100644 (file)
index 0000000..766ebf8
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.Preview',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mcePreview',t._preview,t);ed.addButton('preview',{title:'preview.preview_desc',cmd:'mcePreview'});},getInfo:function(){return{longname:'Preview',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/preview',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_preview:function(){var ed=this.editor,win,html,c,pos,pos2,css,i,page=ed.getParam("plugin_preview_pageurl",null),w=ed.getParam("plugin_preview_width","550"),h=ed.getParam("plugin_preview_height","600");if(page){ed.windowManager.open({file:ed.getParam("plugin_preview_pageurl",null),width:w,height:h},{resizable:"yes",scrollbars:"yes",inline:1});}else{win=window.open("","mcePreview","menubar=no,toolbar=no,scrollbars=yes,resizable=yes,left=20,top=20,width="+w+",height="+h);html="";c=ed.getContent();pos=c.indexOf('<body');css=ed.getParam("content_css",'').split(',');tinymce.map(css,function(u){return ed.documentBaseURI.toAbsolute(u);});if(pos!=-1){pos=c.indexOf('>',pos);pos2=c.lastIndexOf('</body>');c=c.substring(pos+1,pos2);}html+=ed.getParam('doctype');html+='<html xmlns="http://www.w3.org/1999/xhtml">';html+='<head>';html+='<title>'+ed.getLang('preview.preview_desc')+'</title>';html+='<base href="'+ed.documentBaseURI.getURI()+'" />';html+='<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';for(i=0;i<css.length;i++)html+='<link href="'+css[i]+'" rel="stylesheet" type="text/css" />';html+='</head>';html+='<body dir="'+ed.getParam("directionality")+'" onload="window.opener.tinymce.EditorManager.get(\''+ed.id+'\').plugins[\'preview\']._onLoad(window,document);">';html+=c;html+='</body>';html+='</html>';win.document.write(html);win.document.close();}},_onLoad:function(w,d){var t=this,nl,i,el=[],sv,ne;t._doc=d;w.writeFlash=t._writeFlash;w.writeShockWave=t._writeShockWave;w.writeQuickTime=t._writeQuickTime;w.writeRealMedia=t._writeRealMedia;w.writeWindowsMedia=t._writeWindowsMedia;w.writeEmbed=t._writeEmbed;nl=d.getElementsByTagName("script");for(i=0;i<nl.length;i++){sv=tinymce.isIE?nl[i].innerHTML:nl[i].firstChild.nodeValue;if(new RegExp('write(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)\\(.*','g').test(sv))el[el.length]=nl[i];}for(i=0;i<el.length;i++){ne=d.createElement("div");ne.innerHTML=d._embeds[i];el[i].parentNode.insertBefore(ne.firstChild,el[i]);}},_writeFlash:function(p){p.src=this.editor.documentBaseURI.toAbsolute(p.src);TinyMCE_PreviewPlugin._writeEmbed('D27CDB6E-AE6D-11cf-96B8-444553540000','http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0','application/x-shockwave-flash',p);},_writeShockWave:function(p){this.editor.documentBaseURI.toAbsolute(p.src);TinyMCE_PreviewPlugin._writeEmbed('166B1BCA-3F9C-11CF-8075-444553540000','http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0','application/x-director',p);},_writeQuickTime:function(p){this.editor.documentBaseURI.toAbsolute(p.src);TinyMCE_PreviewPlugin._writeEmbed('02BF25D5-8C17-4B23-BC80-D3488ABDDC6B','http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0','video/quicktime',p);},_writeRealMedia:function(p){this.editor.documentBaseURI.toAbsolute(p.src);TinyMCE_PreviewPlugin._writeEmbed('CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA','http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0','audio/x-pn-realaudio-plugin',p);},_writeWindowsMedia:function(p){this.editor.documentBaseURI.toAbsolute(p.src);p.url=p.src;TinyMCE_PreviewPlugin._writeEmbed('6BF52A52-394A-11D3-B153-00C04F79FAA6','http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701','application/x-mplayer2',p);},_writeEmbed:function(cls,cb,mt,p){var h='',n,d=t._doc,ne,c;h+='<object classid="clsid:'+cls+'" codebase="'+cb+'"';h+=typeof(p.id)!="undefined"?'id="'+p.id+'"':'';h+=typeof(p.name)!="undefined"?'name="'+p.name+'"':'';h+=typeof(p.width)!="undefined"?'width="'+p.width+'"':'';h+=typeof(p.height)!="undefined"?'height="'+p.height+'"':'';h+=typeof(p.align)!="undefined"?'align="'+p.align+'"':'';h+='>';for(n in p)h+='<param name="'+n+'" value="'+p[n]+'">';h+='<embed type="'+mt+'"';for(n in p)h+=n+'="'+p[n]+'" ';h+='></embed></object>';d._embeds[d._embeds.length]=h;}});tinymce.PluginManager.add('preview',tinymce.plugins.Preview);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/preview/editor_plugin_src.js b/jscripts/tiny_mce/plugins/preview/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..881acdb
--- /dev/null
@@ -0,0 +1,187 @@
+/**
+ * $Id: editor_plugin_src.js 537 2008-01-14 16:38:33Z spocke $
+ *
+ * @author Moxiecode
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
+ */
+
+(function() {
+       tinymce.create('tinymce.plugins.Preview', {
+               init : function(ed, url) {
+                       var t = this;
+
+                       t.editor = ed;
+
+                       ed.addCommand('mcePreview', t._preview, t);
+                       ed.addButton('preview', {title : 'preview.preview_desc', cmd : 'mcePreview'});
+               },
+
+               getInfo : function() {
+                       return {
+                               longname : 'Preview',
+                               author : 'Moxiecode Systems AB',
+                               authorurl : 'http://tinymce.moxiecode.com',
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/preview',
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion
+                       };
+               },
+
+               // Private methods
+
+               _preview : function() {
+                       var ed = this.editor, win, html, c, pos, pos2, css, i, page = ed.getParam("plugin_preview_pageurl", null), w = ed.getParam("plugin_preview_width", "550"), h = ed.getParam("plugin_preview_height", "600");
+
+                       // Use a custom preview page
+                       if (page) {
+                               ed.windowManager.open({
+                                       file : ed.getParam("plugin_preview_pageurl", null),
+                                       width : w,
+                                       height : h
+                               }, {
+                                       resizable : "yes",
+                                       scrollbars : "yes",
+                                       inline : 1
+                               });
+                       } else {
+                               win = window.open("", "mcePreview", "menubar=no,toolbar=no,scrollbars=yes,resizable=yes,left=20,top=20,width=" + w + ",height="  + h);
+                               html = "";
+                               c = ed.getContent();
+                               pos = c.indexOf('<body');
+                               css = ed.getParam("content_css", '').split(',');
+
+                               tinymce.map(css, function(u) {
+                                       return ed.documentBaseURI.toAbsolute(u);
+                               });
+
+                               if (pos != -1) {
+                                       pos = c.indexOf('>', pos);
+                                       pos2 = c.lastIndexOf('</body>');
+                                       c = c.substring(pos + 1, pos2);
+                               }
+
+                               html += ed.getParam('doctype');
+                               html += '<html xmlns="http://www.w3.org/1999/xhtml">';
+                               html += '<head>';
+                               html += '<title>' + ed.getLang('preview.preview_desc') + '</title>';
+                               html += '<base href="' + ed.documentBaseURI.getURI() + '" />';
+                               html += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
+
+                               for (i=0; i<css.length; i++)
+                                       html += '<link href="' + css[i] + '" rel="stylesheet" type="text/css" />';
+
+                               html += '</head>';
+                               html += '<body dir="' + ed.getParam("directionality") + '" onload="window.opener.tinymce.EditorManager.get(\'' + ed.id + '\').plugins[\'preview\']._onLoad(window,document);">';
+                               html += c;
+                               html += '</body>';
+                               html += '</html>';
+
+                               win.document.write(html);
+                               win.document.close();
+                       }
+               },
+
+               _onLoad : function(w, d) {
+                       var t = this, nl, i, el = [], sv, ne;
+
+                       t._doc = d;
+                       w.writeFlash = t._writeFlash;
+                       w.writeShockWave = t._writeShockWave;
+                       w.writeQuickTime = t._writeQuickTime;
+                       w.writeRealMedia = t._writeRealMedia;
+                       w.writeWindowsMedia = t._writeWindowsMedia;
+                       w.writeEmbed = t._writeEmbed;
+
+                       nl = d.getElementsByTagName("script");
+                       for (i=0; i<nl.length; i++) {
+                               sv = tinymce.isIE ? nl[i].innerHTML : nl[i].firstChild.nodeValue;
+
+                               if (new RegExp('write(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)\\(.*', 'g').test(sv))
+                                       el[el.length] = nl[i];
+                       }
+
+                       for (i=0; i<el.length; i++) {
+                               ne = d.createElement("div");
+                               ne.innerHTML = d._embeds[i];
+                               el[i].parentNode.insertBefore(ne.firstChild, el[i]);
+                       }
+               },
+
+               _writeFlash : function(p) {
+                       p.src = this.editor.documentBaseURI.toAbsolute(p.src);
+                       TinyMCE_PreviewPlugin._writeEmbed(
+                               'D27CDB6E-AE6D-11cf-96B8-444553540000',
+                               'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0',
+                               'application/x-shockwave-flash',
+                               p
+                       );
+               },
+
+               _writeShockWave : function(p) {
+                       this.editor.documentBaseURI.toAbsolute(p.src);
+                       TinyMCE_PreviewPlugin._writeEmbed(
+                               '166B1BCA-3F9C-11CF-8075-444553540000',
+                               'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0',
+                               'application/x-director',
+                               p
+                       );
+               },
+
+               _writeQuickTime : function(p) {
+                       this.editor.documentBaseURI.toAbsolute(p.src);
+                       TinyMCE_PreviewPlugin._writeEmbed(
+                               '02BF25D5-8C17-4B23-BC80-D3488ABDDC6B',
+                               'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0',
+                               'video/quicktime',
+                               p
+                       );
+               },
+
+               _writeRealMedia : function(p) {
+                       this.editor.documentBaseURI.toAbsolute(p.src);
+                       TinyMCE_PreviewPlugin._writeEmbed(
+                               'CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA',
+                               'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0',
+                               'audio/x-pn-realaudio-plugin',
+                               p
+                       );
+               },
+
+               _writeWindowsMedia : function(p) {
+                       this.editor.documentBaseURI.toAbsolute(p.src);
+                       p.url = p.src;
+                       TinyMCE_PreviewPlugin._writeEmbed(
+                               '6BF52A52-394A-11D3-B153-00C04F79FAA6',
+                               'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701',
+                               'application/x-mplayer2',
+                               p
+                       );
+               },
+
+               _writeEmbed : function(cls, cb, mt, p) {
+                       var h = '', n, d = t._doc, ne, c;
+
+                       h += '<object classid="clsid:' + cls + '" codebase="' + cb + '"';
+                       h += typeof(p.id) != "undefined" ? 'id="' + p.id + '"' : '';
+                       h += typeof(p.name) != "undefined" ? 'name="' + p.name + '"' : '';
+                       h += typeof(p.width) != "undefined" ? 'width="' + p.width + '"' : '';
+                       h += typeof(p.height) != "undefined" ? 'height="' + p.height + '"' : '';
+                       h += typeof(p.align) != "undefined" ? 'align="' + p.align + '"' : '';
+                       h += '>';
+
+                       for (n in p)
+                               h += '<param name="' + n + '" value="' + p[n] + '">';
+
+                       h += '<embed type="' + mt + '"';
+
+                       for (n in p)
+                               h += n + '="' + p[n] + '" ';
+
+                       h += '></embed></object>';
+
+                       d._embeds[d._embeds.length] = h;
+               }
+       });
+
+       // Register plugin
+       tinymce.PluginManager.add('preview', tinymce.plugins.Preview);
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/preview/example.html b/jscripts/tiny_mce/plugins/preview/example.html
new file mode 100644 (file)
index 0000000..b2c3d90
--- /dev/null
@@ -0,0 +1,28 @@
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<script language="javascript" src="../../tiny_mce_popup.js"></script>\r
+<script type="text/javascript" src="jscripts/embed.js"></script>\r
+<script type="text/javascript">\r
+tinyMCEPopup.onInit.add(function(ed) {\r
+       var dom = tinyMCEPopup.dom;\r
+\r
+       // Load editor content_css\r
+       tinymce.each(ed.settings.content_css.split(','), function(u) {\r
+               dom.loadCSS(ed.documentBaseURI.toAbsolute(u));\r
+       });\r
+\r
+       // Place contents inside div container\r
+       dom.setHTML('content', ed.getContent());\r
+});\r
+</script>\r
+<title>Example of a custom preview page</title>\r
+</head>\r
+<body>\r
+\r
+Editor contents: <br />\r
+<div id="content">\r
+<!-- Gets filled with editor contents -->\r
+</div>\r
+\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/preview/jscripts/embed.js b/jscripts/tiny_mce/plugins/preview/jscripts/embed.js
new file mode 100644 (file)
index 0000000..f8dc810
--- /dev/null
@@ -0,0 +1,73 @@
+/**\r
+ * This script contains embed functions for common plugins. This scripts are complety free to use for any purpose.\r
+ */\r
+\r
+function writeFlash(p) {\r
+       writeEmbed(\r
+               'D27CDB6E-AE6D-11cf-96B8-444553540000',\r
+               'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0',\r
+               'application/x-shockwave-flash',\r
+               p\r
+       );\r
+}\r
+\r
+function writeShockWave(p) {\r
+       writeEmbed(\r
+       '166B1BCA-3F9C-11CF-8075-444553540000',\r
+       'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0',\r
+       'application/x-director',\r
+               p\r
+       );\r
+}\r
+\r
+function writeQuickTime(p) {\r
+       writeEmbed(\r
+               '02BF25D5-8C17-4B23-BC80-D3488ABDDC6B',\r
+               'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0',\r
+               'video/quicktime',\r
+               p\r
+       );\r
+}\r
+\r
+function writeRealMedia(p) {\r
+       writeEmbed(\r
+               'CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA',\r
+               'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0',\r
+               'audio/x-pn-realaudio-plugin',\r
+               p\r
+       );\r
+}\r
+\r
+function writeWindowsMedia(p) {\r
+       p.url = p.src;\r
+       writeEmbed(\r
+               '6BF52A52-394A-11D3-B153-00C04F79FAA6',\r
+               'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701',\r
+               'application/x-mplayer2',\r
+               p\r
+       );\r
+}\r
+\r
+function writeEmbed(cls, cb, mt, p) {\r
+       var h = '', n;\r
+\r
+       h += '<object classid="clsid:' + cls + '" codebase="' + cb + '"';\r
+       h += typeof(p.id) != "undefined" ? 'id="' + p.id + '"' : '';\r
+       h += typeof(p.name) != "undefined" ? 'name="' + p.name + '"' : '';\r
+       h += typeof(p.width) != "undefined" ? 'width="' + p.width + '"' : '';\r
+       h += typeof(p.height) != "undefined" ? 'height="' + p.height + '"' : '';\r
+       h += typeof(p.align) != "undefined" ? 'align="' + p.align + '"' : '';\r
+       h += '>';\r
+\r
+       for (n in p)\r
+               h += '<param name="' + n + '" value="' + p[n] + '">';\r
+\r
+       h += '<embed type="' + mt + '"';\r
+\r
+       for (n in p)\r
+               h += n + '="' + p[n] + '" ';\r
+\r
+       h += '></embed></object>';\r
+\r
+       document.write(h);\r
+}\r
diff --git a/jscripts/tiny_mce/plugins/print/editor_plugin.js b/jscripts/tiny_mce/plugins/print/editor_plugin.js
new file mode 100644 (file)
index 0000000..7d09a87
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.Print',{init:function(ed,url){ed.addCommand('mcePrint',function(){ed.getWin().print();});ed.addButton('print',{title:'print.print_desc',cmd:'mcePrint'});},getInfo:function(){return{longname:'Print',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/print',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('print',tinymce.plugins.Print);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/print/editor_plugin_src.js b/jscripts/tiny_mce/plugins/print/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..51fe156
--- /dev/null
@@ -0,0 +1,31 @@
+/**\r
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.Print', {\r
+               init : function(ed, url) {\r
+                       ed.addCommand('mcePrint', function() {\r
+                               ed.getWin().print();\r
+                       });\r
+\r
+                       ed.addButton('print', {title : 'print.print_desc', cmd : 'mcePrint'});\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Print',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/print',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('print', tinymce.plugins.Print);\r
+})();\r
diff --git a/jscripts/tiny_mce/plugins/safari/blank.htm b/jscripts/tiny_mce/plugins/safari/blank.htm
new file mode 100644 (file)
index 0000000..266808c
--- /dev/null
@@ -0,0 +1 @@
+<!-- WebKit -->
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/safari/editor_plugin.js b/jscripts/tiny_mce/plugins/safari/editor_plugin.js
new file mode 100644 (file)
index 0000000..f722c2f
--- /dev/null
@@ -0,0 +1 @@
+(function(){var Event=tinymce.dom.Event,grep=tinymce.grep,each=tinymce.each,inArray=tinymce.inArray,isOldWebKit=tinymce.isOldWebKit;tinymce.create('tinymce.plugins.Safari',{init:function(ed){var t=this,dom;if(!tinymce.isWebKit)return;t.editor=ed;t.webKitFontSizes=['x-small','small','medium','large','x-large','xx-large','-webkit-xxx-large'];t.namedFontSizes=['xx-small','x-small','small','medium','large','x-large','xx-large'];ed.onPaste.add(function(ed,e){function removeStyles(e){e=e.target;if(e.nodeType==1){e.style.cssText='';each(ed.dom.select('*',e),function(e){e.style.cssText='';});}};Event.add(ed.getDoc(),'DOMNodeInserted',removeStyles);window.setTimeout(function(){Event.remove(ed.getDoc(),'DOMNodeInserted',removeStyles);},0);});ed.onKeyUp.add(function(ed,e){var h,b;if(e.keyCode==46||e.keyCode==8){b=ed.getBody();h=b.innerHTML;if(b.childNodes.length==1&&!/<(img|hr)/.test(h)&&tinymce.trim(h.replace(/<[^>]+>/g,'')).length==0)ed.setContent('',{format:'raw'});}});ed.addCommand('FormatBlock',function(u,v){var dom=ed.dom,e=dom.getParent(ed.selection.getNode(),dom.isBlock);if(e)dom.replace(dom.create(v),e,1);else ed.getDoc().execCommand("FormatBlock",false,v);});ed.addCommand('mceInsertContent',function(u,v){ed.getDoc().execCommand("InsertText",false,'mce_marker');ed.getBody().innerHTML=ed.getBody().innerHTML.replace(/mce_marker/g,v+'<span id="_mce_tmp">XX</span>');ed.selection.select(ed.dom.get('_mce_tmp'));ed.getDoc().execCommand("Delete",false,' ');});ed.onKeyPress.add(function(ed,e){if(e.keyCode==13&&(e.shiftKey||ed.settings.force_br_newlines&&ed.selection.getNode().nodeName!='LI')){t._insertBR(ed);Event.cancel(e);}});ed.addQueryValueHandler('FontSize',function(u,v){var e,v;if((e=ed.dom.getParent(ed.selection.getStart(),'span'))&&(v=e.style.fontSize))return tinymce.inArray(t.namedFontSizes,v)+1;if((e=ed.dom.getParent(ed.selection.getEnd(),'span'))&&(v=e.style.fontSize))return tinymce.inArray(t.namedFontSizes,v)+1;return ed.getDoc().queryCommandValue('FontSize');});ed.addQueryValueHandler('FontName',function(u,v){var e,v;if((e=ed.dom.getParent(ed.selection.getStart(),'span'))&&(v=e.style.fontFamily))return v.replace(/, /g,',');if((e=ed.dom.getParent(ed.selection.getEnd(),'span'))&&(v=e.style.fontFamily))return v.replace(/, /g,',');return ed.getDoc().queryCommandValue('FontName');});ed.onClick.add(function(ed,e){e=e.target;if(e.nodeName=='IMG'){t.selElm=e;ed.selection.select(e);}else t.selElm=null;});ed.onInit.add(function(){t._fixWebKitSpans();if(isOldWebKit)t._patchSafari2x(ed);});ed.onSetContent.add(function(){dom=ed.dom;each(['strong','b','em','u','strike','sub','sup','a'],function(v){each(grep(dom.select(v)).reverse(),function(n){var nn=n.nodeName.toLowerCase(),st;if(nn=='a'){if(n.name)dom.replace(dom.create('img',{mce_name:'a',name:n.name,'class':'mceItemAnchor'}),n);return;}switch(nn){case'b':case'strong':if(nn=='b')nn='strong';st='font-weight: bold;';break;case'em':st='font-style: italic;';break;case'u':st='text-decoration: underline;';break;case'sub':st='vertical-align: sub;';break;case'sup':st='vertical-align: super;';break;case'strike':st='text-decoration: line-through;';break;}dom.replace(dom.create('span',{mce_name:nn,style:st,'class':'Apple-style-span'}),n,1);});});});ed.onPreProcess.add(function(ed,o){dom=ed.dom;each(grep(o.node.getElementsByTagName('span')).reverse(),function(n){var v,bg;if(o.get){if(dom.hasClass(n,'Apple-style-span')){bg=n.style.backgroundColor;switch(dom.getAttrib(n,'mce_name')){case'font':if(!ed.settings.convert_fonts_to_spans)dom.setAttrib(n,'style','');break;case'strong':case'em':case'sub':case'sup':dom.setAttrib(n,'style','');break;case'strike':case'u':if(!ed.settings.inline_styles)dom.setAttrib(n,'style','');else dom.setAttrib(n,'mce_name','');break;default:if(!ed.settings.inline_styles)dom.setAttrib(n,'style','');}if(bg)n.style.backgroundColor=bg;}}if(dom.hasClass(n,'mceItemRemoved'))dom.remove(n,1);});});ed.onPostProcess.add(function(ed,o){o.content=o.content.replace(/<br \/><\/(h[1-6]|div|p|address|pre)>/g,'</$1>');o.content=o.content.replace(/ id=\"undefined\"/g,'');});},getInfo:function(){return{longname:'Safari compatibility',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/safari',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_fixWebKitSpans:function(){var t=this,ed=t.editor;if(!isOldWebKit){Event.add(ed.getDoc(),'DOMNodeInserted',function(e){e=e.target;if(e&&e.nodeType==1)t._fixAppleSpan(e);});}else{ed.onExecCommand.add(function(){each(ed.dom.select('span'),function(n){t._fixAppleSpan(n);});ed.nodeChanged();});}},_fixAppleSpan:function(e){var ed=this.editor,dom=ed.dom,fz=this.webKitFontSizes,fzn=this.namedFontSizes,s=ed.settings,st,p;if(dom.getAttrib(e,'mce_fixed'))return;if(e.nodeName=='SPAN'&&e.className=='Apple-style-span'){st=e.style;if(!s.convert_fonts_to_spans){if(st.fontSize){dom.setAttrib(e,'mce_name','font');dom.setAttrib(e,'size',inArray(fz,st.fontSize)+1);}if(st.fontFamily){dom.setAttrib(e,'mce_name','font');dom.setAttrib(e,'face',st.fontFamily);}if(st.color){dom.setAttrib(e,'mce_name','font');dom.setAttrib(e,'color',dom.toHex(st.color));}if(st.backgroundColor){dom.setAttrib(e,'mce_name','font');dom.setStyle(e,'background-color',st.backgroundColor);}}else{if(st.fontSize)dom.setStyle(e,'fontSize',fzn[inArray(fz,st.fontSize)]);}if(st.fontWeight=='bold')dom.setAttrib(e,'mce_name','strong');if(st.fontStyle=='italic')dom.setAttrib(e,'mce_name','em');if(st.textDecoration=='underline')dom.setAttrib(e,'mce_name','u');if(st.textDecoration=='line-through')dom.setAttrib(e,'mce_name','strike');if(st.verticalAlign=='super')dom.setAttrib(e,'mce_name','sup');if(st.verticalAlign=='sub')dom.setAttrib(e,'mce_name','sub');dom.setAttrib(e,'mce_fixed','1');}},_patchSafari2x:function(ed){var t=this,setContent,getNode,dom=ed.dom,lr;if(ed.windowManager.onBeforeOpen){ed.windowManager.onBeforeOpen.add(function(){r=ed.selection.getRng();});}ed.selection.select=function(n){this.getSel().setBaseAndExtent(n,0,n,1);};getNode=ed.selection.getNode;ed.selection.getNode=function(){return t.selElm||getNode.call(this);};ed.selection.getRng=function(){var t=this,s=t.getSel(),d=ed.getDoc(),r,rb,ra,di;if(s.anchorNode){r=d.createRange();try{rb=d.createRange();rb.setStart(s.anchorNode,s.anchorOffset);rb.collapse(1);ra=d.createRange();ra.setStart(s.focusNode,s.focusOffset);ra.collapse(1);di=rb.compareBoundaryPoints(rb.START_TO_END,ra)<0;r.setStart(di?s.anchorNode:s.focusNode,di?s.anchorOffset:s.focusOffset);r.setEnd(di?s.focusNode:s.anchorNode,di?s.focusOffset:s.anchorOffset);lr=r;}catch(ex){}}return r||lr;};setContent=ed.selection.setContent;ed.selection.setContent=function(h,s){var r=this.getRng(),b;try{setContent.call(this,h,s);}catch(ex){b=dom.create('body');b.innerHTML=h;each(b.childNodes,function(n){r.insertNode(n.cloneNode(true));});}};},_insertBR:function(ed){var dom=ed.dom,s=ed.selection,r=s.getRng(),br;r.insertNode(br=dom.create('br'));r.setStartAfter(br);r.setEndAfter(br);s.setRng(r);if(s.getSel().focusNode==br.previousSibling){s.select(dom.insertAfter(dom.doc.createTextNode('\u00a0'),br));s.collapse(1);}ed.getWin().scrollTo(0,dom.getPos(s.getRng().startContainer).y);}});tinymce.PluginManager.add('safari',tinymce.plugins.Safari);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/safari/editor_plugin_src.js b/jscripts/tiny_mce/plugins/safari/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..c820353
--- /dev/null
@@ -0,0 +1,460 @@
+/**\r
+ * $Id: editor_plugin_src.js 264 2007-04-26 20:53:09Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       var Event = tinymce.dom.Event, grep = tinymce.grep, each = tinymce.each, inArray = tinymce.inArray, isOldWebKit = tinymce.isOldWebKit;\r
+\r
+       tinymce.create('tinymce.plugins.Safari', {\r
+               init : function(ed) {\r
+                       var t = this, dom;\r
+\r
+                       // Ignore on non webkit\r
+                       if (!tinymce.isWebKit)\r
+                               return;\r
+\r
+                       t.editor = ed;\r
+                       t.webKitFontSizes = ['x-small', 'small', 'medium', 'large', 'x-large', 'xx-large', '-webkit-xxx-large'];\r
+                       t.namedFontSizes = ['xx-small', 'x-small','small','medium','large','x-large', 'xx-large'];\r
+\r
+                       // Safari will crash if the build in createlink command is used\r
+/*                     ed.addCommand('CreateLink', function(u, v) {\r
+                               ed.execCommand("mceInsertContent", false, '<a href="' + dom.encode(v) + '">' + ed.selection.getContent() + '</a>');\r
+                       });*/\r
+\r
+                       ed.onPaste.add(function(ed, e) {\r
+                               function removeStyles(e) {\r
+                                       e = e.target;\r
+\r
+                                       if (e.nodeType == 1) {\r
+                                               e.style.cssText = '';\r
+\r
+                                               each(ed.dom.select('*', e), function(e) {\r
+                                                       e.style.cssText = '';\r
+                                               });\r
+                                       }\r
+                               };\r
+\r
+                               Event.add(ed.getDoc(), 'DOMNodeInserted', removeStyles);\r
+\r
+                               window.setTimeout(function() {\r
+                                       Event.remove(ed.getDoc(), 'DOMNodeInserted', removeStyles);\r
+                               }, 0);\r
+                       });\r
+\r
+                       ed.onKeyUp.add(function(ed, e) {\r
+                               var h, b;\r
+\r
+                               // If backspace or delete key\r
+                               if (e.keyCode == 46 || e.keyCode == 8) {\r
+                                       b = ed.getBody();\r
+                                       h = b.innerHTML;\r
+\r
+                                       // If there is no text content or images or hr elements then remove everything\r
+                                       if (b.childNodes.length == 1 && !/<(img|hr)/.test(h) && tinymce.trim(h.replace(/<[^>]+>/g, '')).length == 0)\r
+                                               ed.setContent('', {format : 'raw'});\r
+                               }\r
+                       });\r
+\r
+                       // Workaround for FormatBlock bug, http://bugs.webkit.org/show_bug.cgi?id=16004\r
+                       ed.addCommand('FormatBlock', function(u, v) {\r
+                               var dom = ed.dom, e = dom.getParent(ed.selection.getNode(), dom.isBlock);\r
+\r
+                               if (e)\r
+                                       dom.replace(dom.create(v), e, 1);\r
+                               else\r
+                                       ed.getDoc().execCommand("FormatBlock", false, v);\r
+                       });\r
+\r
+                       // Workaround for InsertHTML bug, http://bugs.webkit.org/show_bug.cgi?id=16382\r
+                       ed.addCommand('mceInsertContent', function(u, v) {\r
+                               ed.getDoc().execCommand("InsertText", false, 'mce_marker');\r
+                               ed.getBody().innerHTML = ed.getBody().innerHTML.replace(/mce_marker/g, v + '<span id="_mce_tmp">XX</span>');\r
+                               ed.selection.select(ed.dom.get('_mce_tmp'));\r
+                               ed.getDoc().execCommand("Delete", false, ' ');\r
+                       });\r
+\r
+                       // Workaround for missing shift+enter support, http://bugs.webkit.org/show_bug.cgi?id=16973\r
+                       ed.onKeyPress.add(function(ed, e) {\r
+                               if (e.keyCode == 13 && (e.shiftKey || ed.settings.force_br_newlines && ed.selection.getNode().nodeName != 'LI')) {\r
+                                       t._insertBR(ed);\r
+                                       Event.cancel(e);\r
+                               }\r
+                       });\r
+\r
+                       // Safari returns incorrect values\r
+                       ed.addQueryValueHandler('FontSize', function(u, v) {\r
+                               var e, v;\r
+\r
+                               // Check for the real font size at the start of selection\r
+                               if ((e = ed.dom.getParent(ed.selection.getStart(), 'span')) && (v = e.style.fontSize))\r
+                                       return tinymce.inArray(t.namedFontSizes, v) + 1;\r
+\r
+                               // Check for the real font size at the end of selection\r
+                               if ((e = ed.dom.getParent(ed.selection.getEnd(), 'span')) && (v = e.style.fontSize))\r
+                                       return tinymce.inArray(t.namedFontSizes, v) + 1;\r
+\r
+                               // Return default value it's better than nothing right!\r
+                               return ed.getDoc().queryCommandValue('FontSize');\r
+                       });\r
+\r
+                       // Safari returns incorrect values\r
+                       ed.addQueryValueHandler('FontName', function(u, v) {\r
+                               var e, v;\r
+\r
+                               // Check for the real font name at the start of selection\r
+                               if ((e = ed.dom.getParent(ed.selection.getStart(), 'span')) && (v = e.style.fontFamily))\r
+                                       return v.replace(/, /g, ',');\r
+\r
+                               // Check for the real font name at the end of selection\r
+                               if ((e = ed.dom.getParent(ed.selection.getEnd(), 'span')) && (v = e.style.fontFamily))\r
+                                       return v.replace(/, /g, ',');\r
+\r
+                               // Return default value it's better than nothing right!\r
+                               return ed.getDoc().queryCommandValue('FontName');\r
+                       });\r
+\r
+                       // Workaround for bug, http://bugs.webkit.org/show_bug.cgi?id=12250\r
+                       ed.onClick.add(function(ed, e) {\r
+                               e = e.target;\r
+\r
+                               if (e.nodeName == 'IMG') {\r
+                                       t.selElm = e;\r
+                                       ed.selection.select(e);\r
+                               } else\r
+                                       t.selElm = null;\r
+                       });\r
+\r
+/*                     ed.onBeforeExecCommand.add(function(ed, c, b) {\r
+                               var r = t.bookmarkRng;\r
+\r
+                               // Restore selection\r
+                               if (r) {\r
+                                       ed.selection.setRng(r);\r
+                                       t.bookmarkRng = null;\r
+                                       //console.debug('restore', r.startContainer, r.startOffset, r.endContainer, r.endOffset);\r
+                               }\r
+                       });*/\r
+\r
+                       ed.onInit.add(function() {\r
+                               t._fixWebKitSpans();\r
+\r
+/*                             ed.windowManager.onOpen.add(function() {\r
+                                       var r = ed.selection.getRng();\r
+\r
+                                       // Store selection if valid\r
+                                       if (r.startContainer != ed.getDoc()) {\r
+                                               t.bookmarkRng = r.cloneRange();\r
+                                               //console.debug('store', r.startContainer, r.startOffset, r.endContainer, r.endOffset);\r
+                                       }\r
+                               });\r
+\r
+                               ed.windowManager.onClose.add(function() {\r
+                                       t.bookmarkRng = null;\r
+                               });*/\r
+\r
+                               if (isOldWebKit)\r
+                                       t._patchSafari2x(ed);\r
+                       });\r
+\r
+                       ed.onSetContent.add(function() {\r
+                               dom = ed.dom;\r
+\r
+                               // Convert strong,b,em,u,strike to spans\r
+                               each(['strong','b','em','u','strike','sub','sup','a'], function(v) {\r
+                                       each(grep(dom.select(v)).reverse(), function(n) {\r
+                                               var nn = n.nodeName.toLowerCase(), st;\r
+\r
+                                               // Convert anchors into images\r
+                                               if (nn == 'a') {\r
+                                                       if (n.name)\r
+                                                               dom.replace(dom.create('img', {mce_name : 'a', name : n.name, 'class' : 'mceItemAnchor'}), n);\r
+\r
+                                                       return;\r
+                                               }\r
+\r
+                                               switch (nn) {\r
+                                                       case 'b':\r
+                                                       case 'strong':\r
+                                                               if (nn == 'b')\r
+                                                                       nn = 'strong';\r
+\r
+                                                               st = 'font-weight: bold;';\r
+                                                               break;\r
+\r
+                                                       case 'em':\r
+                                                               st = 'font-style: italic;';\r
+                                                               break;\r
+\r
+                                                       case 'u':\r
+                                                               st = 'text-decoration: underline;';\r
+                                                               break;\r
+\r
+                                                       case 'sub':\r
+                                                               st = 'vertical-align: sub;';\r
+                                                               break;\r
+\r
+                                                       case 'sup':\r
+                                                               st = 'vertical-align: super;';\r
+                                                               break;\r
+\r
+                                                       case 'strike':\r
+                                                               st = 'text-decoration: line-through;';\r
+                                                               break;\r
+                                               }\r
+\r
+                                               dom.replace(dom.create('span', {mce_name : nn, style : st, 'class' : 'Apple-style-span'}), n, 1);\r
+                                       });\r
+                               });\r
+                       });\r
+\r
+                       ed.onPreProcess.add(function(ed, o) {\r
+                               dom = ed.dom;\r
+\r
+                               each(grep(o.node.getElementsByTagName('span')).reverse(), function(n) {\r
+                                       var v, bg;\r
+\r
+                                       if (o.get) {\r
+                                               if (dom.hasClass(n, 'Apple-style-span')) {\r
+                                                       bg = n.style.backgroundColor;\r
+\r
+                                                       switch (dom.getAttrib(n, 'mce_name')) {\r
+                                                               case 'font':\r
+                                                                       if (!ed.settings.convert_fonts_to_spans)\r
+                                                                               dom.setAttrib(n, 'style', '');\r
+                                                                       break;\r
+\r
+                                                               case 'strong':\r
+                                                               case 'em':\r
+                                                               case 'sub':\r
+                                                               case 'sup':\r
+                                                                       dom.setAttrib(n, 'style', '');\r
+                                                                       break;\r
+\r
+                                                               case 'strike':\r
+                                                               case 'u':\r
+                                                                       if (!ed.settings.inline_styles)\r
+                                                                               dom.setAttrib(n, 'style', '');\r
+                                                                       else\r
+                                                                               dom.setAttrib(n, 'mce_name', '');\r
+\r
+                                                                       break;\r
+\r
+                                                               default:\r
+                                                                       if (!ed.settings.inline_styles)\r
+                                                                               dom.setAttrib(n, 'style', '');\r
+                                                       }\r
+\r
+\r
+                                                       if (bg)\r
+                                                               n.style.backgroundColor = bg;\r
+                                               }\r
+                                       }\r
+\r
+                                       if (dom.hasClass(n, 'mceItemRemoved'))\r
+                                               dom.remove(n, 1);\r
+                               });\r
+                       });\r
+\r
+                       ed.onPostProcess.add(function(ed, o) {\r
+                               // Safari adds BR at end of all block elements\r
+                               o.content = o.content.replace(/<br \/><\/(h[1-6]|div|p|address|pre)>/g, '</$1>');\r
+\r
+                               // Safari adds id="undefined" to HR elements\r
+                               o.content = o.content.replace(/ id=\"undefined\"/g, '');\r
+                       });\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Safari compatibility',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/safari',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               },\r
+\r
+               // Internal methods\r
+\r
+               _fixWebKitSpans : function() {\r
+                       var t = this, ed = t.editor;\r
+\r
+                       if (!isOldWebKit) {\r
+                               // Use mutator events on new WebKit\r
+                               Event.add(ed.getDoc(), 'DOMNodeInserted', function(e) {\r
+                                       e = e.target;\r
+\r
+                                       if (e && e.nodeType == 1)\r
+                                               t._fixAppleSpan(e);\r
+                               });\r
+                       } else {\r
+                               // Do post command processing in old WebKit since the browser crashes on Mutator events :(\r
+                               ed.onExecCommand.add(function() {\r
+                                       each(ed.dom.select('span'), function(n) {\r
+                                               t._fixAppleSpan(n);\r
+                                       });\r
+\r
+                                       ed.nodeChanged();\r
+                               });\r
+                       }\r
+               },\r
+\r
+               _fixAppleSpan : function(e) {\r
+                       var ed = this.editor, dom = ed.dom, fz = this.webKitFontSizes, fzn = this.namedFontSizes, s = ed.settings, st, p;\r
+\r
+                       if (dom.getAttrib(e, 'mce_fixed'))\r
+                               return;\r
+\r
+                       // Handle Apple style spans\r
+                       if (e.nodeName == 'SPAN' && e.className == 'Apple-style-span') {\r
+                               st = e.style;\r
+\r
+                               if (!s.convert_fonts_to_spans) {\r
+                                       if (st.fontSize) {\r
+                                               dom.setAttrib(e, 'mce_name', 'font');\r
+                                               dom.setAttrib(e, 'size', inArray(fz, st.fontSize) + 1);\r
+                                       }\r
+\r
+                                       if (st.fontFamily) {\r
+                                               dom.setAttrib(e, 'mce_name', 'font');\r
+                                               dom.setAttrib(e, 'face', st.fontFamily);\r
+                                       }\r
+\r
+                                       if (st.color) {\r
+                                               dom.setAttrib(e, 'mce_name', 'font');\r
+                                               dom.setAttrib(e, 'color', dom.toHex(st.color));\r
+                                       }\r
+\r
+                                       if (st.backgroundColor) {\r
+                                               dom.setAttrib(e, 'mce_name', 'font');\r
+                                               dom.setStyle(e, 'background-color', st.backgroundColor);\r
+                                       }\r
+                               } else {\r
+                                       if (st.fontSize)\r
+                                               dom.setStyle(e, 'fontSize', fzn[inArray(fz, st.fontSize)]);\r
+                               }\r
+\r
+                               if (st.fontWeight == 'bold')\r
+                                       dom.setAttrib(e, 'mce_name', 'strong');\r
+\r
+                               if (st.fontStyle == 'italic')\r
+                                       dom.setAttrib(e, 'mce_name', 'em');\r
+\r
+                               if (st.textDecoration == 'underline')\r
+                                       dom.setAttrib(e, 'mce_name', 'u');\r
+\r
+                               if (st.textDecoration == 'line-through')\r
+                                       dom.setAttrib(e, 'mce_name', 'strike');\r
+\r
+                               if (st.verticalAlign == 'super')\r
+                                       dom.setAttrib(e, 'mce_name', 'sup');\r
+\r
+                               if (st.verticalAlign == 'sub')\r
+                                       dom.setAttrib(e, 'mce_name', 'sub');\r
+\r
+                               dom.setAttrib(e, 'mce_fixed', '1');\r
+                       }\r
+               },\r
+\r
+               _patchSafari2x : function(ed) {\r
+                       var t = this, setContent, getNode, dom = ed.dom, lr;\r
+\r
+                       // Inline dialogs\r
+                       if (ed.windowManager.onBeforeOpen) {\r
+                               ed.windowManager.onBeforeOpen.add(function() {\r
+                                       r = ed.selection.getRng();\r
+                               });\r
+                       }\r
+\r
+                       // Fake select on 2.x\r
+                       ed.selection.select = function(n) {\r
+                               this.getSel().setBaseAndExtent(n, 0, n, 1);\r
+                       };\r
+\r
+                       getNode = ed.selection.getNode;\r
+                       ed.selection.getNode = function() {\r
+                               return t.selElm || getNode.call(this);\r
+                       };\r
+\r
+                       // Fake range on Safari 2.x\r
+                       ed.selection.getRng = function() {\r
+                               var t = this, s = t.getSel(), d = ed.getDoc(), r, rb, ra, di;\r
+\r
+                               // Fake range on Safari 2.x\r
+                               if (s.anchorNode) {\r
+                                       r = d.createRange();\r
+\r
+                                       try {\r
+                                               // Setup before range\r
+                                               rb = d.createRange();\r
+                                               rb.setStart(s.anchorNode, s.anchorOffset);\r
+                                               rb.collapse(1);\r
+\r
+                                               // Setup after range\r
+                                               ra = d.createRange();\r
+                                               ra.setStart(s.focusNode, s.focusOffset);\r
+                                               ra.collapse(1);\r
+\r
+                                               // Setup start/end points by comparing locations\r
+                                               di = rb.compareBoundaryPoints(rb.START_TO_END, ra) < 0;\r
+                                               r.setStart(di ? s.anchorNode : s.focusNode, di ? s.anchorOffset : s.focusOffset);\r
+                                               r.setEnd(di ? s.focusNode : s.anchorNode, di ? s.focusOffset : s.anchorOffset);\r
+\r
+                                               lr = r;\r
+                                       } catch (ex) {\r
+                                               // Sometimes fails, at least we tried to do it by the book. I hope Safari 2.x will go disappear soooon!!!\r
+                                       }\r
+                               }\r
+\r
+                               return r || lr;\r
+                       };\r
+\r
+                       // Fix setContent so it works\r
+                       setContent = ed.selection.setContent;\r
+                       ed.selection.setContent = function(h, s) {\r
+                               var r = this.getRng(), b;\r
+\r
+                               try {\r
+                                       setContent.call(this, h, s);\r
+                               } catch (ex) {\r
+                                       // Workaround for Safari 2.x\r
+                                       b = dom.create('body');\r
+                                       b.innerHTML = h;\r
+\r
+                                       each(b.childNodes, function(n) {\r
+                                               r.insertNode(n.cloneNode(true));\r
+                                       });\r
+                               }\r
+                       };\r
+               },\r
+\r
+               _insertBR : function(ed) {\r
+                       var dom = ed.dom, s = ed.selection, r = s.getRng(), br;\r
+\r
+                       // Insert BR element\r
+                       r.insertNode(br = dom.create('br'));\r
+\r
+                       // Place caret after BR\r
+                       r.setStartAfter(br);\r
+                       r.setEndAfter(br);\r
+                       s.setRng(r);\r
+\r
+                       // Could not place caret after BR then insert an nbsp entity and move the caret\r
+                       if (s.getSel().focusNode == br.previousSibling) {\r
+                               s.select(dom.insertAfter(dom.doc.createTextNode('\u00a0'), br));\r
+                               s.collapse(1);\r
+                       }\r
+\r
+                       // Scroll to new position, scrollIntoView can't be used due to bug: http://bugs.webkit.org/show_bug.cgi?id=16117\r
+                       ed.getWin().scrollTo(0, dom.getPos(s.getRng().startContainer).y);\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('safari', tinymce.plugins.Safari);\r
+})();\r
+\r
diff --git a/jscripts/tiny_mce/plugins/save/editor_plugin.js b/jscripts/tiny_mce/plugins/save/editor_plugin.js
new file mode 100644 (file)
index 0000000..43af51b
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.Save',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mceSave',t._save,t);ed.addCommand('mceCancel',t._cancel,t);ed.addButton('save',{title:'save.save_desc',cmd:'mceSave'});ed.addButton('cancel',{title:'save.cancel_desc',cmd:'mceCancel'});ed.onNodeChange.add(t._nodeChange,t);ed.addShortcut('ctrl+s',ed.getLang('save.save_desc'),'mceSave');},getInfo:function(){return{longname:'Save',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/save',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_nodeChange:function(ed,cm,n){var ed=this.editor;if(ed.getParam('save_enablewhendirty')){cm.setDisabled('save',!ed.isDirty());cm.setDisabled('cancel',!ed.isDirty());}},_save:function(){var ed=this.editor,formObj,os,i,elementId;formObj=tinymce.DOM.get(ed.id).form||tinymce.DOM.getParent(ed.id,'form');if(ed.getParam("save_enablewhendirty")&&!ed.isDirty())return true;tinyMCE.triggerSave();if(os=ed.getParam("save_onsavecallback")){if(ed.execCallback('save_onsavecallback',ed)){ed.startContent=tinymce.trim(ed.getContent({format:'raw'}));ed.nodeChanged();}return;}if(formObj){ed.isNotDirty=true;if(formObj.onsubmit==null||formObj.onsubmit()!=false)formObj.submit();ed.nodeChanged();}else ed.windowManager.alert("Error: No form element found.");return true;},_cancel:function(){var ed=this.editor,os,h=tinymce.trim(ed.startContent);if(os=ed.getParam("save_oncancelcallback")){ed.execCallback('save_oncancelcallback',ed);return;}ed.setContent(h);ed.undoManager.clear();ed.nodeChanged();}});tinymce.PluginManager.add('save',tinymce.plugins.Save);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/save/editor_plugin_src.js b/jscripts/tiny_mce/plugins/save/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..f95c65c
--- /dev/null
@@ -0,0 +1,100 @@
+/**\r
+ * $Id: editor_plugin_src.js 609 2008-02-18 16:19:27Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.Save', {\r
+               init : function(ed, url) {\r
+                       var t = this;\r
+\r
+                       t.editor = ed;\r
+\r
+                       // Register commands\r
+                       ed.addCommand('mceSave', t._save, t);\r
+                       ed.addCommand('mceCancel', t._cancel, t);\r
+\r
+                       // Register buttons\r
+                       ed.addButton('save', {title : 'save.save_desc', cmd : 'mceSave'});\r
+                       ed.addButton('cancel', {title : 'save.cancel_desc', cmd : 'mceCancel'});\r
+\r
+                       ed.onNodeChange.add(t._nodeChange, t);\r
+                       ed.addShortcut('ctrl+s', ed.getLang('save.save_desc'), 'mceSave');\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Save',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/save',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               },\r
+\r
+               // Private methods\r
+\r
+               _nodeChange : function(ed, cm, n) {\r
+                       var ed = this.editor;\r
+\r
+                       if (ed.getParam('save_enablewhendirty')) {\r
+                               cm.setDisabled('save', !ed.isDirty());\r
+                               cm.setDisabled('cancel', !ed.isDirty());\r
+                       }\r
+               },\r
+\r
+               // Private methods\r
+\r
+               _save : function() {\r
+                       var ed = this.editor, formObj, os, i, elementId;\r
+\r
+                       formObj = tinymce.DOM.get(ed.id).form || tinymce.DOM.getParent(ed.id, 'form');\r
+\r
+                       if (ed.getParam("save_enablewhendirty") && !ed.isDirty())\r
+                               return true;\r
+\r
+                       tinyMCE.triggerSave();\r
+\r
+                       // Use callback instead\r
+                       if (os = ed.getParam("save_onsavecallback")) {\r
+                               if (ed.execCallback('save_onsavecallback', ed)) {\r
+                                       ed.startContent = tinymce.trim(ed.getContent({format : 'raw'}));\r
+                                       ed.nodeChanged();\r
+                               }\r
+\r
+                               return;\r
+                       }\r
+\r
+                       if (formObj) {\r
+                               ed.isNotDirty = true;\r
+\r
+                               if (formObj.onsubmit == null || formObj.onsubmit() != false)\r
+                                       formObj.submit();\r
+\r
+                               ed.nodeChanged();\r
+                       } else\r
+                               ed.windowManager.alert("Error: No form element found.");\r
+\r
+                       return true;\r
+               },\r
+\r
+               _cancel : function() {\r
+                       var ed = this.editor, os, h = tinymce.trim(ed.startContent);\r
+\r
+                       // Use callback instead\r
+                       if (os = ed.getParam("save_oncancelcallback")) {\r
+                               ed.execCallback('save_oncancelcallback', ed);\r
+                               return;\r
+                       }\r
+\r
+                       ed.setContent(h);\r
+                       ed.undoManager.clear();\r
+                       ed.nodeChanged();\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('save', tinymce.plugins.Save);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/searchreplace/css/searchreplace.css b/jscripts/tiny_mce/plugins/searchreplace/css/searchreplace.css
new file mode 100644 (file)
index 0000000..ecdf58c
--- /dev/null
@@ -0,0 +1,6 @@
+.panel_wrapper {height:85px;}\r
+.panel_wrapper div.current {height:85px;}\r
+\r
+/* IE */\r
+* html .panel_wrapper {height:100px;}\r
+* html .panel_wrapper div.current {height:100px;}\r
diff --git a/jscripts/tiny_mce/plugins/searchreplace/editor_plugin.js b/jscripts/tiny_mce/plugins/searchreplace/editor_plugin.js
new file mode 100644 (file)
index 0000000..7fd913b
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.SearchReplacePlugin',{init:function(ed,url){function open(m){ed.windowManager.open({file:url+'/searchreplace.htm',width:420+parseInt(ed.getLang('searchreplace.delta_width',0)),height:160+parseInt(ed.getLang('searchreplace.delta_height',0)),inline:1,auto_focus:0},{mode:m,search_string:ed.selection.getContent({format:'text'}),plugin_url:url});};ed.addCommand('mceSearch',function(){open('search');});ed.addCommand('mceReplace',function(){open('replace');});ed.addButton('search',{title:'searchreplace.search_desc',cmd:'mceSearch'});ed.addButton('replace',{title:'searchreplace.replace_desc',cmd:'mceReplace'});ed.addShortcut('ctrl+f','searchreplace.search_desc','mceSearch');},getInfo:function(){return{longname:'Search/Replace',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/searchreplace',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('searchreplace',tinymce.plugins.SearchReplacePlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/searchreplace/editor_plugin_src.js b/jscripts/tiny_mce/plugins/searchreplace/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..59edc3b
--- /dev/null
@@ -0,0 +1,54 @@
+/**\r
+ * $Id: editor_plugin_src.js 686 2008-03-09 18:13:49Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.SearchReplacePlugin', {\r
+               init : function(ed, url) {\r
+                       function open(m) {\r
+                               ed.windowManager.open({\r
+                                       file : url + '/searchreplace.htm',\r
+                                       width : 420 + parseInt(ed.getLang('searchreplace.delta_width', 0)),\r
+                                       height : 160 + parseInt(ed.getLang('searchreplace.delta_height', 0)),\r
+                                       inline : 1,\r
+                                       auto_focus : 0\r
+                               }, {\r
+                                       mode : m,\r
+                                       search_string : ed.selection.getContent({format : 'text'}),\r
+                                       plugin_url : url\r
+                               });\r
+                       };\r
+\r
+                       // Register commands\r
+                       ed.addCommand('mceSearch', function() {\r
+                               open('search');\r
+                       });\r
+\r
+                       ed.addCommand('mceReplace', function() {\r
+                               open('replace');\r
+                       });\r
+\r
+                       // Register buttons\r
+                       ed.addButton('search', {title : 'searchreplace.search_desc', cmd : 'mceSearch'});\r
+                       ed.addButton('replace', {title : 'searchreplace.replace_desc', cmd : 'mceReplace'});\r
+\r
+                       ed.addShortcut('ctrl+f', 'searchreplace.search_desc', 'mceSearch');\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Search/Replace',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/searchreplace',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('searchreplace', tinymce.plugins.SearchReplacePlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/searchreplace/js/searchreplace.js b/jscripts/tiny_mce/plugins/searchreplace/js/searchreplace.js
new file mode 100644 (file)
index 0000000..890eb37
--- /dev/null
@@ -0,0 +1,117 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+var SearchReplaceDialog = {\r
+       init : function(ed) {\r
+               var f = document.forms[0], m = tinyMCEPopup.getWindowArg("mode");\r
+\r
+               this.switchMode(m);\r
+\r
+               f[m + '_panel_searchstring'].value = tinyMCEPopup.getWindowArg("search_string");\r
+\r
+               // Focus input field\r
+               f[m + '_panel_searchstring'].focus();\r
+       },\r
+\r
+       switchMode : function(m) {\r
+               var f, lm = this.lastMode;\r
+\r
+               if (lm != m) {\r
+                       f = document.forms[0];\r
+\r
+                       if (lm) {\r
+                               f[m + '_panel_searchstring'].value = f[lm + '_panel_searchstring'].value;\r
+                               f[m + '_panel_backwardsu'].checked = f[lm + '_panel_backwardsu'].checked;\r
+                               f[m + '_panel_backwardsd'].checked = f[lm + '_panel_backwardsd'].checked;\r
+                               f[m + '_panel_casesensitivebox'].checked = f[lm + '_panel_casesensitivebox'].checked;\r
+                       }\r
+\r
+                       mcTabs.displayTab(m + '_tab',  m + '_panel');\r
+                       document.getElementById("replaceBtn").style.display = (m == "replace") ? "inline" : "none";\r
+                       document.getElementById("replaceAllBtn").style.display = (m == "replace") ? "inline" : "none";\r
+                       this.lastMode = m;\r
+               }\r
+       },\r
+\r
+       searchNext : function(a) {\r
+               var ed = tinyMCEPopup.editor, se = ed.selection, r = se.getRng(), f, m = this.lastMode, s, b, fl = 0, w = ed.getWin(), wm = ed.windowManager, fo = 0;\r
+\r
+               // Get input\r
+               f = document.forms[0];\r
+               s = f[m + '_panel_searchstring'].value;\r
+               b = f[m + '_panel_backwardsu'].checked;\r
+               ca = f[m + '_panel_casesensitivebox'].checked;\r
+               rs = f['replace_panel_replacestring'].value;\r
+\r
+               function fix() {\r
+                       // Correct Firefox graphics glitches\r
+                       r = se.getRng().cloneRange();\r
+                       ed.getDoc().execCommand('SelectAll', false, null);\r
+                       se.setRng(r);\r
+               };\r
+\r
+               function replace() {\r
+                       if (tinymce.isIE)\r
+                               ed.selection.getRng().duplicate().pasteHTML(rs); // Needs to be duplicated due to selection bug in IE\r
+                       else\r
+                               ed.getDoc().execCommand('InsertHTML', false, rs);\r
+               };\r
+\r
+               // IE flags\r
+               if (ca)\r
+                       fl = fl | 4;\r
+\r
+               switch (a) {\r
+                       case 'all':\r
+                               if (tinymce.isIE) {\r
+                                       while (r.findText(s, b ? -1 : 1, fl)) {\r
+                                               r.scrollIntoView();\r
+                                               r.select();\r
+                                               replace();\r
+                                               fo = 1;\r
+                                       }\r
+\r
+                                       tinyMCEPopup.storeSelection();\r
+                               } else {\r
+                                       while (w.find(s, ca, b, false, false, false, false)) {\r
+                                               replace();\r
+                                               fo = 1;\r
+                                       }\r
+                               }\r
+\r
+                               if (fo)\r
+                                       wm.alert(ed.getLang('searchreplace_dlg.allreplaced'));\r
+                               else\r
+                                       wm.alert(ed.getLang('searchreplace_dlg.notfound'));\r
+\r
+                               return;\r
+\r
+                       case 'current':\r
+                               replace();\r
+                               break;\r
+               }\r
+\r
+               se.collapse(b);\r
+               r = se.getRng();\r
+\r
+               // Whats the point\r
+               if (!s)\r
+                       return;\r
+\r
+               if (tinymce.isIE) {\r
+                       if (r.findText(s, b ? -1 : 1, fl)) {\r
+                               r.scrollIntoView();\r
+                               r.select();\r
+                       } else\r
+                               wm.alert(ed.getLang('searchreplace_dlg.notfound'));\r
+\r
+                       tinyMCEPopup.storeSelection();\r
+               } else {\r
+                       if (!w.find(s, ca, b, false, false, false, false))\r
+                               wm.alert(ed.getLang('searchreplace_dlg.notfound'));\r
+                       else\r
+                               fix();\r
+               }\r
+       }\r
+};\r
+\r
+tinyMCEPopup.onInit.add(SearchReplaceDialog.init, SearchReplaceDialog);\r
diff --git a/jscripts/tiny_mce/plugins/searchreplace/langs/en_dlg.js b/jscripts/tiny_mce/plugins/searchreplace/langs/en_dlg.js
new file mode 100644 (file)
index 0000000..370959a
--- /dev/null
@@ -0,0 +1,16 @@
+tinyMCE.addI18n('en.searchreplace_dlg',{\r
+searchnext_desc:"Find again",\r
+notfound:"The search has been completed. The search string could not be found.",\r
+search_title:"Find",\r
+replace_title:"Find/Replace",\r
+allreplaced:"All occurrences of the search string were replaced.",\r
+findwhat:"Find what",\r
+replacewith:"Replace with",\r
+direction:"Direction",\r
+up:"Up",\r
+down:"Down",\r
+mcase:"Match case",\r
+findnext:"Find next",\r
+replace:"Replace",\r
+replaceall:"Replace all"\r
+});
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/searchreplace/searchreplace.htm b/jscripts/tiny_mce/plugins/searchreplace/searchreplace.htm
new file mode 100644 (file)
index 0000000..47c9e2e
--- /dev/null
@@ -0,0 +1,105 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#searchreplace_dlg.replace_title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>\r
+       <script type="text/javascript" src="js/searchreplace.js?v=307"></script>\r
+       <link rel="stylesheet" type="text/css" href="css/searchreplace.css?v=307" />\r
+       <base target="_self" />\r
+</head>\r
+<body style="display:none;">\r
+<form onsubmit="SearchReplaceDialog.searchNext('none');return false;" action="#">\r
+       <div class="tabs">\r
+               <ul>\r
+                       <li id="search_tab"><span><a href="javascript:SearchReplaceDialog.switchMode('search');" onmousedown="return false;">{#searchreplace.search_desc}</a></span></li>\r
+                       <li id="replace_tab"><span><a href="javascript:SearchReplaceDialog.switchMode('replace');" onmousedown="return false;">{#searchreplace_dlg.replace}</a></span></li>\r
+               </ul>\r
+       </div>\r
+\r
+       <div class="panel_wrapper">\r
+               <div id="search_panel" class="panel">\r
+                       <table border="0" cellspacing="0" cellpadding="2">\r
+                               <tr>\r
+                                       <td><label for="search_panel_searchstring">{#searchreplace_dlg.findwhat}</label></td>\r
+                                       <td><input type="text" id="search_panel_searchstring" name="search_panel_searchstring" style="width: 200px" /></td>\r
+                               </tr>\r
+                               <tr>\r
+                                       <td colspan="2">\r
+                                               <table border="0" cellspacing="0" cellpadding="0" class="direction">\r
+                                                       <tr>\r
+                                                               <td><label>{#searchreplace_dlg.direction}</label></td>\r
+                                                               <td><input id="search_panel_backwardsu" name="search_panel_backwards" class="radio" type="radio" /></td>\r
+                                                               <td><label for="search_panel_backwardsu">{#searchreplace_dlg.up}</label></td>\r
+                                                               <td><input id="search_panel_backwardsd" name="search_panel_backwards" class="radio" type="radio" checked="checked" /></td>\r
+                                                               <td><label for="search_panel_backwardsd">{#searchreplace_dlg.down}</label></td>\r
+                                                       </tr>\r
+                                               </table>\r
+                                       </td>\r
+                               </tr>\r
+                               <tr>\r
+                                       <td colspan="2">\r
+                                               <table border="0" cellspacing="0" cellpadding="0">\r
+                                                       <tr>\r
+                                                               <td><input id="search_panel_casesensitivebox" name="search_panel_casesensitivebox" class="checkbox" type="checkbox" /></td>\r
+                                                               <td><label for="search_panel_casesensitivebox">{#searchreplace_dlg.mcase}</label></td>\r
+                                                       </tr>\r
+                                               </table>\r
+                                       </td>\r
+                               </tr>\r
+                       </table>\r
+               </div>\r
+\r
+               <div id="replace_panel" class="panel">\r
+                       <table border="0" cellspacing="0" cellpadding="2">\r
+                               <tr>\r
+                                       <td><label for="replace_panel_searchstring">{#searchreplace_dlg.findwhat}</label></td>\r
+                                       <td><input type="text" id="replace_panel_searchstring" name="replace_panel_searchstring" style="width: 200px" /></td>\r
+                               </tr>\r
+                               <tr>\r
+                                       <td><label for="replace_panel_replacestring">{#searchreplace_dlg.replacewith}</label></td>\r
+                                       <td><input type="text" id="replace_panel_replacestring" name="replace_panel_replacestring" style="width: 200px" /></td>\r
+                               </tr>\r
+                               <tr>\r
+                                       <td colspan="2">\r
+                                               <table border="0" cellspacing="0" cellpadding="0" class="direction">\r
+                                                       <tr>\r
+                                                               <td><label>{#searchreplace_dlg.direction}</label></td>\r
+                                                               <td><input id="replace_panel_backwardsu" name="replace_panel_backwards" class="radio" type="radio" /></td>\r
+                                                               <td><label for="replace_panel_backwardsu">{#searchreplace_dlg.up}</label></td>\r
+                                                               <td><input id="replace_panel_backwardsd" name="replace_panel_backwards" class="radio" type="radio" checked="checked" /></td>\r
+                                                               <td><label for="replace_panel_backwardsd">{#searchreplace_dlg.down}</label></td>\r
+                                                       </tr>\r
+                                               </table>\r
+                                       </td>\r
+                               </tr>\r
+                               <tr>\r
+                                       <td colspan="2">\r
+                                               <table border="0" cellspacing="0" cellpadding="0">\r
+                                                       <tr>\r
+                                                               <td><input id="replace_panel_casesensitivebox" name="replace_panel_casesensitivebox" class="checkbox" type="checkbox" /></td>\r
+                                                               <td><label for="replace_panel_casesensitivebox">{#searchreplace_dlg.mcase}</label></td>\r
+                                                       </tr>\r
+                                               </table>\r
+                                       </td>\r
+                               </tr>\r
+                       </table>\r
+               </div>\r
+\r
+       </div>\r
+\r
+       <div class="mceActionPanel">\r
+               <div style="float: left">\r
+                       <input type="submit" id="insert" name="insert" value="{#searchreplace_dlg.findnext}" />\r
+                       <input type="button" class="button" id="replaceBtn" name="replaceBtn" value="{#searchreplace_dlg.replace}" onclick="SearchReplaceDialog.searchNext('current');" />\r
+                       <input type="button" class="button" id="replaceAllBtn" name="replaceAllBtn" value="{#searchreplace_dlg.replaceall}" onclick="SearchReplaceDialog.searchNext('all');" />\r
+               </div>\r
+\r
+               <div style="float: right">      \r
+                       <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+               </div>\r
+       </div>\r
+</form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/spellchecker/css/content.css b/jscripts/tiny_mce/plugins/spellchecker/css/content.css
new file mode 100644 (file)
index 0000000..24efa02
--- /dev/null
@@ -0,0 +1 @@
+.mceItemHiddenSpellWord {background:url(../img/wline.gif) repeat-x bottom left; cursor:default;}\r
diff --git a/jscripts/tiny_mce/plugins/spellchecker/editor_plugin.js b/jscripts/tiny_mce/plugins/spellchecker/editor_plugin.js
new file mode 100644 (file)
index 0000000..9cb6799
--- /dev/null
@@ -0,0 +1 @@
+(function(){var JSONRequest=tinymce.util.JSONRequest,each=tinymce.each,DOM=tinymce.DOM;tinymce.create('tinymce.plugins.SpellcheckerPlugin',{getInfo:function(){return{longname:'Spellchecker',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker',version:tinymce.majorVersion+"."+tinymce.minorVersion};},init:function(ed,url){var t=this,cm;t.url=url;t.editor=ed;ed.addCommand('mceSpellCheck',function(){if(!t.active){ed.setProgressState(1);t._sendRPC('checkWords',[t.selectedLang,t._getWords()],function(r){if(r.length>0){t.active=1;t._markWords(r);ed.setProgressState(0);ed.nodeChanged();}else{ed.setProgressState(0);ed.windowManager.alert('spellchecker.no_mpell');}});}else t._done();});ed.onInit.add(function(){if(ed.settings.content_css!==false)ed.dom.loadCSS(url+'/css/content.css');});ed.onClick.add(t._showMenu,t);ed.onContextMenu.add(t._showMenu,t);ed.onBeforeGetContent.add(function(){if(t.active)t._removeWords();});ed.onNodeChange.add(function(ed,cm){cm.setActive('spellchecker',t.active);});ed.onSetContent.add(function(){t._done();});ed.onBeforeGetContent.add(function(){t._done();});ed.onBeforeExecCommand.add(function(ed,cmd){if(cmd=='mceFullScreen')t._done();});t.languages={};each(ed.getParam('spellchecker_languages','+English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr,German=de,Italian=it,Polish=pl,Portuguese=pt,Spanish=es,Swedish=sv','hash'),function(v,k){if(k.indexOf('+')===0){k=k.substring(1);t.selectedLang=v;}t.languages[k]=v;});},createControl:function(n,cm){var t=this,c,ed=t.editor;if(n=='spellchecker'){c=cm.createSplitButton(n,{title:'spellchecker.desc',cmd:'mceSpellCheck',scope:t});c.onRenderMenu.add(function(c,m){m.add({title:'spellchecker.langs','class':'mceMenuItemTitle'}).setDisabled(1);each(t.languages,function(v,k){var o={icon:1},mi;o.onclick=function(){mi.setSelected(1);t.selectedItem.setSelected(0);t.selectedItem=mi;t.selectedLang=v;};o.title=k;mi=m.add(o);mi.setSelected(v==t.selectedLang);if(v==t.selectedLang)t.selectedItem=mi;})});return c;}},_walk:function(n,f){var d=this.editor.getDoc(),w;if(d.createTreeWalker){w=d.createTreeWalker(n,NodeFilter.SHOW_TEXT,null,false);while((n=w.nextNode())!=null)f.call(this,n);}else tinymce.walk(n,f,'childNodes');},_getSeparators:function(){var re='',i,str=this.editor.getParam('spellchecker_word_separator_chars','\\s!"#$%&()*+,-./:;<=>?@[\]^_{|}����������������\u201d\u201c');for(i=0;i<str.length;i++)re+='\\'+str.charAt(i);return re;},_getWords:function(){var ed=this.editor,wl=[],tx='',lo={};this._walk(ed.getBody(),function(n){if(n.nodeType==3)tx+=n.nodeValue+' ';});tx=tx.replace(new RegExp('([0-9]|['+this._getSeparators()+'])','g'),' ');tx=tinymce.trim(tx.replace(/(\s+)/g,' '));each(tx.split(' '),function(v){if(!lo[v]){wl.push(v);lo[v]=1;}});return wl;},_removeWords:function(w){var ed=this.editor,dom=ed.dom,se=ed.selection,b=se.getBookmark();each(dom.select('span').reverse(),function(n){if(n&&(dom.hasClass(n,'mceItemHiddenSpellWord')||dom.hasClass(n,'mceItemHidden'))){if(!w||dom.decode(n.innerHTML)==w)dom.remove(n,1);}});se.moveToBookmark(b);},_markWords:function(wl){var r1,r2,r3,r4,r5,w='',ed=this.editor,re=this._getSeparators(),dom=ed.dom,nl=[];var se=ed.selection,b=se.getBookmark();each(wl,function(v){w+=(w?'|':'')+v;});r1=new RegExp('(['+re+'])('+w+')(['+re+'])','g');r2=new RegExp('^('+w+')','g');r3=new RegExp('('+w+')(['+re+']?)$','g');r4=new RegExp('^('+w+')(['+re+']?)$','g');r5=new RegExp('('+w+')(['+re+'])','g');this._walk(this.editor.getBody(),function(n){if(n.nodeType==3){nl.push(n);}});each(nl,function(n){var v;if(n.nodeType==3){v=n.nodeValue;if(r1.test(v)||r2.test(v)||r3.test(v)||r4.test(v)){v=dom.encode(v);v=v.replace(r5,'<span class="mceItemHiddenSpellWord">$1</span>$2');v=v.replace(r3,'<span class="mceItemHiddenSpellWord">$1</span>$2');dom.replace(dom.create('span',{'class':'mceItemHidden'},v),n);}}});se.moveToBookmark(b);},_showMenu:function(ed,e){var t=this,ed=t.editor,m=t._menu,p1,dom=ed.dom,vp=dom.getViewPort(ed.getWin());if(!m){p1=DOM.getPos(ed.getContentAreaContainer());m=ed.controlManager.createDropMenu('spellcheckermenu',{offset_x:p1.x,offset_y:p1.y,'class':'mceNoIcons'});t._menu=m;}if(dom.hasClass(e.target,'mceItemHiddenSpellWord')){m.removeAll();m.add({title:'spellchecker.wait','class':'mceMenuItemTitle'}).setDisabled(1);t._sendRPC('getSuggestions',[t.selectedLang,dom.decode(e.target.innerHTML)],function(r){m.removeAll();if(r.length>0){m.add({title:'spellchecker.sug','class':'mceMenuItemTitle'}).setDisabled(1);each(r,function(v){m.add({title:v,onclick:function(){dom.replace(ed.getDoc().createTextNode(v),e.target);t._checkDone();}});});m.addSeparator();}else m.add({title:'spellchecker.no_sug','class':'mceMenuItemTitle'}).setDisabled(1);m.add({title:'spellchecker.ignore_word',onclick:function(){dom.remove(e.target,1);t._checkDone();}});m.add({title:'spellchecker.ignore_words',onclick:function(){t._removeWords(dom.decode(e.target.innerHTML));t._checkDone();}});m.update();});ed.selection.select(e.target);p1=dom.getPos(e.target);m.showMenu(p1.x,p1.y+e.target.offsetHeight-vp.y);return tinymce.dom.Event.cancel(e);}else m.hideMenu();},_checkDone:function(){var t=this,ed=t.editor,dom=ed.dom,o;each(dom.select('span'),function(n){if(n&&dom.hasClass(n,'mceItemHiddenSpellWord')){o=true;return false;}});if(!o)t._done();},_done:function(){var t=this,la=t.active;if(t.active){t.active=0;t._removeWords();if(t._menu)t._menu.hideMenu();if(la)t.editor.nodeChanged();}},_sendRPC:function(m,p,cb){var t=this,url=t.editor.getParam("spellchecker_rpc_url","{backend}");if(url=='{backend}'){t.editor.setProgressState(0);alert('Please specify: spellchecker_rpc_url');return;}JSONRequest.sendRPC({url:url,method:m,params:p,success:cb,error:function(e,x){t.editor.setProgressState(0);t.editor.windowManager.alert(e.errstr||('Error response: '+x.responseText));}});}});tinymce.PluginManager.add('spellchecker',tinymce.plugins.SpellcheckerPlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/spellchecker/editor_plugin_src.js b/jscripts/tiny_mce/plugins/spellchecker/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..c913c46
--- /dev/null
@@ -0,0 +1,338 @@
+/**\r
+ * $Id: editor_plugin_src.js 425 2007-11-21 15:17:39Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       var JSONRequest = tinymce.util.JSONRequest, each = tinymce.each, DOM = tinymce.DOM;\r
+\r
+       tinymce.create('tinymce.plugins.SpellcheckerPlugin', {\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Spellchecker',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               },\r
+\r
+               init : function(ed, url) {\r
+                       var t = this, cm;\r
+\r
+                       t.url = url;\r
+                       t.editor = ed;\r
+\r
+                       // Register commands\r
+                       ed.addCommand('mceSpellCheck', function() {\r
+                               if (!t.active) {\r
+                                       ed.setProgressState(1);\r
+                                       t._sendRPC('checkWords', [t.selectedLang, t._getWords()], function(r) {\r
+                                               if (r.length > 0) {\r
+                                                       t.active = 1;\r
+                                                       t._markWords(r);\r
+                                                       ed.setProgressState(0);\r
+                                                       ed.nodeChanged();\r
+                                               } else {\r
+                                                       ed.setProgressState(0);\r
+                                                       ed.windowManager.alert('spellchecker.no_mpell');\r
+                                               }\r
+                                       });\r
+                               } else\r
+                                       t._done();\r
+                       });\r
+\r
+                       ed.onInit.add(function() {\r
+                               if (ed.settings.content_css !== false)\r
+                                       ed.dom.loadCSS(url + '/css/content.css');\r
+                       });\r
+\r
+                       ed.onClick.add(t._showMenu, t);\r
+                       ed.onContextMenu.add(t._showMenu, t);\r
+                       ed.onBeforeGetContent.add(function() {\r
+                               if (t.active)\r
+                                       t._removeWords();\r
+                       });\r
+\r
+                       ed.onNodeChange.add(function(ed, cm) {\r
+                               cm.setActive('spellchecker', t.active);\r
+                       });\r
+\r
+                       ed.onSetContent.add(function() {\r
+                               t._done();\r
+                       });\r
+\r
+                       ed.onBeforeGetContent.add(function() {\r
+                               t._done();\r
+                       });\r
+\r
+                       ed.onBeforeExecCommand.add(function(ed, cmd) {\r
+                               if (cmd == 'mceFullScreen')\r
+                                       t._done();\r
+                       });\r
+\r
+                       // Find selected language\r
+                       t.languages = {};\r
+                       each(ed.getParam('spellchecker_languages', '+English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr,German=de,Italian=it,Polish=pl,Portuguese=pt,Spanish=es,Swedish=sv', 'hash'), function(v, k) {\r
+                               if (k.indexOf('+') === 0) {\r
+                                       k = k.substring(1);\r
+                                       t.selectedLang = v;\r
+                               }\r
+\r
+                               t.languages[k] = v;\r
+                       });\r
+               },\r
+\r
+               createControl : function(n, cm) {\r
+                       var t = this, c, ed = t.editor;\r
+\r
+                       if (n == 'spellchecker') {\r
+                               c = cm.createSplitButton(n, {title : 'spellchecker.desc', cmd : 'mceSpellCheck', scope : t});\r
+\r
+                               c.onRenderMenu.add(function(c, m) {\r
+                                       m.add({title : 'spellchecker.langs', 'class' : 'mceMenuItemTitle'}).setDisabled(1);\r
+                                       each(t.languages, function(v, k) {\r
+                                               var o = {icon : 1}, mi;\r
+\r
+                                               o.onclick = function() {\r
+                                                       mi.setSelected(1);\r
+                                                       t.selectedItem.setSelected(0);\r
+                                                       t.selectedItem = mi;\r
+                                                       t.selectedLang = v;\r
+                                               };\r
+\r
+                                               o.title = k;\r
+                                               mi = m.add(o);\r
+                                               mi.setSelected(v == t.selectedLang);\r
+\r
+                                               if (v == t.selectedLang)\r
+                                                       t.selectedItem = mi;\r
+                                       })\r
+                               });\r
+\r
+                               return c;\r
+                       }\r
+               },\r
+\r
+               // Internal functions\r
+\r
+               _walk : function(n, f) {\r
+                       var d = this.editor.getDoc(), w;\r
+\r
+                       if (d.createTreeWalker) {\r
+                               w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);\r
+\r
+                               while ((n = w.nextNode()) != null)\r
+                                       f.call(this, n);\r
+                       } else\r
+                               tinymce.walk(n, f, 'childNodes');\r
+               },\r
+\r
+               _getSeparators : function() {\r
+                       var re = '', i, str = this.editor.getParam('spellchecker_word_separator_chars', '\\s!"#$%&()*+,-./:;<=>?@[\]^_{|}§©«®±¶·¸»¼½¾¿×÷¤\u201d\u201c');\r
+\r
+                       // Build word separator regexp\r
+                       for (i=0; i<str.length; i++)\r
+                               re += '\\' + str.charAt(i);\r
+\r
+                       return re;\r
+               },\r
+\r
+               _getWords : function() {\r
+                       var ed = this.editor, wl = [], tx = '', lo = {};\r
+\r
+                       // Get area text\r
+                       this._walk(ed.getBody(), function(n) {\r
+                               if (n.nodeType == 3)\r
+                                       tx += n.nodeValue + ' ';\r
+                       });\r
+\r
+                       // Split words by separator\r
+                       tx = tx.replace(new RegExp('([0-9]|[' + this._getSeparators() + '])', 'g'), ' ');\r
+                       tx = tinymce.trim(tx.replace(/(\s+)/g, ' '));\r
+\r
+                       // Build word array and remove duplicates\r
+                       each(tx.split(' '), function(v) {\r
+                               if (!lo[v]) {\r
+                                       wl.push(v);\r
+                                       lo[v] = 1;\r
+                               }\r
+                       });\r
+\r
+                       return wl;\r
+               },\r
+\r
+               _removeWords : function(w) {\r
+                       var ed = this.editor, dom = ed.dom, se = ed.selection, b = se.getBookmark();\r
+\r
+                       each(dom.select('span').reverse(), function(n) {\r
+                               if (n && (dom.hasClass(n, 'mceItemHiddenSpellWord') || dom.hasClass(n, 'mceItemHidden'))) {\r
+                                       if (!w || dom.decode(n.innerHTML) == w)\r
+                                               dom.remove(n, 1);\r
+                               }\r
+                       });\r
+\r
+                       se.moveToBookmark(b);\r
+               },\r
+\r
+               _markWords : function(wl) {\r
+                       var r1, r2, r3, r4, r5, w = '', ed = this.editor, re = this._getSeparators(), dom = ed.dom, nl = [];\r
+                       var se = ed.selection, b = se.getBookmark();\r
+\r
+                       each(wl, function(v) {\r
+                               w += (w ? '|' : '') + v;\r
+                       });\r
+\r
+                       r1 = new RegExp('([' + re + '])(' + w + ')([' + re + '])', 'g');\r
+                       r2 = new RegExp('^(' + w + ')', 'g');\r
+                       r3 = new RegExp('(' + w + ')([' + re + ']?)$', 'g');\r
+                       r4 = new RegExp('^(' + w + ')([' + re + ']?)$', 'g');\r
+                       r5 = new RegExp('(' + w + ')([' + re + '])', 'g');\r
+\r
+                       // Collect all text nodes\r
+                       this._walk(this.editor.getBody(), function(n) {\r
+                               if (n.nodeType == 3) {\r
+                                       nl.push(n);\r
+                               }\r
+                       });\r
+\r
+                       // Wrap incorrect words in spans\r
+                       each(nl, function(n) {\r
+                               var v;\r
+\r
+                               if (n.nodeType == 3) {\r
+                                       v = n.nodeValue;\r
+\r
+                                       if (r1.test(v) || r2.test(v) || r3.test(v) || r4.test(v)) {\r
+                                               v = dom.encode(v);\r
+                                               v = v.replace(r5, '<span class="mceItemHiddenSpellWord">$1</span>$2');\r
+                                               v = v.replace(r3, '<span class="mceItemHiddenSpellWord">$1</span>$2');\r
+\r
+                                               dom.replace(dom.create('span', {'class' : 'mceItemHidden'}, v), n);\r
+                                       }\r
+                               }\r
+                       });\r
+\r
+                       se.moveToBookmark(b);\r
+               },\r
+\r
+               _showMenu : function(ed, e) {\r
+                       var t = this, ed = t.editor, m = t._menu, p1, dom = ed.dom, vp = dom.getViewPort(ed.getWin());\r
+\r
+                       if (!m) {\r
+                               p1 = DOM.getPos(ed.getContentAreaContainer());\r
+                               //p2 = DOM.getPos(ed.getContainer());\r
+\r
+                               m = ed.controlManager.createDropMenu('spellcheckermenu', {\r
+                                       offset_x : p1.x,\r
+                                       offset_y : p1.y,\r
+                                       'class' : 'mceNoIcons'\r
+                               });\r
+\r
+                               t._menu = m;\r
+                       }\r
+\r
+                       if (dom.hasClass(e.target, 'mceItemHiddenSpellWord')) {\r
+                               m.removeAll();\r
+                               m.add({title : 'spellchecker.wait', 'class' : 'mceMenuItemTitle'}).setDisabled(1);\r
+\r
+                               t._sendRPC('getSuggestions', [t.selectedLang, dom.decode(e.target.innerHTML)], function(r) {\r
+                                       m.removeAll();\r
+\r
+                                       if (r.length > 0) {\r
+                                               m.add({title : 'spellchecker.sug', 'class' : 'mceMenuItemTitle'}).setDisabled(1);\r
+                                               each(r, function(v) {\r
+                                                       m.add({title : v, onclick : function() {\r
+                                                               dom.replace(ed.getDoc().createTextNode(v), e.target);\r
+                                                               t._checkDone();\r
+                                                       }});\r
+                                               });\r
+\r
+                                               m.addSeparator();\r
+                                       } else\r
+                                               m.add({title : 'spellchecker.no_sug', 'class' : 'mceMenuItemTitle'}).setDisabled(1);\r
+\r
+                                       m.add({\r
+                                               title : 'spellchecker.ignore_word',\r
+                                               onclick : function() {\r
+                                                       dom.remove(e.target, 1);\r
+                                                       t._checkDone();\r
+                                               }\r
+                                       });\r
+\r
+                                       m.add({\r
+                                               title : 'spellchecker.ignore_words',\r
+                                               onclick : function() {\r
+                                                       t._removeWords(dom.decode(e.target.innerHTML));\r
+                                                       t._checkDone();\r
+                                               }\r
+                                       });\r
+\r
+                                       m.update();\r
+                               });\r
+\r
+                               ed.selection.select(e.target);\r
+                               p1 = dom.getPos(e.target);\r
+                               m.showMenu(p1.x, p1.y + e.target.offsetHeight - vp.y);\r
+\r
+                               return tinymce.dom.Event.cancel(e);\r
+                       } else\r
+                               m.hideMenu();\r
+               },\r
+\r
+               _checkDone : function() {\r
+                       var t = this, ed = t.editor, dom = ed.dom, o;\r
+\r
+                       each(dom.select('span'), function(n) {\r
+                               if (n && dom.hasClass(n, 'mceItemHiddenSpellWord')) {\r
+                                       o = true;\r
+                                       return false;\r
+                               }\r
+                       });\r
+\r
+                       if (!o)\r
+                               t._done();\r
+               },\r
+\r
+               _done : function() {\r
+                       var t = this, la = t.active;\r
+\r
+                       if (t.active) {\r
+                               t.active = 0;\r
+                               t._removeWords();\r
+\r
+                               if (t._menu)\r
+                                       t._menu.hideMenu();\r
+\r
+                               if (la)\r
+                                       t.editor.nodeChanged();\r
+                       }\r
+               },\r
+\r
+               _sendRPC : function(m, p, cb) {\r
+                       var t = this, url = t.editor.getParam("spellchecker_rpc_url", "{backend}");\r
+\r
+                       if (url == '{backend}') {\r
+                               t.editor.setProgressState(0);\r
+                               alert('Please specify: spellchecker_rpc_url');\r
+                               return;\r
+                       }\r
+\r
+                       JSONRequest.sendRPC({\r
+                               url : url,\r
+                               method : m,\r
+                               params : p,\r
+                               success : cb,\r
+                               error : function(e, x) {\r
+                                       t.editor.setProgressState(0);\r
+                                       t.editor.windowManager.alert(e.errstr || ('Error response: ' + x.responseText));\r
+                               }\r
+                       });\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('spellchecker', tinymce.plugins.SpellcheckerPlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/spellchecker/img/wline.gif b/jscripts/tiny_mce/plugins/spellchecker/img/wline.gif
new file mode 100644 (file)
index 0000000..7d0a4db
Binary files /dev/null and b/jscripts/tiny_mce/plugins/spellchecker/img/wline.gif differ
diff --git a/jscripts/tiny_mce/plugins/style/css/props.css b/jscripts/tiny_mce/plugins/style/css/props.css
new file mode 100644 (file)
index 0000000..eb1f264
--- /dev/null
@@ -0,0 +1,13 @@
+#text_font {width:250px;}\r
+#text_size {width:70px;}\r
+.mceAddSelectValue {background:#DDD;}\r
+select, #block_text_indent, #box_width, #box_height, #box_padding_top, #box_padding_right, #box_padding_bottom, #box_padding_left {width:70px;}\r
+#box_margin_top, #box_margin_right, #box_margin_bottom, #box_margin_left, #positioning_width, #positioning_height, #positioning_zindex {width:70px;}\r
+#positioning_placement_top, #positioning_placement_right, #positioning_placement_bottom, #positioning_placement_left {width:70px;}\r
+#positioning_clip_top, #positioning_clip_right, #positioning_clip_bottom, #positioning_clip_left {width:70px;}\r
+.panel_wrapper div.current {padding-top:10px;height:230px;}\r
+.delim {border-left:1px solid gray;}\r
+.tdelim {border-bottom:1px solid gray;}\r
+#block_display {width:145px;}\r
+#list_type {width:115px;}\r
+.disabled {background:#EEE;}\r
diff --git a/jscripts/tiny_mce/plugins/style/editor_plugin.js b/jscripts/tiny_mce/plugins/style/editor_plugin.js
new file mode 100644 (file)
index 0000000..6ebaa91
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.StylePlugin',{init:function(ed,url){ed.addCommand('mceStyleProps',function(){ed.windowManager.open({file:url+'/props.htm',width:480+parseInt(ed.getLang('style.delta_width',0)),height:320+parseInt(ed.getLang('style.delta_height',0)),inline:1},{plugin_url:url,style_text:ed.selection.getNode().style.cssText});});ed.addCommand('mceSetElementStyle',function(ui,v){if(e=ed.selection.getNode()){ed.dom.setAttrib(e,'style',v);ed.execCommand('mceRepaint');}});ed.onNodeChange.add(function(ed,cm,n){cm.setDisabled('styleprops',n.nodeName==='BODY');});ed.addButton('styleprops',{title:'style.desc',cmd:'mceStyleProps'});},getInfo:function(){return{longname:'Style',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/style',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('style',tinymce.plugins.StylePlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/style/editor_plugin_src.js b/jscripts/tiny_mce/plugins/style/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..6c817ce
--- /dev/null
@@ -0,0 +1,52 @@
+/**\r
+ * $Id: editor_plugin_src.js 787 2008-04-10 11:40:57Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.StylePlugin', {\r
+               init : function(ed, url) {\r
+                       // Register commands\r
+                       ed.addCommand('mceStyleProps', function() {\r
+                               ed.windowManager.open({\r
+                                       file : url + '/props.htm',\r
+                                       width : 480 + parseInt(ed.getLang('style.delta_width', 0)),\r
+                                       height : 320 + parseInt(ed.getLang('style.delta_height', 0)),\r
+                                       inline : 1\r
+                               }, {\r
+                                       plugin_url : url,\r
+                                       style_text : ed.selection.getNode().style.cssText\r
+                               });\r
+                       });\r
+\r
+                       ed.addCommand('mceSetElementStyle', function(ui, v) {\r
+                               if (e = ed.selection.getNode()) {\r
+                                       ed.dom.setAttrib(e, 'style', v);\r
+                                       ed.execCommand('mceRepaint');\r
+                               }\r
+                       });\r
+\r
+                       ed.onNodeChange.add(function(ed, cm, n) {\r
+                               cm.setDisabled('styleprops', n.nodeName === 'BODY');\r
+                       });\r
+\r
+                       // Register buttons\r
+                       ed.addButton('styleprops', {title : 'style.desc', cmd : 'mceStyleProps'});\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Style',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/style',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('style', tinymce.plugins.StylePlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/style/js/props.js b/jscripts/tiny_mce/plugins/style/js/props.js
new file mode 100644 (file)
index 0000000..cafd6b1
--- /dev/null
@@ -0,0 +1,641 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+var defaultFonts = "" + \r
+       "Arial, Helvetica, sans-serif=Arial, Helvetica, sans-serif;" + \r
+       "Times New Roman, Times, serif=Times New Roman, Times, serif;" + \r
+       "Courier New, Courier, mono=Courier New, Courier, mono;" + \r
+       "Times New Roman, Times, serif=Times New Roman, Times, serif;" + \r
+       "Georgia, Times New Roman, Times, serif=Georgia, Times New Roman, Times, serif;" + \r
+       "Verdana, Arial, Helvetica, sans-serif=Verdana, Arial, Helvetica, sans-serif;" + \r
+       "Geneva, Arial, Helvetica, sans-serif=Geneva, Arial, Helvetica, sans-serif";\r
+\r
+var defaultSizes = "9;10;12;14;16;18;24;xx-small;x-small;small;medium;large;x-large;xx-large;smaller;larger";\r
+var defaultMeasurement = "+pixels=px;points=pt;em;in;cm;mm;picas;ems;exs;%";\r
+var defaultSpacingMeasurement = "pixels=px;points=pt;in;cm;mm;picas;+ems;exs;%";\r
+var defaultIndentMeasurement = "pixels=px;+points=pt;in;cm;mm;picas;ems;exs;%";\r
+var defaultWeight = "normal;bold;bolder;lighter;100;200;300;400;500;600;700;800;900";\r
+var defaultTextStyle = "normal;italic;oblique";\r
+var defaultVariant = "normal;small-caps";\r
+var defaultLineHeight = "normal";\r
+var defaultAttachment = "fixed;scroll";\r
+var defaultRepeat = "no-repeat;repeat;repeat-x;repeat-y";\r
+var defaultPosH = "left;center;right";\r
+var defaultPosV = "top;center;bottom";\r
+var defaultVAlign = "baseline;sub;super;top;text-top;middle;bottom;text-bottom";\r
+var defaultDisplay = "inline;block;list-item;run-in;compact;marker;table;inline-table;table-row-group;table-header-group;table-footer-group;table-row;table-column-group;table-column;table-cell;table-caption;none";\r
+var defaultBorderStyle = "none;solid;dashed;dotted;double;groove;ridge;inset;outset";\r
+var defaultBorderWidth = "thin;medium;thick";\r
+var defaultListType = "disc;circle;square;decimal;lower-roman;upper-roman;lower-alpha;upper-alpha;none";\r
+\r
+function init() {\r
+       var ce = document.getElementById('container'), h;\r
+\r
+       ce.style.cssText = tinyMCEPopup.getWindowArg('style_text');\r
+\r
+       h = getBrowserHTML('background_image_browser','background_image','image','advimage');\r
+       document.getElementById("background_image_browser").innerHTML = h;\r
+\r
+       document.getElementById('text_color_pickcontainer').innerHTML = getColorPickerHTML('text_color_pick','text_color');\r
+       document.getElementById('background_color_pickcontainer').innerHTML = getColorPickerHTML('background_color_pick','background_color');\r
+       document.getElementById('border_color_top_pickcontainer').innerHTML = getColorPickerHTML('border_color_top_pick','border_color_top');\r
+       document.getElementById('border_color_right_pickcontainer').innerHTML = getColorPickerHTML('border_color_right_pick','border_color_right');\r
+       document.getElementById('border_color_bottom_pickcontainer').innerHTML = getColorPickerHTML('border_color_bottom_pick','border_color_bottom');\r
+       document.getElementById('border_color_left_pickcontainer').innerHTML = getColorPickerHTML('border_color_left_pick','border_color_left');\r
+\r
+       fillSelect(0, 'text_font', 'style_font', defaultFonts, ';', true);\r
+       fillSelect(0, 'text_size', 'style_font_size', defaultSizes, ';', true);\r
+       fillSelect(0, 'text_size_measurement', 'style_font_size_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'text_case', 'style_text_case', "capitalize;uppercase;lowercase", ';', true);\r
+       fillSelect(0, 'text_weight', 'style_font_weight', defaultWeight, ';', true);\r
+       fillSelect(0, 'text_style', 'style_font_style', defaultTextStyle, ';', true);\r
+       fillSelect(0, 'text_variant', 'style_font_variant', defaultVariant, ';', true);\r
+       fillSelect(0, 'text_lineheight', 'style_font_line_height', defaultLineHeight, ';', true);\r
+       fillSelect(0, 'text_lineheight_measurement', 'style_font_line_height_measurement', defaultMeasurement, ';', true);\r
+\r
+       fillSelect(0, 'background_attachment', 'style_background_attachment', defaultAttachment, ';', true);\r
+       fillSelect(0, 'background_repeat', 'style_background_repeat', defaultRepeat, ';', true);\r
+\r
+       fillSelect(0, 'background_hpos_measurement', 'style_background_hpos_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'background_vpos_measurement', 'style_background_vpos_measurement', defaultMeasurement, ';', true);\r
+\r
+       fillSelect(0, 'background_hpos', 'style_background_hpos', defaultPosH, ';', true);\r
+       fillSelect(0, 'background_vpos', 'style_background_vpos', defaultPosV, ';', true);\r
+\r
+       fillSelect(0, 'block_wordspacing', 'style_wordspacing', 'normal', ';', true);\r
+       fillSelect(0, 'block_wordspacing_measurement', 'style_wordspacing_measurement', defaultSpacingMeasurement, ';', true);\r
+       fillSelect(0, 'block_letterspacing', 'style_letterspacing', 'normal', ';', true);\r
+       fillSelect(0, 'block_letterspacing_measurement', 'style_letterspacing_measurement', defaultSpacingMeasurement, ';', true);\r
+       fillSelect(0, 'block_vertical_alignment', 'style_vertical_alignment', defaultVAlign, ';', true);\r
+       fillSelect(0, 'block_text_align', 'style_text_align', "left;right;center;justify", ';', true);\r
+       fillSelect(0, 'block_whitespace', 'style_whitespace', "normal;pre;nowrap", ';', true);\r
+       fillSelect(0, 'block_display', 'style_display', defaultDisplay, ';', true);\r
+       fillSelect(0, 'block_text_indent_measurement', 'style_text_indent_measurement', defaultIndentMeasurement, ';', true);\r
+\r
+       fillSelect(0, 'box_width_measurement', 'style_box_width_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'box_height_measurement', 'style_box_height_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'box_float', 'style_float', 'left;right;none', ';', true);\r
+       fillSelect(0, 'box_clear', 'style_clear', 'left;right;both;none', ';', true);\r
+       fillSelect(0, 'box_padding_left_measurement', 'style_padding_left_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'box_padding_top_measurement', 'style_padding_top_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'box_padding_bottom_measurement', 'style_padding_bottom_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'box_padding_right_measurement', 'style_padding_right_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'box_margin_left_measurement', 'style_margin_left_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'box_margin_top_measurement', 'style_margin_top_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'box_margin_bottom_measurement', 'style_margin_bottom_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'box_margin_right_measurement', 'style_margin_right_measurement', defaultMeasurement, ';', true);\r
+\r
+       fillSelect(0, 'border_style_top', 'style_border_style_top', defaultBorderStyle, ';', true);\r
+       fillSelect(0, 'border_style_right', 'style_border_style_right', defaultBorderStyle, ';', true);\r
+       fillSelect(0, 'border_style_bottom', 'style_border_style_bottom', defaultBorderStyle, ';', true);\r
+       fillSelect(0, 'border_style_left', 'style_border_style_left', defaultBorderStyle, ';', true);\r
+\r
+       fillSelect(0, 'border_width_top', 'style_border_width_top', defaultBorderWidth, ';', true);\r
+       fillSelect(0, 'border_width_right', 'style_border_width_right', defaultBorderWidth, ';', true);\r
+       fillSelect(0, 'border_width_bottom', 'style_border_width_bottom', defaultBorderWidth, ';', true);\r
+       fillSelect(0, 'border_width_left', 'style_border_width_left', defaultBorderWidth, ';', true);\r
+\r
+       fillSelect(0, 'border_width_top_measurement', 'style_border_width_top_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'border_width_right_measurement', 'style_border_width_right_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'border_width_bottom_measurement', 'style_border_width_bottom_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'border_width_left_measurement', 'style_border_width_left_measurement', defaultMeasurement, ';', true);\r
+\r
+       fillSelect(0, 'list_type', 'style_list_type', defaultListType, ';', true);\r
+       fillSelect(0, 'list_position', 'style_list_position', "inside;outside", ';', true);\r
+\r
+       fillSelect(0, 'positioning_type', 'style_positioning_type', "absolute;relative;static", ';', true);\r
+       fillSelect(0, 'positioning_visibility', 'style_positioning_visibility', "inherit;visible;hidden", ';', true);\r
+\r
+       fillSelect(0, 'positioning_width_measurement', 'style_positioning_width_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'positioning_height_measurement', 'style_positioning_height_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'positioning_overflow', 'style_positioning_overflow', "visible;hidden;scroll;auto", ';', true);\r
+\r
+       fillSelect(0, 'positioning_placement_top_measurement', 'style_positioning_placement_top_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'positioning_placement_right_measurement', 'style_positioning_placement_right_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'positioning_placement_bottom_measurement', 'style_positioning_placement_bottom_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'positioning_placement_left_measurement', 'style_positioning_placement_left_measurement', defaultMeasurement, ';', true);\r
+\r
+       fillSelect(0, 'positioning_clip_top_measurement', 'style_positioning_clip_top_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'positioning_clip_right_measurement', 'style_positioning_clip_right_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'positioning_clip_bottom_measurement', 'style_positioning_clip_bottom_measurement', defaultMeasurement, ';', true);\r
+       fillSelect(0, 'positioning_clip_left_measurement', 'style_positioning_clip_left_measurement', defaultMeasurement, ';', true);\r
+\r
+       TinyMCE_EditableSelects.init();\r
+       setupFormData();\r
+       showDisabledControls();\r
+}\r
+\r
+function setupFormData() {\r
+       var ce = document.getElementById('container'), f = document.forms[0], s, b, i;\r
+\r
+       // Setup text fields\r
+\r
+       selectByValue(f, 'text_font', ce.style.fontFamily, true, true);\r
+       selectByValue(f, 'text_size', getNum(ce.style.fontSize), true, true);\r
+       selectByValue(f, 'text_size_measurement', getMeasurement(ce.style.fontSize));\r
+       selectByValue(f, 'text_weight', ce.style.fontWeight, true, true);\r
+       selectByValue(f, 'text_style', ce.style.fontStyle, true, true);\r
+       selectByValue(f, 'text_lineheight', getNum(ce.style.lineHeight), true, true);\r
+       selectByValue(f, 'text_lineheight_measurement', getMeasurement(ce.style.lineHeight));\r
+       selectByValue(f, 'text_case', ce.style.textTransform, true, true);\r
+       selectByValue(f, 'text_variant', ce.style.fontVariant, true, true);\r
+       f.text_color.value = tinyMCEPopup.editor.dom.toHex(ce.style.color);\r
+       updateColor('text_color_pick', 'text_color');\r
+       f.text_underline.checked = inStr(ce.style.textDecoration, 'underline');\r
+       f.text_overline.checked = inStr(ce.style.textDecoration, 'overline');\r
+       f.text_linethrough.checked = inStr(ce.style.textDecoration, 'line-through');\r
+       f.text_blink.checked = inStr(ce.style.textDecoration, 'blink');\r
+\r
+       // Setup background fields\r
+\r
+       f.background_color.value = tinyMCEPopup.editor.dom.toHex(ce.style.backgroundColor);\r
+       updateColor('background_color_pick', 'background_color');\r
+       f.background_image.value = ce.style.backgroundImage.replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");\r
+       selectByValue(f, 'background_repeat', ce.style.backgroundRepeat, true, true);\r
+       selectByValue(f, 'background_attachment', ce.style.backgroundAttachment, true, true);\r
+       selectByValue(f, 'background_hpos', getNum(getVal(ce.style.backgroundPosition, 0)), true, true);\r
+       selectByValue(f, 'background_hpos_measurement', getMeasurement(getVal(ce.style.backgroundPosition, 0)));\r
+       selectByValue(f, 'background_vpos', getNum(getVal(ce.style.backgroundPosition, 1)), true, true);\r
+       selectByValue(f, 'background_vpos_measurement', getMeasurement(getVal(ce.style.backgroundPosition, 1)));\r
+\r
+       // Setup block fields\r
+\r
+       selectByValue(f, 'block_wordspacing', getNum(ce.style.wordSpacing), true, true);\r
+       selectByValue(f, 'block_wordspacing_measurement', getMeasurement(ce.style.wordSpacing));\r
+       selectByValue(f, 'block_letterspacing', getNum(ce.style.letterSpacing), true, true);\r
+       selectByValue(f, 'block_letterspacing_measurement', getMeasurement(ce.style.letterSpacing));\r
+       selectByValue(f, 'block_vertical_alignment', ce.style.verticalAlign, true, true);\r
+       selectByValue(f, 'block_text_align', ce.style.textAlign, true, true);\r
+       f.block_text_indent.value = getNum(ce.style.textIndent);\r
+       selectByValue(f, 'block_text_indent_measurement', getMeasurement(ce.style.textIndent));\r
+       selectByValue(f, 'block_whitespace', ce.style.whiteSpace, true, true);\r
+       selectByValue(f, 'block_display', ce.style.display, true, true);\r
+\r
+       // Setup box fields\r
+\r
+       f.box_width.value = getNum(ce.style.width);\r
+       selectByValue(f, 'box_width_measurement', getMeasurement(ce.style.width));\r
+\r
+       f.box_height.value = getNum(ce.style.height);\r
+       selectByValue(f, 'box_height_measurement', getMeasurement(ce.style.height));\r
+\r
+       if (tinymce.isGecko)\r
+               selectByValue(f, 'box_float', ce.style.cssFloat, true, true);\r
+       else\r
+               selectByValue(f, 'box_float', ce.style.styleFloat, true, true);\r
+\r
+       selectByValue(f, 'box_clear', ce.style.clear, true, true);\r
+\r
+       setupBox(f, ce, 'box_padding', 'padding', '');\r
+       setupBox(f, ce, 'box_margin', 'margin', '');\r
+\r
+       // Setup border fields\r
+\r
+       setupBox(f, ce, 'border_style', 'border', 'Style');\r
+       setupBox(f, ce, 'border_width', 'border', 'Width');\r
+       setupBox(f, ce, 'border_color', 'border', 'Color');\r
+\r
+       updateColor('border_color_top_pick', 'border_color_top');\r
+       updateColor('border_color_right_pick', 'border_color_right');\r
+       updateColor('border_color_bottom_pick', 'border_color_bottom');\r
+       updateColor('border_color_left_pick', 'border_color_left');\r
+\r
+       f.elements.border_color_top.value = tinyMCEPopup.editor.dom.toHex(f.elements.border_color_top.value);\r
+       f.elements.border_color_right.value = tinyMCEPopup.editor.dom.toHex(f.elements.border_color_right.value);\r
+       f.elements.border_color_bottom.value = tinyMCEPopup.editor.dom.toHex(f.elements.border_color_bottom.value);\r
+       f.elements.border_color_left.value = tinyMCEPopup.editor.dom.toHex(f.elements.border_color_left.value);\r
+\r
+       // Setup list fields\r
+\r
+       selectByValue(f, 'list_type', ce.style.listStyleType, true, true);\r
+       selectByValue(f, 'list_position', ce.style.listStylePosition, true, true);\r
+       f.list_bullet_image.value = ce.style.listStyleImage.replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");\r
+\r
+       // Setup box fields\r
+\r
+       selectByValue(f, 'positioning_type', ce.style.position, true, true);\r
+       selectByValue(f, 'positioning_visibility', ce.style.visibility, true, true);\r
+       selectByValue(f, 'positioning_overflow', ce.style.overflow, true, true);\r
+       f.positioning_zindex.value = ce.style.zIndex ? ce.style.zIndex : "";\r
+\r
+       f.positioning_width.value = getNum(ce.style.width);\r
+       selectByValue(f, 'positioning_width_measurement', getMeasurement(ce.style.width));\r
+\r
+       f.positioning_height.value = getNum(ce.style.height);\r
+       selectByValue(f, 'positioning_height_measurement', getMeasurement(ce.style.height));\r
+\r
+       setupBox(f, ce, 'positioning_placement', '', '', ['top', 'right', 'bottom', 'left']);\r
+\r
+       s = ce.style.clip.replace(new RegExp("rect\\('?([^']*)'?\\)", 'gi'), "$1");\r
+       s = s.replace(/,/g, ' ');\r
+\r
+       if (!hasEqualValues([getVal(s, 0), getVal(s, 1), getVal(s, 2), getVal(s, 3)])) {\r
+               f.positioning_clip_top.value = getNum(getVal(s, 0));\r
+               selectByValue(f, 'positioning_clip_top_measurement', getMeasurement(getVal(s, 0)));\r
+               f.positioning_clip_right.value = getNum(getVal(s, 1));\r
+               selectByValue(f, 'positioning_clip_right_measurement', getMeasurement(getVal(s, 1)));\r
+               f.positioning_clip_bottom.value = getNum(getVal(s, 2));\r
+               selectByValue(f, 'positioning_clip_bottom_measurement', getMeasurement(getVal(s, 2)));\r
+               f.positioning_clip_left.value = getNum(getVal(s, 3));\r
+               selectByValue(f, 'positioning_clip_left_measurement', getMeasurement(getVal(s, 3)));\r
+       } else {\r
+               f.positioning_clip_top.value = getNum(getVal(s, 0));\r
+               selectByValue(f, 'positioning_clip_top_measurement', getMeasurement(getVal(s, 0)));\r
+               f.positioning_clip_right.value = f.positioning_clip_bottom.value = f.positioning_clip_left.value;\r
+       }\r
+\r
+//     setupBox(f, ce, '', 'border', 'Color');\r
+}\r
+\r
+function getMeasurement(s) {\r
+       return s.replace(/^([0-9]+)(.*)$/, "$2");\r
+}\r
+\r
+function getNum(s) {\r
+       if (new RegExp('^[0-9]+[a-z%]+$', 'gi').test(s))\r
+               return s.replace(/[^0-9]/g, '');\r
+\r
+       return s;\r
+}\r
+\r
+function inStr(s, n) {\r
+       return new RegExp(n, 'gi').test(s);\r
+}\r
+\r
+function getVal(s, i) {\r
+       var a = s.split(' ');\r
+\r
+       if (a.length > 1)\r
+               return a[i];\r
+\r
+       return "";\r
+}\r
+\r
+function setValue(f, n, v) {\r
+       if (f.elements[n].type == "text")\r
+               f.elements[n].value = v;\r
+       else\r
+               selectByValue(f, n, v, true, true);\r
+}\r
+\r
+function setupBox(f, ce, fp, pr, sf, b) {\r
+       if (typeof(b) == "undefined")\r
+               b = ['Top', 'Right', 'Bottom', 'Left'];\r
+\r
+       if (isSame(ce, pr, sf, b)) {\r
+               f.elements[fp + "_same"].checked = true;\r
+\r
+               setValue(f, fp + "_top", getNum(ce.style[pr + b[0] + sf]));\r
+               f.elements[fp + "_top"].disabled = false;\r
+\r
+               f.elements[fp + "_right"].value = "";\r
+               f.elements[fp + "_right"].disabled = true;\r
+               f.elements[fp + "_bottom"].value = "";\r
+               f.elements[fp + "_bottom"].disabled = true;\r
+               f.elements[fp + "_left"].value = "";\r
+               f.elements[fp + "_left"].disabled = true;\r
+\r
+               if (f.elements[fp + "_top_measurement"]) {\r
+                       selectByValue(f, fp + '_top_measurement', getMeasurement(ce.style[pr + b[0] + sf]));\r
+                       f.elements[fp + "_left_measurement"].disabled = true;\r
+                       f.elements[fp + "_bottom_measurement"].disabled = true;\r
+                       f.elements[fp + "_right_measurement"].disabled = true;\r
+               }\r
+       } else {\r
+               f.elements[fp + "_same"].checked = false;\r
+\r
+               setValue(f, fp + "_top", getNum(ce.style[pr + b[0] + sf]));\r
+               f.elements[fp + "_top"].disabled = false;\r
+\r
+               setValue(f, fp + "_right", getNum(ce.style[pr + b[1] + sf]));\r
+               f.elements[fp + "_right"].disabled = false;\r
+\r
+               setValue(f, fp + "_bottom", getNum(ce.style[pr + b[2] + sf]));\r
+               f.elements[fp + "_bottom"].disabled = false;\r
+\r
+               setValue(f, fp + "_left", getNum(ce.style[pr + b[3] + sf]));\r
+               f.elements[fp + "_left"].disabled = false;\r
+\r
+               if (f.elements[fp + "_top_measurement"]) {\r
+                       selectByValue(f, fp + '_top_measurement', getMeasurement(ce.style[pr + b[0] + sf]));\r
+                       selectByValue(f, fp + '_right_measurement', getMeasurement(ce.style[pr + b[1] + sf]));\r
+                       selectByValue(f, fp + '_bottom_measurement', getMeasurement(ce.style[pr + b[2] + sf]));\r
+                       selectByValue(f, fp + '_left_measurement', getMeasurement(ce.style[pr + b[3] + sf]));\r
+                       f.elements[fp + "_left_measurement"].disabled = false;\r
+                       f.elements[fp + "_bottom_measurement"].disabled = false;\r
+                       f.elements[fp + "_right_measurement"].disabled = false;\r
+               }\r
+       }\r
+}\r
+\r
+function isSame(e, pr, sf, b) {\r
+       var a = [], i, x;\r
+\r
+       if (typeof(b) == "undefined")\r
+               b = ['Top', 'Right', 'Bottom', 'Left'];\r
+\r
+       if (typeof(sf) == "undefined" || sf == null)\r
+               sf = "";\r
+\r
+       a[0] = e.style[pr + b[0] + sf];\r
+       a[1] = e.style[pr + b[1] + sf];\r
+       a[2] = e.style[pr + b[2] + sf];\r
+       a[3] = e.style[pr + b[3] + sf];\r
+\r
+       for (i=0; i<a.length; i++) {\r
+               if (a[i] == null)\r
+                       return false;\r
+\r
+               for (x=0; x<a.length; x++) {\r
+                       if (a[x] != a[i])\r
+                               return false;\r
+               }\r
+       }\r
+\r
+       return true;\r
+};\r
+\r
+function hasEqualValues(a) {\r
+       var i, x;\r
+\r
+       for (i=0; i<a.length; i++) {\r
+               if (a[i] == null)\r
+                       return false;\r
+\r
+               for (x=0; x<a.length; x++) {\r
+                       if (a[x] != a[i])\r
+                               return false;\r
+               }\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+function applyAction() {\r
+       var ce = document.getElementById('container'), ed = tinyMCEPopup.editor;\r
+\r
+       generateCSS();\r
+\r
+       tinyMCEPopup.restoreSelection();\r
+       ed.dom.setAttrib(ed.selection.getNode(), 'style', tinyMCEPopup.editor.dom.serializeStyle(tinyMCEPopup.editor.dom.parseStyle(ce.style.cssText)));\r
+}\r
+\r
+function updateAction() {\r
+       applyAction();\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function generateCSS() {\r
+       var ce = document.getElementById('container'), f = document.forms[0], num = new RegExp('[0-9]+', 'g'), s, t;\r
+\r
+       ce.style.cssText = "";\r
+\r
+       // Build text styles\r
+       ce.style.fontFamily = f.text_font.value;\r
+       ce.style.fontSize = f.text_size.value + (isNum(f.text_size.value) ? (f.text_size_measurement.value || 'px') : "");\r
+       ce.style.fontStyle = f.text_style.value;\r
+       ce.style.lineHeight = f.text_lineheight.value + (isNum(f.text_lineheight.value) ? f.text_lineheight_measurement.value : "");\r
+       ce.style.textTransform = f.text_case.value;\r
+       ce.style.fontWeight = f.text_weight.value;\r
+       ce.style.fontVariant = f.text_variant.value;\r
+       ce.style.color = f.text_color.value;\r
+\r
+       s = "";\r
+       s += f.text_underline.checked ? " underline" : "";\r
+       s += f.text_overline.checked ? " overline" : "";\r
+       s += f.text_linethrough.checked ? " line-through" : "";\r
+       s += f.text_blink.checked ? " blink" : "";\r
+       s = s.length > 0 ? s.substring(1) : s;\r
+\r
+       if (f.text_none.checked)\r
+               s = "none";\r
+\r
+       ce.style.textDecoration = s;\r
+\r
+       // Build background styles\r
+\r
+       ce.style.backgroundColor = f.background_color.value;\r
+       ce.style.backgroundImage = f.background_image.value != "" ? "url(" + f.background_image.value + ")" : "";\r
+       ce.style.backgroundRepeat = f.background_repeat.value;\r
+       ce.style.backgroundAttachment = f.background_attachment.value;\r
+\r
+       if (f.background_hpos.value != "") {\r
+               s = "";\r
+               s += f.background_hpos.value + (isNum(f.background_hpos.value) ? f.background_hpos_measurement.value : "") + " ";\r
+               s += f.background_vpos.value + (isNum(f.background_vpos.value) ? f.background_vpos_measurement.value : "");\r
+               ce.style.backgroundPosition = s;\r
+       }\r
+\r
+       // Build block styles\r
+\r
+       ce.style.wordSpacing = f.block_wordspacing.value + (isNum(f.block_wordspacing.value) ? f.block_wordspacing_measurement.value : "");\r
+       ce.style.letterSpacing = f.block_letterspacing.value + (isNum(f.block_letterspacing.value) ? f.block_letterspacing_measurement.value : "");\r
+       ce.style.verticalAlign = f.block_vertical_alignment.value;\r
+       ce.style.textAlign = f.block_text_align.value;\r
+       ce.style.textIndent = f.block_text_indent.value + (isNum(f.block_text_indent.value) ? f.block_text_indent_measurement.value : "");\r
+       ce.style.whiteSpace = f.block_whitespace.value;\r
+       ce.style.display = f.block_display.value;\r
+\r
+       // Build box styles\r
+\r
+       ce.style.width = f.box_width.value + (isNum(f.box_width.value) ? f.box_width_measurement.value : "");\r
+       ce.style.height = f.box_height.value + (isNum(f.box_height.value) ? f.box_height_measurement.value : "");\r
+       ce.style.styleFloat = f.box_float.value;\r
+\r
+       if (tinymce.isGecko)\r
+               ce.style.cssFloat = f.box_float.value;\r
+\r
+       ce.style.clear = f.box_clear.value;\r
+\r
+       if (!f.box_padding_same.checked) {\r
+               ce.style.paddingTop = f.box_padding_top.value + (isNum(f.box_padding_top.value) ? f.box_padding_top_measurement.value : "");\r
+               ce.style.paddingRight = f.box_padding_right.value + (isNum(f.box_padding_right.value) ? f.box_padding_right_measurement.value : "");\r
+               ce.style.paddingBottom = f.box_padding_bottom.value + (isNum(f.box_padding_bottom.value) ? f.box_padding_bottom_measurement.value : "");\r
+               ce.style.paddingLeft = f.box_padding_left.value + (isNum(f.box_padding_left.value) ? f.box_padding_left_measurement.value : "");\r
+       } else\r
+               ce.style.padding = f.box_padding_top.value + (isNum(f.box_padding_top.value) ? f.box_padding_top_measurement.value : "");               \r
+\r
+       if (!f.box_margin_same.checked) {\r
+               ce.style.marginTop = f.box_margin_top.value + (isNum(f.box_margin_top.value) ? f.box_margin_top_measurement.value : "");\r
+               ce.style.marginRight = f.box_margin_right.value + (isNum(f.box_margin_right.value) ? f.box_margin_right_measurement.value : "");\r
+               ce.style.marginBottom = f.box_margin_bottom.value + (isNum(f.box_margin_bottom.value) ? f.box_margin_bottom_measurement.value : "");\r
+               ce.style.marginLeft = f.box_margin_left.value + (isNum(f.box_margin_left.value) ? f.box_margin_left_measurement.value : "");\r
+       } else\r
+               ce.style.margin = f.box_margin_top.value + (isNum(f.box_margin_top.value) ? f.box_margin_top_measurement.value : "");           \r
+\r
+       // Build border styles\r
+\r
+       if (!f.border_style_same.checked) {\r
+               ce.style.borderTopStyle = f.border_style_top.value;\r
+               ce.style.borderRightStyle = f.border_style_right.value;\r
+               ce.style.borderBottomStyle = f.border_style_bottom.value;\r
+               ce.style.borderLeftStyle = f.border_style_left.value;\r
+       } else\r
+               ce.style.borderStyle = f.border_style_top.value;\r
+\r
+       if (!f.border_width_same.checked) {\r
+               ce.style.borderTopWidth = f.border_width_top.value + (isNum(f.border_width_top.value) ? f.border_width_top_measurement.value : "");\r
+               ce.style.borderRightWidth = f.border_width_right.value + (isNum(f.border_width_right.value) ? f.border_width_right_measurement.value : "");\r
+               ce.style.borderBottomWidth = f.border_width_bottom.value + (isNum(f.border_width_bottom.value) ? f.border_width_bottom_measurement.value : "");\r
+               ce.style.borderLeftWidth = f.border_width_left.value + (isNum(f.border_width_left.value) ? f.border_width_left_measurement.value : "");\r
+       } else\r
+               ce.style.borderWidth = f.border_width_top.value;\r
+\r
+       if (!f.border_color_same.checked) {\r
+               ce.style.borderTopColor = f.border_color_top.value;\r
+               ce.style.borderRightColor = f.border_color_right.value;\r
+               ce.style.borderBottomColor = f.border_color_bottom.value;\r
+               ce.style.borderLeftColor = f.border_color_left.value;\r
+       } else\r
+               ce.style.borderColor = f.border_color_top.value;\r
+\r
+       // Build list styles\r
+\r
+       ce.style.listStyleType = f.list_type.value;\r
+       ce.style.listStylePosition = f.list_position.value;\r
+       ce.style.listStyleImage = f.list_bullet_image.value != "" ? "url(" + f.list_bullet_image.value + ")" : "";\r
+\r
+       // Build positioning styles\r
+\r
+       ce.style.position = f.positioning_type.value;\r
+       ce.style.visibility = f.positioning_visibility.value;\r
+\r
+       if (ce.style.width == "")\r
+               ce.style.width = f.positioning_width.value + (isNum(f.positioning_width.value) ? f.positioning_width_measurement.value : "");\r
+\r
+       if (ce.style.height == "")\r
+               ce.style.height = f.positioning_height.value + (isNum(f.positioning_height.value) ? f.positioning_height_measurement.value : "");\r
+\r
+       ce.style.zIndex = f.positioning_zindex.value;\r
+       ce.style.overflow = f.positioning_overflow.value;\r
+\r
+       if (!f.positioning_placement_same.checked) {\r
+               ce.style.top = f.positioning_placement_top.value + (isNum(f.positioning_placement_top.value) ? f.positioning_placement_top_measurement.value : "");\r
+               ce.style.right = f.positioning_placement_right.value + (isNum(f.positioning_placement_right.value) ? f.positioning_placement_right_measurement.value : "");\r
+               ce.style.bottom = f.positioning_placement_bottom.value + (isNum(f.positioning_placement_bottom.value) ? f.positioning_placement_bottom_measurement.value : "");\r
+               ce.style.left = f.positioning_placement_left.value + (isNum(f.positioning_placement_left.value) ? f.positioning_placement_left_measurement.value : "");\r
+       } else {\r
+               s = f.positioning_placement_top.value + (isNum(f.positioning_placement_top.value) ? f.positioning_placement_top_measurement.value : "");\r
+               ce.style.top = s;\r
+               ce.style.right = s;\r
+               ce.style.bottom = s;\r
+               ce.style.left = s;\r
+       }\r
+\r
+       if (!f.positioning_clip_same.checked) {\r
+               s = "rect(";\r
+               s += (isNum(f.positioning_clip_top.value) ? f.positioning_clip_top.value + f.positioning_clip_top_measurement.value : "auto") + " ";\r
+               s += (isNum(f.positioning_clip_right.value) ? f.positioning_clip_right.value + f.positioning_clip_right_measurement.value : "auto") + " ";\r
+               s += (isNum(f.positioning_clip_bottom.value) ? f.positioning_clip_bottom.value + f.positioning_clip_bottom_measurement.value : "auto") + " ";\r
+               s += (isNum(f.positioning_clip_left.value) ? f.positioning_clip_left.value + f.positioning_clip_left_measurement.value : "auto");\r
+               s += ")";\r
+\r
+               if (s != "rect(auto auto auto auto)")\r
+                       ce.style.clip = s;\r
+       } else {\r
+               s = "rect(";\r
+               t = isNum(f.positioning_clip_top.value) ? f.positioning_clip_top.value + f.positioning_clip_top_measurement.value : "auto";\r
+               s += t + " ";\r
+               s += t + " ";\r
+               s += t + " ";\r
+               s += t + ")";\r
+\r
+               if (s != "rect(auto auto auto auto)")\r
+                       ce.style.clip = s;\r
+       }\r
+\r
+       ce.style.cssText = ce.style.cssText;\r
+}\r
+\r
+function isNum(s) {\r
+       return new RegExp('[0-9]+', 'g').test(s);\r
+}\r
+\r
+function showDisabledControls() {\r
+       var f = document.forms, i, a;\r
+\r
+       for (i=0; i<f.length; i++) {\r
+               for (a=0; a<f[i].elements.length; a++) {\r
+                       if (f[i].elements[a].disabled)\r
+                               tinyMCEPopup.editor.dom.addClass(f[i].elements[a], "disabled");\r
+                       else\r
+                               tinyMCEPopup.editor.dom.removeClass(f[i].elements[a], "disabled");\r
+               }\r
+       }\r
+}\r
+\r
+function fillSelect(f, s, param, dval, sep, em) {\r
+       var i, ar, p, se;\r
+\r
+       f = document.forms[f];\r
+       sep = typeof(sep) == "undefined" ? ";" : sep;\r
+\r
+       if (em)\r
+               addSelectValue(f, s, "", "");\r
+\r
+       ar = tinyMCEPopup.getParam(param, dval).split(sep);\r
+       for (i=0; i<ar.length; i++) {\r
+               se = false;\r
+\r
+               if (ar[i].charAt(0) == '+') {\r
+                       ar[i] = ar[i].substring(1);\r
+                       se = true;\r
+               }\r
+\r
+               p = ar[i].split('=');\r
+\r
+               if (p.length > 1) {\r
+                       addSelectValue(f, s, p[0], p[1]);\r
+\r
+                       if (se)\r
+                               selectByValue(f, s, p[1]);\r
+               } else {\r
+                       addSelectValue(f, s, p[0], p[0]);\r
+\r
+                       if (se)\r
+                               selectByValue(f, s, p[0]);\r
+               }\r
+       }\r
+}\r
+\r
+function toggleSame(ce, pre) {\r
+       var el = document.forms[0].elements, i;\r
+\r
+       if (ce.checked) {\r
+               el[pre + "_top"].disabled = false;\r
+               el[pre + "_right"].disabled = true;\r
+               el[pre + "_bottom"].disabled = true;\r
+               el[pre + "_left"].disabled = true;\r
+\r
+               if (el[pre + "_top_measurement"]) {\r
+                       el[pre + "_top_measurement"].disabled = false;\r
+                       el[pre + "_right_measurement"].disabled = true;\r
+                       el[pre + "_bottom_measurement"].disabled = true;\r
+                       el[pre + "_left_measurement"].disabled = true;\r
+               }\r
+       } else {\r
+               el[pre + "_top"].disabled = false;\r
+               el[pre + "_right"].disabled = false;\r
+               el[pre + "_bottom"].disabled = false;\r
+               el[pre + "_left"].disabled = false;\r
+\r
+               if (el[pre + "_top_measurement"]) {\r
+                       el[pre + "_top_measurement"].disabled = false;\r
+                       el[pre + "_right_measurement"].disabled = false;\r
+                       el[pre + "_bottom_measurement"].disabled = false;\r
+                       el[pre + "_left_measurement"].disabled = false;\r
+               }\r
+       }\r
+\r
+       showDisabledControls();\r
+}\r
+\r
+function synch(fr, to) {\r
+       var f = document.forms[0];\r
+\r
+       f.elements[to].value = f.elements[fr].value;\r
+\r
+       if (f.elements[fr + "_measurement"])\r
+               selectByValue(f, to + "_measurement", f.elements[fr + "_measurement"].value);\r
+}\r
+\r
+tinyMCEPopup.onInit.add(init);\r
diff --git a/jscripts/tiny_mce/plugins/style/langs/en_dlg.js b/jscripts/tiny_mce/plugins/style/langs/en_dlg.js
new file mode 100644 (file)
index 0000000..5026313
--- /dev/null
@@ -0,0 +1,63 @@
+tinyMCE.addI18n('en.style_dlg',{\r
+title:"Edit CSS Style",\r
+apply:"Apply",\r
+text_tab:"Text",\r
+background_tab:"Background",\r
+block_tab:"Block",\r
+box_tab:"Box",\r
+border_tab:"Border",\r
+list_tab:"List",\r
+positioning_tab:"Positioning",\r
+text_props:"Text",\r
+text_font:"Font",\r
+text_size:"Size",\r
+text_weight:"Weight",\r
+text_style:"Style",\r
+text_variant:"Variant",\r
+text_lineheight:"Line height",\r
+text_case:"Case",\r
+text_color:"Color",\r
+text_decoration:"Decoration",\r
+text_overline:"overline",\r
+text_underline:"underline",\r
+text_striketrough:"strikethrough",\r
+text_blink:"blink",\r
+text_none:"none",\r
+background_color:"Background color",\r
+background_image:"Background image",\r
+background_repeat:"Repeat",\r
+background_attachment:"Attachment",\r
+background_hpos:"Horizontal position",\r
+background_vpos:"Vertical position",\r
+block_wordspacing:"Word spacing",\r
+block_letterspacing:"Letter spacing",\r
+block_vertical_alignment:"Vertical alignment",\r
+block_text_align:"Text align",\r
+block_text_indent:"Text indent",\r
+block_whitespace:"Whitespace",\r
+block_display:"Display",\r
+box_width:"Width",\r
+box_height:"Height",\r
+box_float:"Float",\r
+box_clear:"Clear",\r
+padding:"Padding",\r
+same:"Same for all",\r
+top:"Top",\r
+right:"Right",\r
+bottom:"Bottom",\r
+left:"Left",\r
+margin:"Margin",\r
+style:"Style",\r
+width:"Width",\r
+height:"Height",\r
+color:"Color",\r
+list_type:"Type",\r
+bullet_image:"Bullet image",\r
+position:"Position",\r
+positioning_type:"Type",\r
+visibility:"Visibility",\r
+zindex:"Z-index",\r
+overflow:"Overflow",\r
+placement:"Placement",\r
+clip:"Clip"\r
+});
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/style/props.htm b/jscripts/tiny_mce/plugins/style/props.htm
new file mode 100644 (file)
index 0000000..23ff916
--- /dev/null
@@ -0,0 +1,731 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+       <title>{#style_dlg.title}</title>
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>
+       <script type="text/javascript" src="../../utils/editable_selects.js?v=307"></script>
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>
+       <script type="text/javascript" src="js/props.js?v=307"></script>
+       <link href="css/props.css?v=307" rel="stylesheet" type="text/css" />
+       <base target="_self" />
+</head>
+
+<body id="styleprops" style="display: none">
+<form onsubmit="updateAction();return false;" action="#">
+<div class="tabs">
+       <ul>
+               <li id="text_tab" class="current"><span><a href="javascript:mcTabs.displayTab('text_tab','text_panel');" onMouseDown="return false;">{#style_dlg.text_tab}</a></span></li>
+               <li id="background_tab"><span><a href="javascript:mcTabs.displayTab('background_tab','background_panel');" onMouseDown="return false;">{#style_dlg.background_tab}</a></span></li>
+               <li id="block_tab"><span><a href="javascript:mcTabs.displayTab('block_tab','block_panel');" onMouseDown="return false;">{#style_dlg.block_tab}</a></span></li>
+               <li id="box_tab"><span><a href="javascript:mcTabs.displayTab('box_tab','box_panel');" onMouseDown="return false;">{#style_dlg.box_tab}</a></span></li>
+               <li id="border_tab"><span><a href="javascript:mcTabs.displayTab('border_tab','border_panel');" onMouseDown="return false;">{#style_dlg.border_tab}</a></span></li>
+               <li id="list_tab"><span><a href="javascript:mcTabs.displayTab('list_tab','list_panel');" onMouseDown="return false;">{#style_dlg.list_tab}</a></span></li>
+               <li id="positioning_tab"><span><a href="javascript:mcTabs.displayTab('positioning_tab','positioning_panel');" onMouseDown="return false;">{#style_dlg.positioning_tab}</a></span></li>
+       </ul>
+</div>
+
+<div class="panel_wrapper">
+<div id="text_panel" class="panel current">
+       <table border="0" width="100%">
+               <tr>
+                       <td><label for="text_font">{#style_dlg.text_font}</label></td>
+                       <td colspan="3">
+                               <select id="text_font" name="text_font" class="mceEditableSelect mceFocus"></select>
+                       </td>
+               </tr>
+               <tr>
+                       <td><label for="text_size">{#style_dlg.text_size}</label></td>
+                       <td>
+                               <table border="0" cellspacing="0" cellpadding="0">
+                                       <tr>
+                                               <td><select id="text_size" name="text_size" class="mceEditableSelect"></select></td>
+                                               <td>&nbsp;</td>
+      <td><select id="text_size_measurement" name="text_size_measurement"></select></td>
+                                       </tr>
+                               </table>
+                       </td>
+                       <td><label for="text_weight">{#style_dlg.text_weight}</label></td>
+                       <td>
+                               <select id="text_weight" name="text_weight"></select>
+                       </td>
+               </tr>
+               <tr>
+                       <td><label for="text_style">{#style_dlg.text_style}</label></td>
+                       <td>
+                               <select id="text_style" name="text_style" class="mceEditableSelect"></select>
+                       </td>
+                       <td><label for="text_variant">{#style_dlg.text_variant}</label></td>
+                       <td>
+                               <select id="text_variant" name="text_variant"></select>
+                       </td>
+               </tr>
+               <tr>
+                       <td><label for="text_lineheight">{#style_dlg.text_lineheight}</label></td>
+                       <td>
+                               <table border="0" cellspacing="0" cellpadding="0">
+                                       <tr>
+                                               <td>
+                                                       <select id="text_lineheight" name="text_lineheight" class="mceEditableSelect"></select>
+                                               </td>
+                                               <td>&nbsp;</td>
+                                               <td><select id="text_lineheight_measurement" name="text_lineheight_measurement"></select></td>
+                                       </tr>
+                               </table>
+                       </td>
+                       <td><label for="text_case">{#style_dlg.text_case}</label></td>
+                       <td>
+                               <select id="text_case" name="text_case"></select>
+                       </td>
+               </tr>
+               <tr>
+                       <td><label for="text_color">{#style_dlg.text_color}</label></td>
+                       <td colspan="2">
+                               <table border="0" cellpadding="0" cellspacing="0">
+                                       <tr>
+                                               <td><input id="text_color" name="text_color" type="text" value="" size="9" onChange="updateColor('text_color_pick','text_color');" /></td>
+                                               <td id="text_color_pickcontainer">&nbsp;</td>
+                                       </tr>
+                               </table>
+                       </td>
+               </tr>
+               <tr>
+                       <td valign="top" style="vertical-align: top; padding-top: 3px;">{#style_dlg.text_decoration}</td>
+                       <td colspan="2">
+                               <table border="0" cellspacing="0" cellpadding="0">
+                                       <tr>
+                                               <td><input id="text_underline" name="text_underline" class="checkbox" type="checkbox" /></td>
+                                               <td><label for="text_underline">{#style_dlg.text_underline}</label></td>
+                                       </tr>
+                                       <tr>
+                                               <td><input id="text_overline" name="text_overline" class="checkbox" type="checkbox" /></td>
+                                               <td><label for="text_overline">{#style_dlg.text_overline}</label></td>
+                                       </tr>
+                                       <tr>
+                                               <td><input id="text_linethrough" name="text_linethrough" class="checkbox" type="checkbox" /></td>
+                                               <td><label for="text_linethrough">{#style_dlg.text_striketrough}</label></td>
+                                       </tr>
+                                       <tr>
+                                               <td><input id="text_blink" name="text_blink" class="checkbox" type="checkbox" /></td>
+                                               <td><label for="text_blink">{#style_dlg.text_blink}</label></td>
+                                       </tr>
+                                       <tr>
+                                               <td><input id="text_none" name="text_none" class="checkbox" type="checkbox" /></td>
+                                               <td><label for="text_none">{#style_dlg.text_none}</label></td>
+                                       </tr>
+                               </table>
+                       </td>
+               </tr>
+       </table>
+</div>
+
+<div id="background_panel" class="panel">
+       <table border="0">
+               <tr>
+                       <td><label for="background_color">{#style_dlg.background_color}</label></td>
+                       <td>
+                               <table border="0" cellpadding="0" cellspacing="0">
+                                       <tr>
+                                               <td><input id="background_color" name="background_color" type="text" value="" size="9" onChange="updateColor('background_color_pick','background_color');" /></td>
+                                               <td id="background_color_pickcontainer">&nbsp;</td>
+                                       </tr>
+                               </table>
+                       </td>
+               </tr>
+
+               <tr>
+                       <td><label for="background_image">{#style_dlg.background_image}</label></td>
+                       <td><table border="0" cellspacing="0" cellpadding="0">
+                               <tr> 
+                                 <td><input id="background_image" name="background_image" type="text" /></td> 
+                                 <td id="background_image_browser">&nbsp;</td>
+                               </tr>
+                               </table>
+                       </td>
+               </tr>
+
+               <tr>
+                       <td><label for="background_repeat">{#style_dlg.background_repeat}</label></td>
+                       <td><select id="background_repeat" name="background_repeat" class="mceEditableSelect"></select></td>
+               </tr>
+
+               <tr>
+                       <td><label for="background_attachment">{#style_dlg.background_attachment}</label></td>
+                       <td><select id="background_attachment" name="background_attachment" class="mceEditableSelect"></select></td>
+               </tr>
+
+               <tr>
+                       <td><label for="background_hpos">{#style_dlg.background_hpos}</label></td>
+                       <td>
+                               <table border="0" cellspacing="0" cellpadding="0">
+                                       <tr>
+                                               <td><select id="background_hpos" name="background_hpos" class="mceEditableSelect"></select></td>
+                                               <td>&nbsp;</td>
+                                               <td><select id="background_hpos_measurement" name="background_hpos_measurement"></select></td>
+                                       </tr>
+                               </table>
+                       </td>
+               </tr>
+
+               <tr>
+                       <td><label for="background_vpos">{#style_dlg.background_vpos}</label></td>
+                       <td>
+                               <table border="0" cellspacing="0" cellpadding="0">
+                                       <tr>
+                                               <td><select id="background_vpos" name="background_vpos" class="mceEditableSelect"></select></td>
+                                               <td>&nbsp;</td>
+                                               <td><select id="background_vpos_measurement" name="background_vpos_measurement"></select></td>
+                                       </tr>
+                               </table>
+                       </td>
+               </tr>
+       </table>
+</div>
+
+<div id="block_panel" class="panel">
+       <table border="0">
+               <tr>
+                       <td><label for="block_wordspacing">{#style_dlg.block_wordspacing}</label></td>
+                       <td>
+                               <table border="0" cellspacing="0" cellpadding="0">
+                                       <tr>
+                                               <td><select id="block_wordspacing" name="block_wordspacing" class="mceEditableSelect"></select></td>
+                                               <td>&nbsp;</td>
+                                               <td><select id="block_wordspacing_measurement" name="block_wordspacing_measurement"></select></td>
+                                       </tr>
+                               </table>
+                       </td>
+               </tr>
+
+               <tr>
+                       <td><label for="block_letterspacing">{#style_dlg.block_letterspacing}</label></td>
+                       <td>
+                               <table border="0" cellspacing="0" cellpadding="0">
+                                       <tr>
+                                               <td><select id="block_letterspacing" name="block_letterspacing" class="mceEditableSelect"></select></td>
+                                               <td>&nbsp;</td>
+                                               <td><select id="block_letterspacing_measurement" name="block_letterspacing_measurement"></select></td>
+                                       </tr>
+                               </table>
+                       </td>
+               </tr>
+
+               <tr>
+                       <td><label for="block_vertical_alignment">{#style_dlg.block_vertical_alignment}</label></td>
+                       <td><select id="block_vertical_alignment" name="block_vertical_alignment" class="mceEditableSelect"></select></td>
+               </tr>
+
+               <tr>
+                       <td><label for="block_text_align">{#style_dlg.block_text_align}</label></td>
+                       <td><select id="block_text_align" name="block_text_align" class="mceEditableSelect"></select></td>
+               </tr>
+
+               <tr>
+                       <td><label for="block_text_indent">{#style_dlg.block_text_indent}</label></td>
+                       <td>
+                               <table border="0" cellspacing="0" cellpadding="0">
+                                       <tr>
+                                               <td><input type="text" id="block_text_indent" name="block_text_indent" /></td>
+                                               <td>&nbsp;</td>
+                                               <td><select id="block_text_indent_measurement" name="block_text_indent_measurement"></select></td>
+                                       </tr>
+                               </table>
+                       </td>
+               </tr>
+
+               <tr>
+                       <td><label for="block_whitespace">{#style_dlg.block_whitespace}</label></td>
+                       <td><select id="block_whitespace" name="block_whitespace" class="mceEditableSelect"></select></td>
+               </tr>
+
+               <tr>
+                       <td><label for="block_display">{#style_dlg.block_display}</label></td>
+                       <td><select id="block_display" name="block_display" class="mceEditableSelect"></select></td>
+               </tr>
+       </table>
+</div>
+
+<div id="box_panel" class="panel">
+<table border="0">
+       <tr>
+               <td><label for="box_width">{#style_dlg.box_width}</label></td>
+               <td>
+                       <table border="0" cellspacing="0" cellpadding="0">
+                               <tr>
+                                       <td><input type="text" id="box_width" name="box_width" class="mceEditableSelect" onChange="synch('box_width','positioning_width');" /></td>
+                                       <td>&nbsp;</td>
+                                       <td><select id="box_width_measurement" name="box_width_measurement"></select></td>
+                               </tr>
+                       </table>
+               </td>
+               <td>&nbsp;&nbsp;&nbsp;<label for="box_float">{#style_dlg.box_float}</label></td>
+               <td><select id="box_float" name="box_float" class="mceEditableSelect"></select></td>
+       </tr>
+
+       <tr>
+               <td><label for="box_height">{#style_dlg.box_height}</label></td>
+               <td>
+                       <table border="0" cellspacing="0" cellpadding="0">
+                               <tr>
+                                       <td><input type="text" id="box_height" name="box_height" class="mceEditableSelect" onChange="synch('box_height','positioning_height');" /></td>
+                                       <td>&nbsp;</td>
+                                       <td><select id="box_height_measurement" name="box_height_measurement"></select></td>
+                               </tr>
+                       </table>
+               </td>
+               <td>&nbsp;&nbsp;&nbsp;<label for="box_clear">{#style_dlg.box_clear}</label></td>
+               <td><select id="box_clear" name="box_clear" class="mceEditableSelect"></select></td>
+       </tr>
+</table>
+<div style="float: left; width: 49%">
+       <fieldset>
+               <legend>{#style_dlg.padding}</legend>
+
+               <table border="0">
+                       <tr>
+                               <td>&nbsp;</td>
+                               <td><input type="checkbox" id="box_padding_same" name="box_padding_same" class="checkbox" checked="checked" onClick="toggleSame(this,'box_padding');" /> <label for="box_padding_same">{#style_dlg.same}</label></td>
+                       </tr>
+                       <tr>
+                               <td><label for="box_padding_top">{#style_dlg.top}</label></td>
+                               <td>
+                                       <table border="0" cellspacing="0" cellpadding="0">
+                                               <tr>
+                                                       <td><input type="text" id="box_padding_top" name="box_padding_top" class="mceEditableSelect" /></td>
+                                                       <td>&nbsp;</td>
+                                                       <td><select id="box_padding_top_measurement" name="box_padding_top_measurement"></select></td>
+                                               </tr>
+                                       </table>
+                               </td>
+                       </tr>
+                       <tr>
+                               <td><label for="box_padding_right">{#style_dlg.right}</label></td>
+                               <td>
+                                       <table border="0" cellspacing="0" cellpadding="0">
+                                               <tr>
+                                                       <td><input type="text" id="box_padding_right" name="box_padding_right" class="mceEditableSelect" disabled="disabled" /></td>
+                                                       <td>&nbsp;</td>
+                                                       <td><select id="box_padding_right_measurement" name="box_padding_right_measurement" disabled="disabled"></select></td>
+                                               </tr>
+                                       </table>
+                               </td>
+                       </tr>
+                       <tr>
+                               <td><label for="box_padding_bottom">{#style_dlg.bottom}</label></td>
+                               <td>
+                                       <table border="0" cellspacing="0" cellpadding="0">
+                                               <tr>
+                                                       <td><input type="text" id="box_padding_bottom" name="box_padding_bottom" class="mceEditableSelect" disabled="disabled" /></td>
+                                                       <td>&nbsp;</td>
+                                                       <td><select id="box_padding_bottom_measurement" name="box_padding_bottom_measurement" disabled="disabled"></select></td>
+                                               </tr>
+                                       </table>
+                               </td>
+                       </tr>
+                       <tr>
+                               <td><label for="box_padding_left">{#style_dlg.left}</label></td>
+                               <td>
+                                       <table border="0" cellspacing="0" cellpadding="0">
+                                               <tr>
+                                                       <td><input type="text" id="box_padding_left" name="box_padding_left" class="mceEditableSelect" disabled="disabled" /></td>
+                                                       <td>&nbsp;</td>
+                                                       <td><select id="box_padding_left_measurement" name="box_padding_left_measurement" disabled="disabled"></select></td>
+                                               </tr>
+                                       </table>
+                               </td>
+                       </tr>
+               </table>
+       </fieldset>
+</div>
+
+<div style="float: right; width: 49%">
+       <fieldset>
+               <legend>{#style_dlg.margin}</legend>
+
+               <table border="0">
+                       <tr>
+                               <td>&nbsp;</td>
+                               <td><input type="checkbox" id="box_margin_same" name="box_margin_same" class="checkbox" checked="checked" onClick="toggleSame(this,'box_margin');" /> <label for="box_margin_same">{#style_dlg.same}</label></td>
+                       </tr>
+                       <tr>
+                               <td><label for="box_margin_top">{#style_dlg.top}</label></td>
+                               <td>
+                                       <table border="0" cellspacing="0" cellpadding="0">
+                                               <tr>
+                                                       <td><input type="text" id="box_margin_top" name="box_margin_top" class="mceEditableSelect" /></td>
+                                                       <td>&nbsp;</td>
+                                                       <td><select id="box_margin_top_measurement" name="box_margin_top_measurement"></select></td>
+                                               </tr>
+                                       </table>
+                               </td>
+                       </tr>
+                       <tr>
+                               <td><label for="box_margin_right">{#style_dlg.right}</label></td>
+                               <td>
+                                       <table border="0" cellspacing="0" cellpadding="0">
+                                               <tr>
+                                                       <td><input type="text" id="box_margin_right" name="box_margin_right" class="mceEditableSelect" disabled="disabled" /></td>
+                                                       <td>&nbsp;</td>
+                                                       <td><select id="box_margin_right_measurement" name="box_margin_right_measurement" disabled="disabled"></select></td>
+                                               </tr>
+                                       </table>
+                               </td>
+                       </tr>
+                       <tr>
+                               <td><label for="box_margin_bottom">{#style_dlg.bottom}</label></td>
+                               <td>
+                                       <table border="0" cellspacing="0" cellpadding="0">
+                                               <tr>
+                                                       <td><input type="text" id="box_margin_bottom" name="box_margin_bottom" class="mceEditableSelect" disabled="disabled" /></td>
+                                                       <td>&nbsp;</td>
+                                                       <td><select id="box_margin_bottom_measurement" name="box_margin_bottom_measurement" disabled="disabled"></select></td>
+                                               </tr>
+                                       </table>
+                               </td>
+                       </tr>
+                       <tr>
+                               <td><label for="box_margin_left">{#style_dlg.left}</label></td>
+                               <td>
+                                       <table border="0" cellspacing="0" cellpadding="0">
+                                               <tr>
+                                                       <td><input type="text" id="box_margin_left" name="box_margin_left" class="mceEditableSelect" disabled="disabled" /></td>
+                                                       <td>&nbsp;</td>
+                                                       <td><select id="box_margin_left_measurement" name="box_margin_left_measurement" disabled="disabled"></select></td>
+                                               </tr>
+                                       </table>
+                               </td>
+                       </tr>
+               </table>
+       </fieldset>
+</div>
+<br style="clear: both" />
+</div>
+
+<div id="border_panel" class="panel">
+<table border="0" cellspacing="0" cellpadding="0" width="100%">
+<tr>
+       <td class="tdelim">&nbsp;</td>
+       <td class="tdelim delim">&nbsp;</td>
+       <td class="tdelim">{#style_dlg.style}</td>
+       <td class="tdelim delim">&nbsp;</td>
+       <td class="tdelim">{#style_dlg.width}</td>
+       <td class="tdelim delim">&nbsp;</td>
+       <td class="tdelim">{#style_dlg.color}</td>
+</tr>
+
+<tr>
+       <td>&nbsp;</td>
+       <td class="delim">&nbsp;</td>
+       <td><input type="checkbox" id="border_style_same" name="border_style_same" class="checkbox" checked="checked" onClick="toggleSame(this,'border_style');" /> <label for="border_style_same">{#style_dlg.same}</label></td>
+       <td class="delim">&nbsp;</td>
+       <td><input type="checkbox" id="border_width_same" name="border_width_same" class="checkbox" checked="checked" onClick="toggleSame(this,'border_width');" /> <label for="border_width_same">{#style_dlg.same}</label></td>
+       <td class="delim">&nbsp;</td>
+       <td><input type="checkbox" id="border_color_same" name="border_color_same" class="checkbox" checked="checked" onClick="toggleSame(this,'border_color');" /> <label for="border_color_same">{#style_dlg.same}</label></td>
+</tr>
+
+<tr>
+       <td>{#style_dlg.top}</td>
+       <td class="delim">&nbsp;</td>
+       <td><select id="border_style_top" name="border_style_top" class="mceEditableSelect"></select></td>
+       <td class="delim">&nbsp;</td>
+       <td>
+               <table border="0" cellspacing="0" cellpadding="0">
+                       <tr>
+                               <td><select id="border_width_top" name="border_width_top" class="mceEditableSelect"></select></td>
+                               <td>&nbsp;</td>
+                               <td><select id="border_width_top_measurement" name="border_width_top_measurement"></select></td>
+                       </tr>
+               </table>
+       </td>
+       <td class="delim">&nbsp;</td>
+       <td>
+               <table border="0" cellpadding="0" cellspacing="0">
+                       <tr>
+                               <td><input id="border_color_top" name="border_color_top" type="text" value="" size="9" onChange="updateColor('border_color_top_pick','border_color_top');" /></td>
+                               <td id="border_color_top_pickcontainer">&nbsp;</td>
+                       </tr>
+               </table>
+       </td>
+</tr>
+
+<tr>
+       <td>{#style_dlg.right}</td>
+       <td class="delim">&nbsp;</td>
+       <td><select id="border_style_right" name="border_style_right" class="mceEditableSelect" disabled="disabled"></select></td>
+       <td class="delim">&nbsp;</td>
+       <td>
+               <table border="0" cellspacing="0" cellpadding="0">
+                       <tr>
+                               <td><select id="border_width_right" name="border_width_right" class="mceEditableSelect" disabled="disabled"></select></td>
+                               <td>&nbsp;</td>
+                               <td><select id="border_width_right_measurement" name="border_width_right_measurement" disabled="disabled"></select></td>
+                       </tr>
+               </table>
+       </td>
+       <td class="delim">&nbsp;</td>
+       <td>
+               <table border="0" cellpadding="0" cellspacing="0">
+                       <tr>
+                               <td><input id="border_color_right" name="border_color_right" type="text" value="" size="9" onChange="updateColor('border_color_right_pick','border_color_right');" disabled="disabled" /></td>
+                               <td id="border_color_right_pickcontainer">&nbsp;</td>
+                       </tr>
+               </table>
+       </td>
+</tr>
+
+<tr>
+       <td>{#style_dlg.bottom}</td>
+       <td class="delim">&nbsp;</td>
+       <td><select id="border_style_bottom" name="border_style_bottom" class="mceEditableSelect" disabled="disabled"></select></td>
+       <td class="delim">&nbsp;</td>
+       <td>
+               <table border="0" cellspacing="0" cellpadding="0">
+                       <tr>
+                               <td><select id="border_width_bottom" name="border_width_bottom" class="mceEditableSelect" disabled="disabled"></select></td>
+                               <td>&nbsp;</td>
+                               <td><select id="border_width_bottom_measurement" name="border_width_bottom_measurement" disabled="disabled"></select></td>
+                       </tr>
+               </table>
+       </td>
+       <td class="delim">&nbsp;</td>
+       <td>
+               <table border="0" cellpadding="0" cellspacing="0">
+                       <tr>
+                               <td><input id="border_color_bottom" name="border_color_bottom" type="text" value="" size="9" onChange="updateColor('border_color_bottom_pick','border_color_bottom');" disabled="disabled" /></td>
+                               <td id="border_color_bottom_pickcontainer">&nbsp;</td>
+                       </tr>
+               </table>
+       </td>
+</tr>
+
+<tr>
+       <td>{#style_dlg.left}</td>
+       <td class="delim">&nbsp;</td>
+       <td><select id="border_style_left" name="border_style_left" class="mceEditableSelect" disabled="disabled"></select></td>
+       <td class="delim">&nbsp;</td>
+       <td>
+               <table border="0" cellspacing="0" cellpadding="0">
+                       <tr>
+                               <td><select id="border_width_left" name="border_width_left" class="mceEditableSelect" disabled="disabled"></select></td>
+                               <td>&nbsp;</td>
+                               <td><select id="border_width_left_measurement" name="border_width_left_measurement" disabled="disabled"></select></td>
+                       </tr>
+               </table>
+       </td>
+       <td class="delim">&nbsp;</td>
+       <td>
+               <table border="0" cellpadding="0" cellspacing="0">
+                       <tr>
+                               <td><input id="border_color_left" name="border_color_left" type="text" value="" size="9" onChange="updateColor('border_color_left_pick','border_color_left');" disabled="disabled" /></td>
+                               <td id="border_color_left_pickcontainer">&nbsp;</td>
+                       </tr>
+               </table>
+       </td>
+</tr>
+</table>
+</div>
+
+<div id="list_panel" class="panel">
+       <table border="0">
+               <tr>
+                       <td><label for="list_type">{#style_dlg.list_type}</label></td>
+                       <td><select id="list_type" name="list_type" class="mceEditableSelect"></select></td>
+               </tr>
+
+               <tr>
+                       <td><label for="list_bullet_image">{#style_dlg.bullet_image}</label></td>
+                       <td><input id="list_bullet_image" name="list_bullet_image" type="text" /></td>
+               </tr>
+
+               <tr>
+                       <td><label for="list_position">{#style_dlg.position}</label></td>
+                       <td><select id="list_position" name="list_position" class="mceEditableSelect"></select></td>
+               </tr>
+       </table>
+</div>
+
+<div id="positioning_panel" class="panel">
+<table border="0">
+       <tr>
+               <td><label for="positioning_type">{#style_dlg.positioning_type}</label></td>
+               <td><select id="positioning_type" name="positioning_type" class="mceEditableSelect"></select></td>
+               <td>&nbsp;&nbsp;&nbsp;<label for="positioning_visibility">{#style_dlg.visibility}</label></td>
+               <td><select id="positioning_visibility" name="positioning_visibility" class="mceEditableSelect"></select></td>
+       </tr>
+
+       <tr>
+               <td><label for="positioning_width">{#style_dlg.width}</label></td>
+               <td>
+                       <table border="0" cellspacing="0" cellpadding="0">
+                               <tr>
+                                       <td><input type="text" id="positioning_width" name="positioning_width" onChange="synch('positioning_width','box_width');" /></td>
+                                       <td>&nbsp;</td>
+                                       <td><select id="positioning_width_measurement" name="positioning_width_measurement"></select></td>
+                               </tr>
+                       </table>
+               </td>
+               <td>&nbsp;&nbsp;&nbsp;<label for="positioning_zindex">{#style_dlg.zindex}</label></td>
+               <td><input type="text" id="positioning_zindex" name="positioning_zindex" /></td>
+       </tr>
+
+       <tr>
+               <td><label for="positioning_height">{#style_dlg.height}</label></td>
+               <td>
+                       <table border="0" cellspacing="0" cellpadding="0">
+                               <tr>
+                                       <td><input type="text" id="positioning_height" name="positioning_height" onChange="synch('positioning_height','box_height');" /></td>
+                                       <td>&nbsp;</td>
+                                       <td><select id="positioning_height_measurement" name="positioning_height_measurement"></select></td>
+                               </tr>
+                       </table>
+               </td>
+               <td>&nbsp;&nbsp;&nbsp;<label for="positioning_overflow">{#style_dlg.overflow}</label></td>
+               <td><select id="positioning_overflow" name="positioning_overflow" class="mceEditableSelect"></select></td>
+       </tr>
+</table>
+
+<div style="float: left; width: 49%">
+       <fieldset>
+               <legend>{#style_dlg.placement}</legend>
+
+               <table border="0">
+                       <tr>
+                               <td>&nbsp;</td>
+                               <td><input type="checkbox" id="positioning_placement_same" name="positioning_placement_same" class="checkbox" checked="checked" onClick="toggleSame(this,'positioning_placement');" /> <label for="positioning_placement_same">{#style_dlg.same}</label></td>
+                       </tr>
+                       <tr>
+                               <td>{#style_dlg.top}</td>
+                               <td>
+                                       <table border="0" cellspacing="0" cellpadding="0">
+                                               <tr>
+                                                       <td><input type="text" id="positioning_placement_top" name="positioning_placement_top" /></td>
+                                                       <td>&nbsp;</td>
+                                                       <td><select id="positioning_placement_top_measurement" name="positioning_placement_top_measurement"></select></td>
+                                               </tr>
+                                       </table>
+                               </td>
+                       </tr>
+                       <tr>
+                               <td>{#style_dlg.right}</td>
+                               <td>
+                                       <table border="0" cellspacing="0" cellpadding="0">
+                                               <tr>
+                                                       <td><input type="text" id="positioning_placement_right" name="positioning_placement_right" disabled="disabled" /></td>
+                                                       <td>&nbsp;</td>
+                                                       <td><select id="positioning_placement_right_measurement" name="positioning_placement_right_measurement" disabled="disabled"></select></td>
+                                               </tr>
+                                       </table>
+                               </td>
+                       </tr>
+                       <tr>
+                               <td>{#style_dlg.bottom}</td>
+                               <td>
+                                       <table border="0" cellspacing="0" cellpadding="0">
+                                               <tr>
+                                                       <td><input type="text" id="positioning_placement_bottom" name="positioning_placement_bottom" disabled="disabled" /></td>
+                                                       <td>&nbsp;</td>
+                                                       <td><select id="positioning_placement_bottom_measurement" name="positioning_placement_bottom_measurement" disabled="disabled"></select></td>
+                                               </tr>
+                                       </table>
+                               </td>
+                       </tr>
+                       <tr>
+                               <td>{#style_dlg.left}</td>
+                               <td>
+                                       <table border="0" cellspacing="0" cellpadding="0">
+                                               <tr>
+                                                       <td><input type="text" id="positioning_placement_left" name="positioning_placement_left" disabled="disabled" /></td>
+                                                       <td>&nbsp;</td>
+                                                       <td><select id="positioning_placement_left_measurement" name="positioning_placement_left_measurement" disabled="disabled"></select></td>
+                                               </tr>
+                                       </table>
+                               </td>
+                       </tr>
+               </table>
+       </fieldset>
+</div>
+
+<div style="float: right; width: 49%">
+       <fieldset>
+               <legend>{#style_dlg.clip}</legend>
+
+               <table border="0">
+                       <tr>
+                               <td>&nbsp;</td>
+                               <td><input type="checkbox" id="positioning_clip_same" name="positioning_clip_same" class="checkbox" checked="checked" onClick="toggleSame(this,'positioning_clip');" /> <label for="positioning_clip_same">{#style_dlg.same}</label></td>
+                       </tr>
+                       <tr>
+                               <td>{#style_dlg.top}</td>
+                               <td>
+                                       <table border="0" cellspacing="0" cellpadding="0">
+                                               <tr>
+                                                       <td><input type="text" id="positioning_clip_top" name="positioning_clip_top" /></td>
+                                                       <td>&nbsp;</td>
+                                                       <td><select id="positioning_clip_top_measurement" name="positioning_clip_top_measurement"></select></td>
+                                               </tr>
+                                       </table>
+                               </td>
+                       </tr>
+                       <tr>
+                               <td>{#style_dlg.right}</td>
+                               <td>
+                                       <table border="0" cellspacing="0" cellpadding="0">
+                                               <tr>
+                                                       <td><input type="text" id="positioning_clip_right" name="positioning_clip_right" disabled="disabled" /></td>
+                                                       <td>&nbsp;</td>
+                                                       <td><select id="positioning_clip_right_measurement" name="positioning_clip_right_measurement" disabled="disabled"></select></td>
+                                               </tr>
+                                       </table>
+                               </td>
+                       </tr>
+                       <tr>
+                               <td>{#style_dlg.bottom}</td>
+                               <td>
+                                       <table border="0" cellspacing="0" cellpadding="0">
+                                               <tr>
+                                                       <td><input type="text" id="positioning_clip_bottom" name="positioning_clip_bottom" disabled="disabled" /></td>
+                                                       <td>&nbsp;</td>
+                                                       <td><select id="positioning_clip_bottom_measurement" name="positioning_clip_bottom_measurement" disabled="disabled"></select></td>
+                                               </tr>
+                                       </table>
+                               </td>
+                       </tr>
+                       <tr>
+                               <td>{#style_dlg.left}</td>
+                               <td>
+                                       <table border="0" cellspacing="0" cellpadding="0">
+                                               <tr>
+                                                       <td><input type="text" id="positioning_clip_left" name="positioning_clip_left" disabled="disabled" /></td>
+                                                       <td>&nbsp;</td>
+                                                       <td><select id="positioning_clip_left_measurement" name="positioning_clip_left_measurement" disabled="disabled"></select></td>
+                                               </tr>
+                                       </table>
+                               </td>
+                       </tr>
+               </table>
+       </fieldset>
+</div>
+<br style="clear: both" />
+</div>
+</div>
+
+<div class="mceActionPanel">
+       <div style="float: left">
+               <div style="float: left"><input type="submit" id="insert" name="insert" value="{#update}" /></div>
+
+               <div style="float: left">&nbsp;<input type="button" class="button" id="apply" name="apply" value="{#style_dlg.apply}" onClick="applyAction();" /></div>
+               <br style="clear: both" />
+       </div>
+
+       <div style="float: right">
+               <input type="button" id="cancel" name="cancel" value="{#cancel}" onClick="tinyMCEPopup.close();" />
+       </div>
+</div>
+</form>
+
+<div style="display: none">
+       <div id="container"></div>
+</div>
+
+</body>
+</html>
diff --git a/jscripts/tiny_mce/plugins/table/cell.htm b/jscripts/tiny_mce/plugins/table/cell.htm
new file mode 100644 (file)
index 0000000..abf8577
--- /dev/null
@@ -0,0 +1,184 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#table_dlg.cell_title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/editable_selects.js?v=307"></script>\r
+       <script type="text/javascript" src="js/cell.js?v=307"></script>\r
+       <link href="css/cell.css?v=307" rel="stylesheet" type="text/css" />\r
+       <base target="_self" />\r
+</head>\r
+<body id="tablecell" style="display: none">\r
+       <form onsubmit="updateAction();return false;" action="#">\r
+               <div class="tabs">\r
+                       <ul>\r
+                               <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#table_dlg.general_tab}</a></span></li>\r
+                               <li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#table_dlg.advanced_tab}</a></span></li>\r
+                       </ul>\r
+               </div>\r
+\r
+               <div class="panel_wrapper">\r
+                       <div id="general_panel" class="panel current">\r
+                               <fieldset>\r
+                                       <legend>{#table_dlg.general_props}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td><label for="align">{#table_dlg.align}</label></td>\r
+                                                       <td>\r
+                                                               <select id="align" name="align" class="mceFocus">\r
+                                                                       <option value="">{#not_set}</option>\r
+                                                                       <option value="center">{#table_dlg.align_middle}</option>\r
+                                                                       <option value="left">{#table_dlg.align_left}</option>\r
+                                                                       <option value="right">{#table_dlg.align_right}</option>\r
+                                                               </select>\r
+                                                       </td>\r
+               \r
+                                                       <td><label for="celltype">{#table_dlg.cell_type}</label></td>\r
+                                                       <td>\r
+                                                               <select id="celltype" name="celltype">\r
+                                                                       <option value="td">{#table_dlg.td}</option>\r
+                                                                       <option value="th">{#table_dlg.th}</option>\r
+                                                               </select>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="valign">{#table_dlg.valign}</label></td>\r
+                                                       <td>\r
+                                                               <select id="valign" name="valign">\r
+                                                                       <option value="">{#not_set}</option>\r
+                                                                       <option value="top">{#table_dlg.align_top}</option>\r
+                                                                       <option value="middle">{#table_dlg.align_middle}</option>\r
+                                                                       <option value="bottom">{#table_dlg.align_bottom}</option>\r
+                                                               </select>\r
+                                                       </td>\r
+\r
+                                                       <td><label for="scope">{#table_dlg.scope}</label></td>\r
+                                                       <td>\r
+                                                               <select id="scope" name="scope">\r
+                                                                       <option value="">{#not_set}</option>\r
+                                                                       <option value="col">{#table.col}</option>\r
+                                                                       <option value="row">{#table.row}</option>\r
+                                                                       <option value="rowgroup">{#table_dlg.rowgroup}</option>\r
+                                                                       <option value="colgroup">{#table_dlg.colgroup}</option>\r
+                                                               </select>\r
+                                                       </td>\r
+\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="width">{#table_dlg.width}</label></td>\r
+                                                       <td><input id="width" name="width" type="text" value="" size="4" maxlength="4" onchange="changedSize();" /></td>\r
+\r
+                                                       <td><label for="height">{#table_dlg.height}</label></td>\r
+                                                       <td><input id="height" name="height" type="text" value="" size="4" maxlength="4" onchange="changedSize();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr id="styleSelectRow">\r
+                                                       <td><label for="class">{#class_name}</label></td>\r
+                                                       <td colspan="3">\r
+                                                               <select id="class" name="class" class="mceEditableSelect">\r
+                                                                       <option value="" selected="selected">{#not_set}</option>\r
+                                                               </select>\r
+                                                       </td>\r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+                       </div>\r
+\r
+                       <div id="advanced_panel" class="panel">\r
+                               <fieldset>\r
+                                       <legend>{#table_dlg.advanced_props}</legend>\r
+\r
+                                       <table border="0" cellpadding="0" cellspacing="4">\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="id">{#table_dlg.id}</label></td> \r
+                                                       <td><input id="id" name="id" type="text" value="" style="width: 200px" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="style">{#table_dlg.style}</label></td>\r
+                                                       <td><input type="text" id="style" name="style" value="" style="width: 200px;" onchange="changedStyle();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="dir">{#table_dlg.langdir}</label></td> \r
+                                                       <td>\r
+                                                               <select id="dir" name="dir" style="width: 200px"> \r
+                                                                               <option value="">{#not_set}</option> \r
+                                                                               <option value="ltr">{#table_dlg.ltr}</option> \r
+                                                                               <option value="rtl">{#table_dlg.rtl}</option> \r
+                                                               </select>\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="lang">{#table_dlg.langcode}</label></td> \r
+                                                       <td>\r
+                                                               <input id="lang" name="lang" type="text" value="" style="width: 200px" />\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="backgroundimage">{#table_dlg.bgimage}</label></td> \r
+                                                       <td>\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="backgroundimage" name="backgroundimage" type="text" value="" style="width: 200px" onchange="changedBackgroundImage();" /></td>\r
+                                                                               <td id="backgroundimagebrowsercontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="bordercolor">{#table_dlg.bordercolor}</label></td> \r
+                                                       <td>\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="bordercolor" name="bordercolor" type="text" value="" size="9" onchange="updateColor('bordercolor_pick','bordercolor');changedColor();" /></td>\r
+                                                                               <td id="bordercolor_pickcontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="bgcolor">{#table_dlg.bgcolor}</label></td> \r
+                                                       <td>\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="bgcolor" name="bgcolor" type="text" value="" size="9" onchange="updateColor('bgcolor_pick','bgcolor');changedColor();" /></td>\r
+                                                                               <td id="bgcolor_pickcontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td> \r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+                       </div>\r
+               </div>\r
+\r
+               <div class="mceActionPanel">\r
+                       <div>\r
+                               <select id="action" name="action">\r
+                                       <option value="cell">{#table_dlg.cell_cell}</option>\r
+                                       <option value="row">{#table_dlg.cell_row}</option>\r
+                                       <option value="all">{#table_dlg.cell_all}</option>\r
+                               </select>\r
+                       </div>\r
+\r
+                       <div style="float: left">\r
+                               <div><input type="submit" id="insert" name="insert" value="{#update}" /></div>\r
+                       </div>\r
+\r
+                       <div style="float: right">\r
+                               <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+                       </div>\r
+               </div>\r
+       </form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/table/css/cell.css b/jscripts/tiny_mce/plugins/table/css/cell.css
new file mode 100644 (file)
index 0000000..a067ecd
--- /dev/null
@@ -0,0 +1,17 @@
+/* CSS file for cell dialog in the table plugin */\r
+\r
+.panel_wrapper div.current {\r
+       height: 200px;\r
+}\r
+\r
+.advfield {\r
+       width: 200px;\r
+}\r
+\r
+#action {\r
+       margin-bottom: 3px;\r
+}\r
+\r
+#class {\r
+       width: 150px;\r
+}
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/table/css/row.css b/jscripts/tiny_mce/plugins/table/css/row.css
new file mode 100644 (file)
index 0000000..1f7755d
--- /dev/null
@@ -0,0 +1,25 @@
+/* CSS file for row dialog in the table plugin */\r
+\r
+.panel_wrapper div.current {\r
+       height: 200px;\r
+}\r
+\r
+.advfield {\r
+       width: 200px;\r
+}\r
+\r
+#action {\r
+       margin-bottom: 3px;\r
+}\r
+\r
+#rowtype,#align,#valign,#class,#height {\r
+       width: 150px;\r
+}\r
+\r
+#height {\r
+       width: 50px;    \r
+}\r
+\r
+.col2 {\r
+       padding-left: 20px;\r
+}\r
diff --git a/jscripts/tiny_mce/plugins/table/css/table.css b/jscripts/tiny_mce/plugins/table/css/table.css
new file mode 100644 (file)
index 0000000..d11c3f6
--- /dev/null
@@ -0,0 +1,13 @@
+/* CSS file for table dialog in the table plugin */\r
+\r
+.panel_wrapper div.current {\r
+       height: 245px;\r
+}\r
+\r
+.advfield {\r
+       width: 200px;\r
+}\r
+\r
+#class {\r
+       width: 150px;\r
+}\r
diff --git a/jscripts/tiny_mce/plugins/table/editor_plugin.js b/jscripts/tiny_mce/plugins/table/editor_plugin.js
new file mode 100644 (file)
index 0000000..266b241
--- /dev/null
@@ -0,0 +1 @@
+(function(){var each=tinymce.each;tinymce.create('tinymce.plugins.TablePlugin',{init:function(ed,url){var t=this;t.editor=ed;t.url=url;each([['table','table.desc','mceInsertTable',true],['delete_table','table.del','mceTableDelete'],['delete_col','table.delete_col_desc','mceTableDeleteCol'],['delete_row','table.delete_row_desc','mceTableDeleteRow'],['col_after','table.col_after_desc','mceTableInsertColAfter'],['col_before','table.col_before_desc','mceTableInsertColBefore'],['row_after','table.row_after_desc','mceTableInsertRowAfter'],['row_before','table.row_before_desc','mceTableInsertRowBefore'],['row_props','table.row_desc','mceTableRowProps',true],['cell_props','table.cell_desc','mceTableCellProps',true],['split_cells','table.split_cells_desc','mceTableSplitCells',true],['merge_cells','table.merge_cells_desc','mceTableMergeCells',true]],function(c){ed.addButton(c[0],{title:c[1],cmd:c[2],ui:c[3]});});ed.onInit.add(function(){if(ed&&ed.plugins.contextmenu){ed.plugins.contextmenu.onContextMenu.add(function(th,m,e){var sm,se=ed.selection,el=se.getNode()||ed.getBody();if(ed.dom.getParent(e,'td')||ed.dom.getParent(e,'th')){m.removeAll();if(el.nodeName=='A'&&!ed.dom.getAttrib(el,'name')){m.add({title:'advanced.link_desc',icon:'link',cmd:ed.plugins.advlink?'mceAdvLink':'mceLink',ui:true});m.add({title:'advanced.unlink_desc',icon:'unlink',cmd:'UnLink'});m.addSeparator();}if(el.nodeName=='IMG'&&el.className.indexOf('mceItem')==-1){m.add({title:'advanced.image_desc',icon:'image',cmd:ed.plugins.advimage?'mceAdvImage':'mceImage',ui:true});m.addSeparator();}m.add({title:'table.desc',icon:'table',cmd:'mceInsertTable',ui:true,value:{action:'insert'}});m.add({title:'table.props_desc',icon:'table_props',cmd:'mceInsertTable',ui:true});m.add({title:'table.del',icon:'delete_table',cmd:'mceTableDelete',ui:true});m.addSeparator();sm=m.addMenu({title:'table.cell'});sm.add({title:'table.cell_desc',icon:'cell_props',cmd:'mceTableCellProps',ui:true});sm.add({title:'table.split_cells_desc',icon:'split_cells',cmd:'mceTableSplitCells',ui:true});sm.add({title:'table.merge_cells_desc',icon:'merge_cells',cmd:'mceTableMergeCells',ui:true});sm=m.addMenu({title:'table.row'});sm.add({title:'table.row_desc',icon:'row_props',cmd:'mceTableRowProps',ui:true});sm.add({title:'table.row_before_desc',icon:'row_before',cmd:'mceTableInsertRowBefore'});sm.add({title:'table.row_after_desc',icon:'row_after',cmd:'mceTableInsertRowAfter'});sm.add({title:'table.delete_row_desc',icon:'delete_row',cmd:'mceTableDeleteRow'});sm.addSeparator();sm.add({title:'table.cut_row_desc',icon:'cut',cmd:'mceTableCutRow'});sm.add({title:'table.copy_row_desc',icon:'copy',cmd:'mceTableCopyRow'});sm.add({title:'table.paste_row_before_desc',icon:'paste',cmd:'mceTablePasteRowBefore'});sm.add({title:'table.paste_row_after_desc',icon:'paste',cmd:'mceTablePasteRowAfter'});sm=m.addMenu({title:'table.col'});sm.add({title:'table.col_before_desc',icon:'col_before',cmd:'mceTableInsertColBefore'});sm.add({title:'table.col_after_desc',icon:'col_after',cmd:'mceTableInsertColAfter'});sm.add({title:'table.delete_col_desc',icon:'delete_col',cmd:'mceTableDeleteCol'});}else m.add({title:'table.desc',icon:'table',cmd:'mceInsertTable',ui:true});});}});ed.onKeyDown.add(function(ed,e){if(e.keyCode==9&&ed.dom.getParent(ed.selection.getNode(),'TABLE'))ed.undoManager.add();});if(!tinymce.isIE){if(ed.getParam('table_selection',true)){ed.onClick.add(function(ed,e){e=e.target;if(e.nodeName==='TABLE')ed.selection.select(e);});}}ed.onNodeChange.add(function(ed,cm,n){var p=ed.dom.getParent(n,'td,th,caption');cm.setActive('table',n.nodeName==='TABLE'||!!p);if(p&&p.nodeName==='CAPTION')p=null;cm.setDisabled('delete_table',!p);cm.setDisabled('delete_col',!p);cm.setDisabled('delete_table',!p);cm.setDisabled('delete_row',!p);cm.setDisabled('col_after',!p);cm.setDisabled('col_before',!p);cm.setDisabled('row_after',!p);cm.setDisabled('row_before',!p);cm.setDisabled('row_props',!p);cm.setDisabled('cell_props',!p);cm.setDisabled('split_cells',!p||(parseInt(ed.dom.getAttrib(p,'colspan','1'))<2&&parseInt(ed.dom.getAttrib(p,'rowspan','1'))<2));cm.setDisabled('merge_cells',!p);});if(!tinymce.isIE){ed.onBeforeSetContent.add(function(ed,o){if(o.initial)o.content=o.content.replace(/<(td|th)([^>]+|)>\s*<\/(td|th)>/g,tinymce.isOpera?'<$1$2>&nbsp;</$1>':'<$1$2><br mce_bogus="1" /></$1>');});}},execCommand:function(cmd,ui,val){var ed=this.editor,b;switch(cmd){case"mceInsertTable":case"mceTableRowProps":case"mceTableCellProps":case"mceTableSplitCells":case"mceTableMergeCells":case"mceTableInsertRowBefore":case"mceTableInsertRowAfter":case"mceTableDeleteRow":case"mceTableInsertColBefore":case"mceTableInsertColAfter":case"mceTableDeleteCol":case"mceTableCutRow":case"mceTableCopyRow":case"mceTablePasteRowBefore":case"mceTablePasteRowAfter":case"mceTableDelete":ed.execCommand('mceBeginUndoLevel');this._doExecCommand(cmd,ui,val);ed.execCommand('mceEndUndoLevel');return true;}return false;},getInfo:function(){return{longname:'Tables',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/table',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_doExecCommand:function(command,user_interface,value){var inst=this.editor,ed=inst,url=this.url;var focusElm=inst.selection.getNode();var trElm=inst.dom.getParent(focusElm,"tr");var tdElm=inst.dom.getParent(focusElm,"td,th");var tableElm=inst.dom.getParent(focusElm,"table");var doc=inst.contentWindow.document;var tableBorder=tableElm?tableElm.getAttribute("border"):"";if(trElm&&tdElm==null)tdElm=trElm.cells[0];function inArray(ar,v){for(var i=0;i<ar.length;i++){if(ar[i].length>0&&inArray(ar[i],v))return true;if(ar[i]==v)return true;}return false;}function select(dx,dy){var td;grid=getTableGrid(tableElm);dx=dx||0;dy=dy||0;dx=Math.max(cpos.cellindex+dx,0);dy=Math.max(cpos.rowindex+dy,0);inst.execCommand('mceRepaint');td=getCell(grid,dy,dx);if(td){inst.selection.select(td.firstChild||td);inst.selection.collapse(1);}};function makeTD(){var newTD=doc.createElement("td");if(!tinymce.isIE)newTD.innerHTML='<br mce_bogus="1"/>';}function getColRowSpan(td){var colspan=inst.dom.getAttrib(td,"colspan");var rowspan=inst.dom.getAttrib(td,"rowspan");colspan=colspan==""?1:parseInt(colspan);rowspan=rowspan==""?1:parseInt(rowspan);return{colspan:colspan,rowspan:rowspan};}function getCellPos(grid,td){var x,y;for(y=0;y<grid.length;y++){for(x=0;x<grid[y].length;x++){if(grid[y][x]==td)return{cellindex:x,rowindex:y};}}return null;}function getCell(grid,row,col){if(grid[row]&&grid[row][col])return grid[row][col];return null;}function getTableGrid(table){var grid=[],rows=table.rows,x,y,td,sd,xstart,x2,y2;for(y=0;y<rows.length;y++){for(x=0;x<rows[y].cells.length;x++){td=rows[y].cells[x];sd=getColRowSpan(td);for(xstart=x;grid[y]&&grid[y][xstart];xstart++);for(y2=y;y2<y+sd['rowspan'];y2++){if(!grid[y2])grid[y2]=[];for(x2=xstart;x2<xstart+sd['colspan'];x2++)grid[y2][x2]=td;}}}return grid;}function trimRow(table,tr,td,new_tr){var grid=getTableGrid(table),cpos=getCellPos(grid,td);var cells,lastElm;if(new_tr.cells.length!=tr.childNodes.length){cells=tr.childNodes;lastElm=null;for(var x=0;td=getCell(grid,cpos.rowindex,x);x++){var remove=true;var sd=getColRowSpan(td);if(inArray(cells,td)){new_tr.childNodes[x]._delete=true;}else if((lastElm==null||td!=lastElm)&&sd.colspan>1){for(var i=x;i<x+td.colSpan;i++)new_tr.childNodes[i]._delete=true;}if((lastElm==null||td!=lastElm)&&sd.rowspan>1)td.rowSpan=sd.rowspan+1;lastElm=td;}deleteMarked(tableElm);}}function prevElm(node,name){while((node=node.previousSibling)!=null){if(node.nodeName==name)return node;}return null;}function nextElm(node,names){var namesAr=names.split(',');while((node=node.nextSibling)!=null){for(var i=0;i<namesAr.length;i++){if(node.nodeName.toLowerCase()==namesAr[i].toLowerCase())return node;}}return null;}function deleteMarked(tbl){if(tbl.rows==0)return;var tr=tbl.rows[0];do{var next=nextElm(tr,"TR");if(tr._delete){tr.parentNode.removeChild(tr);continue;}var td=tr.cells[0];if(td.cells>1){do{var nexttd=nextElm(td,"TD,TH");if(td._delete)td.parentNode.removeChild(td);}while((td=nexttd)!=null);}}while((tr=next)!=null);}function addRows(td_elm,tr_elm,rowspan){td_elm.rowSpan=1;var trNext=nextElm(tr_elm,"TR");for(var i=1;i<rowspan&&trNext;i++){var newTD=doc.createElement("td");if(!tinymce.isIE)newTD.innerHTML='<br mce_bogus="1"/>';if(tinymce.isIE)trNext.insertBefore(newTD,trNext.cells(td_elm.cellIndex));else trNext.insertBefore(newTD,trNext.cells[td_elm.cellIndex]);trNext=nextElm(trNext,"TR");}}function copyRow(doc,table,tr){var grid=getTableGrid(table);var newTR=tr.cloneNode(false);var cpos=getCellPos(grid,tr.cells[0]);var lastCell=null;var tableBorder=inst.dom.getAttrib(table,"border");var tdElm=null;for(var x=0;tdElm=getCell(grid,cpos.rowindex,x);x++){var newTD=null;if(lastCell!=tdElm){for(var i=0;i<tr.cells.length;i++){if(tdElm==tr.cells[i]){newTD=tdElm.cloneNode(true);break;}}}if(newTD==null){newTD=doc.createElement("td");if(!tinymce.isIE)newTD.innerHTML='<br mce_bogus="1"/>';}newTD.colSpan=1;newTD.rowSpan=1;newTR.appendChild(newTD);lastCell=tdElm;}return newTR;}switch(command){case"mceTableRowProps":if(trElm==null)return true;if(user_interface){inst.windowManager.open({url:url+'/row.htm',width:400+parseInt(inst.getLang('table.rowprops_delta_width',0)),height:295+parseInt(inst.getLang('table.rowprops_delta_height',0)),inline:1},{plugin_url:url});}return true;case"mceTableCellProps":if(tdElm==null)return true;if(user_interface){inst.windowManager.open({url:url+'/cell.htm',width:400+parseInt(inst.getLang('table.cellprops_delta_width',0)),height:295+parseInt(inst.getLang('table.cellprops_delta_height',0)),inline:1},{plugin_url:url});}return true;case"mceInsertTable":if(user_interface){inst.windowManager.open({url:url+'/table.htm',width:400+parseInt(inst.getLang('table.table_delta_width',0)),height:320+parseInt(inst.getLang('table.table_delta_height',0)),inline:1},{plugin_url:url,action:value?value.action:0});}return true;case"mceTableDelete":var table=inst.dom.getParent(inst.selection.getNode(),"table");if(table){table.parentNode.removeChild(table);inst.execCommand('mceRepaint');}return true;case"mceTableSplitCells":case"mceTableMergeCells":case"mceTableInsertRowBefore":case"mceTableInsertRowAfter":case"mceTableDeleteRow":case"mceTableInsertColBefore":case"mceTableInsertColAfter":case"mceTableDeleteCol":case"mceTableCutRow":case"mceTableCopyRow":case"mceTablePasteRowBefore":case"mceTablePasteRowAfter":if(!tableElm)return true;if(trElm&&tableElm!=trElm.parentNode)tableElm=trElm.parentNode;if(tableElm&&trElm){switch(command){case"mceTableCutRow":if(!trElm||!tdElm)return true;inst.tableRowClipboard=copyRow(doc,tableElm,trElm);inst.execCommand("mceTableDeleteRow");break;case"mceTableCopyRow":if(!trElm||!tdElm)return true;inst.tableRowClipboard=copyRow(doc,tableElm,trElm);break;case"mceTablePasteRowBefore":if(!trElm||!tdElm)return true;var newTR=inst.tableRowClipboard.cloneNode(true);var prevTR=prevElm(trElm,"TR");if(prevTR!=null)trimRow(tableElm,prevTR,prevTR.cells[0],newTR);trElm.parentNode.insertBefore(newTR,trElm);break;case"mceTablePasteRowAfter":if(!trElm||!tdElm)return true;var nextTR=nextElm(trElm,"TR");var newTR=inst.tableRowClipboard.cloneNode(true);trimRow(tableElm,trElm,tdElm,newTR);if(nextTR==null)trElm.parentNode.appendChild(newTR);else nextTR.parentNode.insertBefore(newTR,nextTR);break;case"mceTableInsertRowBefore":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);var newTR=doc.createElement("tr");var lastTDElm=null;cpos.rowindex--;if(cpos.rowindex<0)cpos.rowindex=0;for(var x=0;tdElm=getCell(grid,cpos.rowindex,x);x++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd['rowspan']==1){var newTD=doc.createElement("td");if(!tinymce.isIE)newTD.innerHTML='<br mce_bogus="1"/>';newTD.colSpan=tdElm.colSpan;newTR.appendChild(newTD);}else tdElm.rowSpan=sd['rowspan']+1;lastTDElm=tdElm;}}trElm.parentNode.insertBefore(newTR,trElm);select(0,1);break;case"mceTableInsertRowAfter":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);var newTR=doc.createElement("tr");var lastTDElm=null;for(var x=0;tdElm=getCell(grid,cpos.rowindex,x);x++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd['rowspan']==1){var newTD=doc.createElement("td");if(!tinymce.isIE)newTD.innerHTML='<br mce_bogus="1"/>';newTD.colSpan=tdElm.colSpan;newTR.appendChild(newTD);}else tdElm.rowSpan=sd['rowspan']+1;lastTDElm=tdElm;}}if(newTR.hasChildNodes()){var nextTR=nextElm(trElm,"TR");if(nextTR)nextTR.parentNode.insertBefore(newTR,nextTR);else tableElm.appendChild(newTR);}select(0,1);break;case"mceTableDeleteRow":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);if(grid.length==1){inst.dom.remove(inst.dom.getParent(tableElm,"table"));return true;}var cells=trElm.cells;var nextTR=nextElm(trElm,"TR");for(var x=0;x<cells.length;x++){if(cells[x].rowSpan>1){var newTD=cells[x].cloneNode(true);var sd=getColRowSpan(cells[x]);newTD.rowSpan=sd.rowspan-1;var nextTD=nextTR.cells[x];if(nextTD==null)nextTR.appendChild(newTD);else nextTR.insertBefore(newTD,nextTD);}}var lastTDElm=null;for(var x=0;tdElm=getCell(grid,cpos.rowindex,x);x++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd.rowspan>1){tdElm.rowSpan=sd.rowspan-1;}else{trElm=tdElm.parentNode;if(trElm.parentNode)trElm._delete=true;}lastTDElm=tdElm;}}deleteMarked(tableElm);select(0,-1);break;case"mceTableInsertColBefore":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);var lastTDElm=null;for(var y=0;tdElm=getCell(grid,y,cpos.cellindex);y++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd['colspan']==1){var newTD=doc.createElement(tdElm.nodeName);if(!tinymce.isIE)newTD.innerHTML='<br mce_bogus="1"/>';newTD.rowSpan=tdElm.rowSpan;tdElm.parentNode.insertBefore(newTD,tdElm);}else tdElm.colSpan++;lastTDElm=tdElm;}}select();break;case"mceTableInsertColAfter":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);var lastTDElm=null;for(var y=0;tdElm=getCell(grid,y,cpos.cellindex);y++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd['colspan']==1){var newTD=doc.createElement(tdElm.nodeName);if(!tinymce.isIE)newTD.innerHTML='<br mce_bogus="1"/>';newTD.rowSpan=tdElm.rowSpan;var nextTD=nextElm(tdElm,"TD,TH");if(nextTD==null)tdElm.parentNode.appendChild(newTD);else nextTD.parentNode.insertBefore(newTD,nextTD);}else tdElm.colSpan++;lastTDElm=tdElm;}}select(1);break;case"mceTableDeleteCol":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);var lastTDElm=null;if(grid.length>1&&grid[0].length<=1){inst.dom.remove(inst.dom.getParent(tableElm,"table"));return true;}for(var y=0;tdElm=getCell(grid,y,cpos.cellindex);y++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd['colspan']>1)tdElm.colSpan=sd['colspan']-1;else{if(tdElm.parentNode)tdElm.parentNode.removeChild(tdElm);}lastTDElm=tdElm;}}select(-1);break;case"mceTableSplitCells":if(!trElm||!tdElm)return true;var spandata=getColRowSpan(tdElm);var colspan=spandata["colspan"];var rowspan=spandata["rowspan"];if(colspan>1||rowspan>1){tdElm.colSpan=1;for(var i=1;i<colspan;i++){var newTD=doc.createElement("td");if(!tinymce.isIE)newTD.innerHTML='<br mce_bogus="1"/>';trElm.insertBefore(newTD,nextElm(tdElm,"TD,TH"));if(rowspan>1)addRows(newTD,trElm,rowspan);}addRows(tdElm,trElm,rowspan);}tableElm=inst.dom.getParent(inst.selection.getNode(),"table");break;case"mceTableMergeCells":var rows=[];var sel=inst.selection.getSel();var grid=getTableGrid(tableElm);if(tinymce.isIE||sel.rangeCount==1){if(user_interface){var sp=getColRowSpan(tdElm);inst.windowManager.open({url:url+'/merge_cells.htm',width:240+parseInt(inst.getLang('table.merge_cells_delta_width',0)),height:110+parseInt(inst.getLang('table.merge_cells_delta_height',0)),inline:1},{action:"update",numcols:sp.colspan,numrows:sp.rowspan,plugin_url:url});return true;}else{var numRows=parseInt(value['numrows']);var numCols=parseInt(value['numcols']);var cpos=getCellPos(grid,tdElm);if((""+numRows)=="NaN")numRows=1;if((""+numCols)=="NaN")numCols=1;var tRows=tableElm.rows;for(var y=cpos.rowindex;y<grid.length;y++){var rowCells=[];for(var x=cpos.cellindex;x<grid[y].length;x++){var td=getCell(grid,y,x);if(td&&!inArray(rows,td)&&!inArray(rowCells,td)){var cp=getCellPos(grid,td);if(cp.cellindex<cpos.cellindex+numCols&&cp.rowindex<cpos.rowindex+numRows)rowCells[rowCells.length]=td;}}if(rowCells.length>0)rows[rows.length]=rowCells;var td=getCell(grid,cpos.rowindex,cpos.cellindex);each(ed.dom.select('br',td),function(e,i){if(i>0&&ed.dom.getAttrib('mce_bogus'))ed.dom.remove(e);});}}}else{var cells=[];var sel=inst.selection.getSel();var lastTR=null;var curRow=null;var x1=-1,y1=-1,x2,y2;if(sel.rangeCount<2)return true;for(var i=0;i<sel.rangeCount;i++){var rng=sel.getRangeAt(i);var tdElm=rng.startContainer.childNodes[rng.startOffset];if(!tdElm)break;if(tdElm.nodeName=="TD"||tdElm.nodeName=="TH")cells[cells.length]=tdElm;}var tRows=tableElm.rows;for(var y=0;y<tRows.length;y++){var rowCells=[];for(var x=0;x<tRows[y].cells.length;x++){var td=tRows[y].cells[x];for(var i=0;i<cells.length;i++){if(td==cells[i]){rowCells[rowCells.length]=td;}}}if(rowCells.length>0)rows[rows.length]=rowCells;}var curRow=[];var lastTR=null;for(var y=0;y<grid.length;y++){for(var x=0;x<grid[y].length;x++){grid[y][x]._selected=false;for(var i=0;i<cells.length;i++){if(grid[y][x]==cells[i]){if(x1==-1){x1=x;y1=y;}x2=x;y2=y;grid[y][x]._selected=true;}}}}for(var y=y1;y<=y2;y++){for(var x=x1;x<=x2;x++){if(!grid[y][x]._selected){alert("Invalid selection for merge.");return true;}}}}var rowSpan=1,colSpan=1;var lastRowSpan=-1;for(var y=0;y<rows.length;y++){var rowColSpan=0;for(var x=0;x<rows[y].length;x++){var sd=getColRowSpan(rows[y][x]);rowColSpan+=sd['colspan'];if(lastRowSpan!=-1&&sd['rowspan']!=lastRowSpan){alert("Invalid selection for merge.");return true;}lastRowSpan=sd['rowspan'];}if(rowColSpan>colSpan)colSpan=rowColSpan;lastRowSpan=-1;}var lastColSpan=-1;for(var x=0;x<rows[0].length;x++){var colRowSpan=0;for(var y=0;y<rows.length;y++){var sd=getColRowSpan(rows[y][x]);colRowSpan+=sd['rowspan'];if(lastColSpan!=-1&&sd['colspan']!=lastColSpan){alert("Invalid selection for merge.");return true;}lastColSpan=sd['colspan'];}if(colRowSpan>rowSpan)rowSpan=colRowSpan;lastColSpan=-1;}tdElm=rows[0][0];tdElm.rowSpan=rowSpan;tdElm.colSpan=colSpan;for(var y=0;y<rows.length;y++){for(var x=0;x<rows[y].length;x++){var html=rows[y][x].innerHTML;var chk=html.replace(/[ \t\r\n]/g,"");if(chk!="<br/>"&&chk!="<br>"&&chk!='<br mce_bogus="1"/>'&&(x+y>0))tdElm.innerHTML+=html;if(rows[y][x]!=tdElm&&!rows[y][x]._deleted){var cpos=getCellPos(grid,rows[y][x]);var tr=rows[y][x].parentNode;tr.removeChild(rows[y][x]);rows[y][x]._deleted=true;if(!tr.hasChildNodes()){tr.parentNode.removeChild(tr);var lastCell=null;for(var x=0;cellElm=getCell(grid,cpos.rowindex,x);x++){if(cellElm!=lastCell&&cellElm.rowSpan>1)cellElm.rowSpan--;lastCell=cellElm;}if(tdElm.rowSpan>1)tdElm.rowSpan--;}}}}each(ed.dom.select('br',tdElm),function(e,i){if(i>0&&ed.dom.getAttrib(e,'mce_bogus'))ed.dom.remove(e);});break;}tableElm=inst.dom.getParent(inst.selection.getNode(),"table");inst.addVisual(tableElm);inst.nodeChanged();}return true;}return false;}});tinymce.PluginManager.add('table',tinymce.plugins.TablePlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/table/editor_plugin_src.js b/jscripts/tiny_mce/plugins/table/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..097890f
--- /dev/null
@@ -0,0 +1,1082 @@
+/**\r
+ * $Id: editor_plugin_src.js 792 2008-04-10 16:37:29Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       var each = tinymce.each;\r
+\r
+       tinymce.create('tinymce.plugins.TablePlugin', {\r
+               init : function(ed, url) {\r
+                       var t = this;\r
+\r
+                       t.editor = ed;\r
+                       t.url = url;\r
+\r
+                       // Register buttons\r
+                       each([\r
+                               ['table', 'table.desc', 'mceInsertTable', true],\r
+                               ['delete_table', 'table.del', 'mceTableDelete'],\r
+                               ['delete_col', 'table.delete_col_desc', 'mceTableDeleteCol'],\r
+                               ['delete_row', 'table.delete_row_desc', 'mceTableDeleteRow'],\r
+                               ['col_after', 'table.col_after_desc', 'mceTableInsertColAfter'],\r
+                               ['col_before', 'table.col_before_desc', 'mceTableInsertColBefore'],\r
+                               ['row_after', 'table.row_after_desc', 'mceTableInsertRowAfter'],\r
+                               ['row_before', 'table.row_before_desc', 'mceTableInsertRowBefore'],\r
+                               ['row_props', 'table.row_desc', 'mceTableRowProps', true],\r
+                               ['cell_props', 'table.cell_desc', 'mceTableCellProps', true],\r
+                               ['split_cells', 'table.split_cells_desc', 'mceTableSplitCells', true],\r
+                               ['merge_cells', 'table.merge_cells_desc', 'mceTableMergeCells', true]\r
+                       ], function(c) {\r
+                               ed.addButton(c[0], {title : c[1], cmd : c[2], ui : c[3]});\r
+                       });\r
+\r
+                       ed.onInit.add(function() {\r
+                               if (ed && ed.plugins.contextmenu) {\r
+                                       ed.plugins.contextmenu.onContextMenu.add(function(th, m, e) {\r
+                                               var sm, se = ed.selection, el = se.getNode() || ed.getBody();\r
+\r
+                                               if (ed.dom.getParent(e, 'td') || ed.dom.getParent(e, 'th')) {\r
+                                                       m.removeAll();\r
+\r
+                                                       if (el.nodeName == 'A' && !ed.dom.getAttrib(el, 'name')) {\r
+                                                               m.add({title : 'advanced.link_desc', icon : 'link', cmd : ed.plugins.advlink ? 'mceAdvLink' : 'mceLink', ui : true});\r
+                                                               m.add({title : 'advanced.unlink_desc', icon : 'unlink', cmd : 'UnLink'});\r
+                                                               m.addSeparator();\r
+                                                       }\r
+\r
+                                                       if (el.nodeName == 'IMG' && el.className.indexOf('mceItem') == -1) {\r
+                                                               m.add({title : 'advanced.image_desc', icon : 'image', cmd : ed.plugins.advimage ? 'mceAdvImage' : 'mceImage', ui : true});\r
+                                                               m.addSeparator();\r
+                                                       }\r
+\r
+                                                       m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable', ui : true, value : {action : 'insert'}});\r
+                                                       m.add({title : 'table.props_desc', icon : 'table_props', cmd : 'mceInsertTable', ui : true});\r
+                                                       m.add({title : 'table.del', icon : 'delete_table', cmd : 'mceTableDelete', ui : true});\r
+                                                       m.addSeparator();\r
+\r
+                                                       // Cell menu\r
+                                                       sm = m.addMenu({title : 'table.cell'});\r
+                                                       sm.add({title : 'table.cell_desc', icon : 'cell_props', cmd : 'mceTableCellProps', ui : true});\r
+                                                       sm.add({title : 'table.split_cells_desc', icon : 'split_cells', cmd : 'mceTableSplitCells', ui : true});\r
+                                                       sm.add({title : 'table.merge_cells_desc', icon : 'merge_cells', cmd : 'mceTableMergeCells', ui : true});\r
+\r
+                                                       // Row menu\r
+                                                       sm = m.addMenu({title : 'table.row'});\r
+                                                       sm.add({title : 'table.row_desc', icon : 'row_props', cmd : 'mceTableRowProps', ui : true});\r
+                                                       sm.add({title : 'table.row_before_desc', icon : 'row_before', cmd : 'mceTableInsertRowBefore'});\r
+                                                       sm.add({title : 'table.row_after_desc', icon : 'row_after', cmd : 'mceTableInsertRowAfter'});\r
+                                                       sm.add({title : 'table.delete_row_desc', icon : 'delete_row', cmd : 'mceTableDeleteRow'});\r
+                                                       sm.addSeparator();\r
+                                                       sm.add({title : 'table.cut_row_desc', icon : 'cut', cmd : 'mceTableCutRow'});\r
+                                                       sm.add({title : 'table.copy_row_desc', icon : 'copy', cmd : 'mceTableCopyRow'});\r
+                                                       sm.add({title : 'table.paste_row_before_desc', icon : 'paste', cmd : 'mceTablePasteRowBefore'});\r
+                                                       sm.add({title : 'table.paste_row_after_desc', icon : 'paste', cmd : 'mceTablePasteRowAfter'});\r
+\r
+                                                       // Column menu\r
+                                                       sm = m.addMenu({title : 'table.col'});\r
+                                                       sm.add({title : 'table.col_before_desc', icon : 'col_before', cmd : 'mceTableInsertColBefore'});\r
+                                                       sm.add({title : 'table.col_after_desc', icon : 'col_after', cmd : 'mceTableInsertColAfter'});\r
+                                                       sm.add({title : 'table.delete_col_desc', icon : 'delete_col', cmd : 'mceTableDeleteCol'});\r
+                                               } else\r
+                                                       m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable', ui : true});\r
+                                       });\r
+                               }\r
+                       });\r
+\r
+                       // Add undo level when new rows are created using the tab key\r
+                       ed.onKeyDown.add(function(ed, e) {\r
+                               if (e.keyCode == 9 && ed.dom.getParent(ed.selection.getNode(), 'TABLE'))\r
+                                       ed.undoManager.add();\r
+                       });\r
+\r
+                       // Select whole table is a table border is clicked\r
+                       if (!tinymce.isIE) {\r
+                               if (ed.getParam('table_selection', true)) {\r
+                                       ed.onClick.add(function(ed, e) {\r
+                                               e = e.target;\r
+\r
+                                               if (e.nodeName === 'TABLE')\r
+                                                       ed.selection.select(e);\r
+                                       });\r
+                               }\r
+                       }\r
+\r
+                       ed.onNodeChange.add(function(ed, cm, n) {\r
+                               var p = ed.dom.getParent(n, 'td,th,caption');\r
+\r
+                               cm.setActive('table', n.nodeName === 'TABLE' || !!p);\r
+                               if (p && p.nodeName === 'CAPTION')\r
+                                       p = null;\r
+\r
+                               cm.setDisabled('delete_table', !p);\r
+                               cm.setDisabled('delete_col', !p);\r
+                               cm.setDisabled('delete_table', !p);\r
+                               cm.setDisabled('delete_row', !p);\r
+                               cm.setDisabled('col_after', !p);\r
+                               cm.setDisabled('col_before', !p);\r
+                               cm.setDisabled('row_after', !p);\r
+                               cm.setDisabled('row_before', !p);\r
+                               cm.setDisabled('row_props', !p);\r
+                               cm.setDisabled('cell_props', !p);\r
+                               cm.setDisabled('split_cells', !p || (parseInt(ed.dom.getAttrib(p, 'colspan', '1')) < 2 && parseInt(ed.dom.getAttrib(p, 'rowspan', '1')) < 2));\r
+                               cm.setDisabled('merge_cells', !p);\r
+                       });\r
+\r
+                       // Padd empty table cells\r
+                       if (!tinymce.isIE) {\r
+                               ed.onBeforeSetContent.add(function(ed, o) {\r
+                                       if (o.initial)\r
+                                               o.content = o.content.replace(/<(td|th)([^>]+|)>\s*<\/(td|th)>/g, tinymce.isOpera ? '<$1$2>&nbsp;</$1>' : '<$1$2><br mce_bogus="1" /></$1>');\r
+                               });\r
+                       }\r
+               },\r
+\r
+               execCommand : function(cmd, ui, val) {\r
+                       var ed = this.editor, b;\r
+\r
+                       // Is table command\r
+                       switch (cmd) {\r
+                               case "mceInsertTable":\r
+                               case "mceTableRowProps":\r
+                               case "mceTableCellProps":\r
+                               case "mceTableSplitCells":\r
+                               case "mceTableMergeCells":\r
+                               case "mceTableInsertRowBefore":\r
+                               case "mceTableInsertRowAfter":\r
+                               case "mceTableDeleteRow":\r
+                               case "mceTableInsertColBefore":\r
+                               case "mceTableInsertColAfter":\r
+                               case "mceTableDeleteCol":\r
+                               case "mceTableCutRow":\r
+                               case "mceTableCopyRow":\r
+                               case "mceTablePasteRowBefore":\r
+                               case "mceTablePasteRowAfter":\r
+                               case "mceTableDelete":\r
+                                       ed.execCommand('mceBeginUndoLevel');\r
+                                       this._doExecCommand(cmd, ui, val);\r
+                                       ed.execCommand('mceEndUndoLevel');\r
+\r
+                                       return true;\r
+                       }\r
+\r
+                       // Pass to next handler in chain\r
+                       return false;\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Tables',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/table',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               },\r
+\r
+               // Private plugin internal methods\r
+\r
+               /**\r
+                * Executes the table commands.\r
+                */\r
+               _doExecCommand : function(command, user_interface, value) {\r
+                       var inst = this.editor, ed = inst, url = this.url;\r
+                       var focusElm = inst.selection.getNode();\r
+                       var trElm = inst.dom.getParent(focusElm, "tr");\r
+                       var tdElm = inst.dom.getParent(focusElm, "td,th");\r
+                       var tableElm = inst.dom.getParent(focusElm, "table");\r
+                       var doc = inst.contentWindow.document;\r
+                       var tableBorder = tableElm ? tableElm.getAttribute("border") : "";\r
+\r
+                       // Get first TD if no TD found\r
+                       if (trElm && tdElm == null)\r
+                               tdElm = trElm.cells[0];\r
+\r
+                       function inArray(ar, v) {\r
+                               for (var i=0; i<ar.length; i++) {\r
+                                       // Is array\r
+                                       if (ar[i].length > 0 && inArray(ar[i], v))\r
+                                               return true;\r
+\r
+                                       // Found value\r
+                                       if (ar[i] == v)\r
+                                               return true;\r
+                               }\r
+\r
+                               return false;\r
+                       }\r
+\r
+                       function select(dx, dy) {\r
+                               var td;\r
+\r
+                               grid = getTableGrid(tableElm);\r
+                               dx = dx || 0;\r
+                               dy = dy || 0;\r
+                               dx = Math.max(cpos.cellindex + dx, 0);\r
+                               dy = Math.max(cpos.rowindex + dy, 0);\r
+\r
+                               // Recalculate grid and select\r
+                               inst.execCommand('mceRepaint');\r
+                               td = getCell(grid, dy, dx);\r
+\r
+                               if (td) {\r
+                                       inst.selection.select(td.firstChild || td);\r
+                                       inst.selection.collapse(1);\r
+                               }\r
+                       };\r
+\r
+                       function makeTD() {\r
+                               var newTD = doc.createElement("td");\r
+\r
+                               if (!tinymce.isIE)\r
+                                       newTD.innerHTML = '<br mce_bogus="1"/>';\r
+                       }\r
+\r
+                       function getColRowSpan(td) {\r
+                               var colspan = inst.dom.getAttrib(td, "colspan");\r
+                               var rowspan = inst.dom.getAttrib(td, "rowspan");\r
+\r
+                               colspan = colspan == "" ? 1 : parseInt(colspan);\r
+                               rowspan = rowspan == "" ? 1 : parseInt(rowspan);\r
+\r
+                               return {colspan : colspan, rowspan : rowspan};\r
+                       }\r
+\r
+                       function getCellPos(grid, td) {\r
+                               var x, y;\r
+\r
+                               for (y=0; y<grid.length; y++) {\r
+                                       for (x=0; x<grid[y].length; x++) {\r
+                                               if (grid[y][x] == td)\r
+                                                       return {cellindex : x, rowindex : y};\r
+                                       }\r
+                               }\r
+\r
+                               return null;\r
+                       }\r
+\r
+                       function getCell(grid, row, col) {\r
+                               if (grid[row] && grid[row][col])\r
+                                       return grid[row][col];\r
+\r
+                               return null;\r
+                       }\r
+\r
+                       function getTableGrid(table) {\r
+                               var grid = [], rows = table.rows, x, y, td, sd, xstart, x2, y2;\r
+\r
+                               for (y=0; y<rows.length; y++) {\r
+                                       for (x=0; x<rows[y].cells.length; x++) {\r
+                                               td = rows[y].cells[x];\r
+                                               sd = getColRowSpan(td);\r
+\r
+                                               // All ready filled\r
+                                               for (xstart = x; grid[y] && grid[y][xstart]; xstart++) ;\r
+\r
+                                               // Fill box\r
+                                               for (y2=y; y2<y+sd['rowspan']; y2++) {\r
+                                                       if (!grid[y2])\r
+                                                               grid[y2] = [];\r
+\r
+                                                       for (x2=xstart; x2<xstart+sd['colspan']; x2++)\r
+                                                               grid[y2][x2] = td;\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               return grid;\r
+                       }\r
+\r
+                       function trimRow(table, tr, td, new_tr) {\r
+                               var grid = getTableGrid(table), cpos = getCellPos(grid, td);\r
+                               var cells, lastElm;\r
+\r
+                               // Time to crop away some\r
+                               if (new_tr.cells.length != tr.childNodes.length) {\r
+                                       cells = tr.childNodes;\r
+                                       lastElm = null;\r
+\r
+                                       for (var x=0; td = getCell(grid, cpos.rowindex, x); x++) {\r
+                                               var remove = true;\r
+                                               var sd = getColRowSpan(td);\r
+\r
+                                               // Remove due to rowspan\r
+                                               if (inArray(cells, td)) {\r
+                                                       new_tr.childNodes[x]._delete = true;\r
+                                               } else if ((lastElm == null || td != lastElm) && sd.colspan > 1) { // Remove due to colspan\r
+                                                       for (var i=x; i<x+td.colSpan; i++)\r
+                                                               new_tr.childNodes[i]._delete = true;\r
+                                               }\r
+\r
+                                               if ((lastElm == null || td != lastElm) && sd.rowspan > 1)\r
+                                                       td.rowSpan = sd.rowspan + 1;\r
+\r
+                                               lastElm = td;\r
+                                       }\r
+\r
+                                       deleteMarked(tableElm);\r
+                               }\r
+                       }\r
+\r
+                       function prevElm(node, name) {\r
+                               while ((node = node.previousSibling) != null) {\r
+                                       if (node.nodeName == name)\r
+                                               return node;\r
+                               }\r
+\r
+                               return null;\r
+                       }\r
+\r
+                       function nextElm(node, names) {\r
+                               var namesAr = names.split(',');\r
+\r
+                               while ((node = node.nextSibling) != null) {\r
+                                       for (var i=0; i<namesAr.length; i++) {\r
+                                               if (node.nodeName.toLowerCase() == namesAr[i].toLowerCase() )\r
+                                                       return node;\r
+                                       }\r
+                               }\r
+\r
+                               return null;\r
+                       }\r
+\r
+                       function deleteMarked(tbl) {\r
+                               if (tbl.rows == 0)\r
+                                       return;\r
+\r
+                               var tr = tbl.rows[0];\r
+                               do {\r
+                                       var next = nextElm(tr, "TR");\r
+\r
+                                       // Delete row\r
+                                       if (tr._delete) {\r
+                                               tr.parentNode.removeChild(tr);\r
+                                               continue;\r
+                                       }\r
+\r
+                                       // Delete cells\r
+                                       var td = tr.cells[0];\r
+                                       if (td.cells > 1) {\r
+                                               do {\r
+                                                       var nexttd = nextElm(td, "TD,TH");\r
+\r
+                                                       if (td._delete)\r
+                                                               td.parentNode.removeChild(td);\r
+                                               } while ((td = nexttd) != null);\r
+                                       }\r
+                               } while ((tr = next) != null);\r
+                       }\r
+\r
+                       function addRows(td_elm, tr_elm, rowspan) {\r
+                               // Add rows\r
+                               td_elm.rowSpan = 1;\r
+                               var trNext = nextElm(tr_elm, "TR");\r
+                               for (var i=1; i<rowspan && trNext; i++) {\r
+                                       var newTD = doc.createElement("td");\r
+\r
+                                       if (!tinymce.isIE)\r
+                                               newTD.innerHTML = '<br mce_bogus="1"/>';\r
+\r
+                                       if (tinymce.isIE)\r
+                                               trNext.insertBefore(newTD, trNext.cells(td_elm.cellIndex));\r
+                                       else\r
+                                               trNext.insertBefore(newTD, trNext.cells[td_elm.cellIndex]);\r
+\r
+                                       trNext = nextElm(trNext, "TR");\r
+                               }\r
+                       }\r
+\r
+                       function copyRow(doc, table, tr) {\r
+                               var grid = getTableGrid(table);\r
+                               var newTR = tr.cloneNode(false);\r
+                               var cpos = getCellPos(grid, tr.cells[0]);\r
+                               var lastCell = null;\r
+                               var tableBorder = inst.dom.getAttrib(table, "border");\r
+                               var tdElm = null;\r
+\r
+                               for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {\r
+                                       var newTD = null;\r
+\r
+                                       if (lastCell != tdElm) {\r
+                                               for (var i=0; i<tr.cells.length; i++) {\r
+                                                       if (tdElm == tr.cells[i]) {\r
+                                                               newTD = tdElm.cloneNode(true);\r
+                                                               break;\r
+                                                       }\r
+                                               }\r
+                                       }\r
+\r
+                                       if (newTD == null) {\r
+                                               newTD = doc.createElement("td");\r
+\r
+                                               if (!tinymce.isIE)\r
+                                                       newTD.innerHTML = '<br mce_bogus="1"/>';\r
+                                       }\r
+\r
+                                       // Reset col/row span\r
+                                       newTD.colSpan = 1;\r
+                                       newTD.rowSpan = 1;\r
+\r
+                                       newTR.appendChild(newTD);\r
+\r
+                                       lastCell = tdElm;\r
+                               }\r
+\r
+                               return newTR;\r
+                       }\r
+\r
+                       // ---- Commands -----\r
+\r
+                       // Handle commands\r
+                       switch (command) {\r
+                               case "mceTableRowProps":\r
+                                       if (trElm == null)\r
+                                               return true;\r
+\r
+                                       if (user_interface) {\r
+                                               inst.windowManager.open({\r
+                                                       url : url + '/row.htm',\r
+                                                       width : 400 + parseInt(inst.getLang('table.rowprops_delta_width', 0)),\r
+                                                       height : 295 + parseInt(inst.getLang('table.rowprops_delta_height', 0)),\r
+                                                       inline : 1\r
+                                               }, {\r
+                                                       plugin_url : url\r
+                                               });\r
+                                       }\r
+\r
+                                       return true;\r
+\r
+                               case "mceTableCellProps":\r
+                                       if (tdElm == null)\r
+                                               return true;\r
+\r
+                                       if (user_interface) {\r
+                                               inst.windowManager.open({\r
+                                                       url : url + '/cell.htm',\r
+                                                       width : 400 + parseInt(inst.getLang('table.cellprops_delta_width', 0)),\r
+                                                       height : 295 + parseInt(inst.getLang('table.cellprops_delta_height', 0)),\r
+                                                       inline : 1\r
+                                               }, {\r
+                                                       plugin_url : url\r
+                                               });\r
+                                       }\r
+\r
+                                       return true;\r
+\r
+                               case "mceInsertTable":\r
+                                       if (user_interface) {\r
+                                               inst.windowManager.open({\r
+                                                       url : url + '/table.htm',\r
+                                                       width : 400 + parseInt(inst.getLang('table.table_delta_width', 0)),\r
+                                                       height : 320 + parseInt(inst.getLang('table.table_delta_height', 0)),\r
+                                                       inline : 1\r
+                                               }, {\r
+                                                       plugin_url : url,\r
+                                                       action : value ? value.action : 0\r
+                                               });\r
+                                       }\r
+\r
+                                       return true;\r
+\r
+                               case "mceTableDelete":\r
+                                       var table = inst.dom.getParent(inst.selection.getNode(), "table");\r
+                                       if (table) {\r
+                                               table.parentNode.removeChild(table);\r
+                                               inst.execCommand('mceRepaint');\r
+                                       }\r
+                                       return true;\r
+\r
+                               case "mceTableSplitCells":\r
+                               case "mceTableMergeCells":\r
+                               case "mceTableInsertRowBefore":\r
+                               case "mceTableInsertRowAfter":\r
+                               case "mceTableDeleteRow":\r
+                               case "mceTableInsertColBefore":\r
+                               case "mceTableInsertColAfter":\r
+                               case "mceTableDeleteCol":\r
+                               case "mceTableCutRow":\r
+                               case "mceTableCopyRow":\r
+                               case "mceTablePasteRowBefore":\r
+                               case "mceTablePasteRowAfter":\r
+                                       // No table just return (invalid command)\r
+                                       if (!tableElm)\r
+                                               return true;\r
+\r
+                                       // Table has a tbody use that reference\r
+                                       // Changed logic by ApTest 2005.07.12 (www.aptest.com)\r
+                                       // Now lookk at the focused element and take its parentNode.  That will be a tbody or a table.\r
+                                       if (trElm && tableElm != trElm.parentNode)\r
+                                               tableElm = trElm.parentNode;\r
+\r
+                                       if (tableElm && trElm) {\r
+                                               switch (command) {\r
+                                                       case "mceTableCutRow":\r
+                                                               if (!trElm || !tdElm)\r
+                                                                       return true;\r
+\r
+                                                               inst.tableRowClipboard = copyRow(doc, tableElm, trElm);\r
+                                                               inst.execCommand("mceTableDeleteRow");\r
+                                                               break;\r
+\r
+                                                       case "mceTableCopyRow":\r
+                                                               if (!trElm || !tdElm)\r
+                                                                       return true;\r
+\r
+                                                               inst.tableRowClipboard = copyRow(doc, tableElm, trElm);\r
+                                                               break;\r
+\r
+                                                       case "mceTablePasteRowBefore":\r
+                                                               if (!trElm || !tdElm)\r
+                                                                       return true;\r
+\r
+                                                               var newTR = inst.tableRowClipboard.cloneNode(true);\r
+\r
+                                                               var prevTR = prevElm(trElm, "TR");\r
+                                                               if (prevTR != null)\r
+                                                                       trimRow(tableElm, prevTR, prevTR.cells[0], newTR);\r
+\r
+                                                               trElm.parentNode.insertBefore(newTR, trElm);\r
+                                                               break;\r
+\r
+                                                       case "mceTablePasteRowAfter":\r
+                                                               if (!trElm || !tdElm)\r
+                                                                       return true;\r
+                                                               \r
+                                                               var nextTR = nextElm(trElm, "TR");\r
+                                                               var newTR = inst.tableRowClipboard.cloneNode(true);\r
+\r
+                                                               trimRow(tableElm, trElm, tdElm, newTR);\r
+\r
+                                                               if (nextTR == null)\r
+                                                                       trElm.parentNode.appendChild(newTR);\r
+                                                               else\r
+                                                                       nextTR.parentNode.insertBefore(newTR, nextTR);\r
+\r
+                                                               break;\r
+\r
+                                                       case "mceTableInsertRowBefore":\r
+                                                               if (!trElm || !tdElm)\r
+                                                                       return true;\r
+\r
+                                                               var grid = getTableGrid(tableElm);\r
+                                                               var cpos = getCellPos(grid, tdElm);\r
+                                                               var newTR = doc.createElement("tr");\r
+                                                               var lastTDElm = null;\r
+\r
+                                                               cpos.rowindex--;\r
+                                                               if (cpos.rowindex < 0)\r
+                                                                       cpos.rowindex = 0;\r
+\r
+                                                               // Create cells\r
+                                                               for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {\r
+                                                                       if (tdElm != lastTDElm) {\r
+                                                                               var sd = getColRowSpan(tdElm);\r
+\r
+                                                                               if (sd['rowspan'] == 1) {\r
+                                                                                       var newTD = doc.createElement("td");\r
+\r
+                                                                                       if (!tinymce.isIE)\r
+                                                                                               newTD.innerHTML = '<br mce_bogus="1"/>';\r
+\r
+                                                                                       newTD.colSpan = tdElm.colSpan;\r
+\r
+                                                                                       newTR.appendChild(newTD);\r
+                                                                               } else\r
+                                                                                       tdElm.rowSpan = sd['rowspan'] + 1;\r
+\r
+                                                                               lastTDElm = tdElm;\r
+                                                                       }\r
+                                                               }\r
+\r
+                                                               trElm.parentNode.insertBefore(newTR, trElm);\r
+                                                               select(0, 1);\r
+                                                       break;\r
+\r
+                                                       case "mceTableInsertRowAfter":\r
+                                                               if (!trElm || !tdElm)\r
+                                                                       return true;\r
+\r
+                                                               var grid = getTableGrid(tableElm);\r
+                                                               var cpos = getCellPos(grid, tdElm);\r
+                                                               var newTR = doc.createElement("tr");\r
+                                                               var lastTDElm = null;\r
+\r
+                                                               // Create cells\r
+                                                               for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {\r
+                                                                       if (tdElm != lastTDElm) {\r
+                                                                               var sd = getColRowSpan(tdElm);\r
+\r
+                                                                               if (sd['rowspan'] == 1) {\r
+                                                                                       var newTD = doc.createElement("td");\r
+\r
+                                                                                       if (!tinymce.isIE)\r
+                                                                                               newTD.innerHTML = '<br mce_bogus="1"/>';\r
+\r
+                                                                                       newTD.colSpan = tdElm.colSpan;\r
+\r
+                                                                                       newTR.appendChild(newTD);\r
+                                                                               } else\r
+                                                                                       tdElm.rowSpan = sd['rowspan'] + 1;\r
+\r
+                                                                               lastTDElm = tdElm;\r
+                                                                       }\r
+                                                               }\r
+\r
+                                                               if (newTR.hasChildNodes()) {\r
+                                                                       var nextTR = nextElm(trElm, "TR");\r
+                                                                       if (nextTR)\r
+                                                                               nextTR.parentNode.insertBefore(newTR, nextTR);\r
+                                                                       else\r
+                                                                               tableElm.appendChild(newTR);\r
+                                                               }\r
+\r
+                                                               select(0, 1);\r
+                                                       break;\r
+\r
+                                                       case "mceTableDeleteRow":\r
+                                                               if (!trElm || !tdElm)\r
+                                                                       return true;\r
+\r
+                                                               var grid = getTableGrid(tableElm);\r
+                                                               var cpos = getCellPos(grid, tdElm);\r
+\r
+                                                               // Only one row, remove whole table\r
+                                                               if (grid.length == 1) {\r
+                                                                       inst.dom.remove(inst.dom.getParent(tableElm, "table"));\r
+                                                                       return true;\r
+                                                               }\r
+\r
+                                                               // Move down row spanned cells\r
+                                                               var cells = trElm.cells;\r
+                                                               var nextTR = nextElm(trElm, "TR");\r
+                                                               for (var x=0; x<cells.length; x++) {\r
+                                                                       if (cells[x].rowSpan > 1) {\r
+                                                                               var newTD = cells[x].cloneNode(true);\r
+                                                                               var sd = getColRowSpan(cells[x]);\r
+\r
+                                                                               newTD.rowSpan = sd.rowspan - 1;\r
+\r
+                                                                               var nextTD = nextTR.cells[x];\r
+\r
+                                                                               if (nextTD == null)\r
+                                                                                       nextTR.appendChild(newTD);\r
+                                                                               else\r
+                                                                                       nextTR.insertBefore(newTD, nextTD);\r
+                                                                       }\r
+                                                               }\r
+\r
+                                                               // Delete cells\r
+                                                               var lastTDElm = null;\r
+                                                               for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {\r
+                                                                       if (tdElm != lastTDElm) {\r
+                                                                               var sd = getColRowSpan(tdElm);\r
+\r
+                                                                               if (sd.rowspan > 1) {\r
+                                                                                       tdElm.rowSpan = sd.rowspan - 1;\r
+                                                                               } else {\r
+                                                                                       trElm = tdElm.parentNode;\r
+\r
+                                                                                       if (trElm.parentNode)\r
+                                                                                               trElm._delete = true;\r
+                                                                               }\r
+\r
+                                                                               lastTDElm = tdElm;\r
+                                                                       }\r
+                                                               }\r
+\r
+                                                               deleteMarked(tableElm);\r
+\r
+                                                               select(0, -1);\r
+                                                       break;\r
+\r
+                                                       case "mceTableInsertColBefore":\r
+                                                               if (!trElm || !tdElm)\r
+                                                                       return true;\r
+\r
+                                                               var grid = getTableGrid(tableElm);\r
+                                                               var cpos = getCellPos(grid, tdElm);\r
+                                                               var lastTDElm = null;\r
+\r
+                                                               for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {\r
+                                                                       if (tdElm != lastTDElm) {\r
+                                                                               var sd = getColRowSpan(tdElm);\r
+\r
+                                                                               if (sd['colspan'] == 1) {\r
+                                                                                       var newTD = doc.createElement(tdElm.nodeName);\r
+\r
+                                                                                       if (!tinymce.isIE)\r
+                                                                                               newTD.innerHTML = '<br mce_bogus="1"/>';\r
+\r
+                                                                                       newTD.rowSpan = tdElm.rowSpan;\r
+\r
+                                                                                       tdElm.parentNode.insertBefore(newTD, tdElm);\r
+                                                                               } else\r
+                                                                                       tdElm.colSpan++;\r
+\r
+                                                                               lastTDElm = tdElm;\r
+                                                                       }\r
+                                                               }\r
+\r
+                                                               select();\r
+                                                       break;\r
+\r
+                                                       case "mceTableInsertColAfter":\r
+                                                               if (!trElm || !tdElm)\r
+                                                                       return true;\r
+\r
+                                                               var grid = getTableGrid(tableElm);\r
+                                                               var cpos = getCellPos(grid, tdElm);\r
+                                                               var lastTDElm = null;\r
+\r
+                                                               for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {\r
+                                                                       if (tdElm != lastTDElm) {\r
+                                                                               var sd = getColRowSpan(tdElm);\r
+\r
+                                                                               if (sd['colspan'] == 1) {\r
+                                                                                       var newTD = doc.createElement(tdElm.nodeName);\r
+\r
+                                                                                       if (!tinymce.isIE)\r
+                                                                                               newTD.innerHTML = '<br mce_bogus="1"/>';\r
+\r
+                                                                                       newTD.rowSpan = tdElm.rowSpan;\r
+\r
+                                                                                       var nextTD = nextElm(tdElm, "TD,TH");\r
+                                                                                       if (nextTD == null)\r
+                                                                                               tdElm.parentNode.appendChild(newTD);\r
+                                                                                       else\r
+                                                                                               nextTD.parentNode.insertBefore(newTD, nextTD);\r
+                                                                               } else\r
+                                                                                       tdElm.colSpan++;\r
+\r
+                                                                               lastTDElm = tdElm;\r
+                                                                       }\r
+                                                               }\r
+\r
+                                                               select(1);\r
+                                                       break;\r
+\r
+                                                       case "mceTableDeleteCol":\r
+                                                               if (!trElm || !tdElm)\r
+                                                                       return true;\r
+\r
+                                                               var grid = getTableGrid(tableElm);\r
+                                                               var cpos = getCellPos(grid, tdElm);\r
+                                                               var lastTDElm = null;\r
+\r
+                                                               // Only one col, remove whole table\r
+                                                               if (grid.length > 1 && grid[0].length <= 1) {\r
+                                                                       inst.dom.remove(inst.dom.getParent(tableElm, "table"));\r
+                                                                       return true;\r
+                                                               }\r
+\r
+                                                               // Delete cells\r
+                                                               for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {\r
+                                                                       if (tdElm != lastTDElm) {\r
+                                                                               var sd = getColRowSpan(tdElm);\r
+\r
+                                                                               if (sd['colspan'] > 1)\r
+                                                                                       tdElm.colSpan = sd['colspan'] - 1;\r
+                                                                               else {\r
+                                                                                       if (tdElm.parentNode)\r
+                                                                                               tdElm.parentNode.removeChild(tdElm);\r
+                                                                               }\r
+\r
+                                                                               lastTDElm = tdElm;\r
+                                                                       }\r
+                                                               }\r
+\r
+                                                               select(-1);\r
+                                                       break;\r
+\r
+                                               case "mceTableSplitCells":\r
+                                                       if (!trElm || !tdElm)\r
+                                                               return true;\r
+\r
+                                                       var spandata = getColRowSpan(tdElm);\r
+\r
+                                                       var colspan = spandata["colspan"];\r
+                                                       var rowspan = spandata["rowspan"];\r
+\r
+                                                       // Needs splitting\r
+                                                       if (colspan > 1 || rowspan > 1) {\r
+                                                               // Generate cols\r
+                                                               tdElm.colSpan = 1;\r
+                                                               for (var i=1; i<colspan; i++) {\r
+                                                                       var newTD = doc.createElement("td");\r
+\r
+                                                                       if (!tinymce.isIE)\r
+                                                                               newTD.innerHTML = '<br mce_bogus="1"/>';\r
+\r
+                                                                       trElm.insertBefore(newTD, nextElm(tdElm, "TD,TH"));\r
+\r
+                                                                       if (rowspan > 1)\r
+                                                                               addRows(newTD, trElm, rowspan);\r
+                                                               }\r
+\r
+                                                               addRows(tdElm, trElm, rowspan);\r
+                                                       }\r
+\r
+                                                       // Apply visual aids\r
+                                                       tableElm = inst.dom.getParent(inst.selection.getNode(), "table");\r
+                                                       break;\r
+\r
+                                               case "mceTableMergeCells":\r
+                                                       var rows = [];\r
+                                                       var sel = inst.selection.getSel();\r
+                                                       var grid = getTableGrid(tableElm);\r
+\r
+                                                       if (tinymce.isIE || sel.rangeCount == 1) {\r
+                                                               if (user_interface) {\r
+                                                                       // Setup template\r
+                                                                       var sp = getColRowSpan(tdElm);\r
+\r
+                                                                       inst.windowManager.open({\r
+                                                                               url : url + '/merge_cells.htm',\r
+                                                                               width : 240 + parseInt(inst.getLang('table.merge_cells_delta_width', 0)),\r
+                                                                               height : 110 + parseInt(inst.getLang('table.merge_cells_delta_height', 0)),\r
+                                                                               inline : 1\r
+                                                                       }, {\r
+                                                                               action : "update",\r
+                                                                               numcols : sp.colspan,\r
+                                                                               numrows : sp.rowspan,\r
+                                                                               plugin_url : url\r
+                                                                       });\r
+\r
+                                                                       return true;\r
+                                                               } else {\r
+                                                                       var numRows = parseInt(value['numrows']);\r
+                                                                       var numCols = parseInt(value['numcols']);\r
+                                                                       var cpos = getCellPos(grid, tdElm);\r
+\r
+                                                                       if (("" + numRows) == "NaN")\r
+                                                                               numRows = 1;\r
+\r
+                                                                       if (("" + numCols) == "NaN")\r
+                                                                               numCols = 1;\r
+\r
+                                                                       // Get rows and cells\r
+                                                                       var tRows = tableElm.rows;\r
+                                                                       for (var y=cpos.rowindex; y<grid.length; y++) {\r
+                                                                               var rowCells = [];\r
+\r
+                                                                               for (var x=cpos.cellindex; x<grid[y].length; x++) {\r
+                                                                                       var td = getCell(grid, y, x);\r
+\r
+                                                                                       if (td && !inArray(rows, td) && !inArray(rowCells, td)) {\r
+                                                                                               var cp = getCellPos(grid, td);\r
+\r
+                                                                                               // Within range\r
+                                                                                               if (cp.cellindex < cpos.cellindex+numCols && cp.rowindex < cpos.rowindex+numRows)\r
+                                                                                                       rowCells[rowCells.length] = td;\r
+                                                                                       }\r
+                                                                               }\r
+\r
+                                                                               if (rowCells.length > 0)\r
+                                                                                       rows[rows.length] = rowCells;\r
+\r
+                                                                               var td = getCell(grid, cpos.rowindex, cpos.cellindex);\r
+                                                                               each(ed.dom.select('br', td), function(e, i) {\r
+                                                                                       if (i > 0 && ed.dom.getAttrib('mce_bogus'))\r
+                                                                                               ed.dom.remove(e);\r
+                                                                               });\r
+                                                                       }\r
+\r
+                                                                       //return true;\r
+                                                               }\r
+                                                       } else {\r
+                                                               var cells = [];\r
+                                                               var sel = inst.selection.getSel();\r
+                                                               var lastTR = null;\r
+                                                               var curRow = null;\r
+                                                               var x1 = -1, y1 = -1, x2, y2;\r
+\r
+                                                               // Only one cell selected, whats the point?\r
+                                                               if (sel.rangeCount < 2)\r
+                                                                       return true;\r
+\r
+                                                               // Get all selected cells\r
+                                                               for (var i=0; i<sel.rangeCount; i++) {\r
+                                                                       var rng = sel.getRangeAt(i);\r
+                                                                       var tdElm = rng.startContainer.childNodes[rng.startOffset];\r
+\r
+                                                                       if (!tdElm)\r
+                                                                               break;\r
+\r
+                                                                       if (tdElm.nodeName == "TD" || tdElm.nodeName == "TH")\r
+                                                                               cells[cells.length] = tdElm;\r
+                                                               }\r
+\r
+                                                               // Get rows and cells\r
+                                                               var tRows = tableElm.rows;\r
+                                                               for (var y=0; y<tRows.length; y++) {\r
+                                                                       var rowCells = [];\r
+\r
+                                                                       for (var x=0; x<tRows[y].cells.length; x++) {\r
+                                                                               var td = tRows[y].cells[x];\r
+\r
+                                                                               for (var i=0; i<cells.length; i++) {\r
+                                                                                       if (td == cells[i]) {\r
+                                                                                               rowCells[rowCells.length] = td;\r
+                                                                                       }\r
+                                                                               }\r
+                                                                       }\r
+\r
+                                                                       if (rowCells.length > 0)\r
+                                                                               rows[rows.length] = rowCells;\r
+                                                               }\r
+\r
+                                                               // Find selected cells in grid and box\r
+                                                               var curRow = [];\r
+                                                               var lastTR = null;\r
+                                                               for (var y=0; y<grid.length; y++) {\r
+                                                                       for (var x=0; x<grid[y].length; x++) {\r
+                                                                               grid[y][x]._selected = false;\r
+\r
+                                                                               for (var i=0; i<cells.length; i++) {\r
+                                                                                       if (grid[y][x] == cells[i]) {\r
+                                                                                               // Get start pos\r
+                                                                                               if (x1 == -1) {\r
+                                                                                                       x1 = x;\r
+                                                                                                       y1 = y;\r
+                                                                                               }\r
+\r
+                                                                                               // Get end pos\r
+                                                                                               x2 = x;\r
+                                                                                               y2 = y;\r
+\r
+                                                                                               grid[y][x]._selected = true;\r
+                                                                                       }\r
+                                                                               }\r
+                                                                       }\r
+                                                               }\r
+\r
+                                                               // Is there gaps, if so deny\r
+                                                               for (var y=y1; y<=y2; y++) {\r
+                                                                       for (var x=x1; x<=x2; x++) {\r
+                                                                               if (!grid[y][x]._selected) {\r
+                                                                                       alert("Invalid selection for merge.");\r
+                                                                                       return true;\r
+                                                                               }\r
+                                                                       }\r
+                                                               }\r
+                                                       }\r
+\r
+                                                       // Validate selection and get total rowspan and colspan\r
+                                                       var rowSpan = 1, colSpan = 1;\r
+\r
+                                                       // Validate horizontal and get total colspan\r
+                                                       var lastRowSpan = -1;\r
+                                                       for (var y=0; y<rows.length; y++) {\r
+                                                               var rowColSpan = 0;\r
+\r
+                                                               for (var x=0; x<rows[y].length; x++) {\r
+                                                                       var sd = getColRowSpan(rows[y][x]);\r
+\r
+                                                                       rowColSpan += sd['colspan'];\r
+\r
+                                                                       if (lastRowSpan != -1 && sd['rowspan'] != lastRowSpan) {\r
+                                                                               alert("Invalid selection for merge.");\r
+                                                                               return true;\r
+                                                                       }\r
+\r
+                                                                       lastRowSpan = sd['rowspan'];\r
+                                                               }\r
+\r
+                                                               if (rowColSpan > colSpan)\r
+                                                                       colSpan = rowColSpan;\r
+\r
+                                                               lastRowSpan = -1;\r
+                                                       }\r
+\r
+                                                       // Validate vertical and get total rowspan\r
+                                                       var lastColSpan = -1;\r
+                                                       for (var x=0; x<rows[0].length; x++) {\r
+                                                               var colRowSpan = 0;\r
+\r
+                                                               for (var y=0; y<rows.length; y++) {\r
+                                                                       var sd = getColRowSpan(rows[y][x]);\r
+\r
+                                                                       colRowSpan += sd['rowspan'];\r
+\r
+                                                                       if (lastColSpan != -1 && sd['colspan'] != lastColSpan) {\r
+                                                                               alert("Invalid selection for merge.");\r
+                                                                               return true;\r
+                                                                       }\r
+\r
+                                                                       lastColSpan = sd['colspan'];\r
+                                                               }\r
+\r
+                                                               if (colRowSpan > rowSpan)\r
+                                                                       rowSpan = colRowSpan;\r
+\r
+                                                               lastColSpan = -1;\r
+                                                       }\r
+\r
+                                                       // Setup td\r
+                                                       tdElm = rows[0][0];\r
+                                                       tdElm.rowSpan = rowSpan;\r
+                                                       tdElm.colSpan = colSpan;\r
+\r
+                                                       // Merge cells\r
+                                                       for (var y=0; y<rows.length; y++) {\r
+                                                               for (var x=0; x<rows[y].length; x++) {\r
+                                                                       var html = rows[y][x].innerHTML;\r
+                                                                       var chk = html.replace(/[ \t\r\n]/g, "");\r
+\r
+                                                                       if (chk != "<br/>" && chk != "<br>" && chk != '<br mce_bogus="1"/>' && (x+y > 0))\r
+                                                                               tdElm.innerHTML += html;\r
+\r
+                                                                       // Not current cell\r
+                                                                       if (rows[y][x] != tdElm && !rows[y][x]._deleted) {\r
+                                                                               var cpos = getCellPos(grid, rows[y][x]);\r
+                                                                               var tr = rows[y][x].parentNode;\r
+\r
+                                                                               tr.removeChild(rows[y][x]);\r
+                                                                               rows[y][x]._deleted = true;\r
+\r
+                                                                               // Empty TR, remove it\r
+                                                                               if (!tr.hasChildNodes()) {\r
+                                                                                       tr.parentNode.removeChild(tr);\r
+\r
+                                                                                       var lastCell = null;\r
+                                                                                       for (var x=0; cellElm = getCell(grid, cpos.rowindex, x); x++) {\r
+                                                                                               if (cellElm != lastCell && cellElm.rowSpan > 1)\r
+                                                                                                       cellElm.rowSpan--;\r
+\r
+                                                                                               lastCell = cellElm;\r
+                                                                                       }\r
+\r
+                                                                                       if (tdElm.rowSpan > 1)\r
+                                                                                               tdElm.rowSpan--;\r
+                                                                               }\r
+                                                                       }\r
+                                                               }\r
+                                                       }\r
+\r
+                                                       // Remove all but one bogus br\r
+                                                       each(ed.dom.select('br', tdElm), function(e, i) {\r
+                                                               if (i > 0 && ed.dom.getAttrib(e, 'mce_bogus'))\r
+                                                                       ed.dom.remove(e);\r
+                                                       });\r
+\r
+                                                       break;\r
+                                               }\r
+\r
+                                               tableElm = inst.dom.getParent(inst.selection.getNode(), "table");\r
+                                               inst.addVisual(tableElm);\r
+                                               inst.nodeChanged();\r
+                                       }\r
+\r
+                               return true;\r
+                       }\r
+\r
+                       // Pass to next handler in chain\r
+                       return false;\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('table', tinymce.plugins.TablePlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/table/js/cell.js b/jscripts/tiny_mce/plugins/table/js/cell.js
new file mode 100644 (file)
index 0000000..7d7f977
--- /dev/null
@@ -0,0 +1,259 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+var ed;\r
+\r
+function init() {\r
+       ed = tinyMCEPopup.editor;\r
+       tinyMCEPopup.resizeToInnerSize();\r
+\r
+       document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table');\r
+       document.getElementById('bordercolor_pickcontainer').innerHTML = getColorPickerHTML('bordercolor_pick','bordercolor');\r
+       document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor')\r
+\r
+       var inst = ed;\r
+       var tdElm = ed.dom.getParent(ed.selection.getNode(), "td,th");\r
+       var formObj = document.forms[0];\r
+       var st = ed.dom.parseStyle(ed.dom.getAttrib(tdElm, "style"));\r
+\r
+       // Get table cell data\r
+       var celltype = tdElm.nodeName.toLowerCase();\r
+       var align = ed.dom.getAttrib(tdElm, 'align');\r
+       var valign = ed.dom.getAttrib(tdElm, 'valign');\r
+       var width = trimSize(getStyle(tdElm, 'width', 'width'));\r
+       var height = trimSize(getStyle(tdElm, 'height', 'height'));\r
+       var bordercolor = convertRGBToHex(getStyle(tdElm, 'bordercolor', 'borderLeftColor'));\r
+       var bgcolor = convertRGBToHex(getStyle(tdElm, 'bgcolor', 'backgroundColor'));\r
+       var className = ed.dom.getAttrib(tdElm, 'class');\r
+       var backgroundimage = getStyle(tdElm, 'background', 'backgroundImage').replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");;\r
+       var id = ed.dom.getAttrib(tdElm, 'id');\r
+       var lang = ed.dom.getAttrib(tdElm, 'lang');\r
+       var dir = ed.dom.getAttrib(tdElm, 'dir');\r
+       var scope = ed.dom.getAttrib(tdElm, 'scope');\r
+\r
+       // Setup form\r
+       addClassesToList('class', 'table_cell_styles');\r
+       TinyMCE_EditableSelects.init();\r
+\r
+       formObj.bordercolor.value = bordercolor;\r
+       formObj.bgcolor.value = bgcolor;\r
+       formObj.backgroundimage.value = backgroundimage;\r
+       formObj.width.value = width;\r
+       formObj.height.value = height;\r
+       formObj.id.value = id;\r
+       formObj.lang.value = lang;\r
+       formObj.style.value = ed.dom.serializeStyle(st);\r
+       selectByValue(formObj, 'align', align);\r
+       selectByValue(formObj, 'valign', valign);\r
+       selectByValue(formObj, 'class', className, true, true);\r
+       selectByValue(formObj, 'celltype', celltype);\r
+       selectByValue(formObj, 'dir', dir);\r
+       selectByValue(formObj, 'scope', scope);\r
+\r
+       // Resize some elements\r
+       if (isVisible('backgroundimagebrowser'))\r
+               document.getElementById('backgroundimage').style.width = '180px';\r
+\r
+       updateColor('bordercolor_pick', 'bordercolor');\r
+       updateColor('bgcolor_pick', 'bgcolor');\r
+}\r
+\r
+function updateAction() {\r
+       var el, inst = ed, tdElm, trElm, tableElm, formObj = document.forms[0];\r
+\r
+       tinyMCEPopup.restoreSelection();\r
+       el = ed.selection.getNode();\r
+       tdElm = ed.dom.getParent(el, "td,th");\r
+       trElm = ed.dom.getParent(el, "tr");\r
+       tableElm = ed.dom.getParent(el, "table");\r
+\r
+       ed.execCommand('mceBeginUndoLevel');\r
+\r
+       switch (getSelectValue(formObj, 'action')) {\r
+               case "cell":\r
+                       var celltype = getSelectValue(formObj, 'celltype');\r
+                       var scope = getSelectValue(formObj, 'scope');\r
+\r
+                       if (ed.getParam("accessibility_warnings")) {\r
+                               if (celltype == "th" && scope == "")\r
+                                       var answer = confirm(ed.getLang('table_dlg.missing_scope', '', true));\r
+                               else\r
+                                       var answer = true;\r
+\r
+                               if (!answer)\r
+                                       return;\r
+                       }\r
+\r
+                       updateCell(tdElm);\r
+                       break;\r
+\r
+               case "row":\r
+                       var cell = trElm.firstChild;\r
+\r
+                       if (cell.nodeName != "TD" && cell.nodeName != "TH")\r
+                               cell = nextCell(cell);\r
+\r
+                       do {\r
+                               cell = updateCell(cell, true);\r
+                       } while ((cell = nextCell(cell)) != null);\r
+\r
+                       break;\r
+\r
+               case "all":\r
+                       var rows = tableElm.getElementsByTagName("tr");\r
+\r
+                       for (var i=0; i<rows.length; i++) {\r
+                               var cell = rows[i].firstChild;\r
+\r
+                               if (cell.nodeName != "TD" && cell.nodeName != "TH")\r
+                                       cell = nextCell(cell);\r
+\r
+                               do {\r
+                                       cell = updateCell(cell, true);\r
+                               } while ((cell = nextCell(cell)) != null);\r
+                       }\r
+\r
+                       break;\r
+       }\r
+\r
+       ed.addVisual();\r
+       ed.nodeChanged();\r
+       inst.execCommand('mceEndUndoLevel');\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function nextCell(elm) {\r
+       while ((elm = elm.nextSibling) != null) {\r
+               if (elm.nodeName == "TD" || elm.nodeName == "TH")\r
+                       return elm;\r
+       }\r
+\r
+       return null;\r
+}\r
+\r
+function updateCell(td, skip_id) {\r
+       var inst = ed;\r
+       var formObj = document.forms[0];\r
+       var curCellType = td.nodeName.toLowerCase();\r
+       var celltype = getSelectValue(formObj, 'celltype');\r
+       var doc = inst.getDoc();\r
+       var dom = ed.dom;\r
+\r
+       if (!skip_id)\r
+               td.setAttribute('id', formObj.id.value);\r
+\r
+       td.setAttribute('align', formObj.align.value);\r
+       td.setAttribute('vAlign', formObj.valign.value);\r
+       td.setAttribute('lang', formObj.lang.value);\r
+       td.setAttribute('dir', getSelectValue(formObj, 'dir'));\r
+       td.setAttribute('style', ed.dom.serializeStyle(ed.dom.parseStyle(formObj.style.value)));\r
+       td.setAttribute('scope', formObj.scope.value);\r
+       ed.dom.setAttrib(td, 'class', getSelectValue(formObj, 'class'));\r
+\r
+       // Clear deprecated attributes\r
+       ed.dom.setAttrib(td, 'width', '');\r
+       ed.dom.setAttrib(td, 'height', '');\r
+       ed.dom.setAttrib(td, 'bgColor', '');\r
+       ed.dom.setAttrib(td, 'borderColor', '');\r
+       ed.dom.setAttrib(td, 'background', '');\r
+\r
+       // Set styles\r
+       td.style.width = getCSSSize(formObj.width.value);\r
+       td.style.height = getCSSSize(formObj.height.value);\r
+       if (formObj.bordercolor.value != "") {\r
+               td.style.borderColor = formObj.bordercolor.value;\r
+               td.style.borderStyle = td.style.borderStyle == "" ? "solid" : td.style.borderStyle;\r
+               td.style.borderWidth = td.style.borderWidth == "" ? "1px" : td.style.borderWidth;\r
+       } else\r
+               td.style.borderColor = '';\r
+\r
+       td.style.backgroundColor = formObj.bgcolor.value;\r
+\r
+       if (formObj.backgroundimage.value != "")\r
+               td.style.backgroundImage = "url('" + formObj.backgroundimage.value + "')";\r
+       else\r
+               td.style.backgroundImage = '';\r
+\r
+       if (curCellType != celltype) {\r
+               // changing to a different node type\r
+               var newCell = doc.createElement(celltype);\r
+\r
+               for (var c=0; c<td.childNodes.length; c++)\r
+                       newCell.appendChild(td.childNodes[c].cloneNode(1));\r
+\r
+               for (var a=0; a<td.attributes.length; a++)\r
+                       ed.dom.setAttrib(newCell, td.attributes[a].name, ed.dom.getAttrib(td, td.attributes[a].name));\r
+\r
+               td.parentNode.replaceChild(newCell, td);\r
+               td = newCell;\r
+       }\r
+\r
+       dom.setAttrib(td, 'style', dom.serializeStyle(dom.parseStyle(td.style.cssText)));\r
+\r
+       return td;\r
+}\r
+\r
+function changedBackgroundImage() {\r
+       var formObj = document.forms[0];\r
+       var st = ed.dom.parseStyle(formObj.style.value);\r
+\r
+       st['background-image'] = "url('" + formObj.backgroundimage.value + "')";\r
+\r
+       formObj.style.value = ed.dom.serializeStyle(st);\r
+}\r
+\r
+function changedSize() {\r
+       var formObj = document.forms[0];\r
+       var st = ed.dom.parseStyle(formObj.style.value);\r
+\r
+       var width = formObj.width.value;\r
+       if (width != "")\r
+               st['width'] = getCSSSize(width);\r
+       else\r
+               st['width'] = "";\r
+\r
+       var height = formObj.height.value;\r
+       if (height != "")\r
+               st['height'] = getCSSSize(height);\r
+       else\r
+               st['height'] = "";\r
+\r
+       formObj.style.value = ed.dom.serializeStyle(st);\r
+}\r
+\r
+function changedColor() {\r
+       var formObj = document.forms[0];\r
+       var st = ed.dom.parseStyle(formObj.style.value);\r
+\r
+       st['background-color'] = formObj.bgcolor.value;\r
+       st['border-color'] = formObj.bordercolor.value;\r
+\r
+       formObj.style.value = ed.dom.serializeStyle(st);\r
+}\r
+\r
+function changedStyle() {\r
+       var formObj = document.forms[0];\r
+       var st = ed.dom.parseStyle(formObj.style.value);\r
+\r
+       if (st['background-image'])\r
+               formObj.backgroundimage.value = st['background-image'].replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");\r
+       else\r
+               formObj.backgroundimage.value = '';\r
+\r
+       if (st['width'])\r
+               formObj.width.value = trimSize(st['width']);\r
+\r
+       if (st['height'])\r
+               formObj.height.value = trimSize(st['height']);\r
+\r
+       if (st['background-color']) {\r
+               formObj.bgcolor.value = st['background-color'];\r
+               updateColor('bgcolor_pick','bgcolor');\r
+       }\r
+\r
+       if (st['border-color']) {\r
+               formObj.bordercolor.value = st['border-color'];\r
+               updateColor('bordercolor_pick','bordercolor');\r
+       }\r
+}\r
+\r
+tinyMCEPopup.onInit.add(init);\r
diff --git a/jscripts/tiny_mce/plugins/table/js/merge_cells.js b/jscripts/tiny_mce/plugins/table/js/merge_cells.js
new file mode 100644 (file)
index 0000000..4fd026b
--- /dev/null
@@ -0,0 +1,29 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+function init() {\r
+       var f = document.forms[0], v;\r
+\r
+       tinyMCEPopup.resizeToInnerSize();\r
+\r
+       f.numcols.value = tinyMCEPopup.getWindowArg('numcols', 1);\r
+       f.numrows.value = tinyMCEPopup.getWindowArg('numcols', 1);\r
+}\r
+\r
+function mergeCells() {\r
+       var args = [], f = document.forms[0];\r
+\r
+       tinyMCEPopup.restoreSelection();\r
+\r
+       if (!AutoValidator.validate(f)) {\r
+               alert(tinyMCEPopup.getLang('invalid_data'));\r
+               return false;\r
+       }\r
+\r
+       args["numcols"] = f.numcols.value;\r
+       args["numrows"] = f.numrows.value;\r
+\r
+       tinyMCEPopup.execCommand("mceTableMergeCells", false, args);\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+tinyMCEPopup.onInit.add(init);\r
diff --git a/jscripts/tiny_mce/plugins/table/js/row.js b/jscripts/tiny_mce/plugins/table/js/row.js
new file mode 100644 (file)
index 0000000..d25f635
--- /dev/null
@@ -0,0 +1,212 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+function init() {\r
+       tinyMCEPopup.resizeToInnerSize();\r
+\r
+       document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table');\r
+       document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor');\r
+\r
+       var inst = tinyMCEPopup.editor;\r
+       var dom = inst.dom;\r
+       var trElm = dom.getParent(inst.selection.getNode(), "tr");\r
+       var formObj = document.forms[0];\r
+       var st = dom.parseStyle(dom.getAttrib(trElm, "style"));\r
+\r
+       // Get table row data\r
+       var rowtype = trElm.parentNode.nodeName.toLowerCase();\r
+       var align = dom.getAttrib(trElm, 'align');\r
+       var valign = dom.getAttrib(trElm, 'valign');\r
+       var height = trimSize(getStyle(trElm, 'height', 'height'));\r
+       var className = dom.getAttrib(trElm, 'class');\r
+       var bgcolor = convertRGBToHex(getStyle(trElm, 'bgcolor', 'backgroundColor'));\r
+       var backgroundimage = getStyle(trElm, 'background', 'backgroundImage').replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");;\r
+       var id = dom.getAttrib(trElm, 'id');\r
+       var lang = dom.getAttrib(trElm, 'lang');\r
+       var dir = dom.getAttrib(trElm, 'dir');\r
+\r
+       // Setup form\r
+       addClassesToList('class', 'table_row_styles');\r
+       TinyMCE_EditableSelects.init();\r
+\r
+       formObj.bgcolor.value = bgcolor;\r
+       formObj.backgroundimage.value = backgroundimage;\r
+       formObj.height.value = height;\r
+       formObj.id.value = id;\r
+       formObj.lang.value = lang;\r
+       formObj.style.value = dom.serializeStyle(st);\r
+       selectByValue(formObj, 'align', align);\r
+       selectByValue(formObj, 'valign', valign);\r
+       selectByValue(formObj, 'class', className, true, true);\r
+       selectByValue(formObj, 'rowtype', rowtype);\r
+       selectByValue(formObj, 'dir', dir);\r
+\r
+       // Resize some elements\r
+       if (isVisible('backgroundimagebrowser'))\r
+               document.getElementById('backgroundimage').style.width = '180px';\r
+\r
+       updateColor('bgcolor_pick', 'bgcolor');\r
+}\r
+\r
+function updateAction() {\r
+       var inst = tinyMCEPopup.editor, dom = inst.dom, trElm, tableElm, formObj = document.forms[0];\r
+       var action = getSelectValue(formObj, 'action');\r
+\r
+       tinyMCEPopup.restoreSelection();\r
+       trElm = dom.getParent(inst.selection.getNode(), "tr");\r
+       tableElm = dom.getParent(inst.selection.getNode(), "table");\r
+\r
+       inst.execCommand('mceBeginUndoLevel');\r
+\r
+       switch (action) {\r
+               case "row":\r
+                       updateRow(trElm);\r
+                       break;\r
+\r
+               case "all":\r
+                       var rows = tableElm.getElementsByTagName("tr");\r
+\r
+                       for (var i=0; i<rows.length; i++)\r
+                               updateRow(rows[i], true);\r
+\r
+                       break;\r
+\r
+               case "odd":\r
+               case "even":\r
+                       var rows = tableElm.getElementsByTagName("tr");\r
+\r
+                       for (var i=0; i<rows.length; i++) {\r
+                               if ((i % 2 == 0 && action == "odd") || (i % 2 != 0 && action == "even"))\r
+                                       updateRow(rows[i], true, true);\r
+                       }\r
+\r
+                       break;\r
+       }\r
+\r
+       inst.addVisual();\r
+       inst.nodeChanged();\r
+       inst.execCommand('mceEndUndoLevel');\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function updateRow(tr_elm, skip_id, skip_parent) {\r
+       var inst = tinyMCEPopup.editor;\r
+       var formObj = document.forms[0];\r
+       var dom = inst.dom;\r
+       var curRowType = tr_elm.parentNode.nodeName.toLowerCase();\r
+       var rowtype = getSelectValue(formObj, 'rowtype');\r
+       var doc = inst.getDoc();\r
+\r
+       // Update row element\r
+       if (!skip_id)\r
+               tr_elm.setAttribute('id', formObj.id.value);\r
+\r
+       tr_elm.setAttribute('align', getSelectValue(formObj, 'align'));\r
+       tr_elm.setAttribute('vAlign', getSelectValue(formObj, 'valign'));\r
+       tr_elm.setAttribute('lang', formObj.lang.value);\r
+       tr_elm.setAttribute('dir', getSelectValue(formObj, 'dir'));\r
+       tr_elm.setAttribute('style', dom.serializeStyle(dom.parseStyle(formObj.style.value)));\r
+       dom.setAttrib(tr_elm, 'class', getSelectValue(formObj, 'class'));\r
+\r
+       // Clear deprecated attributes\r
+       tr_elm.setAttribute('background', '');\r
+       tr_elm.setAttribute('bgColor', '');\r
+       tr_elm.setAttribute('height', '');\r
+\r
+       // Set styles\r
+       tr_elm.style.height = getCSSSize(formObj.height.value);\r
+       tr_elm.style.backgroundColor = formObj.bgcolor.value;\r
+\r
+       if (formObj.backgroundimage.value != "")\r
+               tr_elm.style.backgroundImage = "url('" + formObj.backgroundimage.value + "')";\r
+       else\r
+               tr_elm.style.backgroundImage = '';\r
+\r
+       // Setup new rowtype\r
+       if (curRowType != rowtype && !skip_parent) {\r
+               // first, clone the node we are working on\r
+               var newRow = tr_elm.cloneNode(1);\r
+\r
+               // next, find the parent of its new destination (creating it if necessary)\r
+               var theTable = dom.getParent(tr_elm, "table");\r
+               var dest = rowtype;\r
+               var newParent = null;\r
+               for (var i = 0; i < theTable.childNodes.length; i++) {\r
+                       if (theTable.childNodes[i].nodeName.toLowerCase() == dest)\r
+                               newParent = theTable.childNodes[i];\r
+               }\r
+\r
+               if (newParent == null) {\r
+                       newParent = doc.createElement(dest);\r
+\r
+                       if (dest == "thead") {\r
+                               if (theTable.firstChild.nodeName == 'CAPTION')\r
+                                       inst.dom.insertAfter(newParent, theTable.firstChild);\r
+                               else\r
+                                       theTable.insertBefore(newParent, theTable.firstChild);\r
+                       } else\r
+                               theTable.appendChild(newParent);\r
+               }\r
+\r
+               // append the row to the new parent\r
+               newParent.appendChild(newRow);\r
+\r
+               // remove the original\r
+               tr_elm.parentNode.removeChild(tr_elm);\r
+\r
+               // set tr_elm to the new node\r
+               tr_elm = newRow;\r
+       }\r
+\r
+       dom.setAttrib(tr_elm, 'style', dom.serializeStyle(dom.parseStyle(tr_elm.style.cssText)));\r
+}\r
+\r
+function changedBackgroundImage() {\r
+       var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom;\r
+       var st = dom.parseStyle(formObj.style.value);\r
+\r
+       st['background-image'] = "url('" + formObj.backgroundimage.value + "')";\r
+\r
+       formObj.style.value = dom.serializeStyle(st);\r
+}\r
+\r
+function changedStyle() {\r
+       var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom;\r
+       var st = dom.parseStyle(formObj.style.value);\r
+\r
+       if (st['background-image'])\r
+               formObj.backgroundimage.value = st['background-image'].replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");\r
+       else\r
+               formObj.backgroundimage.value = '';\r
+\r
+       if (st['height'])\r
+               formObj.height.value = trimSize(st['height']);\r
+\r
+       if (st['background-color']) {\r
+               formObj.bgcolor.value = st['background-color'];\r
+               updateColor('bgcolor_pick','bgcolor');\r
+       }\r
+}\r
+\r
+function changedSize() {\r
+       var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom;\r
+       var st = dom.parseStyle(formObj.style.value);\r
+\r
+       var height = formObj.height.value;\r
+       if (height != "")\r
+               st['height'] = getCSSSize(height);\r
+       else\r
+               st['height'] = "";\r
+\r
+       formObj.style.value = dom.serializeStyle(st);\r
+}\r
+\r
+function changedColor() {\r
+       var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom;\r
+       var st = dom.parseStyle(formObj.style.value);\r
+\r
+       st['background-color'] = formObj.bgcolor.value;\r
+\r
+       formObj.style.value = dom.serializeStyle(st);\r
+}\r
+\r
+tinyMCEPopup.onInit.add(init);\r
diff --git a/jscripts/tiny_mce/plugins/table/js/table.js b/jscripts/tiny_mce/plugins/table/js/table.js
new file mode 100644 (file)
index 0000000..768c26e
--- /dev/null
@@ -0,0 +1,410 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+var action, orgTableWidth, orgTableHeight, dom = tinyMCEPopup.editor.dom;\r
+\r
+function insertTable() {\r
+       var formObj = document.forms[0];\r
+       var inst = tinyMCEPopup.editor, dom = inst.dom;\r
+       var cols = 2, rows = 2, border = 0, cellpadding = -1, cellspacing = -1, align, width, height, className, caption, frame, rules;\r
+       var html = '', capEl, elm;\r
+       var cellLimit, rowLimit, colLimit;\r
+\r
+       tinyMCEPopup.restoreSelection();\r
+\r
+       if (!AutoValidator.validate(formObj)) {\r
+               alert(inst.getLang('invalid_data'));\r
+               return false;\r
+       }\r
+\r
+       elm = dom.getParent(inst.selection.getNode(), 'table');\r
+\r
+       // Get form data\r
+       cols = formObj.elements['cols'].value;\r
+       rows = formObj.elements['rows'].value;\r
+       border = formObj.elements['border'].value != "" ? formObj.elements['border'].value  : 0;\r
+       cellpadding = formObj.elements['cellpadding'].value != "" ? formObj.elements['cellpadding'].value : "";\r
+       cellspacing = formObj.elements['cellspacing'].value != "" ? formObj.elements['cellspacing'].value : "";\r
+       align = formObj.elements['align'].options[formObj.elements['align'].selectedIndex].value;\r
+       frame = formObj.elements['frame'].options[formObj.elements['frame'].selectedIndex].value;\r
+       rules = formObj.elements['rules'].options[formObj.elements['rules'].selectedIndex].value;\r
+       width = formObj.elements['width'].value;\r
+       height = formObj.elements['height'].value;\r
+       bordercolor = formObj.elements['bordercolor'].value;\r
+       bgcolor = formObj.elements['bgcolor'].value;\r
+       className = formObj.elements['class'].options[formObj.elements['class'].selectedIndex].value;\r
+       id = formObj.elements['id'].value;\r
+       summary = formObj.elements['summary'].value;\r
+       style = formObj.elements['style'].value;\r
+       dir = formObj.elements['dir'].value;\r
+       lang = formObj.elements['lang'].value;\r
+       background = formObj.elements['backgroundimage'].value;\r
+       caption = formObj.elements['caption'].checked;\r
+\r
+       cellLimit = tinyMCEPopup.getParam('table_cell_limit', false);\r
+       rowLimit = tinyMCEPopup.getParam('table_row_limit', false);\r
+       colLimit = tinyMCEPopup.getParam('table_col_limit', false);\r
+\r
+       // Validate table size\r
+       if (colLimit && cols > colLimit) {\r
+               alert(inst.getLang('table_col_limit', '', true, {cols : colLimit}));\r
+               return false;\r
+       } else if (rowLimit && rows > rowLimit) {\r
+               alert(inst.getLang('table_row_limit', '', true, {rows : rowLimit}));\r
+               return false;\r
+       } else if (cellLimit && cols * rows > cellLimit) {\r
+               alert(inst.getLang('table_cell_limit', '', true, {cells : cellLimit}));\r
+               return false;\r
+       }\r
+\r
+       // Update table\r
+       if (action == "update") {\r
+               inst.execCommand('mceBeginUndoLevel');\r
+\r
+               dom.setAttrib(elm, 'cellPadding', cellpadding, true);\r
+               dom.setAttrib(elm, 'cellSpacing', cellspacing, true);\r
+               dom.setAttrib(elm, 'border', border);\r
+               dom.setAttrib(elm, 'align', align);\r
+               dom.setAttrib(elm, 'frame', frame);\r
+               dom.setAttrib(elm, 'rules', rules);\r
+               dom.setAttrib(elm, 'class', className);\r
+               dom.setAttrib(elm, 'style', style);\r
+               dom.setAttrib(elm, 'id', id);\r
+               dom.setAttrib(elm, 'summary', summary);\r
+               dom.setAttrib(elm, 'dir', dir);\r
+               dom.setAttrib(elm, 'lang', lang);\r
+\r
+               capEl = inst.dom.select('caption', elm)[0];\r
+\r
+               if (capEl && !caption)\r
+                       capEl.parentNode.removeChild(capEl);\r
+\r
+               if (!capEl && caption) {\r
+                       capEl = elm.ownerDocument.createElement('caption');\r
+\r
+                       if (!tinymce.isIE)\r
+                               capEl.innerHTML = '<br mce_bogus="1"/>';\r
+\r
+                       elm.insertBefore(capEl, elm.firstChild);\r
+               }\r
+\r
+               if (width && /(pt|em|cm)$/.test(width)) {\r
+                       dom.setStyle(elm, 'width', width);\r
+                       dom.setAttrib(elm, 'width', '');\r
+               } else {\r
+                       dom.setAttrib(elm, 'width', width, true);\r
+                       dom.setStyle(elm, 'width', '');\r
+               }\r
+\r
+               // Remove these since they are not valid XHTML\r
+               dom.setAttrib(elm, 'borderColor', '');\r
+               dom.setAttrib(elm, 'bgColor', '');\r
+               dom.setAttrib(elm, 'background', '');\r
+\r
+               if (height) {\r
+                       dom.setStyle(elm, 'height', height);\r
+                       dom.setAttrib(elm, 'height', '');\r
+               }\r
+\r
+               if (background != '')\r
+                       elm.style.backgroundImage = "url('" + background + "')";\r
+               else\r
+                       elm.style.backgroundImage = '';\r
+\r
+/*             if (tinyMCEPopup.getParam("inline_styles")) {\r
+                       if (width != '')\r
+                               elm.style.width = getCSSSize(width);\r
+               }*/\r
+\r
+               if (bordercolor != "") {\r
+                       elm.style.borderColor = bordercolor;\r
+                       elm.style.borderStyle = elm.style.borderStyle == "" ? "solid" : elm.style.borderStyle;\r
+                       elm.style.borderWidth = border == "" ? "1px" : border;\r
+               } else\r
+                       elm.style.borderColor = '';\r
+\r
+               elm.style.backgroundColor = bgcolor;\r
+               elm.style.height = getCSSSize(height);\r
+\r
+               inst.addVisual();\r
+\r
+               // Fix for stange MSIE align bug\r
+               //elm.outerHTML = elm.outerHTML;\r
+\r
+               inst.nodeChanged();\r
+               inst.execCommand('mceEndUndoLevel');\r
+\r
+               // Repaint if dimensions changed\r
+               if (formObj.width.value != orgTableWidth || formObj.height.value != orgTableHeight)\r
+                       inst.execCommand('mceRepaint');\r
+\r
+               tinyMCEPopup.close();\r
+               return true;\r
+       }\r
+\r
+       // Create new table\r
+       html += '<table';\r
+\r
+       html += makeAttrib('id', id);\r
+       html += makeAttrib('border', border);\r
+       html += makeAttrib('cellpadding', cellpadding);\r
+       html += makeAttrib('cellspacing', cellspacing);\r
+\r
+       if (width && /(pt|em|cm)$/.test(width)) {\r
+               if (style)\r
+                       style += '; ';\r
+\r
+               style += 'width: ' + width;\r
+       } else\r
+               html += makeAttrib('width', width);\r
+\r
+/*     if (height) {\r
+               if (style)\r
+                       style += '; ';\r
+\r
+               style += 'height: ' + height;\r
+       }*/\r
+\r
+       //html += makeAttrib('height', height);\r
+       //html += makeAttrib('bordercolor', bordercolor);\r
+       //html += makeAttrib('bgcolor', bgcolor);\r
+       html += makeAttrib('align', align);\r
+       html += makeAttrib('frame', frame);\r
+       html += makeAttrib('rules', rules);\r
+       html += makeAttrib('class', className);\r
+       html += makeAttrib('style', style);\r
+       html += makeAttrib('summary', summary);\r
+       html += makeAttrib('dir', dir);\r
+       html += makeAttrib('lang', lang);\r
+       html += '>';\r
+\r
+       if (caption) {\r
+               if (!tinymce.isIE)\r
+                       html += '<caption><br mce_bogus="1"/></caption>';\r
+               else\r
+                       html += '<caption></caption>';\r
+       }\r
+\r
+       for (var y=0; y<rows; y++) {\r
+               html += "<tr>";\r
+\r
+               for (var x=0; x<cols; x++) {\r
+                       if (!tinymce.isIE)\r
+                               html += '<td><br mce_bogus="1"/></td>';\r
+                       else\r
+                               html += '<td></td>';\r
+               }\r
+\r
+               html += "</tr>";\r
+       }\r
+\r
+       html += "</table>";\r
+\r
+       inst.execCommand('mceBeginUndoLevel');\r
+       inst.execCommand('mceInsertContent', false, html);\r
+       inst.addVisual();\r
+       inst.execCommand('mceEndUndoLevel');\r
+\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function makeAttrib(attrib, value) {\r
+       var formObj = document.forms[0];\r
+       var valueElm = formObj.elements[attrib];\r
+\r
+       if (typeof(value) == "undefined" || value == null) {\r
+               value = "";\r
+\r
+               if (valueElm)\r
+                       value = valueElm.value;\r
+       }\r
+\r
+       if (value == "")\r
+               return "";\r
+\r
+       // XML encode it\r
+       value = value.replace(/&/g, '&amp;');\r
+       value = value.replace(/\"/g, '&quot;');\r
+       value = value.replace(/</g, '&lt;');\r
+       value = value.replace(/>/g, '&gt;');\r
+\r
+       return ' ' + attrib + '="' + value + '"';\r
+}\r
+\r
+function init() {\r
+       tinyMCEPopup.resizeToInnerSize();\r
+\r
+       document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table');\r
+       document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table');\r
+       document.getElementById('bordercolor_pickcontainer').innerHTML = getColorPickerHTML('bordercolor_pick','bordercolor');\r
+       document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor');\r
+\r
+       var cols = 2, rows = 2, border = tinyMCEPopup.getParam('table_default_border', '0'), cellpadding = tinyMCEPopup.getParam('table_default_cellpadding', ''), cellspacing = tinyMCEPopup.getParam('table_default_cellspacing', '');\r
+       var align = "", width = "", height = "", bordercolor = "", bgcolor = "", className = "";\r
+       var id = "", summary = "", style = "", dir = "", lang = "", background = "", bgcolor = "", bordercolor = "", rules, frame;\r
+       var inst = tinyMCEPopup.editor, dom = inst.dom;\r
+       var formObj = document.forms[0];\r
+       var elm = dom.getParent(inst.selection.getNode(), "table");\r
+\r
+       action = tinyMCEPopup.getWindowArg('action');\r
+\r
+       if (!action)\r
+               action = elm ? "update" : "insert";\r
+\r
+       if (elm && action != "insert") {\r
+               var rowsAr = elm.rows;\r
+               var cols = 0;\r
+               for (var i=0; i<rowsAr.length; i++)\r
+                       if (rowsAr[i].cells.length > cols)\r
+                               cols = rowsAr[i].cells.length;\r
+\r
+               cols = cols;\r
+               rows = rowsAr.length;\r
+\r
+               st = dom.parseStyle(dom.getAttrib(elm, "style"));\r
+               border = trimSize(getStyle(elm, 'border', 'borderWidth'));\r
+               cellpadding = dom.getAttrib(elm, 'cellpadding', "");\r
+               cellspacing = dom.getAttrib(elm, 'cellspacing', "");\r
+               width = trimSize(getStyle(elm, 'width', 'width'));\r
+               height = trimSize(getStyle(elm, 'height', 'height'));\r
+               bordercolor = convertRGBToHex(getStyle(elm, 'bordercolor', 'borderLeftColor'));\r
+               bgcolor = convertRGBToHex(getStyle(elm, 'bgcolor', 'backgroundColor'));\r
+               align = dom.getAttrib(elm, 'align', align);\r
+               frame = dom.getAttrib(elm, 'frame');\r
+               rules = dom.getAttrib(elm, 'rules');\r
+               className = tinymce.trim(dom.getAttrib(elm, 'class').replace(/mceItem.+/g, ''));\r
+               id = dom.getAttrib(elm, 'id');\r
+               summary = dom.getAttrib(elm, 'summary');\r
+               style = dom.serializeStyle(st);\r
+               dir = dom.getAttrib(elm, 'dir');\r
+               lang = dom.getAttrib(elm, 'lang');\r
+               background = getStyle(elm, 'background', 'backgroundImage').replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");\r
+               formObj.caption.checked = elm.getElementsByTagName('caption').length > 0;\r
+\r
+               orgTableWidth = width;\r
+               orgTableHeight = height;\r
+\r
+               action = "update";\r
+               formObj.insert.value = inst.getLang('update');\r
+       }\r
+\r
+       addClassesToList('class', "table_styles");\r
+       TinyMCE_EditableSelects.init();\r
+\r
+       // Update form\r
+       selectByValue(formObj, 'align', align);\r
+       selectByValue(formObj, 'frame', frame);\r
+       selectByValue(formObj, 'rules', rules);\r
+       selectByValue(formObj, 'class', className, true, true);\r
+       formObj.cols.value = cols;\r
+       formObj.rows.value = rows;\r
+       formObj.border.value = border;\r
+       formObj.cellpadding.value = cellpadding;\r
+       formObj.cellspacing.value = cellspacing;\r
+       formObj.width.value = width;\r
+       formObj.height.value = height;\r
+       formObj.bordercolor.value = bordercolor;\r
+       formObj.bgcolor.value = bgcolor;\r
+       formObj.id.value = id;\r
+       formObj.summary.value = summary;\r
+       formObj.style.value = style;\r
+       formObj.dir.value = dir;\r
+       formObj.lang.value = lang;\r
+       formObj.backgroundimage.value = background;\r
+\r
+       updateColor('bordercolor_pick', 'bordercolor');\r
+       updateColor('bgcolor_pick', 'bgcolor');\r
+\r
+       // Resize some elements\r
+       if (isVisible('backgroundimagebrowser'))\r
+               document.getElementById('backgroundimage').style.width = '180px';\r
+\r
+       // Disable some fields in update mode\r
+       if (action == "update") {\r
+               formObj.cols.disabled = true;\r
+               formObj.rows.disabled = true;\r
+       }\r
+}\r
+\r
+function changedSize() {\r
+       var formObj = document.forms[0];\r
+       var st = dom.parseStyle(formObj.style.value);\r
+\r
+/*     var width = formObj.width.value;\r
+       if (width != "")\r
+               st['width'] = tinyMCEPopup.getParam("inline_styles") ? getCSSSize(width) : "";\r
+       else\r
+               st['width'] = "";*/\r
+\r
+       var height = formObj.height.value;\r
+       if (height != "")\r
+               st['height'] = getCSSSize(height);\r
+       else\r
+               st['height'] = "";\r
+\r
+       formObj.style.value = dom.serializeStyle(st);\r
+}\r
+\r
+function changedBackgroundImage() {\r
+       var formObj = document.forms[0];\r
+       var st = dom.parseStyle(formObj.style.value);\r
+\r
+       st['background-image'] = "url('" + formObj.backgroundimage.value + "')";\r
+\r
+       formObj.style.value = dom.serializeStyle(st);\r
+}\r
+\r
+function changedBorder() {\r
+       var formObj = document.forms[0];\r
+       var st = dom.parseStyle(formObj.style.value);\r
+\r
+       // Update border width if the element has a color\r
+       if (formObj.border.value != "" && formObj.bordercolor.value != "")\r
+               st['border-width'] = formObj.border.value + "px";\r
+\r
+       formObj.style.value = dom.serializeStyle(st);\r
+}\r
+\r
+function changedColor() {\r
+       var formObj = document.forms[0];\r
+       var st = dom.parseStyle(formObj.style.value);\r
+\r
+       st['background-color'] = formObj.bgcolor.value;\r
+\r
+       if (formObj.bordercolor.value != "") {\r
+               st['border-color'] = formObj.bordercolor.value;\r
+\r
+               // Add border-width if it's missing\r
+               if (!st['border-width'])\r
+                       st['border-width'] = formObj.border.value == "" ? "1px" : formObj.border.value + "px";\r
+       }\r
+\r
+       formObj.style.value = dom.serializeStyle(st);\r
+}\r
+\r
+function changedStyle() {\r
+       var formObj = document.forms[0];\r
+       var st = dom.parseStyle(formObj.style.value);\r
+\r
+       if (st['background-image'])\r
+               formObj.backgroundimage.value = st['background-image'].replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");\r
+       else\r
+               formObj.backgroundimage.value = '';\r
+\r
+       if (st['width'])\r
+               formObj.width.value = trimSize(st['width']);\r
+\r
+       if (st['height'])\r
+               formObj.height.value = trimSize(st['height']);\r
+\r
+       if (st['background-color']) {\r
+               formObj.bgcolor.value = st['background-color'];\r
+               updateColor('bgcolor_pick','bgcolor');\r
+       }\r
+\r
+       if (st['border-color']) {\r
+               formObj.bordercolor.value = st['border-color'];\r
+               updateColor('bordercolor_pick','bordercolor');\r
+       }\r
+}\r
+\r
+tinyMCEPopup.onInit.add(init);\r
diff --git a/jscripts/tiny_mce/plugins/table/langs/en_dlg.js b/jscripts/tiny_mce/plugins/table/langs/en_dlg.js
new file mode 100644 (file)
index 0000000..000332a
--- /dev/null
@@ -0,0 +1,74 @@
+tinyMCE.addI18n('en.table_dlg',{\r
+general_tab:"General",\r
+advanced_tab:"Advanced",\r
+general_props:"General properties",\r
+advanced_props:"Advanced properties",\r
+rowtype:"Row in table part",\r
+title:"Insert/Modify table",\r
+width:"Width",\r
+height:"Height",\r
+cols:"Cols",\r
+rows:"Rows",\r
+cellspacing:"Cellspacing",\r
+cellpadding:"Cellpadding",\r
+border:"Border",\r
+align:"Alignment",\r
+align_default:"Default",\r
+align_left:"Left",\r
+align_right:"Right",\r
+align_middle:"Center",\r
+row_title:"Table row properties",\r
+cell_title:"Table cell properties",\r
+cell_type:"Cell type",\r
+valign:"Vertical alignment",\r
+align_top:"Top",\r
+align_bottom:"Bottom",\r
+bordercolor:"Border color",\r
+bgcolor:"Background color",\r
+merge_cells_title:"Merge table cells",\r
+id:"Id",\r
+style:"Style",\r
+langdir:"Language direction",\r
+langcode:"Language code",\r
+mime:"Target MIME type",\r
+ltr:"Left to right",\r
+rtl:"Right to left",\r
+bgimage:"Background image",\r
+summary:"Summary",\r
+td:"Data",\r
+th:"Header",\r
+cell_cell:"Update current cell",\r
+cell_row:"Update all cells in row",\r
+cell_all:"Update all cells in table",\r
+row_row:"Update current row",\r
+row_odd:"Update odd rows in table",\r
+row_even:"Update even rows in table",\r
+row_all:"Update all rows in table",\r
+thead:"Table Head",\r
+tbody:"Table Body",\r
+tfoot:"Table Foot",\r
+scope:"Scope",\r
+rowgroup:"Row Group",\r
+colgroup:"Col Group",\r
+col_limit:"You've exceeded the maximum number of columns of {$cols}.",\r
+row_limit:"You've exceeded the maximum number of rows of {$rows}.",\r
+cell_limit:"You've exceeded the maximum number of cells of {$cells}.",\r
+missing_scope:"Are you sure you want to continue without specifying a scope for this table header cell. Without it, it may be difficult for some users with disabilities to understand the content or data displayed of the table.",\r
+caption:"Table caption",\r
+frame:"Frame",\r
+frame_none:"none",\r
+frame_groups:"groups",\r
+frame_rows:"rows",\r
+frame_cols:"cols",\r
+frame_all:"all",\r
+rules:"Rules",\r
+rules_void:"void",\r
+rules_above:"above",\r
+rules_below:"below",\r
+rules_hsides:"hsides",\r
+rules_lhs:"lhs",\r
+rules_rhs:"rhs",\r
+rules_vsides:"vsides",\r
+rules_box:"box",\r
+rules_border:"border"\r
+});
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/table/merge_cells.htm b/jscripts/tiny_mce/plugins/table/merge_cells.htm
new file mode 100644 (file)
index 0000000..30af106
--- /dev/null
@@ -0,0 +1,38 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#table_dlg.merge_cells_title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/validate.js?v=307"></script>\r
+       <script type="text/javascript" src="js/merge_cells.js?v=307"></script>\r
+       <base target="_self" />\r
+</head>\r
+<body style="margin: 8px" style="display: none">\r
+<form onsubmit="mergeCells();return false;" action="#">\r
+       <fieldset>\r
+               <legend>{#table_dlg.merge_cells_title}</legend>\r
+                 <table border="0" cellpadding="0" cellspacing="3" width="100%">\r
+                         <tr>\r
+                               <td>{#table_dlg.cols}:</td>\r
+                               <td align="right"><input type="text" name="numcols" value="" class="number min1 mceFocus" style="width: 30px" /></td>\r
+                         </tr>\r
+                         <tr>\r
+                               <td>{#table_dlg.rows}:</td>\r
+                               <td align="right"><input type="text" name="numrows" value="" class="number min1" style="width: 30px" /></td>\r
+                         </tr>\r
+                 </table>\r
+       </fieldset>\r
+\r
+       <div class="mceActionPanel">\r
+               <div style="float: left">\r
+                       <input type="submit" id="insert" name="insert" value="{#update}" />\r
+               </div>\r
+\r
+               <div style="float: right">\r
+                       <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+               </div>\r
+       </div>\r
+</form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/table/row.htm b/jscripts/tiny_mce/plugins/table/row.htm
new file mode 100644 (file)
index 0000000..00dd356
--- /dev/null
@@ -0,0 +1,161 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#table_dlg.row_title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/editable_selects.js?v=307"></script>\r
+       <script type="text/javascript" src="js/row.js?v=307"></script>\r
+       <link href="css/row.css?v=307" rel="stylesheet" type="text/css" />\r
+       <base target="_self" />\r
+</head>\r
+<body id="tablerow" style="display: none">\r
+       <form onsubmit="updateAction();return false;">\r
+               <div class="tabs">\r
+                       <ul>\r
+                               <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#table_dlg.general_tab}</a></span></li>\r
+                               <li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#table_dlg.advanced_tab}</a></span></li>\r
+                       </ul>\r
+               </div>\r
+\r
+               <div class="panel_wrapper">\r
+                       <div id="general_panel" class="panel current">\r
+                               <fieldset>\r
+                                       <legend>{#table_dlg.general_props}</legend>\r
+\r
+                                       <table border="0" cellpadding="4" cellspacing="0">\r
+                                               <tr>\r
+                                                       <td><label for="rowtype">{#table_dlg.rowtype}</label></td>\r
+                                                       <td class="col2">\r
+                                                               <select id="rowtype" name="rowtype" class="mceFocus">\r
+                                                                       <option value="thead">{#table_dlg.thead}</option>\r
+                                                                       <option value="tbody">{#table_dlg.tbody}</option>\r
+                                                                       <option value="tfoot">{#table_dlg.tfoot}</option>\r
+                                                               </select>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="align">{#table_dlg.align}</label></td>\r
+                                                       <td class="col2">\r
+                                                               <select id="align" name="align">\r
+                                                                       <option value="">{#not_set}</option>\r
+                                                                       <option value="center">{#table_dlg.align_middle}</option>\r
+                                                                       <option value="left">{#table_dlg.align_left}</option>\r
+                                                                       <option value="right">{#table_dlg.align_right}</option>\r
+                                                               </select>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="valign">{#table_dlg.valign}</label></td>\r
+                                                       <td class="col2">\r
+                                                               <select id="valign" name="valign">\r
+                                                                       <option value="">{#not_set}</option>\r
+                                                                       <option value="top">{#table_dlg.align_top}</option>\r
+                                                                       <option value="middle">{#table_dlg.align_middle}</option>\r
+                                                                       <option value="bottom">{#table_dlg.align_bottom}</option>\r
+                                                               </select>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr id="styleSelectRow">\r
+                                                       <td><label for="class">{#class_name}</label></td>\r
+                                                       <td class="col2">\r
+                                                               <select id="class" name="class" class="mceEditableSelect">\r
+                                                                       <option value="" selected="selected">{#not_set}</option>\r
+                                                               </select>\r
+                                                       </td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="height">{#table_dlg.height}</label></td>\r
+                                                       <td class="col2"><input name="height" type="text" id="height" value="" size="4" maxlength="4" onchange="changedSize();" /></td>\r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+                       </div>\r
+\r
+                       <div id="advanced_panel" class="panel">\r
+                               <fieldset>\r
+                                       <legend>{#table_dlg.advanced_props}</legend>\r
+\r
+                                       <table border="0" cellpadding="0" cellspacing="4">\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="id">{#table_dlg.id}</label></td> \r
+                                                       <td><input id="id" name="id" type="text" value="" style="width: 200px" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="style">{#table_dlg.style}</label></td>\r
+                                                       <td><input type="text" id="style" name="style" value="" style="width: 200px;" onchange="changedStyle();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="dir">{#table_dlg.langdir}</label></td> \r
+                                                       <td>\r
+                                                               <select id="dir" name="dir" style="width: 200px"> \r
+                                                                               <option value="">{#not_set}</option> \r
+                                                                               <option value="ltr">{#table_dlg.ltr}</option> \r
+                                                                               <option value="rtl">{#table_dlg.rtl}</option> \r
+                                                               </select>\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="lang">{#table_dlg.langcode}</label></td> \r
+                                                       <td>\r
+                                                               <input id="lang" name="lang" type="text" value="" style="width: 200px" />\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="backgroundimage">{#table_dlg.bgimage}</label></td> \r
+                                                       <td>\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="backgroundimage" name="backgroundimage" type="text" value="" style="width: 200px" onchange="changedBackgroundImage();" /></td>\r
+                                                                               <td id="backgroundimagebrowsercontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="bgcolor">{#table_dlg.bgcolor}</label></td> \r
+                                                       <td>\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="bgcolor" name="bgcolor" type="text" value="" size="9" onchange="updateColor('bgcolor_pick','bgcolor');changedColor();" /></td>\r
+                                                                               <td id="bgcolor_pickcontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td> \r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+                       </div>\r
+               </div>\r
+\r
+               <div class="mceActionPanel">\r
+                       <div>\r
+                               <select id="action" name="action">\r
+                                       <option value="row">{#table_dlg.row_row}</option>\r
+                                       <option value="odd">{#table_dlg.row_odd}</option>\r
+                                       <option value="even">{#table_dlg.row_even}</option>\r
+                                       <option value="all">{#table_dlg.row_all}</option>\r
+                               </select>\r
+                       </div>\r
+\r
+                       <div style="float: left">\r
+                               <div><input type="submit" id="insert" name="insert" value="{#update}" /></div>\r
+                       </div>\r
+\r
+                       <div style="float: right">\r
+                               <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+                       </div>\r
+               </div>\r
+       </form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/table/table.htm b/jscripts/tiny_mce/plugins/table/table.htm
new file mode 100644 (file)
index 0000000..446c909
--- /dev/null
@@ -0,0 +1,193 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#table_dlg.title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/validate.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/editable_selects.js?v=307"></script>\r
+       <script type="text/javascript" src="js/table.js?v=307"></script>\r
+       <link href="css/table.css?v=307" rel="stylesheet" type="text/css" />\r
+       <base target="_self" />\r
+</head>\r
+<body id="table" style="display: none">\r
+       <form onsubmit="insertTable();return false;" action="#">\r
+               <div class="tabs">\r
+                       <ul>\r
+                               <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#table_dlg.general_tab}</a></span></li>\r
+                               <li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#table_dlg.advanced_tab}</a></span></li>\r
+                       </ul>\r
+               </div>\r
+\r
+               <div class="panel_wrapper">\r
+                       <div id="general_panel" class="panel current">\r
+                               <fieldset>\r
+                                       <legend>{#table_dlg.general_props}</legend>\r
+                                         <table border="0" cellpadding="4" cellspacing="0" width="100%">\r
+                                                         <tr>\r
+                                                               <td><label id="colslabel" for="cols">{#table_dlg.cols}</label></td>\r
+                                                               <td><input id="cols" name="cols" type="text" value="" size="3" maxlength="3" class="required number min1 mceFocus" /></td>\r
+                                                               <td><label id="rowslabel" for="rows">{#table_dlg.rows}</label></td>\r
+                                                               <td><input id="rows" name="rows" type="text" value="" size="3" maxlength="3" class="required number min1" /></td>\r
+                                                         </tr>\r
+                                                         <tr>\r
+                                                               <td><label id="cellpaddinglabel" for="cellpadding">{#table_dlg.cellpadding}</label></td>\r
+                                                               <td><input id="cellpadding" name="cellpadding" type="text" value="" size="3" maxlength="3" class="number" /></td>\r
+                                                               <td><label id="cellspacinglabel" for="cellspacing">{#table_dlg.cellspacing}</label></td>\r
+                                                               <td><input id="cellspacing" name="cellspacing" type="text" value="" size="3" maxlength="3" class="number" /></td>\r
+                                                         </tr>\r
+                                                         <tr>\r
+                                                               <td><label id="alignlabel" for="align">{#table_dlg.align}</label></td>\r
+                                                               <td><select id="align" name="align">\r
+                                                                       <option value="">{#not_set}</option>\r
+                                                                       <option value="center">{#table_dlg.align_middle}</option>\r
+                                                                       <option value="left">{#table_dlg.align_left}</option>\r
+                                                                       <option value="right">{#table_dlg.align_right}</option>\r
+                                                                 </select></td>\r
+                                                               <td><label id="borderlabel" for="border">{#table_dlg.border}</label></td>\r
+                                                               <td><input id="border" name="border" type="text" value="" size="3" maxlength="3" onchange="changedBorder();" class="number" /></td>\r
+                                                         </tr>\r
+                                                         <tr id="width_row">\r
+                                                               <td><label id="widthlabel" for="width">{#table_dlg.width}</label></td>\r
+                                                               <td><input name="width" type="text" id="width" value="" size="4" maxlength="4" onchange="changedSize();" class="size" /></td>\r
+                                                               <td><label id="heightlabel" for="height">{#table_dlg.height}</label></td>\r
+                                                               <td><input name="height" type="text" id="height" value="" size="4" maxlength="4" onchange="changedSize();" class="size" /></td>\r
+                                                         </tr>\r
+                                                         <tr id="styleSelectRow">\r
+                                                               <td><label id="classlabel" for="class">{#class_name}</label></td>\r
+                                                               <td colspan="3">\r
+                                                                <select id="class" name="class" class="mceEditableSelect">\r
+                                                                       <option value="" selected>{#not_set}</option>\r
+                                                                </select></td>\r
+                                                         </tr>\r
+                                                         <tr>\r
+                                                               <td class="column1"><label for="caption">{#table_dlg.caption}</label></td> \r
+                                                               <td><input id="caption" name="caption" type="checkbox" class="checkbox" value="true" /></td> \r
+                                                         </tr>\r
+                                                       </table>\r
+                               </fieldset>\r
+                       </div>\r
+\r
+                       <div id="advanced_panel" class="panel">\r
+                               <fieldset>\r
+                                       <legend>{#table_dlg.advanced_props}</legend>\r
+\r
+                                       <table border="0" cellpadding="0" cellspacing="4">\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="id">{#table_dlg.id}</label></td> \r
+                                                       <td><input id="id" name="id" type="text" value="" class="advfield" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="summary">{#table_dlg.summary}</label></td> \r
+                                                       <td><input id="summary" name="summary" type="text" value="" class="advfield" /></td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label for="style">{#table_dlg.style}</label></td>\r
+                                                       <td><input type="text" id="style" name="style" value="" class="advfield" onchange="changedStyle();" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label id="langlabel" for="lang">{#table_dlg.langcode}</label></td> \r
+                                                       <td>\r
+                                                               <input id="lang" name="lang" type="text" value="" class="advfield" />\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="backgroundimage">{#table_dlg.bgimage}</label></td> \r
+                                                       <td>\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="backgroundimage" name="backgroundimage" type="text" value="" class="advfield" onchange="changedBackgroundImage();" /></td>\r
+                                                                               <td id="backgroundimagebrowsercontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="frame">{#table_dlg.frame}</label></td> \r
+                                                       <td>\r
+                                                               <select id="frame" name="frame" class="advfield"> \r
+                                                                               <option value="">{#not_set}</option> \r
+                                                                               <option value="none">{#table_dlg.frame_none}</option>\r
+                                                                               <option value="groups">{#table_dlg.frame_groups}</option>\r
+                                                                               <option value="rows">{#table_dlg.frame_rows}</option>\r
+                                                                               <option value="cols">{#table_dlg.frame_cols}</option>\r
+                                                                               <option value="all">{#table_dlg.frame_all}</option>\r
+                                                               </select>\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="rules">{#table_dlg.rules}</label></td> \r
+                                                       <td>\r
+                                                               <select id="rules" name="rules" class="advfield"> \r
+                                                                               <option value="">{#not_set}</option> \r
+                                                                               <option value="void">{#table_dlg.rules_void}</option>\r
+                                                                               <option value="above">{#table_dlg.rules_above}</option> \r
+                                                                               <option value="below">{#table_dlg.rules_below}</option> \r
+                                                                               <option value="hsides">{#table_dlg.rules_hsides}</option> \r
+                                                                               <option value="lhs">{#table_dlg.rules_lhs}</option> \r
+                                                                               <option value="rhs">{#table_dlg.rules_rhs}</option> \r
+                                                                               <option value="vsides">{#table_dlg.rules_vsides}</option> \r
+                                                                               <option value="box">{#table_dlg.rules_box}</option> \r
+                                                                               <option value="border">{#table_dlg.rules_border}</option> \r
+                                                                       </select>\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="dir">{#table_dlg.langdir}</label></td> \r
+                                                       <td>\r
+                                                               <select id="dir" name="dir" class="advfield"> \r
+                                                                               <option value="">{#not_set}</option> \r
+                                                                               <option value="ltr">{#table_dlg.ltr}</option> \r
+                                                                               <option value="rtl">{#table_dlg.rtl}</option> \r
+                                                               </select>\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="bordercolor">{#table_dlg.bordercolor}</label></td> \r
+                                                       <td>\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="bordercolor" name="bordercolor" type="text" value="" size="9" onchange="updateColor('bordercolor_pick','bordercolor');changedColor();" /></td>\r
+                                                                               <td id="bordercolor_pickcontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td> \r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td class="column1"><label for="bgcolor">{#table_dlg.bgcolor}</label></td> \r
+                                                       <td>\r
+                                                               <table border="0" cellpadding="0" cellspacing="0">\r
+                                                                       <tr>\r
+                                                                               <td><input id="bgcolor" name="bgcolor" type="text" value="" size="9" onchange="updateColor('bgcolor_pick','bgcolor');changedColor();" /></td>\r
+                                                                               <td id="bgcolor_pickcontainer">&nbsp;</td>\r
+                                                                       </tr>\r
+                                                               </table>\r
+                                                       </td> \r
+                                               </tr>\r
+                                       </table>\r
+                               </fieldset>\r
+                       </div>\r
+               </div>\r
+\r
+               <div class="mceActionPanel">\r
+                       <div style="float: left">\r
+                               <input type="submit" id="insert" name="insert" value="{#insert}" />\r
+                       </div>\r
+\r
+                       <div style="float: right">\r
+                               <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+                       </div>\r
+               </div>\r
+       </form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/template/blank.htm b/jscripts/tiny_mce/plugins/template/blank.htm
new file mode 100644 (file)
index 0000000..ecde53f
--- /dev/null
@@ -0,0 +1,12 @@
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>blank_page</title>\r
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+       <script type="text/javascript">\r
+               parent.TemplateDialog.loadCSSFiles(document);\r
+       </script>\r
+</head>\r
+<body id="mceTemplatePreview" class="mceContentBody">\r
+\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/template/css/template.css b/jscripts/tiny_mce/plugins/template/css/template.css
new file mode 100644 (file)
index 0000000..2d23a49
--- /dev/null
@@ -0,0 +1,23 @@
+#frmbody {\r
+       padding: 10px;\r
+       background-color: #FFF;\r
+       border: 1px solid #CCC;\r
+}\r
+\r
+.frmRow {\r
+       margin-bottom: 10px;\r
+}\r
+\r
+#templatesrc {\r
+       border: none;\r
+       width: 320px;\r
+       height: 240px;\r
+}\r
+\r
+.title {\r
+       padding-bottom: 5px;\r
+}\r
+\r
+.mceActionPanel {\r
+       padding-top: 5px;\r
+}\r
diff --git a/jscripts/tiny_mce/plugins/template/editor_plugin.js b/jscripts/tiny_mce/plugins/template/editor_plugin.js
new file mode 100644 (file)
index 0000000..0f7fb01
--- /dev/null
@@ -0,0 +1 @@
+(function(){var each=tinymce.each;tinymce.create('tinymce.plugins.TemplatePlugin',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mceTemplate',function(ui){ed.windowManager.open({file:url+'/template.htm',width:ed.getParam('template_popup_width',750),height:ed.getParam('template_popup_height',600),inline:1},{plugin_url:url});});ed.addCommand('mceInsertTemplate',t._insertTemplate,t);ed.addButton('template',{title:'template.desc',cmd:'mceTemplate'});ed.onPreProcess.add(function(ed,o){var dom=ed.dom;each(dom.select('div',o.node),function(e){if(dom.hasClass(e,'mceTmpl')){each(dom.select('*',e),function(e){if(dom.hasClass(e,ed.getParam('template_mdate_classes','mdate').replace(/\s+/g,'|')))e.innerHTML=t._getDateTime(new Date(),ed.getParam("template_mdate_format",ed.getLang("template.mdate_format")));});t._replaceVals(e);}});});},getInfo:function(){return{longname:'Template plugin',author:'Moxiecode Systems AB',authorurl:'http://www.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/template',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_insertTemplate:function(ui,v){var t=this,ed=t.editor,h,el,dom=ed.dom,sel=ed.selection.getContent();h=v.content;each(t.editor.getParam('template_replace_values'),function(v,k){if(typeof(v)!='function')h=h.replace(new RegExp('\\{\\$'+k+'\\}','g'),v);});el=dom.create('div',null,h);n=dom.select('.mceTmpl',el);if(n&&n.length>0){el=dom.create('div',null);el.appendChild(n[0].cloneNode(true));}function hasClass(n,c){return new RegExp('\\b'+c+'\\b','g').test(n.className);};each(dom.select('*',el),function(n){if(hasClass(n,ed.getParam('template_cdate_classes','cdate').replace(/\s+/g,'|')))n.innerHTML=t._getDateTime(new Date(),ed.getParam("template_cdate_format",ed.getLang("template.cdate_format")));if(hasClass(n,ed.getParam('template_mdate_classes','mdate').replace(/\s+/g,'|')))n.innerHTML=t._getDateTime(new Date(),ed.getParam("template_mdate_format",ed.getLang("template.mdate_format")));if(hasClass(n,ed.getParam('template_selected_content_classes','selcontent').replace(/\s+/g,'|')))n.innerHTML=sel;});t._replaceVals(el);ed.execCommand('mceInsertContent',false,el.innerHTML);ed.addVisual();},_replaceVals:function(e){var dom=this.editor.dom,vl=this.editor.getParam('template_replace_values');each(dom.select('*',e),function(e){each(vl,function(v,k){if(dom.hasClass(e,k)){if(typeof(vl[k])=='function')vl[k](e);}});});},_getDateTime:function(d,fmt){if(!fmt)return"";function addZeros(value,len){var i;value=""+value;if(value.length<len){for(i=0;i<(len-value.length);i++)value="0"+value;}return value;}fmt=fmt.replace("%D","%m/%d/%y");fmt=fmt.replace("%r","%I:%M:%S %p");fmt=fmt.replace("%Y",""+d.getFullYear());fmt=fmt.replace("%y",""+d.getYear());fmt=fmt.replace("%m",addZeros(d.getMonth()+1,2));fmt=fmt.replace("%d",addZeros(d.getDate(),2));fmt=fmt.replace("%H",""+addZeros(d.getHours(),2));fmt=fmt.replace("%M",""+addZeros(d.getMinutes(),2));fmt=fmt.replace("%S",""+addZeros(d.getSeconds(),2));fmt=fmt.replace("%I",""+((d.getHours()+11)%12+1));fmt=fmt.replace("%p",""+(d.getHours()<12?"AM":"PM"));fmt=fmt.replace("%B",""+tinyMCE.getLang("template_months_long").split(',')[d.getMonth()]);fmt=fmt.replace("%b",""+tinyMCE.getLang("template_months_short").split(',')[d.getMonth()]);fmt=fmt.replace("%A",""+tinyMCE.getLang("template_day_long").split(',')[d.getDay()]);fmt=fmt.replace("%a",""+tinyMCE.getLang("template_day_short").split(',')[d.getDay()]);fmt=fmt.replace("%%","%");return fmt;}});tinymce.PluginManager.add('template',tinymce.plugins.TemplatePlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/template/editor_plugin_src.js b/jscripts/tiny_mce/plugins/template/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..73ab39e
--- /dev/null
@@ -0,0 +1,156 @@
+/**\r
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       var each = tinymce.each;\r
+\r
+       tinymce.create('tinymce.plugins.TemplatePlugin', {\r
+               init : function(ed, url) {\r
+                       var t = this;\r
+\r
+                       t.editor = ed;\r
+\r
+                       // Register commands\r
+                       ed.addCommand('mceTemplate', function(ui) {\r
+                               ed.windowManager.open({\r
+                                       file : url + '/template.htm',\r
+                                       width : ed.getParam('template_popup_width', 750),\r
+                                       height : ed.getParam('template_popup_height', 600),\r
+                                       inline : 1\r
+                               }, {\r
+                                       plugin_url : url\r
+                               });\r
+                       });\r
+\r
+                       ed.addCommand('mceInsertTemplate', t._insertTemplate, t);\r
+\r
+                       // Register buttons\r
+                       ed.addButton('template', {title : 'template.desc', cmd : 'mceTemplate'});\r
+\r
+                       ed.onPreProcess.add(function(ed, o) {\r
+                               var dom = ed.dom;\r
+\r
+                               each(dom.select('div', o.node), function(e) {\r
+                                       if (dom.hasClass(e, 'mceTmpl')) {\r
+                                               each(dom.select('*', e), function(e) {\r
+                                                       if (dom.hasClass(e, ed.getParam('template_mdate_classes', 'mdate').replace(/\s+/g, '|')))\r
+                                                               e.innerHTML = t._getDateTime(new Date(), ed.getParam("template_mdate_format", ed.getLang("template.mdate_format")));\r
+                                               });\r
+\r
+                                               t._replaceVals(e);\r
+                                       }\r
+                               });\r
+                       });\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Template plugin',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://www.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/template',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               },\r
+\r
+               _insertTemplate : function(ui, v) {\r
+                       var t = this, ed = t.editor, h, el, dom = ed.dom, sel = ed.selection.getContent();\r
+\r
+                       h = v.content;\r
+\r
+                       each(t.editor.getParam('template_replace_values'), function(v, k) {\r
+                               if (typeof(v) != 'function')\r
+                                       h = h.replace(new RegExp('\\{\\$' + k + '\\}', 'g'), v);\r
+                       });\r
+\r
+                       el = dom.create('div', null, h);\r
+\r
+                       // Find template element within div\r
+                       n = dom.select('.mceTmpl', el);\r
+                       if (n && n.length > 0) {\r
+                               el = dom.create('div', null);\r
+                               el.appendChild(n[0].cloneNode(true));\r
+                       }\r
+\r
+                       function hasClass(n, c) {\r
+                               return new RegExp('\\b' + c + '\\b', 'g').test(n.className);\r
+                       };\r
+\r
+                       each(dom.select('*', el), function(n) {\r
+                               // Replace cdate\r
+                               if (hasClass(n, ed.getParam('template_cdate_classes', 'cdate').replace(/\s+/g, '|')))\r
+                                       n.innerHTML = t._getDateTime(new Date(), ed.getParam("template_cdate_format", ed.getLang("template.cdate_format")));\r
+\r
+                               // Replace mdate\r
+                               if (hasClass(n, ed.getParam('template_mdate_classes', 'mdate').replace(/\s+/g, '|')))\r
+                                       n.innerHTML = t._getDateTime(new Date(), ed.getParam("template_mdate_format", ed.getLang("template.mdate_format")));\r
+\r
+                               // Replace selection\r
+                               if (hasClass(n, ed.getParam('template_selected_content_classes', 'selcontent').replace(/\s+/g, '|')))\r
+                                       n.innerHTML = sel;\r
+                       });\r
+\r
+                       t._replaceVals(el);\r
+\r
+                       ed.execCommand('mceInsertContent', false, el.innerHTML);\r
+                       ed.addVisual();\r
+               },\r
+\r
+               _replaceVals : function(e) {\r
+                       var dom = this.editor.dom, vl = this.editor.getParam('template_replace_values');\r
+\r
+                       each(dom.select('*', e), function(e) {\r
+                               each(vl, function(v, k) {\r
+                                       if (dom.hasClass(e, k)) {\r
+                                               if (typeof(vl[k]) == 'function')\r
+                                                       vl[k](e);\r
+                                       }\r
+                               });\r
+                       });\r
+               },\r
+\r
+               _getDateTime : function(d, fmt) {\r
+                               if (!fmt)\r
+                                       return "";\r
+\r
+                               function addZeros(value, len) {\r
+                                       var i;\r
+\r
+                                       value = "" + value;\r
+\r
+                                       if (value.length < len) {\r
+                                               for (i=0; i<(len-value.length); i++)\r
+                                                       value = "0" + value;\r
+                                       }\r
+\r
+                                       return value;\r
+                               }\r
+\r
+                               fmt = fmt.replace("%D", "%m/%d/%y");\r
+                               fmt = fmt.replace("%r", "%I:%M:%S %p");\r
+                               fmt = fmt.replace("%Y", "" + d.getFullYear());\r
+                               fmt = fmt.replace("%y", "" + d.getYear());\r
+                               fmt = fmt.replace("%m", addZeros(d.getMonth()+1, 2));\r
+                               fmt = fmt.replace("%d", addZeros(d.getDate(), 2));\r
+                               fmt = fmt.replace("%H", "" + addZeros(d.getHours(), 2));\r
+                               fmt = fmt.replace("%M", "" + addZeros(d.getMinutes(), 2));\r
+                               fmt = fmt.replace("%S", "" + addZeros(d.getSeconds(), 2));\r
+                               fmt = fmt.replace("%I", "" + ((d.getHours() + 11) % 12 + 1));\r
+                               fmt = fmt.replace("%p", "" + (d.getHours() < 12 ? "AM" : "PM"));\r
+                               fmt = fmt.replace("%B", "" + tinyMCE.getLang("template_months_long").split(',')[d.getMonth()]);\r
+                               fmt = fmt.replace("%b", "" + tinyMCE.getLang("template_months_short").split(',')[d.getMonth()]);\r
+                               fmt = fmt.replace("%A", "" + tinyMCE.getLang("template_day_long").split(',')[d.getDay()]);\r
+                               fmt = fmt.replace("%a", "" + tinyMCE.getLang("template_day_short").split(',')[d.getDay()]);\r
+                               fmt = fmt.replace("%%", "%");\r
+\r
+                               return fmt;\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('template', tinymce.plugins.TemplatePlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/template/js/template.js b/jscripts/tiny_mce/plugins/template/js/template.js
new file mode 100644 (file)
index 0000000..a8e64b1
--- /dev/null
@@ -0,0 +1,100 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+var TemplateDialog = {\r
+       preInit : function() {\r
+               var url = tinyMCEPopup.getParam("template_external_list_url");\r
+\r
+               if (url != null)\r
+                       document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></sc'+'ript>');\r
+       },\r
+\r
+       init : function() {\r
+               var ed = tinyMCEPopup.editor, tsrc, sel, x, u;\r
+\r
+               tsrc = ed.getParam("template_templates", false);\r
+               sel = document.getElementById('tpath');\r
+\r
+               // Setup external template list\r
+               if (!tsrc && typeof(tinyMCETemplateList) != 'undefined') {\r
+                       for (x=0, tsrc = []; x<tinyMCETemplateList.length; x++)\r
+                               tsrc.push({title : tinyMCETemplateList[x][0], src : tinyMCETemplateList[x][1], description : tinyMCETemplateList[x][2]});\r
+               }\r
+\r
+               for (x=0; x<tsrc.length; x++)\r
+                       sel.options[sel.options.length] = new Option(tsrc[x].title, tinyMCEPopup.editor.documentBaseURI.toAbsolute(tsrc[x].src));\r
+\r
+               this.resize();\r
+       },\r
+\r
+       resize : function() {\r
+               var w, h, e;\r
+\r
+               if (!self.innerWidth) {\r
+                       w = document.body.clientWidth - 50;\r
+                       h = document.body.clientHeight - 160;\r
+               } else {\r
+                       w = self.innerWidth - 50;\r
+                       h = self.innerHeight - 170;\r
+               }\r
+\r
+               e = document.getElementById('templatesrc');\r
+\r
+               if (e) {\r
+                       e.style.height = Math.abs(h) + 'px';\r
+                       e.style.width  = Math.abs(w - 5) + 'px';\r
+               }\r
+       },\r
+\r
+       loadCSSFiles : function(d) {\r
+               var ed = tinyMCEPopup.editor;\r
+\r
+               tinymce.each(ed.getParam("content_css", '').split(','), function(u) {\r
+                       d.write('<link href="' + ed.documentBaseURI.toAbsolute(u) + '" rel="stylesheet" type="text/css" />');\r
+               });\r
+       },\r
+\r
+       selectTemplate : function(u) {\r
+               var d = window.frames['templatesrc'].document;\r
+\r
+               if (!u)\r
+                       return;\r
+\r
+               d.body.innerHTML = this.templateHTML = this.getFileContents(u);\r
+       },\r
+\r
+       insert : function() {\r
+               tinyMCEPopup.execCommand('mceInsertTemplate', false, {\r
+                       content : this.templateHTML,\r
+                       selection : tinyMCEPopup.editor.selection.getContent()\r
+               });\r
+\r
+               tinyMCEPopup.close();\r
+       },\r
+\r
+       getFileContents : function(u) {\r
+               var x, d, t = 'text/plain';\r
+\r
+               function g(s) {\r
+                       x = 0;\r
+\r
+                       try {\r
+                               x = new ActiveXObject(s);\r
+                       } catch (s) {\r
+                       }\r
+\r
+                       return x;\r
+               };\r
+\r
+               x = window.ActiveXObject ? g('Msxml2.XMLHTTP') || g('Microsoft.XMLHTTP') : new XMLHttpRequest();\r
+\r
+               // Synchronous AJAX load file\r
+               x.overrideMimeType && x.overrideMimeType(t);\r
+               x.open("GET", u, false);\r
+               x.send(null);\r
+\r
+               return x.responseText;\r
+       }\r
+};\r
+\r
+TemplateDialog.preInit();\r
+tinyMCEPopup.onInit.add(TemplateDialog.init, TemplateDialog);\r
diff --git a/jscripts/tiny_mce/plugins/template/langs/en_dlg.js b/jscripts/tiny_mce/plugins/template/langs/en_dlg.js
new file mode 100644 (file)
index 0000000..2471c3f
--- /dev/null
@@ -0,0 +1,15 @@
+tinyMCE.addI18n('en.template_dlg',{\r
+title:"Templates",\r
+label:"Template",\r
+desc_label:"Description",\r
+desc:"Insert predefined template content",\r
+select:"Select a template",\r
+preview:"Preview",\r
+warning:"Warning: Updating a template with a different one may cause data loss.",\r
+mdate_format:"%Y-%m-%d %H:%M:%S",\r
+cdate_format:"%Y-%m-%d %H:%M:%S",\r
+months_long:"January,February,March,April,May,June,July,August,September,October,November,December",\r
+months_short:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",\r
+day_long:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday",\r
+day_short:"Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun"\r
+});
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/template/template.htm b/jscripts/tiny_mce/plugins/template/template.htm
new file mode 100644 (file)
index 0000000..e26a2a9
--- /dev/null
@@ -0,0 +1,39 @@
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#template_dlg.title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="js/template.js?v=307"></script>\r
+       <link href="css/template.css?v=307" rel="stylesheet" type="text/css" />\r
+       <base target="_self" />\r
+</head>\r
+<body onresize="TemplateDialog.resize();"> \r
+       <form onsubmit="TemplateDialog.insert();return false;">\r
+               <div id="frmbody">\r
+                       <div class="title">{#template_dlg.desc}</div>\r
+                       <div class="frmRow"><label for="tpath" title="{#template_dlg.select}">{#template_dlg.label}:</label>\r
+                       <select id="tpath" name="tpath" onchange="TemplateDialog.selectTemplate(this.options[this.selectedIndex].value);" class="mceFocus">\r
+                               <option value="">{#template_dlg.select}...</option>\r
+                       </select>\r
+                       <span id="warning"></span></div>\r
+                       <div class="frmRow"><label for="tdesc">{#template_dlg.desc_label}:</label>\r
+                       <span id="tmpldesc"></span></div>\r
+                       <fieldset>\r
+                               <legend>{#template_dlg.preview}</legend>\r
+                               <iframe id="templatesrc" name="templatesrc" src="blank.htm" width="690" height="400" frameborder="0"></iframe>\r
+                       </fieldset>\r
+               </div>\r
+               \r
+               <div class="mceActionPanel">\r
+                       <div style="float: left">\r
+                               <input type="submit" id="insert" name="insert" value="{#insert}" />\r
+                       </div>\r
+\r
+                       <div style="float: right">\r
+                               <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+                       </div>\r
+\r
+                       <br style="clear:both" />\r
+               </div>\r
+       </form>\r
+</body> \r
+</html> \r
diff --git a/jscripts/tiny_mce/plugins/visualchars/editor_plugin.js b/jscripts/tiny_mce/plugins/visualchars/editor_plugin.js
new file mode 100644 (file)
index 0000000..e1e4238
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.VisualChars',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mceVisualChars',t._toggleVisualChars,t);ed.addButton('visualchars',{title:'visualchars.desc',cmd:'mceVisualChars'});ed.onBeforeGetContent.add(function(ed,o){if(t.state){t.state=true;t._toggleVisualChars();}});},getInfo:function(){return{longname:'Visual characters',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/visualchars',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_toggleVisualChars:function(){var t=this,ed=t.editor,nl,i,h,d=ed.getDoc(),b=ed.getBody(),nv,s=ed.selection,bo;t.state=!t.state;ed.controlManager.setActive('visualchars',t.state);if(t.state){nl=[];tinymce.walk(b,function(n){if(n.nodeType==3&&n.nodeValue&&n.nodeValue.indexOf('\u00a0')!=-1)nl.push(n);},'childNodes');for(i=0;i<nl.length;i++){nv=nl[i].nodeValue;nv=nv.replace(/(\u00a0+)/g,'<span class="mceItemHidden mceVisualNbsp">$1</span>');nv=nv.replace(/\u00a0/g,'\u00b7');ed.dom.setOuterHTML(nl[i],nv,d);}}else{nl=tinymce.grep(ed.dom.select('span',b),function(n){return ed.dom.hasClass(n,'mceVisualNbsp');});for(i=0;i<nl.length;i++)ed.dom.setOuterHTML(nl[i],nl[i].innerHTML.replace(/(&middot;|\u00b7)/g,'&nbsp;'),d);}}});tinymce.PluginManager.add('visualchars',tinymce.plugins.VisualChars);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/visualchars/editor_plugin_src.js b/jscripts/tiny_mce/plugins/visualchars/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..02ec4e6
--- /dev/null
@@ -0,0 +1,73 @@
+/**\r
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.VisualChars', {\r
+               init : function(ed, url) {\r
+                       var t = this;\r
+\r
+                       t.editor = ed;\r
+\r
+                       // Register commands\r
+                       ed.addCommand('mceVisualChars', t._toggleVisualChars, t);\r
+\r
+                       // Register buttons\r
+                       ed.addButton('visualchars', {title : 'visualchars.desc', cmd : 'mceVisualChars'});\r
+\r
+                       ed.onBeforeGetContent.add(function(ed, o) {\r
+                               if (t.state) {\r
+                                       t.state = true;\r
+                                       t._toggleVisualChars();\r
+                               }\r
+                       });\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Visual characters',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/visualchars',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               },\r
+\r
+               // Private methods\r
+\r
+               _toggleVisualChars : function() {\r
+                       var t = this, ed = t.editor, nl, i, h, d = ed.getDoc(), b = ed.getBody(), nv, s = ed.selection, bo;\r
+\r
+                       t.state = !t.state;\r
+                       ed.controlManager.setActive('visualchars', t.state);\r
+\r
+                       if (t.state) {\r
+                               nl = [];\r
+                               tinymce.walk(b, function(n) {\r
+                                       if (n.nodeType == 3 && n.nodeValue && n.nodeValue.indexOf('\u00a0') != -1)\r
+                                               nl.push(n);\r
+                               }, 'childNodes');\r
+\r
+                               for (i=0; i<nl.length; i++) {\r
+                                       nv = nl[i].nodeValue;\r
+                                       nv = nv.replace(/(\u00a0+)/g, '<span class="mceItemHidden mceVisualNbsp">$1</span>');\r
+                                       nv = nv.replace(/\u00a0/g, '\u00b7');\r
+                                       ed.dom.setOuterHTML(nl[i], nv, d);\r
+                               }\r
+                       } else {\r
+                               nl = tinymce.grep(ed.dom.select('span', b), function(n) {\r
+                                       return ed.dom.hasClass(n, 'mceVisualNbsp');\r
+                               });\r
+\r
+                               for (i=0; i<nl.length; i++)\r
+                                       ed.dom.setOuterHTML(nl[i], nl[i].innerHTML.replace(/(&middot;|\u00b7)/g, '&nbsp;'), d);\r
+                       }\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('visualchars', tinymce.plugins.VisualChars);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/abbr.htm b/jscripts/tiny_mce/plugins/xhtmlxtras/abbr.htm
new file mode 100644 (file)
index 0000000..8748d42
--- /dev/null
@@ -0,0 +1,149 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#xhtmlxtras_dlg.title_abbr_element}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/editable_selects.js?v=307"></script>\r
+       <script type="text/javascript" src="js/element_common.js?v=307"></script>\r
+       <script type="text/javascript" src="js/abbr.js?v=307"></script>\r
+       <link rel="stylesheet" type="text/css" href="css/popup.css?v=307" />\r
+       <base target="_self" />\r
+</head>\r
+<body style="display: none">\r
+<form onsubmit="insertAbbr();return false;" action="#">\r
+       <div class="tabs">\r
+               <ul>\r
+                       <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li>\r
+                       <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> -->\r
+               </ul>\r
+       </div>\r
+\r
+       <div class="panel_wrapper">\r
+               <div id="general_panel" class="panel current">\r
+                       <fieldset>\r
+                               <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend>\r
+                               <table border="0" cellpadding="0" cellspacing="4">\r
+                                       <tr>\r
+                                               <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> \r
+                                               <td><input id="title" name="title" type="text" value="" class="field mceFocus" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> \r
+                                               <td><input id="id" name="id" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> \r
+                                               <td>\r
+                                                       <select id="class" name="class" class="field mceEditableSelect">\r
+                                                               <option value="">{#not_set}</option> \r
+                                                       </select>\r
+                                               </td>\r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="stylelabel" for="class">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> \r
+                                               <td><input id="style" name="style" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> \r
+                                               <td>\r
+                                                       <select id="dir" name="dir" class="field"> \r
+                                                               <option value="">{#not_set}</option> \r
+                                                               <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> \r
+                                                               <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> \r
+                                                       </select>\r
+                                               </td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> \r
+                                               <td>\r
+                                                       <input id="lang" name="lang" type="text" value="" class="field" />\r
+                                               </td> \r
+                                       </tr>\r
+                               </table>\r
+                       </fieldset>\r
+               </div>\r
+               <div id="events_panel" class="panel">\r
+                       <fieldset>\r
+                               <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend>\r
+\r
+                               <table border="0" cellpadding="0" cellspacing="4">\r
+                                       <tr>\r
+                                               <td class="label"><label for="onfocus">onfocus</label>:</td> \r
+                                               <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onblur">onblur</label>:</td> \r
+                                               <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onclick">onclick</label>:</td> \r
+                                               <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="ondblclick">ondblclick</label>:</td> \r
+                                               <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmousedown">onmousedown</label>:</td> \r
+                                               <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseup">onmouseup</label>:</td> \r
+                                               <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseover">onmouseover</label>:</td> \r
+                                               <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmousemove">onmousemove</label>:</td> \r
+                                               <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseout">onmouseout</label>:</td> \r
+                                               <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeypress">onkeypress</label>:</td> \r
+                                               <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeydown">onkeydown</label>:</td> \r
+                                               <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeyup">onkeyup</label>:</td> \r
+                                               <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                               </table>\r
+                       </fieldset>\r
+               </div>\r
+       </div>\r
+       <div class="mceActionPanel">\r
+               <div style="float: left">\r
+                       <input type="submit" id="insert" name="insert" value="{#update}" />\r
+               </div>\r
+               <div style="float: left">\r
+                       <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeAbbr();" style="display: none;" />\r
+               </div>\r
+               <div style="float: right">\r
+                       <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+               </div>\r
+       </div>\r
+\r
+</form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/acronym.htm b/jscripts/tiny_mce/plugins/xhtmlxtras/acronym.htm
new file mode 100644 (file)
index 0000000..03394f6
--- /dev/null
@@ -0,0 +1,149 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#xhtmlxtras_dlg.title_acronym_element}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/editable_selects.js?v=307"></script>\r
+       <script type="text/javascript" src="js/element_common.js?v=307"></script>\r
+       <script type="text/javascript" src="js/acronym.js?v=307"></script>\r
+       <link rel="stylesheet" type="text/css" href="css/popup.css?v=307" />\r
+       <base target="_self" />\r
+</head>\r
+<body style="display: none">\r
+<form onsubmit="insertAcronym();return false;" action="#">\r
+       <div class="tabs">\r
+               <ul>\r
+                       <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li>\r
+                       <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> -->\r
+               </ul>\r
+       </div>\r
+\r
+       <div class="panel_wrapper">\r
+               <div id="general_panel" class="panel current">\r
+                       <fieldset>\r
+                               <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend>\r
+                               <table border="0" cellpadding="0" cellspacing="4">\r
+                                       <tr>\r
+                                               <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> \r
+                                               <td><input id="title" name="title" type="text" value="" class="field mceFocus" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> \r
+                                               <td><input id="id" name="id" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> \r
+                                               <td>\r
+                                                       <select id="class" name="class" class="field mceEditableSelect">\r
+                                                               <option value="">{#not_set}</option> \r
+                                                       </select>\r
+                                               </td>\r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="stylelabel" for="class">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> \r
+                                               <td><input id="style" name="style" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> \r
+                                               <td>\r
+                                                       <select id="dir" name="dir" class="field"> \r
+                                                               <option value="">{#not_set}</option> \r
+                                                               <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> \r
+                                                               <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> \r
+                                                       </select>\r
+                                               </td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> \r
+                                               <td>\r
+                                                       <input id="lang" name="lang" type="text" value="" class="field" />\r
+                                               </td> \r
+                                       </tr>\r
+                               </table>\r
+                       </fieldset>\r
+               </div>\r
+               <div id="events_panel" class="panel">\r
+                       <fieldset>\r
+                               <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend>\r
+\r
+                               <table border="0" cellpadding="0" cellspacing="4">\r
+                                       <tr>\r
+                                               <td class="label"><label for="onfocus">onfocus</label>:</td> \r
+                                               <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onblur">onblur</label>:</td> \r
+                                               <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onclick">onclick</label>:</td> \r
+                                               <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="ondblclick">ondblclick</label>:</td> \r
+                                               <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmousedown">onmousedown</label>:</td> \r
+                                               <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseup">onmouseup</label>:</td> \r
+                                               <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseover">onmouseover</label>:</td> \r
+                                               <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmousemove">onmousemove</label>:</td> \r
+                                               <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseout">onmouseout</label>:</td> \r
+                                               <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeypress">onkeypress</label>:</td> \r
+                                               <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeydown">onkeydown</label>:</td> \r
+                                               <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeyup">onkeyup</label>:</td> \r
+                                               <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                               </table>\r
+                       </fieldset>\r
+               </div>\r
+       </div>\r
+       <div class="mceActionPanel">\r
+               <div style="float: left">\r
+                       <input type="submit" id="insert" name="insert" value="{#update}" />\r
+               </div>\r
+               <div style="float: left">\r
+                       <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeAcronym();" style="display: none;" />\r
+               </div>\r
+               <div style="float: right">\r
+                       <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+               </div>\r
+       </div>\r
+\r
+</form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/attributes.htm b/jscripts/tiny_mce/plugins/xhtmlxtras/attributes.htm
new file mode 100644 (file)
index 0000000..27c829c
--- /dev/null
@@ -0,0 +1,154 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#xhtmlxtras_dlg.attribs_title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/editable_selects.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>\r
+       <script type="text/javascript" src="js/attributes.js?v=307"></script>\r
+       <link rel="stylesheet" type="text/css" href="css/attributes.css?v=307" />\r
+       <base target="_self" />\r
+</head>\r
+<body style="display: none">\r
+<form onsubmit="insertAction();return false;" action="#">\r
+       <div class="tabs">\r
+               <ul>\r
+                       <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.attribute_attrib_tab}</a></span></li>\r
+                       <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.attribute_events_tab}</a></span></li>\r
+               </ul>\r
+       </div>\r
+\r
+       <div class="panel_wrapper">\r
+               <div id="general_panel" class="panel current">\r
+                       <fieldset>\r
+                               <legend>{#xhtmlxtras_dlg.attribute_attrib_tab}</legend>\r
+                               <table border="0" cellpadding="0" cellspacing="4">\r
+                                       <tr>\r
+                                               <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> \r
+                                               <td><input id="title" name="title" type="text" value="" class="mceFocus" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> \r
+                                               <td><input id="id" name="id" type="text" value="" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td><label id="classlabel" for="classlist">{#class_name}</label></td>\r
+                                               <td>\r
+                                                       <select id="classlist" name="classlist" class="mceEditableSelect">\r
+                                                               <option value="" selected>{#not_set}</option>\r
+                                                       </select>\r
+                                               </td>\r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="stylelabel" for="class">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> \r
+                                               <td><input id="style" name="style" type="text" value="" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> \r
+                                               <td>\r
+                                                       <select id="dir" name="dir"> \r
+                                                               <option value="">{#not_set}</option> \r
+                                                               <option value="ltr">{#xhtmlxtras_dlg.option_ltr}</option> \r
+                                                               <option value="rtl">{#xhtmlxtras_dlg.option_rtl}</option> \r
+                                                       </select>\r
+                                               </td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> \r
+                                               <td>\r
+                                                       <input id="lang" name="lang" type="text" value="" />\r
+                                               </td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                                       <td><label id="tabindexlabel" for="tabindex">{#xhtmlxtras_dlg.attribute_label_tabindex}</label></td>\r
+                                                       <td><input type="text" id="tabindex" name="tabindex" value="" /></td>\r
+                                               </tr>\r
+\r
+                                               <tr>\r
+                                                       <td><label id="accesskeylabel" for="accesskey">{#xhtmlxtras_dlg.attribute_label_accesskey}</label></td>\r
+                                                       <td><input type="text" id="accesskey" name="accesskey" value="" /></td>\r
+                                               </tr>\r
+                               </table>\r
+                       </fieldset>\r
+               </div>\r
+               <div id="events_panel" class="panel">\r
+                       <fieldset>\r
+                               <legend>{#xhtmlxtras_dlg.attribute_events_tab}</legend>\r
+\r
+                               <table border="0" cellpadding="0" cellspacing="4">\r
+                                       <tr>\r
+                                               <td class="label"><label for="onfocus">onfocus</label>:</td> \r
+                                               <td><input id="onfocus" name="onfocus" type="text" value="" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onblur">onblur</label>:</td> \r
+                                               <td><input id="onblur" name="onblur" type="text" value="" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onclick">onclick</label>:</td> \r
+                                               <td><input id="onclick" name="onclick" type="text" value="" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="ondblclick">ondblclick</label>:</td> \r
+                                               <td><input id="ondblclick" name="ondblclick" type="text" value="" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmousedown">onmousedown</label>:</td> \r
+                                               <td><input id="onmousedown" name="onmousedown" type="text" value="" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseup">onmouseup</label>:</td> \r
+                                               <td><input id="onmouseup" name="onmouseup" type="text" value="" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseover">onmouseover</label>:</td> \r
+                                               <td><input id="onmouseover" name="onmouseover" type="text" value="" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmousemove">onmousemove</label>:</td> \r
+                                               <td><input id="onmousemove" name="onmousemove" type="text" value="" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseout">onmouseout</label>:</td> \r
+                                               <td><input id="onmouseout" name="onmouseout" type="text" value="" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeypress">onkeypress</label>:</td> \r
+                                               <td><input id="onkeypress" name="onkeypress" type="text" value="" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeydown">onkeydown</label>:</td> \r
+                                               <td><input id="onkeydown" name="onkeydown" type="text" value="" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeyup">onkeyup</label>:</td> \r
+                                               <td><input id="onkeyup" name="onkeyup" type="text" value="" /></td> \r
+                                       </tr>\r
+                               </table>\r
+                       </fieldset>\r
+               </div>\r
+       </div>\r
+       <div class="mceActionPanel">\r
+               <div style="float: left">\r
+                       <input type="submit" id="insert" name="insert" value="{#insert}" />\r
+               </div>\r
+               <div style="float: right">\r
+                       <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+               </div>\r
+       </div>\r
+\r
+</form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/cite.htm b/jscripts/tiny_mce/plugins/xhtmlxtras/cite.htm
new file mode 100644 (file)
index 0000000..11f96fa
--- /dev/null
@@ -0,0 +1,149 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#xhtmlxtras_dlg.title_cite_element}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/editable_selects.js?v=307"></script>\r
+       <script type="text/javascript" src="js/element_common.js?v=307"></script>\r
+       <script type="text/javascript" src="js/cite.js?v=307"></script>\r
+       <link rel="stylesheet" type="text/css" href="css/popup.css?v=307" />\r
+       <base target="_self" />\r
+</head>\r
+<body style="display: none">\r
+<form onsubmit="insertCite();return false;" action="#">\r
+       <div class="tabs">\r
+               <ul>\r
+                       <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li>\r
+                       <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> -->\r
+               </ul>\r
+       </div>\r
+\r
+       <div class="panel_wrapper">\r
+               <div id="general_panel" class="panel current">\r
+                       <fieldset>\r
+                               <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend>\r
+                               <table border="0" cellpadding="0" cellspacing="4">\r
+                                       <tr>\r
+                                               <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> \r
+                                               <td><input id="title" name="title" type="text" value="" class="field mceFocus" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> \r
+                                               <td><input id="id" name="id" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> \r
+                                               <td>\r
+                                                       <select id="class" name="class" class="field mceEditableSelect">\r
+                                                               <option value="">{#not_set}</option> \r
+                                                       </select>\r
+                                               </td>\r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="stylelabel" for="class">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> \r
+                                               <td><input id="style" name="style" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> \r
+                                               <td>\r
+                                                       <select id="dir" name="dir" class="field"> \r
+                                                               <option value="">{#not_set}</option> \r
+                                                               <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> \r
+                                                               <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> \r
+                                                       </select>\r
+                                               </td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> \r
+                                               <td>\r
+                                                       <input id="lang" name="lang" type="text" value="" class="field" />\r
+                                               </td> \r
+                                       </tr>\r
+                               </table>\r
+                       </fieldset>\r
+               </div>\r
+               <div id="events_panel" class="panel">\r
+                       <fieldset>\r
+                               <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend>\r
+\r
+                               <table border="0" cellpadding="0" cellspacing="4">\r
+                                       <tr>\r
+                                               <td class="label"><label for="onfocus">onfocus</label>:</td> \r
+                                               <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onblur">onblur</label>:</td> \r
+                                               <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onclick">onclick</label>:</td> \r
+                                               <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="ondblclick">ondblclick</label>:</td> \r
+                                               <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmousedown">onmousedown</label>:</td> \r
+                                               <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseup">onmouseup</label>:</td> \r
+                                               <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseover">onmouseover</label>:</td> \r
+                                               <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmousemove">onmousemove</label>:</td> \r
+                                               <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseout">onmouseout</label>:</td> \r
+                                               <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeypress">onkeypress</label>:</td> \r
+                                               <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeydown">onkeydown</label>:</td> \r
+                                               <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeyup">onkeyup</label>:</td> \r
+                                               <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                               </table>\r
+                       </fieldset>\r
+               </div>\r
+       </div>\r
+       <div class="mceActionPanel">\r
+               <div style="float: left">\r
+                       <input type="submit" id="insert" name="insert" value="{#update}" />\r
+               </div>\r
+               <div style="float: left">\r
+                       <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeCite();" style="display: none;" />\r
+               </div>\r
+               <div style="float: right">\r
+                       <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+               </div>\r
+       </div>\r
+\r
+</form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/css/attributes.css b/jscripts/tiny_mce/plugins/xhtmlxtras/css/attributes.css
new file mode 100644 (file)
index 0000000..9a6a235
--- /dev/null
@@ -0,0 +1,11 @@
+.panel_wrapper div.current {\r
+       height: 290px;\r
+}\r
+\r
+#id, #style, #title, #dir, #hreflang, #lang, #classlist, #tabindex, #accesskey {\r
+       width: 200px;\r
+}\r
+\r
+#events_panel input {\r
+       width: 200px;\r
+}\r
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/css/popup.css b/jscripts/tiny_mce/plugins/xhtmlxtras/css/popup.css
new file mode 100644 (file)
index 0000000..e67114d
--- /dev/null
@@ -0,0 +1,9 @@
+input.field, select.field {width:200px;}\r
+input.picker {width:179px; margin-left: 5px;}\r
+input.disabled {border-color:#F2F2F2;}\r
+img.picker {vertical-align:text-bottom; cursor:pointer;}\r
+h1 {padding: 0 0 5px 0;}\r
+.panel_wrapper div.current {height:160px;}\r
+#xhtmlxtrasdel .panel_wrapper div.current, #xhtmlxtrasins .panel_wrapper div.current {height: 230px;}\r
+a.browse span {display:block; width:20px; height:20px; background:url('../../../themes/advanced/img/icons.gif') -140px -20px;}\r
+#datetime {width:180px;}\r
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/css/xhtmlxtras.css b/jscripts/tiny_mce/plugins/xhtmlxtras/css/xhtmlxtras.css
new file mode 100644 (file)
index 0000000..6838d90
--- /dev/null
@@ -0,0 +1,24 @@
+ins {\r
+       border-bottom: 1px solid green;\r
+       text-decoration: none;\r
+       color: green;\r
+}\r
+\r
+del {\r
+       color: Red;\r
+       text-decoration: line-through;\r
+}\r
+\r
+cite {\r
+       border-bottom: 1px dashed blue;\r
+}\r
+\r
+acronym {\r
+       border-bottom: 1px dotted #CCC;\r
+       cursor: help;\r
+}\r
+\r
+abbr, html\:abbr {\r
+       border-bottom: 1px dashed #CCC;\r
+       cursor: help;\r
+}\r
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/del.htm b/jscripts/tiny_mce/plugins/xhtmlxtras/del.htm
new file mode 100644 (file)
index 0000000..a29588b
--- /dev/null
@@ -0,0 +1,170 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#xhtmlxtras_dlg.title_del_element}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/editable_selects.js?v=307"></script>\r
+       <script type="text/javascript" src="js/element_common.js?v=307"></script>\r
+       <script type="text/javascript" src="js/del.js?v=307"></script>\r
+       <link rel="stylesheet" type="text/css" href="css/popup.css?v=307" />\r
+       <base target="_self" />\r
+</head>\r
+<body id="xhtmlxtrasins" style="display: none">\r
+<form onsubmit="insertDel();return false;" action="#">\r
+       <div class="tabs">\r
+               <ul>\r
+                       <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li>\r
+                       <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> -->\r
+               </ul>\r
+       </div>\r
+\r
+       <div class="panel_wrapper">\r
+               <div id="general_panel" class="panel current">\r
+                       <fieldset>\r
+                               <legend>{#xhtmlxtras_dlg.fieldset_general_tab}</legend>\r
+                               <table border="0" cellpadding="0" cellspacing="4">\r
+                                       <tr>\r
+                                               <td class="label"><label id="datetimelabel" for="datetime">{#xhtmlxtras_dlg.attribute_label_datetime}</label>:</td>\r
+                                               <td>\r
+                                                       <table border="0" cellspacing="0" cellpadding="0">\r
+                                                               <tr> \r
+                                                                       <td><input id="datetime" name="datetime" type="text" value="" maxlength="19" class="field mceFocus" /></td> \r
+                                                                       <td><a href="javascript:insertDateTime('datetime');" onmousedown="return false;" class="browse"><span class="datetime" alt="{#xhtmlxtras_dlg.insert_date}" title="{#xhtmlxtras_dlg.insert_date}"></span></a></td>\r
+                                                               </tr>\r
+                                                       </table>\r
+                                               </td>\r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="citelabel" for="cite">{#xhtmlxtras_dlg.attribute_label_cite}</label>:</td>\r
+                                               <td><input id="cite" name="cite" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                               </table>\r
+                       </fieldset>\r
+                       <fieldset>\r
+                               <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend>\r
+                               <table border="0" cellpadding="0" cellspacing="4">\r
+                                       <tr>\r
+                                               <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> \r
+                                               <td><input id="title" name="title" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> \r
+                                               <td><input id="id" name="id" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> \r
+                                               <td>\r
+                                                       <select id="class" name="class" class="field mceEditableSelect">\r
+                                                               <option value="">{#not_set}</option> \r
+                                                       </select>\r
+                                               </td>\r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="stylelabel" for="class">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> \r
+                                               <td><input id="style" name="style" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> \r
+                                               <td>\r
+                                                       <select id="dir" name="dir" class="field"> \r
+                                                               <option value="">{#not_set}</option> \r
+                                                               <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> \r
+                                                               <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> \r
+                                                       </select>\r
+                                               </td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> \r
+                                               <td>\r
+                                                       <input id="lang" name="lang" type="text" value="" class="field" />\r
+                                               </td> \r
+                                       </tr>\r
+                               </table>\r
+                       </fieldset>\r
+               </div>\r
+               <div id="events_panel" class="panel">\r
+                       <fieldset>\r
+                               <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend>\r
+\r
+                               <table border="0" cellpadding="0" cellspacing="4">\r
+                                       <tr>\r
+                                               <td class="label"><label for="onfocus">onfocus</label>:</td> \r
+                                               <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onblur">onblur</label>:</td> \r
+                                               <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onclick">onclick</label>:</td> \r
+                                               <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="ondblclick">ondblclick</label>:</td> \r
+                                               <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmousedown">onmousedown</label>:</td> \r
+                                               <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseup">onmouseup</label>:</td> \r
+                                               <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseover">onmouseover</label>:</td> \r
+                                               <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmousemove">onmousemove</label>:</td> \r
+                                               <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseout">onmouseout</label>:</td> \r
+                                               <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeypress">onkeypress</label>:</td> \r
+                                               <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeydown">onkeydown</label>:</td> \r
+                                               <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeyup">onkeyup</label>:</td> \r
+                                               <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                               </table>\r
+                       </fieldset>\r
+               </div>\r
+       </div>\r
+       <div class="mceActionPanel">\r
+               <div style="float: left">\r
+                       <input type="submit" id="insert" name="insert" value="{#update}" />\r
+               </div>\r
+               <div style="float: left">\r
+                       <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeDel();" style="display: none;" />\r
+               </div>\r
+               <div style="float: right">\r
+                       <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+               </div>\r
+       </div>\r
+\r
+</form>\r
+\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/editor_plugin.js b/jscripts/tiny_mce/plugins/xhtmlxtras/editor_plugin.js
new file mode 100644 (file)
index 0000000..6a3270d
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.XHTMLXtrasPlugin',{init:function(ed,url){ed.addCommand('mceCite',function(){ed.windowManager.open({file:url+'/cite.htm',width:350+parseInt(ed.getLang('xhtmlxtras.cite_delta_width',0)),height:250+parseInt(ed.getLang('xhtmlxtras.cite_delta_height',0)),inline:1},{plugin_url:url});});ed.addCommand('mceAcronym',function(){ed.windowManager.open({file:url+'/acronym.htm',width:350+parseInt(ed.getLang('xhtmlxtras.acronym_delta_width',0)),height:250+parseInt(ed.getLang('xhtmlxtras.acronym_delta_width',0)),inline:1},{plugin_url:url});});ed.addCommand('mceAbbr',function(){ed.windowManager.open({file:url+'/abbr.htm',width:350+parseInt(ed.getLang('xhtmlxtras.abbr_delta_width',0)),height:250+parseInt(ed.getLang('xhtmlxtras.abbr_delta_width',0)),inline:1},{plugin_url:url});});ed.addCommand('mceDel',function(){ed.windowManager.open({file:url+'/del.htm',width:340+parseInt(ed.getLang('xhtmlxtras.del_delta_width',0)),height:310+parseInt(ed.getLang('xhtmlxtras.del_delta_width',0)),inline:1},{plugin_url:url});});ed.addCommand('mceIns',function(){ed.windowManager.open({file:url+'/ins.htm',width:340+parseInt(ed.getLang('xhtmlxtras.ins_delta_width',0)),height:310+parseInt(ed.getLang('xhtmlxtras.ins_delta_width',0)),inline:1},{plugin_url:url});});ed.addCommand('mceAttributes',function(){ed.windowManager.open({file:url+'/attributes.htm',width:380,height:370,inline:1},{plugin_url:url});});ed.addButton('cite',{title:'xhtmlxtras.cite_desc',cmd:'mceCite'});ed.addButton('acronym',{title:'xhtmlxtras.acronym_desc',cmd:'mceAcronym'});ed.addButton('abbr',{title:'xhtmlxtras.abbr_desc',cmd:'mceAbbr'});ed.addButton('del',{title:'xhtmlxtras.del_desc',cmd:'mceDel'});ed.addButton('ins',{title:'xhtmlxtras.ins_desc',cmd:'mceIns'});ed.addButton('attribs',{title:'xhtmlxtras.attribs_desc',cmd:'mceAttributes'});if(tinymce.isIE){function fix(ed,o){if(o.set){o.content=o.content.replace(/<abbr([^>]+)>/gi,'<html:abbr $1>');o.content=o.content.replace(/<\/abbr>/gi,'</html:abbr>');}};ed.onBeforeSetContent.add(fix);ed.onPostProcess.add(fix);}ed.onNodeChange.add(function(ed,cm,n,co){n=ed.dom.getParent(n,'CITE,ACRONYM,ABBR,DEL,INS');cm.setDisabled('cite',co);cm.setDisabled('acronym',co);cm.setDisabled('abbr',co);cm.setDisabled('del',co);cm.setDisabled('ins',co);cm.setDisabled('attribs',n&&n.nodeName=='BODY');if(n){cm.setDisabled(n.nodeName.toLowerCase(),0);cm.setActive(n.nodeName.toLowerCase(),1);}else{cm.setActive('cite',0);cm.setActive('acronym',0);cm.setActive('abbr',0);cm.setActive('del',0);cm.setActive('ins',0);}});},getInfo:function(){return{longname:'XHTML Xtras Plugin',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/xhtmlxtras',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('xhtmlxtras',tinymce.plugins.XHTMLXtrasPlugin);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js b/jscripts/tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..143ed92
--- /dev/null
@@ -0,0 +1,134 @@
+/**\r
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.plugins.XHTMLXtrasPlugin', {\r
+               init : function(ed, url) {\r
+                       // Register commands\r
+                       ed.addCommand('mceCite', function() {\r
+                               ed.windowManager.open({\r
+                                       file : url + '/cite.htm',\r
+                                       width : 350 + parseInt(ed.getLang('xhtmlxtras.cite_delta_width', 0)),\r
+                                       height : 250 + parseInt(ed.getLang('xhtmlxtras.cite_delta_height', 0)),\r
+                                       inline : 1\r
+                               }, {\r
+                                       plugin_url : url\r
+                               });\r
+                       });\r
+\r
+                       ed.addCommand('mceAcronym', function() {\r
+                               ed.windowManager.open({\r
+                                       file : url + '/acronym.htm',\r
+                                       width : 350 + parseInt(ed.getLang('xhtmlxtras.acronym_delta_width', 0)),\r
+                                       height : 250 + parseInt(ed.getLang('xhtmlxtras.acronym_delta_width', 0)),\r
+                                       inline : 1\r
+                               }, {\r
+                                       plugin_url : url\r
+                               });\r
+                       });\r
+\r
+                       ed.addCommand('mceAbbr', function() {\r
+                               ed.windowManager.open({\r
+                                       file : url + '/abbr.htm',\r
+                                       width : 350 + parseInt(ed.getLang('xhtmlxtras.abbr_delta_width', 0)),\r
+                                       height : 250 + parseInt(ed.getLang('xhtmlxtras.abbr_delta_width', 0)),\r
+                                       inline : 1\r
+                               }, {\r
+                                       plugin_url : url\r
+                               });\r
+                       });\r
+\r
+                       ed.addCommand('mceDel', function() {\r
+                               ed.windowManager.open({\r
+                                       file : url + '/del.htm',\r
+                                       width : 340 + parseInt(ed.getLang('xhtmlxtras.del_delta_width', 0)),\r
+                                       height : 310 + parseInt(ed.getLang('xhtmlxtras.del_delta_width', 0)),\r
+                                       inline : 1\r
+                               }, {\r
+                                       plugin_url : url\r
+                               });\r
+                       });\r
+\r
+                       ed.addCommand('mceIns', function() {\r
+                               ed.windowManager.open({\r
+                                       file : url + '/ins.htm',\r
+                                       width : 340 + parseInt(ed.getLang('xhtmlxtras.ins_delta_width', 0)),\r
+                                       height : 310 + parseInt(ed.getLang('xhtmlxtras.ins_delta_width', 0)),\r
+                                       inline : 1\r
+                               }, {\r
+                                       plugin_url : url\r
+                               });\r
+                       });\r
+\r
+                       ed.addCommand('mceAttributes', function() {\r
+                               ed.windowManager.open({\r
+                                       file : url + '/attributes.htm',\r
+                                       width : 380,\r
+                                       height : 370,\r
+                                       inline : 1\r
+                               }, {\r
+                                       plugin_url : url\r
+                               });\r
+                       });\r
+\r
+                       // Register buttons\r
+                       ed.addButton('cite', {title : 'xhtmlxtras.cite_desc', cmd : 'mceCite'});\r
+                       ed.addButton('acronym', {title : 'xhtmlxtras.acronym_desc', cmd : 'mceAcronym'});\r
+                       ed.addButton('abbr', {title : 'xhtmlxtras.abbr_desc', cmd : 'mceAbbr'});\r
+                       ed.addButton('del', {title : 'xhtmlxtras.del_desc', cmd : 'mceDel'});\r
+                       ed.addButton('ins', {title : 'xhtmlxtras.ins_desc', cmd : 'mceIns'});\r
+                       ed.addButton('attribs', {title : 'xhtmlxtras.attribs_desc', cmd : 'mceAttributes'});\r
+\r
+                       if (tinymce.isIE) {\r
+                               function fix(ed, o) {\r
+                                       if (o.set) {\r
+                                               o.content = o.content.replace(/<abbr([^>]+)>/gi, '<html:abbr $1>');\r
+                                               o.content = o.content.replace(/<\/abbr>/gi, '</html:abbr>');\r
+                                       }\r
+                               };\r
+\r
+                               ed.onBeforeSetContent.add(fix);\r
+                               ed.onPostProcess.add(fix);\r
+                       }\r
+\r
+                       ed.onNodeChange.add(function(ed, cm, n, co) {\r
+                               n = ed.dom.getParent(n, 'CITE,ACRONYM,ABBR,DEL,INS');\r
+\r
+                               cm.setDisabled('cite', co);\r
+                               cm.setDisabled('acronym', co);\r
+                               cm.setDisabled('abbr', co);\r
+                               cm.setDisabled('del', co);\r
+                               cm.setDisabled('ins', co);\r
+                               cm.setDisabled('attribs', n && n.nodeName == 'BODY');\r
+\r
+                               if (n) {\r
+                                       cm.setDisabled(n.nodeName.toLowerCase(), 0);\r
+                                       cm.setActive(n.nodeName.toLowerCase(), 1);\r
+                               } else {\r
+                                       cm.setActive('cite', 0);\r
+                                       cm.setActive('acronym', 0);\r
+                                       cm.setActive('abbr', 0);\r
+                                       cm.setActive('del', 0);\r
+                                       cm.setActive('ins', 0);\r
+                               }\r
+                       });\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'XHTML Xtras Plugin',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/xhtmlxtras',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       };\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('xhtmlxtras', tinymce.plugins.XHTMLXtrasPlugin);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/ins.htm b/jscripts/tiny_mce/plugins/xhtmlxtras/ins.htm
new file mode 100644 (file)
index 0000000..0ea4838
--- /dev/null
@@ -0,0 +1,170 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#xhtmlxtras_dlg.title_ins_element}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/editable_selects.js?v=307"></script>\r
+       <script type="text/javascript" src="js/element_common.js?v=307"></script>\r
+       <script type="text/javascript" src="js/ins.js?v=307"></script>\r
+       <link rel="stylesheet" type="text/css" href="css/popup.css?v=307" />\r
+       <base target="_self" />\r
+</head>\r
+<body id="xhtmlxtrasins" style="display: none">\r
+<form onsubmit="insertIns();return false;" action="#">\r
+       <div class="tabs">\r
+               <ul>\r
+                       <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li>\r
+                       <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> -->\r
+               </ul>\r
+       </div>\r
+\r
+       <div class="panel_wrapper">\r
+               <div id="general_panel" class="panel current">\r
+                       <fieldset>\r
+                               <legend>{#xhtmlxtras_dlg.fieldset_general_tab}</legend>\r
+                               <table border="0" cellpadding="0" cellspacing="4">\r
+                                       <tr>\r
+                                               <td class="label"><label id="datetimelabel" for="datetime">{#xhtmlxtras_dlg.attribute_label_datetime}</label>:</td> \r
+                                               <td>\r
+                                                       <table border="0" cellspacing="0" cellpadding="0">\r
+                                                               <tr> \r
+                                                                       <td><input id="datetime" name="datetime" type="text" value="" maxlength="19" class="field mceFocus" /></td> \r
+                                                                       <td><a href="javascript:insertDateTime('datetime');" onmousedown="return false;" class="browse"><span class="datetime" alt="{#xhtmlxtras_dlg.insert_date}" title="{#xhtmlxtras_dlg.insert_date}"></span></a></td>\r
+                                                               </tr>\r
+                                                       </table>\r
+                                               </td>\r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="citelabel" for="cite">{#xhtmlxtras_dlg.attribute_label_cite}</label>:</td> \r
+                                               <td><input id="cite" name="cite" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                               </table>\r
+                       </fieldset>\r
+                       <fieldset>\r
+                               <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend>\r
+                               <table border="0" cellpadding="0" cellspacing="4">\r
+                                       <tr>\r
+                                               <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> \r
+                                               <td><input id="title" name="title" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> \r
+                                               <td><input id="id" name="id" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> \r
+                                               <td>\r
+                                                       <select id="class" name="class" class="field mceEditableSelect">\r
+                                                               <option value="">{#not_set}</option> \r
+                                                       </select>\r
+                                               </td>\r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="stylelabel" for="class">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> \r
+                                               <td><input id="style" name="style" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> \r
+                                               <td>\r
+                                                       <select id="dir" name="dir" class="field"> \r
+                                                               <option value="">{#not_set}</option> \r
+                                                               <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> \r
+                                                               <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> \r
+                                                       </select>\r
+                                               </td> \r
+                                       </tr>\r
+                                       <tr>\r
+                                               <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> \r
+                                               <td>\r
+                                                       <input id="lang" name="lang" type="text" value="" class="field" />\r
+                                               </td> \r
+                                       </tr>\r
+                               </table>\r
+                       </fieldset>\r
+               </div>\r
+               <div id="events_panel" class="panel">\r
+                       <fieldset>\r
+                               <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend>\r
+\r
+                               <table border="0" cellpadding="0" cellspacing="4">\r
+                                       <tr>\r
+                                               <td class="label"><label for="onfocus">onfocus</label>:</td> \r
+                                               <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onblur">onblur</label>:</td> \r
+                                               <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onclick">onclick</label>:</td> \r
+                                               <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="ondblclick">ondblclick</label>:</td> \r
+                                               <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmousedown">onmousedown</label>:</td> \r
+                                               <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseup">onmouseup</label>:</td> \r
+                                               <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseover">onmouseover</label>:</td> \r
+                                               <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmousemove">onmousemove</label>:</td> \r
+                                               <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onmouseout">onmouseout</label>:</td> \r
+                                               <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeypress">onkeypress</label>:</td> \r
+                                               <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeydown">onkeydown</label>:</td> \r
+                                               <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+\r
+                                       <tr>\r
+                                               <td class="label"><label for="onkeyup">onkeyup</label>:</td> \r
+                                               <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td> \r
+                                       </tr>\r
+                               </table>\r
+                       </fieldset>\r
+               </div>\r
+       </div>\r
+       <div class="mceActionPanel">\r
+               <div style="float: left">\r
+                       <input type="submit" id="insert" name="insert" value="{#update}" />\r
+               </div>\r
+               <div style="float: left">\r
+                       <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeIns();" style="display: none;" />\r
+               </div>\r
+               <div style="float: right">\r
+                       <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+               </div>\r
+       </div>\r
+\r
+</form>\r
+\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/js/abbr.js b/jscripts/tiny_mce/plugins/xhtmlxtras/js/abbr.js
new file mode 100644 (file)
index 0000000..e84b6a8
--- /dev/null
@@ -0,0 +1,25 @@
+ /**\r
+ * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $\r
+ *\r
+ * @author Moxiecode - based on work by Andrew Tetlaw\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+function init() {\r
+       SXE.initElementDialog('abbr');\r
+       if (SXE.currentAction == "update") {\r
+               SXE.showRemoveButton();\r
+       }\r
+}\r
+\r
+function insertAbbr() {\r
+       SXE.insertElement(tinymce.isIE ? 'html:abbr' : 'abbr');\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function removeAbbr() {\r
+       SXE.removeElement('abbr');\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+tinyMCEPopup.onInit.add(init);\r
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/js/acronym.js b/jscripts/tiny_mce/plugins/xhtmlxtras/js/acronym.js
new file mode 100644 (file)
index 0000000..933d122
--- /dev/null
@@ -0,0 +1,25 @@
+ /**\r
+ * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $\r
+ *\r
+ * @author Moxiecode - based on work by Andrew Tetlaw\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+function init() {\r
+       SXE.initElementDialog('acronym');\r
+       if (SXE.currentAction == "update") {\r
+               SXE.showRemoveButton();\r
+       }\r
+}\r
+\r
+function insertAcronym() {\r
+       SXE.insertElement('acronym');\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function removeAcronym() {\r
+       SXE.removeElement('acronym');\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+tinyMCEPopup.onInit.add(init);\r
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/js/attributes.js b/jscripts/tiny_mce/plugins/xhtmlxtras/js/attributes.js
new file mode 100644 (file)
index 0000000..23c7fa4
--- /dev/null
@@ -0,0 +1,123 @@
+ /**\r
+ * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $\r
+ *\r
+ * @author Moxiecode - based on work by Andrew Tetlaw\r
+ * @copyright Copyright © 2004-2006, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+function init() {\r
+       tinyMCEPopup.resizeToInnerSize();\r
+       var inst = tinyMCEPopup.editor;\r
+       var dom = inst.dom;\r
+       var elm = inst.selection.getNode();\r
+       var f = document.forms[0];\r
+       var onclick = dom.getAttrib(elm, 'onclick');\r
+\r
+       setFormValue('title', dom.getAttrib(elm, 'title'));\r
+       setFormValue('id', dom.getAttrib(elm, 'id'));\r
+       setFormValue('style', dom.getAttrib(elm, "style"));\r
+       setFormValue('dir', dom.getAttrib(elm, 'dir'));\r
+       setFormValue('lang', dom.getAttrib(elm, 'lang'));\r
+       setFormValue('tabindex', dom.getAttrib(elm, 'tabindex', typeof(elm.tabindex) != "undefined" ? elm.tabindex : ""));\r
+       setFormValue('accesskey', dom.getAttrib(elm, 'accesskey', typeof(elm.accesskey) != "undefined" ? elm.accesskey : ""));\r
+       setFormValue('onfocus', dom.getAttrib(elm, 'onfocus'));\r
+       setFormValue('onblur', dom.getAttrib(elm, 'onblur'));\r
+       setFormValue('onclick', onclick);\r
+       setFormValue('ondblclick', dom.getAttrib(elm, 'ondblclick'));\r
+       setFormValue('onmousedown', dom.getAttrib(elm, 'onmousedown'));\r
+       setFormValue('onmouseup', dom.getAttrib(elm, 'onmouseup'));\r
+       setFormValue('onmouseover', dom.getAttrib(elm, 'onmouseover'));\r
+       setFormValue('onmousemove', dom.getAttrib(elm, 'onmousemove'));\r
+       setFormValue('onmouseout', dom.getAttrib(elm, 'onmouseout'));\r
+       setFormValue('onkeypress', dom.getAttrib(elm, 'onkeypress'));\r
+       setFormValue('onkeydown', dom.getAttrib(elm, 'onkeydown'));\r
+       setFormValue('onkeyup', dom.getAttrib(elm, 'onkeyup'));\r
+       className = dom.getAttrib(elm, 'class');\r
+\r
+       addClassesToList('classlist', 'advlink_styles');\r
+       selectByValue(f, 'classlist', className, true);\r
+\r
+       TinyMCE_EditableSelects.init();\r
+}\r
+\r
+function setFormValue(name, value) {\r
+       if(value && document.forms[0].elements[name]){\r
+               document.forms[0].elements[name].value = value;\r
+       }\r
+}\r
+\r
+function insertAction() {\r
+       var inst = tinyMCEPopup.editor;\r
+       var elm = inst.selection.getNode();\r
+\r
+       tinyMCEPopup.execCommand("mceBeginUndoLevel");  \r
+       setAllAttribs(elm);\r
+       tinyMCEPopup.execCommand("mceEndUndoLevel");\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function setAttrib(elm, attrib, value) {\r
+       var formObj = document.forms[0];\r
+       var valueElm = formObj.elements[attrib.toLowerCase()];\r
+       var inst = tinyMCEPopup.editor;\r
+       var dom = inst.dom;\r
+\r
+       if (typeof(value) == "undefined" || value == null) {\r
+               value = "";\r
+\r
+               if (valueElm)\r
+                       value = valueElm.value;\r
+       }\r
+\r
+       if (value != "") {\r
+               dom.setAttrib(elm, attrib.toLowerCase(), value);\r
+\r
+               if (attrib == "style")\r
+                       attrib = "style.cssText";\r
+\r
+               if (attrib.substring(0, 2) == 'on')\r
+                       value = 'return true;' + value;\r
+\r
+               if (attrib == "class")\r
+                       attrib = "className";\r
+\r
+               elm[attrib]=value;\r
+       } else\r
+               elm.removeAttribute(attrib);\r
+}\r
+\r
+function setAllAttribs(elm) {\r
+       var f = document.forms[0];\r
+\r
+       setAttrib(elm, 'title');\r
+       setAttrib(elm, 'id');\r
+       setAttrib(elm, 'style');\r
+       setAttrib(elm, 'class', getSelectValue(f, 'classlist'));\r
+       setAttrib(elm, 'dir');\r
+       setAttrib(elm, 'lang');\r
+       setAttrib(elm, 'tabindex');\r
+       setAttrib(elm, 'accesskey');\r
+       setAttrib(elm, 'onfocus');\r
+       setAttrib(elm, 'onblur');\r
+       setAttrib(elm, 'onclick');\r
+       setAttrib(elm, 'ondblclick');\r
+       setAttrib(elm, 'onmousedown');\r
+       setAttrib(elm, 'onmouseup');\r
+       setAttrib(elm, 'onmouseover');\r
+       setAttrib(elm, 'onmousemove');\r
+       setAttrib(elm, 'onmouseout');\r
+       setAttrib(elm, 'onkeypress');\r
+       setAttrib(elm, 'onkeydown');\r
+       setAttrib(elm, 'onkeyup');\r
+\r
+       // Refresh in old MSIE\r
+//     if (tinyMCE.isMSIE5)\r
+//             elm.outerHTML = elm.outerHTML;\r
+}\r
+\r
+function insertAttribute() {\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+tinyMCEPopup.onInit.add(init);\r
+tinyMCEPopup.requireLangPack();\r
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/js/cite.js b/jscripts/tiny_mce/plugins/xhtmlxtras/js/cite.js
new file mode 100644 (file)
index 0000000..c36f7fd
--- /dev/null
@@ -0,0 +1,25 @@
+ /**\r
+ * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $\r
+ *\r
+ * @author Moxiecode - based on work by Andrew Tetlaw\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+function init() {\r
+       SXE.initElementDialog('cite');\r
+       if (SXE.currentAction == "update") {\r
+               SXE.showRemoveButton();\r
+       }\r
+}\r
+\r
+function insertCite() {\r
+       SXE.insertElement('cite');\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function removeCite() {\r
+       SXE.removeElement('cite');\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+tinyMCEPopup.onInit.add(init);\r
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/js/del.js b/jscripts/tiny_mce/plugins/xhtmlxtras/js/del.js
new file mode 100644 (file)
index 0000000..005a619
--- /dev/null
@@ -0,0 +1,50 @@
+ /**\r
+ * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $\r
+ *\r
+ * @author Moxiecode - based on work by Andrew Tetlaw\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+function init() {\r
+       SXE.initElementDialog('del');\r
+       if (SXE.currentAction == "update") {\r
+               setFormValue('datetime', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'datetime'));\r
+               setFormValue('cite', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'cite'));\r
+               SXE.showRemoveButton();\r
+       }\r
+}\r
+\r
+function setElementAttribs(elm) {\r
+       setAllCommonAttribs(elm);\r
+       setAttrib(elm, 'datetime');\r
+       setAttrib(elm, 'cite');\r
+}\r
+\r
+function insertDel() {\r
+       var elm = tinyMCEPopup.editor.dom.getParent(SXE.focusElement, 'DEL');\r
+\r
+       tinyMCEPopup.execCommand('mceBeginUndoLevel');\r
+       if (elm == null) {\r
+               var s = SXE.inst.selection.getContent();\r
+               if(s.length > 0) {\r
+                       tinyMCEPopup.execCommand('mceInsertContent', false, '<del id="#sxe_temp_del#">' + s + '</del>');\r
+                       var elementArray = tinymce.grep(SXE.inst.dom.select('del'), function(n) {return n.id == '#sxe_temp_del#';});\r
+                       for (var i=0; i<elementArray.length; i++) {\r
+                               var elm = elementArray[i];\r
+                               setElementAttribs(elm);\r
+                       }\r
+               }\r
+       } else {\r
+               setElementAttribs(elm);\r
+       }\r
+       tinyMCEPopup.editor.nodeChanged();\r
+       tinyMCEPopup.execCommand('mceEndUndoLevel');\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function removeDel() {\r
+       SXE.removeElement('del');\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+tinyMCEPopup.onInit.add(init);\r
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/js/element_common.js b/jscripts/tiny_mce/plugins/xhtmlxtras/js/element_common.js
new file mode 100644 (file)
index 0000000..724d9d1
--- /dev/null
@@ -0,0 +1,221 @@
+ /**\r
+ * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $\r
+ *\r
+ * @author Moxiecode - based on work by Andrew Tetlaw\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+tinyMCEPopup.requireLangPack();\r
+\r
+function initCommonAttributes(elm) {\r
+       var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom;\r
+\r
+       // Setup form data for common element attributes\r
+       setFormValue('title', dom.getAttrib(elm, 'title'));\r
+       setFormValue('id', dom.getAttrib(elm, 'id'));\r
+       selectByValue(formObj, 'class', dom.getAttrib(elm, 'class'), true);\r
+       setFormValue('style', dom.getAttrib(elm, 'style'));\r
+       selectByValue(formObj, 'dir', dom.getAttrib(elm, 'dir'));\r
+       setFormValue('lang', dom.getAttrib(elm, 'lang'));\r
+       setFormValue('onfocus', dom.getAttrib(elm, 'onfocus'));\r
+       setFormValue('onblur', dom.getAttrib(elm, 'onblur'));\r
+       setFormValue('onclick', dom.getAttrib(elm, 'onclick'));\r
+       setFormValue('ondblclick', dom.getAttrib(elm, 'ondblclick'));\r
+       setFormValue('onmousedown', dom.getAttrib(elm, 'onmousedown'));\r
+       setFormValue('onmouseup', dom.getAttrib(elm, 'onmouseup'));\r
+       setFormValue('onmouseover', dom.getAttrib(elm, 'onmouseover'));\r
+       setFormValue('onmousemove', dom.getAttrib(elm, 'onmousemove'));\r
+       setFormValue('onmouseout', dom.getAttrib(elm, 'onmouseout'));\r
+       setFormValue('onkeypress', dom.getAttrib(elm, 'onkeypress'));\r
+       setFormValue('onkeydown', dom.getAttrib(elm, 'onkeydown'));\r
+       setFormValue('onkeyup', dom.getAttrib(elm, 'onkeyup'));\r
+}\r
+\r
+function setFormValue(name, value) {\r
+       if(document.forms[0].elements[name]) document.forms[0].elements[name].value = value;\r
+}\r
+\r
+function insertDateTime(id) {\r
+       document.getElementById(id).value = getDateTime(new Date(), "%Y-%m-%dT%H:%M:%S");\r
+}\r
+\r
+function getDateTime(d, fmt) {\r
+       fmt = fmt.replace("%D", "%m/%d/%y");\r
+       fmt = fmt.replace("%r", "%I:%M:%S %p");\r
+       fmt = fmt.replace("%Y", "" + d.getFullYear());\r
+       fmt = fmt.replace("%y", "" + d.getYear());\r
+       fmt = fmt.replace("%m", addZeros(d.getMonth()+1, 2));\r
+       fmt = fmt.replace("%d", addZeros(d.getDate(), 2));\r
+       fmt = fmt.replace("%H", "" + addZeros(d.getHours(), 2));\r
+       fmt = fmt.replace("%M", "" + addZeros(d.getMinutes(), 2));\r
+       fmt = fmt.replace("%S", "" + addZeros(d.getSeconds(), 2));\r
+       fmt = fmt.replace("%I", "" + ((d.getHours() + 11) % 12 + 1));\r
+       fmt = fmt.replace("%p", "" + (d.getHours() < 12 ? "AM" : "PM"));\r
+       fmt = fmt.replace("%%", "%");\r
+\r
+       return fmt;\r
+}\r
+\r
+function addZeros(value, len) {\r
+       var i;\r
+\r
+       value = "" + value;\r
+\r
+       if (value.length < len) {\r
+               for (i=0; i<(len-value.length); i++)\r
+                       value = "0" + value;\r
+       }\r
+\r
+       return value;\r
+}\r
+\r
+function selectByValue(form_obj, field_name, value, add_custom, ignore_case) {\r
+       if (!form_obj || !form_obj.elements[field_name])\r
+               return;\r
+\r
+       var sel = form_obj.elements[field_name];\r
+\r
+       var found = false;\r
+       for (var i=0; i<sel.options.length; i++) {\r
+               var option = sel.options[i];\r
+\r
+               if (option.value == value || (ignore_case && option.value.toLowerCase() == value.toLowerCase())) {\r
+                       option.selected = true;\r
+                       found = true;\r
+               } else\r
+                       option.selected = false;\r
+       }\r
+\r
+       if (!found && add_custom && value != '') {\r
+               var option = new Option('Value: ' + value, value);\r
+               option.selected = true;\r
+               sel.options[sel.options.length] = option;\r
+       }\r
+\r
+       return found;\r
+}\r
+\r
+function setAttrib(elm, attrib, value) {\r
+       var formObj = document.forms[0];\r
+       var valueElm = formObj.elements[attrib.toLowerCase()];\r
+       tinyMCEPopup.editor.dom.setAttrib(elm, attrib, value || valueElm.value);\r
+}\r
+\r
+function setAllCommonAttribs(elm) {\r
+       setAttrib(elm, 'title');\r
+       setAttrib(elm, 'id');\r
+       setAttrib(elm, 'class');\r
+       setAttrib(elm, 'style');\r
+       setAttrib(elm, 'dir');\r
+       setAttrib(elm, 'lang');\r
+       /*setAttrib(elm, 'onfocus');\r
+       setAttrib(elm, 'onblur');\r
+       setAttrib(elm, 'onclick');\r
+       setAttrib(elm, 'ondblclick');\r
+       setAttrib(elm, 'onmousedown');\r
+       setAttrib(elm, 'onmouseup');\r
+       setAttrib(elm, 'onmouseover');\r
+       setAttrib(elm, 'onmousemove');\r
+       setAttrib(elm, 'onmouseout');\r
+       setAttrib(elm, 'onkeypress');\r
+       setAttrib(elm, 'onkeydown');\r
+       setAttrib(elm, 'onkeyup');*/\r
+}\r
+\r
+SXE = {\r
+       currentAction : "insert",\r
+       inst : tinyMCEPopup.editor,\r
+       updateElement : null\r
+}\r
+\r
+SXE.focusElement = SXE.inst.selection.getNode();\r
+\r
+SXE.initElementDialog = function(element_name) {\r
+       addClassesToList('class', 'xhtmlxtras_styles');\r
+       TinyMCE_EditableSelects.init();\r
+\r
+       element_name = element_name.toLowerCase();\r
+       var elm = SXE.inst.dom.getParent(SXE.focusElement, element_name.toUpperCase());\r
+       if (elm != null && elm.nodeName == element_name.toUpperCase()) {\r
+               SXE.currentAction = "update";\r
+       }\r
+\r
+       if (SXE.currentAction == "update") {\r
+               initCommonAttributes(elm);\r
+               SXE.updateElement = elm;\r
+       }\r
+\r
+       document.forms[0].insert.value = tinyMCEPopup.getLang(SXE.currentAction, 'Insert', true); \r
+}\r
+\r
+SXE.insertElement = function(element_name) {\r
+       var elm = SXE.inst.dom.getParent(SXE.focusElement, element_name.toUpperCase()), h, tagName;\r
+\r
+       tinyMCEPopup.execCommand('mceBeginUndoLevel');\r
+       if (elm == null) {\r
+               var s = SXE.inst.selection.getContent();\r
+               if(s.length > 0) {\r
+                       tagName = element_name;\r
+\r
+                       if (tinymce.isIE && element_name.indexOf('html:') == 0)\r
+                               element_name = element_name.substring(5).toLowerCase();\r
+\r
+                       h = '<' + tagName + ' id="#sxe_temp_' + element_name + '#">' + s + '</' + tagName + '>';\r
+\r
+                       tinyMCEPopup.execCommand('mceInsertContent', false, h);\r
+\r
+                       var elementArray = tinymce.grep(SXE.inst.dom.select(element_name), function(n) {return n.id == '#sxe_temp_' + element_name + '#';});\r
+                       for (var i=0; i<elementArray.length; i++) {\r
+                               var elm = elementArray[i];\r
+\r
+                               elm.id = '';\r
+                               elm.setAttribute('id', '');\r
+                               elm.removeAttribute('id');\r
+\r
+                               setAllCommonAttribs(elm);\r
+                       }\r
+               }\r
+       } else {\r
+               setAllCommonAttribs(elm);\r
+       }\r
+       SXE.inst.nodeChanged();\r
+       tinyMCEPopup.execCommand('mceEndUndoLevel');\r
+}\r
+\r
+SXE.removeElement = function(element_name){\r
+       element_name = element_name.toLowerCase();\r
+       elm = SXE.inst.dom.getParent(SXE.focusElement, element_name.toUpperCase());\r
+       if(elm && elm.nodeName == element_name.toUpperCase()){\r
+               tinyMCEPopup.execCommand('mceBeginUndoLevel');\r
+               tinyMCE.execCommand('mceRemoveNode', false, elm);\r
+               SXE.inst.nodeChanged();\r
+               tinyMCEPopup.execCommand('mceEndUndoLevel');\r
+       }\r
+}\r
+\r
+SXE.showRemoveButton = function() {\r
+               document.getElementById("remove").style.display = 'block';\r
+}\r
+\r
+SXE.containsClass = function(elm,cl) {\r
+       return (elm.className.indexOf(cl) > -1) ? true : false;\r
+}\r
+\r
+SXE.removeClass = function(elm,cl) {\r
+       if(elm.className == null || elm.className == "" || !SXE.containsClass(elm,cl)) {\r
+               return true;\r
+       }\r
+       var classNames = elm.className.split(" ");\r
+       var newClassNames = "";\r
+       for (var x = 0, cnl = classNames.length; x < cnl; x++) {\r
+               if (classNames[x] != cl) {\r
+                       newClassNames += (classNames[x] + " ");\r
+               }\r
+       }\r
+       elm.className = newClassNames.substring(0,newClassNames.length-1); //removes extra space at the end\r
+}\r
+\r
+SXE.addClass = function(elm,cl) {\r
+       if(!SXE.containsClass(elm,cl)) elm.className ? elm.className += " " + cl : elm.className = cl;\r
+       return true;\r
+}
\ No newline at end of file
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/js/ins.js b/jscripts/tiny_mce/plugins/xhtmlxtras/js/ins.js
new file mode 100644 (file)
index 0000000..b03ca1b
--- /dev/null
@@ -0,0 +1,49 @@
+ /**\r
+ * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $\r
+ *\r
+ * @author Moxiecode - based on work by Andrew Tetlaw\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+function init() {\r
+       SXE.initElementDialog('ins');\r
+       if (SXE.currentAction == "update") {\r
+               setFormValue('datetime', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'datetime'));\r
+               setFormValue('cite', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'cite'));\r
+               SXE.showRemoveButton();\r
+       }\r
+}\r
+\r
+function setElementAttribs(elm) {\r
+       setAllCommonAttribs(elm);\r
+       setAttrib(elm, 'datetime');\r
+       setAttrib(elm, 'cite');\r
+}\r
+\r
+function insertIns() {\r
+       var elm = tinyMCEPopup.editor.dom.getParent(SXE.focusElement, 'INS');\r
+       tinyMCEPopup.execCommand('mceBeginUndoLevel');\r
+       if (elm == null) {\r
+               var s = SXE.inst.selection.getContent();\r
+               if(s.length > 0) {\r
+                       tinyMCEPopup.execCommand('mceInsertContent', false, '<ins id="#sxe_temp_ins#">' + s + '</ins>');\r
+                       var elementArray = tinymce.grep(SXE.inst.dom.select('ins'), function(n) {return n.id == '#sxe_temp_ins#';});\r
+                       for (var i=0; i<elementArray.length; i++) {\r
+                               var elm = elementArray[i];\r
+                               setElementAttribs(elm);\r
+                       }\r
+               }\r
+       } else {\r
+               setElementAttribs(elm);\r
+       }\r
+       tinyMCEPopup.editor.nodeChanged();\r
+       tinyMCEPopup.execCommand('mceEndUndoLevel');\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function removeIns() {\r
+       SXE.removeElement('ins');\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+tinyMCEPopup.onInit.add(init);\r
diff --git a/jscripts/tiny_mce/plugins/xhtmlxtras/langs/en_dlg.js b/jscripts/tiny_mce/plugins/xhtmlxtras/langs/en_dlg.js
new file mode 100644 (file)
index 0000000..45b6b26
--- /dev/null
@@ -0,0 +1,32 @@
+tinyMCE.addI18n('en.xhtmlxtras_dlg',{\r
+attribute_label_title:"Title",\r
+attribute_label_id:"ID",\r
+attribute_label_class:"Class",\r
+attribute_label_style:"Style",\r
+attribute_label_cite:"Cite",\r
+attribute_label_datetime:"Date/Time",\r
+attribute_label_langdir:"Text Direction",\r
+attribute_option_ltr:"Left to right",\r
+attribute_option_rtl:"Right to left",\r
+attribute_label_langcode:"Language",\r
+attribute_label_tabindex:"TabIndex",\r
+attribute_label_accesskey:"AccessKey",\r
+attribute_events_tab:"Events",\r
+attribute_attrib_tab:"Attributes",\r
+general_tab:"General",\r
+attrib_tab:"Attributes",\r
+events_tab:"Events",\r
+fieldset_general_tab:"General Settings",\r
+fieldset_attrib_tab:"Element Attributes",\r
+fieldset_events_tab:"Element Events",\r
+title_ins_element:"Insertion Element",\r
+title_del_element:"Deletion Element",\r
+title_acronym_element:"Acronym Element",\r
+title_abbr_element:"Abbreviation Element",\r
+title_cite_element:"Citation Element",\r
+remove:"Remove",\r
+insert_date:"Insert current date/time",\r
+option_ltr:"Left to right",\r
+option_rtl:"Right to left",\r
+attribs_title:"Insert/Edit Attributes"\r
+});
\ No newline at end of file
diff --git a/jscripts/tiny_mce/themes/advanced/about.htm b/jscripts/tiny_mce/themes/advanced/about.htm
new file mode 100644 (file)
index 0000000..f47d168
--- /dev/null
@@ -0,0 +1,56 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#advanced_dlg.about_title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="js/about.js?v=307"></script>\r
+</head>\r
+<body id="about" style="display: none">\r
+               <div class="tabs">\r
+                       <ul>\r
+                               <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advanced_dlg.about_general}</a></span></li>\r
+                               <li id="help_tab" style="display:none"><span><a href="javascript:mcTabs.displayTab('help_tab','help_panel');" onmousedown="return false;">{#advanced_dlg.about_help}</a></span></li>\r
+                               <li id="plugins_tab"><span><a href="javascript:mcTabs.displayTab('plugins_tab','plugins_panel');" onmousedown="return false;">{#advanced_dlg.about_plugins}</a></span></li>\r
+                       </ul>\r
+               </div>\r
+\r
+               <div class="panel_wrapper">\r
+                       <div id="general_panel" class="panel current">\r
+                               <h3>{#advanced_dlg.about_title}</h3>\r
+                               <p>Version: <span id="version"></span> (<span id="date"></span>)</p>\r
+                               <p>TinyMCE is a platform independent web based Javascript HTML WYSIWYG editor control released as Open Source under <a href="../../license.txt" target="_blank">LGPL</a>\r
+                               by Moxiecode Systems AB. It has the ability to convert HTML TEXTAREA fields or other HTML elements to editor instances.</p>\r
+                               <p>Copyright &copy; 2003-2008, <a href="http://www.moxiecode.com" target="_blank">Moxiecode Systems AB</a>, All rights reserved.</p>\r
+                               <p>For more information about this software visit the <a href="http://tinymce.moxiecode.com" target="_blank">TinyMCE website</a>.</p>\r
+\r
+                               <div id="buttoncontainer">\r
+                                       <a href="http://www.moxiecode.com" target="_blank"><img src="http://tinymce.moxiecode.com/images/gotmoxie.png" alt="Got Moxie?" border="0" /></a>\r
+                                       <a href="http://sourceforge.net/projects/tinymce/" target="_blank"><img src="http://sourceforge.net/sflogo.php?group_id=103281" alt="Hosted By Sourceforge" border="0" /></a>\r
+                                       <a href="http://www.freshmeat.net/projects/tinymce" target="_blank"><img src="http://tinymce.moxiecode.com/images/fm.gif" alt="Also on freshmeat" border="0" /></a>\r
+                               </div>\r
+                       </div>\r
+\r
+                       <div id="plugins_panel" class="panel">\r
+                               <div id="pluginscontainer">\r
+                                       <h3>{#advanced_dlg.about_loaded}</h3>\r
+\r
+                                       <div id="plugintablecontainer">\r
+                                       </div>\r
+\r
+                                       <p>&nbsp;</p>\r
+                               </div>\r
+                       </div>\r
+\r
+                       <div id="help_panel" class="panel noscroll" style="overflow: visible;">\r
+                               <div id="iframecontainer"></div>\r
+                       </div>\r
+               </div>\r
+\r
+               <div class="mceActionPanel">\r
+                       <div style="float: right">\r
+                               <input type="button" id="cancel" name="cancel" value="{#close}" onclick="tinyMCEPopup.close();" />\r
+                       </div>\r
+               </div>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/themes/advanced/anchor.htm b/jscripts/tiny_mce/themes/advanced/anchor.htm
new file mode 100644 (file)
index 0000000..5ba592d
--- /dev/null
@@ -0,0 +1,32 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#advanced_dlg.anchor_title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="js/anchor.js?v=307"></script>\r
+       <base target="_self" />\r
+</head>\r
+<body style="display: none">\r
+<form onsubmit="AnchorDialog.update();return false;" action="#">\r
+       <table border="0" cellpadding="4" cellspacing="0">\r
+               <tr>\r
+                       <td colspan="2" class="title">{#advanced_dlg.anchor_title}</td>\r
+               </tr>\r
+               <tr>\r
+                       <td nowrap="nowrap">{#advanced_dlg.anchor_name}:</td>\r
+                       <td><input name="anchorName" type="text" class="mceFocus" id="anchorName" value="" style="width: 200px" /></td>\r
+               </tr>\r
+       </table>\r
+\r
+       <div class="mceActionPanel">\r
+               <div style="float: left">\r
+                       <input type="submit" id="insert" name="insert" value="{#update}" />\r
+               </div>\r
+\r
+               <div style="float: right">\r
+                       <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+               </div>\r
+       </div>\r
+</form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/themes/advanced/charmap.htm b/jscripts/tiny_mce/themes/advanced/charmap.htm
new file mode 100644 (file)
index 0000000..21e84aa
--- /dev/null
@@ -0,0 +1,54 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#advanced_dlg.charmap_title}</title>\r
+       <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="js/charmap.js?v=307"></script>\r
+       <base target="_self" />\r
+</head>\r
+<body id="charmap" style="display:none">\r
+<table align="center" border="0" cellspacing="0" cellpadding="2">\r
+    <tr>\r
+        <td colspan="2" class="title">{#advanced_dlg.charmap_title}</td>\r
+    </tr>\r
+    <tr>\r
+        <td id="charmapView" rowspan="2" align="left" valign="top">\r
+                       <!-- Chars will be rendered here -->\r
+        </td>\r
+        <td width="100" align="center" valign="top">\r
+            <table border="0" cellpadding="0" cellspacing="0" width="100" style="height:100px">\r
+                <tr>\r
+                    <td id="codeV">&nbsp;</td>\r
+                </tr>\r
+                <tr>\r
+                    <td id="codeN">&nbsp;</td>\r
+                </tr>\r
+            </table>\r
+        </td>\r
+    </tr>\r
+    <tr>\r
+        <td valign="bottom" style="padding-bottom: 3px;">\r
+            <table width="100" align="center" border="0" cellpadding="2" cellspacing="0">\r
+                <tr>\r
+                    <td align="center" style="border-left: 1px solid #666699; border-top: 1px solid #666699; border-right: 1px solid #666699;">HTML-Code</td>\r
+                </tr>\r
+                <tr>\r
+                    <td style="font-size: 16px; font-weight: bold; border-left: 1px solid #666699; border-bottom: 1px solid #666699; border-right: 1px solid #666699;" id="codeA" align="center">&nbsp;</td>\r
+                </tr>\r
+                <tr>\r
+                    <td style="font-size: 1px;">&nbsp;</td>\r
+                </tr>\r
+                <tr>\r
+                    <td align="center" style="border-left: 1px solid #666699; border-top: 1px solid #666699; border-right: 1px solid #666699;">NUM-Code</td>\r
+                </tr>\r
+                <tr>\r
+                    <td style="font-size: 16px; font-weight: bold; border-left: 1px solid #666699; border-bottom: 1px solid #666699; border-right: 1px solid #666699;" id="codeB" align="center">&nbsp;</td>\r
+                </tr>\r
+            </table>\r
+        </td>\r
+    </tr>\r
+</table>\r
+\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/themes/advanced/color_picker.htm b/jscripts/tiny_mce/themes/advanced/color_picker.htm
new file mode 100644 (file)
index 0000000..21c8351
--- /dev/null
@@ -0,0 +1,76 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#advanced_dlg.colorpicker_title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="js/color_picker.js?v=307"></script>\r
+       <base target="_self" />\r
+</head>\r
+<body id="colorpicker" style="display: none">\r
+<form onsubmit="insertAction();return false" action="#">\r
+       <div class="tabs">\r
+               <ul>\r
+                       <li id="picker_tab" class="current"><span><a href="javascript:mcTabs.displayTab('picker_tab','picker_panel');" onmousedown="return false;">{#advanced_dlg.colorpicker_picker_tab}</a></span></li>\r
+                       <li id="rgb_tab"><span><a href="javascript:;" onclick="generateWebColors();mcTabs.displayTab('rgb_tab','rgb_panel');" onmousedown="return false;">{#advanced_dlg.colorpicker_palette_tab}</a></span></li>\r
+                       <li id="named_tab"><span><a  href="javascript:;" onclick="generateNamedColors();javascript:mcTabs.displayTab('named_tab','named_panel');" onmousedown="return false;">{#advanced_dlg.colorpicker_named_tab}</a></span></li>\r
+               </ul>\r
+       </div>\r
+\r
+       <div class="panel_wrapper">\r
+               <div id="picker_panel" class="panel current">\r
+                       <fieldset>\r
+                               <legend>{#advanced_dlg.colorpicker_picker_title}</legend>\r
+                               <div id="picker">\r
+                                       <img id="colors" src="img/colorpicker.jpg" onclick="computeColor(event)" onmousedown="isMouseDown = true;return false;" onmouseup="isMouseDown = false;" onmousemove="if (isMouseDown && isMouseOver) computeColor(event); return false;" onmouseover="isMouseOver=true;" onmouseout="isMouseOver=false;" />\r
+\r
+                                       <div id="light">\r
+                                               <!-- Will be filled with divs -->\r
+                                       </div>\r
+\r
+                                       <br style="clear: both" />\r
+                               </div>\r
+                       </fieldset>\r
+               </div>\r
+\r
+               <div id="rgb_panel" class="panel">\r
+                       <fieldset>\r
+                               <legend>{#advanced_dlg.colorpicker_palette_title}</legend>\r
+                               <div id="webcolors">\r
+                                       <!-- Gets filled with web safe colors-->\r
+                               </div>\r
+\r
+                               <br style="clear: both" />\r
+                       </fieldset>\r
+               </div>\r
+\r
+               <div id="named_panel" class="panel">\r
+                       <fieldset>\r
+                               <legend>{#advanced_dlg.colorpicker_named_title}</legend>\r
+                               <div id="namedcolors">\r
+                                       <!-- Gets filled with named colors-->\r
+                               </div>\r
+\r
+                               <br style="clear: both" />\r
+\r
+                               <div id="colornamecontainer">\r
+                                       {#advanced_dlg.colorpicker_name} <span id="colorname"></span>\r
+                               </div>\r
+                       </fieldset>\r
+               </div>\r
+       </div>\r
+\r
+       <div class="mceActionPanel">\r
+               <div style="float: left">\r
+                       <input type="submit" id="insert" name="insert" value="{#apply}" />\r
+               </div>\r
+\r
+               <div id="preview"></div>\r
+\r
+               <div id="previewblock">\r
+                       <label for="color">{#advanced_dlg.colorpicker_color}</label> <input id="color" type="text" size="8" maxlength="8" class="text mceFocus" />\r
+               </div>\r
+       </div>\r
+</form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/themes/advanced/editor_template.js b/jscripts/tiny_mce/themes/advanced/editor_template.js
new file mode 100644 (file)
index 0000000..465a809
--- /dev/null
@@ -0,0 +1 @@
+(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,extend=tinymce.extend,each=tinymce.each,Cookie=tinymce.util.Cookie,lastExtID,explode=tinymce.explode;tinymce.ThemeManager.requireLangPack('advanced');tinymce.create('tinymce.themes.AdvancedTheme',{controls:{bold:['bold_desc','Bold'],italic:['italic_desc','Italic'],underline:['underline_desc','Underline'],strikethrough:['striketrough_desc','Strikethrough'],justifyleft:['justifyleft_desc','JustifyLeft'],justifycenter:['justifycenter_desc','JustifyCenter'],justifyright:['justifyright_desc','JustifyRight'],justifyfull:['justifyfull_desc','JustifyFull'],bullist:['bullist_desc','InsertUnorderedList'],numlist:['numlist_desc','InsertOrderedList'],outdent:['outdent_desc','Outdent'],indent:['indent_desc','Indent'],cut:['cut_desc','Cut'],copy:['copy_desc','Copy'],paste:['paste_desc','Paste'],undo:['undo_desc','Undo'],redo:['redo_desc','Redo'],link:['link_desc','mceLink'],unlink:['unlink_desc','unlink'],image:['image_desc','mceImage'],cleanup:['cleanup_desc','mceCleanup'],help:['help_desc','mceHelp'],code:['code_desc','mceCodeEditor'],hr:['hr_desc','InsertHorizontalRule'],removeformat:['removeformat_desc','RemoveFormat'],sub:['sub_desc','subscript'],sup:['sup_desc','superscript'],forecolor:['forecolor_desc','ForeColor'],forecolorpicker:['forecolor_desc','mceForeColor'],backcolor:['backcolor_desc','HiliteColor'],backcolorpicker:['backcolor_desc','mceBackColor'],charmap:['charmap_desc','mceCharMap'],visualaid:['visualaid_desc','mceToggleVisualAid'],anchor:['anchor_desc','mceInsertAnchor'],newdocument:['newdocument_desc','mceNewDocument'],blockquote:['blockquote_desc','mceBlockQuote']},stateControls:['bold','italic','underline','strikethrough','bullist','numlist','justifyleft','justifycenter','justifyright','justifyfull','sub','sup','blockquote'],init:function(ed,url){var t=this,s,v;t.editor=ed;t.url=url;t.onResolveName=new tinymce.util.Dispatcher(this);t.settings=s=extend({theme_advanced_path:true,theme_advanced_toolbar_location:'bottom',theme_advanced_buttons1:"bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect",theme_advanced_buttons2:"bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code",theme_advanced_buttons3:"hr,removeformat,visualaid,|,sub,sup,|,charmap",theme_advanced_blockformats:"p,address,pre,h1,h2,h3,h4,h5,h6",theme_advanced_toolbar_align:"center",theme_advanced_fonts:"Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",theme_advanced_font_sizes:"1,2,3,4,5,6,7",theme_advanced_more_colors:1,theme_advanced_row_height:23,theme_advanced_resize_horizontal:1,theme_advanced_resizing_use_cookie:1},ed.settings);if((v=s.theme_advanced_path_location)&&v!='none')s.theme_advanced_statusbar_location=s.theme_advanced_path_location;if(s.theme_advanced_statusbar_location=='none')s.theme_advanced_statusbar_location=0;ed.onInit.add(function(){ed.onNodeChange.add(t._nodeChanged,t);if(ed.settings.content_css!==false)ed.dom.loadCSS(ed.baseURI.toAbsolute("themes/advanced/skins/"+ed.settings.skin+"/content.css"));});ed.onSetProgressState.add(function(ed,b,ti){var co,id=ed.id,tb;if(b){t.progressTimer=setTimeout(function(){co=ed.getContainer();co=co.insertBefore(DOM.create('DIV',{style:'position:relative'}),co.firstChild);tb=DOM.get(ed.id+'_tbl');DOM.add(co,'div',{id:id+'_blocker','class':'mceBlocker',style:{width:tb.clientWidth+2,height:tb.clientHeight+2}});DOM.add(co,'div',{id:id+'_progress','class':'mceProgress',style:{left:tb.clientWidth/ 2, top : tb.clientHeight /2}});},ti||0);}else{DOM.remove(id+'_blocker');DOM.remove(id+'_progress');clearTimeout(t.progressTimer);}});DOM.loadCSS(ed.baseURI.toAbsolute(s.editor_css||"themes/advanced/skins/"+ed.settings.skin+"/ui.css"));if(s.skin_variant)DOM.loadCSS(ed.baseURI.toAbsolute(s.editor_css||"themes/advanced/skins/"+ed.settings.skin+"/ui_"+s.skin_variant+".css"));},createControl:function(n,cf){var cd,c;if(c=cf.createControl(n))return c;switch(n){case"styleselect":return this._createStyleSelect();case"formatselect":return this._createBlockFormats();case"fontselect":return this._createFontSelect();case"fontsizeselect":return this._createFontSizeSelect();case"forecolor":return this._createForeColorMenu();case"backcolor":return this._createBackColorMenu();}if((cd=this.controls[n]))return cf.createButton(n,{title:"advanced."+cd[0],cmd:cd[1],ui:cd[2],value:cd[3]});},execCommand:function(cmd,ui,val){var f=this['_'+cmd];if(f){f.call(this,ui,val);return true;}return false;},_importClasses:function(){var ed=this.editor,c=ed.controlManager.get('styleselect');if(c.getLength()==0){each(ed.dom.getClasses(),function(o){c.add(o['class'],o['class']);});}},_createStyleSelect:function(n){var t=this,ed=t.editor,cf=ed.controlManager,c=cf.createListBox('styleselect',{title:'advanced.style_select',onselect:function(v){if(c.selectedValue===v){ed.execCommand('mceSetStyleInfo',0,{command:'removeformat'});c.select();return false;}else ed.execCommand('mceSetCSSClass',0,v);}});if(c){each(ed.getParam('theme_advanced_styles','','hash'),function(v,k){if(v)c.add(t.editor.translate(k),v);});c.onPostRender.add(function(ed,n){Event.add(n,'focus',t._importClasses,t);Event.add(n,'mousedown',t._importClasses,t);});}return c;},_createFontSelect:function(){var c,t=this,ed=t.editor;c=ed.controlManager.createListBox('fontselect',{title:'advanced.fontdefault',cmd:'FontName'});if(c){each(ed.getParam('theme_advanced_fonts',t.settings.theme_advanced_fonts,'hash'),function(v,k){c.add(ed.translate(k),v,{style:v.indexOf('dings')==-1?'font-family:'+v:''});});}return c;},_createFontSizeSelect:function(){var c,t=this,lo=["1 (8 pt)","2 (10 pt)","3 (12 pt)","4 (14 pt)","5 (18 pt)","6 (24 pt)","7 (36 pt)"],fz=[8,10,12,14,18,24,36];c=t.editor.controlManager.createListBox('fontsizeselect',{title:'advanced.font_size',cmd:'FontSize'});if(c){each(explode(t.settings.theme_advanced_font_sizes),function(v){c.add(lo[parseInt(v)-1],v,{'style':'font-size:'+fz[v-1]+'pt','class':'mceFontSize'+v});});}return c;},_createBlockFormats:function(){var c,fmts={p:'advanced.paragraph',address:'advanced.address',pre:'advanced.pre',h1:'advanced.h1',h2:'advanced.h2',h3:'advanced.h3',h4:'advanced.h4',h5:'advanced.h5',h6:'advanced.h6',div:'advanced.div',blockquote:'advanced.blockquote',code:'advanced.code',dt:'advanced.dt',dd:'advanced.dd',samp:'advanced.samp'},t=this;c=t.editor.controlManager.createListBox('formatselect',{title:'advanced.block',cmd:'FormatBlock'});if(c){each(t.editor.getParam('theme_advanced_blockformats',t.settings.theme_advanced_blockformats,'hash'),function(v,k){c.add(t.editor.translate(k!=v?k:fmts[v]),v,{'class':'mce_formatPreview mce_'+v});});}return c;},_createForeColorMenu:function(){var c,t=this,s=t.settings,o={},v;if(s.theme_advanced_more_colors){o.more_colors_func=function(){t._mceColorPicker(0,{color:c.value,func:function(co){c.setColor(co);}});};}if(v=s.theme_advanced_text_colors)o.colors=v;o.title='advanced.forecolor_desc';o.cmd='ForeColor';o.scope=this;c=t.editor.controlManager.createColorSplitButton('forecolor',o);return c;},_createBackColorMenu:function(){var c,t=this,s=t.settings,o={},v;if(s.theme_advanced_more_colors){o.more_colors_func=function(){t._mceColorPicker(0,{color:c.value,func:function(co){c.setColor(co);}});};}if(v=s.theme_advanced_background_colors)o.colors=v;o.title='advanced.backcolor_desc';o.cmd='HiliteColor';o.scope=this;c=t.editor.controlManager.createColorSplitButton('backcolor',o);return c;},renderUI:function(o){var n,ic,tb,t=this,ed=t.editor,s=t.settings,sc,p,nl;n=p=DOM.create('span',{id:ed.id+'_parent','class':'mceEditor '+ed.settings.skin+'Skin'+(s.skin_variant?' '+ed.settings.skin+'Skin'+t._ufirst(s.skin_variant):'')});if(!DOM.boxModel)n=DOM.add(n,'div',{'class':'mceOldBoxModel'});n=sc=DOM.add(n,'table',{id:ed.id+'_tbl','class':'mceLayout',cellSpacing:0,cellPadding:0});n=tb=DOM.add(n,'tbody');switch((s.theme_advanced_layout_manager||'').toLowerCase()){case"rowlayout":ic=t._rowLayout(s,tb,o);break;case"customlayout":ic=ed.execCallback("theme_advanced_custom_layout",s,tb,o,p);break;default:ic=t._simpleLayout(s,tb,o,p);}n=o.targetNode;nl=DOM.stdMode?sc.getElementsByTagName('tr'):sc.rows;DOM.addClass(nl[0],'mceFirst');DOM.addClass(nl[nl.length-1],'mceLast');each(DOM.select('tr',tb),function(n){DOM.addClass(n.firstChild,'mceFirst');DOM.addClass(n.childNodes[n.childNodes.length-1],'mceLast');});if(DOM.get(s.theme_advanced_toolbar_container))DOM.get(s.theme_advanced_toolbar_container).appendChild(p);else DOM.insertAfter(p,n);Event.add(ed.id+'_path_row','click',function(e){e=e.target;if(e.nodeName=='A'){t._sel(e.className.replace(/^.*mcePath_([0-9]+).*$/,'$1'));return Event.cancel(e);}});if(!ed.getParam('accessibility_focus')||ed.getParam('tab_focus'))Event.add(DOM.add(p,'a',{href:'#'},'<!-- IE -->'),'focus',function(){tinyMCE.get(ed.id).focus();});if(s.theme_advanced_toolbar_location=='external')o.deltaHeight=0;t.deltaHeight=o.deltaHeight;o.targetNode=null;return{iframeContainer:ic,editorContainer:ed.id+'_parent',sizeContainer:sc,deltaHeight:o.deltaHeight};},getInfo:function(){return{longname:'Advanced theme',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',version:tinymce.majorVersion+"."+tinymce.minorVersion}},resizeBy:function(dw,dh){var e=DOM.get(this.editor.id+'_tbl');this.resizeTo(e.clientWidth+dw,e.clientHeight+dh);},resizeTo:function(w,h){var ed=this.editor,s=ed.settings,e=DOM.get(ed.id+'_tbl'),ifr=DOM.get(ed.id+'_ifr'),dh;w=Math.max(s.theme_advanced_resizing_min_width||100,w);h=Math.max(s.theme_advanced_resizing_min_height||100,h);w=Math.min(s.theme_advanced_resizing_max_width||0xFFFF,w);h=Math.min(s.theme_advanced_resizing_max_height||0xFFFF,h);dh=e.clientHeight-ifr.clientHeight;DOM.setStyle(ifr,'height',h-dh);DOM.setStyles(e,{width:w,height:h});},destroy:function(){var id=this.editor.id;Event.clear(id+'_resize');Event.clear(id+'_path_row');Event.clear(id+'_external_close');},_simpleLayout:function(s,tb,o,p){var t=this,ed=t.editor,lo=s.theme_advanced_toolbar_location,sl=s.theme_advanced_statusbar_location,n,ic,etb,c;if(lo=='top')t._addToolbars(tb,o);if(lo=='external'){n=c=DOM.create('div',{style:'position:relative'});n=DOM.add(n,'div',{id:ed.id+'_external','class':'mceExternalToolbar'});DOM.add(n,'a',{id:ed.id+'_external_close',href:'javascript:;','class':'mceExternalClose'});n=DOM.add(n,'table',{id:ed.id+'_tblext',cellSpacing:0,cellPadding:0});etb=DOM.add(n,'tbody');if(p.firstChild.className=='mceOldBoxModel')p.firstChild.appendChild(c);else p.insertBefore(c,p.firstChild);t._addToolbars(etb,o);ed.onMouseUp.add(function(){var e=DOM.get(ed.id+'_external');DOM.show(e);DOM.hide(lastExtID);var f=Event.add(ed.id+'_external_close','click',function(){DOM.hide(ed.id+'_external');Event.remove(ed.id+'_external_close','click',f);});DOM.show(e);DOM.setStyle(e,'top',0-DOM.getRect(ed.id+'_tblext').h-1);DOM.hide(e);DOM.show(e);e.style.filter='';lastExtID=ed.id+'_external';e=null;});}if(sl=='top')t._addStatusBar(tb,o);if(!s.theme_advanced_toolbar_container){n=DOM.add(tb,'tr');n=ic=DOM.add(n,'td',{'class':'mceIframeContainer'});}if(lo=='bottom')t._addToolbars(tb,o);if(sl=='bottom')t._addStatusBar(tb,o);return ic;},_rowLayout:function(s,tb,o){var t=this,ed=t.editor,dc,da,cf=ed.controlManager,n,ic,to,a;dc=s.theme_advanced_containers_default_class||'';da=s.theme_advanced_containers_default_align||'center';each(explode(s.theme_advanced_containers||''),function(c,i){var v=s['theme_advanced_container_'+c]||'';switch(c.toLowerCase()){case'mceeditor':n=DOM.add(tb,'tr');n=ic=DOM.add(n,'td',{'class':'mceIframeContainer'});break;case'mceelementpath':t._addStatusBar(tb,o);break;default:a=s['theme_advanced_container_'+c+'_align'].toLowerCase();a='mce'+t._ufirst(a);n=DOM.add(DOM.add(tb,'tr'),'td',{'class':'mceToolbar '+(s['theme_advanced_container_'+c+'_class']||dc)+' '+a||da});to=cf.createToolbar("toolbar"+i);t._addControls(v,to);DOM.setHTML(n,to.renderHTML());o.deltaHeight-=s.theme_advanced_row_height;}});return ic;},_addControls:function(v,tb){var t=this,s=t.settings,di,cf=t.editor.controlManager;if(s.theme_advanced_disable&&!t._disabled){di={};each(explode(s.theme_advanced_disable),function(v){di[v]=1;});t._disabled=di;}else di=t._disabled;each(explode(v),function(n){var c;if(di&&di[n])return;if(n=='tablecontrols'){each(["table","|","row_props","cell_props","|","row_before","row_after","delete_row","|","col_before","col_after","delete_col","|","split_cells","merge_cells"],function(n){n=t.createControl(n,cf);if(n)tb.add(n);});return;}c=t.createControl(n,cf);if(c)tb.add(c);});},_addToolbars:function(c,o){var t=this,i,tb,ed=t.editor,s=t.settings,v,cf=ed.controlManager,di,n,h=[],a;a=s.theme_advanced_toolbar_align.toLowerCase();a='mce'+t._ufirst(a);n=DOM.add(DOM.add(c,'tr'),'td',{'class':'mceToolbar '+a});if(!ed.getParam('accessibility_focus')||ed.getParam('tab_focus'))h.push(DOM.createHTML('a',{href:'#',onfocus:'tinyMCE.get(\''+ed.id+'\').focus();'},'<!-- IE -->'));h.push(DOM.createHTML('a',{href:'#',accesskey:'q',title:ed.getLang("advanced.toolbar_focus")},'<!-- IE -->'));for(i=1;(v=s['theme_advanced_buttons'+i]);i++){tb=cf.createToolbar("toolbar"+i,{'class':'mceToolbarRow'+i});if(s['theme_advanced_buttons'+i+'_add'])v+=','+s['theme_advanced_buttons'+i+'_add'];if(s['theme_advanced_buttons'+i+'_add_before'])v=s['theme_advanced_buttons'+i+'_add_before']+','+v;t._addControls(v,tb);h.push(tb.renderHTML());o.deltaHeight-=s.theme_advanced_row_height;}h.push(DOM.createHTML('a',{href:'#',accesskey:'z',title:ed.getLang("advanced.toolbar_focus"),onfocus:'tinyMCE.getInstanceById(\''+ed.id+'\').focus();'},'<!-- IE -->'));DOM.setHTML(n,h.join(''));},_addStatusBar:function(tb,o){var n,t=this,ed=t.editor,s=t.settings,r,mf,me,td;n=DOM.add(tb,'tr');n=td=DOM.add(n,'td',{'class':'mceStatusbar'});n=DOM.add(n,'div',{id:ed.id+'_path_row'},s.theme_advanced_path?ed.translate('advanced.path')+': ':'&nbsp;');DOM.add(n,'a',{href:'#',accesskey:'x'});if(s.theme_advanced_resizing&&!tinymce.isOldWebKit){DOM.add(td,'a',{id:ed.id+'_resize',href:'javascript:;',onclick:"return false;",'class':'mceResize'});if(s.theme_advanced_resizing_use_cookie){ed.onPostRender.add(function(){var o=Cookie.getHash("TinyMCE_"+ed.id+"_size"),c=DOM.get(ed.id+'_tbl');if(!o)return;if(s.theme_advanced_resize_horizontal)c.style.width=Math.max(10,o.cw)+'px';c.style.height=Math.max(10,o.ch)+'px';DOM.get(ed.id+'_ifr').style.height=Math.max(10,parseInt(o.ch)+t.deltaHeight)+'px';});}ed.onPostRender.add(function(){Event.add(ed.id+'_resize','mousedown',function(e){var c,p,w,h,n,pa;c=DOM.get(ed.id+'_tbl');w=c.clientWidth;h=c.clientHeight;miw=s.theme_advanced_resizing_min_width||100;mih=s.theme_advanced_resizing_min_height||100;maw=s.theme_advanced_resizing_max_width||0xFFFF;mah=s.theme_advanced_resizing_max_height||0xFFFF;p=DOM.add(DOM.get(ed.id+'_parent'),'div',{'class':'mcePlaceHolder'});DOM.setStyles(p,{width:w,height:h});DOM.hide(c);DOM.show(p);r={x:e.screenX,y:e.screenY,w:w,h:h,dx:null,dy:null};mf=Event.add(DOM.doc,'mousemove',function(e){var w,h;r.dx=e.screenX-r.x;r.dy=e.screenY-r.y;w=Math.max(miw,r.w+r.dx);h=Math.max(mih,r.h+r.dy);w=Math.min(maw,w);h=Math.min(mah,h);if(s.theme_advanced_resize_horizontal)p.style.width=w+'px';p.style.height=h+'px';return Event.cancel(e);});me=Event.add(DOM.doc,'mouseup',function(e){var ifr;Event.remove(DOM.doc,'mousemove',mf);Event.remove(DOM.doc,'mouseup',me);c.style.display='';DOM.remove(p);if(r.dx===null)return;ifr=DOM.get(ed.id+'_ifr');if(s.theme_advanced_resize_horizontal)c.style.width=Math.max(10,r.w+r.dx)+'px';c.style.height=Math.max(10,r.h+r.dy)+'px';ifr.style.height=Math.max(10,ifr.clientHeight+r.dy)+'px';if(s.theme_advanced_resizing_use_cookie){Cookie.setHash("TinyMCE_"+ed.id+"_size",{cw:r.w+r.dx,ch:r.h+r.dy});}});return Event.cancel(e);});});}o.deltaHeight-=21;n=tb=null;},_nodeChanged:function(ed,cm,n,co){var t=this,p,de=0,v,c,s=t.settings;tinymce.each(t.stateControls,function(c){cm.setActive(c,ed.queryCommandState(t.controls[c][1]));});cm.setActive('visualaid',ed.hasVisual);cm.setDisabled('undo',!ed.undoManager.hasUndo()&&!ed.typing);cm.setDisabled('redo',!ed.undoManager.hasRedo());cm.setDisabled('outdent',!ed.queryCommandState('Outdent'));p=DOM.getParent(n,'A');if(c=cm.get('link')){if(!p||!p.name){c.setDisabled(!p&&co);c.setActive(!!p);}}if(c=cm.get('unlink')){c.setDisabled(!p&&co);c.setActive(!!p&&!p.name);}if(c=cm.get('anchor')){c.setActive(!!p&&p.name);if(tinymce.isWebKit){p=DOM.getParent(n,'IMG');c.setActive(!!p&&DOM.getAttrib(p,'mce_name')=='a');}}p=DOM.getParent(n,'IMG');if(c=cm.get('image'))c.setActive(!!p&&n.className.indexOf('mceItem')==-1);if(c=cm.get('styleselect')){if(n.className){t._importClasses();c.select(n.className);}else c.select();}if(c=cm.get('formatselect')){p=DOM.getParent(n,DOM.isBlock);if(p)c.select(p.nodeName.toLowerCase());}if(c=cm.get('fontselect'))c.select(ed.queryCommandValue('FontName'));if(c=cm.get('fontsizeselect'))c.select(ed.queryCommandValue('FontSize'));if(s.theme_advanced_path&&s.theme_advanced_statusbar_location){p=DOM.get(ed.id+'_path')||DOM.add(ed.id+'_path_row','span',{id:ed.id+'_path'});DOM.setHTML(p,'');ed.dom.getParent(n,function(n){var na=n.nodeName.toLowerCase(),u,pi,ti='';if(n.nodeType!=1||(DOM.hasClass(n,'mceItemHidden')||DOM.hasClass(n,'mceItemRemoved')))return;if(v=DOM.getAttrib(n,'mce_name'))na=v;if(tinymce.isIE&&n.scopeName!=='HTML')na=n.scopeName+':'+na;na=na.replace(/mce\:/g,'');switch(na){case'b':na='strong';break;case'i':na='em';break;case'img':if(v=DOM.getAttrib(n,'src'))ti+='src: '+v+' ';break;case'a':if(v=DOM.getAttrib(n,'name')){ti+='name: '+v+' ';na+='#'+v;}if(v=DOM.getAttrib(n,'href'))ti+='href: '+v+' ';break;case'font':if(s.convert_fonts_to_spans)na='span';if(v=DOM.getAttrib(n,'face'))ti+='font: '+v+' ';if(v=DOM.getAttrib(n,'size'))ti+='size: '+v+' ';if(v=DOM.getAttrib(n,'color'))ti+='color: '+v+' ';break;case'span':if(v=DOM.getAttrib(n,'style'))ti+='style: '+v+' ';break;}if(v=DOM.getAttrib(n,'id'))ti+='id: '+v+' ';if(v=n.className){v=v.replace(/(webkit-[\w\-]+|Apple-[\w\-]+|mceItem\w+|mceVisualAid)/g,'');if(v&&v.indexOf('mceItem')==-1){ti+='class: '+v+' ';if(DOM.isBlock(n)||na=='img'||na=='span')na+='.'+v;}}na=na.replace(/(html:)/g,'');na={name:na,node:n,title:ti};t.onResolveName.dispatch(t,na);ti=na.title;na=na.name;pi=DOM.create('a',{'href':"javascript:;",onmousedown:"return false;",title:ti,'class':'mcePath_'+(de++)},na);if(p.hasChildNodes()){p.insertBefore(DOM.doc.createTextNode(' \u00bb '),p.firstChild);p.insertBefore(pi,p.firstChild);}else p.appendChild(pi);},ed.getBody());}},_sel:function(v){this.editor.execCommand('mceSelectNodeDepth',false,v);},_mceInsertAnchor:function(ui,v){var ed=this.editor;ed.windowManager.open({url:tinymce.baseURL+'/themes/advanced/anchor.htm',width:320+parseInt(ed.getLang('advanced.anchor_delta_width',0)),height:90+parseInt(ed.getLang('advanced.anchor_delta_height',0)),inline:true},{theme_url:this.url});},_mceCharMap:function(){var ed=this.editor;ed.windowManager.open({url:tinymce.baseURL+'/themes/advanced/charmap.htm',width:550+parseInt(ed.getLang('advanced.charmap_delta_width',0)),height:250+parseInt(ed.getLang('advanced.charmap_delta_height',0)),inline:true},{theme_url:this.url});},_mceHelp:function(){var ed=this.editor;ed.windowManager.open({url:tinymce.baseURL+'/themes/advanced/about.htm',width:480,height:380,inline:true},{theme_url:this.url});},_mceColorPicker:function(u,v){var ed=this.editor;v=v||{};ed.windowManager.open({url:tinymce.baseURL+'/themes/advanced/color_picker.htm',width:375+parseInt(ed.getLang('advanced.colorpicker_delta_width',0)),height:250+parseInt(ed.getLang('advanced.colorpicker_delta_height',0)),close_previous:false,inline:true},{input_color:v.color,func:v.func,theme_url:this.url});},_mceCodeEditor:function(ui,val){var ed=this.editor;ed.windowManager.open({url:tinymce.baseURL+'/themes/advanced/source_editor.htm',width:parseInt(ed.getParam("theme_advanced_source_editor_width",720)),height:parseInt(ed.getParam("theme_advanced_source_editor_height",580)),inline:true,resizable:true,maximizable:true},{theme_url:this.url});},_mceImage:function(ui,val){var ed=this.editor;if(ed.dom.getAttrib(ed.selection.getNode(),'class').indexOf('mceItem')!=-1)return;ed.windowManager.open({url:tinymce.baseURL+'/themes/advanced/image.htm',width:355+parseInt(ed.getLang('advanced.image_delta_width',0)),height:275+parseInt(ed.getLang('advanced.image_delta_height',0)),inline:true},{theme_url:this.url});},_mceLink:function(ui,val){var ed=this.editor;ed.windowManager.open({url:tinymce.baseURL+'/themes/advanced/link.htm',width:310+parseInt(ed.getLang('advanced.link_delta_width',0)),height:200+parseInt(ed.getLang('advanced.link_delta_height',0)),inline:true},{theme_url:this.url});},_mceNewDocument:function(){var ed=this.editor;ed.windowManager.confirm('advanced.newdocument',function(s){if(s)ed.execCommand('mceSetContent',false,'');});},_mceForeColor:function(){var t=this;this._mceColorPicker(0,{color:t.fgColor,func:function(co){t.fgColor=co;t.editor.execCommand('ForeColor',false,co);}});},_mceBackColor:function(){var t=this;this._mceColorPicker(0,{color:t.bgColor,func:function(co){t.bgColor=co;t.editor.execCommand('HiliteColor',false,co);}});},_ufirst:function(s){return s.substring(0,1).toUpperCase()+s.substring(1);}});tinymce.ThemeManager.add('advanced',tinymce.themes.AdvancedTheme);}());
\ No newline at end of file
diff --git a/jscripts/tiny_mce/themes/advanced/editor_template_src.js b/jscripts/tiny_mce/themes/advanced/editor_template_src.js
new file mode 100644 (file)
index 0000000..4369717
--- /dev/null
@@ -0,0 +1,1052 @@
+/**\r
+ * $Id: editor_template_src.js 793 2008-04-10 17:32:40Z spocke $\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, each = tinymce.each, Cookie = tinymce.util.Cookie, lastExtID, explode = tinymce.explode;\r
+\r
+       // Tell it to load theme specific language pack(s)\r
+       tinymce.ThemeManager.requireLangPack('advanced');\r
+\r
+       tinymce.create('tinymce.themes.AdvancedTheme', {\r
+               // Control name lookup, format: title, command\r
+               controls : {\r
+                       bold : ['bold_desc', 'Bold'],\r
+                       italic : ['italic_desc', 'Italic'],\r
+                       underline : ['underline_desc', 'Underline'],\r
+                       strikethrough : ['striketrough_desc', 'Strikethrough'],\r
+                       justifyleft : ['justifyleft_desc', 'JustifyLeft'],\r
+                       justifycenter : ['justifycenter_desc', 'JustifyCenter'],\r
+                       justifyright : ['justifyright_desc', 'JustifyRight'],\r
+                       justifyfull : ['justifyfull_desc', 'JustifyFull'],\r
+                       bullist : ['bullist_desc', 'InsertUnorderedList'],\r
+                       numlist : ['numlist_desc', 'InsertOrderedList'],\r
+                       outdent : ['outdent_desc', 'Outdent'],\r
+                       indent : ['indent_desc', 'Indent'],\r
+                       cut : ['cut_desc', 'Cut'],\r
+                       copy : ['copy_desc', 'Copy'],\r
+                       paste : ['paste_desc', 'Paste'],\r
+                       undo : ['undo_desc', 'Undo'],\r
+                       redo : ['redo_desc', 'Redo'],\r
+                       link : ['link_desc', 'mceLink'],\r
+                       unlink : ['unlink_desc', 'unlink'],\r
+                       image : ['image_desc', 'mceImage'],\r
+                       cleanup : ['cleanup_desc', 'mceCleanup'],\r
+                       help : ['help_desc', 'mceHelp'],\r
+                       code : ['code_desc', 'mceCodeEditor'],\r
+                       hr : ['hr_desc', 'InsertHorizontalRule'],\r
+                       removeformat : ['removeformat_desc', 'RemoveFormat'],\r
+                       sub : ['sub_desc', 'subscript'],\r
+                       sup : ['sup_desc', 'superscript'],\r
+                       forecolor : ['forecolor_desc', 'ForeColor'],\r
+                       forecolorpicker : ['forecolor_desc', 'mceForeColor'],\r
+                       backcolor : ['backcolor_desc', 'HiliteColor'],\r
+                       backcolorpicker : ['backcolor_desc', 'mceBackColor'],\r
+                       charmap : ['charmap_desc', 'mceCharMap'],\r
+                       visualaid : ['visualaid_desc', 'mceToggleVisualAid'],\r
+                       anchor : ['anchor_desc', 'mceInsertAnchor'],\r
+                       newdocument : ['newdocument_desc', 'mceNewDocument'],\r
+                       blockquote : ['blockquote_desc', 'mceBlockQuote']\r
+               },\r
+\r
+               stateControls : ['bold', 'italic', 'underline', 'strikethrough', 'bullist', 'numlist', 'justifyleft', 'justifycenter', 'justifyright', 'justifyfull', 'sub', 'sup', 'blockquote'],\r
+\r
+               init : function(ed, url) {\r
+                       var t = this, s, v;\r
+       \r
+                       t.editor = ed;\r
+                       t.url = url;\r
+                       t.onResolveName = new tinymce.util.Dispatcher(this);\r
+\r
+                       // Default settings\r
+                       t.settings = s = extend({\r
+                               theme_advanced_path : true,\r
+                               theme_advanced_toolbar_location : 'bottom',\r
+                               theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect",\r
+                               theme_advanced_buttons2 : "bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code",\r
+                               theme_advanced_buttons3 : "hr,removeformat,visualaid,|,sub,sup,|,charmap",\r
+                               theme_advanced_blockformats : "p,address,pre,h1,h2,h3,h4,h5,h6",\r
+                               theme_advanced_toolbar_align : "center",\r
+                               theme_advanced_fonts : "Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",\r
+                               theme_advanced_font_sizes : "1,2,3,4,5,6,7",\r
+                               theme_advanced_more_colors : 1,\r
+                               theme_advanced_row_height : 23,\r
+                               theme_advanced_resize_horizontal : 1,\r
+                               theme_advanced_resizing_use_cookie : 1\r
+                       }, ed.settings);\r
+\r
+                       if ((v = s.theme_advanced_path_location) && v != 'none')\r
+                               s.theme_advanced_statusbar_location = s.theme_advanced_path_location;\r
+\r
+                       if (s.theme_advanced_statusbar_location == 'none')\r
+                               s.theme_advanced_statusbar_location = 0;\r
+\r
+                       // Init editor\r
+                       ed.onInit.add(function() {\r
+                               ed.onNodeChange.add(t._nodeChanged, t);\r
+\r
+                               if (ed.settings.content_css !== false)\r
+                                       ed.dom.loadCSS(ed.baseURI.toAbsolute("themes/advanced/skins/" + ed.settings.skin + "/content.css"));\r
+                       });\r
+\r
+                       ed.onSetProgressState.add(function(ed, b, ti) {\r
+                               var co, id = ed.id, tb;\r
+\r
+                               if (b) {\r
+                                       t.progressTimer = setTimeout(function() {\r
+                                               co = ed.getContainer();\r
+                                               co = co.insertBefore(DOM.create('DIV', {style : 'position:relative'}), co.firstChild);\r
+                                               tb = DOM.get(ed.id + '_tbl');\r
+\r
+                                               DOM.add(co, 'div', {id : id + '_blocker', 'class' : 'mceBlocker', style : {width : tb.clientWidth + 2, height : tb.clientHeight + 2}});\r
+                                               DOM.add(co, 'div', {id : id + '_progress', 'class' : 'mceProgress', style : {left : tb.clientWidth / 2, top : tb.clientHeight / 2}});\r
+                                       }, ti || 0);\r
+                               } else {\r
+                                       DOM.remove(id + '_blocker');\r
+                                       DOM.remove(id + '_progress');\r
+                                       clearTimeout(t.progressTimer);\r
+                               }\r
+                       });\r
+\r
+                       DOM.loadCSS(ed.baseURI.toAbsolute(s.editor_css || "themes/advanced/skins/" + ed.settings.skin + "/ui.css"));\r
+\r
+                       if (s.skin_variant)\r
+                               DOM.loadCSS(ed.baseURI.toAbsolute(s.editor_css || "themes/advanced/skins/" + ed.settings.skin + "/ui_" + s.skin_variant + ".css"));\r
+               },\r
+\r
+               createControl : function(n, cf) {\r
+                       var cd, c;\r
+\r
+                       if (c = cf.createControl(n))\r
+                               return c;\r
+\r
+                       switch (n) {\r
+                               case "styleselect":\r
+                                       return this._createStyleSelect();\r
+\r
+                               case "formatselect":\r
+                                       return this._createBlockFormats();\r
+\r
+                               case "fontselect":\r
+                                       return this._createFontSelect();\r
+\r
+                               case "fontsizeselect":\r
+                                       return this._createFontSizeSelect();\r
+\r
+                               case "forecolor":\r
+                                       return this._createForeColorMenu();\r
+\r
+                               case "backcolor":\r
+                                       return this._createBackColorMenu();\r
+                       }\r
+\r
+                       if ((cd = this.controls[n]))\r
+                               return cf.createButton(n, {title : "advanced." + cd[0], cmd : cd[1], ui : cd[2], value : cd[3]});\r
+               },\r
+\r
+               execCommand : function(cmd, ui, val) {\r
+                       var f = this['_' + cmd];\r
+\r
+                       if (f) {\r
+                               f.call(this, ui, val);\r
+                               return true;\r
+                       }\r
+\r
+                       return false;\r
+               },\r
+\r
+               _importClasses : function() {\r
+                       var ed = this.editor, c = ed.controlManager.get('styleselect');\r
+\r
+                       if (c.getLength() == 0) {\r
+                               each(ed.dom.getClasses(), function(o) {\r
+                                       c.add(o['class'], o['class']);\r
+                               });\r
+                       }\r
+               },\r
+\r
+               _createStyleSelect : function(n) {\r
+                       var t = this, ed = t.editor, cf = ed.controlManager, c = cf.createListBox('styleselect', {\r
+                               title : 'advanced.style_select',\r
+                               onselect : function(v) {\r
+                                       if (c.selectedValue === v) {\r
+                                               ed.execCommand('mceSetStyleInfo', 0, {command : 'removeformat'});\r
+                                               c.select();\r
+                                               return false;\r
+                                       } else\r
+                                               ed.execCommand('mceSetCSSClass', 0, v);\r
+                               }\r
+                       });\r
+\r
+                       if (c) {\r
+                               each(ed.getParam('theme_advanced_styles', '', 'hash'), function(v, k) {\r
+                                       if (v)\r
+                                               c.add(t.editor.translate(k), v);\r
+                               });\r
+\r
+                               c.onPostRender.add(function(ed, n) {\r
+                                       Event.add(n, 'focus', t._importClasses, t);\r
+                                       Event.add(n, 'mousedown', t._importClasses, t);\r
+                               });\r
+                       }\r
+\r
+                       return c;\r
+               },\r
+\r
+               _createFontSelect : function() {\r
+                       var c, t = this, ed = t.editor;\r
+\r
+                       c = ed.controlManager.createListBox('fontselect', {title : 'advanced.fontdefault', cmd : 'FontName'});\r
+                       if (c) {\r
+                               each(ed.getParam('theme_advanced_fonts', t.settings.theme_advanced_fonts, 'hash'), function(v, k) {\r
+                                       c.add(ed.translate(k), v, {style : v.indexOf('dings') == -1 ? 'font-family:' + v : ''});\r
+                               });\r
+                       }\r
+\r
+                       return c;\r
+               },\r
+\r
+               _createFontSizeSelect : function() {\r
+                       var c, t = this, lo = [\r
+                               "1 (8 pt)",\r
+                               "2 (10 pt)",\r
+                               "3 (12 pt)",\r
+                               "4 (14 pt)",\r
+                               "5 (18 pt)",\r
+                               "6 (24 pt)",\r
+                               "7 (36 pt)"\r
+                       ], fz = [8, 10, 12, 14, 18, 24, 36];\r
+\r
+                       c = t.editor.controlManager.createListBox('fontsizeselect', {title : 'advanced.font_size', cmd : 'FontSize'});\r
+                       if (c) {\r
+                               each(explode(t.settings.theme_advanced_font_sizes), function(v) {\r
+                                       c.add(lo[parseInt(v) - 1], v, {'style' : 'font-size:' + fz[v - 1] + 'pt', 'class' : 'mceFontSize' + v});\r
+                               });\r
+                       }\r
+\r
+                       return c;\r
+               },\r
+\r
+               _createBlockFormats : function() {\r
+                       var c, fmts = {\r
+                               p : 'advanced.paragraph',\r
+                               address : 'advanced.address',\r
+                               pre : 'advanced.pre',\r
+                               h1 : 'advanced.h1',\r
+                               h2 : 'advanced.h2',\r
+                               h3 : 'advanced.h3',\r
+                               h4 : 'advanced.h4',\r
+                               h5 : 'advanced.h5',\r
+                               h6 : 'advanced.h6',\r
+                               div : 'advanced.div',\r
+                               blockquote : 'advanced.blockquote',\r
+                               code : 'advanced.code',\r
+                               dt : 'advanced.dt',\r
+                               dd : 'advanced.dd',\r
+                               samp : 'advanced.samp'\r
+                       }, t = this;\r
+\r
+                       c = t.editor.controlManager.createListBox('formatselect', {title : 'advanced.block', cmd : 'FormatBlock'});\r
+                       if (c) {\r
+                               each(t.editor.getParam('theme_advanced_blockformats', t.settings.theme_advanced_blockformats, 'hash'), function(v, k) {\r
+                                       c.add(t.editor.translate(k != v ? k : fmts[v]), v, {'class' : 'mce_formatPreview mce_' + v});\r
+                               });\r
+                       }\r
+\r
+                       return c;\r
+               },\r
+\r
+               _createForeColorMenu : function() {\r
+                       var c, t = this, s = t.settings, o = {}, v;\r
+\r
+                       if (s.theme_advanced_more_colors) {\r
+                               o.more_colors_func = function() {\r
+                                       t._mceColorPicker(0, {\r
+                                               color : c.value,\r
+                                               func : function(co) {\r
+                                                       c.setColor(co);\r
+                                               }\r
+                                       });\r
+                               };\r
+                       }\r
+\r
+                       if (v = s.theme_advanced_text_colors)\r
+                               o.colors = v;\r
+\r
+                       o.title = 'advanced.forecolor_desc';\r
+                       o.cmd = 'ForeColor';\r
+                       o.scope = this;\r
+\r
+                       c = t.editor.controlManager.createColorSplitButton('forecolor', o);\r
+\r
+                       return c;\r
+               },\r
+\r
+               _createBackColorMenu : function() {\r
+                       var c, t = this, s = t.settings, o = {}, v;\r
+\r
+                       if (s.theme_advanced_more_colors) {\r
+                               o.more_colors_func = function() {\r
+                                       t._mceColorPicker(0, {\r
+                                               color : c.value,\r
+                                               func : function(co) {\r
+                                                       c.setColor(co);\r
+                                               }\r
+                                       });\r
+                               };\r
+                       }\r
+\r
+                       if (v = s.theme_advanced_background_colors)\r
+                               o.colors = v;\r
+\r
+                       o.title = 'advanced.backcolor_desc';\r
+                       o.cmd = 'HiliteColor';\r
+                       o.scope = this;\r
+\r
+                       c = t.editor.controlManager.createColorSplitButton('backcolor', o);\r
+\r
+                       return c;\r
+               },\r
+\r
+               renderUI : function(o) {\r
+                       var n, ic, tb, t = this, ed = t.editor, s = t.settings, sc, p, nl;\r
+\r
+                       n = p = DOM.create('span', {id : ed.id + '_parent', 'class' : 'mceEditor ' + ed.settings.skin + 'Skin' + (s.skin_variant ? ' ' + ed.settings.skin + 'Skin' + t._ufirst(s.skin_variant) : '')});\r
+\r
+                       if (!DOM.boxModel)\r
+                               n = DOM.add(n, 'div', {'class' : 'mceOldBoxModel'});\r
+\r
+                       n = sc = DOM.add(n, 'table', {id : ed.id + '_tbl', 'class' : 'mceLayout', cellSpacing : 0, cellPadding : 0});\r
+                       n = tb = DOM.add(n, 'tbody');\r
+\r
+                       switch ((s.theme_advanced_layout_manager || '').toLowerCase()) {\r
+                               case "rowlayout":\r
+                                       ic = t._rowLayout(s, tb, o);\r
+                                       break;\r
+\r
+                               case "customlayout":\r
+                                       ic = ed.execCallback("theme_advanced_custom_layout", s, tb, o, p);\r
+                                       break;\r
+\r
+                               default:\r
+                                       ic = t._simpleLayout(s, tb, o, p);\r
+                       }\r
+\r
+                       n = o.targetNode;\r
+\r
+                       // Add classes to first and last TRs\r
+                       nl = DOM.stdMode ? sc.getElementsByTagName('tr') : sc.rows; // Quick fix for IE 8\r
+                       DOM.addClass(nl[0], 'mceFirst');\r
+                       DOM.addClass(nl[nl.length - 1], 'mceLast');\r
+\r
+                       // Add classes to first and last TDs\r
+                       each(DOM.select('tr', tb), function(n) {\r
+                               DOM.addClass(n.firstChild, 'mceFirst');\r
+                               DOM.addClass(n.childNodes[n.childNodes.length - 1], 'mceLast');\r
+                       });\r
+\r
+                       if (DOM.get(s.theme_advanced_toolbar_container))\r
+                               DOM.get(s.theme_advanced_toolbar_container).appendChild(p);\r
+                       else\r
+                               DOM.insertAfter(p, n);\r
+\r
+                       Event.add(ed.id + '_path_row', 'click', function(e) {\r
+                               e = e.target;\r
+\r
+                               if (e.nodeName == 'A') {\r
+                                       t._sel(e.className.replace(/^.*mcePath_([0-9]+).*$/, '$1'));\r
+\r
+                                       return Event.cancel(e);\r
+                               }\r
+                       });\r
+/*\r
+                       if (DOM.get(ed.id + '_path_row')) {\r
+                               Event.add(ed.id + '_tbl', 'mouseover', function(e) {\r
+                                       var re;\r
+       \r
+                                       e = e.target;\r
+\r
+                                       if (e.nodeName == 'SPAN' && DOM.hasClass(e.parentNode, 'mceButton')) {\r
+                                               re = DOM.get(ed.id + '_path_row');\r
+                                               t.lastPath = re.innerHTML;\r
+                                               DOM.setHTML(re, e.parentNode.title);\r
+                                       }\r
+                               });\r
+\r
+                               Event.add(ed.id + '_tbl', 'mouseout', function(e) {\r
+                                       if (t.lastPath) {\r
+                                               DOM.setHTML(ed.id + '_path_row', t.lastPath);\r
+                                               t.lastPath = 0;\r
+                                       }\r
+                               });\r
+                       }\r
+*/\r
+\r
+                       if (!ed.getParam('accessibility_focus') || ed.getParam('tab_focus'))\r
+                               Event.add(DOM.add(p, 'a', {href : '#'}, '<!-- IE -->'), 'focus', function() {tinyMCE.get(ed.id).focus();});\r
+\r
+                       if (s.theme_advanced_toolbar_location == 'external')\r
+                               o.deltaHeight = 0;\r
+\r
+                       t.deltaHeight = o.deltaHeight;\r
+                       o.targetNode = null;\r
+\r
+                       return {\r
+                               iframeContainer : ic,\r
+                               editorContainer : ed.id + '_parent',\r
+                               sizeContainer : sc,\r
+                               deltaHeight : o.deltaHeight\r
+                       };\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Advanced theme',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       }\r
+               },\r
+\r
+               resizeBy : function(dw, dh) {\r
+                       var e = DOM.get(this.editor.id + '_tbl');\r
+\r
+                       this.resizeTo(e.clientWidth + dw, e.clientHeight + dh);\r
+               },\r
+\r
+               resizeTo : function(w, h) {\r
+                       var ed = this.editor, s = ed.settings, e = DOM.get(ed.id + '_tbl'), ifr = DOM.get(ed.id + '_ifr'), dh;\r
+\r
+                       // Boundery fix box\r
+                       w = Math.max(s.theme_advanced_resizing_min_width || 100, w);\r
+                       h = Math.max(s.theme_advanced_resizing_min_height || 100, h);\r
+                       w = Math.min(s.theme_advanced_resizing_max_width || 0xFFFF, w);\r
+                       h = Math.min(s.theme_advanced_resizing_max_height || 0xFFFF, h);\r
+\r
+                       // Calc difference between iframe and container\r
+                       dh = e.clientHeight - ifr.clientHeight;\r
+\r
+                       // Resize iframe and container\r
+                       DOM.setStyle(ifr, 'height', h - dh);\r
+                       DOM.setStyles(e, {width : w, height : h});\r
+               },\r
+\r
+               destroy : function() {\r
+                       var id = this.editor.id;\r
+\r
+                       Event.clear(id + '_resize');\r
+                       Event.clear(id + '_path_row');\r
+                       Event.clear(id + '_external_close');\r
+               },\r
+\r
+               // Internal functions\r
+\r
+               _simpleLayout : function(s, tb, o, p) {\r
+                       var t = this, ed = t.editor, lo = s.theme_advanced_toolbar_location, sl = s.theme_advanced_statusbar_location, n, ic, etb, c;\r
+\r
+                       // Create toolbar container at top\r
+                       if (lo == 'top')\r
+                               t._addToolbars(tb, o);\r
+\r
+                       // Create external toolbar\r
+                       if (lo == 'external') {\r
+                               n = c = DOM.create('div', {style : 'position:relative'});\r
+                               n = DOM.add(n, 'div', {id : ed.id + '_external', 'class' : 'mceExternalToolbar'});\r
+                               DOM.add(n, 'a', {id : ed.id + '_external_close', href : 'javascript:;', 'class' : 'mceExternalClose'});\r
+                               n = DOM.add(n, 'table', {id : ed.id + '_tblext', cellSpacing : 0, cellPadding : 0});\r
+                               etb = DOM.add(n, 'tbody');\r
+\r
+                               if (p.firstChild.className == 'mceOldBoxModel')\r
+                                       p.firstChild.appendChild(c);\r
+                               else\r
+                                       p.insertBefore(c, p.firstChild);\r
+\r
+                               t._addToolbars(etb, o);\r
+\r
+                               ed.onMouseUp.add(function() {\r
+                                       var e = DOM.get(ed.id + '_external');\r
+                                       DOM.show(e);\r
+\r
+                                       DOM.hide(lastExtID);\r
+\r
+                                       var f = Event.add(ed.id + '_external_close', 'click', function() {\r
+                                               DOM.hide(ed.id + '_external');\r
+                                               Event.remove(ed.id + '_external_close', 'click', f);\r
+                                       });\r
+\r
+                                       DOM.show(e);\r
+                                       DOM.setStyle(e, 'top', 0 - DOM.getRect(ed.id + '_tblext').h - 1);\r
+\r
+                                       // Fixes IE rendering bug\r
+                                       DOM.hide(e);\r
+                                       DOM.show(e);\r
+                                       e.style.filter = '';\r
+\r
+                                       lastExtID = ed.id + '_external';\r
+\r
+                                       e = null;\r
+                               });\r
+                       }\r
+\r
+                       if (sl == 'top')\r
+                               t._addStatusBar(tb, o);\r
+\r
+                       // Create iframe container\r
+                       if (!s.theme_advanced_toolbar_container) {\r
+                               n = DOM.add(tb, 'tr');\r
+                               n = ic = DOM.add(n, 'td', {'class' : 'mceIframeContainer'});\r
+                       }\r
+\r
+                       // Create toolbar container at bottom\r
+                       if (lo == 'bottom')\r
+                               t._addToolbars(tb, o);\r
+\r
+                       if (sl == 'bottom')\r
+                               t._addStatusBar(tb, o);\r
+\r
+                       return ic;\r
+               },\r
+\r
+               _rowLayout : function(s, tb, o) {\r
+                       var t = this, ed = t.editor, dc, da, cf = ed.controlManager, n, ic, to, a;\r
+\r
+                       dc = s.theme_advanced_containers_default_class || '';\r
+                       da = s.theme_advanced_containers_default_align || 'center';\r
+\r
+                       each(explode(s.theme_advanced_containers || ''), function(c, i) {\r
+                               var v = s['theme_advanced_container_' + c] || '';\r
+\r
+                               switch (c.toLowerCase()) {\r
+                                       case 'mceeditor':\r
+                                               n = DOM.add(tb, 'tr');\r
+                                               n = ic = DOM.add(n, 'td', {'class' : 'mceIframeContainer'});\r
+                                               break;\r
+\r
+                                       case 'mceelementpath':\r
+                                               t._addStatusBar(tb, o);\r
+                                               break;\r
+\r
+                                       default:\r
+                                               a = s['theme_advanced_container_' + c + '_align'].toLowerCase();\r
+                                               a = 'mce' + t._ufirst(a);\r
+\r
+                                               n = DOM.add(DOM.add(tb, 'tr'), 'td', {\r
+                                                       'class' : 'mceToolbar ' + (s['theme_advanced_container_' + c + '_class'] || dc) + ' ' + a || da\r
+                                               });\r
+\r
+                                               to = cf.createToolbar("toolbar" + i);\r
+                                               t._addControls(v, to);\r
+                                               DOM.setHTML(n, to.renderHTML());\r
+                                               o.deltaHeight -= s.theme_advanced_row_height;\r
+                               }\r
+                       });\r
+\r
+                       return ic;\r
+               },\r
+\r
+               _addControls : function(v, tb) {\r
+                       var t = this, s = t.settings, di, cf = t.editor.controlManager;\r
+\r
+                       if (s.theme_advanced_disable && !t._disabled) {\r
+                               di = {};\r
+\r
+                               each(explode(s.theme_advanced_disable), function(v) {\r
+                                       di[v] = 1;\r
+                               });\r
+\r
+                               t._disabled = di;\r
+                       } else\r
+                               di = t._disabled;\r
+\r
+                       each(explode(v), function(n) {\r
+                               var c;\r
+\r
+                               if (di && di[n])\r
+                                       return;\r
+\r
+                               // Compatiblity with 2.x\r
+                               if (n == 'tablecontrols') {\r
+                                       each(["table","|","row_props","cell_props","|","row_before","row_after","delete_row","|","col_before","col_after","delete_col","|","split_cells","merge_cells"], function(n) {\r
+                                               n = t.createControl(n, cf);\r
+\r
+                                               if (n)\r
+                                                       tb.add(n);\r
+                                       });\r
+\r
+                                       return;\r
+                               }\r
+\r
+                               c = t.createControl(n, cf);\r
+\r
+                               if (c)\r
+                                       tb.add(c);\r
+                       });\r
+               },\r
+\r
+               _addToolbars : function(c, o) {\r
+                       var t = this, i, tb, ed = t.editor, s = t.settings, v, cf = ed.controlManager, di, n, h = [], a;\r
+\r
+                       a = s.theme_advanced_toolbar_align.toLowerCase();\r
+                       a = 'mce' + t._ufirst(a);\r
+\r
+                       n = DOM.add(DOM.add(c, 'tr'), 'td', {'class' : 'mceToolbar ' + a});\r
+\r
+                       if (!ed.getParam('accessibility_focus') || ed.getParam('tab_focus'))\r
+                               h.push(DOM.createHTML('a', {href : '#', onfocus : 'tinyMCE.get(\'' + ed.id + '\').focus();'}, '<!-- IE -->'));\r
+\r
+                       h.push(DOM.createHTML('a', {href : '#', accesskey : 'q', title : ed.getLang("advanced.toolbar_focus")}, '<!-- IE -->'));\r
+\r
+                       // Create toolbar and add the controls\r
+                       for (i=1; (v = s['theme_advanced_buttons' + i]); i++) {\r
+                               tb = cf.createToolbar("toolbar" + i, {'class' : 'mceToolbarRow' + i});\r
+\r
+                               if (s['theme_advanced_buttons' + i + '_add'])\r
+                                       v += ',' + s['theme_advanced_buttons' + i + '_add'];\r
+\r
+                               if (s['theme_advanced_buttons' + i + '_add_before'])\r
+                                       v = s['theme_advanced_buttons' + i + '_add_before'] + ',' + v;\r
+\r
+                               t._addControls(v, tb);\r
+\r
+                               //n.appendChild(n = tb.render());\r
+                               h.push(tb.renderHTML());\r
+\r
+                               o.deltaHeight -= s.theme_advanced_row_height;\r
+                       }\r
+\r
+                       h.push(DOM.createHTML('a', {href : '#', accesskey : 'z', title : ed.getLang("advanced.toolbar_focus"), onfocus : 'tinyMCE.getInstanceById(\'' + ed.id + '\').focus();'}, '<!-- IE -->'));\r
+                       DOM.setHTML(n, h.join(''));\r
+               },\r
+\r
+               _addStatusBar : function(tb, o) {\r
+                       var n, t = this, ed = t.editor, s = t.settings, r, mf, me, td;\r
+\r
+                       n = DOM.add(tb, 'tr');\r
+                       n = td = DOM.add(n, 'td', {'class' : 'mceStatusbar'});\r
+                       n = DOM.add(n, 'div', {id : ed.id + '_path_row'}, s.theme_advanced_path ? ed.translate('advanced.path') + ': ' : '&nbsp;');\r
+                       DOM.add(n, 'a', {href : '#', accesskey : 'x'});\r
+\r
+                       if (s.theme_advanced_resizing && !tinymce.isOldWebKit) {\r
+                               DOM.add(td, 'a', {id : ed.id + '_resize', href : 'javascript:;', onclick : "return false;", 'class' : 'mceResize'});\r
+\r
+                               if (s.theme_advanced_resizing_use_cookie) {\r
+                                       ed.onPostRender.add(function() {\r
+                                               var o = Cookie.getHash("TinyMCE_" + ed.id + "_size"), c = DOM.get(ed.id + '_tbl');\r
+\r
+                                               if (!o)\r
+                                                       return;\r
+\r
+                                               if (s.theme_advanced_resize_horizontal)\r
+                                                       c.style.width = Math.max(10, o.cw) + 'px';\r
+\r
+                                               c.style.height = Math.max(10, o.ch) + 'px';\r
+                                               DOM.get(ed.id + '_ifr').style.height = Math.max(10, parseInt(o.ch) + t.deltaHeight) + 'px';\r
+                                       });\r
+                               }\r
+\r
+                               ed.onPostRender.add(function() {\r
+                                       Event.add(ed.id + '_resize', 'mousedown', function(e) {\r
+                                               var c, p, w, h, n, pa;\r
+\r
+                                               // Measure container\r
+                                               c = DOM.get(ed.id + '_tbl');\r
+                                               w = c.clientWidth;\r
+                                               h = c.clientHeight;\r
+\r
+                                               miw = s.theme_advanced_resizing_min_width || 100;\r
+                                               mih = s.theme_advanced_resizing_min_height || 100;\r
+                                               maw = s.theme_advanced_resizing_max_width || 0xFFFF;\r
+                                               mah = s.theme_advanced_resizing_max_height || 0xFFFF;\r
+\r
+                                               // Setup placeholder\r
+                                               p = DOM.add(DOM.get(ed.id + '_parent'), 'div', {'class' : 'mcePlaceHolder'});\r
+                                               DOM.setStyles(p, {width : w, height : h});\r
+\r
+                                               // Replace with placeholder\r
+                                               DOM.hide(c);\r
+                                               DOM.show(p);\r
+\r
+                                               // Create internal resize obj\r
+                                               r = {\r
+                                                       x : e.screenX,\r
+                                                       y : e.screenY,\r
+                                                       w : w,\r
+                                                       h : h,\r
+                                                       dx : null,\r
+                                                       dy : null\r
+                                               };\r
+\r
+                                               // Start listening\r
+                                               mf = Event.add(DOM.doc, 'mousemove', function(e) {\r
+                                                       var w, h;\r
+\r
+                                                       // Calc delta values\r
+                                                       r.dx = e.screenX - r.x;\r
+                                                       r.dy = e.screenY - r.y;\r
+\r
+                                                       // Boundery fix box\r
+                                                       w = Math.max(miw, r.w + r.dx);\r
+                                                       h = Math.max(mih, r.h + r.dy);\r
+                                                       w = Math.min(maw, w);\r
+                                                       h = Math.min(mah, h);\r
+\r
+                                                       // Resize placeholder\r
+                                                       if (s.theme_advanced_resize_horizontal)\r
+                                                               p.style.width = w + 'px';\r
+\r
+                                                       p.style.height = h + 'px';\r
+\r
+                                                       return Event.cancel(e);\r
+                                               });\r
+\r
+                                               me = Event.add(DOM.doc, 'mouseup', function(e) {\r
+                                                       var ifr;\r
+\r
+                                                       // Stop listening\r
+                                                       Event.remove(DOM.doc, 'mousemove', mf);\r
+                                                       Event.remove(DOM.doc, 'mouseup', me);\r
+\r
+                                                       c.style.display = '';\r
+                                                       DOM.remove(p);\r
+\r
+                                                       if (r.dx === null)\r
+                                                               return;\r
+\r
+                                                       ifr = DOM.get(ed.id + '_ifr');\r
+\r
+                                                       if (s.theme_advanced_resize_horizontal)\r
+                                                               c.style.width = Math.max(10, r.w + r.dx) + 'px';\r
+\r
+                                                       c.style.height = Math.max(10, r.h + r.dy) + 'px';\r
+                                                       ifr.style.height = Math.max(10, ifr.clientHeight + r.dy) + 'px';\r
+\r
+                                                       if (s.theme_advanced_resizing_use_cookie) {\r
+                                                               Cookie.setHash("TinyMCE_" + ed.id + "_size", {\r
+                                                                       cw : r.w + r.dx,\r
+                                                                       ch : r.h + r.dy\r
+                                                               });\r
+                                                       }\r
+                                               });\r
+\r
+                                               return Event.cancel(e);\r
+                                       });\r
+                               });\r
+                       }\r
+\r
+                       o.deltaHeight -= 21;\r
+                       n = tb = null;\r
+               },\r
+\r
+               _nodeChanged : function(ed, cm, n, co) {\r
+                       var t = this, p, de = 0, v, c, s = t.settings;\r
+\r
+                       tinymce.each(t.stateControls, function(c) {\r
+                               cm.setActive(c, ed.queryCommandState(t.controls[c][1]));\r
+                       });\r
+\r
+                       cm.setActive('visualaid', ed.hasVisual);\r
+                       cm.setDisabled('undo', !ed.undoManager.hasUndo() && !ed.typing);\r
+                       cm.setDisabled('redo', !ed.undoManager.hasRedo());\r
+                       cm.setDisabled('outdent', !ed.queryCommandState('Outdent'));\r
+\r
+                       p = DOM.getParent(n, 'A');\r
+                       if (c = cm.get('link')) {\r
+                               if (!p || !p.name) {\r
+                                       c.setDisabled(!p && co);\r
+                                       c.setActive(!!p);\r
+                               }\r
+                       }\r
+\r
+                       if (c = cm.get('unlink')) {\r
+                               c.setDisabled(!p && co);\r
+                               c.setActive(!!p && !p.name);\r
+                       }\r
+\r
+                       if (c = cm.get('anchor')) {\r
+                               c.setActive(!!p && p.name);\r
+\r
+                               if (tinymce.isWebKit) {\r
+                                       p = DOM.getParent(n, 'IMG');\r
+                                       c.setActive(!!p && DOM.getAttrib(p, 'mce_name') == 'a');\r
+                               }\r
+                       }\r
+\r
+                       p = DOM.getParent(n, 'IMG');\r
+                       if (c = cm.get('image'))\r
+                               c.setActive(!!p && n.className.indexOf('mceItem') == -1);\r
+\r
+                       if (c = cm.get('styleselect')) {\r
+                               if (n.className) {\r
+                                       t._importClasses();\r
+                                       c.select(n.className);\r
+                               } else\r
+                                       c.select();\r
+                       }\r
+\r
+                       if (c = cm.get('formatselect')) {\r
+                               p = DOM.getParent(n, DOM.isBlock);\r
+\r
+                               if (p)\r
+                                       c.select(p.nodeName.toLowerCase());\r
+                       }\r
+\r
+                       if (c = cm.get('fontselect'))\r
+                               c.select(ed.queryCommandValue('FontName'));\r
+\r
+                       if (c = cm.get('fontsizeselect'))\r
+                               c.select(ed.queryCommandValue('FontSize'));\r
+\r
+                       if (s.theme_advanced_path && s.theme_advanced_statusbar_location) {\r
+                               p = DOM.get(ed.id + '_path') || DOM.add(ed.id + '_path_row', 'span', {id : ed.id + '_path'});\r
+                               DOM.setHTML(p, '');\r
+\r
+                               ed.dom.getParent(n, function(n) {\r
+                                       var na = n.nodeName.toLowerCase(), u, pi, ti = '';\r
+\r
+                                       // Ignore non element and hidden elements\r
+                                       if (n.nodeType != 1 || (DOM.hasClass(n, 'mceItemHidden') || DOM.hasClass(n, 'mceItemRemoved')))\r
+                                               return;\r
+\r
+                                       // Fake name\r
+                                       if (v = DOM.getAttrib(n, 'mce_name'))\r
+                                               na = v;\r
+       \r
+                                       // Handle prefix\r
+                                       if (tinymce.isIE && n.scopeName !== 'HTML')\r
+                                               na = n.scopeName + ':' + na;\r
+\r
+                                       // Remove internal prefix\r
+                                       na = na.replace(/mce\:/g, '');\r
+\r
+                                       // Handle node name\r
+                                       switch (na) {\r
+                                               case 'b':\r
+                                                       na = 'strong';\r
+                                                       break;\r
+\r
+                                               case 'i':\r
+                                                       na = 'em';\r
+                                                       break;\r
+\r
+                                               case 'img':\r
+                                                       if (v = DOM.getAttrib(n, 'src'))\r
+                                                               ti += 'src: ' + v + ' ';\r
+\r
+                                                       break;\r
+\r
+                                               case 'a':\r
+                                                       if (v = DOM.getAttrib(n, 'name')) {\r
+                                                               ti += 'name: ' + v + ' ';\r
+                                                               na += '#' + v;\r
+                                                       }\r
+\r
+                                                       if (v = DOM.getAttrib(n, 'href'))\r
+                                                               ti += 'href: ' + v + ' ';\r
+\r
+                                                       break;\r
+\r
+                                               case 'font':\r
+                                                       if (s.convert_fonts_to_spans)\r
+                                                               na = 'span';\r
+\r
+                                                       if (v = DOM.getAttrib(n, 'face'))\r
+                                                               ti += 'font: ' + v + ' ';\r
+\r
+                                                       if (v = DOM.getAttrib(n, 'size'))\r
+                                                               ti += 'size: ' + v + ' ';\r
+\r
+                                                       if (v = DOM.getAttrib(n, 'color'))\r
+                                                               ti += 'color: ' + v + ' ';\r
+\r
+                                                       break;\r
+\r
+                                               case 'span':\r
+                                                       if (v = DOM.getAttrib(n, 'style'))\r
+                                                               ti += 'style: ' + v + ' ';\r
+\r
+                                                       break;\r
+                                       }\r
+\r
+                                       if (v = DOM.getAttrib(n, 'id'))\r
+                                               ti += 'id: ' + v + ' ';\r
+\r
+                                       if (v = n.className) {\r
+                                               v = v.replace(/(webkit-[\w\-]+|Apple-[\w\-]+|mceItem\w+|mceVisualAid)/g, '');\r
+\r
+                                               if (v && v.indexOf('mceItem') == -1) {\r
+                                                       ti += 'class: ' + v + ' ';\r
+\r
+                                                       if (DOM.isBlock(n) || na == 'img' || na == 'span')\r
+                                                               na += '.' + v;\r
+                                               }\r
+                                       }\r
+\r
+                                       na = na.replace(/(html:)/g, '');\r
+                                       na = {name : na, node : n, title : ti};\r
+                                       t.onResolveName.dispatch(t, na);\r
+                                       ti = na.title;\r
+                                       na = na.name;\r
+\r
+                                       //u = "javascript:tinymce.EditorManager.get('" + ed.id + "').theme._sel('" + (de++) + "');";\r
+                                       pi = DOM.create('a', {'href' : "javascript:;", onmousedown : "return false;", title : ti, 'class' : 'mcePath_' + (de++)}, na);\r
+\r
+                                       if (p.hasChildNodes()) {\r
+                                               p.insertBefore(DOM.doc.createTextNode(' \u00bb '), p.firstChild);\r
+                                               p.insertBefore(pi, p.firstChild);\r
+                                       } else\r
+                                               p.appendChild(pi);\r
+                               }, ed.getBody());\r
+                       }\r
+               },\r
+\r
+               // Commands gets called by execCommand\r
+\r
+               _sel : function(v) {\r
+                       this.editor.execCommand('mceSelectNodeDepth', false, v);\r
+               },\r
+\r
+               _mceInsertAnchor : function(ui, v) {\r
+                       var ed = this.editor;\r
+\r
+                       ed.windowManager.open({\r
+                               url : tinymce.baseURL + '/themes/advanced/anchor.htm',\r
+                               width : 320 + parseInt(ed.getLang('advanced.anchor_delta_width', 0)),\r
+                               height : 90 + parseInt(ed.getLang('advanced.anchor_delta_height', 0)),\r
+                               inline : true\r
+                       }, {\r
+                               theme_url : this.url\r
+                       });\r
+               },\r
+\r
+               _mceCharMap : function() {\r
+                       var ed = this.editor;\r
+\r
+                       ed.windowManager.open({\r
+                               url : tinymce.baseURL + '/themes/advanced/charmap.htm',\r
+                               width : 550 + parseInt(ed.getLang('advanced.charmap_delta_width', 0)),\r
+                               height : 250 + parseInt(ed.getLang('advanced.charmap_delta_height', 0)),\r
+                               inline : true\r
+                       }, {\r
+                               theme_url : this.url\r
+                       });\r
+               },\r
+\r
+               _mceHelp : function() {\r
+                       var ed = this.editor;\r
+\r
+                       ed.windowManager.open({\r
+                               url : tinymce.baseURL + '/themes/advanced/about.htm',\r
+                               width : 480,\r
+                               height : 380,\r
+                               inline : true\r
+                       }, {\r
+                               theme_url : this.url\r
+                       });\r
+               },\r
+\r
+               _mceColorPicker : function(u, v) {\r
+                       var ed = this.editor;\r
+\r
+                       v = v || {};\r
+\r
+                       ed.windowManager.open({\r
+                               url : tinymce.baseURL + '/themes/advanced/color_picker.htm',\r
+                               width : 375 + parseInt(ed.getLang('advanced.colorpicker_delta_width', 0)),\r
+                               height : 250 + parseInt(ed.getLang('advanced.colorpicker_delta_height', 0)),\r
+                               close_previous : false,\r
+                               inline : true\r
+                       }, {\r
+                               input_color : v.color,\r
+                               func : v.func,\r
+                               theme_url : this.url\r
+                       });\r
+               },\r
+\r
+               _mceCodeEditor : function(ui, val) {\r
+                       var ed = this.editor;\r
+\r
+                       ed.windowManager.open({\r
+                               url : tinymce.baseURL + '/themes/advanced/source_editor.htm',\r
+                               width : parseInt(ed.getParam("theme_advanced_source_editor_width", 720)),\r
+                               height : parseInt(ed.getParam("theme_advanced_source_editor_height", 580)),\r
+                               inline : true,\r
+                               resizable : true,\r
+                               maximizable : true\r
+                       }, {\r
+                               theme_url : this.url\r
+                       });\r
+               },\r
+\r
+               _mceImage : function(ui, val) {\r
+                       var ed = this.editor;\r
+\r
+                       // Internal image object like a flash placeholder\r
+                       if (ed.dom.getAttrib(ed.selection.getNode(), 'class').indexOf('mceItem') != -1)\r
+                               return;\r
+\r
+                       ed.windowManager.open({\r
+                               url : tinymce.baseURL + '/themes/advanced/image.htm',\r
+                               width : 355 + parseInt(ed.getLang('advanced.image_delta_width', 0)),\r
+                               height : 275 + parseInt(ed.getLang('advanced.image_delta_height', 0)),\r
+                               inline : true\r
+                       }, {\r
+                               theme_url : this.url\r
+                       });\r
+               },\r
+\r
+               _mceLink : function(ui, val) {\r
+                       var ed = this.editor;\r
+\r
+                       ed.windowManager.open({\r
+                               url : tinymce.baseURL + '/themes/advanced/link.htm',\r
+                               width : 310 + parseInt(ed.getLang('advanced.link_delta_width', 0)),\r
+                               height : 200 + parseInt(ed.getLang('advanced.link_delta_height', 0)),\r
+                               inline : true\r
+                       }, {\r
+                               theme_url : this.url\r
+                       });\r
+               },\r
+\r
+               _mceNewDocument : function() {\r
+                       var ed = this.editor;\r
+\r
+                       ed.windowManager.confirm('advanced.newdocument', function(s) {\r
+                               if (s)\r
+                                       ed.execCommand('mceSetContent', false, '');\r
+                       });\r
+               },\r
+\r
+               _mceForeColor : function() {\r
+                       var t = this;\r
+\r
+                       this._mceColorPicker(0, {\r
+                               color: t.fgColor,\r
+                               func : function(co) {\r
+                                       t.fgColor = co;\r
+                                       t.editor.execCommand('ForeColor', false, co);\r
+                               }\r
+                       });\r
+               },\r
+\r
+               _mceBackColor : function() {\r
+                       var t = this;\r
+\r
+                       this._mceColorPicker(0, {\r
+                               color: t.bgColor,\r
+                               func : function(co) {\r
+                                       t.bgColor = co;\r
+                                       t.editor.execCommand('HiliteColor', false, co);\r
+                               }\r
+                       });\r
+               },\r
+\r
+               _ufirst : function(s) {\r
+                       return s.substring(0, 1).toUpperCase() + s.substring(1);\r
+               }\r
+       });\r
+\r
+       tinymce.ThemeManager.add('advanced', tinymce.themes.AdvancedTheme);\r
+}());
\ No newline at end of file
diff --git a/jscripts/tiny_mce/themes/advanced/image.htm b/jscripts/tiny_mce/themes/advanced/image.htm
new file mode 100644 (file)
index 0000000..cea51af
--- /dev/null
@@ -0,0 +1,86 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#advanced_dlg.image_title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>\r
+       <script type="text/javascript" src="js/image.js?v=307"></script>\r
+       <base target="_self" />\r
+</head>\r
+<body id="image" style="display: none">\r
+<form onsubmit="ImageDialog.update();return false;" action="#">\r
+       <div class="tabs">\r
+               <ul>\r
+                       <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advanced_dlg.image_title}</a></span></li>\r
+               </ul>\r
+       </div>\r
+\r
+       <div class="panel_wrapper">\r
+               <div id="general_panel" class="panel current">\r
+     <table border="0" cellpadding="4" cellspacing="0">\r
+          <tr>\r
+            <td nowrap="nowrap"><label for="src">{#advanced_dlg.image_src}</label></td>\r
+            <td><table border="0" cellspacing="0" cellpadding="0">\r
+                <tr>\r
+                  <td><input id="src" name="src" type="text" class="mceFocus" value="" style="width: 200px" onchange="ImageDialog.getImageData();" /></td>\r
+                  <td id="srcbrowsercontainer">&nbsp;</td>\r
+                </tr>\r
+              </table></td>\r
+          </tr>\r
+                 <tr>\r
+                       <td><label for="image_list">{#advanced_dlg.image_list}</label></td>\r
+                       <td><select id="image_list" name="image_list" onchange="document.getElementById('src').value=this.options[this.selectedIndex].value;document.getElementById('alt').value=this.options[this.selectedIndex].text;"></select></td>\r
+                 </tr>\r
+          <tr>\r
+            <td nowrap="nowrap"><label for="alt">{#advanced_dlg.image_alt}</label></td>\r
+            <td><input id="alt" name="alt" type="text" value="" style="width: 200px" /></td>\r
+          </tr>\r
+          <tr>\r
+            <td nowrap="nowrap"><label for="align">{#advanced_dlg.image_align}</label></td>\r
+            <td><select id="align" name="align" onchange="ImageDialog.updateStyle();">\r
+                <option value="">{#not_set}</option>\r
+                <option value="baseline">{#advanced_dlg.image_align_baseline}</option>\r
+                <option value="top">{#advanced_dlg.image_align_top}</option>\r
+                <option value="middle">{#advanced_dlg.image_align_middle}</option>\r
+                <option value="bottom">{#advanced_dlg.image_align_bottom}</option>\r
+                <option value="text-top">{#advanced_dlg.image_align_texttop}</option>\r
+                <option value="text-bottom">{#advanced_dlg.image_align_textbottom}</option>\r
+                <option value="left">{#advanced_dlg.image_align_left}</option>\r
+                <option value="right">{#advanced_dlg.image_align_right}</option>\r
+              </select></td>\r
+          </tr>\r
+          <tr>\r
+            <td nowrap="nowrap"><label for="width">{#advanced_dlg.image_dimensions}</label></td>\r
+            <td><input id="width" name="width" type="text" value="" size="3" maxlength="5" />\r
+              x\r
+              <input id="height" name="height" type="text" value="" size="3" maxlength="5" /></td>\r
+          </tr>\r
+          <tr>\r
+            <td nowrap="nowrap"><label for="border">{#advanced_dlg.image_border}</label></td>\r
+            <td><input id="border" name="border" type="text" value="" size="3" maxlength="3" onchange="ImageDialog.updateStyle();" /></td>\r
+          </tr>\r
+          <tr>\r
+            <td nowrap="nowrap"><label for="vspace">{#advanced_dlg.image_vspace}</label></td>\r
+            <td><input id="vspace" name="vspace" type="text" value="" size="3" maxlength="3" onchange="ImageDialog.updateStyle();" /></td>\r
+          </tr>\r
+          <tr>\r
+            <td nowrap="nowrap"><label for="hspace">{#advanced_dlg.image_hspace}</label></td>\r
+            <td><input id="hspace" name="hspace" type="text" value="" size="3" maxlength="3" onchange="ImageDialog.updateStyle();" /></td>\r
+          </tr>\r
+        </table>\r
+               </div>\r
+       </div>\r
+\r
+       <div class="mceActionPanel">\r
+               <div style="float: left">\r
+                       <input type="submit" id="insert" name="insert" value="{#insert}" />\r
+               </div>\r
+\r
+               <div style="float: right">\r
+                       <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+               </div>\r
+       </div>\r
+</form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/themes/advanced/img/colorpicker.jpg b/jscripts/tiny_mce/themes/advanced/img/colorpicker.jpg
new file mode 100644 (file)
index 0000000..b4c542d
Binary files /dev/null and b/jscripts/tiny_mce/themes/advanced/img/colorpicker.jpg differ
diff --git a/jscripts/tiny_mce/themes/advanced/img/icons.gif b/jscripts/tiny_mce/themes/advanced/img/icons.gif
new file mode 100644 (file)
index 0000000..ccac36f
Binary files /dev/null and b/jscripts/tiny_mce/themes/advanced/img/icons.gif differ
diff --git a/jscripts/tiny_mce/themes/advanced/js/about.js b/jscripts/tiny_mce/themes/advanced/js/about.js
new file mode 100644 (file)
index 0000000..9081e1d
--- /dev/null
@@ -0,0 +1,72 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+function init() {\r
+       var ed, tcont;\r
+\r
+       tinyMCEPopup.resizeToInnerSize();\r
+       ed = tinyMCEPopup.editor;\r
+\r
+       // Give FF some time\r
+       window.setTimeout('insertHelpIFrame();', 10);\r
+\r
+       tcont = document.getElementById('plugintablecontainer');\r
+       document.getElementById('plugins_tab').style.display = 'none';\r
+\r
+       var html = "";\r
+       html += '<table id="plugintable">';\r
+       html += '<thead>';\r
+       html += '<tr>';\r
+       html += '<td>' + ed.getLang('advanced_dlg.about_plugin') + '</td>';\r
+       html += '<td>' + ed.getLang('advanced_dlg.about_author') + '</td>';\r
+       html += '<td>' + ed.getLang('advanced_dlg.about_version') + '</td>';\r
+       html += '</tr>';\r
+       html += '</thead>';\r
+       html += '<tbody>';\r
+\r
+       tinymce.each(ed.plugins, function(p, n) {\r
+               var info;\r
+\r
+               if (!p.getInfo)\r
+                       return;\r
+\r
+               html += '<tr>';\r
+\r
+               info = p.getInfo();\r
+\r
+               if (info.infourl != null && info.infourl != '')\r
+                       html += '<td width="50%" title="' + n + '"><a href="' + info.infourl + '" target="_blank">' + info.longname + '</a></td>';\r
+               else\r
+                       html += '<td width="50%" title="' + n + '">' + info.longname + '</td>';\r
+\r
+               if (info.authorurl != null && info.authorurl != '')\r
+                       html += '<td width="35%"><a href="' + info.authorurl + '" target="_blank">' + info.author + '</a></td>';\r
+               else\r
+                       html += '<td width="35%">' + info.author + '</td>';\r
+\r
+               html += '<td width="15%">' + info.version + '</td>';\r
+               html += '</tr>';\r
+\r
+               document.getElementById('plugins_tab').style.display = '';\r
+\r
+       });\r
+\r
+       html += '</tbody>';\r
+       html += '</table>';\r
+\r
+       tcont.innerHTML = html;\r
+\r
+       tinyMCEPopup.dom.get('version').innerHTML = tinymce.majorVersion + "." + tinymce.minorVersion;\r
+       tinyMCEPopup.dom.get('date').innerHTML = tinymce.releaseDate;\r
+}\r
+\r
+function insertHelpIFrame() {\r
+       var html;\r
+\r
+       if (tinyMCEPopup.getParam('docs_url')) {\r
+               html = '<iframe width="100%" height="300" src="' + tinyMCEPopup.editor.baseURI.toAbsolute(tinyMCEPopup.getParam('docs_url')) + '"></iframe>';\r
+               document.getElementById('iframecontainer').innerHTML = html;\r
+               document.getElementById('help_tab').style.display = 'block';\r
+       }\r
+}\r
+\r
+tinyMCEPopup.onInit.add(init);\r
diff --git a/jscripts/tiny_mce/themes/advanced/js/anchor.js b/jscripts/tiny_mce/themes/advanced/js/anchor.js
new file mode 100644 (file)
index 0000000..b5efd1e
--- /dev/null
@@ -0,0 +1,37 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+var AnchorDialog = {\r
+       init : function(ed) {\r
+               var action, elm, f = document.forms[0];\r
+\r
+               this.editor = ed;\r
+               elm = ed.dom.getParent(ed.selection.getNode(), 'A,IMG');\r
+               v = ed.dom.getAttrib(elm, 'name');\r
+\r
+               if (v) {\r
+                       this.action = 'update';\r
+                       f.anchorName.value = v;\r
+               }\r
+\r
+               f.insert.value = ed.getLang(elm ? 'update' : 'insert');\r
+       },\r
+\r
+       update : function() {\r
+               var ed = this.editor;\r
+               \r
+               tinyMCEPopup.restoreSelection();\r
+\r
+               if (this.action != 'update')\r
+                       ed.selection.collapse(1);\r
+\r
+               // Webkit acts weird if empty inline element is inserted so we need to use a image instead\r
+               if (tinymce.isWebKit)\r
+                       ed.execCommand('mceInsertContent', 0, ed.dom.createHTML('img', {mce_name : 'a', name : document.forms[0].anchorName.value, 'class' : 'mceItemAnchor'}));\r
+               else\r
+                       ed.execCommand('mceInsertContent', 0, ed.dom.createHTML('a', {name : document.forms[0].anchorName.value, 'class' : 'mceItemAnchor'}, ''));\r
+\r
+               tinyMCEPopup.close();\r
+       }\r
+};\r
+\r
+tinyMCEPopup.onInit.add(AnchorDialog.init, AnchorDialog);\r
diff --git a/jscripts/tiny_mce/themes/advanced/js/charmap.js b/jscripts/tiny_mce/themes/advanced/js/charmap.js
new file mode 100644 (file)
index 0000000..8467ef6
--- /dev/null
@@ -0,0 +1,325 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+var charmap = [\r
+       ['&nbsp;',    '&#160;',  true, 'no-break space'],\r
+       ['&amp;',     '&#38;',   true, 'ampersand'],\r
+       ['&quot;',    '&#34;',   true, 'quotation mark'],\r
+// finance\r
+       ['&cent;',    '&#162;',  true, 'cent sign'],\r
+       ['&euro;',    '&#8364;', true, 'euro sign'],\r
+       ['&pound;',   '&#163;',  true, 'pound sign'],\r
+       ['&yen;',     '&#165;',  true, 'yen sign'],\r
+// signs\r
+       ['&copy;',    '&#169;',  true, 'copyright sign'],\r
+       ['&reg;',     '&#174;',  true, 'registered sign'],\r
+       ['&trade;',   '&#8482;', true, 'trade mark sign'],\r
+       ['&permil;',  '&#8240;', true, 'per mille sign'],\r
+       ['&micro;',   '&#181;',  true, 'micro sign'],\r
+       ['&middot;',  '&#183;',  true, 'middle dot'],\r
+       ['&bull;',    '&#8226;', true, 'bullet'],\r
+       ['&hellip;',  '&#8230;', true, 'three dot leader'],\r
+       ['&prime;',   '&#8242;', true, 'minutes / feet'],\r
+       ['&Prime;',   '&#8243;', true, 'seconds / inches'],\r
+       ['&sect;',    '&#167;',  true, 'section sign'],\r
+       ['&para;',    '&#182;',  true, 'paragraph sign'],\r
+       ['&szlig;',   '&#223;',  true, 'sharp s / ess-zed'],\r
+// quotations\r
+       ['&lsaquo;',  '&#8249;', true, 'single left-pointing angle quotation mark'],\r
+       ['&rsaquo;',  '&#8250;', true, 'single right-pointing angle quotation mark'],\r
+       ['&laquo;',   '&#171;',  true, 'left pointing guillemet'],\r
+       ['&raquo;',   '&#187;',  true, 'right pointing guillemet'],\r
+       ['&lsquo;',   '&#8216;', true, 'left single quotation mark'],\r
+       ['&rsquo;',   '&#8217;', true, 'right single quotation mark'],\r
+       ['&ldquo;',   '&#8220;', true, 'left double quotation mark'],\r
+       ['&rdquo;',   '&#8221;', true, 'right double quotation mark'],\r
+       ['&sbquo;',   '&#8218;', true, 'single low-9 quotation mark'],\r
+       ['&bdquo;',   '&#8222;', true, 'double low-9 quotation mark'],\r
+       ['&lt;',      '&#60;',   true, 'less-than sign'],\r
+       ['&gt;',      '&#62;',   true, 'greater-than sign'],\r
+       ['&le;',      '&#8804;', true, 'less-than or equal to'],\r
+       ['&ge;',      '&#8805;', true, 'greater-than or equal to'],\r
+       ['&ndash;',   '&#8211;', true, 'en dash'],\r
+       ['&mdash;',   '&#8212;', true, 'em dash'],\r
+       ['&macr;',    '&#175;',  true, 'macron'],\r
+       ['&oline;',   '&#8254;', true, 'overline'],\r
+       ['&curren;',  '&#164;',  true, 'currency sign'],\r
+       ['&brvbar;',  '&#166;',  true, 'broken bar'],\r
+       ['&uml;',     '&#168;',  true, 'diaeresis'],\r
+       ['&iexcl;',   '&#161;',  true, 'inverted exclamation mark'],\r
+       ['&iquest;',  '&#191;',  true, 'turned question mark'],\r
+       ['&circ;',    '&#710;',  true, 'circumflex accent'],\r
+       ['&tilde;',   '&#732;',  true, 'small tilde'],\r
+       ['&deg;',     '&#176;',  true, 'degree sign'],\r
+       ['&minus;',   '&#8722;', true, 'minus sign'],\r
+       ['&plusmn;',  '&#177;',  true, 'plus-minus sign'],\r
+       ['&divide;',  '&#247;',  true, 'division sign'],\r
+       ['&frasl;',   '&#8260;', true, 'fraction slash'],\r
+       ['&times;',   '&#215;',  true, 'multiplication sign'],\r
+       ['&sup1;',    '&#185;',  true, 'superscript one'],\r
+       ['&sup2;',    '&#178;',  true, 'superscript two'],\r
+       ['&sup3;',    '&#179;',  true, 'superscript three'],\r
+       ['&frac14;',  '&#188;',  true, 'fraction one quarter'],\r
+       ['&frac12;',  '&#189;',  true, 'fraction one half'],\r
+       ['&frac34;',  '&#190;',  true, 'fraction three quarters'],\r
+// math / logical\r
+       ['&fnof;',    '&#402;',  true, 'function / florin'],\r
+       ['&int;',     '&#8747;', true, 'integral'],\r
+       ['&sum;',     '&#8721;', true, 'n-ary sumation'],\r
+       ['&infin;',   '&#8734;', true, 'infinity'],\r
+       ['&radic;',   '&#8730;', true, 'square root'],\r
+       ['&sim;',     '&#8764;', false,'similar to'],\r
+       ['&cong;',    '&#8773;', false,'approximately equal to'],\r
+       ['&asymp;',   '&#8776;', true, 'almost equal to'],\r
+       ['&ne;',      '&#8800;', true, 'not equal to'],\r
+       ['&equiv;',   '&#8801;', true, 'identical to'],\r
+       ['&isin;',    '&#8712;', false,'element of'],\r
+       ['&notin;',   '&#8713;', false,'not an element of'],\r
+       ['&ni;',      '&#8715;', false,'contains as member'],\r
+       ['&prod;',    '&#8719;', true, 'n-ary product'],\r
+       ['&and;',     '&#8743;', false,'logical and'],\r
+       ['&or;',      '&#8744;', false,'logical or'],\r
+       ['&not;',     '&#172;',  true, 'not sign'],\r
+       ['&cap;',     '&#8745;', true, 'intersection'],\r
+       ['&cup;',     '&#8746;', false,'union'],\r
+       ['&part;',    '&#8706;', true, 'partial differential'],\r
+       ['&forall;',  '&#8704;', false,'for all'],\r
+       ['&exist;',   '&#8707;', false,'there exists'],\r
+       ['&empty;',   '&#8709;', false,'diameter'],\r
+       ['&nabla;',   '&#8711;', false,'backward difference'],\r
+       ['&lowast;',  '&#8727;', false,'asterisk operator'],\r
+       ['&prop;',    '&#8733;', false,'proportional to'],\r
+       ['&ang;',     '&#8736;', false,'angle'],\r
+// undefined\r
+       ['&acute;',   '&#180;',  true, 'acute accent'],\r
+       ['&cedil;',   '&#184;',  true, 'cedilla'],\r
+       ['&ordf;',    '&#170;',  true, 'feminine ordinal indicator'],\r
+       ['&ordm;',    '&#186;',  true, 'masculine ordinal indicator'],\r
+       ['&dagger;',  '&#8224;', true, 'dagger'],\r
+       ['&Dagger;',  '&#8225;', true, 'double dagger'],\r
+// alphabetical special chars\r
+       ['&Agrave;',  '&#192;',  true, 'A - grave'],\r
+       ['&Aacute;',  '&#193;',  true, 'A - acute'],\r
+       ['&Acirc;',   '&#194;',  true, 'A - circumflex'],\r
+       ['&Atilde;',  '&#195;',  true, 'A - tilde'],\r
+       ['&Auml;',    '&#196;',  true, 'A - diaeresis'],\r
+       ['&Aring;',   '&#197;',  true, 'A - ring above'],\r
+       ['&AElig;',   '&#198;',  true, 'ligature AE'],\r
+       ['&Ccedil;',  '&#199;',  true, 'C - cedilla'],\r
+       ['&Egrave;',  '&#200;',  true, 'E - grave'],\r
+       ['&Eacute;',  '&#201;',  true, 'E - acute'],\r
+       ['&Ecirc;',   '&#202;',  true, 'E - circumflex'],\r
+       ['&Euml;',    '&#203;',  true, 'E - diaeresis'],\r
+       ['&Igrave;',  '&#204;',  true, 'I - grave'],\r
+       ['&Iacute;',  '&#205;',  true, 'I - acute'],\r
+       ['&Icirc;',   '&#206;',  true, 'I - circumflex'],\r
+       ['&Iuml;',    '&#207;',  true, 'I - diaeresis'],\r
+       ['&ETH;',     '&#208;',  true, 'ETH'],\r
+       ['&Ntilde;',  '&#209;',  true, 'N - tilde'],\r
+       ['&Ograve;',  '&#210;',  true, 'O - grave'],\r
+       ['&Oacute;',  '&#211;',  true, 'O - acute'],\r
+       ['&Ocirc;',   '&#212;',  true, 'O - circumflex'],\r
+       ['&Otilde;',  '&#213;',  true, 'O - tilde'],\r
+       ['&Ouml;',    '&#214;',  true, 'O - diaeresis'],\r
+       ['&Oslash;',  '&#216;',  true, 'O - slash'],\r
+       ['&OElig;',   '&#338;',  true, 'ligature OE'],\r
+       ['&Scaron;',  '&#352;',  true, 'S - caron'],\r
+       ['&Ugrave;',  '&#217;',  true, 'U - grave'],\r
+       ['&Uacute;',  '&#218;',  true, 'U - acute'],\r
+       ['&Ucirc;',   '&#219;',  true, 'U - circumflex'],\r
+       ['&Uuml;',    '&#220;',  true, 'U - diaeresis'],\r
+       ['&Yacute;',  '&#221;',  true, 'Y - acute'],\r
+       ['&Yuml;',    '&#376;',  true, 'Y - diaeresis'],\r
+       ['&THORN;',   '&#222;',  true, 'THORN'],\r
+       ['&agrave;',  '&#224;',  true, 'a - grave'],\r
+       ['&aacute;',  '&#225;',  true, 'a - acute'],\r
+       ['&acirc;',   '&#226;',  true, 'a - circumflex'],\r
+       ['&atilde;',  '&#227;',  true, 'a - tilde'],\r
+       ['&auml;',    '&#228;',  true, 'a - diaeresis'],\r
+       ['&aring;',   '&#229;',  true, 'a - ring above'],\r
+       ['&aelig;',   '&#230;',  true, 'ligature ae'],\r
+       ['&ccedil;',  '&#231;',  true, 'c - cedilla'],\r
+       ['&egrave;',  '&#232;',  true, 'e - grave'],\r
+       ['&eacute;',  '&#233;',  true, 'e - acute'],\r
+       ['&ecirc;',   '&#234;',  true, 'e - circumflex'],\r
+       ['&euml;',    '&#235;',  true, 'e - diaeresis'],\r
+       ['&igrave;',  '&#236;',  true, 'i - grave'],\r
+       ['&iacute;',  '&#237;',  true, 'i - acute'],\r
+       ['&icirc;',   '&#238;',  true, 'i - circumflex'],\r
+       ['&iuml;',    '&#239;',  true, 'i - diaeresis'],\r
+       ['&eth;',     '&#240;',  true, 'eth'],\r
+       ['&ntilde;',  '&#241;',  true, 'n - tilde'],\r
+       ['&ograve;',  '&#242;',  true, 'o - grave'],\r
+       ['&oacute;',  '&#243;',  true, 'o - acute'],\r
+       ['&ocirc;',   '&#244;',  true, 'o - circumflex'],\r
+       ['&otilde;',  '&#245;',  true, 'o - tilde'],\r
+       ['&ouml;',    '&#246;',  true, 'o - diaeresis'],\r
+       ['&oslash;',  '&#248;',  true, 'o slash'],\r
+       ['&oelig;',   '&#339;',  true, 'ligature oe'],\r
+       ['&scaron;',  '&#353;',  true, 's - caron'],\r
+       ['&ugrave;',  '&#249;',  true, 'u - grave'],\r
+       ['&uacute;',  '&#250;',  true, 'u - acute'],\r
+       ['&ucirc;',   '&#251;',  true, 'u - circumflex'],\r
+       ['&uuml;',    '&#252;',  true, 'u - diaeresis'],\r
+       ['&yacute;',  '&#253;',  true, 'y - acute'],\r
+       ['&thorn;',   '&#254;',  true, 'thorn'],\r
+       ['&yuml;',    '&#255;',  true, 'y - diaeresis'],\r
+    ['&Alpha;',   '&#913;',  true, 'Alpha'],\r
+       ['&Beta;',    '&#914;',  true, 'Beta'],\r
+       ['&Gamma;',   '&#915;',  true, 'Gamma'],\r
+       ['&Delta;',   '&#916;',  true, 'Delta'],\r
+       ['&Epsilon;', '&#917;',  true, 'Epsilon'],\r
+       ['&Zeta;',    '&#918;',  true, 'Zeta'],\r
+       ['&Eta;',     '&#919;',  true, 'Eta'],\r
+       ['&Theta;',   '&#920;',  true, 'Theta'],\r
+       ['&Iota;',    '&#921;',  true, 'Iota'],\r
+       ['&Kappa;',   '&#922;',  true, 'Kappa'],\r
+       ['&Lambda;',  '&#923;',  true, 'Lambda'],\r
+       ['&Mu;',      '&#924;',  true, 'Mu'],\r
+       ['&Nu;',      '&#925;',  true, 'Nu'],\r
+       ['&Xi;',      '&#926;',  true, 'Xi'],\r
+       ['&Omicron;', '&#927;',  true, 'Omicron'],\r
+       ['&Pi;',      '&#928;',  true, 'Pi'],\r
+       ['&Rho;',     '&#929;',  true, 'Rho'],\r
+       ['&Sigma;',   '&#931;',  true, 'Sigma'],\r
+       ['&Tau;',     '&#932;',  true, 'Tau'],\r
+       ['&Upsilon;', '&#933;',  true, 'Upsilon'],\r
+       ['&Phi;',     '&#934;',  true, 'Phi'],\r
+       ['&Chi;',     '&#935;',  true, 'Chi'],\r
+       ['&Psi;',     '&#936;',  true, 'Psi'],\r
+       ['&Omega;',   '&#937;',  true, 'Omega'],\r
+       ['&alpha;',   '&#945;',  true, 'alpha'],\r
+       ['&beta;',    '&#946;',  true, 'beta'],\r
+       ['&gamma;',   '&#947;',  true, 'gamma'],\r
+       ['&delta;',   '&#948;',  true, 'delta'],\r
+       ['&epsilon;', '&#949;',  true, 'epsilon'],\r
+       ['&zeta;',    '&#950;',  true, 'zeta'],\r
+       ['&eta;',     '&#951;',  true, 'eta'],\r
+       ['&theta;',   '&#952;',  true, 'theta'],\r
+       ['&iota;',    '&#953;',  true, 'iota'],\r
+       ['&kappa;',   '&#954;',  true, 'kappa'],\r
+       ['&lambda;',  '&#955;',  true, 'lambda'],\r
+       ['&mu;',      '&#956;',  true, 'mu'],\r
+       ['&nu;',      '&#957;',  true, 'nu'],\r
+       ['&xi;',      '&#958;',  true, 'xi'],\r
+       ['&omicron;', '&#959;',  true, 'omicron'],\r
+       ['&pi;',      '&#960;',  true, 'pi'],\r
+       ['&rho;',     '&#961;',  true, 'rho'],\r
+       ['&sigmaf;',  '&#962;',  true, 'final sigma'],\r
+       ['&sigma;',   '&#963;',  true, 'sigma'],\r
+       ['&tau;',     '&#964;',  true, 'tau'],\r
+       ['&upsilon;', '&#965;',  true, 'upsilon'],\r
+       ['&phi;',     '&#966;',  true, 'phi'],\r
+       ['&chi;',     '&#967;',  true, 'chi'],\r
+       ['&psi;',     '&#968;',  true, 'psi'],\r
+       ['&omega;',   '&#969;',  true, 'omega'],\r
+// symbols\r
+       ['&alefsym;', '&#8501;', false,'alef symbol'],\r
+       ['&piv;',     '&#982;',  false,'pi symbol'],\r
+       ['&real;',    '&#8476;', false,'real part symbol'],\r
+       ['&thetasym;','&#977;',  false,'theta symbol'],\r
+       ['&upsih;',   '&#978;',  false,'upsilon - hook symbol'],\r
+       ['&weierp;',  '&#8472;', false,'Weierstrass p'],\r
+       ['&image;',   '&#8465;', false,'imaginary part'],\r
+// arrows\r
+       ['&larr;',    '&#8592;', true, 'leftwards arrow'],\r
+       ['&uarr;',    '&#8593;', true, 'upwards arrow'],\r
+       ['&rarr;',    '&#8594;', true, 'rightwards arrow'],\r
+       ['&darr;',    '&#8595;', true, 'downwards arrow'],\r
+       ['&harr;',    '&#8596;', true, 'left right arrow'],\r
+       ['&crarr;',   '&#8629;', false,'carriage return'],\r
+       ['&lArr;',    '&#8656;', false,'leftwards double arrow'],\r
+       ['&uArr;',    '&#8657;', false,'upwards double arrow'],\r
+       ['&rArr;',    '&#8658;', false,'rightwards double arrow'],\r
+       ['&dArr;',    '&#8659;', false,'downwards double arrow'],\r
+       ['&hArr;',    '&#8660;', false,'left right double arrow'],\r
+       ['&there4;',  '&#8756;', false,'therefore'],\r
+       ['&sub;',     '&#8834;', false,'subset of'],\r
+       ['&sup;',     '&#8835;', false,'superset of'],\r
+       ['&nsub;',    '&#8836;', false,'not a subset of'],\r
+       ['&sube;',    '&#8838;', false,'subset of or equal to'],\r
+       ['&supe;',    '&#8839;', false,'superset of or equal to'],\r
+       ['&oplus;',   '&#8853;', false,'circled plus'],\r
+       ['&otimes;',  '&#8855;', false,'circled times'],\r
+       ['&perp;',    '&#8869;', false,'perpendicular'],\r
+       ['&sdot;',    '&#8901;', false,'dot operator'],\r
+       ['&lceil;',   '&#8968;', false,'left ceiling'],\r
+       ['&rceil;',   '&#8969;', false,'right ceiling'],\r
+       ['&lfloor;',  '&#8970;', false,'left floor'],\r
+       ['&rfloor;',  '&#8971;', false,'right floor'],\r
+       ['&lang;',    '&#9001;', false,'left-pointing angle bracket'],\r
+       ['&rang;',    '&#9002;', false,'right-pointing angle bracket'],\r
+       ['&loz;',     '&#9674;', true,'lozenge'],\r
+       ['&spades;',  '&#9824;', false,'black spade suit'],\r
+       ['&clubs;',   '&#9827;', true, 'black club suit'],\r
+       ['&hearts;',  '&#9829;', true, 'black heart suit'],\r
+       ['&diams;',   '&#9830;', true, 'black diamond suit'],\r
+       ['&ensp;',    '&#8194;', false,'en space'],\r
+       ['&emsp;',    '&#8195;', false,'em space'],\r
+       ['&thinsp;',  '&#8201;', false,'thin space'],\r
+       ['&zwnj;',    '&#8204;', false,'zero width non-joiner'],\r
+       ['&zwj;',     '&#8205;', false,'zero width joiner'],\r
+       ['&lrm;',     '&#8206;', false,'left-to-right mark'],\r
+       ['&rlm;',     '&#8207;', false,'right-to-left mark'],\r
+       ['&shy;',     '&#173;',  false,'soft hyphen']\r
+];\r
+\r
+tinyMCEPopup.onInit.add(function() {\r
+       tinyMCEPopup.dom.setHTML('charmapView', renderCharMapHTML());\r
+});\r
+\r
+function renderCharMapHTML() {\r
+       var charsPerRow = 20, tdWidth=20, tdHeight=20, i;\r
+       var html = '<table border="0" cellspacing="1" cellpadding="0" width="' + (tdWidth*charsPerRow) + '"><tr height="' + tdHeight + '">';\r
+       var cols=-1;\r
+\r
+       for (i=0; i<charmap.length; i++) {\r
+               if (charmap[i][2]==true) {\r
+                       cols++;\r
+                       html += ''\r
+                               + '<td class="charmap">'\r
+                               + '<a onmouseover="previewChar(\'' + charmap[i][1].substring(1,charmap[i][1].length) + '\',\'' + charmap[i][0].substring(1,charmap[i][0].length) + '\',\'' + charmap[i][3] + '\');" onfocus="previewChar(\'' + charmap[i][1].substring(1,charmap[i][1].length) + '\',\'' + charmap[i][0].substring(1,charmap[i][0].length) + '\',\'' + charmap[i][3] + '\');" href="javascript:void(0)" onclick="insertChar(\'' + charmap[i][1].substring(2,charmap[i][1].length-1) + '\');" onclick="return false;" onmousedown="return false;" title="' + charmap[i][3] + '">'\r
+                               + charmap[i][1]\r
+                               + '</a></td>';\r
+                       if ((cols+1) % charsPerRow == 0)\r
+                               html += '</tr><tr height="' + tdHeight + '">';\r
+               }\r
+        }\r
+\r
+       if (cols % charsPerRow > 0) {\r
+               var padd = charsPerRow - (cols % charsPerRow);\r
+               for (var i=0; i<padd-1; i++)\r
+                       html += '<td width="' + tdWidth + '" height="' + tdHeight + '" class="charmap">&nbsp;</td>';\r
+       }\r
+\r
+       html += '</tr></table>';\r
+\r
+       return html;\r
+}\r
+\r
+function insertChar(chr) {\r
+       tinyMCEPopup.execCommand('mceInsertContent', false, '&#' + chr + ';');\r
+\r
+       // Refocus in window\r
+       if (tinyMCEPopup.isWindow)\r
+               window.focus();\r
+\r
+       tinyMCEPopup.editor.focus();\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function previewChar(codeA, codeB, codeN) {\r
+       var elmA = document.getElementById('codeA');\r
+       var elmB = document.getElementById('codeB');\r
+       var elmV = document.getElementById('codeV');\r
+       var elmN = document.getElementById('codeN');\r
+\r
+       if (codeA=='#160;') {\r
+               elmV.innerHTML = '__';\r
+       } else {\r
+               elmV.innerHTML = '&' + codeA;\r
+       }\r
+\r
+       elmB.innerHTML = '&amp;' + codeA;\r
+       elmA.innerHTML = '&amp;' + codeB;\r
+       elmN.innerHTML = codeN;\r
+}\r
diff --git a/jscripts/tiny_mce/themes/advanced/js/color_picker.js b/jscripts/tiny_mce/themes/advanced/js/color_picker.js
new file mode 100644 (file)
index 0000000..da833dc
--- /dev/null
@@ -0,0 +1,245 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+var detail = 50, strhex = "0123456789abcdef", i, isMouseDown = false, isMouseOver = false;\r
+\r
+var colors = [\r
+       "#000000","#000033","#000066","#000099","#0000cc","#0000ff","#330000","#330033",\r
+       "#330066","#330099","#3300cc","#3300ff","#660000","#660033","#660066","#660099",\r
+       "#6600cc","#6600ff","#990000","#990033","#990066","#990099","#9900cc","#9900ff",\r
+       "#cc0000","#cc0033","#cc0066","#cc0099","#cc00cc","#cc00ff","#ff0000","#ff0033",\r
+       "#ff0066","#ff0099","#ff00cc","#ff00ff","#003300","#003333","#003366","#003399",\r
+       "#0033cc","#0033ff","#333300","#333333","#333366","#333399","#3333cc","#3333ff",\r
+       "#663300","#663333","#663366","#663399","#6633cc","#6633ff","#993300","#993333",\r
+       "#993366","#993399","#9933cc","#9933ff","#cc3300","#cc3333","#cc3366","#cc3399",\r
+       "#cc33cc","#cc33ff","#ff3300","#ff3333","#ff3366","#ff3399","#ff33cc","#ff33ff",\r
+       "#006600","#006633","#006666","#006699","#0066cc","#0066ff","#336600","#336633",\r
+       "#336666","#336699","#3366cc","#3366ff","#666600","#666633","#666666","#666699",\r
+       "#6666cc","#6666ff","#996600","#996633","#996666","#996699","#9966cc","#9966ff",\r
+       "#cc6600","#cc6633","#cc6666","#cc6699","#cc66cc","#cc66ff","#ff6600","#ff6633",\r
+       "#ff6666","#ff6699","#ff66cc","#ff66ff","#009900","#009933","#009966","#009999",\r
+       "#0099cc","#0099ff","#339900","#339933","#339966","#339999","#3399cc","#3399ff",\r
+       "#669900","#669933","#669966","#669999","#6699cc","#6699ff","#999900","#999933",\r
+       "#999966","#999999","#9999cc","#9999ff","#cc9900","#cc9933","#cc9966","#cc9999",\r
+       "#cc99cc","#cc99ff","#ff9900","#ff9933","#ff9966","#ff9999","#ff99cc","#ff99ff",\r
+       "#00cc00","#00cc33","#00cc66","#00cc99","#00cccc","#00ccff","#33cc00","#33cc33",\r
+       "#33cc66","#33cc99","#33cccc","#33ccff","#66cc00","#66cc33","#66cc66","#66cc99",\r
+       "#66cccc","#66ccff","#99cc00","#99cc33","#99cc66","#99cc99","#99cccc","#99ccff",\r
+       "#cccc00","#cccc33","#cccc66","#cccc99","#cccccc","#ccccff","#ffcc00","#ffcc33",\r
+       "#ffcc66","#ffcc99","#ffcccc","#ffccff","#00ff00","#00ff33","#00ff66","#00ff99",\r
+       "#00ffcc","#00ffff","#33ff00","#33ff33","#33ff66","#33ff99","#33ffcc","#33ffff",\r
+       "#66ff00","#66ff33","#66ff66","#66ff99","#66ffcc","#66ffff","#99ff00","#99ff33",\r
+       "#99ff66","#99ff99","#99ffcc","#99ffff","#ccff00","#ccff33","#ccff66","#ccff99",\r
+       "#ccffcc","#ccffff","#ffff00","#ffff33","#ffff66","#ffff99","#ffffcc","#ffffff"\r
+];\r
+\r
+var named = {\r
+       '#F0F8FF':'AliceBlue','#FAEBD7':'AntiqueWhite','#00FFFF':'Aqua','#7FFFD4':'Aquamarine','#F0FFFF':'Azure','#F5F5DC':'Beige',\r
+       '#FFE4C4':'Bisque','#000000':'Black','#FFEBCD':'BlanchedAlmond','#0000FF':'Blue','#8A2BE2':'BlueViolet','#A52A2A':'Brown',\r
+       '#DEB887':'BurlyWood','#5F9EA0':'CadetBlue','#7FFF00':'Chartreuse','#D2691E':'Chocolate','#FF7F50':'Coral','#6495ED':'CornflowerBlue',\r
+       '#FFF8DC':'Cornsilk','#DC143C':'Crimson','#00FFFF':'Cyan','#00008B':'DarkBlue','#008B8B':'DarkCyan','#B8860B':'DarkGoldenRod',\r
+       '#A9A9A9':'DarkGray','#A9A9A9':'DarkGrey','#006400':'DarkGreen','#BDB76B':'DarkKhaki','#8B008B':'DarkMagenta','#556B2F':'DarkOliveGreen',\r
+       '#FF8C00':'Darkorange','#9932CC':'DarkOrchid','#8B0000':'DarkRed','#E9967A':'DarkSalmon','#8FBC8F':'DarkSeaGreen','#483D8B':'DarkSlateBlue',\r
+       '#2F4F4F':'DarkSlateGray','#2F4F4F':'DarkSlateGrey','#00CED1':'DarkTurquoise','#9400D3':'DarkViolet','#FF1493':'DeepPink','#00BFFF':'DeepSkyBlue',\r
+       '#696969':'DimGray','#696969':'DimGrey','#1E90FF':'DodgerBlue','#B22222':'FireBrick','#FFFAF0':'FloralWhite','#228B22':'ForestGreen',\r
+       '#FF00FF':'Fuchsia','#DCDCDC':'Gainsboro','#F8F8FF':'GhostWhite','#FFD700':'Gold','#DAA520':'GoldenRod','#808080':'Gray','#808080':'Grey',\r
+       '#008000':'Green','#ADFF2F':'GreenYellow','#F0FFF0':'HoneyDew','#FF69B4':'HotPink','#CD5C5C':'IndianRed','#4B0082':'Indigo','#FFFFF0':'Ivory',\r
+       '#F0E68C':'Khaki','#E6E6FA':'Lavender','#FFF0F5':'LavenderBlush','#7CFC00':'LawnGreen','#FFFACD':'LemonChiffon','#ADD8E6':'LightBlue',\r
+       '#F08080':'LightCoral','#E0FFFF':'LightCyan','#FAFAD2':'LightGoldenRodYellow','#D3D3D3':'LightGray','#D3D3D3':'LightGrey','#90EE90':'LightGreen',\r
+       '#FFB6C1':'LightPink','#FFA07A':'LightSalmon','#20B2AA':'LightSeaGreen','#87CEFA':'LightSkyBlue','#778899':'LightSlateGray','#778899':'LightSlateGrey',\r
+       '#B0C4DE':'LightSteelBlue','#FFFFE0':'LightYellow','#00FF00':'Lime','#32CD32':'LimeGreen','#FAF0E6':'Linen','#FF00FF':'Magenta','#800000':'Maroon',\r
+       '#66CDAA':'MediumAquaMarine','#0000CD':'MediumBlue','#BA55D3':'MediumOrchid','#9370D8':'MediumPurple','#3CB371':'MediumSeaGreen','#7B68EE':'MediumSlateBlue',\r
+       '#00FA9A':'MediumSpringGreen','#48D1CC':'MediumTurquoise','#C71585':'MediumVioletRed','#191970':'MidnightBlue','#F5FFFA':'MintCream','#FFE4E1':'MistyRose','#FFE4B5':'Moccasin',\r
+       '#FFDEAD':'NavajoWhite','#000080':'Navy','#FDF5E6':'OldLace','#808000':'Olive','#6B8E23':'OliveDrab','#FFA500':'Orange','#FF4500':'OrangeRed','#DA70D6':'Orchid',\r
+       '#EEE8AA':'PaleGoldenRod','#98FB98':'PaleGreen','#AFEEEE':'PaleTurquoise','#D87093':'PaleVioletRed','#FFEFD5':'PapayaWhip','#FFDAB9':'PeachPuff',\r
+       '#CD853F':'Peru','#FFC0CB':'Pink','#DDA0DD':'Plum','#B0E0E6':'PowderBlue','#800080':'Purple','#FF0000':'Red','#BC8F8F':'RosyBrown','#4169E1':'RoyalBlue',\r
+       '#8B4513':'SaddleBrown','#FA8072':'Salmon','#F4A460':'SandyBrown','#2E8B57':'SeaGreen','#FFF5EE':'SeaShell','#A0522D':'Sienna','#C0C0C0':'Silver',\r
+       '#87CEEB':'SkyBlue','#6A5ACD':'SlateBlue','#708090':'SlateGray','#708090':'SlateGrey','#FFFAFA':'Snow','#00FF7F':'SpringGreen',\r
+       '#4682B4':'SteelBlue','#D2B48C':'Tan','#008080':'Teal','#D8BFD8':'Thistle','#FF6347':'Tomato','#40E0D0':'Turquoise','#EE82EE':'Violet',\r
+       '#F5DEB3':'Wheat','#FFFFFF':'White','#F5F5F5':'WhiteSmoke','#FFFF00':'Yellow','#9ACD32':'YellowGreen'\r
+};\r
+\r
+function init() {\r
+       var inputColor = convertRGBToHex(tinyMCEPopup.getWindowArg('input_color'));\r
+\r
+       tinyMCEPopup.resizeToInnerSize();\r
+\r
+       generatePicker();\r
+\r
+       if (inputColor) {\r
+               changeFinalColor(inputColor);\r
+\r
+               col = convertHexToRGB(inputColor);\r
+\r
+               if (col)\r
+                       updateLight(col.r, col.g, col.b);\r
+       }\r
+}\r
+\r
+function insertAction() {\r
+       var color = document.getElementById("color").value, f = tinyMCEPopup.getWindowArg('func');\r
+\r
+       tinyMCEPopup.restoreSelection();\r
+\r
+       if (f)\r
+               f(color);\r
+\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function showColor(color, name) {\r
+       if (name)\r
+               document.getElementById("colorname").innerHTML = name;\r
+\r
+       document.getElementById("preview").style.backgroundColor = color;\r
+       document.getElementById("color").value = color.toLowerCase();\r
+}\r
+\r
+function convertRGBToHex(col) {\r
+       var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi");\r
+\r
+       if (!col)\r
+               return col;\r
+\r
+       var rgb = col.replace(re, "$1,$2,$3").split(',');\r
+       if (rgb.length == 3) {\r
+               r = parseInt(rgb[0]).toString(16);\r
+               g = parseInt(rgb[1]).toString(16);\r
+               b = parseInt(rgb[2]).toString(16);\r
+\r
+               r = r.length == 1 ? '0' + r : r;\r
+               g = g.length == 1 ? '0' + g : g;\r
+               b = b.length == 1 ? '0' + b : b;\r
+\r
+               return "#" + r + g + b;\r
+       }\r
+\r
+       return col;\r
+}\r
+\r
+function convertHexToRGB(col) {\r
+       if (col.indexOf('#') != -1) {\r
+               col = col.replace(new RegExp('[^0-9A-F]', 'gi'), '');\r
+\r
+               r = parseInt(col.substring(0, 2), 16);\r
+               g = parseInt(col.substring(2, 4), 16);\r
+               b = parseInt(col.substring(4, 6), 16);\r
+\r
+               return {r : r, g : g, b : b};\r
+       }\r
+\r
+       return null;\r
+}\r
+\r
+function generatePicker() {\r
+       var el = document.getElementById('light'), h = '', i;\r
+\r
+       for (i = 0; i < detail; i++){\r
+               h += '<div id="gs'+i+'" style="background-color:#000000; width:15px; height:3px; border-style:none; border-width:0px;"'\r
+               + ' onclick="changeFinalColor(this.style.backgroundColor)"'\r
+               + ' onmousedown="isMouseDown = true; return false;"'\r
+               + ' onmouseup="isMouseDown = false;"'\r
+               + ' onmousemove="if (isMouseDown && isMouseOver) changeFinalColor(this.style.backgroundColor); return false;"'\r
+               + ' onmouseover="isMouseOver = true;"'\r
+               + ' onmouseout="isMouseOver = false;"'\r
+               + '></div>';\r
+       }\r
+\r
+       el.innerHTML = h;\r
+}\r
+\r
+function generateWebColors() {\r
+       var el = document.getElementById('webcolors'), h = '', i;\r
+\r
+       if (el.className == 'generated')\r
+               return;\r
+\r
+       h += '<table border="0" cellspacing="1" cellpadding="0">'\r
+               + '<tr>';\r
+\r
+       for (i=0; i<colors.length; i++) {\r
+               h += '<td bgcolor="' + colors[i] + '" width="10" height="10">'\r
+                       + '<a href="javascript:insertAction();" onfocus="showColor(\'' + colors[i] +  '\');" onmouseover="showColor(\'' + colors[i] +  '\');" style="display:block;width:10px;height:10px;overflow:hidden;">'\r
+                       + '</a></td>';\r
+               if ((i+1) % 18 == 0)\r
+                       h += '</tr><tr>';\r
+       }\r
+\r
+       h += '</table>';\r
+\r
+       el.innerHTML = h;\r
+       el.className = 'generated';\r
+}\r
+\r
+function generateNamedColors() {\r
+       var el = document.getElementById('namedcolors'), h = '', n, v, i = 0;\r
+\r
+       if (el.className == 'generated')\r
+               return;\r
+\r
+       for (n in named) {\r
+               v = named[n];\r
+               h += '<a href="javascript:insertAction();" onmouseover="showColor(\'' + n +  '\',\'' + v + '\');" style="background-color: ' + n + '"><!-- IE --></a>'\r
+       }\r
+\r
+       el.innerHTML = h;\r
+       el.className = 'generated';\r
+}\r
+\r
+function dechex(n) {\r
+       return strhex.charAt(Math.floor(n / 16)) + strhex.charAt(n % 16);\r
+}\r
+\r
+function computeColor(e) {\r
+       var x, y, partWidth, partDetail, imHeight, r, g, b, coef, i, finalCoef, finalR, finalG, finalB;\r
+\r
+       x = e.offsetX ? e.offsetX : (e.target ? e.clientX - e.target.x : 0);\r
+       y = e.offsetY ? e.offsetY : (e.target ? e.clientY - e.target.y : 0);\r
+\r
+       partWidth = document.getElementById('colors').width / 6;\r
+       partDetail = detail / 2;\r
+       imHeight = document.getElementById('colors').height;\r
+\r
+       r = (x >= 0)*(x < partWidth)*255 + (x >= partWidth)*(x < 2*partWidth)*(2*255 - x * 255 / partWidth) + (x >= 4*partWidth)*(x < 5*partWidth)*(-4*255 + x * 255 / partWidth) + (x >= 5*partWidth)*(x < 6*partWidth)*255;\r
+       g = (x >= 0)*(x < partWidth)*(x * 255 / partWidth) + (x >= partWidth)*(x < 3*partWidth)*255     + (x >= 3*partWidth)*(x < 4*partWidth)*(4*255 - x * 255 / partWidth);\r
+       b = (x >= 2*partWidth)*(x < 3*partWidth)*(-2*255 + x * 255 / partWidth) + (x >= 3*partWidth)*(x < 5*partWidth)*255 + (x >= 5*partWidth)*(x < 6*partWidth)*(6*255 - x * 255 / partWidth);\r
+\r
+       coef = (imHeight - y) / imHeight;\r
+       r = 128 + (r - 128) * coef;\r
+       g = 128 + (g - 128) * coef;\r
+       b = 128 + (b - 128) * coef;\r
+\r
+       changeFinalColor('#' + dechex(r) + dechex(g) + dechex(b));\r
+       updateLight(r, g, b);\r
+}\r
+\r
+function updateLight(r, g, b) {\r
+       var i, partDetail = detail / 2, finalCoef, finalR, finalG, finalB, color;\r
+\r
+       for (i=0; i<detail; i++) {\r
+               if ((i>=0) && (i<partDetail)) {\r
+                       finalCoef = i / partDetail;\r
+                       finalR = dechex(255 - (255 - r) * finalCoef);\r
+                       finalG = dechex(255 - (255 - g) * finalCoef);\r
+                       finalB = dechex(255 - (255 - b) * finalCoef);\r
+               } else {\r
+                       finalCoef = 2 - i / partDetail;\r
+                       finalR = dechex(r * finalCoef);\r
+                       finalG = dechex(g * finalCoef);\r
+                       finalB = dechex(b * finalCoef);\r
+               }\r
+\r
+               color = finalR + finalG + finalB;\r
+\r
+               document.getElementById('gs' + i).style.backgroundColor = '#'+color;\r
+       }\r
+}\r
+\r
+function changeFinalColor(color) {\r
+       if (color.indexOf('#') == -1)\r
+               color = convertRGBToHex(color);\r
+\r
+       document.getElementById('preview').style.backgroundColor = color;\r
+       document.getElementById('color').value = color;\r
+}\r
+\r
+tinyMCEPopup.onInit.add(init);\r
diff --git a/jscripts/tiny_mce/themes/advanced/js/image.js b/jscripts/tiny_mce/themes/advanced/js/image.js
new file mode 100644 (file)
index 0000000..038ace7
--- /dev/null
@@ -0,0 +1,245 @@
+var ImageDialog = {\r
+       preInit : function() {\r
+               var url;\r
+\r
+               tinyMCEPopup.requireLangPack();\r
+\r
+               if (url = tinyMCEPopup.getParam("external_image_list_url"))\r
+                       document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>');\r
+       },\r
+\r
+       init : function() {\r
+               var f = document.forms[0], ed = tinyMCEPopup.editor;\r
+\r
+               // Setup browse button\r
+               document.getElementById('srcbrowsercontainer').innerHTML = getBrowserHTML('srcbrowser','src','image','theme_advanced_image');\r
+               if (isVisible('srcbrowser'))\r
+                       document.getElementById('src').style.width = '180px';\r
+\r
+               e = ed.selection.getNode();\r
+\r
+               this.fillFileList('image_list', 'tinyMCEImageList');\r
+\r
+               if (e.nodeName == 'IMG') {\r
+                       f.src.value = ed.dom.getAttrib(e, 'src');\r
+                       f.alt.value = ed.dom.getAttrib(e, 'alt');\r
+                       f.border.value = this.getAttrib(e, 'border');\r
+                       f.vspace.value = this.getAttrib(e, 'vspace');\r
+                       f.hspace.value = this.getAttrib(e, 'hspace');\r
+                       f.width.value = ed.dom.getAttrib(e, 'width');\r
+                       f.height.value = ed.dom.getAttrib(e, 'height');\r
+                       f.insert.value = ed.getLang('update');\r
+                       this.styleVal = ed.dom.getAttrib(e, 'style');\r
+                       selectByValue(f, 'image_list', f.src.value);\r
+                       selectByValue(f, 'align', this.getAttrib(e, 'align'));\r
+                       this.updateStyle();\r
+               }\r
+       },\r
+\r
+       fillFileList : function(id, l) {\r
+               var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl;\r
+\r
+               l = window[l];\r
+\r
+               if (l && l.length > 0) {\r
+                       lst.options[lst.options.length] = new Option('', '');\r
+\r
+                       tinymce.each(l, function(o) {\r
+                               lst.options[lst.options.length] = new Option(o[0], o[1]);\r
+                       });\r
+               } else\r
+                       dom.remove(dom.getParent(id, 'tr'));\r
+       },\r
+\r
+       update : function() {\r
+               var f = document.forms[0], nl = f.elements, ed = tinyMCEPopup.editor, args = {}, el;\r
+\r
+               tinyMCEPopup.restoreSelection();\r
+\r
+               if (f.src.value === '') {\r
+                       if (ed.selection.getNode().nodeName == 'IMG') {\r
+                               ed.dom.remove(ed.selection.getNode());\r
+                               ed.execCommand('mceRepaint');\r
+                       }\r
+\r
+                       tinyMCEPopup.close();\r
+                       return;\r
+               }\r
+\r
+               if (!ed.settings.inline_styles) {\r
+                       args = tinymce.extend(args, {\r
+                               vspace : nl.vspace.value,\r
+                               hspace : nl.hspace.value,\r
+                               border : nl.border.value,\r
+                               align : getSelectValue(f, 'align')\r
+                       });\r
+               } else\r
+                       args.style = this.styleVal;\r
+\r
+               tinymce.extend(args, {\r
+                       src : f.src.value,\r
+                       alt : f.alt.value,\r
+                       width : f.width.value,\r
+                       height : f.height.value\r
+               });\r
+\r
+               el = ed.selection.getNode();\r
+\r
+               if (el && el.nodeName == 'IMG') {\r
+                       ed.dom.setAttribs(el, args);\r
+               } else {\r
+                       ed.execCommand('mceInsertContent', false, '<img id="__mce_tmp" src="javascript:;" />', {skip_undo : 1});\r
+                       ed.dom.setAttribs('__mce_tmp', args);\r
+                       ed.dom.setAttrib('__mce_tmp', 'id', '');\r
+                       ed.undoManager.add();\r
+               }\r
+\r
+               tinyMCEPopup.close();\r
+       },\r
+\r
+       updateStyle : function() {\r
+               var dom = tinyMCEPopup.dom, st, v, f = document.forms[0];\r
+\r
+               if (tinyMCEPopup.editor.settings.inline_styles) {\r
+                       st = tinyMCEPopup.dom.parseStyle(this.styleVal);\r
+\r
+                       // Handle align\r
+                       v = getSelectValue(f, 'align');\r
+                       if (v) {\r
+                               if (v == 'left' || v == 'right') {\r
+                                       st['float'] = v;\r
+                                       delete st['vertical-align'];\r
+                               } else {\r
+                                       st['vertical-align'] = v;\r
+                                       delete st['float'];\r
+                               }\r
+                       } else {\r
+                               delete st['float'];\r
+                               delete st['vertical-align'];\r
+                       }\r
+\r
+                       // Handle border\r
+                       v = f.border.value;\r
+                       if (v || v == '0') {\r
+                               if (v == '0')\r
+                                       st['border'] = '0';\r
+                               else\r
+                                       st['border'] = v + 'px solid black';\r
+                       } else\r
+                               delete st['border'];\r
+\r
+                       // Handle hspace\r
+                       v = f.hspace.value;\r
+                       if (v) {\r
+                               delete st['margin'];\r
+                               st['margin-left'] = v + 'px';\r
+                               st['margin-right'] = v + 'px';\r
+                       } else {\r
+                               delete st['margin-left'];\r
+                               delete st['margin-right'];\r
+                       }\r
+\r
+                       // Handle vspace\r
+                       v = f.vspace.value;\r
+                       if (v) {\r
+                               delete st['margin'];\r
+                               st['margin-top'] = v + 'px';\r
+                               st['margin-bottom'] = v + 'px';\r
+                       } else {\r
+                               delete st['margin-top'];\r
+                               delete st['margin-bottom'];\r
+                       }\r
+\r
+                       // Merge\r
+                       st = tinyMCEPopup.dom.parseStyle(dom.serializeStyle(st));\r
+                       this.styleVal = dom.serializeStyle(st);\r
+               }\r
+       },\r
+\r
+       getAttrib : function(e, at) {\r
+               var ed = tinyMCEPopup.editor, dom = ed.dom, v, v2;\r
+\r
+               if (ed.settings.inline_styles) {\r
+                       switch (at) {\r
+                               case 'align':\r
+                                       if (v = dom.getStyle(e, 'float'))\r
+                                               return v;\r
+\r
+                                       if (v = dom.getStyle(e, 'vertical-align'))\r
+                                               return v;\r
+\r
+                                       break;\r
+\r
+                               case 'hspace':\r
+                                       v = dom.getStyle(e, 'margin-left')\r
+                                       v2 = dom.getStyle(e, 'margin-right');\r
+                                       if (v && v == v2)\r
+                                               return parseInt(v.replace(/[^0-9]/g, ''));\r
+\r
+                                       break;\r
+\r
+                               case 'vspace':\r
+                                       v = dom.getStyle(e, 'margin-top')\r
+                                       v2 = dom.getStyle(e, 'margin-bottom');\r
+                                       if (v && v == v2)\r
+                                               return parseInt(v.replace(/[^0-9]/g, ''));\r
+\r
+                                       break;\r
+\r
+                               case 'border':\r
+                                       v = 0;\r
+\r
+                                       tinymce.each(['top', 'right', 'bottom', 'left'], function(sv) {\r
+                                               sv = dom.getStyle(e, 'border-' + sv + '-width');\r
+\r
+                                               // False or not the same as prev\r
+                                               if (!sv || (sv != v && v !== 0)) {\r
+                                                       v = 0;\r
+                                                       return false;\r
+                                               }\r
+\r
+                                               if (sv)\r
+                                                       v = sv;\r
+                                       });\r
+\r
+                                       if (v)\r
+                                               return parseInt(v.replace(/[^0-9]/g, ''));\r
+\r
+                                       break;\r
+                       }\r
+               }\r
+\r
+               if (v = dom.getAttrib(e, at))\r
+                       return v;\r
+\r
+               return '';\r
+       },\r
+\r
+       resetImageData : function() {\r
+               var f = document.forms[0];\r
+\r
+               f.width.value = f.height.value = "";    \r
+       },\r
+\r
+       updateImageData : function() {\r
+               var f = document.forms[0], t = ImageDialog;\r
+\r
+               if (f.width.value == "")\r
+                       f.width.value = t.preloadImg.width;\r
+\r
+               if (f.height.value == "")\r
+                       f.height.value = t.preloadImg.height;\r
+       },\r
+\r
+       getImageData : function() {\r
+               var f = document.forms[0];\r
+\r
+               this.preloadImg = new Image();\r
+               this.preloadImg.onload = this.updateImageData;\r
+               this.preloadImg.onerror = this.resetImageData;\r
+               this.preloadImg.src = tinyMCEPopup.editor.documentBaseURI.toAbsolute(f.src.value);\r
+       }\r
+};\r
+\r
+ImageDialog.preInit();\r
+tinyMCEPopup.onInit.add(ImageDialog.init, ImageDialog);\r
diff --git a/jscripts/tiny_mce/themes/advanced/js/link.js b/jscripts/tiny_mce/themes/advanced/js/link.js
new file mode 100644 (file)
index 0000000..2974878
--- /dev/null
@@ -0,0 +1,155 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+var LinkDialog = {\r
+       preInit : function() {\r
+               var url;\r
+\r
+               if (url = tinyMCEPopup.getParam("external_link_list_url"))\r
+                       document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>');\r
+       },\r
+\r
+       init : function() {\r
+               var f = document.forms[0], ed = tinyMCEPopup.editor;\r
+\r
+               // Setup browse button\r
+               document.getElementById('hrefbrowsercontainer').innerHTML = getBrowserHTML('hrefbrowser', 'href', 'file', 'theme_advanced_link');\r
+               if (isVisible('hrefbrowser'))\r
+                       document.getElementById('href').style.width = '180px';\r
+\r
+               this.fillClassList('class_list');\r
+               this.fillFileList('link_list', 'tinyMCELinkList');\r
+               this.fillTargetList('target_list');\r
+\r
+               if (e = ed.dom.getParent(ed.selection.getNode(), 'A')) {\r
+                       f.href.value = ed.dom.getAttrib(e, 'href');\r
+                       f.linktitle.value = ed.dom.getAttrib(e, 'title');\r
+                       f.insert.value = ed.getLang('update');\r
+                       selectByValue(f, 'link_list', f.href.value);\r
+                       selectByValue(f, 'target_list', ed.dom.getAttrib(e, 'target'));\r
+                       selectByValue(f, 'class_list', ed.dom.getAttrib(e, 'class'));\r
+               }\r
+       },\r
+\r
+       update : function() {\r
+               var f = document.forms[0], ed = tinyMCEPopup.editor, e, b;\r
+\r
+               tinyMCEPopup.restoreSelection();\r
+               e = ed.dom.getParent(ed.selection.getNode(), 'A');\r
+\r
+               // Remove element if there is no href\r
+               if (!f.href.value) {\r
+                       if (e) {\r
+                               tinyMCEPopup.execCommand("mceBeginUndoLevel");\r
+                               b = ed.selection.getBookmark();\r
+                               ed.dom.remove(e, 1);\r
+                               ed.selection.moveToBookmark(b);\r
+                               tinyMCEPopup.execCommand("mceEndUndoLevel");\r
+                               tinyMCEPopup.close();\r
+                               return;\r
+                       }\r
+               }\r
+\r
+               tinyMCEPopup.execCommand("mceBeginUndoLevel");\r
+\r
+               // Create new anchor elements\r
+               if (e == null) {\r
+                       tinyMCEPopup.execCommand("CreateLink", false, "#mce_temp_url#", {skip_undo : 1});\r
+\r
+                       tinymce.each(ed.dom.select("a"), function(n) {\r
+                               if (ed.dom.getAttrib(n, 'href') == '#mce_temp_url#') {\r
+                                       e = n;\r
+\r
+                                       ed.dom.setAttribs(e, {\r
+                                               href : f.href.value,\r
+                                               title : f.linktitle.value,\r
+                                               target : f.target_list ? f.target_list.options[f.target_list.selectedIndex].value : null,\r
+                                               'class' : f.class_list ? f.class_list.options[f.class_list.selectedIndex].value : null\r
+                                       });\r
+                               }\r
+                       });\r
+               } else {\r
+                       ed.dom.setAttribs(e, {\r
+                               href : f.href.value,\r
+                               title : f.linktitle.value,\r
+                               target : f.target_list ? f.target_list.options[f.target_list.selectedIndex].value : null,\r
+                               'class' : f.class_list ? f.class_list.options[f.class_list.selectedIndex].value : null\r
+                       });\r
+               }\r
+\r
+               // Don't move caret if selection was image\r
+               if (e.childNodes.length != 1 || e.firstChild.nodeName != 'IMG') {\r
+                       ed.focus();\r
+                       ed.selection.select(e);\r
+                       ed.selection.collapse(0);\r
+                       tinyMCEPopup.storeSelection();\r
+               }\r
+\r
+               tinyMCEPopup.execCommand("mceEndUndoLevel");\r
+               tinyMCEPopup.close();\r
+       },\r
+\r
+       checkPrefix : function(n) {\r
+               if (n.value && Validator.isEmail(n) && !/^\s*mailto:/i.test(n.value) && confirm(tinyMCEPopup.getLang('advanced_dlg.link_is_email')))\r
+                       n.value = 'mailto:' + n.value;\r
+\r
+               if (/^\s*www./i.test(n.value) && confirm(tinyMCEPopup.getLang('advanced_dlg.link_is_external')))\r
+                       n.value = 'http://' + n.value;\r
+       },\r
+\r
+       fillFileList : function(id, l) {\r
+               var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl;\r
+\r
+               l = window[l];\r
+\r
+               if (l && l.length > 0) {\r
+                       lst.options[lst.options.length] = new Option('', '');\r
+\r
+                       tinymce.each(l, function(o) {\r
+                               lst.options[lst.options.length] = new Option(o[0], o[1]);\r
+                       });\r
+               } else\r
+                       dom.remove(dom.getParent(id, 'tr'));\r
+       },\r
+\r
+       fillClassList : function(id) {\r
+               var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl;\r
+\r
+               if (v = tinyMCEPopup.getParam('theme_advanced_styles')) {\r
+                       cl = [];\r
+\r
+                       tinymce.each(v.split(';'), function(v) {\r
+                               var p = v.split('=');\r
+\r
+                               cl.push({'title' : p[0], 'class' : p[1]});\r
+                       });\r
+               } else\r
+                       cl = tinyMCEPopup.editor.dom.getClasses();\r
+\r
+               if (cl.length > 0) {\r
+                       lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('not_set'), '');\r
+\r
+                       tinymce.each(cl, function(o) {\r
+                               lst.options[lst.options.length] = new Option(o.title || o['class'], o['class']);\r
+                       });\r
+               } else\r
+                       dom.remove(dom.getParent(id, 'tr'));\r
+       },\r
+\r
+       fillTargetList : function(id) {\r
+               var dom = tinyMCEPopup.dom, lst = dom.get(id), v;\r
+\r
+               lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('not_set'), '');\r
+               lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('advanced_dlg.link_target_same'), '_self');\r
+               lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('advanced_dlg.link_target_blank'), '_blank');\r
+\r
+               if (v = tinyMCEPopup.getParam('theme_advanced_link_targets')) {\r
+                       tinymce.each(v.split(','), function(v) {\r
+                               v = v.split('=');\r
+                               lst.options[lst.options.length] = new Option(v[0], v[1]);\r
+                       });\r
+               }\r
+       }\r
+};\r
+\r
+LinkDialog.preInit();\r
+tinyMCEPopup.onInit.add(LinkDialog.init, LinkDialog);\r
diff --git a/jscripts/tiny_mce/themes/advanced/js/source_editor.js b/jscripts/tiny_mce/themes/advanced/js/source_editor.js
new file mode 100644 (file)
index 0000000..af2231c
--- /dev/null
@@ -0,0 +1,62 @@
+tinyMCEPopup.requireLangPack();\r
+tinyMCEPopup.onInit.add(onLoadInit);\r
+\r
+function saveContent() {\r
+       tinyMCEPopup.editor.setContent(document.getElementById('htmlSource').value);\r
+       tinyMCEPopup.close();\r
+}\r
+\r
+function onLoadInit() {\r
+       tinyMCEPopup.resizeToInnerSize();\r
+\r
+       // Remove Gecko spellchecking\r
+       if (tinymce.isGecko)\r
+               document.body.spellcheck = tinyMCEPopup.editor.getParam("gecko_spellcheck");\r
+\r
+       document.getElementById('htmlSource').value = tinyMCEPopup.editor.getContent();\r
+\r
+       if (tinyMCEPopup.editor.getParam("theme_advanced_source_editor_wrap", true)) {\r
+               setWrap('soft');\r
+               document.getElementById('wraped').checked = true;\r
+       }\r
+\r
+       resizeInputs();\r
+}\r
+\r
+function setWrap(val) {\r
+       var v, n, s = document.getElementById('htmlSource');\r
+\r
+       s.wrap = val;\r
+\r
+       if (!tinymce.isIE) {\r
+               v = s.value;\r
+               n = s.cloneNode(false);\r
+               n.setAttribute("wrap", val);\r
+               s.parentNode.replaceChild(n, s);\r
+               n.value = v;\r
+       }\r
+}\r
+\r
+function toggleWordWrap(elm) {\r
+       if (elm.checked)\r
+               setWrap('soft');\r
+       else\r
+               setWrap('off');\r
+}\r
+\r
+var wHeight=0, wWidth=0, owHeight=0, owWidth=0;\r
+\r
+function resizeInputs() {\r
+       var el = document.getElementById('htmlSource');\r
+\r
+       if (!tinymce.isIE) {\r
+                wHeight = self.innerHeight - 65;\r
+                wWidth = self.innerWidth - 16;\r
+       } else {\r
+                wHeight = document.body.clientHeight - 70;\r
+                wWidth = document.body.clientWidth - 16;\r
+       }\r
+\r
+       el.style.height = Math.abs(wHeight) + 'px';\r
+       el.style.width  = Math.abs(wWidth) + 'px';\r
+}\r
diff --git a/jscripts/tiny_mce/themes/advanced/langs/en.js b/jscripts/tiny_mce/themes/advanced/langs/en.js
new file mode 100644 (file)
index 0000000..69694b1
--- /dev/null
@@ -0,0 +1,62 @@
+tinyMCE.addI18n('en.advanced',{\r
+style_select:"Styles",\r
+font_size:"Font size",\r
+fontdefault:"Font family",\r
+block:"Format",\r
+paragraph:"Paragraph",\r
+div:"Div",\r
+address:"Address",\r
+pre:"Preformatted",\r
+h1:"Heading 1",\r
+h2:"Heading 2",\r
+h3:"Heading 3",\r
+h4:"Heading 4",\r
+h5:"Heading 5",\r
+h6:"Heading 6",\r
+blockquote:"Blockquote",\r
+code:"Code",\r
+samp:"Code sample",\r
+dt:"Definition term ",\r
+dd:"Definition description",\r
+bold_desc:"Bold (Ctrl+B)",\r
+italic_desc:"Italic (Ctrl+I)",\r
+underline_desc:"Underline (Ctrl+U)",\r
+striketrough_desc:"Strikethrough",\r
+justifyleft_desc:"Align left",\r
+justifycenter_desc:"Align center",\r
+justifyright_desc:"Align right",\r
+justifyfull_desc:"Align full",\r
+bullist_desc:"Unordered list",\r
+numlist_desc:"Ordered list",\r
+outdent_desc:"Outdent",\r
+indent_desc:"Indent",\r
+undo_desc:"Undo (Ctrl+Z)",\r
+redo_desc:"Redo (Ctrl+Y)",\r
+link_desc:"Insert/edit link",\r
+unlink_desc:"Unlink",\r
+image_desc:"Insert/edit image",\r
+cleanup_desc:"Cleanup messy code",\r
+code_desc:"Edit HTML Source",\r
+sub_desc:"Subscript",\r
+sup_desc:"Superscript",\r
+hr_desc:"Insert horizontal ruler",\r
+removeformat_desc:"Remove formatting",\r
+custom1_desc:"Your custom description here",\r
+forecolor_desc:"Select text color",\r
+backcolor_desc:"Select background color",\r
+charmap_desc:"Insert custom character",\r
+visualaid_desc:"Toggle guidelines/invisible elements",\r
+anchor_desc:"Insert/edit anchor",\r
+cut_desc:"Cut",\r
+copy_desc:"Copy",\r
+paste_desc:"Paste",\r
+image_props_desc:"Image properties",\r
+newdocument_desc:"New document",\r
+help_desc:"Help",\r
+blockquote_desc:"Blockquote",\r
+clipboard_msg:"Copy/Cut/Paste is not available in Mozilla and Firefox.\r\nDo you want more information about this issue?",\r
+path:"Path",\r
+newdocument:"Are you sure you want clear all contents?",\r
+toolbar_focus:"Jump to tool buttons - Alt+Q, Jump to editor - Alt-Z, Jump to element path - Alt-X",\r
+more_colors:"More colors"\r
+});
\ No newline at end of file
diff --git a/jscripts/tiny_mce/themes/advanced/langs/en_dlg.js b/jscripts/tiny_mce/themes/advanced/langs/en_dlg.js
new file mode 100644 (file)
index 0000000..9d124d7
--- /dev/null
@@ -0,0 +1,51 @@
+tinyMCE.addI18n('en.advanced_dlg',{\r
+about_title:"About TinyMCE",\r
+about_general:"About",\r
+about_help:"Help",\r
+about_license:"License",\r
+about_plugins:"Plugins",\r
+about_plugin:"Plugin",\r
+about_author:"Author",\r
+about_version:"Version",\r
+about_loaded:"Loaded plugins",\r
+anchor_title:"Insert/edit anchor",\r
+anchor_name:"Anchor name",\r
+code_title:"HTML Source Editor",\r
+code_wordwrap:"Word wrap",\r
+colorpicker_title:"Select a color",\r
+colorpicker_picker_tab:"Picker",\r
+colorpicker_picker_title:"Color picker",\r
+colorpicker_palette_tab:"Palette",\r
+colorpicker_palette_title:"Palette colors",\r
+colorpicker_named_tab:"Named",\r
+colorpicker_named_title:"Named colors",\r
+colorpicker_color:"Color:",\r
+colorpicker_name:"Name:",\r
+charmap_title:"Select custom character",\r
+image_title:"Insert/edit image",\r
+image_src:"Image URL",\r
+image_alt:"Image description",\r
+image_list:"Image list",\r
+image_border:"Border",\r
+image_dimensions:"Dimensions",\r
+image_vspace:"Vertical space",\r
+image_hspace:"Horizontal space",\r
+image_align:"Alignment",\r
+image_align_baseline:"Baseline",\r
+image_align_top:"Top",\r
+image_align_middle:"Middle",\r
+image_align_bottom:"Bottom",\r
+image_align_texttop:"Text top",\r
+image_align_textbottom:"Text bottom",\r
+image_align_left:"Left",\r
+image_align_right:"Right",\r
+link_title:"Insert/edit link",\r
+link_url:"Link URL",\r
+link_target:"Target",\r
+link_target_same:"Open link in the same window",\r
+link_target_blank:"Open link in a new window",\r
+link_titlefield:"Title",\r
+link_is_email:"The URL you entered seems to be an email address, do you want to add the required mailto: prefix?",\r
+link_is_external:"The URL you entered seems to external link, do you want to add the required http:// prefix?",\r
+link_list:"Link list"\r
+});
\ No newline at end of file
diff --git a/jscripts/tiny_mce/themes/advanced/link.htm b/jscripts/tiny_mce/themes/advanced/link.htm
new file mode 100644 (file)
index 0000000..68c1dab
--- /dev/null
@@ -0,0 +1,64 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#advanced_dlg.link_title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/mctabs.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/form_utils.js?v=307"></script>\r
+       <script type="text/javascript" src="../../utils/validate.js?v=307"></script>\r
+       <script type="text/javascript" src="js/link.js?v=307"></script>\r
+       <base target="_self" />\r
+</head>\r
+<body id="link" style="display: none">\r
+<form onsubmit="LinkDialog.update();return false;" action="#">\r
+       <div class="tabs">\r
+               <ul>\r
+                       <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advanced_dlg.link_title}</a></span></li>\r
+               </ul>\r
+       </div>\r
+\r
+       <div class="panel_wrapper">\r
+               <div id="general_panel" class="panel current">\r
+\r
+               <table border="0" cellpadding="4" cellspacing="0">\r
+          <tr>\r
+            <td nowrap="nowrap"><label for="href">{#advanced_dlg.link_url}</label></td>\r
+            <td><table border="0" cellspacing="0" cellpadding="0"> \r
+                                 <tr> \r
+                                       <td><input id="href" name="href" type="text" class="mceFocus" value="" style="width: 200px" onchange="LinkDialog.checkPrefix(this);" /></td> \r
+                                       <td id="hrefbrowsercontainer">&nbsp;</td>\r
+                                 </tr> \r
+                               </table></td>\r
+          </tr>\r
+                 <tr>\r
+                       <td><label for="link_list">{#advanced_dlg.link_list}</label></td>\r
+                       <td><select id="link_list" name="link_list" onchange="document.getElementById('href').value=this.options[this.selectedIndex].value;"></select></td>\r
+                 </tr>\r
+               <tr>\r
+                       <td><label id="targetlistlabel" for="targetlist">{#advanced_dlg.link_target}</label></td>\r
+                       <td><select id="target_list" name="target_list"></select></td>\r
+               </tr>\r
+          <tr>\r
+            <td nowrap="nowrap"><label for="linktitle">{#advanced_dlg.link_titlefield}</label></td>\r
+            <td><input id="linktitle" name="linktitle" type="text" value="" style="width: 200px" /></td>\r
+          </tr>\r
+                       <tr>\r
+                               <td><label for="class_list">{#class_name}</label></td>\r
+                               <td><select id="class_list" name="class_list"></select></td>\r
+                       </tr>\r
+        </table>\r
+               </div>\r
+       </div>\r
+\r
+       <div class="mceActionPanel">\r
+               <div style="float: left">\r
+                       <input type="submit" id="insert" name="insert" value="{#insert}" />\r
+               </div>\r
+\r
+               <div style="float: right">\r
+                       <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />\r
+               </div>\r
+       </div>\r
+</form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/themes/advanced/skins/default/content.css b/jscripts/tiny_mce/themes/advanced/skins/default/content.css
new file mode 100644 (file)
index 0000000..e3adc44
--- /dev/null
@@ -0,0 +1,27 @@
+body, td, pre {color:#000; font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px; margin:8px;}\r
+body {background:#FFF;}\r
+body.mceForceColors {background:#FFF; color:#000;}\r
+h1 {font-size: 2em}\r
+h2 {font-size: 1.5em}\r
+h3 {font-size: 1.17em}\r
+h4 {font-size: 1em}\r
+h5 {font-size: .83em}\r
+h6 {font-size: .75em}\r
+.mceItemTable, .mceItemTable td, .mceItemTable th, .mceItemTable caption, .mceItemVisualAid {border: 1px dashed #BBB;}\r
+a.mceItemAnchor {width:12px; line-height:6px; overflow:hidden; padding-left:12px; background:url(img/items.gif) no-repeat bottom left;}\r
+img.mceItemAnchor {width:12px; height:12px; background:url(img/items.gif) no-repeat;}\r
+img {border:0;}\r
+table {cursor:default}\r
+table td, table th {cursor:text}\r
+\r
+/* IE */\r
+* html body {\r
+scrollbar-3dlight-color:#F0F0EE;\r
+scrollbar-arrow-color:#676662;\r
+scrollbar-base-color:#F0F0EE;\r
+scrollbar-darkshadow-color:#DDD;\r
+scrollbar-face-color:#E0E0DD;\r
+scrollbar-highlight-color:#F0F0EE;\r
+scrollbar-shadow-color:#F0F0EE;\r
+scrollbar-track-color:#F5F5F5;\r
+}\r
diff --git a/jscripts/tiny_mce/themes/advanced/skins/default/dialog.css b/jscripts/tiny_mce/themes/advanced/skins/default/dialog.css
new file mode 100644 (file)
index 0000000..c944a60
--- /dev/null
@@ -0,0 +1,114 @@
+/* Generic */\r
+body {\r
+font-family:Verdana, Arial, Helvetica, sans-serif; font-size:11px;\r
+scrollbar-3dlight-color:#F0F0EE;\r
+scrollbar-arrow-color:#676662;\r
+scrollbar-base-color:#F0F0EE;\r
+scrollbar-darkshadow-color:#DDDDDD;\r
+scrollbar-face-color:#E0E0DD;\r
+scrollbar-highlight-color:#F0F0EE;\r
+scrollbar-shadow-color:#F0F0EE;\r
+scrollbar-track-color:#F5F5F5;\r
+background:#F0F0EE;\r
+padding:0;\r
+margin:8px 8px 0 8px;\r
+}\r
+\r
+html {background:#F0F0EE;}\r
+td {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;}\r
+textarea {resize:none;outline:none;}\r
+a:link, a:visited {color:black;}\r
+a:hover {color:#2B6FB6;}\r
+\r
+/* Forms */\r
+fieldset {margin:0; padding:4px; border:1px solid #919B9C; font-family:Verdana, Arial; font-size:10px;}\r
+legend {color:#2B6FB6; font-weight:bold;}\r
+label.msg {display:none;}\r
+label.invalid {color:#EE0000; display:inline;}\r
+input.invalid {border:1px solid #EE0000;}\r
+input {background:#FFF; border:1px solid #CCC;}\r
+input, select, textarea {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;}\r
+input, select, textarea {border:1px solid #808080;}\r
+input.radio {border:1px none #000000; background:transparent; vertical-align:middle;}\r
+input.checkbox {border:1px none #000000; background:transparent; vertical-align:middle;}\r
+.input_noborder {border:0;}\r
+\r
+/* Buttons */\r
+#insert, #cancel, input.button, .updateButton {\r
+border:0; margin:0; padding:0;\r
+font-weight:bold;\r
+width:94px; height:26px;\r
+background:url(img/buttons.png) 0 -26px;\r
+cursor:pointer;\r
+padding-bottom:2px;\r
+}\r
+\r
+#insert {background:url(img/buttons.png) 0 -52px;}\r
+#cancel {background:url(img/buttons.png) 0 0;}\r
+\r
+/* Browse */\r
+a.browse span {display:block; width:20px; height:18px; background:url(../../img/icons.gif) -860px 0; border:1px solid #FFF; margin-left:1px;}\r
+.mceOldBoxModel a.browse span {width:22px; height:20px;}\r
+a.browse:hover span {border:1px solid #0A246A; background-color:#B2BBD0;}\r
+a.browse span.disabled {border:1px solid white; -moz-opacity:0.3; opacity:0.3; filter:progid:DXImageTransform.Microsoft.Alpha(opacity=30);}\r
+a.browse:hover span.disabled {border:1px solid white; background-color:transparent;}\r
+a.pickcolor span {display:block; width:20px; height:16px; background:url(../../img/icons.gif) -840px 0; margin-left:2px;}\r
+.mceOldBoxModel a.pickcolor span {width:21px; height:17px;}\r
+a.pickcolor:hover span {background-color:#B2BBD0;}\r
+a.pickcolor:hover span.disabled {}\r
+\r
+/* Charmap */\r
+table.charmap {border:1px solid #AAA; text-align:center}\r
+td.charmap, #charmap a {width:18px; height:18px; color:#000; border:1px solid #AAA; text-align:center; font-size:12px; vertical-align:middle; line-height: 18px;}\r
+#charmap a {display:block; color:#000; text-decoration:none; border:0}\r
+#charmap a:hover {background:#CCC;color:#2B6FB6}\r
+#charmap #codeN {font-size:10px; font-family:Arial,Helvetica,sans-serif; text-align:center}\r
+#charmap #codeV {font-size:40px; height:80px; border:1px solid #AAA; text-align:center}\r
+\r
+/* Source */\r
+.wordWrapCode {vertical-align:middle; border:1px none #000000; background:transparent;}\r
+.mceActionPanel {margin-top:5px;}\r
+\r
+/* Tabs classes */\r
+.tabs {width:100%; height:18px; line-height:normal; background:url(img/tabs.gif) repeat-x 0 -72px;}\r
+.tabs ul {margin:0; padding:0; list-style:none;}\r
+.tabs li {float:left; background:url(img/tabs.gif) no-repeat 0 0; margin:0 2px 0 0; padding:0 0 0 10px; line-height:17px; height:18px; display:block;}\r
+.tabs li.current {background:url(img/tabs.gif) no-repeat 0 -18px; margin-right:2px;}\r
+.tabs span {float:left; display:block; background:url(img/tabs.gif) no-repeat right -36px; padding:0px 10px 0 0;}\r
+.tabs .current span {background:url(img/tabs.gif) no-repeat right -54px;}\r
+.tabs a {text-decoration:none; font-family:Verdana, Arial; font-size:10px;}\r
+.tabs a:link, .tabs a:visited, .tabs a:hover {color:black;}\r
+\r
+/* Panels */\r
+.panel_wrapper div.panel {display:none;}\r
+.panel_wrapper div.current {display:block; width:100%; height:300px; overflow:visible;}\r
+.panel_wrapper {border:1px solid #919B9C; border-top:0px; padding:10px; padding-top:5px; clear:both; background:white;}\r
+\r
+/* Columns */\r
+.column {float:left;}\r
+.properties {width:100%;}\r
+.properties .column1 {}\r
+.properties .column2 {text-align:left;}\r
+\r
+/* Titles */\r
+h1, h2, h3, h4 {color:#2B6FB6; margin:0; padding:0; padding-top:5px;}\r
+h3 {font-size:14px;}\r
+.title {font-size:12px; font-weight:bold; color:#2B6FB6;}\r
+\r
+/* Dialog specific */\r
+#link .panel_wrapper, #link div.current {height:125px;}\r
+#image .panel_wrapper, #image div.current {height:200px;}\r
+#plugintable thead {font-weight:bold; background:#DDD;}\r
+#plugintable, #about #plugintable td {border:1px solid #919B9C;}\r
+#plugintable {width:96%; margin-top:10px;}\r
+#pluginscontainer {height:290px; overflow:auto;}\r
+#colorpicker #preview {float:right; width:50px; height:14px;line-height:1px; border:1px solid black; margin-left:5px;}\r
+#colorpicker #colors {float:left; border:1px solid gray; cursor:crosshair;}\r
+#colorpicker #light {border:1px solid gray; margin-left:5px; float:left;width:15px; height:150px; cursor:crosshair;}\r
+#colorpicker #light div {overflow:hidden;}\r
+#colorpicker #previewblock {float:right; padding-left:10px; height:20px;}\r
+#colorpicker .panel_wrapper div.current {height:175px;}\r
+#colorpicker #namedcolors {width:150px;}\r
+#colorpicker #namedcolors a {display:block; float:left; width:10px; height:10px; margin:1px 1px 0 0; overflow:hidden;}\r
+#colorpicker #colornamecontainer {margin-top:5px;}\r
+#colorpicker #picker_panel fieldset {margin:auto;width:325px;}
\ No newline at end of file
diff --git a/jscripts/tiny_mce/themes/advanced/skins/default/img/buttons.png b/jscripts/tiny_mce/themes/advanced/skins/default/img/buttons.png
new file mode 100644 (file)
index 0000000..7dd5841
Binary files /dev/null and b/jscripts/tiny_mce/themes/advanced/skins/default/img/buttons.png differ
diff --git a/jscripts/tiny_mce/themes/advanced/skins/default/img/items.gif b/jscripts/tiny_mce/themes/advanced/skins/default/img/items.gif
new file mode 100644 (file)
index 0000000..2eafd79
Binary files /dev/null and b/jscripts/tiny_mce/themes/advanced/skins/default/img/items.gif differ
diff --git a/jscripts/tiny_mce/themes/advanced/skins/default/img/menu_arrow.gif b/jscripts/tiny_mce/themes/advanced/skins/default/img/menu_arrow.gif
new file mode 100644 (file)
index 0000000..85e31df
Binary files /dev/null and b/jscripts/tiny_mce/themes/advanced/skins/default/img/menu_arrow.gif differ
diff --git a/jscripts/tiny_mce/themes/advanced/skins/default/img/menu_check.gif b/jscripts/tiny_mce/themes/advanced/skins/default/img/menu_check.gif
new file mode 100644 (file)
index 0000000..adfdddc
Binary files /dev/null and b/jscripts/tiny_mce/themes/advanced/skins/default/img/menu_check.gif differ
diff --git a/jscripts/tiny_mce/themes/advanced/skins/default/img/progress.gif b/jscripts/tiny_mce/themes/advanced/skins/default/img/progress.gif
new file mode 100644 (file)
index 0000000..5bb90fd
Binary files /dev/null and b/jscripts/tiny_mce/themes/advanced/skins/default/img/progress.gif differ
diff --git a/jscripts/tiny_mce/themes/advanced/skins/default/img/tabs.gif b/jscripts/tiny_mce/themes/advanced/skins/default/img/tabs.gif
new file mode 100644 (file)
index 0000000..ce4be63
Binary files /dev/null and b/jscripts/tiny_mce/themes/advanced/skins/default/img/tabs.gif differ
diff --git a/jscripts/tiny_mce/themes/advanced/skins/default/ui.css b/jscripts/tiny_mce/themes/advanced/skins/default/ui.css
new file mode 100644 (file)
index 0000000..7e202a7
--- /dev/null
@@ -0,0 +1,215 @@
+/* Reset */\r
+.defaultSkin table, .defaultSkin tbody, .defaultSkin a, .defaultSkin img, .defaultSkin tr, .defaultSkin div, .defaultSkin td, .defaultSkin iframe, .defaultSkin span, .defaultSkin *, .defaultSkin .mceText {border:0; margin:0; padding:0; background:transparent; white-space:nowrap; text-decoration:none; font-weight:normal; cursor:default; color:#000; vertical-align:baseline; width:auto; border-collapse:separate; text-align:left}\r
+.defaultSkin a:hover, .defaultSkin a:link, .defaultSkin a:visited, .defaultSkin a:active {text-decoration:none; font-weight:normal; cursor:default; color:#000}\r
+.defaultSkin table td {vertical-align:middle}\r
+\r
+/* Containers */\r
+.defaultSkin table {background:#F0F0EE}\r
+.defaultSkin iframe {display:block; background:#FFF}\r
+.defaultSkin .mceToolbar {height:26px}\r
+.defaultSkin .mceLeft {text-align:left}\r
+.defaultSkin .mceRight {text-align:right}\r
+\r
+/* External */\r
+.defaultSkin .mceExternalToolbar {position:absolute; border:1px solid #CCC; border-bottom:0; display:none;}\r
+.defaultSkin .mceExternalToolbar td.mceToolbar {padding-right:13px;}\r
+.defaultSkin .mceExternalClose {position:absolute; top:3px; right:3px; width:7px; height:7px; background:url(../../img/icons.gif) -820px 0}\r
+\r
+/* Layout */\r
+.defaultSkin table.mceLayout {border:0; border-left:1px solid #CCC; border-right:1px solid #CCC}\r
+.defaultSkin table.mceLayout tr.mceFirst td {border-top:1px solid #CCC}\r
+.defaultSkin table.mceLayout tr.mceLast td {border-bottom:1px solid #CCC}\r
+.defaultSkin table.mceToolbar, .defaultSkin tr.mceFirst .mceToolbar tr td, .defaultSkin tr.mceLast .mceToolbar tr td {border:0; margin:0; padding:0;}\r
+.defaultSkin td.mceToolbar {padding-top:1px; vertical-align:top}\r
+.defaultSkin .mceIframeContainer {border-top:1px solid #CCC; border-bottom:1px solid #CCC}\r
+.defaultSkin .mceStatusbar {font-family:'MS Sans Serif',sans-serif,Verdana,Arial; font-size:9pt; line-height:16px; overflow:visible; color:#000; display:block; height:20px}\r
+.defaultSkin .mceStatusbar div {float:left; margin:2px}\r
+.defaultSkin .mceStatusbar a.mceResize {display:block; float:right; background:url(../../img/icons.gif) -800px 0; width:20px; height:20px; cursor:se-resize}\r
+.defaultSkin .mceStatusbar a:hover {text-decoration:underline}\r
+.defaultSkin table.mceToolbar {margin-left:3px}\r
+.defaultSkin span.mceIcon, .defaultSkin img.mceIcon {display:block; width:20px; height:20px}\r
+.defaultSkin .mceIcon {background:url(../../img/icons.gif) no-repeat 20px 20px}\r
+.defaultSkin td.mceCenter {text-align:center;}\r
+.defaultSkin td.mceCenter table {margin:0 auto; text-align:left;}\r
+.defaultSkin td.mceRight table {margin:0 0 0 auto;}\r
+\r
+/* Button */\r
+.defaultSkin .mceButton {display:block; border:1px solid #F0F0EE; width:20px; height:20px; margin-right:1px}\r
+.defaultSkin a.mceButtonEnabled:hover {border:1px solid #0A246A; background-color:#B2BBD0}\r
+.defaultSkin a.mceButtonActive, .defaultSkin a.mceButtonSelected {border:1px solid #0A246A; background-color:#C2CBE0}\r
+.defaultSkin .mceButtonDisabled .mceIcon {opacity:0.3; filter:alpha(opacity=30)}\r
+.defaultSkin .mceButtonLabeled {width:auto}\r
+.defaultSkin .mceButtonLabeled span.mceIcon {float:left}\r
+.defaultSkin span.mceButtonLabel {display:block; font-size:10px; padding:4px 6px 0 22px; font-family:Tahoma,Verdana,Arial,Helvetica}\r
+.defaultSkin .mceButtonDisabled .mceButtonLabel {color:#888}\r
+\r
+/* Separator */\r
+.defaultSkin .mceSeparator {display:block; background:url(../../img/icons.gif) -180px 0; width:2px; height:20px; margin:2px 2px 0 4px}\r
+\r
+/* ListBox */\r
+.defaultSkin .mceListBox {direction:ltr}\r
+.defaultSkin .mceListBox, .defaultSkin .mceListBox a {display:block}\r
+.defaultSkin .mceListBox .mceText {padding-left:4px; width:70px; text-align:left; border:1px solid #CCC; border-right:0; background:#FFF; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; height:20px; line-height:20px; overflow:hidden}\r
+.defaultSkin .mceListBox .mceOpen {width:9px; height:20px; background:url(../../img/icons.gif) -741px 0; margin-right:2px; border:1px solid #CCC;}\r
+.defaultSkin table.mceListBoxEnabled:hover .mceText, .defaultSkin .mceListBoxHover .mceText, .defaultSkin .mceListBoxSelected .mceText {border:1px solid #A2ABC0; border-right:0; background:#FFF}\r
+.defaultSkin table.mceListBoxEnabled:hover .mceOpen, .defaultSkin .mceListBoxHover .mceOpen, .defaultSkin .mceListBoxSelected .mceOpen {background-color:#FFF; border:1px solid #A2ABC0}\r
+.defaultSkin .mceListBoxDisabled a.mceText {color:gray; background-color:transparent;}\r
+.defaultSkin .mceListBoxMenu {overflow:auto; overflow-x:hidden}\r
+.defaultSkin .mceOldBoxModel .mceListBox .mceText {height:22px}\r
+.defaultSkin .mceOldBoxModel .mceListBox .mceOpen {width:11px; height:22px;}\r
+.defaultSkin select.mceNativeListBox {font-family:'MS Sans Serif',sans-serif,Verdana,Arial; font-size:7pt; background:#F0F0EE; border:1px solid gray; margin-right:2px;}\r
+\r
+/* SplitButton */\r
+.defaultSkin .mceSplitButton {width:32px; height:20px; direction:ltr}\r
+.defaultSkin .mceSplitButton a, .defaultSkin .mceSplitButton span {height:20px; display:block}\r
+.defaultSkin .mceSplitButton a.mceAction {width:20px; border:1px solid #F0F0EE; border-right:0;}\r
+.defaultSkin .mceSplitButton span.mceAction {width:20px; background:url(../../img/icons.gif) 20px 20px;}\r
+.defaultSkin .mceSplitButton a.mceOpen {width:9px; border:1px solid #F0F0EE;}\r
+.defaultSkin .mceSplitButton span.mceOpen {width:9px; background:url(../../img/icons.gif) -741px 0;}\r
+.defaultSkin table.mceSplitButtonEnabled:hover a.mceAction, .defaultSkin .mceSplitButtonHover a.mceAction, .defaultSkin .mceSplitButtonSelected a.mceAction {border:1px solid #0A246A; border-right:0; background-color:#B2BBD0}\r
+.defaultSkin table.mceSplitButtonEnabled:hover a.mceOpen, .defaultSkin .mceSplitButtonHover a.mceOpen, .defaultSkin .mceSplitButtonSelected a.mceOpen {border:1px solid #0A246A;}\r
+.defaultSkin table.mceSplitButtonEnabled:hover span.mceOpen, .defaultSkin .mceSplitButtonHover span.mceOpen, .defaultSkin .mceSplitButtonSelected span.mceOpen {background-color:#B2BBD0}\r
+.defaultSkin .mceSplitButtonDisabled .mceAction, .defaultSkin .mceSplitButtonDisabled span.mceOpen {opacity:0.3; filter:alpha(opacity=30)}\r
+.defaultSkin .mceSplitButtonActive a.mceAction {border:1px solid #0A246A; background-color:#C2CBE0}\r
+.defaultSkin .mceSplitButtonActive a.mceOpen {border-left:0;}\r
+\r
+/* ColorSplitButton */\r
+.defaultSkin div.mceColorSplitMenu table {background:#FFF; border:1px solid gray}\r
+.defaultSkin .mceColorSplitMenu td {padding:2px}\r
+.defaultSkin .mceColorSplitMenu a {display:block; width:9px; height:9px; overflow:hidden; border:1px solid #808080}\r
+.defaultSkin .mceColorSplitMenu td.mceMoreColors {padding:1px 3px 1px 1px}\r
+.defaultSkin .mceColorSplitMenu a.mceMoreColors {width:100%; height:auto; text-align:center; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; line-height:20px; border:1px solid #FFF}\r
+.defaultSkin .mceColorSplitMenu a.mceMoreColors:hover {border:1px solid #0A246A; background-color:#B6BDD2}\r
+.defaultSkin a.mceMoreColors:hover {border:1px solid #0A246A}\r
+.defaultSkin .mceColorPreview {margin-left:2px; width:16px; height:4px; overflow:hidden; background:#9a9b9a}\r
+.defaultSkin .mce_forecolor span.mceAction, .defaultSkin .mce_backcolor span.mceAction {overflow:hidden; height:16px}\r
+\r
+/* Menu */\r
+.defaultSkin .mceMenu {position:absolute; left:0; top:0; z-index:1000; border:1px solid #D4D0C8}\r
+.defaultSkin .mceNoIcons span.mceIcon {width:0;}\r
+.defaultSkin .mceNoIcons a .mceText {padding-left:10px}\r
+.defaultSkin .mceMenu table {background:#FFF}\r
+.defaultSkin .mceMenu a, .defaultSkin .mceMenu span, .defaultSkin .mceMenu {display:block}\r
+.defaultSkin .mceMenu td {height:20px}\r
+.defaultSkin .mceMenu a {position:relative;padding:3px 0 4px 0}\r
+.defaultSkin .mceMenu .mceText {position:relative; display:block; font-family:Tahoma,Verdana,Arial,Helvetica; color:#000; cursor:default; margin:0; padding:0 25px 0 25px; display:block}\r
+.defaultSkin .mceMenu span.mceText, .defaultSkin .mceMenu .mcePreview {font-size:11px}\r
+.defaultSkin .mceMenu pre.mceText {font-family:Monospace}\r
+.defaultSkin .mceMenu .mceIcon {position:absolute; top:0; left:0; width:22px;}\r
+.defaultSkin .mceMenu .mceMenuItemEnabled a:hover, .defaultSkin .mceMenu .mceMenuItemActive {background-color:#dbecf3}\r
+.defaultSkin td.mceMenuItemSeparator {background:#DDD; height:1px}\r
+.defaultSkin .mceMenuItemTitle a {border:0; background:#EEE; border-bottom:1px solid #DDD}\r
+.defaultSkin .mceMenuItemTitle span.mceText {color:#000; font-weight:bold; padding-left:4px}\r
+.defaultSkin .mceMenuItemDisabled .mceText {color:#888}\r
+.defaultSkin .mceMenuItemSelected .mceIcon {background:url(img/menu_check.gif)}\r
+.defaultSkin .mceNoIcons .mceMenuItemSelected a {background:url(img/menu_arrow.gif) no-repeat -6px center}\r
+.defaultSkin .mceMenu span.mceMenuLine {display:none}\r
+.defaultSkin .mceMenuItemSub a {background:url(img/menu_arrow.gif) no-repeat top right;}\r
+\r
+/* Progress,Resize */\r
+.defaultSkin .mceBlocker {position:absolute; left:0; top:0; z-index:1000; opacity:0.5; filter:alpha(opacity=50); background:#FFF}\r
+.defaultSkin .mceProgress {position:absolute; left:0; top:0; z-index:1001; background:url(img/progress.gif) no-repeat; width:32px; height:32px; margin:-16px 0 0 -16px}\r
+.defaultSkin .mcePlaceHolder {border:1px dotted gray}\r
+\r
+/* Formats */\r
+.defaultSkin .mce_formatPreview a {font-size:10px}\r
+.defaultSkin .mce_p span.mceText {}\r
+.defaultSkin .mce_address span.mceText {font-style:italic}\r
+.defaultSkin .mce_pre span.mceText {font-family:monospace}\r
+.defaultSkin .mce_h1 span.mceText {font-weight:bolder; font-size: 2em}\r
+.defaultSkin .mce_h2 span.mceText {font-weight:bolder; font-size: 1.5em}\r
+.defaultSkin .mce_h3 span.mceText {font-weight:bolder; font-size: 1.17em}\r
+.defaultSkin .mce_h4 span.mceText {font-weight:bolder; font-size: 1em}\r
+.defaultSkin .mce_h5 span.mceText {font-weight:bolder; font-size: .83em}\r
+.defaultSkin .mce_h6 span.mceText {font-weight:bolder; font-size: .75em}\r
+\r
+/* Theme */\r
+.defaultSkin span.mce_bold {background-position:0 0}\r
+.defaultSkin span.mce_italic {background-position:-60px 0}\r
+.defaultSkin span.mce_underline {background-position:-140px 0}\r
+.defaultSkin span.mce_strikethrough {background-position:-120px 0}\r
+.defaultSkin span.mce_undo {background-position:-160px 0}\r
+.defaultSkin span.mce_redo {background-position:-100px 0}\r
+.defaultSkin span.mce_cleanup {background-position:-40px 0}\r
+.defaultSkin span.mce_bullist {background-position:-20px 0}\r
+.defaultSkin span.mce_numlist {background-position:-80px 0}\r
+.defaultSkin span.mce_justifyleft {background-position:-460px 0}\r
+.defaultSkin span.mce_justifyright {background-position:-480px 0}\r
+.defaultSkin span.mce_justifycenter {background-position:-420px 0}\r
+.defaultSkin span.mce_justifyfull {background-position:-440px 0}\r
+.defaultSkin span.mce_anchor {background-position:-200px 0}\r
+.defaultSkin span.mce_indent {background-position:-400px 0}\r
+.defaultSkin span.mce_outdent {background-position:-540px 0}\r
+.defaultSkin span.mce_link {background-position:-500px 0}\r
+.defaultSkin span.mce_unlink {background-position:-640px 0}\r
+.defaultSkin span.mce_sub {background-position:-600px 0}\r
+.defaultSkin span.mce_sup {background-position:-620px 0}\r
+.defaultSkin span.mce_removeformat {background-position:-580px 0}\r
+.defaultSkin span.mce_newdocument {background-position:-520px 0}\r
+.defaultSkin span.mce_image {background-position:-380px 0}\r
+.defaultSkin span.mce_help {background-position:-340px 0}\r
+.defaultSkin span.mce_code {background-position:-260px 0}\r
+.defaultSkin span.mce_hr {background-position:-360px 0}\r
+.defaultSkin span.mce_visualaid {background-position:-660px 0}\r
+.defaultSkin span.mce_charmap {background-position:-240px 0}\r
+.defaultSkin span.mce_paste {background-position:-560px 0}\r
+.defaultSkin span.mce_copy {background-position:-700px 0}\r
+.defaultSkin span.mce_cut {background-position:-680px 0}\r
+.defaultSkin span.mce_blockquote {background-position:-220px 0}\r
+.defaultSkin .mce_forecolor span.mceAction {background-position:-720px 0}\r
+.defaultSkin .mce_backcolor span.mceAction {background-position:-760px 0}\r
+.defaultSkin span.mce_forecolorpicker {background-position:-720px 0}\r
+.defaultSkin span.mce_backcolorpicker {background-position:-760px 0}\r
+\r
+/* Plugins */\r
+.defaultSkin span.mce_advhr {background-position:-0px -20px}\r
+.defaultSkin span.mce_ltr {background-position:-20px -20px}\r
+.defaultSkin span.mce_rtl {background-position:-40px -20px}\r
+.defaultSkin span.mce_emotions {background-position:-60px -20px}\r
+.defaultSkin span.mce_fullpage {background-position:-80px -20px}\r
+.defaultSkin span.mce_fullscreen {background-position:-100px -20px}\r
+.defaultSkin span.mce_iespell {background-position:-120px -20px}\r
+.defaultSkin span.mce_insertdate {background-position:-140px -20px}\r
+.defaultSkin span.mce_inserttime {background-position:-160px -20px}\r
+.defaultSkin span.mce_absolute {background-position:-180px -20px}\r
+.defaultSkin span.mce_backward {background-position:-200px -20px}\r
+.defaultSkin span.mce_forward {background-position:-220px -20px}\r
+.defaultSkin span.mce_insert_layer {background-position:-240px -20px}\r
+.defaultSkin span.mce_insertlayer {background-position:-260px -20px}\r
+.defaultSkin span.mce_movebackward {background-position:-280px -20px}\r
+.defaultSkin span.mce_moveforward {background-position:-300px -20px}\r
+.defaultSkin span.mce_media {background-position:-320px -20px}\r
+.defaultSkin span.mce_nonbreaking {background-position:-340px -20px}\r
+.defaultSkin span.mce_pastetext {background-position:-360px -20px}\r
+.defaultSkin span.mce_pasteword {background-position:-380px -20px}\r
+.defaultSkin span.mce_selectall {background-position:-400px -20px}\r
+.defaultSkin span.mce_preview {background-position:-420px -20px}\r
+.defaultSkin span.mce_print {background-position:-440px -20px}\r
+.defaultSkin span.mce_cancel {background-position:-460px -20px}\r
+.defaultSkin span.mce_save {background-position:-480px -20px}\r
+.defaultSkin span.mce_replace {background-position:-500px -20px}\r
+.defaultSkin span.mce_search {background-position:-520px -20px}\r
+.defaultSkin span.mce_styleprops {background-position:-560px -20px}\r
+.defaultSkin span.mce_table {background-position:-580px -20px}\r
+.defaultSkin span.mce_cell_props {background-position:-600px -20px}\r
+.defaultSkin span.mce_delete_table {background-position:-620px -20px}\r
+.defaultSkin span.mce_delete_col {background-position:-640px -20px}\r
+.defaultSkin span.mce_delete_row {background-position:-660px -20px}\r
+.defaultSkin span.mce_col_after {background-position:-680px -20px}\r
+.defaultSkin span.mce_col_before {background-position:-700px -20px}\r
+.defaultSkin span.mce_row_after {background-position:-720px -20px}\r
+.defaultSkin span.mce_row_before {background-position:-740px -20px}\r
+.defaultSkin span.mce_merge_cells {background-position:-760px -20px}\r
+.defaultSkin span.mce_table_props {background-position:-980px -20px}\r
+.defaultSkin span.mce_row_props {background-position:-780px -20px}\r
+.defaultSkin span.mce_split_cells {background-position:-800px -20px}\r
+.defaultSkin span.mce_template {background-position:-820px -20px}\r
+.defaultSkin span.mce_visualchars {background-position:-840px -20px}\r
+.defaultSkin span.mce_abbr {background-position:-860px -20px}\r
+.defaultSkin span.mce_acronym {background-position:-880px -20px}\r
+.defaultSkin span.mce_attribs {background-position:-900px -20px}\r
+.defaultSkin span.mce_cite {background-position:-920px -20px}\r
+.defaultSkin span.mce_del {background-position:-940px -20px}\r
+.defaultSkin span.mce_ins {background-position:-960px -20px}\r
+.defaultSkin span.mce_pagebreak {background-position:0 -40px}\r
+.defaultSkin .mce_spellchecker span.mceAction {background-position:-540px -20px}\r
diff --git a/jscripts/tiny_mce/themes/advanced/skins/o2k7/content.css b/jscripts/tiny_mce/themes/advanced/skins/o2k7/content.css
new file mode 100644 (file)
index 0000000..d08cd8b
--- /dev/null
@@ -0,0 +1,27 @@
+body, td, pre {color:#000; font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px; margin:8px;}\r
+body {background:#FFF;}\r
+body.mceForceColors {background:#FFF; color:#000;}\r
+h1 {font-size: 2em}\r
+h2 {font-size: 1.5em}\r
+h3 {font-size: 1.17em}\r
+h4 {font-size: 1em}\r
+h5 {font-size: .83em}\r
+h6 {font-size: .75em}\r
+.mceItemTable, .mceItemTable td, .mceItemTable th, .mceItemTable caption, .mceItemVisualAid {border: 1px dashed #BBB;}\r
+a.mceItemAnchor {width:12px; line-height:6px; overflow:hidden; padding-left:12px; background:url(../default/img/items.gif) no-repeat bottom left;}\r
+img.mceItemAnchor {width:12px; height:12px; background:url(../default/img/items.gif) no-repeat;}\r
+img {border:0;}\r
+table {cursor:default}\r
+table td, table th {cursor:text}\r
+\r
+/* IE */\r
+* html body {\r
+scrollbar-3dlight-color:#F0F0EE;\r
+scrollbar-arrow-color:#676662;\r
+scrollbar-base-color:#F0F0EE;\r
+scrollbar-darkshadow-color:#DDD;\r
+scrollbar-face-color:#E0E0DD;\r
+scrollbar-highlight-color:#F0F0EE;\r
+scrollbar-shadow-color:#F0F0EE;\r
+scrollbar-track-color:#F5F5F5;\r
+}\r
diff --git a/jscripts/tiny_mce/themes/advanced/skins/o2k7/dialog.css b/jscripts/tiny_mce/themes/advanced/skins/o2k7/dialog.css
new file mode 100644 (file)
index 0000000..e36042e
--- /dev/null
@@ -0,0 +1,113 @@
+/* Generic */\r
+body {\r
+font-family:Verdana, Arial, Helvetica, sans-serif; font-size:11px;\r
+scrollbar-3dlight-color:#F0F0EE;\r
+scrollbar-arrow-color:#676662;\r
+scrollbar-base-color:#F0F0EE;\r
+scrollbar-darkshadow-color:#DDDDDD;\r
+scrollbar-face-color:#E0E0DD;\r
+scrollbar-highlight-color:#F0F0EE;\r
+scrollbar-shadow-color:#F0F0EE;\r
+scrollbar-track-color:#F5F5F5;\r
+background:#F0F0EE;\r
+padding:0;\r
+margin:8px 8px 0 8px;\r
+}\r
+\r
+html {background:#F0F0EE;}\r
+td {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;}\r
+textarea {resize:none;outline:none;}\r
+a:link, a:visited {color:black;}\r
+a:hover {color:#2B6FB6;}\r
+\r
+/* Forms */\r
+fieldset {margin:0; padding:4px; border:1px solid #919B9C; font-family:Verdana, Arial; font-size:10px;}\r
+legend {color:#2B6FB6; font-weight:bold;}\r
+label.msg {display:none;}\r
+label.invalid {color:#EE0000; display:inline;}\r
+input.invalid {border:1px solid #EE0000;}\r
+input {background:#FFF; border:1px solid #CCC;}\r
+input, select, textarea {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;}\r
+input, select, textarea {border:1px solid #808080;}\r
+input.radio {border:1px none #000000; background:transparent; vertical-align:middle;}\r
+input.checkbox {border:1px none #000000; background:transparent; vertical-align:middle;}\r
+.input_noborder {border:0;}\r
+\r
+/* Buttons */\r
+#insert, #cancel, input.button, .updateButton {\r
+border:0; margin:0; padding:0;\r
+font-weight:bold;\r
+width:94px; height:26px;\r
+background:url(../default/img/buttons.png) 0 -26px;\r
+cursor:pointer;\r
+padding-bottom:2px;\r
+}\r
+\r
+#insert {background:url(../default/img/buttons.png) 0 -52px;}\r
+#cancel {background:url(../default/img/buttons.png) 0 0;}\r
+\r
+/* Browse */\r
+a.browse span {display:block; width:20px; height:18px; background:url(../../img/icons.gif) -860px 0; border:1px solid #FFF; margin-left:1px;}\r
+.mceOldBoxModel a.browse span {width:22px; height:20px;}\r
+a.browse:hover span {border:1px solid #0A246A; background-color:#B2BBD0;}\r
+a.browse span.disabled {border:1px solid white; -moz-opacity:0.3; opacity:0.3; filter:progid:DXImageTransform.Microsoft.Alpha(opacity=30);}\r
+a.browse:hover span.disabled {border:1px solid white; background-color:transparent;}\r
+a.pickcolor span {display:block; width:20px; height:16px; background:url(../../img/icons.gif) -840px 0; margin-left:2px;}\r
+.mceOldBoxModel a.pickcolor span {width:21px; height:17px;}\r
+a.pickcolor:hover span {background-color:#B2BBD0;}\r
+a.pickcolor:hover span.disabled {}\r
+\r
+/* Charmap */\r
+table.charmap {border:1px solid #AAA; text-align:center}\r
+td.charmap, #charmap a {width:18px; height:18px; color:#000; border:1px solid #AAA; text-align:center; font-size:12px; vertical-align:middle; line-height: 18px;}\r
+#charmap a {display:block; color:#000; text-decoration:none; border:0}\r
+#charmap a:hover {background:#CCC;color:#2B6FB6}\r
+#charmap #codeN {font-size:10px; font-family:Arial,Helvetica,sans-serif; text-align:center}\r
+#charmap #codeV {font-size:40px; height:80px; border:1px solid #AAA; text-align:center}\r
+\r
+/* Source */\r
+.wordWrapCode {vertical-align:middle; border:1px none #000000; background:transparent;}\r
+.mceActionPanel {margin-top:5px;}\r
+\r
+/* Tabs classes */\r
+.tabs {width:100%; height:18px; line-height:normal; background:url(../default/img/tabs.gif) repeat-x 0 -72px;}\r
+.tabs ul {margin:0; padding:0; list-style:none;}\r
+.tabs li {float:left; background:url(../default/img/tabs.gif) no-repeat 0 0; margin:0 2px 0 0; padding:0 0 0 10px; line-height:17px; height:18px; display:block;}\r
+.tabs li.current {background:url(../default/img/tabs.gif) no-repeat 0 -18px; margin-right:2px;}\r
+.tabs span {float:left; display:block; background:url(../default/img/tabs.gif) no-repeat right -36px; padding:0px 10px 0 0;}\r
+.tabs .current span {background:url(../default/img/tabs.gif) no-repeat right -54px;}\r
+.tabs a {text-decoration:none; font-family:Verdana, Arial; font-size:10px;}\r
+.tabs a:link, .tabs a:visited, .tabs a:hover {color:black;}\r
+\r
+/* Panels */\r
+.panel_wrapper div.panel {display:none;}\r
+.panel_wrapper div.current {display:block; width:100%; height:300px; overflow:visible;}\r
+.panel_wrapper {border:1px solid #919B9C; border-top:0px; padding:10px; padding-top:5px; clear:both; background:white;}\r
+\r
+/* Columns */\r
+.column {float:left;}\r
+.properties {width:100%;}\r
+.properties .column1 {}\r
+.properties .column2 {text-align:left;}\r
+\r
+/* Titles */\r
+h1, h2, h3, h4 {color:#2B6FB6; margin:0; padding:0; padding-top:5px;}\r
+h3 {font-size:14px;}\r
+.title {font-size:12px; font-weight:bold; color:#2B6FB6;}\r
+\r
+/* Dialog specific */\r
+#link .panel_wrapper, #link div.current {height:125px;}\r
+#image .panel_wrapper, #image div.current {height:200px;}\r
+#plugintable thead {font-weight:bold; background:#DDD;}\r
+#plugintable, #about #plugintable td {border:1px solid #919B9C;}\r
+#plugintable {width:96%; margin-top:10px;}\r
+#pluginscontainer {height:290px; overflow:auto;}\r
+#colorpicker #preview {float:right; width:50px; height:14px;line-height:1px; border:1px solid black; margin-left:5px;}\r
+#colorpicker #colors {float:left; border:1px solid gray; cursor:crosshair;}\r
+#colorpicker #light {border:1px solid gray; margin-left:5px; float:left;width:15px; height:150px; cursor:crosshair;}\r
+#colorpicker #light div {overflow:hidden;}\r
+#colorpicker #previewblock {float:right; padding-left:10px; height:20px;}\r
+#colorpicker .panel_wrapper div.current {height:175px;}\r
+#colorpicker #namedcolors {width:150px;}\r
+#colorpicker #namedcolors a {display:block; float:left; width:10px; height:10px; margin:1px 1px 0 0; overflow:hidden;}\r
+#colorpicker #colornamecontainer {margin-top:5px;}\r
diff --git a/jscripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg.png b/jscripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg.png
new file mode 100644 (file)
index 0000000..12cfb41
Binary files /dev/null and b/jscripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg.png differ
diff --git a/jscripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_black.png b/jscripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_black.png
new file mode 100644 (file)
index 0000000..8996c74
Binary files /dev/null and b/jscripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_black.png differ
diff --git a/jscripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_silver.png b/jscripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_silver.png
new file mode 100644 (file)
index 0000000..bd5d255
Binary files /dev/null and b/jscripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_silver.png differ
diff --git a/jscripts/tiny_mce/themes/advanced/skins/o2k7/ui.css b/jscripts/tiny_mce/themes/advanced/skins/o2k7/ui.css
new file mode 100644 (file)
index 0000000..0da56e9
--- /dev/null
@@ -0,0 +1,215 @@
+/* Reset */\r
+.o2k7Skin table, .o2k7Skin tbody, .o2k7Skin a, .o2k7Skin img, .o2k7Skin tr, .o2k7Skin div, .o2k7Skin td, .o2k7Skin iframe, .o2k7Skin span, .o2k7Skin *, .o2k7Skin .mceText {border:0; margin:0; padding:0; background:transparent; white-space:nowrap; text-decoration:none; font-weight:normal; cursor:default; color:#000; vertical-align:baseline; width:auto; border-collapse:separate; text-align:left}\r
+.o2k7Skin a:hover, .o2k7Skin a:link, .o2k7Skin a:visited, .o2k7Skin a:active {text-decoration:none; font-weight:normal; cursor:default; color:#000}\r
+.o2k7Skin table td {vertical-align:middle}\r
+\r
+/* Containers */\r
+.o2k7Skin table {background:#E5EFFD}\r
+.o2k7Skin iframe {display:block; background:#FFF}\r
+.o2k7Skin .mceToolbar {height:26px}\r
+\r
+/* External */\r
+.o2k7Skin .mceExternalToolbar {position:absolute; border:1px solid #ABC6DD; border-bottom:0; display:none}\r
+.o2k7Skin .mceExternalToolbar td.mceToolbar {padding-right:13px;}\r
+.o2k7Skin .mceExternalClose {position:absolute; top:3px; right:3px; width:7px; height:7px; background:url(../../img/icons.gif) -820px 0}\r
+\r
+/* Layout */\r
+.o2k7Skin table.mceLayout {border:0; border-left:1px solid #ABC6DD; border-right:1px solid #ABC6DD}\r
+.o2k7Skin table.mceLayout tr.mceFirst td {border-top:1px solid #ABC6DD}\r
+.o2k7Skin table.mceLayout tr.mceLast td {border-bottom:1px solid #ABC6DD}\r
+.o2k7Skin table.mceToolbar, .o2k7Skin tr.mceFirst .mceToolbar tr td, .o2k7Skin tr.mceLast .mceToolbar tr td {border:0; margin:0; padding:0}\r
+.o2k7Skin .mceIframeContainer {border-top:1px solid #ABC6DD; border-bottom:1px solid #ABC6DD}\r
+.o2k7Skin .mceStatusbar {display:block; font-family:'MS Sans Serif',sans-serif,Verdana,Arial; font-size:9pt; line-height:16px; overflow:visible; color:#000; height:20px}\r
+.o2k7Skin .mceStatusbar div {float:left; padding:2px}\r
+.o2k7Skin .mceStatusbar a.mceResize {display:block; float:right; background:url(../../img/icons.gif) -800px 0; width:20px; height:20px; cursor:se-resize}\r
+.o2k7Skin .mceStatusbar a:hover {text-decoration:underline}\r
+.o2k7Skin table.mceToolbar {margin-left:3px}\r
+.o2k7Skin .mceToolbar .mceToolbarStart span {display:block; background:url(img/button_bg.png) -22px 0; width:1px; height:22px; margin-left:3px;}\r
+.o2k7Skin .mceToolbar td.mceFirst span {margin:0}\r
+.o2k7Skin .mceToolbar .mceToolbarEnd span {display:block; background:url(img/button_bg.png) -22px 0; width:1px; height:22px}\r
+.o2k7Skin .mceToolbar .mceToolbarEndListBox span, .o2k7Skin .mceToolbar .mceToolbarStartListBox span {display:none}\r
+.o2k7Skin span.mceIcon, .o2k7Skin img.mceIcon {display:block; width:20px; height:20px}\r
+.o2k7Skin .mceIcon {background:url(../../img/icons.gif) no-repeat 20px 20px}\r
+.o2k7Skin td.mceCenter {text-align:center;}\r
+.o2k7Skin td.mceCenter table {margin:0 auto; text-align:left;}\r
+.o2k7Skin td.mceRight table {margin:0 0 0 auto;}\r
+\r
+/* Button */\r
+.o2k7Skin .mceButton {display:block; background:url(img/button_bg.png); width:22px; height:22px}\r
+.o2k7Skin a.mceButton span, .o2k7Skin a.mceButton img {margin-left:1px}\r
+.o2k7Skin .mceOldBoxModel a.mceButton span, .o2k7Skin .mceOldBoxModel a.mceButton img {margin:0 0 0 1px}\r
+.o2k7Skin a.mceButtonEnabled:hover {background-color:#B2BBD0; background-position:0 -22px}\r
+.o2k7Skin a.mceButtonActive, .o2k7Skin a.mceButtonSelected {background-position:0 -44px}\r
+.o2k7Skin .mceButtonDisabled .mceIcon {opacity:0.3; filter:alpha(opacity=30)}\r
+.o2k7Skin .mceButtonLabeled {width:auto}\r
+.o2k7Skin .mceButtonLabeled span.mceIcon {float:left}\r
+.o2k7Skin span.mceButtonLabel {display:block; font-size:10px; padding:4px 6px 0 22px; font-family:Tahoma,Verdana,Arial,Helvetica}\r
+.o2k7Skin .mceButtonDisabled .mceButtonLabel {color:#888}\r
+\r
+/* Separator */\r
+.o2k7Skin .mceSeparator {display:block; background:url(img/button_bg.png) -22px 0; width:5px; height:22px}\r
+\r
+/* ListBox */\r
+.o2k7Skin .mceListBox {margin-left:3px}\r
+.o2k7Skin .mceListBox, .o2k7Skin .mceListBox a {display:block}\r
+.o2k7Skin .mceListBox .mceText {padding-left:4px; text-align:left; width:70px; border:1px solid #b3c7e1; border-right:0; background:#eaf2fb; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; height:20px; line-height:20px; overflow:hidden}\r
+.o2k7Skin .mceListBox .mceOpen {width:14px; height:22px; background:url(img/button_bg.png) -66px 0}\r
+.o2k7Skin table.mceListBoxEnabled:hover .mceText, .o2k7Skin .mceListBoxHover .mceText, .o2k7Skin .mceListBoxSelected .mceText {background:#FFF}\r
+.o2k7Skin table.mceListBoxEnabled:hover .mceOpen, .o2k7Skin .mceListBoxHover .mceOpen, .o2k7Skin .mceListBoxSelected .mceOpen {background-position:-66px -22px}\r
+.o2k7Skin .mceListBoxDisabled .mceText {color:gray}\r
+.o2k7Skin .mceListBoxMenu {overflow:auto; overflow-x:hidden}\r
+.o2k7Skin .mceOldBoxModel .mceListBox .mceText {height:22px}\r
+.o2k7Skin select.mceListBox {font-family:Tahoma,Verdana,Arial,Helvetica; font-size:12px; border:1px solid #b3c7e1; background:#FFF;}\r
+\r
+/* SplitButton */\r
+.o2k7Skin .mceSplitButton, .o2k7Skin .mceSplitButton a, .o2k7Skin .mceSplitButton span {display:block; height:22px}\r
+.o2k7Skin .mceSplitButton {background:url(img/button_bg.png)}\r
+.o2k7Skin .mceSplitButton a.mceAction {width:22px}\r
+.o2k7Skin .mceSplitButton span.mceAction {width:22px; background:url(../../img/icons.gif) 20px 20px}\r
+.o2k7Skin .mceSplitButton a.mceOpen {width:10px}\r
+.o2k7Skin .mceSplitButton span.mceOpen {width:10px; background:url(img/button_bg.png) -44px 0}\r
+.o2k7Skin table.mceSplitButtonEnabled:hover a.mceAction, .o2k7Skin .mceSplitButtonHover a.mceAction, .o2k7Skin .mceSplitButtonSelected {background:url(img/button_bg.png) 0 -22px}\r
+.o2k7Skin table.mceSplitButtonEnabled:hover span.mceOpen, .o2k7Skin .mceSplitButtonHover span.mceOpen, .o2k7Skin .mceSplitButtonSelected span.mceOpen {background-position:-44px -44px}\r
+.o2k7Skin .mceSplitButtonDisabled .mceAction {opacity:0.3; filter:alpha(opacity=30)}\r
+.o2k7Skin .mceSplitButtonActive {background-position:0 -44px}\r
+\r
+/* ColorSplitButton */\r
+.o2k7Skin div.mceColorSplitMenu table {background:#FFF; border:1px solid gray}\r
+.o2k7Skin .mceColorSplitMenu td {padding:2px}\r
+.o2k7Skin .mceColorSplitMenu a {display:block; width:9px; height:9px; overflow:hidden; border:1px solid #808080}\r
+.o2k7Skin .mceColorSplitMenu td.mceMoreColors {padding:1px 3px 1px 1px}\r
+.o2k7Skin .mceColorSplitMenu a.mceMoreColors {width:100%; height:auto; text-align:center; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; line-height:20px; border:1px solid #FFF}\r
+.o2k7Skin .mceColorSplitMenu a.mceMoreColors:hover {border:1px solid #0A246A; background-color:#B6BDD2}\r
+.o2k7Skin a.mceMoreColors:hover {border:1px solid #0A246A}\r
+.o2k7Skin .mceColorPreview {margin-left:2px; width:16px; height:4px; overflow:hidden; background:#9a9b9a;overflow:hidden}\r
+.o2k7Skin .mce_forecolor span.mceAction, .o2k7Skin .mce_backcolor span.mceAction {height:15px;overflow:hidden}\r
+\r
+/* Menu */\r
+.o2k7Skin .mceMenu {position:absolute; left:0; top:0; z-index:1000; border:1px solid #ABC6DD}\r
+.o2k7Skin .mceNoIcons span.mceIcon {width:0;}\r
+.o2k7Skin .mceNoIcons a .mceText {padding-left:10px}\r
+.o2k7Skin .mceMenu table {background:#FFF}\r
+.o2k7Skin .mceMenu a, .o2k7Skin .mceMenu span, .o2k7Skin .mceMenu {display:block}\r
+.o2k7Skin .mceMenu td {height:20px}\r
+.o2k7Skin .mceMenu a {position:relative;padding:3px 0 4px 0}\r
+.o2k7Skin .mceMenu .mceText {position:relative; display:block; font-family:Tahoma,Verdana,Arial,Helvetica; color:#000; cursor:default; margin:0; padding:0 25px 0 25px; display:block}\r
+.o2k7Skin .mceMenu span.mceText, .o2k7Skin .mceMenu .mcePreview {font-size:11px}\r
+.o2k7Skin .mceMenu pre.mceText {font-family:Monospace}\r
+.o2k7Skin .mceMenu .mceIcon {position:absolute; top:0; left:0; width:22px;}\r
+.o2k7Skin .mceMenu .mceMenuItemEnabled a:hover, .o2k7Skin .mceMenu .mceMenuItemActive {background-color:#dbecf3}\r
+.o2k7Skin td.mceMenuItemSeparator {background:#DDD; height:1px}\r
+.o2k7Skin .mceMenuItemTitle a {border:0; background:#E5EFFD; border-bottom:1px solid #ABC6DD}\r
+.o2k7Skin .mceMenuItemTitle span.mceText {color:#000; font-weight:bold; padding-left:4px}\r
+.o2k7Skin .mceMenuItemDisabled .mceText {color:#888}\r
+.o2k7Skin .mceMenuItemSelected .mceIcon {background:url(../default/img/menu_check.gif)}\r
+.o2k7Skin .mceNoIcons .mceMenuItemSelected a {background:url(../default/img/menu_arrow.gif) no-repeat -6px center}\r
+.o2k7Skin .mceMenu span.mceMenuLine {display:none}\r
+.o2k7Skin .mceMenuItemSub a {background:url(../default/img/menu_arrow.gif) no-repeat top right;}\r
+\r
+/* Progress,Resize */\r
+.o2k7Skin .mceBlocker {position:absolute; left:0; top:0; z-index:1000; opacity:0.5; filter:alpha(opacity=50); background:#FFF}\r
+.o2k7Skin .mceProgress {position:absolute; left:0; top:0; z-index:1001; background:url(../default/img/progress.gif) no-repeat; width:32px; height:32px; margin:-16px 0 0 -16px}\r
+.o2k7Skin .mcePlaceHolder {border:1px dotted gray}\r
+\r
+/* Formats */\r
+.o2k7Skin .mce_formatPreview a {font-size:10px}\r
+.o2k7Skin .mce_p span.mceText {}\r
+.o2k7Skin .mce_address span.mceText {font-style:italic}\r
+.o2k7Skin .mce_pre span.mceText {font-family:monospace}\r
+.o2k7Skin .mce_h1 span.mceText {font-weight:bolder; font-size: 2em}\r
+.o2k7Skin .mce_h2 span.mceText {font-weight:bolder; font-size: 1.5em}\r
+.o2k7Skin .mce_h3 span.mceText {font-weight:bolder; font-size: 1.17em}\r
+.o2k7Skin .mce_h4 span.mceText {font-weight:bolder; font-size: 1em}\r
+.o2k7Skin .mce_h5 span.mceText {font-weight:bolder; font-size: .83em}\r
+.o2k7Skin .mce_h6 span.mceText {font-weight:bolder; font-size: .75em}\r
+\r
+/* Theme */\r
+.o2k7Skin span.mce_bold {background-position:0 0}\r
+.o2k7Skin span.mce_italic {background-position:-60px 0}\r
+.o2k7Skin span.mce_underline {background-position:-140px 0}\r
+.o2k7Skin span.mce_strikethrough {background-position:-120px 0}\r
+.o2k7Skin span.mce_undo {background-position:-160px 0}\r
+.o2k7Skin span.mce_redo {background-position:-100px 0}\r
+.o2k7Skin span.mce_cleanup {background-position:-40px 0}\r
+.o2k7Skin span.mce_bullist {background-position:-20px 0}\r
+.o2k7Skin span.mce_numlist {background-position:-80px 0}\r
+.o2k7Skin span.mce_justifyleft {background-position:-460px 0}\r
+.o2k7Skin span.mce_justifyright {background-position:-480px 0}\r
+.o2k7Skin span.mce_justifycenter {background-position:-420px 0}\r
+.o2k7Skin span.mce_justifyfull {background-position:-440px 0}\r
+.o2k7Skin span.mce_anchor {background-position:-200px 0}\r
+.o2k7Skin span.mce_indent {background-position:-400px 0}\r
+.o2k7Skin span.mce_outdent {background-position:-540px 0}\r
+.o2k7Skin span.mce_link {background-position:-500px 0}\r
+.o2k7Skin span.mce_unlink {background-position:-640px 0}\r
+.o2k7Skin span.mce_sub {background-position:-600px 0}\r
+.o2k7Skin span.mce_sup {background-position:-620px 0}\r
+.o2k7Skin span.mce_removeformat {background-position:-580px 0}\r
+.o2k7Skin span.mce_newdocument {background-position:-520px 0}\r
+.o2k7Skin span.mce_image {background-position:-380px 0}\r
+.o2k7Skin span.mce_help {background-position:-340px 0}\r
+.o2k7Skin span.mce_code {background-position:-260px 0}\r
+.o2k7Skin span.mce_hr {background-position:-360px 0}\r
+.o2k7Skin span.mce_visualaid {background-position:-660px 0}\r
+.o2k7Skin span.mce_charmap {background-position:-240px 0}\r
+.o2k7Skin span.mce_paste {background-position:-560px 0}\r
+.o2k7Skin span.mce_copy {background-position:-700px 0}\r
+.o2k7Skin span.mce_cut {background-position:-680px 0}\r
+.o2k7Skin span.mce_blockquote {background-position:-220px 0}\r
+.o2k7Skin .mce_forecolor span.mceAction {background-position:-720px 0}\r
+.o2k7Skin .mce_backcolor span.mceAction {background-position:-760px 0}\r
+.o2k7Skin span.mce_forecolorpicker {background-position:-720px 0}\r
+.o2k7Skin span.mce_backcolorpicker {background-position:-760px 0}\r
+\r
+/* Plugins */\r
+.o2k7Skin span.mce_advhr {background-position:-0px -20px}\r
+.o2k7Skin span.mce_ltr {background-position:-20px -20px}\r
+.o2k7Skin span.mce_rtl {background-position:-40px -20px}\r
+.o2k7Skin span.mce_emotions {background-position:-60px -20px}\r
+.o2k7Skin span.mce_fullpage {background-position:-80px -20px}\r
+.o2k7Skin span.mce_fullscreen {background-position:-100px -20px}\r
+.o2k7Skin span.mce_iespell {background-position:-120px -20px}\r
+.o2k7Skin span.mce_insertdate {background-position:-140px -20px}\r
+.o2k7Skin span.mce_inserttime {background-position:-160px -20px}\r
+.o2k7Skin span.mce_absolute {background-position:-180px -20px}\r
+.o2k7Skin span.mce_backward {background-position:-200px -20px}\r
+.o2k7Skin span.mce_forward {background-position:-220px -20px}\r
+.o2k7Skin span.mce_insert_layer {background-position:-240px -20px}\r
+.o2k7Skin span.mce_insertlayer {background-position:-260px -20px}\r
+.o2k7Skin span.mce_movebackward {background-position:-280px -20px}\r
+.o2k7Skin span.mce_moveforward {background-position:-300px -20px}\r
+.o2k7Skin span.mce_media {background-position:-320px -20px}\r
+.o2k7Skin span.mce_nonbreaking {background-position:-340px -20px}\r
+.o2k7Skin span.mce_pastetext {background-position:-360px -20px}\r
+.o2k7Skin span.mce_pasteword {background-position:-380px -20px}\r
+.o2k7Skin span.mce_selectall {background-position:-400px -20px}\r
+.o2k7Skin span.mce_preview {background-position:-420px -20px}\r
+.o2k7Skin span.mce_print {background-position:-440px -20px}\r
+.o2k7Skin span.mce_cancel {background-position:-460px -20px}\r
+.o2k7Skin span.mce_save {background-position:-480px -20px}\r
+.o2k7Skin span.mce_replace {background-position:-500px -20px}\r
+.o2k7Skin span.mce_search {background-position:-520px -20px}\r
+.o2k7Skin span.mce_styleprops {background-position:-560px -20px}\r
+.o2k7Skin span.mce_table {background-position:-580px -20px}\r
+.o2k7Skin span.mce_cell_props {background-position:-600px -20px}\r
+.o2k7Skin span.mce_delete_table {background-position:-620px -20px}\r
+.o2k7Skin span.mce_delete_col {background-position:-640px -20px}\r
+.o2k7Skin span.mce_delete_row {background-position:-660px -20px}\r
+.o2k7Skin span.mce_col_after {background-position:-680px -20px}\r
+.o2k7Skin span.mce_col_before {background-position:-700px -20px}\r
+.o2k7Skin span.mce_row_after {background-position:-720px -20px}\r
+.o2k7Skin span.mce_row_before {background-position:-740px -20px}\r
+.o2k7Skin span.mce_merge_cells {background-position:-760px -20px}\r
+.o2k7Skin span.mce_table_props {background-position:-980px -20px}\r
+.o2k7Skin span.mce_row_props {background-position:-780px -20px}\r
+.o2k7Skin span.mce_split_cells {background-position:-800px -20px}\r
+.o2k7Skin span.mce_template {background-position:-820px -20px}\r
+.o2k7Skin span.mce_visualchars {background-position:-840px -20px}\r
+.o2k7Skin span.mce_abbr {background-position:-860px -20px}\r
+.o2k7Skin span.mce_acronym {background-position:-880px -20px}\r
+.o2k7Skin span.mce_attribs {background-position:-900px -20px}\r
+.o2k7Skin span.mce_cite {background-position:-920px -20px}\r
+.o2k7Skin span.mce_del {background-position:-940px -20px}\r
+.o2k7Skin span.mce_ins {background-position:-960px -20px}\r
+.o2k7Skin span.mce_pagebreak {background-position:0 -40px}\r
+.o2k7Skin .mce_spellchecker span.mceAction {background-position:-540px -20px}\r
diff --git a/jscripts/tiny_mce/themes/advanced/skins/o2k7/ui_black.css b/jscripts/tiny_mce/themes/advanced/skins/o2k7/ui_black.css
new file mode 100644 (file)
index 0000000..a42a727
--- /dev/null
@@ -0,0 +1,8 @@
+/* Black */\r
+.o2k7SkinBlack .mceToolbar .mceToolbarStart span, .o2k7SkinBlack .mceToolbar .mceToolbarEnd span, .o2k7SkinBlack .mceButton, .o2k7SkinBlack .mceSplitButton, .o2k7SkinBlack .mceSeparator, .o2k7SkinBlack .mceSplitButton span.mceOpen, .o2k7SkinBlack .mceListBox .mceOpen {background-image:url(img/button_bg_black.png)}\r
+.o2k7SkinBlack table, .o2k7SkinBlack .mceMenuItemTitle a, .o2k7SkinBlack .mceMenuItemTitle span.mceText, .o2k7SkinBlack .mceStatusbar div, .o2k7SkinBlack .mceStatusbar span, .o2k7SkinBlack .mceStatusbar a {background:#535353; color:#FFF}\r
+.o2k7SkinBlack table.mceListBoxEnabled .mceText, o2k7SkinBlack .mceListBox .mceText {background:#FFF; border:1px solid #CBCFD4; border-bottom-color:#989FA9; border-right:0}\r
+.o2k7SkinBlack table.mceListBoxEnabled:hover .mceText, .o2k7Skin .mceListBoxHover .mceText, .o2k7Skin .mceListBoxSelected .mceText {background:#FFF; border:1px solid #FFBD69; border-right:0}\r
+.o2k7SkinBlack .mceExternalToolbar, .o2k7SkinBlack .mceListBox .mceText, .o2k7SkinBlack div.mceMenu, .o2k7SkinBlack table.mceLayout, .o2k7SkinBlack .mceMenuItemTitle a, .o2k7SkinBlack table.mceLayout tr.mceFirst td, .o2k7SkinBlack table.mceLayout, .o2k7SkinBlack .mceMenuItemTitle a, .o2k7SkinBlack table.mceLayout tr.mceLast td, .o2k7SkinBlack .mceIframeContainer {border-color: #535353;}\r
+.o2k7SkinBlack table.mceSplitButtonEnabled:hover a.mceAction, .o2k7Skin .mceSplitButtonHover a.mceAction, .o2k7Skin .mceSplitButtonSelected {background-image:url(img/button_bg_black.png)}\r
+.o2k7SkinBlack .mceMenu .mceMenuItemEnabled a:hover, .o2k7Skin .mceMenu .mceMenuItemActive {background-color:#FFE7A1}
\ No newline at end of file
diff --git a/jscripts/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css b/jscripts/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css
new file mode 100644 (file)
index 0000000..548b1b8
--- /dev/null
@@ -0,0 +1,5 @@
+/* Silver */\r
+.o2k7SkinSilver .mceToolbar .mceToolbarStart span, .o2k7SkinSilver .mceButton, .o2k7SkinSilver .mceSplitButton, .o2k7SkinSilver .mceSeparator, .o2k7SkinSilver .mceSplitButton span.mceOpen, .o2k7SkinSilver .mceListBox .mceOpen {background-image:url(img/button_bg_silver.png)}\r
+.o2k7SkinSilver table, .o2k7SkinSilver .mceMenuItemTitle a {background:#eee}\r
+.o2k7SkinSilver .mceListBox .mceText {background:#FFF}\r
+.o2k7SkinSilver .mceExternalToolbar, .o2k7SkinSilver .mceListBox .mceText, .o2k7SkinSilver div.mceMenu, .o2k7SkinSilver table.mceLayout, .o2k7SkinSilver .mceMenuItemTitle a, .o2k7SkinSilver table.mceLayout tr.mceFirst td, .o2k7SkinSilver table.mceLayout, .o2k7SkinSilver .mceMenuItemTitle a, .o2k7SkinSilver table.mceLayout tr.mceLast td, .o2k7SkinSilver .mceIframeContainer {border-color: #bbb}\r
diff --git a/jscripts/tiny_mce/themes/advanced/source_editor.htm b/jscripts/tiny_mce/themes/advanced/source_editor.htm
new file mode 100644 (file)
index 0000000..60f482d
--- /dev/null
@@ -0,0 +1,32 @@
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />\r
+       <title>{#advanced_dlg.code_title}</title>\r
+       <script type="text/javascript" src="../../tiny_mce_popup.js?v=307"></script>\r
+       <script type="text/javascript" src="js/source_editor.js?v=307"></script>\r
+       <base target="_self" />\r
+</head>\r
+<body onresize="resizeInputs();" style="display:none; overflow:hidden;">\r
+       <form name="source" onsubmit="saveContent();return false;" action="#">\r
+               <div style="float: left" class="title">{#advanced_dlg.code_title}</div>\r
+\r
+               <div id="wrapline" style="float: right">\r
+                       <input type="checkbox" name="wraped" id="wraped" onclick="toggleWordWrap(this);" class="wordWrapCode" /><label for="wraped">{#advanced_dlg.code_wordwrap}</label>\r
+               </div>\r
+\r
+               <br style="clear: both" />\r
+\r
+               <textarea name="htmlSource" id="htmlSource" rows="15" cols="100" style="width: 100%; height: 100%; font-family: 'Courier New',Courier,monospace; font-size: 12px;" dir="ltr" wrap="off" class="mceFocus"></textarea>\r
+\r
+               <div class="mceActionPanel">\r
+                       <div style="float: left">\r
+                               <input type="submit" name="insert" value="{#update}" id="insert" />\r
+                       </div>\r
+\r
+                       <div style="float: right">\r
+                               <input type="button" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" id="cancel" />\r
+                       </div>\r
+               </div>\r
+       </form>\r
+</body>\r
+</html>\r
diff --git a/jscripts/tiny_mce/themes/simple/editor_template.js b/jscripts/tiny_mce/themes/simple/editor_template.js
new file mode 100644 (file)
index 0000000..3a25c04
--- /dev/null
@@ -0,0 +1 @@
+(function(){var DOM=tinymce.DOM;tinymce.ThemeManager.requireLangPack('simple');tinymce.create('tinymce.themes.SimpleTheme',{init:function(ed,url){var t=this,states=['Bold','Italic','Underline','Strikethrough','InsertUnorderedList','InsertOrderedList'],s=ed.settings;t.editor=ed;ed.onInit.add(function(){ed.onNodeChange.add(function(ed,cm){tinymce.each(states,function(c){cm.get(c.toLowerCase()).setActive(ed.queryCommandState(c));});});ed.dom.loadCSS(url+"/skins/"+s.skin+"/content.css");});DOM.loadCSS((s.editor_css?ed.baseURI.toAbsolute(s.editor_css):'')||url+"/skins/"+s.skin+"/ui.css");},renderUI:function(o){var t=this,n=o.targetNode,ic,tb,ed=t.editor,cf=ed.controlManager,sc;n=DOM.insertAfter(DOM.create('span',{id:ed.id+'_container','class':'mceEditor '+ed.settings.skin+'SimpleSkin'}),n);n=sc=DOM.add(n,'table',{cellPadding:0,cellSpacing:0,'class':'mceLayout'});n=tb=DOM.add(n,'tbody');n=DOM.add(tb,'tr');n=ic=DOM.add(DOM.add(n,'td'),'div',{'class':'mceIframeContainer'});n=DOM.add(DOM.add(tb,'tr',{'class':'last'}),'td',{'class':'mceToolbar mceLast',align:'center'});tb=t.toolbar=cf.createToolbar("tools1");tb.add(cf.createButton('bold',{title:'simple.bold_desc',cmd:'Bold'}));tb.add(cf.createButton('italic',{title:'simple.italic_desc',cmd:'Italic'}));tb.add(cf.createButton('underline',{title:'simple.underline_desc',cmd:'Underline'}));tb.add(cf.createButton('strikethrough',{title:'simple.striketrough_desc',cmd:'Strikethrough'}));tb.add(cf.createSeparator());tb.add(cf.createButton('undo',{title:'simple.undo_desc',cmd:'Undo'}));tb.add(cf.createButton('redo',{title:'simple.redo_desc',cmd:'Redo'}));tb.add(cf.createSeparator());tb.add(cf.createButton('cleanup',{title:'simple.cleanup_desc',cmd:'mceCleanup'}));tb.add(cf.createSeparator());tb.add(cf.createButton('insertunorderedlist',{title:'simple.bullist_desc',cmd:'InsertUnorderedList'}));tb.add(cf.createButton('insertorderedlist',{title:'simple.numlist_desc',cmd:'InsertOrderedList'}));tb.renderTo(n);return{iframeContainer:ic,editorContainer:ed.id+'_container',sizeContainer:sc,deltaHeight:-20};},getInfo:function(){return{longname:'Simple theme',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.ThemeManager.add('simple',tinymce.themes.SimpleTheme);})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/themes/simple/editor_template_src.js b/jscripts/tiny_mce/themes/simple/editor_template_src.js
new file mode 100644 (file)
index 0000000..adc4492
--- /dev/null
@@ -0,0 +1,85 @@
+/**\r
+ * $Id: editor_template_src.js 752 2008-03-27 21:51:25Z spocke $\r
+ *\r
+ * This file is meant to showcase how to create a simple theme. The advanced\r
+ * theme is more suitable for production use.\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+(function() {\r
+       var DOM = tinymce.DOM;\r
+\r
+       // Tell it to load theme specific language pack(s)\r
+       tinymce.ThemeManager.requireLangPack('simple');\r
+\r
+       tinymce.create('tinymce.themes.SimpleTheme', {\r
+               init : function(ed, url) {\r
+                       var t = this, states = ['Bold', 'Italic', 'Underline', 'Strikethrough', 'InsertUnorderedList', 'InsertOrderedList'], s = ed.settings;\r
+\r
+                       t.editor = ed;\r
+\r
+                       ed.onInit.add(function() {\r
+                               ed.onNodeChange.add(function(ed, cm) {\r
+                                       tinymce.each(states, function(c) {\r
+                                               cm.get(c.toLowerCase()).setActive(ed.queryCommandState(c));\r
+                                       });\r
+                               });\r
+\r
+                               ed.dom.loadCSS(url + "/skins/" + s.skin + "/content.css");\r
+                       });\r
+\r
+                       DOM.loadCSS((s.editor_css ? ed.baseURI.toAbsolute(s.editor_css) : '') || url + "/skins/" + s.skin + "/ui.css");\r
+               },\r
+\r
+               renderUI : function(o) {\r
+                       var t = this, n = o.targetNode, ic, tb, ed = t.editor, cf = ed.controlManager, sc;\r
+\r
+                       n = DOM.insertAfter(DOM.create('span', {id : ed.id + '_container', 'class' : 'mceEditor ' + ed.settings.skin + 'SimpleSkin'}), n);\r
+                       n = sc = DOM.add(n, 'table', {cellPadding : 0, cellSpacing : 0, 'class' : 'mceLayout'});\r
+                       n = tb = DOM.add(n, 'tbody');\r
+\r
+                       // Create iframe container\r
+                       n = DOM.add(tb, 'tr');\r
+                       n = ic = DOM.add(DOM.add(n, 'td'), 'div', {'class' : 'mceIframeContainer'});\r
+\r
+                       // Create toolbar container\r
+                       n = DOM.add(DOM.add(tb, 'tr', {'class' : 'last'}), 'td', {'class' : 'mceToolbar mceLast', align : 'center'});\r
+\r
+                       // Create toolbar\r
+                       tb = t.toolbar = cf.createToolbar("tools1");\r
+                       tb.add(cf.createButton('bold', {title : 'simple.bold_desc', cmd : 'Bold'}));\r
+                       tb.add(cf.createButton('italic', {title : 'simple.italic_desc', cmd : 'Italic'}));\r
+                       tb.add(cf.createButton('underline', {title : 'simple.underline_desc', cmd : 'Underline'}));\r
+                       tb.add(cf.createButton('strikethrough', {title : 'simple.striketrough_desc', cmd : 'Strikethrough'}));\r
+                       tb.add(cf.createSeparator());\r
+                       tb.add(cf.createButton('undo', {title : 'simple.undo_desc', cmd : 'Undo'}));\r
+                       tb.add(cf.createButton('redo', {title : 'simple.redo_desc', cmd : 'Redo'}));\r
+                       tb.add(cf.createSeparator());\r
+                       tb.add(cf.createButton('cleanup', {title : 'simple.cleanup_desc', cmd : 'mceCleanup'}));\r
+                       tb.add(cf.createSeparator());\r
+                       tb.add(cf.createButton('insertunorderedlist', {title : 'simple.bullist_desc', cmd : 'InsertUnorderedList'}));\r
+                       tb.add(cf.createButton('insertorderedlist', {title : 'simple.numlist_desc', cmd : 'InsertOrderedList'}));\r
+                       tb.renderTo(n);\r
+\r
+                       return {\r
+                               iframeContainer : ic,\r
+                               editorContainer : ed.id + '_container',\r
+                               sizeContainer : sc,\r
+                               deltaHeight : -20\r
+                       };\r
+               },\r
+\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Simple theme',\r
+                               author : 'Moxiecode Systems AB',\r
+                               authorurl : 'http://tinymce.moxiecode.com',\r
+                               version : tinymce.majorVersion + "." + tinymce.minorVersion\r
+                       }\r
+               }\r
+       });\r
+\r
+       tinymce.ThemeManager.add('simple', tinymce.themes.SimpleTheme);\r
+})();
\ No newline at end of file
diff --git a/jscripts/tiny_mce/themes/simple/img/icons.gif b/jscripts/tiny_mce/themes/simple/img/icons.gif
new file mode 100644 (file)
index 0000000..16af141
Binary files /dev/null and b/jscripts/tiny_mce/themes/simple/img/icons.gif differ
diff --git a/jscripts/tiny_mce/themes/simple/langs/en.js b/jscripts/tiny_mce/themes/simple/langs/en.js
new file mode 100644 (file)
index 0000000..9f08f10
--- /dev/null
@@ -0,0 +1,11 @@
+tinyMCE.addI18n('en.simple',{\r
+bold_desc:"Bold (Ctrl+B)",\r
+italic_desc:"Italic (Ctrl+I)",\r
+underline_desc:"Underline (Ctrl+U)",\r
+striketrough_desc:"Strikethrough",\r
+bullist_desc:"Unordered list",\r
+numlist_desc:"Ordered list",\r
+undo_desc:"Undo (Ctrl+Z)",\r
+redo_desc:"Redo (Ctrl+Y)",\r
+cleanup_desc:"Cleanup messy code"\r
+});
\ No newline at end of file
diff --git a/jscripts/tiny_mce/themes/simple/skins/default/content.css b/jscripts/tiny_mce/themes/simple/skins/default/content.css
new file mode 100644 (file)
index 0000000..2506c80
--- /dev/null
@@ -0,0 +1,25 @@
+body, td, pre {\r
+       font-family: Verdana, Arial, Helvetica, sans-serif;\r
+       font-size: 10px;\r
+}\r
+\r
+body {\r
+       background-color: #FFFFFF;\r
+}\r
+\r
+.mceVisualAid {\r
+       border: 1px dashed #BBBBBB;\r
+}\r
+\r
+/* MSIE specific */\r
+\r
+* html body {\r
+       scrollbar-3dlight-color: #F0F0EE;\r
+       scrollbar-arrow-color: #676662;\r
+       scrollbar-base-color: #F0F0EE;\r
+       scrollbar-darkshadow-color: #DDDDDD;\r
+       scrollbar-face-color: #E0E0DD;\r
+       scrollbar-highlight-color: #F0F0EE;\r
+       scrollbar-shadow-color: #F0F0EE;\r
+       scrollbar-track-color: #F5F5F5; \r
+}\r
diff --git a/jscripts/tiny_mce/themes/simple/skins/default/ui.css b/jscripts/tiny_mce/themes/simple/skins/default/ui.css
new file mode 100644 (file)
index 0000000..1cf64b8
--- /dev/null
@@ -0,0 +1,32 @@
+/* Reset */\r
+.defaultSimpleSkin table, .defaultSimpleSkin tbody, .defaultSimpleSkin a, .defaultSimpleSkin img, .defaultSimpleSkin tr, .defaultSimpleSkin div, .defaultSimpleSkin td, .defaultSimpleSkin iframe, .defaultSimpleSkin span, .defaultSimpleSkin * {border:0; margin:0; padding:0; background:transparent; white-space:nowrap; text-decoration:none; font-weight:normal; cursor:default; color:#000}\r
+\r
+/* Containers */\r
+.defaultSimpleSkin {position:relative}\r
+.defaultSimpleSkin table.mceLayout {background:#F0F0EE; border:1px solid #CCC;}\r
+.defaultSimpleSkin iframe {display:block; background:#FFF; border-bottom:1px solid #CCC;}\r
+.defaultSimpleSkin .mceToolbar {height:24px;}\r
+\r
+/* Layout */\r
+.defaultSimpleSkin span.mceIcon, .defaultSimpleSkin img.mceIcon {display:block; width:20px; height:20px}\r
+.defaultSimpleSkin .mceIcon {background:url(../../img/icons.gif) no-repeat 20px 20px}\r
+\r
+/* Button */\r
+.defaultSimpleSkin .mceButton {display:block; border:1px solid #F0F0EE; width:20px; height:20px}\r
+.defaultSimpleSkin a.mceButtonEnabled:hover {border:1px solid #0A246A; background-color:#B2BBD0}\r
+.defaultSimpleSkin a.mceButtonActive {border:1px solid #0A246A; background-color:#C2CBE0}\r
+.defaultSimpleSkin .mceButtonDisabled span {opacity:0.3; filter:alpha(opacity=30)}\r
+\r
+/* Separator */\r
+.defaultSimpleSkin .mceSeparator {display:block; background:url(../../img/icons.gif) -180px 0; width:2px; height:20px; margin:0 2px 0 4px}\r
+\r
+/* Theme */\r
+.defaultSimpleSkin span.mce_bold {background-position:0 0}\r
+.defaultSimpleSkin span.mce_italic {background-position:-60px 0}\r
+.defaultSimpleSkin span.mce_underline {background-position:-140px 0}\r
+.defaultSimpleSkin span.mce_strikethrough {background-position:-120px 0}\r
+.defaultSimpleSkin span.mce_undo {background-position:-160px 0}\r
+.defaultSimpleSkin span.mce_redo {background-position:-100px 0}\r
+.defaultSimpleSkin span.mce_cleanup {background-position:-40px 0}\r
+.defaultSimpleSkin span.mce_insertunorderedlist {background-position:-20px 0}\r
+.defaultSimpleSkin span.mce_insertorderedlist {background-position:-80px 0}\r
diff --git a/jscripts/tiny_mce/themes/simple/skins/o2k7/content.css b/jscripts/tiny_mce/themes/simple/skins/o2k7/content.css
new file mode 100644 (file)
index 0000000..595809f
--- /dev/null
@@ -0,0 +1,17 @@
+body, td, pre {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;}\r
+\r
+body {background: #FFF;}\r
+.mceVisualAid {border: 1px dashed #BBB;}\r
+\r
+/* IE */\r
+\r
+* html body {\r
+scrollbar-3dlight-color: #F0F0EE;\r
+scrollbar-arrow-color: #676662;\r
+scrollbar-base-color: #F0F0EE;\r
+scrollbar-darkshadow-color: #DDDDDD;\r
+scrollbar-face-color: #E0E0DD;\r
+scrollbar-highlight-color: #F0F0EE;\r
+scrollbar-shadow-color: #F0F0EE;\r
+scrollbar-track-color: #F5F5F5;        \r
+}\r
diff --git a/jscripts/tiny_mce/themes/simple/skins/o2k7/img/button_bg.png b/jscripts/tiny_mce/themes/simple/skins/o2k7/img/button_bg.png
new file mode 100644 (file)
index 0000000..527e349
Binary files /dev/null and b/jscripts/tiny_mce/themes/simple/skins/o2k7/img/button_bg.png differ
diff --git a/jscripts/tiny_mce/themes/simple/skins/o2k7/ui.css b/jscripts/tiny_mce/themes/simple/skins/o2k7/ui.css
new file mode 100644 (file)
index 0000000..bfae96e
--- /dev/null
@@ -0,0 +1,35 @@
+/* Reset */\r
+.o2k7SimpleSkin table, .o2k7SimpleSkin tbody, .o2k7SimpleSkin a, .o2k7SimpleSkin img, .o2k7SimpleSkin tr, .o2k7SimpleSkin div, .o2k7SimpleSkin td, .o2k7SimpleSkin iframe, .o2k7SimpleSkin span, .o2k7SimpleSkin * {border:0; margin:0; padding:0; background:transparent; white-space:nowrap; text-decoration:none; font-weight:normal; cursor:default; color:#000}\r
+\r
+/* Containers */\r
+.o2k7SimpleSkin {position:relative}\r
+.o2k7SimpleSkin table.mceLayout {background:#E5EFFD; border:1px solid #ABC6DD;}\r
+.o2k7SimpleSkin iframe {display:block; background:#FFF; border-bottom:1px solid #ABC6DD;}\r
+.o2k7SimpleSkin .mceToolbar {height:26px;}\r
+\r
+/* Layout */\r
+.o2k7SimpleSkin .mceToolbar .mceToolbarStart span {display:block; background:url(img/button_bg.png) -22px 0; width:1px; height:22px; }\r
+.o2k7SimpleSkin .mceToolbar .mceToolbarEnd span {display:block; background:url(img/button_bg.png) -22px 0; width:1px; height:22px}\r
+.o2k7SimpleSkin span.mceIcon, .o2k7SimpleSkin img.mceIcon {display:block; width:20px; height:20px}\r
+.o2k7SimpleSkin .mceIcon {background:url(../../img/icons.gif) no-repeat 20px 20px}\r
+\r
+/* Button */\r
+.o2k7SimpleSkin .mceButton {display:block; background:url(img/button_bg.png); width:22px; height:22px}\r
+.o2k7SimpleSkin a.mceButton span, .o2k7SimpleSkin a.mceButton img {margin:1px 0 0 1px}\r
+.o2k7SimpleSkin a.mceButtonEnabled:hover {background-color:#B2BBD0; background-position:0 -22px}\r
+.o2k7SimpleSkin a.mceButtonActive {background-position:0 -44px}\r
+.o2k7SimpleSkin .mceButtonDisabled span {opacity:0.3; filter:alpha(opacity=30)}\r
+\r
+/* Separator */\r
+.o2k7SimpleSkin .mceSeparator {display:block; background:url(img/button_bg.png) -22px 0; width:5px; height:22px}\r
+\r
+/* Theme */\r
+.o2k7SimpleSkin span.mce_bold {background-position:0 0}\r
+.o2k7SimpleSkin span.mce_italic {background-position:-60px 0}\r
+.o2k7SimpleSkin span.mce_underline {background-position:-140px 0}\r
+.o2k7SimpleSkin span.mce_strikethrough {background-position:-120px 0}\r
+.o2k7SimpleSkin span.mce_undo {background-position:-160px 0}\r
+.o2k7SimpleSkin span.mce_redo {background-position:-100px 0}\r
+.o2k7SimpleSkin span.mce_cleanup {background-position:-40px 0}\r
+.o2k7SimpleSkin span.mce_insertunorderedlist {background-position:-20px 0}\r
+.o2k7SimpleSkin span.mce_insertorderedlist {background-position:-80px 0}\r
diff --git a/jscripts/tiny_mce/tiny_mce.js b/jscripts/tiny_mce/tiny_mce.js
new file mode 100644 (file)
index 0000000..ebf8c32
--- /dev/null
@@ -0,0 +1 @@
+var tinymce={majorVersion:'3',minorVersion:'0.7',releaseDate:'2008-04-14',_init:function(){var t=this,d=document,w=window,na=navigator,ua=na.userAgent,i,nl,n,base;t.isOpera=w.opera&&opera.buildNumber;t.isWebKit=/WebKit/.test(ua);t.isOldWebKit=t.isWebKit&&!w.getSelection().getRangeAt;t.isIE=!t.isWebKit&&!t.isOpera&&(/MSIE/gi).test(ua)&&(/Explorer/gi).test(na.appName);t.isIE6=t.isIE&&/MSIE [56]/.test(ua);t.isGecko=!t.isWebKit&&/Gecko/.test(ua);t.isMac=ua.indexOf('Mac')!=-1;if(w.tinyMCEPreInit){t.suffix=tinyMCEPreInit.suffix;t.baseURL=tinyMCEPreInit.base;return;}t.suffix='';nl=d.getElementsByTagName('base');for(i=0;i<nl.length;i++){if(nl[i].href)base=nl[i].href;}function getBase(n){if(n.src&&/tiny_mce(|_dev|_src|_gzip|_jquery|_prototype).js/.test(n.src)){if(/_(src|dev)\.js/g.test(n.src))t.suffix='_src';t.baseURL=n.src.substring(0,n.src.lastIndexOf('/'));if(base&&t.baseURL.indexOf('://')==-1)t.baseURL=base+t.baseURL;return t.baseURL;}return null;};nl=d.getElementsByTagName('script');for(i=0;i<nl.length;i++){if(getBase(nl[i]))return;}n=d.getElementsByTagName('head')[0];if(n){nl=n.getElementsByTagName('script');for(i=0;i<nl.length;i++){if(getBase(nl[i]))return;}}return;},is:function(o,t){var n=typeof(o);if(!t)return n!='undefined';if(t=='array'&&(o instanceof Array))return true;return n==t;},each:function(o,cb,s){var n,l;if(!o)return 0;s=s||o;if(typeof(o.length)!='undefined'){for(n=0,l=o.length;n<l;n++){if(cb.call(s,o[n],n,o)===false)return 0;}}else{for(n in o){if(o.hasOwnProperty(n)){if(cb.call(s,o[n],n,o)===false)return 0;}}}return 1;},map:function(a,f){var o=[];tinymce.each(a,function(v){o.push(f(v));});return o;},grep:function(a,f){var o=[];tinymce.each(a,function(v){if(!f||f(v))o.push(v);});return o;},inArray:function(a,v){var i,l;if(a){for(i=0,l=a.length;i<l;i++){if(a[i]===v)return i;}}return-1;},extend:function(o,e){var i,a=arguments;for(i=1;i<a.length;i++){e=a[i];tinymce.each(e,function(v,n){if(typeof(v)!=='undefined')o[n]=v;});}return o;},trim:function(s){return(s?''+s:'').replace(/^\s*|\s*$/g,'');},create:function(s,p){var t=this,sp,ns,cn,scn,c,de=0;s=/^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);cn=s[3].match(/(^|\.)(\w+)$/i)[2];ns=t.createNS(s[3].replace(/\.\w+$/,''));if(ns[cn])return;if(s[2]=='static'){ns[cn]=p;if(this.onCreate)this.onCreate(s[2],s[3],ns[cn]);return;}if(!p[cn]){p[cn]=function(){};de=1;}ns[cn]=p[cn];t.extend(ns[cn].prototype,p);if(s[5]){sp=t.resolve(s[5]).prototype;scn=s[5].match(/\.(\w+)$/i)[1];c=ns[cn];if(de){ns[cn]=function(){return sp[scn].apply(this,arguments);};}else{ns[cn]=function(){this.parent=sp[scn];return c.apply(this,arguments);};}ns[cn].prototype[cn]=ns[cn];t.each(sp,function(f,n){ns[cn].prototype[n]=sp[n];});t.each(p,function(f,n){if(sp[n]){ns[cn].prototype[n]=function(){this.parent=sp[n];return f.apply(this,arguments);};}else{if(n!=cn)ns[cn].prototype[n]=f;}});}t.each(p['static'],function(f,n){ns[cn][n]=f;});if(this.onCreate)this.onCreate(s[2],s[3],ns[cn].prototype);},walk:function(o,f,n,s){s=s||this;if(o){if(n)o=o[n];tinymce.each(o,function(o,i){if(f.call(s,o,i,n)===false)return false;tinymce.walk(o,f,n,s);});}},createNS:function(n,o){var i,v;o=o||window;n=n.split('.');for(i=0;i<n.length;i++){v=n[i];if(!o[v])o[v]={};o=o[v];}return o;},resolve:function(n,o){var i,l;o=o||window;n=n.split('.');for(i=0,l=n.length;i<l;i++){o=o[n[i]];if(!o)break;}return o;},addUnload:function(f,s){var t=this,w=window;f={func:f,scope:s||this};if(!t.unloads){function unload(){var li=t.unloads,o,n;if(li){for(n in li){o=li[n];if(o&&o.func)o.func.call(o.scope,1);}if(w.detachEvent){w.detachEvent('onbeforeunload',fakeUnload);w.detachEvent('onunload',unload);}else if(w.removeEventListener)w.removeEventListener('unload',unload,false);t.unloads=o=li=w=unload=null;if(window.CollectGarbage)window.CollectGarbage();}};function fakeUnload(){var d=document;if(d.readyState=='interactive'){function stop(){d.detachEvent('onstop',stop);unload();d=null;};d.attachEvent('onstop',stop);window.setTimeout(function(){d.detachEvent('onstop',stop);},0);}};if(w.attachEvent){w.attachEvent('onunload',unload);w.attachEvent('onbeforeunload',fakeUnload);}else if(w.addEventListener)w.addEventListener('unload',unload,false);t.unloads=[f];}else t.unloads.push(f);return f;},removeUnload:function(f){var u=this.unloads,r=null;tinymce.each(u,function(o,i){if(o&&o.func==f){u.splice(i,1);r=f;return false;}});return r;},explode:function(s,d){return tinymce.map(s.split(d||','),tinymce.trim);},_addVer:function(u,s){return u+(u.indexOf('?')==-1?'?':'&')+'v='+(tinymce.majorVersion+tinymce.minorVersion).replace(/[^0-9]/g,'');}};window.tinymce=tinymce;tinymce._init();tinymce.create('tinymce.util.Dispatcher',{scope:null,listeners:null,Dispatcher:function(s){this.scope=s||this;this.listeners=[];},add:function(cb,s){this.listeners.push({cb:cb,scope:s||this.scope});return cb;},addToTop:function(cb,s){this.listeners.unshift({cb:cb,scope:s||this.scope});return cb;},remove:function(cb){var l=this.listeners,o=null;tinymce.each(l,function(c,i){if(cb==c.cb){o=cb;l.splice(i,1);return false;}});return o;},dispatch:function(){var s,a=arguments,i,li=this.listeners,c;for(i=0;i<li.length;i++){c=li[i];s=c.cb.apply(c.scope,a);if(s===false)break;}return s;}});(function(){var each=tinymce.each;tinymce.create('tinymce.util.URI',{URI:function(u,s){var t=this,o,a,b;s=t.settings=s||{};if(/^(mailto|news|javascript|about):/i.test(u)||/^\s*#/.test(u)){t.source=u;return;}if(u.indexOf('/')===0&&u.indexOf('//')!==0)u=(s.base_uri?s.base_uri.protocol||'http':'http')+'://mce_host'+u;if(u.indexOf('://')===-1&&u.indexOf('//')!==0)u=(s.base_uri.protocol||'http')+'://mce_host'+t.toAbsPath(s.base_uri.path,u);u=u.replace(/@@/g,'(mce_at)');u=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u);each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],function(v,i){var s=u[i];if(s)s=s.replace(/\(mce_at\)/g,'@@');t[v]=s;});if(b=s.base_uri){if(!t.protocol)t.protocol=b.protocol;if(!t.userInfo)t.userInfo=b.userInfo;if(!t.port&&t.host=='mce_host')t.port=b.port;if(!t.host||t.host=='mce_host')t.host=b.host;t.source='';}},setPath:function(p){var t=this;p=/^(.*?)\/?(\w+)?$/.exec(p);t.path=p[0];t.directory=p[1];t.file=p[2];t.source='';t.getURI();},toRelative:function(u){var t=this,o;u=new tinymce.util.URI(u,{base_uri:t});if((u.host!='mce_host'&&t.host!=u.host&&u.host)||t.port!=u.port||t.protocol!=u.protocol)return u.getURI();o=t.toRelPath(t.path,u.path);if(u.query)o+='?'+u.query;if(u.anchor)o+='#'+u.anchor;return o;},toAbsolute:function(u,nh){var u=new tinymce.util.URI(u,{base_uri:this});return u.getURI(this.host==u.host?nh:0);},toRelPath:function(base,path){var items,bp=0,out='',i;base=base.substring(0,base.lastIndexOf('/'));base=base.split('/');items=path.split('/');if(base.length>=items.length){for(i=0;i<base.length;i++){if(i>=items.length||base[i]!=items[i]){bp=i+1;break;}}}if(base.length<items.length){for(i=0;i<items.length;i++){if(i>=base.length||base[i]!=items[i]){bp=i+1;break;}}}if(bp==1)return path;for(i=0;i<base.length-(bp-1);i++)out+="../";for(i=bp-1;i<items.length;i++){if(i!=bp-1)out+="/"+items[i];else out+=items[i];}return out;},toAbsPath:function(base,path){var i,nb=0,o=[];base=base.split('/');path=path.split('/');each(base,function(k){if(k)o.push(k);});base=o;for(i=path.length-1,o=[];i>=0;i--){if(path[i].length==0||path[i]==".")continue;if(path[i]=='..'){nb++;continue;}if(nb>0){nb--;continue;}o.push(path[i]);}i=base.length-nb;if(i<=0)return'/'+o.reverse().join('/');return'/'+base.slice(0,i).join('/')+'/'+o.reverse().join('/');},getURI:function(nh){var s,t=this;if(!t.source||nh){s='';if(!nh){if(t.protocol)s+=t.protocol+'://';if(t.userInfo)s+=t.userInfo+'@';if(t.host)s+=t.host;if(t.port)s+=':'+t.port;}if(t.path)s+=t.path;if(t.query)s+='?'+t.query;if(t.anchor)s+='#'+t.anchor;t.source=s;}return t.source;}});})();(function(){var each=tinymce.each;tinymce.create('static tinymce.util.Cookie',{getHash:function(n){var v=this.get(n),h;if(v){each(v.split('&'),function(v){v=v.split('=');h=h||{};h[unescape(v[0])]=unescape(v[1]);});}return h;},setHash:function(n,v,e,p,d,s){var o='';each(v,function(v,k){o+=(!o?'':'&')+escape(k)+'='+escape(v);});this.set(n,o,e,p,d,s);},get:function(n){var c=document.cookie,e,p=n+"=",b;if(!c)return;b=c.indexOf("; "+p);if(b==-1){b=c.indexOf(p);if(b!=0)return null;}else b+=2;e=c.indexOf(";",b);if(e==-1)e=c.length;return unescape(c.substring(b+p.length,e));},set:function(n,v,e,p,d,s){document.cookie=n+"="+escape(v)+((e)?"; expires="+e.toGMTString():"")+((p)?"; path="+escape(p):"")+((d)?"; domain="+d:"")+((s)?"; secure":"");},remove:function(n,p){var d=new Date();d.setTime(d.getTime()-1000);this.set(n,'',d,p,d);}});})();tinymce.create('static tinymce.util.JSON',{serialize:function(o){var i,v,s=tinymce.util.JSON.serialize,t;if(o==null)return'null';t=typeof o;if(t=='string'){v='\bb\tt\nn\ff\rr\""\'\'\\\\';return'"'+o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'])/g,function(a,b){i=v.indexOf(b);if(i+1)return'\\'+v.charAt(i+1);a=b.charCodeAt().toString(16);return'\\u'+'0000'.substring(a.length)+a;})+'"';}if(t=='object'){if(o instanceof Array){for(i=0,v='[';i<o.length;i++)v+=(i>0?',':'')+s(o[i]);return v+']';}v='{';for(i in o)v+=typeof o[i]!='function'?(v.length>1?',"':'"')+i+'":'+s(o[i]):'';return v+'}';}return''+o;},parse:function(s){try{return eval('('+s+')');}catch(ex){}}});tinymce.create('static tinymce.util.XHR',{send:function(o){var x,t,w=window,c=0;o.scope=o.scope||this;o.success_scope=o.success_scope||o.scope;o.error_scope=o.error_scope||o.scope;o.async=o.async===false?false:true;o.data=o.data||'';function get(s){x=0;try{x=new ActiveXObject(s);}catch(ex){}return x;};x=w.XMLHttpRequest?new XMLHttpRequest():get('Microsoft.XMLHTTP')||get('Msxml2.XMLHTTP');if(x){if(x.overrideMimeType)x.overrideMimeType(o.content_type);x.open(o.type||(o.data?'POST':'GET'),o.url,o.async);if(o.content_type)x.setRequestHeader('Content-Type',o.content_type);x.send(o.data);t=w.setInterval(function(){if(x.readyState==4||c++>10000){w.clearInterval(t);if(o.success&&c<10000&&x.status==200)o.success.call(o.success_scope,''+x.responseText,x,o);else if(o.error)o.error.call(o.error_scope,c>10000?'TIMED_OUT':'GENERAL',x,o);x=null;}},10);}}});(function(){var extend=tinymce.extend,JSON=tinymce.util.JSON,XHR=tinymce.util.XHR;tinymce.create('tinymce.util.JSONRequest',{JSONRequest:function(s){this.settings=extend({},s);this.count=0;},send:function(o){var ecb=o.error,scb=o.success;o=extend(this.settings,o);o.success=function(c,x){c=JSON.parse(c);if(typeof(c)=='undefined'){c={error:'JSON Parse error.'};}if(c.error)ecb.call(o.error_scope||o.scope,c.error,x);else scb.call(o.success_scope||o.scope,c.result);};o.error=function(ty,x){ecb.call(o.error_scope||o.scope,ty,x);};o.data=JSON.serialize({id:o.id||'c'+(this.count++),method:o.method,params:o.params});o.content_type='application/json';XHR.send(o);},'static':{sendRPC:function(o){return new tinymce.util.JSONRequest().send(o);}}});}());(function(){var each=tinymce.each,is=tinymce.is;var isWebKit=tinymce.isWebKit,isIE=tinymce.isIE;tinymce.create('tinymce.dom.DOMUtils',{doc:null,root:null,files:null,listeners:{},pixelStyles:/^(top|left|bottom|right|width|height|borderWidth)$/,cache:{},idPattern:/^#[\w]+$/,elmPattern:/^[\w_*]+$/,elmClassPattern:/^([\w_]*)\.([\w_]+)$/,DOMUtils:function(d,s){var t=this;t.doc=d;t.win=window;t.files={};t.cssFlicker=false;t.counter=0;t.boxModel=!tinymce.isIE||d.compatMode=="CSS1Compat";t.stdMode=d.documentMode===8;this.settings=s=tinymce.extend({keep_values:false,hex_colors:1,process_html:1},s);if(tinymce.isIE6){try{d.execCommand('BackgroundImageCache',false,true);}catch(e){t.cssFlicker=true;}}tinymce.addUnload(t.destroy,t);},getRoot:function(){var t=this,s=t.settings;return(s&&t.get(s.root_element))||t.doc.body;},getViewPort:function(w){var d,b;w=!w?this.win:w;d=w.document;b=this.boxModel?d.documentElement:d.body;return{x:w.pageXOffset||b.scrollLeft,y:w.pageYOffset||b.scrollTop,w:w.innerWidth||b.clientWidth,h:w.innerHeight||b.clientHeight};},getRect:function(e){var p,t=this,w,h;e=t.get(e);p=t.getPos(e);w=t.getStyle(e,'width');h=t.getStyle(e,'height');if(w.indexOf('px')===-1)w=0;if(h.indexOf('px')===-1)h=0;return{x:p.x,y:p.y,w:parseInt(w)||e.offsetWidth||e.clientWidth,h:parseInt(h)||e.offsetHeight||e.clientHeight};},getParent:function(n,f,r){var na,se=this.settings;n=this.get(n);if(se.strict_root)r=r||this.getRoot();if(is(f,'string')){na=f.toUpperCase();f=function(n){var s=false;if(n.nodeType==1&&na==='*'){s=true;return false;}each(na.split(','),function(v){if(n.nodeType==1&&((se.strict&&n.nodeName.toUpperCase()==v)||n.nodeName==v)){s=true;return false;}});return s;};}while(n){if(n==r)return null;if(f(n))return n;n=n.parentNode;}return null;},get:function(e){var n;if(this.doc&&typeof(e)=='string'){n=e;e=this.doc.getElementById(e);if(e&&e.id!==n)return this.doc.getElementsByName(n)[1];}return e;},select:function(pa,s){var t=this,cs,c,pl,o=[],x,i,l,n;s=t.get(s)||t.doc;if(s.querySelectorAll){if(s!=t.doc){i=s.id;s.id='_mc_tmp';pa='#_mc_tmp '+pa;}l=tinymce.grep(s.querySelectorAll(pa));s.id=i;return l;}if(t.settings.strict){function get(s,n){return s.getElementsByTagName(n.toLowerCase());};}else{function get(s,n){return s.getElementsByTagName(n);};}if(t.elmPattern.test(pa)){x=get(s,pa);for(i=0,l=x.length;i<l;i++)o.push(x[i]);return o;}if(t.elmClassPattern.test(pa)){pl=t.elmClassPattern.exec(pa);x=get(s,pl[1]||'*');c=' '+pl[2]+' ';for(i=0,l=x.length;i<l;i++){n=x[i];if(n.className&&(' '+n.className+' ').indexOf(c)!==-1)o.push(n);}return o;}function collect(n){if(!n.mce_save){n.mce_save=1;o.push(n);}};function collectIE(n){if(!n.getAttribute('mce_save')){n.setAttribute('mce_save','1');o.push(n);}};function find(n,f,r){var i,l,nl=get(r,n);for(i=0,l=nl.length;i<l;i++)f(nl[i]);};each(pa.split(','),function(v,i){v=tinymce.trim(v);if(t.elmPattern.test(v)){each(get(s,v),function(n){collect(n);});return;}if(t.elmClassPattern.test(v)){x=t.elmClassPattern.exec(v);each(get(s,x[1]),function(n){if(t.hasClass(n,x[2]))collect(n);});return;}if(!(cs=t.cache[pa])){cs='x=(function(cf, s) {';pl=v.split(' ');each(pl,function(v){var p=/^([\w\\*]+)?(?:#([\w\\]+))?(?:\.([\w\\\.]+))?(?:\[\@([\w\\]+)([\^\$\*!]?=)([\w\\]+)\])?(?:\:([\w\\]+))?/i.exec(v);p[1]=p[1]||'*';cs+='find("'+p[1]+'", function(n) {';if(p[2])cs+='if (n.id !== "'+p[2]+'") return;';if(p[3]){cs+='var c = " " + n.className + " ";';cs+='if (';c='';each(p[3].split('.'),function(v){if(v)c+=(c?'||':'')+'c.indexOf(" '+v+' ") === -1';});cs+=c+') return;';}});cs+='cf(n);';for(i=pl.length-1;i>=0;i--)cs+='}, '+(i?'n':'s')+');';cs+='})';t.cache[pa]=cs=eval(cs);}cs(isIE?collectIE:collect,s);});each(o,function(n){if(isIE)n.removeAttribute('mce_save');else delete n.mce_save;});return o;},add:function(p,n,a,h,c){var t=this;return this.run(p,function(p){var e,k;e=is(n,'string')?t.doc.createElement(n):n;if(a){for(k in a){if(a.hasOwnProperty(k)&&!is(a[k],'object'))t.setAttrib(e,k,''+a[k]);}if(a.style&&!is(a.style,'string')){each(a.style,function(v,n){t.setStyle(e,n,v);});}}if(h){if(h.nodeType)e.appendChild(h);else t.setHTML(e,h);}return!c?p.appendChild(e):e;});},create:function(n,a,h){return this.add(this.doc.createElement(n),n,a,h,1);},createHTML:function(n,a,h){var o='',t=this,k;o+='<'+n;for(k in a){if(a.hasOwnProperty(k))o+=' '+k+'="'+t.encode(a[k])+'"';}if(tinymce.is(h))return o+'>'+h+'</'+n+'>';return o+' />';},remove:function(n,k){return this.run(n,function(n){var p,g;p=n.parentNode;if(!p)return null;if(k){each(n.childNodes,function(c){p.insertBefore(c.cloneNode(true),n);});}return p.removeChild(n);});},setStyle:function(n,na,v){var t=this;return t.run(n,function(e){var s,i;s=e.style;na=na.replace(/-(\D)/g,function(a,b){return b.toUpperCase();});if(t.pixelStyles.test(na)&&(tinymce.is(v,'number')||/^[\-0-9\.]+$/.test(v)))v+='px';switch(na){case'opacity':if(isIE){s.filter=v===''?'':"alpha(opacity="+(v*100)+")";if(!n.currentStyle||!n.currentStyle.hasLayout)s.display='inline-block';}s[na]=s['-moz-opacity']=s['-khtml-opacity']=v||'';break;case'float':isIE?s.styleFloat=v:s.cssFloat=v;break;default:s[na]=v||'';}if(t.settings.update_styles)t.setAttrib(e,'mce_style');});},getStyle:function(n,na,c){n=this.get(n);if(!n)return false;if(this.doc.defaultView&&c){na=na.replace(/[A-Z]/g,function(a){return'-'+a;});try{return this.doc.defaultView.getComputedStyle(n,null).getPropertyValue(na);}catch(ex){return null;}}na=na.replace(/-(\D)/g,function(a,b){return b.toUpperCase();});if(na=='float')na=isIE?'styleFloat':'cssFloat';if(n.currentStyle&&c)return n.currentStyle[na];return n.style[na];},setStyles:function(e,o){var t=this,s=t.settings,ol;ol=s.update_styles;s.update_styles=0;each(o,function(v,n){t.setStyle(e,n,v);});s.update_styles=ol;if(s.update_styles)t.setAttrib(e,s.cssText);},setAttrib:function(e,n,v){var t=this;if(t.settings.strict)n=n.toLowerCase();return this.run(e,function(e){var s=t.settings;switch(n){case"style":if(s.keep_values&&/^(| )(top|left|bottom|right|width|height)/i.test(v)){if(v)e.setAttribute('mce_style',v,2);else e.removeAttribute('mce_style',2);}e.style.cssText=v;break;case"class":e.className=v||'';break;case"src":case"href":if(s.keep_values){if(s.url_converter)v=s.url_converter.call(s.url_converter_scope||t,v,n,e);t.setAttrib(e,'mce_'+n,v,2);}break;}if(is(v)&&v!==null&&v.length!==0)e.setAttribute(n,''+v,2);else e.removeAttribute(n,2);});},setAttribs:function(e,o){var t=this;return this.run(e,function(e){each(o,function(v,n){t.setAttrib(e,n,v);});});},getAttrib:function(e,n,dv){var v,t=this;e=t.get(e);if(!e||e.nodeType!==1)return false;if(!is(dv))dv="";if(/^(src|href|style|coords)$/.test(n)){v=e.getAttribute("mce_"+n);if(v)return v;}v=e.getAttribute(n,2);if(!v){switch(n){case'class':v=e.className;break;default:if(isIE&&n==='name'&&e.nodeName==='A'){v=e.name;break;}v=e.attributes[n];v=v&&is(v.nodeValue)?v.nodeValue:v;}}switch(n){case'style':v=v||e.style.cssText;if(v){v=t.serializeStyle(t.parseStyle(v));if(t.settings.keep_values&&/^(| )(top|left|bottom|right|width|height)/i.test(v))e.setAttribute('mce_style',v);}break;}if(isWebKit&&n==="class"&&v)v=v.replace(/(apple|webkit)\-[a-z\-]+/gi,'');if(isIE){switch(n){case'rowspan':case'colspan':if(v===1)v='';break;case'size':if(v==='+0')v='';break;case'hspace':if(v===-1)v='';break;case'tabindex':if(v===32768)v='';break;case'shape':v=v.toLowerCase();break;default:if(n.indexOf('on')===0&&v)v=(''+v).replace(/^function\s+anonymous\(\)\s+\{\s+(.*)\s+\}$/,'$1');}}return(v&&v!='')?''+v:dv;},getPos:function(n){var t=this,x=0,y=0,e,d=t.doc,r;n=t.get(n);if(n&&isIE){n=n.getBoundingClientRect();e=t.boxModel?d.documentElement:d.body;x=t.getStyle(t.select('html')[0],'borderWidth');x=(x=='medium'||t.boxModel&&!t.isIE6)&&2||x;n.top+=t.win.self!=t.win.top?2:0;return{x:n.left+e.scrollLeft-x,y:n.top+e.scrollTop-x};}r=n;while(r){x+=r.offsetLeft||0;y+=r.offsetTop||0;r=r.offsetParent;}r=n;while(r){if(!/^table-row|inline.*/i.test(t.getStyle(r,"display",1))){x-=r.scrollLeft||0;y-=r.scrollTop||0;}r=r.parentNode;if(r==d.body)break;}return{x:x,y:y};},parseStyle:function(st){var t=this,s=t.settings,o={};if(!st)return o;function compress(p,s,ot){var t,r,b,l;t=o[p+'-top'+s];if(!t)return;r=o[p+'-right'+s];if(t!=r)return;b=o[p+'-bottom'+s];if(r!=b)return;l=o[p+'-left'+s];if(b!=l)return;o[ot]=l;delete o[p+'-top'+s];delete o[p+'-right'+s];delete o[p+'-bottom'+s];delete o[p+'-left'+s];};function compress2(ta,a,b,c){var t;t=o[a];if(!t)return;t=o[b];if(!t)return;t=o[c];if(!t)return;o[ta]=o[a]+' '+o[b]+' '+o[c];delete o[a];delete o[b];delete o[c];};each(st.split(';'),function(v){var sv,ur=[];if(v){v=v.replace(/url\([^\)]+\)/g,function(v){ur.push(v);return'url('+ur.length+')';});v=v.split(':');sv=tinymce.trim(v[1]);sv=sv.replace(/url\(([^\)]+)\)/g,function(a,b){return ur[parseInt(b)-1];});sv=sv.replace(/rgb\([^\)]+\)/g,function(v){return t.toHex(v);});if(s.url_converter){sv=sv.replace(/url\([\'\"]?([^\)\'\"]+)[\'\"]?\)/g,function(x,c){return'url('+t.encode(s.url_converter.call(s.url_converter_scope||t,t.decode(c),'style',null))+')';});}o[tinymce.trim(v[0]).toLowerCase()]=sv;}});compress("border","","border");compress("border","-width","border-width");compress("border","-color","border-color");compress("border","-style","border-style");compress("padding","","padding");compress("margin","","margin");compress2('border','border-width','border-style','border-color');if(isIE){if(o.border=='medium none')o.border='';}return o;},serializeStyle:function(o){var s='';each(o,function(v,k){if(k&&v){switch(k){case'color':case'background-color':v=v.toLowerCase();break;}s+=(s?' ':'')+k+': '+v+';';}});return s;},loadCSS:function(u){var t=this,d=t.doc;if(!u)u='';each(u.split(','),function(u){if(t.files[u])return;t.files[u]=true;t.add(t.select('head')[0],'link',{rel:'stylesheet',href:tinymce._addVer(u)});});},addClass:function(e,c){return this.run(e,function(e){var o;if(!c)return 0;if(this.hasClass(e,c))return e.className;o=this.removeClass(e,c);return e.className=(o!=''?(o+' '):'')+c;});},removeClass:function(e,c){var t=this,re;return t.run(e,function(e){var v;if(t.hasClass(e,c)){if(!re)re=new RegExp("(^|\\s+)"+c+"(\\s+|$)","g");v=e.className.replace(re,' ');return e.className=tinymce.trim(v!=' '?v:'');}return e.className;});},hasClass:function(n,c){n=this.get(n);if(!n||!c)return false;return(' '+n.className+' ').indexOf(' '+c+' ')!==-1;},show:function(e){return this.setStyle(e,'display','block');},hide:function(e){return this.setStyle(e,'display','none');},isHidden:function(e){e=this.get(e);return e.style.display=='none'||this.getStyle(e,'display')=='none';},uniqueId:function(p){return(!p?'mce_':p)+(this.counter++);},setHTML:function(e,h){var t=this;return this.run(e,function(e){var x,i,nl,n,p,x;h=t.processHTML(h);if(isIE){function set(){try{e.innerHTML='<br />'+h;e.removeChild(e.firstChild);}catch(ex){while(e.firstChild)e.firstChild.removeNode();x=t.create('div');x.innerHTML='<br />'+h;each(x.childNodes,function(n,i){if(i)e.appendChild(n);});}};if(t.settings.fix_ie_paragraphs)h=h.replace(/<p><\/p>|<p([^>]+)><\/p>|<p[^\/+]\/>/gi,'<p$1 mce_keep="true">&nbsp;</p>');set();if(t.settings.fix_ie_paragraphs){nl=e.getElementsByTagName("p");for(i=nl.length-1,x=0;i>=0;i--){n=nl[i];if(!n.hasChildNodes()){if(!n.mce_keep){x=1;break;}n.removeAttribute('mce_keep');}}}if(x){h=h.replace(/<p([^>]+)>|<p>/g,'<div$1 mce_tmp="1">');h=h.replace(/<\/p>/g,'</div>');set();if(t.settings.fix_ie_paragraphs){nl=e.getElementsByTagName("DIV");for(i=nl.length-1;i>=0;i--){n=nl[i];if(n.mce_tmp){p=t.doc.createElement('p');n.cloneNode(false).outerHTML.replace(/([a-z0-9\-_]+)=/gi,function(a,b){var v;if(b!=='mce_tmp'){v=n.getAttribute(b);if(!v&&b==='class')v=n.className;p.setAttribute(b,v);}});for(x=0;x<n.childNodes.length;x++)p.appendChild(n.childNodes[x].cloneNode(true));n.swapNode(p);}}}}}else e.innerHTML=h;return h;});},processHTML:function(h){var t=this,s=t.settings;if(!s.process_html)return h;if(tinymce.isGecko){h=h.replace(/<(\/?)strong>|<strong( [^>]+)>/gi,'<$1b$2>');h=h.replace(/<(\/?)em>|<em( [^>]+)>/gi,'<$1i$2>');}else if(isIE)h=h.replace(/&apos;/g,'&#39;');h=h.replace(/<a( )([^>]+)\/>|<a\/>/gi,'<a$1$2></a>');if(s.keep_values){if(h.indexOf('<script')!==-1){h=h.replace(/<script>/g,'<script type="text/javascript">');h=h.replace(/<script(|[^>]+)>(\s*<!--|\/\/\s*<\[CDATA\[)?[\r\n]*/g,'<mce:script$1><!--\n');h=h.replace(/\s*(\/\/\s*-->|\/\/\s*]]>)?<\/script>/g,'\n// --></mce:script>');h=h.replace(/<mce:script(|[^>]+)><!--\n\/\/ --><\/mce:script>/g,'<mce:script$1></mce:script>');}h=h.replace(/<([\w:]+) [^>]*(src|href|style|coords)[^>]*>/gi,function(a,n){function handle(m,b,c){var u=c;if(a.indexOf('mce_'+b)!=-1)return m;if(b=='style'){if(/^(| )(top|left|bottom|right|width|height)/i.test(c))return m;if(s.hex_colors){u=u.replace(/rgb\([^\)]+\)/g,function(v){return t.toHex(v);});}if(s.url_converter){u=u.replace(/url\([\'\"]?([^\)\'\"]+)\)/g,function(x,c){return'url('+t.encode(s.url_converter.call(s.url_converter_scope||t,t.decode(c),b,n))+')';});}}else if(b!='coords'){if(s.url_converter)u=t.encode(s.url_converter.call(s.url_converter_scope||t,t.decode(c),b,n));}return' '+b+'="'+c+'" mce_'+b+'="'+u+'"';};a=a.replace(/ (src|href|style|coords)=[\"]([^\"]+)[\"]/gi,handle);a=a.replace(/ (src|href|style|coords)=[\']([^\']+)[\']/gi,handle);return a.replace(/ (src|href|style|coords)=([^\s\"\'>]+)/gi,handle);});}return h;},getOuterHTML:function(e){var d;e=this.get(e);if(!e)return null;if(isIE)return e.outerHTML;d=(e.ownerDocument||this.doc).createElement("body");d.appendChild(e.cloneNode(true));return d.innerHTML;},setOuterHTML:function(e,h,d){var t=this;return this.run(e,function(e){var n,tp;e=t.get(e);d=d||e.ownerDocument||t.doc;if(isIE&&e.nodeType==1)e.outerHTML=h;else{tp=d.createElement("body");tp.innerHTML=h;n=tp.lastChild;while(n){t.insertAfter(n.cloneNode(true),e);n=n.previousSibling;}t.remove(e);}});},decode:function(s){var e;if(/&[^;]+;/.test(s)){e=this.doc.createElement("div");e.innerHTML=s;return!e.firstChild?s:e.firstChild.nodeValue;}return s;},encode:function(s){return s?(''+s).replace(/[<>&\"]/g,function(c,b){switch(c){case'&':return'&amp;';case'"':return'&quot;';case'<':return'&lt;';case'>':return'&gt;';}return c;}):s;},insertAfter:function(n,r){var t=this;r=t.get(r);return this.run(n,function(n){var p,ns;p=r.parentNode;ns=r.nextSibling;if(ns)p.insertBefore(n,ns);else p.appendChild(n);return n;});},isBlock:function(n){if(n.nodeType&&n.nodeType!==1)return false;n=n.nodeName||n;return/^(H[1-6]|HR|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP)$/.test(n);},replace:function(n,o,k){if(is(o,'array'))n=n.cloneNode(true);return this.run(o,function(o){if(k){each(o.childNodes,function(c){n.appendChild(c.cloneNode(true));});}return o.parentNode.replaceChild(n,o);});},toHex:function(s){var c=/^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(s);function hex(s){s=parseInt(s).toString(16);return s.length>1?s:'0'+s;};if(c){s='#'+hex(c[1])+hex(c[2])+hex(c[3]);return s;}return s;},getClasses:function(){var t=this,cl=[],i,lo={},f=t.settings.class_filter,ov;if(t.classes)return t.classes;function addClasses(s){each(s.imports,function(r){addClasses(r);});each(s.cssRules||s.rules,function(r){switch(r.type||1){case 1:if(r.selectorText){each(r.selectorText.split(','),function(v){v=v.replace(/^\s*|\s*$|^\s\./g,"");if(/\.mce/.test(v)||!/\.[\w\-]+$/.test(v))return;ov=v;v=v.replace(/.*\.([a-z0-9_\-]+).*/i,'$1');if(f&&!(v=f(v,ov)))return;if(!lo[v]){cl.push({'class':v});lo[v]=1;}});}break;case 3:addClasses(r.styleSheet);break;}});};try{each(t.doc.styleSheets,addClasses);}catch(ex){}if(cl.length>0)t.classes=cl;return cl;},run:function(e,f,s){var t=this,o;if(t.doc&&typeof(e)==='string')e=t.doc.getElementById(e);if(!e)return false;s=s||this;if(!e.nodeType&&(e.length||e.length===0)){o=[];each(e,function(e,i){if(e){if(typeof(e)=='string')e=t.doc.getElementById(e);o.push(f.call(s,e,i));}});return o;}return f.call(s,e);},getAttribs:function(n){var o;n=this.get(n);if(!n)return[];if(isIE){o=[];if(n.nodeName=='OBJECT')return n.attributes;n.cloneNode(false).outerHTML.replace(/([a-z0-9\:\-_]+)=/gi,function(a,b){o.push({specified:1,nodeName:b});});return o;}return n.attributes;},destroy:function(s){var t=this;t.win=t.doc=t.root=null;if(!s)tinymce.removeUnload(t.destroy);}});tinymce.DOM=new tinymce.dom.DOMUtils(document,{process_html:0});})();(function(){var each=tinymce.each,DOM=tinymce.DOM,isIE=tinymce.isIE,isWebKit=tinymce.isWebKit,Event;tinymce.create('static tinymce.dom.Event',{inits:[],events:[],add:function(o,n,f,s){var cb,t=this,el=t.events,r;if(o&&o instanceof Array){r=[];each(o,function(o){o=DOM.get(o);r.push(t.add(o,n,f,s));});return r;}o=DOM.get(o);if(!o)return;cb=function(e){e=e||window.event;if(e&&!e.target&&isIE)e.target=e.srcElement;if(!s)return f(e);return f.call(s,e);};if(n=='unload'){tinymce.unloads.unshift({func:cb});return cb;}if(n=='init'){if(t.domLoaded)cb();else t.inits.push(cb);return cb;}el.push({obj:o,name:n,func:f,cfunc:cb,scope:s});t._add(o,n,cb);return f;},remove:function(o,n,f){var t=this,a=t.events,s=false,r;if(o&&o instanceof Array){r=[];each(o,function(o){o=DOM.get(o);r.push(t.remove(o,n,f));});return r;}o=DOM.get(o);each(a,function(e,i){if(e.obj==o&&e.name==n&&(!f||(e.func==f||e.cfunc==f))){a.splice(i,1);t._remove(o,n,e.cfunc);s=true;return false;}});return s;},clear:function(o){var t=this,a=t.events,i,e;if(o){o=DOM.get(o);for(i=a.length-1;i>=0;i--){e=a[i];if(e.obj===o){t._remove(e.obj,e.name,e.cfunc);e.obj=e.cfunc=null;a.splice(i,1);}}}},cancel:function(e){if(!e)return false;this.stop(e);return this.prevent(e);},stop:function(e){if(e.stopPropagation)e.stopPropagation();else e.cancelBubble=true;return false;},prevent:function(e){if(e.preventDefault)e.preventDefault();else e.returnValue=false;return false;},_unload:function(){var t=Event;each(t.events,function(e,i){t._remove(e.obj,e.name,e.cfunc);e.obj=e.cfunc=null;});t.events=[];t=null;},_add:function(o,n,f){if(o.attachEvent)o.attachEvent('on'+n,f);else if(o.addEventListener)o.addEventListener(n,f,false);else o['on'+n]=f;},_remove:function(o,n,f){if(o){try{if(o.detachEvent)o.detachEvent('on'+n,f);else if(o.removeEventListener)o.removeEventListener(n,f,false);else o['on'+n]=null;}catch(ex){}}},_pageInit:function(){var e=Event;e._remove(window,'DOMContentLoaded',e._pageInit);e.domLoaded=true;each(e.inits,function(c){c();});e.inits=[];},_wait:function(){var t;if(window.tinyMCE_GZ&&tinyMCE_GZ.loaded)return;if(isIE&&document.location.protocol!='https:'){document.write('<script id=__ie_onload defer src=\'javascript:""\';><\/script>');DOM.get("__ie_onload").onreadystatechange=function(){if(this.readyState=="complete"){Event._pageInit();DOM.get("__ie_onload").onreadystatechange=null;}};}else{Event._add(window,'DOMContentLoaded',Event._pageInit,Event);if(isIE||isWebKit){t=setInterval(function(){if(/loaded|complete/.test(document.readyState)){clearInterval(t);Event._pageInit();}},10);}}}});Event=tinymce.dom.Event;Event._wait();tinymce.addUnload(Event._unload);})();(function(){var each=tinymce.each;tinymce.create('tinymce.dom.Element',{Element:function(id,s){var t=this,dom,el;s=s||{};t.id=id;t.dom=dom=s.dom||tinymce.DOM;t.settings=s;if(!tinymce.isIE)el=t.dom.get(t.id);each(['getPos','getRect','getParent','add','setStyle','getStyle','setStyles','setAttrib','setAttribs','getAttrib','addClass','removeClass','hasClass','getOuterHTML','setOuterHTML','remove','show','hide','isHidden','setHTML','get'],function(k){t[k]=function(){var a=arguments,o;if(tinymce.isOpera){a=[id];each(arguments,function(v){a.push(v);});}else Array.prototype.unshift.call(a,el||id);o=dom[k].apply(dom,a);t.update(k);return o;};});},on:function(n,f,s){return tinymce.dom.Event.add(this.id,n,f,s);},getXY:function(){return{x:parseInt(this.getStyle('left')),y:parseInt(this.getStyle('top'))};},getSize:function(){var n=this.dom.get(this.id);return{w:parseInt(this.getStyle('width')||n.clientWidth),h:parseInt(this.getStyle('height')||n.clientHeight)};},moveTo:function(x,y){this.setStyles({left:x,top:y});},moveBy:function(x,y){var p=this.getXY();this.moveTo(p.x+x,p.y+y);},resizeTo:function(w,h){this.setStyles({width:w,height:h});},resizeBy:function(w,h){var s=this.getSize();this.resizeTo(s.w+w,s.h+h);},update:function(k){var t=this,b,dom=t.dom;if(tinymce.isIE6&&t.settings.blocker){k=k||'';if(k.indexOf('get')===0||k.indexOf('has')===0||k.indexOf('is')===0)return;if(k=='remove'){dom.remove(t.blocker);return;}if(!t.blocker){t.blocker=dom.uniqueId();b=dom.add(t.settings.container||dom.getRoot(),'iframe',{id:t.blocker,style:'position:absolute;',frameBorder:0,src:'javascript:""'});dom.setStyle(b,'opacity',0);}else b=dom.get(t.blocker);dom.setStyle(b,'left',t.getStyle('left',1));dom.setStyle(b,'top',t.getStyle('top',1));dom.setStyle(b,'width',t.getStyle('width',1));dom.setStyle(b,'height',t.getStyle('height',1));dom.setStyle(b,'display',t.getStyle('display',1));dom.setStyle(b,'zIndex',parseInt(t.getStyle('zIndex',1)||0)-1);}}});})();(function(){var is=tinymce.is,isIE=tinymce.isIE,each=tinymce.each;tinymce.create('tinymce.dom.Selection',{Selection:function(dom,win,serializer){var t=this;t.dom=dom;t.win=win;t.serializer=serializer;tinymce.addUnload(t.destroy,t);},getContent:function(s){var t=this,r=t.getRng(),e=t.dom.create("body"),se=t.getSel(),wb,wa,n;s=s||{};wb=wa='';s.get=true;s.format=s.format||'html';if(s.format=='text')return t.isCollapsed()?'':(r.text||(se.toString?se.toString():''));if(r.cloneContents){n=r.cloneContents();if(n)e.appendChild(n);}else if(is(r.item)||is(r.htmlText))e.innerHTML=r.item?r.item(0).outerHTML:r.htmlText;else e.innerHTML=r.toString();if(/^\s/.test(e.innerHTML))wb=' ';if(/\s+$/.test(e.innerHTML))wa=' ';s.getInner=true;return t.isCollapsed()?'':wb+t.serializer.serialize(e,s)+wa;},setContent:function(h,s){var t=this,r=t.getRng(),d;s=s||{format:'html'};s.set=true;h=t.dom.processHTML(h);if(r.insertNode){d=t.win.document;if(tinymce.isGecko&&h.indexOf('<')==-1){r.deleteContents();r.insertNode(t.getRng().createContextualFragment(h+'<span id="__caret">_</span>'));t.select(t.dom.get('__caret'));t.getRng().deleteContents();return;}try{if(d.queryCommandEnabled('InsertHTML'))return d.execCommand('InsertHTML',false,h);}catch(ex){r.deleteContents();r.insertNode(t.getRng().createContextualFragment(h));}}else{if(r.item)r.item(0).outerHTML=h;else r.pasteHTML(h);}},getStart:function(){var t=this,r=t.getRng(),e;if(isIE){if(r.item)return r.item(0);r=r.duplicate();r.collapse(1);e=r.parentElement();if(e.nodeName=='BODY')return e.firstChild;return e;}else{e=r.startContainer;if(e.nodeName=='BODY')return e.firstChild;return t.dom.getParent(e,function(n){return n.nodeType==1;});}},getEnd:function(){var t=this,r=t.getRng(),e;if(isIE){if(r.item)return r.item(0);r=r.duplicate();r.collapse(0);e=r.parentElement();if(e.nodeName=='BODY')return e.lastChild;return e;}else{e=r.endContainer;if(e.nodeName=='BODY')return e.lastChild;return t.dom.getParent(e,function(n){return n.nodeType==1;});}},getBookmark:function(si){var t=this,r=t.getRng(),tr,sx,sy,vp=t.dom.getViewPort(t.win),e,sp,bp,le,c=-0xFFFFFF,s,ro=t.dom.getRoot(),wb=0,wa=0,nv;sx=vp.x;sy=vp.y;if(si=='simple')return{rng:r,scrollX:sx,scrollY:sy};if(isIE){if(r.item){e=r.item(0);each(t.dom.select(e.nodeName),function(n,i){if(e==n){sp=i;return false;}});return{tag:e.nodeName,index:sp,scrollX:sx,scrollY:sy};}tr=t.dom.doc.body.createTextRange();tr.moveToElementText(ro);tr.collapse(true);bp=Math.abs(tr.move('character',c));tr=r.duplicate();tr.collapse(true);sp=Math.abs(tr.move('character',c));tr=r.duplicate();tr.collapse(false);le=Math.abs(tr.move('character',c))-sp;return{start:sp-bp,length:le,scrollX:sx,scrollY:sy};}e=t.getNode();s=t.getSel();if(!s)return null;if(e&&e.nodeName=='IMG'){return{scrollX:sx,scrollY:sy};}function getPos(r,sn,en){var w=t.dom.doc.createTreeWalker(r,NodeFilter.SHOW_TEXT,null,false),n,p=0,d={};while((n=w.nextNode())!=null){if(n==sn)d.start=p;if(n==en){d.end=p;return d;}p+=tinymce.trim(n.nodeValue||'').length;}return null;};if(s.anchorNode==s.focusNode&&s.anchorOffset==s.focusOffset){e=getPos(ro,s.anchorNode,s.focusNode);if(!e)return{scrollX:sx,scrollY:sy};(s.anchorNode.nodeValue||'').replace(/^\s+/,function(a){wb=a.length;});return{start:Math.max(e.start+s.anchorOffset-wb,0),end:Math.max(e.end+s.focusOffset-wb,0),scrollX:sx,scrollY:sy,beg:s.anchorOffset-wb==0};}else{e=getPos(ro,r.startContainer,r.endContainer);(r.startContainer.nodeValue||'').replace(/^\s+/,function(a){wb=a.length;});(r.endContainer.nodeValue||'').replace(/^\s+/,function(a){wa=a.length;});if(!e)return{scrollX:sx,scrollY:sy};return{start:Math.max(e.start+r.startOffset-wb,0),end:Math.max(e.end+r.endOffset-wa,0),scrollX:sx,scrollY:sy,beg:r.startOffset-wb==0};}},moveToBookmark:function(b){var t=this,r=t.getRng(),s=t.getSel(),ro=t.dom.getRoot(),sd,nvl,nv;function getPos(r,sp,ep){var w=t.dom.doc.createTreeWalker(r,NodeFilter.SHOW_TEXT,null,false),n,p=0,d={},o,v,wa,wb;while((n=w.nextNode())!=null){wa=wb=0;nv=n.nodeValue||'';nv.replace(/^\s+[^\s]/,function(a){wb=a.length-1;});nv.replace(/[^\s]\s+$/,function(a){wa=a.length-1;});nvl=tinymce.trim(nv).length;p+=nvl;if(p>=sp&&!d.startNode){o=sp-(p-nvl);if(b.beg&&o>=nvl)continue;d.startNode=n;d.startOffset=o+wb;}if(p>=ep){d.endNode=n;d.endOffset=ep-(p-nvl)+wb;return d;}}return null;};if(!b)return false;t.win.scrollTo(b.scrollX,b.scrollY);if(isIE){if(r=b.rng){try{r.select();}catch(ex){}return true;}t.win.focus();if(b.tag){r=ro.createControlRange();each(t.dom.select(b.tag),function(n,i){if(i==b.index)r.addElement(n);});}else{try{if(b.start<0)return true;r=s.createRange();r.moveToElementText(ro);r.collapse(true);r.moveStart('character',b.start);r.moveEnd('character',b.length);}catch(ex2){return true;}}try{r.select();}catch(ex){}return true;}if(!s)return false;if(b.rng){s.removeAllRanges();s.addRange(b.rng);}else{if(is(b.start)&&is(b.end)){try{sd=getPos(ro,b.start,b.end);if(sd){r=t.dom.doc.createRange();r.setStart(sd.startNode,sd.startOffset);r.setEnd(sd.endNode,sd.endOffset);s.removeAllRanges();s.addRange(r);}if(!tinymce.isOpera)t.win.focus();}catch(ex){}}}},select:function(n,c){var t=this,r=t.getRng(),s=t.getSel(),b,fn,ln,d=t.win.document;function first(n){return n?d.createTreeWalker(n,NodeFilter.SHOW_TEXT,null,false).nextNode():null;};function last(n){var c,o,w;if(!n)return null;w=d.createTreeWalker(n,NodeFilter.SHOW_TEXT,null,false);while(c=w.nextNode())o=c;return o;};if(isIE){try{b=d.body;if(/^(IMG|TABLE)$/.test(n.nodeName)){r=b.createControlRange();r.addElement(n);}else{r=b.createTextRange();r.moveToElementText(n);}r.select();}catch(ex){}}else{if(c){fn=first(n);ln=last(n);if(fn&&ln){r=d.createRange();r.setStart(fn,0);r.setEnd(ln,ln.nodeValue.length);}else r.selectNode(n);}else r.selectNode(n);t.setRng(r);}return n;},isCollapsed:function(){var t=this,r=t.getRng(),s=t.getSel();if(!r||r.item)return false;return!s||r.boundingWidth==0||s.isCollapsed;},collapse:function(b){var t=this,r=t.getRng(),n;if(r.item){n=r.item(0);r=this.win.document.body.createTextRange();r.moveToElementText(n);}r.collapse(!!b);t.setRng(r);},getSel:function(){var t=this,w=this.win;return w.getSelection?w.getSelection():w.document.selection;},getRng:function(){var t=this,s=t.getSel(),r;try{if(s)r=s.rangeCount>0?s.getRangeAt(0):(s.createRange?s.createRange():t.win.document.createRange());}catch(ex){}if(!r)r=isIE?t.win.document.body.createTextRange():t.win.document.createRange();return r;},setRng:function(r){var s;if(!isIE){s=this.getSel();if(s){s.removeAllRanges();s.addRange(r);}}else{try{r.select();}catch(ex){}}},setNode:function(n){var t=this;t.setContent(t.dom.getOuterHTML(n));return n;},getNode:function(){var t=this,r=t.getRng(),s=t.getSel(),e;if(!isIE){if(!r)return t.dom.getRoot();e=r.commonAncestorContainer;if(!r.collapsed){if(r.startContainer==r.endContainer||(tinymce.isWebKit&&r.startContainer==r.endContainer.parentNode)){if(r.startOffset-r.endOffset<2||tinymce.isWebKit){if(r.startContainer.hasChildNodes())e=r.startContainer.childNodes[r.startOffset];}}}return t.dom.getParent(e,function(n){return n.nodeType==1;});}return r.item?r.item(0):r.parentElement();},destroy:function(s){var t=this;t.win=null;if(!s)tinymce.removeUnload(t.destroy);}});})();(function(){tinymce.create('tinymce.dom.XMLWriter',{node:null,XMLWriter:function(s){function getXML(){var i=document.implementation;if(!i||!i.createDocument){try{return new ActiveXObject('MSXML2.DOMDocument');}catch(ex){}try{return new ActiveXObject('Microsoft.XmlDom');}catch(ex){}}else return i.createDocument('','',null);};this.doc=getXML();this.valid=tinymce.isOpera||tinymce.isWebKit;this.reset();},reset:function(){var t=this,d=t.doc;if(d.firstChild)d.removeChild(d.firstChild);t.node=d.appendChild(d.createElement("html"));},writeStartElement:function(n){var t=this;t.node=t.node.appendChild(t.doc.createElement(n));},writeAttribute:function(n,v){if(this.valid)v=v.replace(/>/g,'%MCGT%');this.node.setAttribute(n,v);},writeEndElement:function(){this.node=this.node.parentNode;},writeFullEndElement:function(){var t=this,n=t.node;n.appendChild(t.doc.createTextNode(""));t.node=n.parentNode;},writeText:function(v){if(this.valid)v=v.replace(/>/g,'%MCGT%');this.node.appendChild(this.doc.createTextNode(v));},writeCDATA:function(v){this.node.appendChild(this.doc.createCDATA(v));},writeComment:function(v){this.node.appendChild(this.doc.createComment(v.replace(/\-\-/g,' ')));},getContent:function(){var h;h=this.doc.xml||new XMLSerializer().serializeToString(this.doc);h=h.replace(/<\?[^?]+\?>|<html>|<\/html>|<html\/>|<!DOCTYPE[^>]+>/g,'');h=h.replace(/ ?\/>/g,' />');if(this.valid)h=h.replace(/\%MCGT%/g,'&gt;');return h;}});})();(function(){tinymce.create('tinymce.dom.StringWriter',{str:null,tags:null,count:0,settings:null,indent:null,StringWriter:function(s){this.settings=tinymce.extend({indent_char:' ',indentation:1},s);this.reset();},reset:function(){this.indent='';this.str="";this.tags=[];this.count=0;},writeStartElement:function(n){this._writeAttributesEnd();this.writeRaw('<'+n);this.tags.push(n);this.inAttr=true;this.count++;this.elementCount=this.count;},writeAttribute:function(n,v){var t=this;t.writeRaw(" "+t.encode(n)+'="'+t.encode(v)+'"');},writeEndElement:function(){var n;if(this.tags.length>0){n=this.tags.pop();if(this._writeAttributesEnd(1))this.writeRaw('</'+n+'>');if(this.settings.indentation>0)this.writeRaw('\n');}},writeFullEndElement:function(){if(this.tags.length>0){this._writeAttributesEnd();this.writeRaw('</'+this.tags.pop()+'>');if(this.settings.indentation>0)this.writeRaw('\n');}},writeText:function(v){this._writeAttributesEnd();this.writeRaw(this.encode(v));this.count++;},writeCDATA:function(v){this._writeAttributesEnd();this.writeRaw('<![CDATA['+v+']]>');this.count++;},writeComment:function(v){this._writeAttributesEnd();this.writeRaw('<!-- '+v+'-->');this.count++;},writeRaw:function(v){this.str+=v;},encode:function(s){return s.replace(/[<>&"]/g,function(v){switch(v){case'<':return'&lt;';case'>':return'&gt;';case'&':return'&amp;';case'"':return'&quot;';}return v;});},getContent:function(){return this.str;},_writeAttributesEnd:function(s){if(!this.inAttr)return;this.inAttr=false;if(s&&this.elementCount==this.count){this.writeRaw(' />');return false;}this.writeRaw('>');return true;}});})();(function(){var extend=tinymce.extend,each=tinymce.each,Dispatcher=tinymce.util.Dispatcher,isIE=tinymce.isIE,isGecko=tinymce.isGecko;function getIEAtts(n){var o=[];if(n.nodeName=='OBJECT')return n.attributes;n.cloneNode(false).outerHTML.replace(/([a-z0-9\:\-_]+)=/gi,function(a,b){o.push({specified:1,nodeName:b});});return o;};function wildcardToRE(s){return s.replace(/([?+*])/g,'.$1');};tinymce.create('tinymce.dom.Serializer',{Serializer:function(s){var t=this;t.key=0;t.onPreProcess=new Dispatcher(t);t.onPostProcess=new Dispatcher(t);if(tinymce.relaxedDomain&&tinymce.isGecko){t.writer=new tinymce.dom.StringWriter();}else{try{t.writer=new tinymce.dom.XMLWriter();}catch(ex){t.writer=new tinymce.dom.StringWriter();}}t.settings=s=extend({dom:tinymce.DOM,valid_nodes:0,node_filter:0,attr_filter:0,invalid_attrs:/^(mce_|_moz_)/,closed:/(br|hr|input|meta|img|link|param)/,entity_encoding:'named',entities:'160,nbsp,161,iexcl,162,cent,163,pound,164,curren,165,yen,166,brvbar,167,sect,168,uml,169,copy,170,ordf,171,laquo,172,not,173,shy,174,reg,175,macr,176,deg,177,plusmn,178,sup2,179,sup3,180,acute,181,micro,182,para,183,middot,184,cedil,185,sup1,186,ordm,187,raquo,188,frac14,189,frac12,190,frac34,191,iquest,192,Agrave,193,Aacute,194,Acirc,195,Atilde,196,Auml,197,Aring,198,AElig,199,Ccedil,200,Egrave,201,Eacute,202,Ecirc,203,Euml,204,Igrave,205,Iacute,206,Icirc,207,Iuml,208,ETH,209,Ntilde,210,Ograve,211,Oacute,212,Ocirc,213,Otilde,214,Ouml,215,times,216,Oslash,217,Ugrave,218,Uacute,219,Ucirc,220,Uuml,221,Yacute,222,THORN,223,szlig,224,agrave,225,aacute,226,acirc,227,atilde,228,auml,229,aring,230,aelig,231,ccedil,232,egrave,233,eacute,234,ecirc,235,euml,236,igrave,237,iacute,238,icirc,239,iuml,240,eth,241,ntilde,242,ograve,243,oacute,244,ocirc,245,otilde,246,ouml,247,divide,248,oslash,249,ugrave,250,uacute,251,ucirc,252,uuml,253,yacute,254,thorn,255,yuml,402,fnof,913,Alpha,914,Beta,915,Gamma,916,Delta,917,Epsilon,918,Zeta,919,Eta,920,Theta,921,Iota,922,Kappa,923,Lambda,924,Mu,925,Nu,926,Xi,927,Omicron,928,Pi,929,Rho,931,Sigma,932,Tau,933,Upsilon,934,Phi,935,Chi,936,Psi,937,Omega,945,alpha,946,beta,947,gamma,948,delta,949,epsilon,950,zeta,951,eta,952,theta,953,iota,954,kappa,955,lambda,956,mu,957,nu,958,xi,959,omicron,960,pi,961,rho,962,sigmaf,963,sigma,964,tau,965,upsilon,966,phi,967,chi,968,psi,969,omega,977,thetasym,978,upsih,982,piv,8226,bull,8230,hellip,8242,prime,8243,Prime,8254,oline,8260,frasl,8472,weierp,8465,image,8476,real,8482,trade,8501,alefsym,8592,larr,8593,uarr,8594,rarr,8595,darr,8596,harr,8629,crarr,8656,lArr,8657,uArr,8658,rArr,8659,dArr,8660,hArr,8704,forall,8706,part,8707,exist,8709,empty,8711,nabla,8712,isin,8713,notin,8715,ni,8719,prod,8721,sum,8722,minus,8727,lowast,8730,radic,8733,prop,8734,infin,8736,ang,8743,and,8744,or,8745,cap,8746,cup,8747,int,8756,there4,8764,sim,8773,cong,8776,asymp,8800,ne,8801,equiv,8804,le,8805,ge,8834,sub,8835,sup,8836,nsub,8838,sube,8839,supe,8853,oplus,8855,otimes,8869,perp,8901,sdot,8968,lceil,8969,rceil,8970,lfloor,8971,rfloor,9001,lang,9002,rang,9674,loz,9824,spades,9827,clubs,9829,hearts,9830,diams,338,OElig,339,oelig,352,Scaron,353,scaron,376,Yuml,710,circ,732,tilde,8194,ensp,8195,emsp,8201,thinsp,8204,zwnj,8205,zwj,8206,lrm,8207,rlm,8211,ndash,8212,mdash,8216,lsquo,8217,rsquo,8218,sbquo,8220,ldquo,8221,rdquo,8222,bdquo,8224,dagger,8225,Dagger,8240,permil,8249,lsaquo,8250,rsaquo,8364,euro',valid_elements:'*[*]',extended_valid_elements:0,valid_child_elements:0,invalid_elements:0,fix_table_elements:0,fix_list_elements:true,fix_content_duplication:true,convert_fonts_to_spans:false,font_size_classes:0,font_size_style_values:0,apply_source_formatting:0,indent_mode:'simple',indent_char:'\t',indent_levels:1,remove_linebreaks:1},s);t.dom=s.dom;if(s.fix_list_elements){t.onPreProcess.add(function(se,o){var nl,x,a=['ol','ul'],i,n,p,r=/^(OL|UL)$/,np;function prevNode(e,n){var a=n.split(','),i;while((e=e.previousSibling)!=null){for(i=0;i<a.length;i++){if(e.nodeName==a[i])return e;}}return null;};for(x=0;x<a.length;x++){nl=t.dom.select(a[x],o.node);for(i=0;i<nl.length;i++){n=nl[i];p=n.parentNode;if(r.test(p.nodeName)){np=prevNode(n,'LI');if(!np){np=t.dom.create('li');np.innerHTML='&nbsp;';np.appendChild(n);p.insertBefore(np,p.firstChild);}else np.appendChild(n);}}}});}if(s.fix_table_elements){t.onPreProcess.add(function(se,o){each(t.dom.select('table',o.node),function(e){var pa=t.dom.getParent(e,'H1,H2,H3,H4,H5,H6,P'),pa2,n,tm,pl=[],i,ns;if(pa){pa2=pa.cloneNode(false);pl.push(e);for(n=e;n=n.parentNode;){pl.push(n);if(n==pa)break;}tm=pa2;for(i=pl.length-1;i>=0;i--){if(i==pl.length-1){while(ns=pl[i-1].nextSibling)tm.appendChild(ns.parentNode.removeChild(ns));}else{n=pl[i].cloneNode(false);if(i!=0){while(ns=pl[i-1].nextSibling)n.appendChild(ns.parentNode.removeChild(ns));}tm=tm.appendChild(n);}}e=t.dom.insertAfter(e.parentNode.removeChild(e),pa);t.dom.insertAfter(e,pa);t.dom.insertAfter(pa2,e);}});});}},setEntities:function(s){var t=this,a,i,l={},re='',v;if(t.entityLookup)return;a=s.split(',');for(i=0;i<a.length;i+=2){v=a[i];if(v==34||v==38||v==60||v==62)continue;l[String.fromCharCode(a[i])]=a[i+1];v=parseInt(a[i]).toString(16);re+='\\u'+'0000'.substring(v.length)+v;}if(!re){t.settings.entity_encoding='raw';return;}t.entitiesRE=new RegExp('['+re+']','g');t.entityLookup=l;},setValidChildRules:function(s){this.childRules=null;this.addValidChildRules(s);},addValidChildRules:function(s){var t=this,inst,intr,bloc;if(!s)return;inst='A|BR|SPAN|BDO|MAP|OBJECT|IMG|TT|I|B|BIG|SMALL|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|#text|#comment';intr='A|BR|SPAN|BDO|OBJECT|APPLET|IMG|MAP|IFRAME|TT|I|B|U|S|STRIKE|BIG|SMALL|FONT|BASEFONT|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|INPUT|SELECT|TEXTAREA|LABEL|BUTTON|#text|#comment';bloc='H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP';each(s.split(','),function(s){var p=s.split(/\[|\]/),re;s='';each(p[1].split('|'),function(v){if(s)s+='|';switch(v){case'%itrans':v=intr;break;case'%itrans_na':v=intr.substring(2);break;case'%istrict':v=inst;break;case'%istrict_na':v=inst.substring(2);break;case'%btrans':v=bloc;break;case'%bstrict':v=bloc;break;}s+=v;});re=new RegExp('^('+s.toLowerCase()+')$','i');each(p[0].split('/'),function(s){t.childRules=t.childRules||{};t.childRules[s]=re;});});s='';each(t.childRules,function(v,k){if(s)s+='|';s+=k;});t.parentElementsRE=new RegExp('^('+s.toLowerCase()+')$','i');},setRules:function(s){var t=this;t._setup();t.rules={};t.wildRules=[];t.validElements={};return t.addRules(s);},addRules:function(s){var t=this,dr;if(!s)return;t._setup();each(s.split(','),function(s){var p=s.split(/\[|\]/),tn=p[0].split('/'),ra,at,wat,va=[];if(dr)at=tinymce.extend([],dr.attribs);if(p.length>1){each(p[1].split('|'),function(s){var ar={},i;at=at||[];s=s.replace(/::/g,'~');s=/^([!\-])?([\w*.?~_\-]+|)([=:<])?(.+)?$/.exec(s);s[2]=s[2].replace(/~/g,':');if(s[1]=='!'){ra=ra||[];ra.push(s[2]);}if(s[1]=='-'){for(i=0;i<at.length;i++){if(at[i].name==s[2]){at.splice(i,1);return;}}}switch(s[3]){case'=':ar.defaultVal=s[4]||'';break;case':':ar.forcedVal=s[4];break;case'<':ar.validVals=s[4].split('?');break;}if(/[*.?]/.test(s[2])){wat=wat||[];ar.nameRE=new RegExp('^'+wildcardToRE(s[2])+'$');wat.push(ar);}else{ar.name=s[2];at.push(ar);}va.push(s[2]);});}each(tn,function(s,i){var pr=s.charAt(0),x=1,ru={};if(dr){if(dr.noEmpty)ru.noEmpty=dr.noEmpty;if(dr.fullEnd)ru.fullEnd=dr.fullEnd;if(dr.padd)ru.padd=dr.padd;}switch(pr){case'-':ru.noEmpty=true;break;case'+':ru.fullEnd=true;break;case'#':ru.padd=true;break;default:x=0;}tn[i]=s=s.substring(x);t.validElements[s]=1;if(/[*.?]/.test(tn[0])){ru.nameRE=new RegExp('^'+wildcardToRE(tn[0])+'$');t.wildRules=t.wildRules||{};t.wildRules.push(ru);}else{ru.name=tn[0];if(tn[0]=='@')dr=ru;t.rules[s]=ru;}ru.attribs=at;if(ra)ru.requiredAttribs=ra;if(wat){s='';each(va,function(v){if(s)s+='|';s+='('+wildcardToRE(v)+')';});ru.validAttribsRE=new RegExp('^'+s.toLowerCase()+'$');ru.wildAttribs=wat;}});});s='';each(t.validElements,function(v,k){if(s)s+='|';if(k!='@')s+=k;});t.validElementsRE=new RegExp('^('+wildcardToRE(s.toLowerCase())+')$');},findRule:function(n){var t=this,rl=t.rules,i,r;t._setup();r=rl[n];if(r)return r;rl=t.wildRules;for(i=0;i<rl.length;i++){if(rl[i].nameRE.test(n))return rl[i];}return null;},findAttribRule:function(ru,n){var i,wa=ru.wildAttribs;for(i=0;i<wa.length;i++){if(wa[i].nameRE.test(n))return wa[i];}return null;},serialize:function(n,o){var h,t=this;t._setup();o=o||{};o.format=o.format||'html';t.processObj=o;n=n.cloneNode(true);t.key=''+(parseInt(t.key)+1);if(!o.no_events){o.node=n;t.onPreProcess.dispatch(t,o);}t.writer.reset();t._serializeNode(n,o.getInner);o.content=t.writer.getContent();if(!o.no_events)t.onPostProcess.dispatch(t,o);t._postProcess(o);o.node=null;return tinymce.trim(o.content);},_postProcess:function(o){var t=this,s=t.settings,h=o.content,sc=[],p;if(o.format=='html'){p=t._protect({content:h,patterns:[{pattern:/(<script[^>]*>)(.*?)(<\/script>)/g},{pattern:/(<style[^>]*>)(.*?)(<\/style>)/g},{pattern:/(<pre[^>]*>)(.*?)(<\/pre>)/g,encode:1}]});h=p.content;if(s.entity_encoding!=='raw')h=t._encode(h);if(!o.set){h=h.replace(/<p>\s+<\/p>|<p([^>]+)>\s+<\/p>/g,s.entity_encoding=='numeric'?'<p$1>&#160;</p>':'<p$1>&nbsp;</p>');if(s.remove_linebreaks){h=h.replace(/\r?\n|\r/g,' ');h=h.replace(/(<[^>]+>)\s+/g,'$1 ');h=h.replace(/\s+(<\/[^>]+>)/g,' $1');h=h.replace(/<(p|h[1-6]|blockquote|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object) ([^>]+)>\s+/g,'<$1 $2>');h=h.replace(/<(p|h[1-6]|blockquote|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>\s+/g,'<$1>');h=h.replace(/\s+<\/(p|h[1-6]|blockquote|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>/g,'</$1>');}if(s.apply_source_formatting&&s.indent_mode=='simple'){h=h.replace(/<(\/?)(ul|hr|table|meta|link|tbody|tr|object|body|head|html|map)(|[^>]+)>\s*/g,'\n<$1$2$3>\n');h=h.replace(/\s*<(p|h[1-6]|blockquote|div|title|style|pre|script|td|li|area)(|[^>]+)>/g,'\n<$1$2>');h=h.replace(/<\/(p|h[1-6]|blockquote|div|title|style|pre|script|td|li)>\s*/g,'</$1>\n');h=h.replace(/\n\n/g,'\n');}}h=t._unprotect(h,p);if(s.entity_encoding=='raw')h=h.replace(/<p>&nbsp;<\/p>|<p([^>]+)>&nbsp;<\/p>/g,'<p$1>\u00a0</p>');}o.content=h;},_serializeNode:function(n,inn){var t=this,s=t.settings,w=t.writer,hc,el,cn,i,l,a,at,no,v,nn,ru,ar,iv;if(!s.node_filter||s.node_filter(n)){switch(n.nodeType){case 1:if(n.hasAttribute?n.hasAttribute('mce_bogus'):n.getAttribute('mce_bogus'))return;iv=false;hc=n.hasChildNodes();nn=n.getAttribute('mce_name')||n.nodeName.toLowerCase();if(isIE){if(n.scopeName!=='HTML'&&n.scopeName!=='html')nn=n.scopeName+':'+nn;}if(nn.indexOf('mce:')===0)nn=nn.substring(4);if(!t.validElementsRE.test(nn)||(t.invalidElementsRE&&t.invalidElementsRE.test(nn))||inn){iv=true;break;}if(isIE){if(s.fix_content_duplication){if(n.mce_serialized==t.key)return;n.mce_serialized=t.key;}if(nn.charAt(0)=='/')nn=nn.substring(1);}else if(isGecko){if(n.nodeName==='BR'&&n.getAttribute('type')=='_moz')return;}if(t.childRules){if(t.parentElementsRE.test(t.elementName)){if(!t.childRules[t.elementName].test(nn)){iv=true;break;}}t.elementName=nn;}ru=t.findRule(nn);nn=ru.name||nn;if((!hc&&ru.noEmpty)||(isIE&&!nn)){iv=true;break;}if(ru.requiredAttribs){a=ru.requiredAttribs;for(i=a.length-1;i>=0;i--){if(this.dom.getAttrib(n,a[i])!=='')break;}if(i==-1){iv=true;break;}}w.writeStartElement(nn);if(ru.attribs){for(i=0,at=ru.attribs,l=at.length;i<l;i++){a=at[i];v=t._getAttrib(n,a);if(v!==null)w.writeAttribute(a.name,v);}}if(ru.validAttribsRE){at=isIE?getIEAtts(n):n.attributes;for(i=at.length-1;i>-1;i--){no=at[i];if(no.specified){a=no.nodeName.toLowerCase();if(s.invalid_attrs.test(a)||!ru.validAttribsRE.test(a))continue;ar=t.findAttribRule(ru,a);v=t._getAttrib(n,ar,a);if(v!==null)w.writeAttribute(a,v);}}}if(!hc&&ru.padd)w.writeText('\u00a0');break;case 3:if(t.childRules&&t.parentElementsRE.test(t.elementName)){if(!t.childRules[t.elementName].test(n.nodeName))return;}return w.writeText(n.nodeValue);case 4:return w.writeCDATA(n.nodeValue);case 8:return w.writeComment(n.nodeValue);}}else if(n.nodeType==1)hc=n.hasChildNodes();if(hc){cn=n.firstChild;while(cn){t._serializeNode(cn);t.elementName=nn;cn=cn.nextSibling;}}if(!iv){if(hc||!s.closed.test(nn))w.writeFullEndElement();else w.writeEndElement();}},_protect:function(o){var t=this;o.items=o.items||[];function enc(s){return s.replace(/[\r\n\\]/g,function(c){if(c==='\n')return'\\n';else if(c==='\\')return'\\\\';return'\\r';});};function dec(s){return s.replace(/\\[\\rn]/g,function(c){if(c==='\\n')return'\n';else if(c==='\\\\')return'\\';return'\r';});};each(o.patterns,function(p){o.content=dec(enc(o.content).replace(p.pattern,function(x,a,b,c){b=dec(b);if(p.encode)b=t._encode(b);o.items.push(b);return a+'<!--mce:'+(o.items.length-1)+'-->'+c;}));});return o;},_unprotect:function(h,o){h=h.replace(/\<!--mce:([0-9]+)--\>/g,function(a,b){return o.items[parseInt(b)];});o.items=[];return h;},_encode:function(h){var t=this,s=t.settings,l;if(s.entity_encoding!=='raw'){if(s.entity_encoding.indexOf('named')!=-1){t.setEntities(s.entities);l=t.entityLookup;h=h.replace(t.entitiesRE,function(a){var v;if(v=l[a])a='&'+v+';';return a;});}if(s.entity_encoding.indexOf('numeric')!=-1){h=h.replace(/[\u007E-\uFFFF]/g,function(a){return'&#'+a.charCodeAt(0)+';';});}}return h;},_setup:function(){var t=this,s=this.settings;if(t.done)return;t.done=1;t.setRules(s.valid_elements);t.addRules(s.extended_valid_elements);t.addValidChildRules(s.valid_child_elements);if(s.invalid_elements)t.invalidElementsRE=new RegExp('^('+wildcardToRE(s.invalid_elements.replace(',','|').toLowerCase())+')$');if(s.attrib_value_filter)t.attribValueFilter=s.attribValueFilter;},_getAttrib:function(n,a,na){var i,v;na=na||a.name;if(a.forcedVal&&(v=a.forcedVal)){if(v==='{$uid}')return this.dom.uniqueId();return v;}v=this.dom.getAttrib(n,na);switch(na){case'rowspan':case'colspan':if(v=='1')v='';break;}if(this.attribValueFilter)v=this.attribValueFilter(na,v,n);if(a.validVals){for(i=a.validVals.length-1;i>=0;i--){if(v==a.validVals[i])break;}if(i==-1)return null;}if(v===''&&typeof(a.defaultVal)!='undefined'){v=a.defaultVal;if(v==='{$uid}')return this.dom.uniqueId();return v;}else{if(na=='class'&&this.processObj.get)v=v.replace(/\s?mceItem\w+\s?/g,'');}if(v==='')return null;return v;}});})();(function(){var each=tinymce.each;tinymce.create('tinymce.dom.ScriptLoader',{ScriptLoader:function(s){this.settings=s||{};this.queue=[];this.lookup={};},isDone:function(u){return this.lookup[u]?this.lookup[u].state==2:0;},markDone:function(u){this.lookup[u]={state:2,url:u};},add:function(u,cb,s,pr){var t=this,lo=t.lookup,o;if(o=lo[u]){if(cb&&o.state==2)cb.call(s||this);return o;}o={state:0,url:u,func:cb,scope:s||this};if(pr)t.queue.unshift(o);else t.queue.push(o);lo[u]=o;return o;},load:function(u,cb,s){var t=this,o;if(o=t.lookup[u]){if(cb&&o.state==2)cb.call(s||t);return o;}function loadScript(u){if(tinymce.dom.Event.domLoaded||t.settings.strict_mode){tinymce.util.XHR.send({url:tinymce._addVer(u),error:t.settings.error,async:false,success:function(co){t.eval(co);}});}else document.write('<script type="text/javascript" src="'+tinymce._addVer(u)+'"></script>');};if(!tinymce.is(u,'string')){each(u,function(u){loadScript(u);});if(cb)cb.call(s||t);}else{loadScript(u);if(cb)cb.call(s||t);}},loadQueue:function(cb,s){var t=this;if(!t.queueLoading){t.queueLoading=1;t.queueCallbacks=[];t.loadScripts(t.queue,function(){t.queueLoading=0;if(cb)cb.call(s||t);each(t.queueCallbacks,function(o){o.func.call(o.scope);});});}else if(cb)t.queueCallbacks.push({func:cb,scope:s||t});},eval:function(co){var w=window;if(!w.execScript){try{eval.call(w,co);}catch(ex){eval(co,w);}}else w.execScript(co);},loadScripts:function(sc,cb,s){var t=this,lo=t.lookup;function done(o){o.state=2;if(o.func)o.func.call(o.scope||t);};function allDone(){var l;l=sc.length;each(sc,function(o){o=lo[o.url];if(o.state===2){done(o);l--;}else load(o);});if(l===0&&cb){cb.call(s||t);cb=0;}};function load(o){if(o.state>0)return;o.state=1;tinymce.util.XHR.send({url:o.url,error:t.settings.error,success:function(co){t.eval(co);done(o);allDone();}});};each(sc,function(o){var u=o.url;if(!lo[u]){lo[u]=o;t.queue.push(o);}else o=lo[u];if(o.state>0)return;if(!tinymce.dom.Event.domLoaded&&!t.settings.strict_mode){var ix,ol='';if(cb||o.func){o.state=1;ix=tinymce.dom.ScriptLoader._addOnLoad(function(){done(o);allDone();});if(tinymce.isIE)ol=' onreadystatechange="';else ol=' onload="';ol+='tinymce.dom.ScriptLoader._onLoad(this,\''+u+'\','+ix+');"';}document.write('<script type="text/javascript" src="'+tinymce._addVer(u)+'"'+ol+'></script>');if(!o.func)done(o);}else load(o);});allDone();},'static':{_addOnLoad:function(f){var t=this;t._funcs=t._funcs||[];t._funcs.push(f);return t._funcs.length-1;},_onLoad:function(e,u,ix){if(!tinymce.isIE||e.readyState=='complete')this._funcs[ix].call(this);}}});tinymce.ScriptLoader=new tinymce.dom.ScriptLoader();})();(function(){var DOM=tinymce.DOM,is=tinymce.is;tinymce.create('tinymce.ui.Control',{Control:function(id,s){this.id=id;this.settings=s=s||{};this.rendered=false;this.onRender=new tinymce.util.Dispatcher(this);this.classPrefix='';this.scope=s.scope||this;this.disabled=0;this.active=0;},setDisabled:function(s){var e;if(s!=this.disabled){e=DOM.get(this.id);if(e&&this.settings.unavailable_prefix){if(s){this.prevTitle=e.title;e.title=this.settings.unavailable_prefix+": "+e.title;}else e.title=this.prevTitle;}this.setState('Disabled',s);this.setState('Enabled',!s);this.disabled=s;}},isDisabled:function(){return this.disabled;},setActive:function(s){if(s!=this.active){this.setState('Active',s);this.active=s;}},isActive:function(){return this.active;},setState:function(c,s){var n=DOM.get(this.id);c=this.classPrefix+c;if(s)DOM.addClass(n,c);else DOM.removeClass(n,c);},isRendered:function(){return this.rendered;},renderHTML:function(){},renderTo:function(n){DOM.setHTML(n,this.renderHTML());},postRender:function(){var t=this,b;if(is(t.disabled)){b=t.disabled;t.disabled=-1;t.setDisabled(b);}if(is(t.active)){b=t.active;t.active=-1;t.setActive(b);}},remove:function(){DOM.remove(this.id);this.destroy();},destroy:function(){tinymce.dom.Event.clear(this.id);}});})();tinymce.create('tinymce.ui.Container:tinymce.ui.Control',{Container:function(id,s){this.parent(id,s);this.controls=[];this.lookup={};},add:function(c){this.lookup[c.id]=c;this.controls.push(c);return c;},get:function(n){return this.lookup[n];}});tinymce.create('tinymce.ui.Separator:tinymce.ui.Control',{Separator:function(id,s){this.parent(id,s);this.classPrefix='mceSeparator';},renderHTML:function(){return tinymce.DOM.createHTML('span',{'class':this.classPrefix});}});(function(){var is=tinymce.is,DOM=tinymce.DOM,each=tinymce.each,walk=tinymce.walk;tinymce.create('tinymce.ui.MenuItem:tinymce.ui.Control',{MenuItem:function(id,s){this.parent(id,s);this.classPrefix='mceMenuItem';},setSelected:function(s){this.setState('Selected',s);this.selected=s;},isSelected:function(){return this.selected;},postRender:function(){var t=this;t.parent();if(is(t.selected))t.setSelected(t.selected);}});})();(function(){var is=tinymce.is,DOM=tinymce.DOM,each=tinymce.each,walk=tinymce.walk;tinymce.create('tinymce.ui.Menu:tinymce.ui.MenuItem',{Menu:function(id,s){var t=this;t.parent(id,s);t.items={};t.collapsed=false;t.menuCount=0;t.onAddItem=new tinymce.util.Dispatcher(this);},expand:function(d){var t=this;if(d){walk(t,function(o){if(o.expand)o.expand();},'items',t);}t.collapsed=false;},collapse:function(d){var t=this;if(d){walk(t,function(o){if(o.collapse)o.collapse();},'items',t);}t.collapsed=true;},isCollapsed:function(){return this.collapsed;},add:function(o){if(!o.settings)o=new tinymce.ui.MenuItem(o.id||DOM.uniqueId(),o);this.onAddItem.dispatch(this,o);return this.items[o.id]=o;},addSeparator:function(){return this.add({separator:true});},addMenu:function(o){if(!o.collapse)o=this.createMenu(o);this.menuCount++;return this.add(o);},hasMenus:function(){return this.menuCount!==0;},remove:function(o){delete this.items[o.id];},removeAll:function(){var t=this;walk(t,function(o){if(o.removeAll)o.removeAll();else o.remove();o.destroy();},'items',t);t.items={};},createMenu:function(o){var m=new tinymce.ui.Menu(o.id||DOM.uniqueId(),o);m.onAddItem.add(this.onAddItem.dispatch,this.onAddItem);return m;}});})();(function(){var is=tinymce.is,DOM=tinymce.DOM,each=tinymce.each,Event=tinymce.dom.Event,Element=tinymce.dom.Element;tinymce.create('tinymce.ui.DropMenu:tinymce.ui.Menu',{DropMenu:function(id,s){s=s||{};s.container=s.container||DOM.doc.body;s.offset_x=s.offset_x||0;s.offset_y=s.offset_y||0;s.vp_offset_x=s.vp_offset_x||0;s.vp_offset_y=s.vp_offset_y||0;if(is(s.icons)&&!s.icons)s['class']+=' mceNoIcons';this.parent(id,s);this.onShowMenu=new tinymce.util.Dispatcher(this);this.onHideMenu=new tinymce.util.Dispatcher(this);this.classPrefix='mceMenu';this.fixIE=tinymce.isIE&&DOM.win.top!=DOM.win;},createMenu:function(s){var t=this,cs=t.settings,m;s.container=s.container||cs.container;s.parent=t;s.constrain=s.constrain||cs.constrain;s['class']=s['class']||cs['class'];s.vp_offset_x=s.vp_offset_x||cs.vp_offset_x;s.vp_offset_y=s.vp_offset_y||cs.vp_offset_y;m=new tinymce.ui.DropMenu(s.id||DOM.uniqueId(),s);m.onAddItem.add(t.onAddItem.dispatch,t.onAddItem);return m;},update:function(){var t=this,s=t.settings,tb=DOM.get('menu_'+t.id+'_tbl'),co=DOM.get('menu_'+t.id+'_co'),tw,th;tw=s.max_width?Math.min(tb.clientWidth,s.max_width):tb.clientWidth;th=s.max_height?Math.min(tb.clientHeight,s.max_height):tb.clientHeight;if(!DOM.boxModel)t.element.setStyles({width:tw+2,height:th+2});else t.element.setStyles({width:tw,height:th});if(s.max_width)DOM.setStyle(co,'width',tw);if(s.max_height){DOM.setStyle(co,'height',th);if(tb.clientHeight<s.max_height)DOM.setStyle(co,'overflow','hidden');}},showMenu:function(x,y,px){var t=this,s=t.settings,co,vp=DOM.getViewPort(),w,h,mx,my,ot=2,dm,tb,cp=t.classPrefix;t.collapse(1);if(t.isMenuVisible)return;if(!t.rendered){co=DOM.add(t.settings.container,t.renderNode());each(t.items,function(o){o.postRender();});t.element=new Element('menu_'+t.id,{blocker:1,container:s.container});}else co=DOM.get('menu_'+t.id);if(!tinymce.isOpera)DOM.setStyles(co,{left:-0xFFFF,top:-0xFFFF});DOM.show(co);t.update();x+=s.offset_x||0;y+=s.offset_y||0;vp.w-=4;vp.h-=4;if(s.constrain){w=co.clientWidth-ot;h=co.clientHeight-ot;mx=vp.x+vp.w;my=vp.y+vp.h;if((x+s.vp_offset_x+w)>mx)x=px?px-w:Math.max(0,(mx-s.vp_offset_x)-w);if((y+s.vp_offset_y+h)>my)y=Math.max(0,(my-s.vp_offset_y)-h);}DOM.setStyles(co,{left:x,top:y});t.element.update();t.isMenuVisible=1;t.mouseClickFunc=Event.add(co,t.fixIE?'mousedown':'click',function(e){var m;e=e.target;if(e&&(e=DOM.getParent(e,'TR'))&&!DOM.hasClass(e,cp+'ItemSub')){m=t.items[e.id];if(m.isDisabled())return;dm=t;DOM.win.setTimeout(function(){while(dm){if(dm.hideMenu)dm.hideMenu();dm=dm.settings.parent;}},0);if(m.settings.onclick)m.settings.onclick(e);return Event.cancel(e);}});if(t.hasMenus()){t.mouseOverFunc=Event.add(co,'mouseover',function(e){var m,r,mi;e=e.target;if(e&&(e=DOM.getParent(e,'TR'))){m=t.items[e.id];if(t.lastMenu)t.lastMenu.collapse(1);if(m.isDisabled())return;if(e&&DOM.hasClass(e,cp+'ItemSub')){r=DOM.getRect(e);m.showMenu((r.x+r.w-ot),r.y-ot,r.x);t.lastMenu=m;DOM.addClass(DOM.get(m.id).firstChild,cp+'ItemActive');}}});}t.onShowMenu.dispatch(t);if(s.keyboard_focus){Event.add(co,'keydown',t._keyHandler,t);DOM.select('a','menu_'+t.id)[0].focus();}},hideMenu:function(c){var t=this,co=DOM.get('menu_'+t.id),e;if(!t.isMenuVisible)return;Event.remove(co,'mouseover',t.mouseOverFunc);Event.remove(co,t.fixIE?'mousedown':'click',t.mouseClickFunc);Event.remove(co,'keydown',t._keyHandler);DOM.hide(co);t.isMenuVisible=0;if(!c)t.collapse(1);if(t.element)t.element.hide();if(e=DOM.get(t.id))DOM.removeClass(e.firstChild,t.classPrefix+'ItemActive');t.onHideMenu.dispatch(t);},add:function(o){var t=this,co;o=t.parent(o);if(t.isRendered&&(co=DOM.get('menu_'+t.id)))t._add(DOM.select('tbody',co)[0],o);return o;},collapse:function(d){this.parent(d);this.hideMenu(1);},remove:function(o){DOM.remove(o.id);this.destroy();return this.parent(o);},destroy:function(){var t=this,co=DOM.get('menu_'+t.id);Event.remove(co,'mouseover',t.mouseOverFunc);Event.remove(co,'click',t.mouseClickFunc);if(t.element)t.element.remove();DOM.remove(co);},renderNode:function(){var t=this,s=t.settings,n,tb,co,w;w=DOM.create('div',{id:'menu_'+t.id,'class':s['class'],'style':'position:absolute;left:0;top:0;z-index:200000'});co=DOM.add(w,'div',{id:'menu_'+t.id+'_co','class':t.classPrefix+(s['class']?' '+s['class']:'')});t.element=new Element('menu_'+t.id,{blocker:1,container:s.container});if(s.menu_line)DOM.add(co,'span',{'class':t.classPrefix+'Line'});n=DOM.add(co,'table',{id:'menu_'+t.id+'_tbl',border:0,cellPadding:0,cellSpacing:0});tb=DOM.add(n,'tbody');each(t.items,function(o){t._add(tb,o);});t.rendered=true;return w;},_keyHandler:function(e){if(e.keyCode==27)this.hideMenu();},_add:function(tb,o){var n,s=o.settings,a,ro,it,cp=this.classPrefix;if(s.separator){ro=DOM.add(tb,'tr',{id:o.id,'class':cp+'ItemSeparator'});DOM.add(ro,'td',{'class':cp+'ItemSeparator'});if(n=ro.previousSibling)DOM.addClass(n,'mceLast');return;}n=ro=DOM.add(tb,'tr',{id:o.id,'class':cp+'Item '+cp+'ItemEnabled'});n=it=DOM.add(n,'td');n=a=DOM.add(n,'a',{href:'javascript:;',onclick:"return false;",onmousedown:'return false;'});DOM.addClass(it,s['class']);DOM.add(n,'span',{'class':'mceIcon'+(s.icon?' mce_'+s.icon:'')});n=DOM.add(n,s.element||'span',{'class':'mceText',title:o.settings.title},o.settings.title);if(o.settings.style)DOM.setAttrib(n,'style',o.settings.style);if(tb.childNodes.length==1)DOM.addClass(ro,'mceFirst');if((n=ro.previousSibling)&&DOM.hasClass(n,cp+'ItemSeparator'))DOM.addClass(ro,'mceFirst');if(o.collapse)DOM.addClass(ro,cp+'ItemSub');if(n=ro.previousSibling)DOM.removeClass(n,'mceLast');DOM.addClass(ro,'mceLast');}});})();(function(){var DOM=tinymce.DOM;tinymce.create('tinymce.ui.Button:tinymce.ui.Control',{Button:function(id,s){this.parent(id,s);this.classPrefix='mceButton';},renderHTML:function(){var cp=this.classPrefix,s=this.settings,h,l;l=DOM.encode(s.label||'');h='<a id="'+this.id+'" href="javascript:;" class="'+cp+' '+cp+'Enabled '+s['class']+(l?' '+cp+'Labeled':'')+'" onmousedown="return false;" onclick="return false;" title="'+DOM.encode(s.title)+'">';if(s.image)h+='<img class="mceIcon" src="'+s.image+'" />'+l+'</a>';else h+='<span class="mceIcon '+s['class']+'"></span>'+(l?'<span class="'+cp+'Label">'+l+'</span>':'')+'</a>';return h;},postRender:function(){var t=this,s=t.settings;tinymce.dom.Event.add(t.id,'click',function(e){if(!t.isDisabled())return s.onclick.call(s.scope,e);});}});})();(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,each=tinymce.each,Dispatcher=tinymce.util.Dispatcher;tinymce.create('tinymce.ui.ListBox:tinymce.ui.Control',{ListBox:function(id,s){var t=this;t.parent(id,s);t.items=[];t.onChange=new Dispatcher(t);t.onPostRender=new Dispatcher(t);t.onAdd=new Dispatcher(t);t.onRenderMenu=new tinymce.util.Dispatcher(this);t.classPrefix='mceListBox';},select:function(v){var t=this,e,fv;if(v!=t.selectedValue){e=DOM.get(t.id+'_text');t.selectedValue=v;each(t.items,function(o){if(o.value==v){DOM.setHTML(e,DOM.encode(o.title));fv=1;return false;}});if(!fv){DOM.setHTML(e,DOM.encode(t.settings.title));DOM.addClass(e,'mceTitle');e=0;return;}else DOM.removeClass(e,'mceTitle');}e=0;},add:function(n,v,o){var t=this;o=o||{};o=tinymce.extend(o,{title:n,value:v});t.items.push(o);t.onAdd.dispatch(t,o);},getLength:function(){return this.items.length;},renderHTML:function(){var h='',t=this,s=t.settings,cp=t.classPrefix;h='<table id="'+t.id+'" cellpadding="0" cellspacing="0" class="'+cp+' '+cp+'Enabled'+(s['class']?(' '+s['class']):'')+'"><tbody><tr>';h+='<td>'+DOM.createHTML('a',{id:t.id+'_text',href:'javascript:;','class':'mceText',onclick:"return false;",onmousedown:'return false;'},DOM.encode(t.settings.title))+'</td>';h+='<td>'+DOM.createHTML('a',{id:t.id+'_open',tabindex:-1,href:'javascript:;','class':'mceOpen',onclick:"return false;",onmousedown:'return false;'},'<span></span>')+'</td>';h+='</tr></tbody></table>';return h;},showMenu:function(){var t=this,p1,p2,e=DOM.get(this.id),m;if(t.isDisabled()||t.items.length==0)return;if(t.menu&&t.menu.isMenuVisible)return t.hideMenu();if(!t.isMenuRendered){t.renderMenu();t.isMenuRendered=true;}p1=DOM.getPos(this.settings.menu_container);p2=DOM.getPos(e);m=t.menu;m.settings.offset_x=p2.x;m.settings.offset_y=p2.y;m.settings.keyboard_focus=t._focused;if(t.oldID)m.items[t.oldID].setSelected(0);each(t.items,function(o){if(o.value===t.selectedValue){m.items[o.id].setSelected(1);t.oldID=o.id;}});m.showMenu(0,e.clientHeight);Event.add(DOM.doc,'mousedown',t.hideMenu,t);DOM.addClass(t.id,t.classPrefix+'Selected');},hideMenu:function(e){var t=this;if(e&&e.type=="mousedown"&&(e.target.id==t.id+'_text'||e.target.id==t.id+'_open'))return;if(!e||!DOM.getParent(e.target,function(n){return DOM.hasClass(n,'mceMenu');})){DOM.removeClass(t.id,t.classPrefix+'Selected');Event.remove(DOM.doc,'mousedown',t.hideMenu,t);if(t.menu)t.menu.hideMenu();}},renderMenu:function(){var t=this,m;m=t.settings.control_manager.createDropMenu(t.id+'_menu',{menu_line:1,'class':t.classPrefix+'Menu mceNoIcons',max_width:150,max_height:150});m.onHideMenu.add(t.hideMenu,t);m.add({title:t.settings.title,'class':'mceMenuItemTitle'}).setDisabled(1);each(t.items,function(o){o.id=DOM.uniqueId();o.onclick=function(){if(t.settings.onselect(o.value)!==false)t.select(o.value);};m.add(o);});t.onRenderMenu.dispatch(t,m);t.menu=m;},postRender:function(){var t=this,cp=t.classPrefix;Event.add(t.id,'click',t.showMenu,t);Event.add(t.id+'_text','focus',function(){t._focused=1;});Event.add(t.id+'_text','blur',function(){t._focused=0;});if(tinymce.isIE6||!DOM.boxModel){Event.add(t.id,'mouseover',function(){if(!DOM.hasClass(t.id,cp+'Disabled'))DOM.addClass(t.id,cp+'Hover');});Event.add(t.id,'mouseout',function(){if(!DOM.hasClass(t.id,cp+'Disabled'))DOM.removeClass(t.id,cp+'Hover');});}t.onPostRender.dispatch(t,DOM.get(t.id));},destroy:function(){this.parent();Event.clear(this.id+'_text');}});})();(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,each=tinymce.each,Dispatcher=tinymce.util.Dispatcher;tinymce.create('tinymce.ui.NativeListBox:tinymce.ui.ListBox',{NativeListBox:function(id,s){this.parent(id,s);this.classPrefix='mceNativeListBox';},setDisabled:function(s){DOM.get(this.id).disabled=s;},isDisabled:function(){return DOM.get(this.id).disabled;},select:function(v){var e=DOM.get(this.id),ol=e.options;v=''+(v||'');e.selectedIndex=0;each(ol,function(o,i){if(o.value==v){e.selectedIndex=i;return false;}});},add:function(n,v,a){var o,t=this;a=a||{};a.value=v;if(t.isRendered())DOM.add(DOM.get(this.id),'option',a,n);o={title:n,value:v,attribs:a};t.items.push(o);t.onAdd.dispatch(t,o);},getLength:function(){return DOM.get(this.id).options.length-1;},renderHTML:function(){var h,t=this;h=DOM.createHTML('option',{value:''},'-- '+t.settings.title+' --');each(t.items,function(it){h+=DOM.createHTML('option',{value:it.value},it.title);});h=DOM.createHTML('select',{id:t.id,'class':'mceNativeListBox'},h);return h;},postRender:function(){var t=this,ch;t.rendered=true;function onChange(e){var v=e.target.options[e.target.selectedIndex].value;t.onChange.dispatch(t,v);if(t.settings.onselect)t.settings.onselect(v);};Event.add(t.id,'change',onChange);Event.add(t.id,'keydown',function(e){var bf;Event.remove(t.id,'change',ch);bf=Event.add(t.id,'blur',function(){Event.add(t.id,'change',onChange);Event.remove(t.id,'blur',bf);});if(e.keyCode==13||e.keyCode==32){onChange(e);return Event.cancel(e);}});t.onPostRender.dispatch(t,DOM.get(t.id));}});})();(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,each=tinymce.each;tinymce.create('tinymce.ui.MenuButton:tinymce.ui.Button',{MenuButton:function(id,s){this.parent(id,s);this.onRenderMenu=new tinymce.util.Dispatcher(this);s.menu_container=s.menu_container||DOM.doc.body;},showMenu:function(){var t=this,p1,p2,e=DOM.get(t.id),m;if(t.isDisabled())return;if(!t.isMenuRendered){t.renderMenu();t.isMenuRendered=true;}if(t.isMenuVisible)return t.hideMenu();p1=DOM.getPos(t.settings.menu_container);p2=DOM.getPos(e);m=t.menu;m.settings.offset_x=p2.x;m.settings.offset_y=p2.y;m.settings.vp_offset_x=p2.x;m.settings.vp_offset_y=p2.y;m.settings.keyboard_focus=t._focused;m.showMenu(0,e.clientHeight);Event.add(DOM.doc,'mousedown',t.hideMenu,t);t.setState('Selected',1);t.isMenuVisible=1;},renderMenu:function(){var t=this,m;m=t.settings.control_manager.createDropMenu(t.id+'_menu',{menu_line:1,'class':this.classPrefix+'Menu',icons:t.settings.icons});m.onHideMenu.add(t.hideMenu,t);t.onRenderMenu.dispatch(t,m);t.menu=m;},hideMenu:function(e){var t=this;if(e&&e.type=="mousedown"&&DOM.getParent(e.target,function(e){return e.id===t.id||e.id===t.id+'_open';}))return;if(!e||!DOM.getParent(e.target,function(n){return DOM.hasClass(n,'mceMenu');})){t.setState('Selected',0);Event.remove(DOM.doc,'mousedown',t.hideMenu,t);if(t.menu)t.menu.hideMenu();}t.isMenuVisible=0;},postRender:function(){var t=this,s=t.settings;Event.add(t.id,'click',function(){if(!t.isDisabled()){if(s.onclick)s.onclick(t.value);t.showMenu();}});}});})();(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,each=tinymce.each;tinymce.create('tinymce.ui.SplitButton:tinymce.ui.MenuButton',{SplitButton:function(id,s){this.parent(id,s);this.classPrefix='mceSplitButton';},renderHTML:function(){var h,t=this,s=t.settings,h1;h='<tbody><tr>';if(s.image)h1=DOM.createHTML('img ',{src:s.image,'class':'mceAction '+s['class']});else h1=DOM.createHTML('span',{'class':'mceAction '+s['class']},'');h+='<td>'+DOM.createHTML('a',{id:t.id+'_action',href:'javascript:;','class':'mceAction '+s['class'],onclick:"return false;",onmousedown:'return false;',title:s.title},h1)+'</td>';h1=DOM.createHTML('span',{'class':'mceOpen '+s['class']});h+='<td>'+DOM.createHTML('a',{id:t.id+'_open',href:'javascript:;','class':'mceOpen '+s['class'],onclick:"return false;",onmousedown:'return false;',title:s.title},h1)+'</td>';h+='</tr></tbody>';return DOM.createHTML('table',{id:t.id,'class':'mceSplitButton mceSplitButtonEnabled '+s['class'],cellpadding:'0',cellspacing:'0',onmousedown:'return false;',title:s.title},h);},postRender:function(){var t=this,s=t.settings;if(s.onclick){Event.add(t.id+'_action','click',function(){if(!t.isDisabled())s.onclick(t.value);});}Event.add(t.id+'_open','click',t.showMenu,t);Event.add(t.id+'_open','focus',function(){t._focused=1;});Event.add(t.id+'_open','blur',function(){t._focused=0;});if(tinymce.isIE6||!DOM.boxModel){Event.add(t.id,'mouseover',function(){if(!DOM.hasClass(t.id,'mceSplitButtonDisabled'))DOM.addClass(t.id,'mceSplitButtonHover');});Event.add(t.id,'mouseout',function(){if(!DOM.hasClass(t.id,'mceSplitButtonDisabled'))DOM.removeClass(t.id,'mceSplitButtonHover');});}},destroy:function(){this.parent();Event.clear(this.id+'_action');Event.clear(this.id+'_open');}});})();(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,is=tinymce.is,each=tinymce.each;tinymce.create('tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton',{ColorSplitButton:function(id,s){var t=this;t.parent(id,s);t.settings=s=tinymce.extend({colors:'000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF',grid_width:8,default_color:'#888888'},t.settings);t.value=s.default_color;},showMenu:function(){var t=this,r,p,e,p2;if(t.isDisabled())return;if(!t.isMenuRendered){t.renderMenu();t.isMenuRendered=true;}if(t.isMenuVisible)return t.hideMenu();e=DOM.get(t.id);DOM.show(t.id+'_menu');DOM.addClass(e,'mceSplitButtonSelected');p2=DOM.getPos(e);DOM.setStyles(t.id+'_menu',{left:p2.x,top:p2.y+e.clientHeight,zIndex:200000});e=0;Event.add(DOM.doc,'mousedown',t.hideMenu,t);if(t._focused){t._keyHandler=Event.add(t.id+'_menu','keydown',function(e){if(e.keyCode==27)t.hideMenu();});DOM.select('a',t.id+'_menu')[0].focus();}t.isMenuVisible=1;},hideMenu:function(e){var t=this;if(e&&e.type=="mousedown"&&DOM.getParent(e.target,function(e){return e.id===t.id+'_open';}))return;if(!e||!DOM.getParent(e.target,function(n){return DOM.hasClass(n,'mceSplitButtonMenu');})){DOM.removeClass(t.id,'mceSplitButtonSelected');Event.remove(DOM.doc,'mousedown',t.hideMenu,t);Event.remove(t.id+'_menu','keydown',t._keyHandler);DOM.hide(t.id+'_menu');}t.isMenuVisible=0;},renderMenu:function(){var t=this,m,i=0,s=t.settings,n,tb,tr,w;w=DOM.add(s.menu_container,'div',{id:t.id+'_menu','class':s['menu_class']+' '+s['class'],style:'position:absolute;left:0;top:-1000px;'});m=DOM.add(w,'div',{'class':s['class']+' mceSplitButtonMenu'});DOM.add(m,'span',{'class':'mceMenuLine'});n=DOM.add(m,'table',{'class':'mceColorSplitMenu'});tb=DOM.add(n,'tbody');i=0;each(is(s.colors,'array')?s.colors:s.colors.split(','),function(c){c=c.replace(/^#/,'');if(!i--){tr=DOM.add(tb,'tr');i=s.grid_width-1;}n=DOM.add(tr,'td');n=DOM.add(n,'a',{href:'javascript:;',style:{backgroundColor:'#'+c},mce_color:'#'+c});});if(s.more_colors_func){n=DOM.add(tb,'tr');n=DOM.add(n,'td',{colspan:s.grid_width,'class':'mceMoreColors'});n=DOM.add(n,'a',{id:t.id+'_more',href:'javascript:;',onclick:'return false;','class':'mceMoreColors'},s.more_colors_title);Event.add(n,'click',function(e){s.more_colors_func.call(s.more_colors_scope||this);return Event.cancel(e);});}DOM.addClass(m,'mceColorSplitMenu');Event.add(t.id+'_menu','click',function(e){var c;e=e.target;if(e.nodeName=='A'&&(c=e.getAttribute('mce_color')))t.setColor(c);});return w;},setColor:function(c){var t=this;DOM.setStyle(t.id+'_preview','backgroundColor',c);t.value=c;t.hideMenu();t.settings.onselect(c);},postRender:function(){var t=this,id=t.id;t.parent();DOM.add(id+'_action','div',{id:id+'_preview','class':'mceColorPreview'});},destroy:function(){this.parent();Event.clear(this.id+'_menu');Event.clear(this.id+'_more');DOM.remove(this.id+'_menu');}});})();tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container',{renderHTML:function(){var t=this,h='',c,co,dom=tinymce.DOM,s=t.settings,i,pr,nx,cl;cl=t.controls;for(i=0;i<cl.length;i++){co=cl[i];pr=cl[i-1];nx=cl[i+1];if(i===0){c='mceToolbarStart';if(co.Button)c+=' mceToolbarStartButton';else if(co.SplitButton)c+=' mceToolbarStartSplitButton';else if(co.ListBox)c+=' mceToolbarStartListBox';h+=dom.createHTML('td',{'class':c},dom.createHTML('span',null,'<!-- IE -->'));}if(pr&&co.ListBox){if(pr.Button||pr.SplitButton)h+=dom.createHTML('td',{'class':'mceToolbarEnd'},dom.createHTML('span',null,'<!-- IE -->'));}if(dom.stdMode)h+='<td style="position: relative">'+co.renderHTML()+'</td>';else h+='<td>'+co.renderHTML()+'</td>';if(nx&&co.ListBox){if(nx.Button||nx.SplitButton)h+=dom.createHTML('td',{'class':'mceToolbarStart'},dom.createHTML('span',null,'<!-- IE -->'));}}c='mceToolbarEnd';if(co.Button)c+=' mceToolbarEndButton';else if(co.SplitButton)c+=' mceToolbarEndSplitButton';else if(co.ListBox)c+=' mceToolbarEndListBox';h+=dom.createHTML('td',{'class':c},dom.createHTML('span',null,'<!-- IE -->'));return dom.createHTML('table',{id:t.id,'class':'mceToolbar'+(s['class']?' '+s['class']:''),cellpadding:'0',cellspacing:'0',align:t.settings.align||''},'<tbody><tr>'+h+'</tr></tbody>');}});(function(){var Dispatcher=tinymce.util.Dispatcher,each=tinymce.each;tinymce.create('tinymce.AddOnManager',{items:[],urls:{},lookup:{},onAdd:new Dispatcher(this),get:function(n){return this.lookup[n];},requireLangPack:function(n){var u,s;if(tinymce.EditorManager.settings){u=this.urls[n]+'/langs/'+tinymce.EditorManager.settings.language+'.js';s=tinymce.EditorManager.settings;if(s){if(!tinymce.dom.Event.domLoaded&&!s.strict_mode)tinymce.ScriptLoader.load(u);else tinymce.ScriptLoader.add(u);}}},add:function(id,o){this.items.push(o);this.lookup[id]=o;this.onAdd.dispatch(this,id,o);return o;},load:function(n,u,cb,s){var t=this;if(t.urls[n])return;if(u.indexOf('/')!=0&&u.indexOf('://')==-1)u=tinymce.baseURL+'/'+u;t.urls[n]=u.substring(0,u.lastIndexOf('/'));tinymce.ScriptLoader.add(u,cb,s);}});tinymce.PluginManager=new tinymce.AddOnManager();tinymce.ThemeManager=new tinymce.AddOnManager();}());(function(){var each=tinymce.each,extend=tinymce.extend,DOM=tinymce.DOM,Event=tinymce.dom.Event,ThemeManager=tinymce.ThemeManager,PluginManager=tinymce.PluginManager,explode=tinymce.explode;tinymce.create('static tinymce.EditorManager',{editors:{},i18n:{},activeEditor:null,preInit:function(){var t=this,lo=window.location;tinymce.documentBaseURL=lo.href.replace(/[\?#].*$/,'').replace(/[\/\\][^\/]+$/,'');if(!/[\/\\]$/.test(tinymce.documentBaseURL))tinymce.documentBaseURL+='/';tinymce.baseURL=new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.baseURL);tinymce.EditorManager.baseURI=new tinymce.util.URI(tinymce.baseURL);if(tinymce.EditorManager.baseURI.host!=lo.hostname&&lo.hostname)document.domain=tinymce.relaxedDomain=lo.hostname.replace(/.*\.(.+\..+)$/,'$1');t.onBeforeUnload=new tinymce.util.Dispatcher(t);Event.add(window,'beforeunload',function(e){t.onBeforeUnload.dispatch(t,e);});},init:function(s){var t=this,pl,sl=tinymce.ScriptLoader,c,e;function execCallback(se,n,s){var f=se[n];if(!f)return;if(tinymce.is(f,'string')){s=f.replace(/\.\w+$/,'');s=s?tinymce.resolve(s):0;f=tinymce.resolve(f);}return f.apply(s||this,Array.prototype.slice.call(arguments,2));};s=extend({theme:"simple",language:"en",strict_loading_mode:document.contentType=='application/xhtml+xml'},s);t.settings=s;if(!Event.domLoaded&&!s.strict_loading_mode){if(s.language)sl.add(tinymce.baseURL+'/langs/'+s.language+'.js');if(s.theme&&s.theme.charAt(0)!='-'&&!ThemeManager.urls[s.theme])ThemeManager.load(s.theme,'themes/'+s.theme+'/editor_template'+tinymce.suffix+'.js');if(s.plugins){pl=explode(s.plugins);if(tinymce.inArray(pl,'compat2x')!=-1)PluginManager.load('compat2x','plugins/compat2x/editor_plugin'+tinymce.suffix+'.js');each(pl,function(v){if(v&&v.charAt(0)!='-'&&!PluginManager.urls[v]){if(!tinymce.isWebKit&&v=='safari')return;PluginManager.load(v,'plugins/'+v+'/editor_plugin'+tinymce.suffix+'.js');}});}sl.loadQueue();}Event.add(document,'init',function(){var l,co;execCallback(s,'onpageload');if(s.browsers){l=false;each(explode(s.browsers),function(v){switch(v){case'ie':case'msie':if(tinymce.isIE)l=true;break;case'gecko':if(tinymce.isGecko)l=true;break;case'safari':case'webkit':if(tinymce.isWebKit)l=true;break;case'opera':if(tinymce.isOpera)l=true;break;}});if(!l)return;}switch(s.mode){case"exact":l=s.elements||'';if(l.length>0){each(explode(l),function(v){if(DOM.get(v))new tinymce.Editor(v,s).render(1);else{c=0;each(document.forms,function(f){each(f.elements,function(e){if(e.name===v){v='mce_editor_'+c;DOM.setAttrib(e,'id',v);new tinymce.Editor(v,s).render(1);}});});}});}break;case"textareas":case"specific_textareas":function hasClass(n,c){return new RegExp('\\b'+c+'\\b','g').test(n.className);};each(DOM.select('textarea'),function(v){if(s.editor_deselector&&hasClass(v,s.editor_deselector))return;if(!s.editor_selector||hasClass(v,s.editor_selector)){e=DOM.get(v.name);if(!v.id&&!e)v.id=v.name;if(!v.id||t.get(v.id))v.id=DOM.uniqueId();new tinymce.Editor(v.id,s).render(1);}});break;}if(s.oninit){l=co=0;each(t.editors,function(ed){co++;if(!ed.initialized){ed.onInit.add(function(){l++;if(l==co)execCallback(s,'oninit');});}else l++;if(l==co)execCallback(s,'oninit');});}});},get:function(id){return this.editors[id];},getInstanceById:function(id){return this.get(id);},add:function(e){this.editors[e.id]=e;this._setActive(e);return e;},remove:function(e){var t=this;if(!t.editors[e.id])return null;delete t.editors[e.id];if(t.activeEditor==e){each(t.editors,function(e){t._setActive(e);return false;});}e.destroy();return e;},execCommand:function(c,u,v){var t=this,ed=t.get(v),w;switch(c){case"mceFocus":ed.focus();return true;case"mceAddEditor":case"mceAddControl":if(!t.get(v))new tinymce.Editor(v,t.settings).render();return true;case"mceAddFrameControl":w=v.window;w.tinyMCE=tinyMCE;w.tinymce=tinymce;tinymce.DOM.doc=w.document;tinymce.DOM.win=w;ed=new tinymce.Editor(v.element_id,v);ed.render();if(tinymce.isIE){function clr(){ed.destroy();w.detachEvent('onunload',clr);w=w.tinyMCE=w.tinymce=null;};w.attachEvent('onunload',clr);}v.page_window=null;return true;case"mceRemoveEditor":case"mceRemoveControl":ed.remove();return true;case'mceToggleEditor':if(!ed){t.execCommand('mceAddControl',0,v);return true;}if(ed.isHidden())ed.show();else ed.hide();return true;}if(t.activeEditor)return t.activeEditor.execCommand(c,u,v);return false;},execInstanceCommand:function(id,c,u,v){var ed=this.get(id);if(ed)return ed.execCommand(c,u,v);return false;},triggerSave:function(){each(this.editors,function(e){e.save();});},addI18n:function(p,o){var lo,i18n=this.i18n;if(!tinymce.is(p,'string')){each(p,function(o,lc){each(o,function(o,g){each(o,function(o,k){if(g==='common')i18n[lc+'.'+k]=o;else i18n[lc+'.'+g+'.'+k]=o;});});});}else{each(o,function(o,k){i18n[p+'.'+k]=o;});}},_setActive:function(e){this.selectedInstance=this.activeEditor=e;}});tinymce.EditorManager.preInit();})();var tinyMCE=window.tinyMCE=tinymce.EditorManager;(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,extend=tinymce.extend,Dispatcher=tinymce.util.Dispatcher;var each=tinymce.each,isGecko=tinymce.isGecko,isIE=tinymce.isIE,isWebKit=tinymce.isWebKit;var is=tinymce.is,ThemeManager=tinymce.ThemeManager,PluginManager=tinymce.PluginManager,EditorManager=tinymce.EditorManager;var inArray=tinymce.inArray,grep=tinymce.grep,explode=tinymce.explode;tinymce.create('tinymce.Editor',{Editor:function(id,s){var t=this;t.id=t.editorId=id;t.execCommands={};t.queryStateCommands={};t.queryValueCommands={};t.plugins={};each(['onPreInit','onBeforeRenderUI','onPostRender','onInit','onRemove','onActivate','onDeactivate','onClick','onEvent','onMouseUp','onMouseDown','onDblClick','onKeyDown','onKeyUp','onKeyPress','onContextMenu','onSubmit','onReset','onPaste','onPreProcess','onPostProcess','onBeforeSetContent','onBeforeGetContent','onSetContent','onGetContent','onLoadContent','onSaveContent','onNodeChange','onChange','onBeforeExecCommand','onExecCommand','onUndo','onRedo','onVisualAid','onSetProgressState'],function(e){t[e]=new Dispatcher(t);});t.settings=s=extend({id:id,language:'en',docs_language:'en',theme:'simple',skin:'default',delta_width:0,delta_height:0,popup_css:'',plugins:'',document_base_url:tinymce.documentBaseURL,add_form_submit_trigger:1,submit_patch:1,add_unload_trigger:1,convert_urls:1,relative_urls:1,remove_script_host:1,table_inline_editing:0,object_resizing:1,cleanup:1,accessibility_focus:1,custom_shortcuts:1,custom_undo_redo_keyboard_shortcuts:1,custom_undo_redo_restore_selection:1,custom_undo_redo:1,doctype:'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">',visual_table_class:'mceItemTable',visual:1,inline_styles:true,convert_fonts_to_spans:true,font_size_style_values:'xx-small,x-small,small,medium,large,x-large,xx-large',apply_source_formatting:1,directionality:'ltr',forced_root_block:'p',valid_elements:'@[id|class|style|title|dir<ltr?rtl|lang|xml::lang|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],a[rel|rev|charset|hreflang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur],strong/b,em/i,strike,u,#p[align],-ol[type|compact],-ul[type|compact],-li,br,img[longdesc|usemap|src|border|alt=|title|hspace|vspace|width|height|align],-sub,-sup,-blockquote,-table[border=0|cellspacing|cellpadding|width|frame|rules|height|align|summary|bgcolor|background|bordercolor],-tr[rowspan|width|height|align|valign|bgcolor|background|bordercolor],tbody,thead,tfoot,#td[colspan|rowspan|width|height|align|valign|bgcolor|background|bordercolor|scope],#th[colspan|rowspan|width|height|align|valign|scope],caption,-div,-span,-code,-pre,address,-h1,-h2,-h3,-h4,-h5,-h6,hr[size|noshade],-font[face|size|color],dd,dl,dt,cite,abbr,acronym,del[datetime|cite],ins[datetime|cite],object[classid|width|height|codebase|*],param[name|value|_value],embed[type|width|height|src|*],script[src|type],map[name],area[shape|coords|href|alt|target],bdo,button,col[align|char|charoff|span|valign|width],colgroup[align|char|charoff|span|valign|width],dfn,fieldset,form[action|accept|accept-charset|enctype|method],input[accept|alt|checked|disabled|maxlength|name|readonly|size|src|type|value],kbd,label[for],legend,noscript,optgroup[label|disabled],option[disabled|label|selected|value],q[cite],samp,select[disabled|multiple|name|size],small,textarea[cols|rows|disabled|name|readonly],tt,var,big',hidden_input:1,padd_empty_editor:1,render_ui:1,init_theme:1,force_p_newlines:1,indentation:'30px'},s);t.documentBaseURI=new tinymce.util.URI(s.document_base_url||tinymce.documentBaseURL,{base_uri:tinyMCE.baseURI});t.baseURI=EditorManager.baseURI;t.execCallback('setup',t);},render:function(nst){var t=this,s=t.settings,id=t.id,sl=tinymce.ScriptLoader;if(!Event.domLoaded){Event.add(document,'init',function(){t.render();});return;}if(!nst){s.strict_loading_mode=1;tinyMCE.settings=s;}if(!t.getElement())return;if(s.strict_loading_mode){sl.settings.strict_mode=s.strict_loading_mode;tinymce.DOM.settings.strict=1;}if(!/TEXTAREA|INPUT/i.test(t.getElement().nodeName)&&s.hidden_input&&DOM.getParent(id,'form'))DOM.insertAfter(DOM.create('input',{type:'hidden',name:id}),id);t.windowManager=new tinymce.WindowManager(t);if(s.encoding=='xml'){t.onGetContent.add(function(ed,o){if(o.get)o.content=DOM.encode(o.content);});}if(s.add_form_submit_trigger){t.onSubmit.addToTop(function(){if(t.initialized){t.save();t.isNotDirty=1;}});}if(s.add_unload_trigger){t._beforeUnload=tinyMCE.onBeforeUnload.add(function(){if(t.initialized&&!t.destroyed&&!t.isHidden())t.save({format:'raw',no_events:true});});}tinymce.addUnload(t.destroy,t);if(s.submit_patch){t.onBeforeRenderUI.add(function(){var n=t.getElement().form;if(!n)return;if(n._mceOldSubmit)return;if(!n.submit.nodeType&&!n.submit.length){t.formElement=n;n._mceOldSubmit=n.submit;n.submit=function(){EditorManager.triggerSave();t.isNotDirty=1;return this._mceOldSubmit(this);};}n=null;});}function loadScripts(){if(s.language)sl.add(tinymce.baseURL+'/langs/'+s.language+'.js');if(s.theme.charAt(0)!='-'&&!ThemeManager.urls[s.theme])ThemeManager.load(s.theme,'themes/'+s.theme+'/editor_template'+tinymce.suffix+'.js');each(explode(s.plugins),function(p){if(p&&p.charAt(0)!='-'&&!PluginManager.urls[p]){if(!isWebKit&&p=='safari')return;PluginManager.load(p,'plugins/'+p+'/editor_plugin'+tinymce.suffix+'.js');}});sl.loadQueue(function(){if(s.ask){function ask(){t.windowManager.confirm(t.getLang('edit_confirm'),function(s){if(s)t.init();else Event.remove(t.id,'focus',ask);});};Event.add(t.id,'focus',ask);return;}if(!t.removed)t.init();});};if(s.plugins.indexOf('compat2x')!=-1){PluginManager.load('compat2x','plugins/compat2x/editor_plugin'+tinymce.suffix+'.js');sl.loadQueue(loadScripts);}else loadScripts();},init:function(){var n,t=this,s=t.settings,w,h,e=t.getElement(),o,ti,u,bi,bc,re;EditorManager.add(t);s.theme=s.theme.replace(/-/,'');o=ThemeManager.get(s.theme);t.theme=new o();if(t.theme.init&&s.init_theme)t.theme.init(t,ThemeManager.urls[s.theme]||tinymce.documentBaseURL.replace(/\/$/,''));each(explode(s.plugins.replace(/\-/g,'')),function(p){var c=PluginManager.get(p),u=PluginManager.urls[p]||tinymce.documentBaseURL.replace(/\/$/,''),po;if(c){po=new c(t,u);t.plugins[p]=po;if(po.init)po.init(t,u);}});if(s.popup_css)s.popup_css=t.documentBaseURI.toAbsolute(s.popup_css);else s.popup_css=t.baseURI.toAbsolute("themes/"+s.theme+"/skins/"+s.skin+"/dialog.css");if(s.popup_css_add)s.popup_css+=','+t.documentBaseURI.toAbsolute(s.popup_css_add);t.controlManager=new tinymce.ControlManager(t);t.undoManager=new tinymce.UndoManager(t);t.undoManager.onAdd.add(function(um,l){return t.onChange.dispatch(t,l,um);});t.undoManager.onUndo.add(function(um,l){return t.onUndo.dispatch(t,l,um);});t.undoManager.onRedo.add(function(um,l){return t.onRedo.dispatch(t,l,um);});if(s.custom_undo_redo){t.onExecCommand.add(function(ed,cmd,ui,val,a){if(cmd!='Undo'&&cmd!='Redo'&&cmd!='mceRepaint'&&(!a||!a.skip_undo))t.undoManager.add();});}t.onExecCommand.add(function(ed,c){if(!/^(FontName|FontSize)$/.test(c))t.nodeChanged();});if(isGecko){function repaint(a,o){if(!o||!o.initial)t.execCommand('mceRepaint');};t.onUndo.add(repaint);t.onRedo.add(repaint);t.onSetContent.add(repaint);}t.onBeforeRenderUI.dispatch(t,t.controlManager);if(s.render_ui){w=s.width||e.style.width||e.clientWidth;h=s.height||e.style.height||e.clientHeight;t.orgDisplay=e.style.display;re=/^[0-9\.]+(|px)$/i;if(re.test(''+w))w=Math.max(parseInt(w)+(o.deltaWidth||0),100);if(re.test(''+h))h=Math.max(parseInt(h)+(o.deltaHeight||0),100);o=t.theme.renderUI({targetNode:e,width:w,height:h,deltaWidth:s.delta_width,deltaHeight:s.delta_height});t.editorContainer=o.editorContainer;}DOM.setStyles(o.sizeContainer||o.editorContainer,{width:w,height:h});h=(o.iframeHeight||h)+((h+'').indexOf('%')==-1?(o.deltaHeight||0):'');if(h<100)h=100;t.iframeHTML=s.doctype+'<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="'+t.documentBaseURI.getURI()+'"></base>';t.iframeHTML+='<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';if(tinymce.relaxedDomain)t.iframeHTML+='<script type="text/javascript">document.domain = "'+tinymce.relaxedDomain+'";</script>';bi=s.body_id||'tinymce';if(bi.indexOf('=')!=-1){bi=t.getParam('body_id','','hash');bi=bi[t.id]||bi;}bc=s.body_class||'';if(bc.indexOf('=')!=-1){bc=t.getParam('body_class','','hash');bc=bc[t.id]||'';}t.iframeHTML+='</head><body id="'+bi+'" class="mceContentBody '+bc+'"></body></html>';if(tinymce.relaxedDomain){if(isIE)u='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinyMCE.get("'+t.id+'");document.write(ed.iframeHTML);document.close();ed.setupIframe();})()';else if(tinymce.isOpera)u='javascript:(function(){document.open();document.domain="'+document.domain+'";document.close();ed.setupIframe();})()';}n=DOM.add(o.iframeContainer,'iframe',{id:t.id+"_ifr",src:u||'javascript:""',frameBorder:'0',style:{width:'100%',height:h}});t.contentAreaContainer=o.iframeContainer;DOM.get(o.editorContainer).style.display=t.orgDisplay;DOM.get(t.id).style.display='none';if(tinymce.isOldWebKit){Event.add(n,'load',t.setupIframe,t);n.src=tinymce.baseURL+'/plugins/safari/blank.htm';}else{if(!isIE||!tinymce.relaxedDomain)t.setupIframe();e=n=o=null;}},setupIframe:function(){var t=this,s=t.settings,e=DOM.get(t.id),d=t.getDoc(),h,b;if(!isIE||!tinymce.relaxedDomain){d.open();d.write(t.iframeHTML);d.close();}if(!isIE){try{d.designMode='On';}catch(ex){}}if(isIE){b=t.getBody();DOM.hide(b);b.contentEditable=true;DOM.show(b);}t.dom=new tinymce.DOM.DOMUtils(t.getDoc(),{keep_values:true,url_converter:t.convertURL,url_converter_scope:t,hex_colors:s.force_hex_style_colors,class_filter:s.class_filter,update_styles:1,fix_ie_paragraphs:1});t.serializer=new tinymce.dom.Serializer({entity_encoding:s.entity_encoding,entities:s.entities,valid_elements:s.verify_html===false?'*[*]':s.valid_elements,extended_valid_elements:s.extended_valid_elements,valid_child_elements:s.valid_child_elements,invalid_elements:s.invalid_elements,fix_table_elements:s.fix_table_elements,fix_list_elements:s.fix_list_elements,fix_content_duplication:s.fix_content_duplication,convert_fonts_to_spans:s.convert_fonts_to_spans,font_size_classes:s.font_size_classes,font_size_style_values:s.font_size_style_values,apply_source_formatting:s.apply_source_formatting,remove_linebreaks:s.remove_linebreaks,dom:t.dom});t.selection=new tinymce.dom.Selection(t.dom,t.getWin(),t.serializer);t.forceBlocks=new tinymce.ForceBlocks(t,{forced_root_block:s.forced_root_block});t.editorCommands=new tinymce.EditorCommands(t);t.serializer.onPreProcess.add(function(se,o){return t.onPreProcess.dispatch(t,o,se);});t.serializer.onPostProcess.add(function(se,o){return t.onPostProcess.dispatch(t,o,se);});t.onPreInit.dispatch(t);if(!s.gecko_spellcheck)t.getBody().spellcheck=0;t._addEvents();t.controlManager.onPostRender.dispatch(t,t.controlManager);t.onPostRender.dispatch(t);if(s.directionality)t.getBody().dir=s.directionality;if(s.nowrap)t.getBody().style.whiteSpace="nowrap";if(s.auto_resize)t.onNodeChange.add(t.resizeToContent,t);if(s.custom_elements){function handleCustom(ed,o){each(explode(s.custom_elements),function(v){var n;if(v.indexOf('~')===0){v=v.substring(1);n='span';}else n='div';o.content=o.content.replace(new RegExp('<('+v+')([^>]*)>','g'),'<'+n+' mce_name="$1"$2>');o.content=o.content.replace(new RegExp('</('+v+')>','g'),'</'+n+'>');});};t.onBeforeSetContent.add(handleCustom);t.onPostProcess.add(function(ed,o){if(o.set)handleCustom(ed,o)});}if(s.handle_node_change_callback){t.onNodeChange.add(function(ed,cm,n){t.execCallback('handle_node_change_callback',t.id,n,-1,-1,true,t.selection.isCollapsed());});}if(s.save_callback){t.onSaveContent.add(function(ed,o){var h=t.execCallback('save_callback',t.id,o.content,t.getBody());if(h)o.content=h;});}if(s.onchange_callback){t.onChange.add(function(ed,l){t.execCallback('onchange_callback',t,l);});}if(s.convert_newlines_to_brs){t.onBeforeSetContent.add(function(ed,o){if(o.initial)o.content=o.content.replace(/\r?\n/g,'<br />');});}if(s.fix_nesting&&isIE){t.onBeforeSetContent.add(function(ed,o){o.content=t._fixNesting(o.content);});}if(s.preformatted){t.onPostProcess.add(function(ed,o){o.content=o.content.replace(/^\s*<pre.*?>/,'');o.content=o.content.replace(/<\/pre>\s*$/,'');if(o.set)o.content='<pre class="mceItemHidden">'+o.content+'</pre>';});}if(s.verify_css_classes){t.serializer.attribValueFilter=function(n,v){var s,cl;if(n=='class'){if(!t.classesRE){cl=t.dom.getClasses();if(cl.length>0){s='';each(cl,function(o){s+=(s?'|':'')+o['class'];});t.classesRE=new RegExp('('+s+')','gi');}}return!t.classesRE||/(\bmceItem\w+\b|\bmceTemp\w+\b)/g.test(v)||t.classesRE.test(v)?v:'';}return v;};}if(s.convert_fonts_to_spans)t._convertFonts();if(s.inline_styles)t._convertInlineElements();if(s.cleanup_callback){t.onBeforeSetContent.add(function(ed,o){o.content=t.execCallback('cleanup_callback','insert_to_editor',o.content,o);});t.onPreProcess.add(function(ed,o){if(o.set)t.execCallback('cleanup_callback','insert_to_editor_dom',o.node,o);if(o.get)t.execCallback('cleanup_callback','get_from_editor_dom',o.node,o);});t.onPostProcess.add(function(ed,o){if(o.set)o.content=t.execCallback('cleanup_callback','insert_to_editor',o.content,o);if(o.get)o.content=t.execCallback('cleanup_callback','get_from_editor',o.content,o);});}if(s.save_callback){t.onGetContent.add(function(ed,o){if(o.save)o.content=t.execCallback('save_callback',t.id,o.content,t.getBody());});}if(s.handle_event_callback){t.onEvent.add(function(ed,e,o){if(t.execCallback('handle_event_callback',e,ed,o)===false)Event.cancel(e);});}t.onSetContent.add(function(){t.addVisual(t.getBody());});if(s.padd_empty_editor){t.onPostProcess.add(function(ed,o){o.content=o.content.replace(/^<p>(&nbsp;|#160;|\s|\u00a0)<\/p>$/,'');});}if(isGecko){try{d.designMode='Off';d.designMode='On';}catch(ex){}}setTimeout(function(){if(t.removed)return;t.load({initial:true,format:(s.cleanup_on_startup?'html':'raw')});t.startContent=t.getContent({format:'raw'});t.undoManager.add({initial:true});t.initialized=true;t.onInit.dispatch(t);t.execCallback('setupcontent_callback',t.id,t.getBody(),t.getDoc());t.execCallback('init_instance_callback',t);t.focus(true);t.nodeChanged({initial:1});if(s.content_css){tinymce.each(explode(s.content_css),function(u){t.dom.loadCSS(t.documentBaseURI.toAbsolute(u));});}if(s.auto_focus){setTimeout(function(){var ed=EditorManager.get(s.auto_focus);ed.selection.select(ed.getBody(),1);ed.selection.collapse(1);ed.getWin().focus();},100);}},1);e=null;},focus:function(sf){var oed,t=this;if(!sf){t.getWin().focus();}if(EditorManager.activeEditor!=t){if((oed=EditorManager.activeEditor)!=null)oed.onDeactivate.dispatch(oed,t);t.onActivate.dispatch(t,oed);}EditorManager._setActive(t);},execCallback:function(n){var t=this,f=t.settings[n],s;if(!f)return;if(t.callbackLookup&&(s=t.callbackLookup[n])){f=s.func;s=s.scope;}if(is(f,'string')){s=f.replace(/\.\w+$/,'');s=s?tinymce.resolve(s):0;f=tinymce.resolve(f);t.callbackLookup=t.callbackLookup||{};t.callbackLookup[n]={func:f,scope:s};}return f.apply(s||t,Array.prototype.slice.call(arguments,1));},translate:function(s){var c=this.settings.language,i18n=EditorManager.i18n;if(!s)return'';return i18n[c+'.'+s]||s.replace(/{\#([^}]+)\}/g,function(a,b){return i18n[c+'.'+b]||'{#'+b+'}';});},getLang:function(n,dv){return EditorManager.i18n[this.settings.language+'.'+n]||(is(dv)?dv:'{#'+n+'}');},getParam:function(n,dv,ty){var tr=tinymce.trim,v=is(this.settings[n])?this.settings[n]:dv,o;if(ty==='hash'){o={};if(is(v,'string')){each(v.indexOf('=')>0?v.split(/[;,](?![^=;,]*(?:[;,]|$))/):v.split(','),function(v){v=v.split('=');if(v.length>1)o[tr(v[0])]=tr(v[1]);else o[tr(v[0])]=tr(v);});}else o=v;return o;}return v;},nodeChanged:function(o){var t=this,s=t.selection,n=s.getNode()||t.getBody();if(t.initialized){t.onNodeChange.dispatch(t,o?o.controlManager||t.controlManager:t.controlManager,isIE&&n.ownerDocument!=t.getDoc()?t.getBody():n,s.isCollapsed(),o);}},addButton:function(n,s){var t=this;t.buttons=t.buttons||{};t.buttons[n]=s;},addCommand:function(n,f,s){this.execCommands[n]={func:f,scope:s||this};},addQueryStateHandler:function(n,f,s){this.queryStateCommands[n]={func:f,scope:s||this};},addQueryValueHandler:function(n,f,s){this.queryValueCommands[n]={func:f,scope:s||this};},addShortcut:function(pa,desc,cmd_func,sc){var t=this,c;if(!t.settings.custom_shortcuts)return false;t.shortcuts=t.shortcuts||{};if(is(cmd_func,'string')){c=cmd_func;cmd_func=function(){t.execCommand(c,false,null);};}if(is(cmd_func,'object')){c=cmd_func;cmd_func=function(){t.execCommand(c[0],c[1],c[2]);};}each(explode(pa),function(pa){var o={func:cmd_func,scope:sc||this,desc:desc,alt:false,ctrl:false,shift:false};each(explode(pa,'+'),function(v){switch(v){case'alt':case'ctrl':case'shift':o[v]=true;break;default:o.charCode=v.charCodeAt(0);o.keyCode=v.toUpperCase().charCodeAt(0);}});t.shortcuts[(o.ctrl?'ctrl':'')+','+(o.alt?'alt':'')+','+(o.shift?'shift':'')+','+o.keyCode]=o;});return true;},execCommand:function(cmd,ui,val,a){var t=this,s=0,o,st;if(!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(cmd)&&(!a||!a.skip_focus))t.focus();o={};t.onBeforeExecCommand.dispatch(t,cmd,ui,val,o);if(o.terminate)return false;if(t.execCallback('execcommand_callback',t.id,t.selection.getNode(),cmd,ui,val)){t.onExecCommand.dispatch(t,cmd,ui,val,a);return true;}if(o=t.execCommands[cmd]){st=o.func.call(o.scope,ui,val);if(st!==true){t.onExecCommand.dispatch(t,cmd,ui,val,a);return st;}}each(t.plugins,function(p){if(p.execCommand&&p.execCommand(cmd,ui,val)){t.onExecCommand.dispatch(t,cmd,ui,val,a);s=1;return false;}});if(s)return true;if(t.theme.execCommand&&t.theme.execCommand(cmd,ui,val)){t.onExecCommand.dispatch(t,cmd,ui,val,a);return true;}if(t.editorCommands.execCommand(cmd,ui,val)){t.onExecCommand.dispatch(t,cmd,ui,val,a);return true;}t.getDoc().execCommand(cmd,ui,val);t.onExecCommand.dispatch(t,cmd,ui,val,a);},queryCommandState:function(c){var t=this,o,s;if(t._isHidden())return;if(o=t.queryStateCommands[c]){s=o.func.call(o.scope);if(s!==true)return s;}o=t.editorCommands.queryCommandState(c);if(o!==-1)return o;try{return this.getDoc().queryCommandState(c);}catch(ex){}},queryCommandValue:function(c){var t=this,o,s;if(t._isHidden())return;if(o=t.queryValueCommands[c]){s=o.func.call(o.scope);if(s!==true)return s;}o=t.editorCommands.queryCommandValue(c);if(is(o))return o;try{return this.getDoc().queryCommandValue(c);}catch(ex){}},show:function(){var t=this;DOM.show(t.getContainer());DOM.hide(t.id);t.load();},hide:function(){var t=this,d=t.getDoc();if(isIE&&d)d.execCommand('SelectAll');t.save();DOM.hide(t.getContainer());DOM.setStyle(t.id,'display',t.orgDisplay);},isHidden:function(){return!DOM.isHidden(this.id);},setProgressState:function(b,ti,o){this.onSetProgressState.dispatch(this,b,ti,o);return b;},resizeToContent:function(){var t=this;DOM.setStyle(t.id+"_ifr",'height',t.getBody().scrollHeight);},load:function(o){var t=this,e=t.getElement(),h;o=o||{};o.load=true;h=t.setContent(is(e.value)?e.value:e.innerHTML,o);o.element=e;if(!o.no_events)t.onLoadContent.dispatch(t,o);o.element=e=null;return h;},save:function(o){var t=this,e=t.getElement(),h,f;if(!t.initialized)return;o=o||{};o.save=true;o.element=e;h=o.content=t.getContent(o);if(!o.no_events)t.onSaveContent.dispatch(t,o);h=o.content;if(!/TEXTAREA|INPUT/i.test(e.nodeName)){e.innerHTML=h;if(f=DOM.getParent(t.id,'form')){each(f.elements,function(e){if(e.name==t.id){e.value=h;return false;}});}}else e.value=h;o.element=e=null;return h;},setContent:function(h,o){var t=this;o=o||{};o.format=o.format||'html';o.set=true;o.content=h;if(!o.no_events)t.onBeforeSetContent.dispatch(t,o);if(!tinymce.isIE&&(h.length===0||/^\s+$/.test(h))){o.content=t.dom.setHTML(t.getBody(),'<br mce_bogus="1" />',1);o.format='raw';}o.content=t.dom.setHTML(t.getBody(),tinymce.trim(o.content));if(o.format!='raw'&&t.settings.cleanup){o.getInner=true;o.content=t.dom.setHTML(t.getBody(),t.serializer.serialize(t.getBody(),o));}if(!o.no_events)t.onSetContent.dispatch(t,o);return o.content;},getContent:function(o){var t=this,h;o=o||{};o.format=o.format||'html';o.get=true;if(!o.no_events)t.onBeforeGetContent.dispatch(t,o);if(o.format!='raw'&&t.settings.cleanup){o.getInner=true;h=t.serializer.serialize(t.getBody(),o);}else h=t.getBody().innerHTML;h=h.replace(/^\s*|\s*$/g,'');o={content:h};t.onGetContent.dispatch(t,o);return o.content;},isDirty:function(){var t=this;return tinymce.trim(t.startContent)!=tinymce.trim(t.getContent({format:'raw',no_events:1}))&&!t.isNotDirty;},getContainer:function(){var t=this;if(!t.container)t.container=DOM.get(t.editorContainer||t.id+'_parent');return t.container;},getContentAreaContainer:function(){return this.contentAreaContainer;},getElement:function(){return DOM.get(this.settings.content_element||this.id);},getWin:function(){var t=this,e;if(!t.contentWindow){e=DOM.get(t.id+"_ifr");if(e)t.contentWindow=e.contentWindow;}return t.contentWindow;},getDoc:function(){var t=this,w;if(!t.contentDocument){w=t.getWin();if(w)t.contentDocument=w.document;}return t.contentDocument;},getBody:function(){return this.bodyElement||this.getDoc().body;},convertURL:function(u,n,e){var t=this,s=t.settings;if(s.urlconverter_callback)return t.execCallback('urlconverter_callback',u,e,true,n);if(!s.convert_urls||(e&&e.nodeName=='LINK')||u.indexOf('file:')===0)return u;if(s.relative_urls)return t.documentBaseURI.toRelative(u);u=t.documentBaseURI.toAbsolute(u,s.remove_script_host);return u;},addVisual:function(e){var t=this,s=t.settings;e=e||t.getBody();if(!is(t.hasVisual))t.hasVisual=s.visual;each(t.dom.select('table,a',e),function(e){var v;switch(e.nodeName){case'TABLE':v=t.dom.getAttrib(e,'border');if(!v||v=='0'){if(t.hasVisual)t.dom.addClass(e,s.visual_table_class);else t.dom.removeClass(e,s.visual_table_class);}return;case'A':v=t.dom.getAttrib(e,'name');if(v){if(t.hasVisual)t.dom.addClass(e,'mceItemAnchor');else t.dom.removeClass(e,'mceItemAnchor');}return;}});t.onVisualAid.dispatch(t,e,t.hasVisual);},remove:function(){var t=this,e=t.getContainer();t.removed=1;t.hide();t.execCallback('remove_instance_callback',t);t.onRemove.dispatch(t);t.onExecCommand.listeners=[];EditorManager.remove(t);DOM.remove(e);},destroy:function(s){var t=this;if(t.destroyed)return;if(!s){tinymce.removeUnload(t.destroy);tinyMCE.onBeforeUnload.remove(t._beforeUnload);if(t.theme.destroy)t.theme.destroy();t.controlManager.destroy();t.selection.destroy();t.dom.destroy();if(!t.settings.content_editable){Event.clear(t.getWin());Event.clear(t.getDoc());}Event.clear(t.getBody());Event.clear(t.formElement);}if(t.formElement){t.formElement.submit=t.formElement._mceOldSubmit;t.formElement._mceOldSubmit=null;}t.contentAreaContainer=t.formElement=t.container=t.settings.content_element=t.bodyElement=t.contentDocument=t.contentWindow=null;if(t.selection)t.selection=t.selection.win=t.selection.dom=t.selection.dom.doc=null;t.destroyed=1;},_addEvents:function(){var t=this,i,s=t.settings,lo={mouseup:'onMouseUp',mousedown:'onMouseDown',click:'onClick',keyup:'onKeyUp',keydown:'onKeyDown',keypress:'onKeyPress',submit:'onSubmit',reset:'onReset',contextmenu:'onContextMenu',dblclick:'onDblClick',paste:'onPaste'};function eventHandler(e,o){var ty=e.type;if(t.removed)return;if(t.onEvent.dispatch(t,e,o)!==false){t[lo[e.fakeType||e.type]].dispatch(t,e,o);}};each(lo,function(v,k){switch(k){case'contextmenu':if(tinymce.isOpera){Event.add(t.getDoc(),'mousedown',function(e){if(e.ctrlKey){e.fakeType='contextmenu';eventHandler(e);}});}else Event.add(t.getDoc(),k,eventHandler);break;case'paste':Event.add(t.getBody(),k,function(e){var tx,h,el,r;if(e.clipboardData)tx=e.clipboardData.getData('text/plain');else if(tinymce.isIE)tx=t.getWin().clipboardData.getData('Text');eventHandler(e,{text:tx,html:h});});break;case'submit':case'reset':Event.add(t.getElement().form||DOM.getParent(t.id,'form'),k,eventHandler);break;default:Event.add(s.content_editable?t.getBody():t.getDoc(),k,eventHandler);}});Event.add(s.content_editable?t.getBody():(isGecko?t.getDoc():t.getWin()),'focus',function(e){t.focus(true);});if(tinymce.isGecko){Event.add(t.getDoc(),'DOMNodeInserted',function(e){var v;e=e.target;if(e.nodeType===1&&e.nodeName==='IMG'&&(v=e.getAttribute('mce_src')))e.src=t.documentBaseURI.toAbsolute(v);});}if(isGecko){function setOpts(){var t=this,d=t.getDoc(),s=t.settings;if(isGecko){if(t._isHidden()){try{if(!s.content_editable)d.designMode='On';}catch(ex){}}try{d.execCommand("styleWithCSS",0,false);}catch(ex){if(!t._isHidden())d.execCommand("useCSS",0,true);}if(!s.table_inline_editing)try{d.execCommand('enableInlineTableEditing',false,false);}catch(ex){}if(!s.object_resizing)try{d.execCommand('enableObjectResizing',false,false);}catch(ex){}}};t.onBeforeExecCommand.add(setOpts);t.onMouseDown.add(setOpts);}t.onMouseUp.add(t.nodeChanged);t.onClick.add(t.nodeChanged);t.onKeyUp.add(function(ed,e){if((e.keyCode>=33&&e.keyCode<=36)||(e.keyCode>=37&&e.keyCode<=40)||e.keyCode==13||e.keyCode==45||e.keyCode==46||e.keyCode==8||e.ctrlKey)t.nodeChanged();});t.onReset.add(function(){t.setContent(t.startContent,{format:'raw'});});if(t.getParam('tab_focus')){function tabCancel(ed,e){if(e.keyCode===9)return Event.cancel(e);};function tabHandler(ed,e){var x,i,f,el,v;function find(d){f=DOM.getParent(ed.id,'form');el=f.elements;if(f){each(el,function(e,i){if(e.id==ed.id){x=i;return false;}});if(d>0){for(i=x+1;i<el.length;i++){if(el[i].type!='hidden')return el[i];}}else{for(i=x-1;i>=0;i--){if(el[i].type!='hidden')return el[i];}}}return null;};if(e.keyCode===9){v=explode(ed.getParam('tab_focus'));if(v.length==1){v[1]=v[0];v[0]=':prev';}if(e.shiftKey){if(v[0]==':prev')el=find(-1);else el=DOM.get(v[0]);}else{if(v[1]==':next')el=find(1);else el=DOM.get(v[1]);}if(el){if(ed=EditorManager.get(el.id||el.name))ed.focus();else window.setTimeout(function(){window.focus();el.focus();},10);return Event.cancel(e);}}};t.onKeyUp.add(tabCancel);if(isGecko){t.onKeyPress.add(tabHandler);t.onKeyDown.add(tabCancel);}else t.onKeyDown.add(tabHandler);}if(s.custom_shortcuts){if(s.custom_undo_redo_keyboard_shortcuts){t.addShortcut('ctrl+z',t.getLang('undo_desc'),'Undo');t.addShortcut('ctrl+y',t.getLang('redo_desc'),'Redo');}if(isGecko){t.addShortcut('ctrl+b',t.getLang('bold_desc'),'Bold');t.addShortcut('ctrl+i',t.getLang('italic_desc'),'Italic');t.addShortcut('ctrl+u',t.getLang('underline_desc'),'Underline');}for(i=1;i<=6;i++)t.addShortcut('ctrl+'+i,'',['FormatBlock',false,'<h'+i+'>']);t.addShortcut('ctrl+7','',['FormatBlock',false,'<p>']);t.addShortcut('ctrl+8','',['FormatBlock',false,'<div>']);t.addShortcut('ctrl+9','',['FormatBlock',false,'<address>']);function find(e){var v=null;if(!e.altKey&&!e.ctrlKey&&!e.metaKey)return v;each(t.shortcuts,function(o){if(o.ctrl!=e.ctrlKey&&(!tinymce.isMac||o.ctrl==e.metaKey))return;if(o.alt!=e.altKey)return;if(o.shift!=e.shiftKey)return;if(e.keyCode==o.keyCode||(e.charCode&&e.charCode==o.charCode)){v=o;return false;}});return v;};t.onKeyUp.add(function(ed,e){var o=find(e);if(o)return Event.cancel(e);});t.onKeyPress.add(function(ed,e){var o=find(e);if(o)return Event.cancel(e);});t.onKeyDown.add(function(ed,e){var o=find(e);if(o){o.func.call(o.scope);return Event.cancel(e);}});}if(tinymce.isIE){Event.add(t.getDoc(),'controlselect',function(e){var re=t.resizeInfo,cb;e=e.target;if(e.nodeName!=='IMG')return;if(re)Event.remove(re.node,re.ev,re.cb);if(!t.dom.hasClass(e,'mceItemNoResize')){ev='resizeend';cb=Event.add(e,ev,function(e){var v;e=e.target;if(v=t.dom.getStyle(e,'width')){t.dom.setAttrib(e,'width',v.replace(/[^0-9%]+/g,''));t.dom.setStyle(e,'width','');}if(v=t.dom.getStyle(e,'height')){t.dom.setAttrib(e,'height',v.replace(/[^0-9%]+/g,''));t.dom.setStyle(e,'height','');}});}else{ev='resizestart';cb=Event.add(e,'resizestart',Event.cancel,Event);}re=t.resizeInfo={node:e,ev:ev,cb:cb};});t.onKeyDown.add(function(ed,e){switch(e.keyCode){case 8:if(t.selection.getRng().item){t.selection.getRng().item(0).removeNode();return Event.cancel(e);}}});}if(tinymce.isOpera){t.onClick.add(function(ed,e){Event.prevent(e);});}if(s.custom_undo_redo){function addUndo(){t.undoManager.typing=0;t.undoManager.add();};if(tinymce.isIE){Event.add(t.getWin(),'blur',function(e){var n;if(t.selection){n=t.selection.getNode();if(!t.removed&&n.ownerDocument&&n.ownerDocument!=t.getDoc())addUndo();}});}else{Event.add(t.getDoc(),'blur',function(){if(t.selection&&!t.removed)addUndo();});}t.onMouseDown.add(addUndo);t.onKeyUp.add(function(ed,e){if((e.keyCode>=33&&e.keyCode<=36)||(e.keyCode>=37&&e.keyCode<=40)||e.keyCode==13||e.keyCode==45||e.ctrlKey){t.undoManager.typing=0;t.undoManager.add();}});t.onKeyDown.add(function(ed,e){if((e.keyCode>=33&&e.keyCode<=36)||(e.keyCode>=37&&e.keyCode<=40)||e.keyCode==13||e.keyCode==45){if(t.undoManager.typing){t.undoManager.add();t.undoManager.typing=0;}return;}if(!t.undoManager.typing){t.undoManager.add();t.undoManager.typing=1;}});}},_convertInlineElements:function(){var t=this,s=t.settings,dom=t.dom,v,e,na,st,sp;function convert(ed,o){if(!s.inline_styles)return;if(o.get){each(t.dom.select('table,u,strike',o.node),function(n){switch(n.nodeName){case'TABLE':if(v=dom.getAttrib(n,'height')){dom.setStyle(n,'height',v);dom.setAttrib(n,'height','');}break;case'U':case'STRIKE':n.style.textDecoration=n.nodeName=='U'?'underline':'line-through';dom.setAttrib(n,'mce_style','');dom.setAttrib(n,'mce_name','span');break;}});}else if(o.set){each(t.dom.select('table,span',o.node).reverse(),function(n){if(n.nodeName=='TABLE'){if(v=dom.getStyle(n,'height'))dom.setAttrib(n,'height',v.replace(/[^0-9%]+/g,''));}else{if(n.style.textDecoration=='underline')na='u';else if(n.style.textDecoration=='line-through')na='strike';else na='';if(na){n.style.textDecoration='';dom.setAttrib(n,'mce_style','');e=dom.create(na,{style:dom.getAttrib(n,'style')});dom.replace(e,n,1);}}});}};t.onPreProcess.add(convert);if(!s.cleanup_on_startup){t.onSetContent.add(function(ed,o){if(o.initial)convert(t,{node:t.getBody(),set:1});});}},_convertFonts:function(){var t=this,s=t.settings,dom=t.dom,fz,fzn,sl,cl;if(!s.inline_styles)return;fz=[8,10,12,14,18,24,36];fzn=['xx-small','x-small','small','medium','large','x-large','xx-large'];if(sl=s.font_size_style_values)sl=explode(sl);if(cl=s.font_size_classes)cl=explode(cl);function convertToFonts(no){var n,f,nl,x,i,v,st;if(tinymce.isWebKit||!s.inline_styles)return;nl=t.dom.select('span',no);for(x=nl.length-1;x>=0;x--){n=nl[x];f=dom.create('font',{color:dom.toHex(dom.getStyle(n,'color')),face:dom.getStyle(n,'fontFamily'),style:dom.getAttrib(n,'style'),'class':dom.getAttrib(n,'class')});st=f.style;if(st.color||st.fontFamily){st.color=st.fontFamily='';dom.setAttrib(f,'mce_style','');}if(sl){i=inArray(sl,dom.getStyle(n,'fontSize'));if(i!=-1){dom.setAttrib(f,'size',''+(i+1||1));f.style.fontSize='';}}else if(cl){i=inArray(cl,dom.getAttrib(n,'class'));v=dom.getStyle(n,'fontSize');if(i==-1&&v.indexOf('pt')>0)i=inArray(fz,parseInt(v));if(i==-1)i=inArray(fzn,v);if(i!=-1){dom.setAttrib(f,'size',''+(i+1||1));f.style.fontSize='';}}if(f.color||f.face||f.size){f.style.fontFamily='';dom.setAttrib(f,'mce_style','');dom.replace(f,n,1);}f=n=null;}};t.onSetContent.add(function(ed,o){convertToFonts(ed.getBody());});t.onPreProcess.add(function(ed,o){var n,sp,nl,x;if(!s.inline_styles)return;if(o.get){nl=t.dom.select('font',o.node);for(x=nl.length-1;x>=0;x--){n=nl[x];sp=dom.create('span',{style:dom.getAttrib(n,'style'),'class':dom.getAttrib(n,'class')});dom.setStyles(sp,{fontFamily:dom.getAttrib(n,'face'),color:dom.getAttrib(n,'color'),backgroundColor:n.style.backgroundColor});if(n.size){if(sl)dom.setStyle(sp,'fontSize',sl[parseInt(n.size)-1]);else dom.setAttrib(sp,'class',cl[parseInt(n.size)-1]);}dom.setAttrib(sp,'mce_style','');dom.replace(sp,n,1);}}});},_isHidden:function(){var s;if(!isGecko)return 0;s=this.selection.getSel();return(!s||!s.rangeCount||s.rangeCount==0);},_fixNesting:function(s){var d=[],i;s=s.replace(/<(\/)?([^\s>]+)[^>]*?>/g,function(a,b,c){var e;if(b==='/'){if(!d.length)return'';if(c!==d[d.length-1].tag){for(i=d.length-1;i>=0;i--){if(d[i].tag===c){d[i].close=1;break;}}return'';}else{d.pop();if(d.length&&d[d.length-1].close){a=a+'</'+d[d.length-1].tag+'>';d.pop();}}}else{if(/^(br|hr|input|meta|img|link|param)$/i.test(c))return a;if(/\/>$/.test(a))return a;d.push({tag:c});}return a;});for(i=d.length-1;i>=0;i--)s+='</'+d[i].tag+'>';return s;}});})();(function(){var each=tinymce.each,isIE=tinymce.isIE,isGecko=tinymce.isGecko,isOpera=tinymce.isOpera,isWebKit=tinymce.isWebKit;tinymce.create('tinymce.EditorCommands',{EditorCommands:function(ed){this.editor=ed;},execCommand:function(cmd,ui,val){var t=this,ed=t.editor,f;switch(cmd){case'Cut':case'Copy':case'Paste':try{ed.getDoc().execCommand(cmd,ui,val);}catch(ex){if(isGecko){ed.windowManager.confirm(ed.getLang('clipboard_msg'),function(s){if(s)window.open('http://www.mozilla.org/editor/midasdemo/securityprefs.html','mceExternal');});}else ed.windowManager.alert(ed.getLang('clipboard_no_support'));}return true;case'mceResetDesignMode':case'mceBeginUndoLevel':return true;case'unlink':t.UnLink();return true;case'JustifyLeft':case'JustifyCenter':case'JustifyRight':case'JustifyFull':t.mceJustify(cmd,cmd.substring(7).toLowerCase());return true;case'mceEndUndoLevel':case'mceAddUndoLevel':ed.undoManager.add();return true;default:f=this[cmd];if(f){f.call(this,ui,val);return true;}}return false;},Indent:function(){var ed=this.editor,d=ed.dom,s=ed.selection,e,iv,iu;iv=ed.settings.indentation;iu=/[a-z%]+$/i.exec(iv);iv=parseInt(iv);if(ed.settings.inline_styles&&(!this.queryStateInsertUnorderedList()&&!this.queryStateInsertOrderedList())){each(this._getSelectedBlocks(),function(e){d.setStyle(e,'paddingLeft',(parseInt(e.style.paddingLeft||0)+iv)+iu);});return;}ed.getDoc().execCommand('Indent',false,null);if(isIE){d.getParent(s.getNode(),function(n){if(n.nodeName=='BLOCKQUOTE'){n.dir=n.style.cssText='';}});}},Outdent:function(){var ed=this.editor,d=ed.dom,s=ed.selection,e,v,iv,iu;iv=ed.settings.indentation;iu=/[a-z%]+$/i.exec(iv);iv=parseInt(iv);if(ed.settings.inline_styles&&(!this.queryStateInsertUnorderedList()&&!this.queryStateInsertOrderedList())){each(this._getSelectedBlocks(),function(e){v=Math.max(0,parseInt(e.style.paddingLeft||0)-iv);d.setStyle(e,'paddingLeft',v?v+iu:'');});return;}ed.getDoc().execCommand('Outdent',false,null);},mceSetAttribute:function(u,v){var ed=this.editor,d=ed.dom,e;if(e=d.getParent(ed.selection.getNode(),d.isBlock))d.setAttrib(e,v.name,v.value);},mceSetContent:function(u,v){this.editor.setContent(v);},mceToggleVisualAid:function(){var ed=this.editor;ed.hasVisual=!ed.hasVisual;ed.addVisual();},mceReplaceContent:function(u,v){var s=this.editor.selection;s.setContent(v.replace(/\{\$selection\}/g,s.getContent({format:'text'})));},mceInsertLink:function(u,v){var ed=this.editor,s=ed.selection,e=ed.dom.getParent(s.getNode(),'A');if(tinymce.is(v,'string'))v={href:v};function set(e){each(v,function(v,k){ed.dom.setAttrib(e,k,v);});};if(!e){ed.execCommand('CreateLink',false,'javascript:mctmp(0);');each(ed.dom.select('a'),function(e){if(e.href=='javascript:mctmp(0);')set(e);});}else{if(v.href)set(e);else ed.dom.remove(e,1);}},UnLink:function(){var ed=this.editor,s=ed.selection;if(s.isCollapsed())s.select(s.getNode());ed.getDoc().execCommand('unlink',false,null);s.collapse(0);},FontName:function(u,v){var t=this,ed=t.editor,s=ed.selection,e;if(!v){if(s.isCollapsed())s.select(s.getNode());t.RemoveFormat();}else ed.getDoc().execCommand('FontName',false,v);},queryCommandValue:function(c){var f=this['queryValue'+c];if(f)return f.call(this,c);return false;},queryCommandState:function(cmd){var f;switch(cmd){case'JustifyLeft':case'JustifyCenter':case'JustifyRight':case'JustifyFull':return this.queryStateJustify(cmd,cmd.substring(7).toLowerCase());default:if(f=this['queryState'+cmd])return f.call(this,cmd);}return-1;},_queryState:function(c){try{return this.editor.getDoc().queryCommandState(c);}catch(ex){}},_queryVal:function(c){try{return this.editor.getDoc().queryCommandValue(c);}catch(ex){}},queryValueFontSize:function(){var ed=this.editor,v=0,p;if(isOpera||isWebKit){if(p=ed.dom.getParent(ed.selection.getNode(),'FONT'))v=p.size;return v;}return this._queryVal('FontSize');},queryValueFontName:function(){var ed=this.editor,v=0,p;if(p=ed.dom.getParent(ed.selection.getNode(),'FONT'))v=p.face;if(!v)v=this._queryVal('FontName');return v;},mceJustify:function(c,v){var ed=this.editor,se=ed.selection,n=se.getNode(),nn=n.nodeName,bl,nb,dom=ed.dom,rm;if(ed.settings.inline_styles&&this.queryStateJustify(c,v))rm=1;bl=dom.getParent(n,ed.dom.isBlock);if(nn=='IMG'){if(v=='full')return;if(rm){if(v=='center')dom.setStyle(n.parentNode,'textAlign','');dom.setStyle(n,'float','');this.mceRepaint();return;}if(v=='center'){if(/^(TD|TH)$/.test(bl.nodeName))bl=0;if(!bl||bl.childNodes.length>1){nb=dom.create('p');nb.appendChild(n.cloneNode(false));if(bl)dom.insertAfter(nb,bl);else dom.insertAfter(nb,n);dom.remove(n);n=nb.firstChild;bl=nb;}dom.setStyle(bl,'textAlign',v);dom.setStyle(n,'float','');}else{dom.setStyle(n,'float',v);dom.setStyle(n.parentNode,'textAlign','');}this.mceRepaint();return;}if(ed.settings.inline_styles&&ed.settings.forced_root_block){if(rm)v='';each(this._getSelectedBlocks(dom.getParent(se.getStart(),dom.isBlock),dom.getParent(se.getEnd(),dom.isBlock)),function(e){dom.setAttrib(e,'align','');dom.setStyle(e,'textAlign',v=='full'?'justify':v);});return;}else if(!rm)ed.getDoc().execCommand(c,false,null);if(ed.settings.inline_styles){if(rm){dom.getParent(ed.selection.getNode(),function(n){if(n.style&&n.style.textAlign)dom.setStyle(n,'textAlign','');});return;}each(dom.select('*'),function(n){var v=n.align;if(v){if(v=='full')v='justify';dom.setStyle(n,'textAlign',v);dom.setAttrib(n,'align','');}});}},mceSetCSSClass:function(u,v){this.mceSetStyleInfo(0,{command:'setattrib',name:'class',value:v});},getSelectedElement:function(){var t=this,ed=t.editor,dom=ed.dom,se=ed.selection,r=se.getRng(),r1,r2,sc,ec,so,eo,e,sp,ep,re;if(se.isCollapsed()||r.item)return se.getNode();re=ed.settings.merge_styles_invalid_parents;if(tinymce.is(re,'string'))re=new RegExp(re,'i');if(isIE){r1=r.duplicate();r1.collapse(true);sc=r1.parentElement();r2=r.duplicate();r2.collapse(false);ec=r2.parentElement();if(sc!=ec){r1.move('character',1);sc=r1.parentElement();}if(sc==ec){r1=r.duplicate();r1.moveToElementText(sc);if(r1.compareEndPoints('StartToStart',r)==0&&r1.compareEndPoints('EndToEnd',r)==0)return re&&re.test(sc.nodeName)?null:sc;}}else{function getParent(n){return dom.getParent(n,function(n){return n.nodeType==1;});};sc=r.startContainer;ec=r.endContainer;so=r.startOffset;eo=r.endOffset;if(!r.collapsed){if(sc==ec){if(so-eo<2){if(sc.hasChildNodes()){sp=sc.childNodes[so];return re&&re.test(sp.nodeName)?null:sp;}}}}if(sc.nodeType!=3||ec.nodeType!=3)return null;if(so==0){sp=getParent(sc);if(sp&&sp.firstChild!=sc)sp=null;}if(so==sc.nodeValue.length){e=sc.nextSibling;if(e&&e.nodeType==1)sp=sc.nextSibling;}if(eo==0){e=ec.previousSibling;if(e&&e.nodeType==1)ep=e;}if(eo==ec.nodeValue.length){ep=getParent(ec);if(ep&&ep.lastChild!=ec)ep=null;}if(sp==ep)return re&&sp&&re.test(sp.nodeName)?null:sp;}return null;},InsertHorizontalRule:function(){if(isGecko||isIE)this.editor.selection.setContent('<hr />');else this.editor.getDoc().execCommand('InsertHorizontalRule',false,'');},RemoveFormat:function(){var t=this,ed=t.editor,s=ed.selection,b;if(isWebKit)s.setContent(s.getContent({format:'raw'}).replace(/(<(span|b|i|strong|em|strike) [^>]+>|<(span|b|i|strong|em|strike)>|<\/(span|b|i|strong|em|strike)>|)/g,''),{format:'raw'});else ed.getDoc().execCommand('RemoveFormat',false,null);t.mceSetStyleInfo(0,{command:'removeformat'});ed.addVisual();},mceSetStyleInfo:function(u,v){var t=this,ed=t.editor,d=ed.getDoc(),dom=ed.dom,e,b,s=ed.selection,nn=v.wrapper||'span',b=s.getBookmark(),re;function set(n,e){if(n.nodeType==1){switch(v.command){case'setattrib':return dom.setAttrib(n,v.name,v.value);case'setstyle':return dom.setStyle(n,v.name,v.value);case'removeformat':return dom.setAttrib(n,'class','');}}};re=ed.settings.merge_styles_invalid_parents;if(tinymce.is(re,'string'))re=new RegExp(re,'i');if(e=t.getSelectedElement())set(e,1);else{d.execCommand('FontName',false,'__');each(isWebKit?dom.select('span'):dom.select('font'),function(n){var sp,e;if(dom.getAttrib(n,'face')=='__'||n.style.fontFamily==='__'){sp=dom.create(nn,{mce_new:'1'});set(sp);each(n.childNodes,function(n){sp.appendChild(n.cloneNode(true));});dom.replace(sp,n);}});}each(dom.select(nn).reverse(),function(n){var p=n.parentNode;if(!dom.getAttrib(n,'mce_new')){p=dom.getParent(n,function(n){return n.nodeType==1&&dom.getAttrib(n,'mce_new');});if(p)dom.remove(n,1);}});each(dom.select(nn).reverse(),function(n){var p=n.parentNode;if(!p||!dom.getAttrib(n,'mce_new'))return;if(p.nodeName==nn.toUpperCase()&&p.childNodes.length==1)return dom.remove(p,1);if(n.nodeType==1&&(!re||!re.test(p.nodeName))&&p.childNodes.length==1){set(p);dom.setAttrib(n,'class','');}});each(dom.select(nn).reverse(),function(n){if(dom.getAttrib(n,'mce_new')||(dom.getAttribs(n).length<=1&&n.className==='')){if(!dom.getAttrib(n,'class')&&!dom.getAttrib(n,'style'))return dom.remove(n,1);dom.setAttrib(n,'mce_new','');}});s.moveToBookmark(b);},queryStateJustify:function(c,v){var ed=this.editor,n=ed.selection.getNode(),dom=ed.dom;if(n&&n.nodeName=='IMG'){if(dom.getStyle(n,'float')==v)return 1;return n.parentNode.style.textAlign==v;}n=dom.getParent(ed.selection.getStart(),function(n){return n.nodeType==1&&n.style.textAlign;});if(v=='full')v='justify';if(ed.settings.inline_styles)return(n&&n.style.textAlign==v);return this._queryState(c);},HiliteColor:function(ui,val){var t=this,ed=t.editor,d=ed.getDoc();function set(s){if(!isGecko)return;try{d.execCommand("styleWithCSS",0,s);}catch(ex){d.execCommand("useCSS",0,!s);}};if(isGecko||isOpera){set(true);d.execCommand('hilitecolor',false,val);set(false);}else d.execCommand('BackColor',false,val);},Undo:function(){var ed=this.editor;if(ed.settings.custom_undo_redo){ed.undoManager.undo();ed.nodeChanged();}else ed.getDoc().execCommand('Undo',false,null);},Redo:function(){var ed=this.editor;if(ed.settings.custom_undo_redo){ed.undoManager.redo();ed.nodeChanged();}else ed.getDoc().execCommand('Redo',false,null);},FormatBlock:function(ui,val){var t=this,ed=t.editor;val=ed.settings.forced_root_block?(val||'<p>'):val;if(/^(P|DIV|H[1-6]|ADDRESS|BLOCKQUOTE|PRE)$/.test(ed.selection.getNode().nodeName))t.mceRemoveNode();if(val.indexOf('<')==-1)val='<'+val+'>';if(tinymce.isGecko)val=val.replace(/<(div|blockquote|code|dt|dd|dl|samp)>/gi,'$1');ed.getDoc().execCommand('FormatBlock',false,val);},mceCleanup:function(){var ed=this.editor,s=ed.selection,b=s.getBookmark();ed.setContent(ed.getContent());s.moveToBookmark(b);},mceRemoveNode:function(ui,val){var ed=this.editor,s=ed.selection,b,n=val||s.getNode();if(n==ed.getBody())return;b=s.getBookmark();ed.dom.remove(n,1);s.moveToBookmark(b);ed.nodeChanged();},mceSelectNodeDepth:function(ui,val){var ed=this.editor,s=ed.selection,c=0;ed.dom.getParent(s.getNode(),function(n){if(n.nodeType==1&&c++==val){s.select(n);ed.nodeChanged();return false;}},ed.getBody());},mceSelectNode:function(u,v){this.editor.selection.select(v);},mceInsertContent:function(ui,val){this.editor.selection.setContent(val);},mceInsertRawHTML:function(ui,val){var ed=this.editor;ed.selection.setContent('tiny_mce_marker');ed.setContent(ed.getContent().replace(/tiny_mce_marker/g,val));},mceRepaint:function(){var s,b,e=this.editor;if(tinymce.isGecko){try{s=e.selection;b=s.getBookmark(true);if(s.getSel())s.getSel().selectAllChildren(e.getBody());s.collapse(true);s.moveToBookmark(b);}catch(ex){}}},queryStateUnderline:function(){var ed=this.editor,n=ed.selection.getNode();if(n&&n.nodeName=='A')return false;return this._queryState('Underline');},queryStateOutdent:function(){var ed=this.editor,n;if(ed.settings.inline_styles){if((n=ed.dom.getParent(ed.selection.getStart(),ed.dom.isBlock))&&parseInt(n.style.paddingLeft)>0)return true;if((n=ed.dom.getParent(ed.selection.getEnd(),ed.dom.isBlock))&&parseInt(n.style.paddingLeft)>0)return true;}else return!!ed.dom.getParent(ed.selection.getNode(),'BLOCKQUOTE');return this.queryStateInsertUnorderedList()||this.queryStateInsertOrderedList();},queryStateInsertUnorderedList:function(){return this.editor.dom.getParent(this.editor.selection.getNode(),'UL');},queryStateInsertOrderedList:function(){return this.editor.dom.getParent(this.editor.selection.getNode(),'OL');},queryStatemceBlockQuote:function(){return!!this.editor.dom.getParent(this.editor.selection.getStart(),function(n){return n.nodeName==='BLOCKQUOTE';});},mceBlockQuote:function(){var t=this,ed=t.editor,s=ed.selection,dom=ed.dom,sb,eb,n,bm,bq,r,bq2,i,nl;function getBQ(e){return dom.getParent(e,function(n){return n.nodeName==='BLOCKQUOTE';});};sb=dom.getParent(s.getStart(),dom.isBlock);eb=dom.getParent(s.getEnd(),dom.isBlock);if(bq=getBQ(sb)){if(sb!=eb||sb.childNodes.length>1||(sb.childNodes.length==1&&sb.firstChild.nodeName!='BR'))bm=s.getBookmark();if(getBQ(eb)){bq2=bq.cloneNode(false);while(n=eb.nextSibling)bq2.appendChild(n.parentNode.removeChild(n));}if(bq2)dom.insertAfter(bq2,bq);nl=t._getSelectedBlocks(sb,eb);for(i=nl.length-1;i>=0;i--){dom.insertAfter(nl[i],bq);}if(/^\s*$/.test(bq.innerHTML))dom.remove(bq,1);if(bq2&&/^\s*$/.test(bq2.innerHTML))dom.remove(bq2,1);if(!bm){if(!isIE){r=ed.getDoc().createRange();r.setStart(sb,0);r.setEnd(sb,0);s.setRng(r);}else{s.select(sb);s.collapse(0);if(dom.getParent(s.getStart(),dom.isBlock)!=sb){r=s.getRng();r.move('character',-1);r.select();}}}else t.editor.selection.moveToBookmark(bm);return;}if(isIE&&!sb&&!eb){t.editor.getDoc().execCommand('Indent');n=getBQ(s.getNode());n.style.margin=n.dir='';return;}if(!sb||!eb)return;if(sb!=eb||sb.childNodes.length>1||(sb.childNodes.length==1&&sb.firstChild.nodeName!='BR'))bm=s.getBookmark();each(t._getSelectedBlocks(getBQ(s.getStart()),getBQ(s.getEnd())),function(e){if(e.nodeName=='BLOCKQUOTE'&&!bq){bq=e;return;}if(!bq){bq=dom.create('blockquote');e.parentNode.insertBefore(bq,e);}if(e.nodeName=='BLOCKQUOTE'&&bq){n=e.firstChild;while(n){bq.appendChild(n.cloneNode(true));n=n.nextSibling;}dom.remove(e);return;}bq.appendChild(dom.remove(e));});if(!bm){if(!isIE){r=ed.getDoc().createRange();r.setStart(sb,0);r.setEnd(sb,0);s.setRng(r);}else{s.select(sb);s.collapse(1);}}else s.moveToBookmark(bm);},_getSelectedBlocks:function(st,en){var ed=this.editor,dom=ed.dom,s=ed.selection,sb,eb,n,bl=[];sb=dom.getParent(st||s.getStart(),dom.isBlock);eb=dom.getParent(en||s.getEnd(),dom.isBlock);if(sb)bl.push(sb);if(sb&&eb&&sb!=eb){n=sb;while((n=n.nextSibling)&&n!=eb){if(dom.isBlock(n))bl.push(n);}}if(eb&&sb!=eb)bl.push(eb);return bl;}});})();tinymce.create('tinymce.UndoManager',{index:0,data:null,typing:0,UndoManager:function(ed){var t=this,Dispatcher=tinymce.util.Dispatcher;t.editor=ed;t.data=[];t.onAdd=new Dispatcher(this);t.onUndo=new Dispatcher(this);t.onRedo=new Dispatcher(this);},add:function(l){var t=this,i,ed=t.editor,b,s=ed.settings,la;l=l||{};l.content=l.content||ed.getContent({format:'raw',no_events:1});l.content=l.content.replace(/^\s*|\s*$/g,'');la=t.data[t.index>0?t.index-1:0];if(!l.initial&&la&&l.content==la.content)return null;if(s.custom_undo_redo_levels){if(t.data.length>s.custom_undo_redo_levels){for(i=0;i<t.data.length-1;i++)t.data[i]=t.data[i+1];t.data.length--;t.index=t.data.length;}}if(s.custom_undo_redo_restore_selection&&!l.initial)l.bookmark=b=l.bookmark||ed.selection.getBookmark();if(t.index<t.data.length&&t.data[t.index].initial)t.index++;if(t.data.length===0&&!l.initial)return null;t.data.length=t.index+1;t.data[t.index++]=l;if(l.initial)t.index=0;if(t.data.length==2&&t.data[0].initial)t.data[0].bookmark=b;t.onAdd.dispatch(t,l);ed.isNotDirty=0;return l;},undo:function(){var t=this,ed=t.editor,l=l,i;if(t.typing){t.add();t.typing=0;}if(t.index>0){if(t.index==t.data.length&&t.index>1){i=t.index;t.typing=0;if(!t.add())t.index=i;--t.index;}l=t.data[--t.index];ed.setContent(l.content,{format:'raw'});ed.selection.moveToBookmark(l.bookmark);t.onUndo.dispatch(t,l);}return l;},redo:function(){var t=this,ed=t.editor,l=null;if(t.index<t.data.length-1){l=t.data[++t.index];ed.setContent(l.content,{format:'raw'});ed.selection.moveToBookmark(l.bookmark);t.onRedo.dispatch(t,l);}return l;},clear:function(){var t=this;t.data=[];t.index=0;t.typing=0;t.add({initial:true});},hasUndo:function(){return this.index!=0||this.typing;},hasRedo:function(){return this.index<this.data.length-1;}});(function(){var Event,isIE,isGecko,isOpera,each,extend;Event=tinymce.dom.Event;isIE=tinymce.isIE;isGecko=tinymce.isGecko;isOpera=tinymce.isOpera;each=tinymce.each;extend=tinymce.extend;tinymce.create('tinymce.ForceBlocks',{ForceBlocks:function(ed){var t=this,s=ed.settings,elm;t.editor=ed;t.dom=ed.dom;elm=(s.forced_root_block||'p').toLowerCase();s.element=elm.toUpperCase();ed.onPreInit.add(t.setup,t);t.reOpera=new RegExp('(\\u00a0|&#160;|&nbsp;)<\/'+elm+'>','gi');t.rePadd=new RegExp('<p( )([^>]+)><\\\/p>|<p( )([^>]+)\\\/>|<p( )([^>]+)>\\s+<\\\/p>|<p><\\\/p>|<p\\\/>|<p>\\s+<\\\/p>'.replace(/p/g,elm),'gi');t.reNbsp2BR1=new RegExp('<p( )([^>]+)>[\\s\\u00a0]+<\\\/p>|<p>[\\s\\u00a0]+<\\\/p>'.replace(/p/g,elm),'gi');t.reNbsp2BR2=new RegExp('<p( )([^>]+)>(&nbsp;|&#160;)<\\\/p>|<p>(&nbsp;|&#160;)<\\\/p>'.replace(/p/g,elm),'gi');t.reBR2Nbsp=new RegExp('<p( )([^>]+)>\\s*<br \\\/>\\s*<\\\/p>|<p>\\s*<br \\\/>\\s*<\\\/p>'.replace(/p/g,elm),'gi');t.reTrailBr=new RegExp('\\s*<br \\/>\\s*<\\\/p>'.replace(/p/g,elm),'gi');function padd(ed,o){if(isOpera)o.content=o.content.replace(t.reOpera,'</'+elm+'>');o.content=o.content.replace(t.rePadd,'<'+elm+'$1$2$3$4$5$6>\u00a0</'+elm+'>');if(!isIE&&!isOpera&&o.set){o.content=o.content.replace(t.reNbsp2BR1,'<'+elm+'$1$2><br /></'+elm+'>');o.content=o.content.replace(t.reNbsp2BR2,'<'+elm+'$1$2><br /></'+elm+'>');}else{o.content=o.content.replace(t.reBR2Nbsp,'<'+elm+'$1$2>\u00a0</'+elm+'>');o.content=o.content.replace(t.reTrailBr,'</'+elm+'>');}};ed.onBeforeSetContent.add(padd);ed.onPostProcess.add(padd);if(s.forced_root_block){ed.onInit.add(t.forceRoots,t);ed.onSetContent.add(t.forceRoots,t);ed.onBeforeGetContent.add(t.forceRoots,t);}},setup:function(){var t=this,ed=t.editor,s=ed.settings;if(s.forced_root_block){ed.onKeyUp.add(t.forceRoots,t);ed.onPreProcess.add(t.forceRoots,t);}if(s.force_br_newlines){if(isIE){ed.onKeyPress.add(function(ed,e){var n,s=ed.selection;if(e.keyCode==13&&s.getNode().nodeName!='LI'){s.setContent('<br id="__" /> ',{format:'raw'});n=ed.dom.get('__');n.removeAttribute('id');s.select(n);s.collapse();return Event.cancel(e);}});}return;}if(!isIE&&s.force_p_newlines){ed.onKeyPress.add(function(ed,e){if(e.keyCode==13&&!e.shiftKey){if(!t.insertPara(e))Event.cancel(e);}});if(isGecko){ed.onKeyDown.add(function(ed,e){if((e.keyCode==8||e.keyCode==46)&&!e.shiftKey)t.backspaceDelete(e,e.keyCode==8);});}}function ren(rn,na){var ne=ed.dom.create(na);each(rn.attributes,function(a){if(a.specified&&a.nodeValue)ne.setAttribute(a.nodeName.toLowerCase(),a.nodeValue);});each(rn.childNodes,function(n){ne.appendChild(n.cloneNode(true));});rn.parentNode.replaceChild(ne,rn);return ne;};if(isIE&&s.element!='P'){ed.onKeyPress.add(function(ed,e){t.lastElm=ed.selection.getNode().nodeName;});ed.onKeyUp.add(function(ed,e){var bl,sel=ed.selection,n=sel.getNode(),b=ed.getBody();if(b.childNodes.length===1&&n.nodeName=='P'){n=ren(n,s.element);sel.select(n);sel.collapse();ed.nodeChanged();}else if(e.keyCode==13&&!e.shiftKey&&t.lastElm!='P'){bl=ed.dom.getParent(n,'P');if(bl){ren(bl,s.element);ed.nodeChanged();}}});}},find:function(n,t,s){var ed=this.editor,w=ed.getDoc().createTreeWalker(n,4,null,false),c=-1;while(n=w.nextNode()){c++;if(t==0&&n==s)return c;if(t==1&&c==s)return n;}return-1;},forceRoots:function(ed,e){var t=this,ed=t.editor,b=ed.getBody(),d=ed.getDoc(),se=ed.selection,s=se.getSel(),r=se.getRng(),si=-2,ei,so,eo,tr,c=-0xFFFFFF;var nx,bl,bp,sp,le,nl=b.childNodes,i;if(e&&e.keyCode==13)return true;for(i=nl.length-1;i>=0;i--){nx=nl[i];if(nx.nodeType==3||(!t.dom.isBlock(nx)&&nx.nodeType!=8)){if(!bl){if(nx.nodeType!=3||/[^\s]/g.test(nx.nodeValue)){if(si==-2&&r){if(!isIE){so=r.startOffset;eo=r.endOffset;si=t.find(b,0,r.startContainer);ei=t.find(b,0,r.endContainer);}else{tr=d.body.createTextRange();tr.moveToElementText(b);tr.collapse(1);bp=tr.move('character',c)*-1;tr=r.duplicate();tr.collapse(1);sp=tr.move('character',c)*-1;tr=r.duplicate();tr.collapse(0);le=(tr.move('character',c)*-1)-sp;si=sp-bp;ei=le;}}bl=ed.dom.create(ed.settings.forced_root_block);bl.appendChild(nx.cloneNode(1));nx.parentNode.replaceChild(bl,nx);}}else{if(bl.hasChildNodes())bl.insertBefore(nx,bl.firstChild);else bl.appendChild(nx);}}else bl=null;}if(si!=-2){if(!isIE){bl=d.getElementsByTagName(ed.settings.element)[0];r=d.createRange();if(si!=-1)r.setStart(t.find(b,1,si),so);else r.setStart(bl,0);if(ei!=-1)r.setEnd(t.find(b,1,ei),eo);else r.setEnd(bl,0);if(s){s.removeAllRanges();s.addRange(r);}}else{try{r=s.createRange();r.moveToElementText(b);r.collapse(1);r.moveStart('character',si);r.moveEnd('character',ei);r.select();}catch(ex){}}}},getParentBlock:function(n){var d=this.dom;return d.getParent(n,d.isBlock);},insertPara:function(e){var t=this,ed=t.editor,dom=ed.dom,d=ed.getDoc(),se=ed.settings,s=ed.selection.getSel(),r=s.getRangeAt(0),b=d.body;var rb,ra,dir,sn,so,en,eo,sb,eb,bn,bef,aft,sc,ec,n,vp=dom.getViewPort(ed.getWin()),y,ch;function isEmpty(n){n=n.innerHTML;n=n.replace(/<(img|hr|table)/gi,'-');n=n.replace(/<[^>]+>/g,'');return n.replace(/[ \t\r\n]+/g,'')=='';};rb=d.createRange();rb.setStart(s.anchorNode,s.anchorOffset);rb.collapse(true);ra=d.createRange();ra.setStart(s.focusNode,s.focusOffset);ra.collapse(true);dir=rb.compareBoundaryPoints(rb.START_TO_END,ra)<0;sn=dir?s.anchorNode:s.focusNode;so=dir?s.anchorOffset:s.focusOffset;en=dir?s.focusNode:s.anchorNode;eo=dir?s.focusOffset:s.anchorOffset;if(sn===en&&/^(TD|TH)$/.test(sn.nodeName)){dom.remove(sn.firstChild);ed.dom.add(sn,se.element,null,'<br />');aft=ed.dom.add(sn,se.element,null,'<br />');r=d.createRange();r.selectNodeContents(aft);r.collapse(1);ed.selection.setRng(r);return false;}if(sn==b&&en==b&&b.firstChild&&ed.dom.isBlock(b.firstChild)){sn=en=sn.firstChild;so=eo=0;rb=d.createRange();rb.setStart(sn,0);ra=d.createRange();ra.setStart(en,0);}sn=sn.nodeName=="HTML"?d.body:sn;sn=sn.nodeName=="BODY"?sn.firstChild:sn;en=en.nodeName=="HTML"?d.body:en;en=en.nodeName=="BODY"?en.firstChild:en;sb=t.getParentBlock(sn);eb=t.getParentBlock(en);bn=sb?sb.nodeName:se.element;if(t.dom.getParent(sb,function(n){return/OL|UL|PRE/.test(n.nodeName);}))return true;if(sb&&(sb.nodeName=='CAPTION'||/absolute|relative|static/gi.test(sb.style.position))){bn=se.element;sb=null;}if(eb&&(eb.nodeName=='CAPTION'||/absolute|relative|static/gi.test(eb.style.position))){bn=se.element;eb=null;}if(/(TD|TABLE|TH|CAPTION)/.test(bn)||(sb&&bn=="DIV"&&/left|right/gi.test(sb.style.cssFloat))){bn=se.element;sb=eb=null;}bef=(sb&&sb.nodeName==bn)?sb.cloneNode(0):ed.dom.create(bn);aft=(eb&&eb.nodeName==bn)?eb.cloneNode(0):ed.dom.create(bn);aft.removeAttribute('id');if(/^(H[1-6])$/.test(bn)&&sn.nodeValue&&so==sn.nodeValue.length)aft=ed.dom.create(se.element);n=sc=sn;do{if(n==b||n.nodeType==9||t.dom.isBlock(n)||/(TD|TABLE|TH|CAPTION)/.test(n.nodeName))break;sc=n;}while((n=n.previousSibling?n.previousSibling:n.parentNode));n=ec=en;do{if(n==b||n.nodeType==9||t.dom.isBlock(n)||/(TD|TABLE|TH|CAPTION)/.test(n.nodeName))break;ec=n;}while((n=n.nextSibling?n.nextSibling:n.parentNode));if(sc.nodeName==bn)rb.setStart(sc,0);else rb.setStartBefore(sc);rb.setEnd(sn,so);bef.appendChild(rb.cloneContents()||d.createTextNode(''));try{ra.setEndAfter(ec);}catch(ex){}ra.setStart(en,eo);aft.appendChild(ra.cloneContents()||d.createTextNode(''));r=d.createRange();if(!sc.previousSibling&&sc.parentNode.nodeName==bn){r.setStartBefore(sc.parentNode);}else{if(rb.startContainer.nodeName==bn&&rb.startOffset==0)r.setStartBefore(rb.startContainer);else r.setStart(rb.startContainer,rb.startOffset);}if(!ec.nextSibling&&ec.parentNode.nodeName==bn)r.setEndAfter(ec.parentNode);else r.setEnd(ra.endContainer,ra.endOffset);r.deleteContents();if(isOpera)ed.getWin().scrollTo(0,vp.y);if(bef.firstChild&&bef.firstChild.nodeName==bn)bef.innerHTML=bef.firstChild.innerHTML;if(aft.firstChild&&aft.firstChild.nodeName==bn)aft.innerHTML=aft.firstChild.innerHTML;if(isEmpty(bef))bef.innerHTML='<br />';if(isEmpty(aft))aft.innerHTML=isOpera?'&nbsp;':'<br />';if(isOpera){r.insertNode(bef);r.insertNode(aft);}else{r.insertNode(aft);r.insertNode(bef);}aft.normalize();bef.normalize();r=d.createRange();r.selectNodeContents(aft);r.collapse(1);s.removeAllRanges();s.addRange(r);y=ed.dom.getPos(aft).y;ch=aft.clientHeight;if(y<vp.y||y+ch>vp.y+vp.h){ed.getWin().scrollTo(0,y<vp.y?y:y-vp.h+ch);}return false;},backspaceDelete:function(e,bs){var t=this,ed=t.editor,b=ed.getBody(),n,se=ed.selection,r=se.getRng(),sc=r.startContainer,n,w,tn;if(sc&&ed.dom.isBlock(sc)&&!/^(TD|TH)$/.test(sc.nodeName)&&bs){if(sc.childNodes.length==0||(sc.childNodes.length==1&&sc.firstChild.nodeName=='BR')){n=sc;while((n=n.previousSibling)&&!ed.dom.isBlock(n));if(n){if(sc!=b.firstChild){w=ed.dom.doc.createTreeWalker(n,NodeFilter.SHOW_TEXT,null,false);while(tn=w.nextNode())n=tn;r=ed.getDoc().createRange();r.setStart(n,n.nodeValue?n.nodeValue.length:0);r.setEnd(n,n.nodeValue?n.nodeValue.length:0);se.setRng(r);ed.dom.remove(sc);}return Event.cancel(e);}}}function handler(e){e=e.target;if(e&&e.parentNode&&e.nodeName=='BR'&&(n=t.getParentBlock(e))){Event.remove(b,'DOMNodeInserted',handler);if(e.previousSibling||e.nextSibling)ed.dom.remove(e);}};Event._add(b,'DOMNodeInserted',handler);window.setTimeout(function(){Event._remove(b,'DOMNodeInserted',handler);},1);}});})();(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,each=tinymce.each,extend=tinymce.extend;tinymce.create('tinymce.ControlManager',{ControlManager:function(ed,s){var t=this,i;s=s||{};t.editor=ed;t.controls={};t.onAdd=new tinymce.util.Dispatcher(t);t.onPostRender=new tinymce.util.Dispatcher(t);t.prefix=s.prefix||ed.id+'_';t._cls={};t.onPostRender.add(function(){each(t.controls,function(c){c.postRender();});});},get:function(id){return this.controls[this.prefix+id]||this.controls[id];},setActive:function(id,s){var c=null;if(c=this.get(id))c.setActive(s);return c;},setDisabled:function(id,s){var c=null;if(c=this.get(id))c.setDisabled(s);return c;},add:function(c){var t=this;if(c){t.controls[c.id]=c;t.onAdd.dispatch(c,t);}return c;},createControl:function(n){var c,t=this,ed=t.editor;each(ed.plugins,function(p){if(p.createControl){c=p.createControl(n,t);if(c)return false;}});switch(n){case"|":case"separator":return t.createSeparator();}if(!c&&ed.buttons&&(c=ed.buttons[n]))return t.createButton(n,c);return t.add(c);},createDropMenu:function(id,s,cc){var t=this,ed=t.editor,c,bm,v,cls;s=extend({'class':'mceDropDown',constrain:ed.settings.constrain_menus},s);s['class']=s['class']+' '+ed.getParam('skin')+'Skin';if(v=ed.getParam('skin_variant'))s['class']+=' '+ed.getParam('skin')+'Skin'+v.substring(0,1).toUpperCase()+v.substring(1);id=t.prefix+id;cls=cc||t._cls.dropmenu||tinymce.ui.DropMenu;c=t.controls[id]=new cls(id,s);c.onAddItem.add(function(c,o){var s=o.settings;s.title=ed.getLang(s.title,s.title);if(!s.onclick){s.onclick=function(v){ed.execCommand(s.cmd,s.ui||false,s.value);};}});ed.onRemove.add(function(){c.destroy();});if(tinymce.isIE){c.onShowMenu.add(function(){var s=ed.selection,n=s.getNode();if(n.nodeName=='IMG')bm=s.getBookmark();else bm=0;});c.onHideMenu.add(function(){if(bm)ed.selection.moveToBookmark(bm);});}return t.add(c);},createListBox:function(id,s,cc){var t=this,ed=t.editor,cmd,c,cls;if(t.get(id))return null;s.title=ed.translate(s.title);s.scope=s.scope||ed;if(!s.onselect){s.onselect=function(v){ed.execCommand(s.cmd,s.ui||false,v||s.value);};}s=extend({title:s.title,'class':'mce_'+id,scope:s.scope,control_manager:t},s);id=t.prefix+id;if(ed.settings.use_native_selects)c=new tinymce.ui.NativeListBox(id,s);else{cls=cc||t._cls.listbox||tinymce.ui.ListBox;c=new cls(id,s);}t.controls[id]=c;if(tinymce.isWebKit){c.onPostRender.add(function(c,n){Event.add(n,'mousedown',function(){ed.bookmark=ed.selection.getBookmark('simple');});Event.add(n,'focus',function(){ed.selection.moveToBookmark(ed.bookmark);ed.bookmark=null;});});}if(c.hideMenu)ed.onMouseDown.add(c.hideMenu,c);return t.add(c);},createButton:function(id,s,cc){var t=this,ed=t.editor,o,c,cls;if(t.get(id))return null;s.title=ed.translate(s.title);s.label=ed.translate(s.label);s.scope=s.scope||ed;if(!s.onclick&&!s.menu_button){s.onclick=function(){ed.execCommand(s.cmd,s.ui||false,s.value);};}s=extend({title:s.title,'class':'mce_'+id,unavailable_prefix:ed.getLang('unavailable',''),scope:s.scope,control_manager:t},s);id=t.prefix+id;if(s.menu_button){cls=cc||t._cls.menubutton||tinymce.ui.MenuButton;c=new cls(id,s);ed.onMouseDown.add(c.hideMenu,c);}else{cls=t._cls.button||tinymce.ui.Button;c=new cls(id,s);}return t.add(c);},createMenuButton:function(id,s){s=s||{};s.menu_button=1;return this.createButton(id,s);},createSplitButton:function(id,s,cc){var t=this,ed=t.editor,cmd,c,cls;if(t.get(id))return null;s.title=ed.translate(s.title);s.scope=s.scope||ed;if(!s.onclick){s.onclick=function(v){ed.execCommand(s.cmd,s.ui||false,v||s.value);};}if(!s.onselect){s.onselect=function(v){ed.execCommand(s.cmd,s.ui||false,v||s.value);};}s=extend({title:s.title,'class':'mce_'+id,scope:s.scope,control_manager:t},s);id=t.prefix+id;cls=cc||t._cls.splitbutton||tinymce.ui.SplitButton;c=t.add(new cls(id,s));ed.onMouseDown.add(c.hideMenu,c);return c;},createColorSplitButton:function(id,s,cc){var t=this,ed=t.editor,cmd,c,cls;if(t.get(id))return null;s.title=ed.translate(s.title);s.scope=s.scope||ed;if(!s.onclick){s.onclick=function(v){ed.execCommand(s.cmd,s.ui||false,v||s.value);};}if(!s.onselect){s.onselect=function(v){ed.execCommand(s.cmd,s.ui||false,v||s.value);};}s=extend({title:s.title,'class':'mce_'+id,'menu_class':ed.getParam('skin')+'Skin',scope:s.scope,more_colors_title:ed.getLang('more_colors')},s);id=t.prefix+id;cls=cc||t._cls.colorsplitbutton||tinymce.ui.ColorSplitButton;c=new cls(id,s);ed.onMouseDown.add(c.hideMenu,c);ed.onRemove.add(function(){c.destroy();});return t.add(c);},createToolbar:function(id,s,cc){var c,t=this,cls;id=t.prefix+id;cls=cc||t._cls.toolbar||tinymce.ui.Toolbar;c=new cls(id,s);if(t.get(id))return null;return t.add(c);},createSeparator:function(cc){var cls=cc||this._cls.separator||tinymce.ui.Separator;return new cls();},setControlType:function(n,c){return this._cls[n.toLowerCase()]=c;},destroy:function(){each(this.controls,function(c){c.destroy();});this.controls=null;}});})();(function(){var Dispatcher=tinymce.util.Dispatcher,each=tinymce.each,isIE=tinymce.isIE,isOpera=tinymce.isOpera;tinymce.create('tinymce.WindowManager',{WindowManager:function(ed){var t=this;t.editor=ed;t.onOpen=new Dispatcher(t);t.onClose=new Dispatcher(t);t.params={};t.features={};},open:function(s,p){var t=this,f='',x,y,mo=t.editor.settings.dialog_type=='modal',w,sw,sh,vp=tinymce.DOM.getViewPort(),u;s=s||{};p=p||{};sw=isOpera?vp.w:screen.width;sh=isOpera?vp.h:screen.height;s.name=s.name||'mc_'+new Date().getTime();s.width=parseInt(s.width||320);s.height=parseInt(s.height||240);s.resizable=true;s.left=s.left||parseInt(sw/ 2.0) - (s.width /2.0);s.top=s.top||parseInt(sh/ 2.0) - (s.height /2.0);p.inline=false;p.mce_width=s.width;p.mce_height=s.height;p.mce_auto_focus=s.auto_focus;if(mo){if(isIE){s.center=true;s.help=false;s.dialogWidth=s.width+'px';s.dialogHeight=s.height+'px';s.scroll=s.scrollbars||false;}else s.modal=s.alwaysRaised=s.dialog=s.centerscreen=s.dependent=true;}each(s,function(v,k){if(tinymce.is(v,'boolean'))v=v?'yes':'no';if(!/^(name|url)$/.test(k)){if(isIE&&mo)f+=(f?';':'')+k+':'+v;else f+=(f?',':'')+k+'='+v;}});t.features=s;t.params=p;t.onOpen.dispatch(t,s,p);u=s.url||s.file;if(tinymce.relaxedDomain)u+=(u.indexOf('?')==-1?'?':'&')+'mce_rdomain='+tinymce.relaxedDomain;u=tinymce._addVer(u);try{if(isIE&&mo){w=1;window.showModalDialog(u,window,f);}else w=window.open(u,s.name,f);}catch(ex){}if(!w)alert(t.editor.getLang('popup_blocked'));},close:function(w){w.close();this.onClose.dispatch(this);},createInstance:function(cl,a,b,c,d,e){var f=tinymce.resolve(cl);return new f(a,b,c,d,e);},confirm:function(t,cb,s){cb.call(s||this,confirm(this._decode(this.editor.getLang(t,t))));},alert:function(tx,cb,s){var t=this;alert(t._decode(t.editor.getLang(tx,tx)));if(cb)cb.call(s||t);},_decode:function(s){return tinymce.DOM.decode(s).replace(/\\n/g,'\n');}});}());
\ No newline at end of file
diff --git a/jscripts/tiny_mce/tiny_mce_popup.js b/jscripts/tiny_mce/tiny_mce_popup.js
new file mode 100644 (file)
index 0000000..92a3a8e
--- /dev/null
@@ -0,0 +1,275 @@
+// Some global instances\r
+var tinymce = null, tinyMCEPopup, tinyMCE;\r
+\r
+tinyMCEPopup = {\r
+       init : function() {\r
+               var t = this, w, ti, li, q, i, it;\r
+\r
+               li = ('' + document.location.search).replace(/^\?/, '').split('&');\r
+               q = {};\r
+               for (i=0; i<li.length; i++) {\r
+                       it = li[i].split('=');\r
+                       q[unescape(it[0])] = unescape(it[1]);\r
+               }\r
+\r
+               if (q.mce_rdomain)\r
+                       document.domain = q.mce_rdomain;\r
+\r
+               // Find window & API\r
+               w = t.getWin();\r
+               tinymce = w.tinymce;\r
+               tinyMCE = w.tinyMCE;\r
+               t.editor = tinymce.EditorManager.activeEditor;\r
+               t.params = t.editor.windowManager.params;\r
+\r
+               // Setup local DOM\r
+               t.dom = t.editor.windowManager.createInstance('tinymce.dom.DOMUtils', document);\r
+               t.dom.loadCSS(t.editor.settings.popup_css);\r
+\r
+               // Setup on init listeners\r
+               t.listeners = [];\r
+               t.onInit = {\r
+                       add : function(f, s) {\r
+                               t.listeners.push({func : f, scope : s});\r
+                       }\r
+               };\r
+\r
+               t.isWindow = !t.getWindowArg('mce_inline');\r
+               t.id = t.getWindowArg('mce_window_id');\r
+               t.editor.windowManager.onOpen.dispatch(t.editor.windowManager, window);\r
+       },\r
+\r
+       getWin : function() {\r
+               return window.dialogArguments || opener || parent || top;\r
+       },\r
+\r
+       getWindowArg : function(n, dv) {\r
+               var v = this.params[n];\r
+\r
+               return tinymce.is(v) ? v : dv;\r
+       },\r
+\r
+       getParam : function(n, dv) {\r
+               return this.editor.getParam(n, dv);\r
+       },\r
+\r
+       getLang : function(n, dv) {\r
+               return this.editor.getLang(n, dv);\r
+       },\r
+\r
+       execCommand : function(cmd, ui, val, a) {\r
+               a = a || {};\r
+               a.skip_focus = 1;\r
+\r
+               this.restoreSelection();\r
+               return this.editor.execCommand(cmd, ui, val, a);\r
+       },\r
+\r
+       resizeToInnerSize : function() {\r
+               var t = this, n, b = document.body, vp = t.dom.getViewPort(window), dw, dh;\r
+\r
+               dw = t.getWindowArg('mce_width') - vp.w;\r
+               dh = t.getWindowArg('mce_height') - vp.h;\r
+\r
+               if (t.isWindow)\r
+                       window.resizeBy(dw, dh);\r
+               else\r
+                       t.editor.windowManager.resizeBy(dw, dh, t.id);\r
+       },\r
+\r
+       executeOnLoad : function(s) {\r
+               this.onInit.add(function() {\r
+                       eval(s);\r
+               });\r
+       },\r
+\r
+       storeSelection : function() {\r
+               this.editor.windowManager.bookmark = tinyMCEPopup.editor.selection.getBookmark('simple');\r
+       },\r
+\r
+       restoreSelection : function() {\r
+               var t = tinyMCEPopup;\r
+\r
+               if (!t.isWindow && tinymce.isIE)\r
+                       t.editor.selection.moveToBookmark(t.editor.windowManager.bookmark);\r
+       },\r
+\r
+       requireLangPack : function() {\r
+               var u = this.getWindowArg('plugin_url') || this.getWindowArg('theme_url');\r
+\r
+               if (u && this.editor.settings.language) {\r
+                       u += '/langs/' + this.editor.settings.language + '_dlg.js';\r
+\r
+                       if (!tinymce.ScriptLoader.isDone(u)) {\r
+                               document.write('<script type="text/javascript" src="' + tinymce._addVer(u) + '"></script>');\r
+                               tinymce.ScriptLoader.markDone(u);\r
+                       }\r
+               }\r
+       },\r
+\r
+       pickColor : function(e, element_id) {\r
+               this.execCommand('mceColorPicker', true, {\r
+                       color : document.getElementById(element_id).value,\r
+                       func : function(c) {\r
+                               document.getElementById(element_id).value = c;\r
+\r
+                               try {\r
+                                       document.getElementById(element_id).onchange();\r
+                               } catch (ex) {\r
+                                       // Try fire event, ignore errors\r
+                               }\r
+                       }\r
+               });\r
+       },\r
+\r
+       openBrowser : function(element_id, type, option) {\r
+               tinyMCEPopup.restoreSelection();\r
+               this.editor.execCallback('file_browser_callback', element_id, document.getElementById(element_id).value, type, window);\r
+       },\r
+\r
+       close : function() {\r
+               var t = this;\r
+\r
+               // To avoid domain relaxing issue in Opera\r
+               function close() {\r
+                       t.editor.windowManager.close(window, t.id);\r
+                       tinymce = tinyMCE = t.editor = t.params = t.dom = t.dom.doc = null; // Cleanup\r
+               };\r
+\r
+               if (tinymce.isOpera)\r
+                       t.getWin().setTimeout(close, 0);\r
+               else\r
+                       close();\r
+       },\r
+\r
+       // Internal functions   \r
+\r
+       _restoreSelection : function() {\r
+               var e = window.event.srcElement;\r
+\r
+               if (e.nodeName == 'INPUT' && (e.type == 'submit' || e.type == 'button'))\r
+                       tinyMCEPopup.restoreSelection();\r
+       },\r
+\r
+/*     _restoreSelection : function() {\r
+               var e = window.event.srcElement;\r
+\r
+               // If user focus a non text input or textarea\r
+               if ((e.nodeName != 'INPUT' && e.nodeName != 'TEXTAREA') || e.type != 'text')\r
+                       tinyMCEPopup.restoreSelection();\r
+       },*/\r
+\r
+       _onDOMLoaded : function() {\r
+               var t = this, ti = document.title, bm, h;\r
+\r
+               // Translate page\r
+               h = document.body.innerHTML;\r
+\r
+               // Replace a=x with a="x" in IE\r
+               if (tinymce.isIE)\r
+                       h = h.replace(/ (value|title|alt)=([^"][^\s>]+)/gi, ' $1="$2"')\r
+\r
+               document.dir = t.editor.getParam('directionality','');\r
+               document.body.innerHTML = t.editor.translate(h);\r
+               document.title = ti = t.editor.translate(ti);\r
+               document.body.style.display = '';\r
+\r
+               // Restore selection in IE when focus is placed on a non textarea or input element of the type text\r
+               if (tinymce.isIE)\r
+                       document.attachEvent('onmouseup', tinyMCEPopup._restoreSelection);\r
+\r
+               t.restoreSelection();\r
+               t.resizeToInnerSize();\r
+\r
+               // Set inline title\r
+               if (!t.isWindow)\r
+                       t.editor.windowManager.setTitle(ti, t.id);\r
+               else\r
+                       window.focus();\r
+\r
+               if (!tinymce.isIE && !t.isWindow) {\r
+                       tinymce.dom.Event._add(document, 'focus', function() {\r
+                               t.editor.windowManager.focus(t.id)\r
+                       });\r
+               }\r
+\r
+               // Patch for accessibility\r
+               tinymce.each(t.dom.select('select'), function(e) {\r
+                       e.onkeydown = tinyMCEPopup._accessHandler;\r
+               });\r
+\r
+               // Call onInit\r
+               // Init must be called before focus so the selection won't get lost by the focus call\r
+               tinymce.each(t.listeners, function(o) {\r
+                       o.func.call(o.scope, t.editor);\r
+               });\r
+\r
+               // Move focus to window\r
+               if (t.getWindowArg('mce_auto_focus', true)) {\r
+                       window.focus();\r
+\r
+                       // Focus element with mceFocus class\r
+                       tinymce.each(document.forms, function(f) {\r
+                               tinymce.each(f.elements, function(e) {\r
+                                       if (t.dom.hasClass(e, 'mceFocus') && !e.disabled) {\r
+                                               e.focus();\r
+                                               return false; // Break loop\r
+                                       }\r
+                               });\r
+                       });\r
+               }\r
+\r
+               document.onkeyup = tinyMCEPopup._closeWinKeyHandler;\r
+       },\r
+\r
+       _accessHandler : function(e) {\r
+               e = e || window.event;\r
+\r
+               if (e.keyCode == 13 || e.keyCode == 32) {\r
+                       e = e.target || e.srcElement;\r
+\r
+                       if (e.onchange)\r
+                               e.onchange();\r
+\r
+                       return tinymce.dom.Event.cancel(e);\r
+               }\r
+       },\r
+\r
+       _closeWinKeyHandler : function(e) {\r
+               e = e || window.event;\r
+\r
+               if (e.keyCode == 27)\r
+                       tinyMCEPopup.close();\r
+       },\r
+\r
+       _wait : function() {\r
+               var t = this, ti;\r
+\r
+               if (tinymce.isIE && document.location.protocol != 'https:') {\r
+                       // Fake DOMContentLoaded on IE\r
+                       document.write('<script id=__ie_onload defer src=\'javascript:""\';><\/script>');\r
+                       document.getElementById("__ie_onload").onreadystatechange = function() {\r
+                               if (this.readyState == "complete") {\r
+                                       t._onDOMLoaded();\r
+                                       document.getElementById("__ie_onload").onreadystatechange = null; // Prevent leak\r
+                               }\r
+                       };\r
+               } else {\r
+                       if (tinymce.isIE || tinymce.isWebKit) {\r
+                               ti = setInterval(function() {\r
+                                       if (/loaded|complete/.test(document.readyState)) {\r
+                                               clearInterval(ti);\r
+                                               t._onDOMLoaded();\r
+                                       }\r
+                               }, 10);\r
+                       } else {\r
+                               window.addEventListener('DOMContentLoaded', function() {\r
+                                       t._onDOMLoaded();\r
+                               }, false);\r
+                       }\r
+               }\r
+       }\r
+};\r
+\r
+tinyMCEPopup.init();\r
+tinyMCEPopup._wait(); // Wait for DOM Content Loaded\r
diff --git a/jscripts/tiny_mce/tiny_mce_src.js b/jscripts/tiny_mce/tiny_mce_src.js
new file mode 100644 (file)
index 0000000..3ee6bbb
--- /dev/null
@@ -0,0 +1,10423 @@
+\r
+/* file:jscripts/tiny_mce/classes/tinymce.js */\r
+\r
+var tinymce = {\r
+       majorVersion : '3',\r
+       minorVersion : '0.7',\r
+       releaseDate : '2008-04-14',\r
+\r
+       _init : function() {\r
+               var t = this, d = document, w = window, na = navigator, ua = na.userAgent, i, nl, n, base;\r
+\r
+               // Browser checks\r
+               t.isOpera = w.opera && opera.buildNumber;\r
+               t.isWebKit = /WebKit/.test(ua);\r
+               t.isOldWebKit = t.isWebKit && !w.getSelection().getRangeAt;\r
+               t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName);\r
+               t.isIE6 = t.isIE && /MSIE [56]/.test(ua);\r
+               t.isGecko = !t.isWebKit && /Gecko/.test(ua);\r
+               t.isMac = ua.indexOf('Mac') != -1;\r
+\r
+               // TinyMCE .NET webcontrol might be setting the values for TinyMCE\r
+               if (w.tinyMCEPreInit) {\r
+                       t.suffix = tinyMCEPreInit.suffix;\r
+                       t.baseURL = tinyMCEPreInit.base;\r
+                       return;\r
+               }\r
+\r
+               // Get suffix and base\r
+               t.suffix = '';\r
+\r
+               // If base element found, add that infront of baseURL\r
+               nl = d.getElementsByTagName('base');\r
+               for (i=0; i<nl.length; i++) {\r
+                       if (nl[i].href)\r
+                               base = nl[i].href;\r
+               }\r
+\r
+               function getBase(n) {\r
+                       if (n.src && /tiny_mce(|_dev|_src|_gzip|_jquery|_prototype).js/.test(n.src)) {\r
+                               if (/_(src|dev)\.js/g.test(n.src))\r
+                                       t.suffix = '_src';\r
+\r
+                               t.baseURL = n.src.substring(0, n.src.lastIndexOf('/'));\r
+\r
+                               // If path to script is relative and a base href was found add that one infront\r
+                               if (base && t.baseURL.indexOf('://') == -1)\r
+                                       t.baseURL = base + t.baseURL;\r
+\r
+                               return t.baseURL;\r
+                       }\r
+\r
+                       return null;\r
+               };\r
+\r
+               // Check document\r
+               nl = d.getElementsByTagName('script');\r
+               for (i=0; i<nl.length; i++) {\r
+                       if (getBase(nl[i]))\r
+                               return;\r
+               }\r
+\r
+               // Check head\r
+               n = d.getElementsByTagName('head')[0];\r
+               if (n) {\r
+                       nl = n.getElementsByTagName('script');\r
+                       for (i=0; i<nl.length; i++) {\r
+                               if (getBase(nl[i]))\r
+                                       return;\r
+                       }\r
+               }\r
+\r
+               return;\r
+       },\r
+\r
+       is : function(o, t) {\r
+               var n = typeof(o);\r
+\r
+               if (!t)\r
+                       return n != 'undefined';\r
+\r
+               if (t == 'array' && (o instanceof Array))\r
+                       return true;\r
+\r
+               return n == t;\r
+       },\r
+\r
+       // #if !jquery\r
+\r
+       each : function(o, cb, s) {\r
+               var n, l;\r
+\r
+               if (!o)\r
+                       return 0;\r
+\r
+               s = s || o;\r
+\r
+               if (typeof(o.length) != 'undefined') {\r
+                       // Indexed arrays, needed for Safari\r
+                       for (n=0, l = o.length; n<l; n++) {\r
+                               if (cb.call(s, o[n], n, o) === false)\r
+                                       return 0;\r
+                       }\r
+               } else {\r
+                       // Hashtables\r
+                       for (n in o) {\r
+                               if (o.hasOwnProperty(n)) {\r
+                                       if (cb.call(s, o[n], n, o) === false)\r
+                                               return 0;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               return 1;\r
+       },\r
+\r
+       map : function(a, f) {\r
+               var o = [];\r
+\r
+               tinymce.each(a, function(v) {\r
+                       o.push(f(v));\r
+               });\r
+\r
+               return o;\r
+       },\r
+\r
+       grep : function(a, f) {\r
+               var o = [];\r
+\r
+               tinymce.each(a, function(v) {\r
+                       if (!f || f(v))\r
+                               o.push(v);\r
+               });\r
+\r
+               return o;\r
+       },\r
+\r
+       inArray : function(a, v) {\r
+               var i, l;\r
+\r
+               if (a) {\r
+                       for (i = 0, l = a.length; i < l; i++) {\r
+                               if (a[i] === v)\r
+                                       return i;\r
+                       }\r
+               }\r
+\r
+               return -1;\r
+       },\r
+\r
+       extend : function(o, e) {\r
+               var i, a = arguments;\r
+\r
+               for (i=1; i<a.length; i++) {\r
+                       e = a[i];\r
+\r
+                       tinymce.each(e, function(v, n) {\r
+                               if (typeof(v) !== 'undefined')\r
+                                       o[n] = v;\r
+                       });\r
+               }\r
+\r
+               return o;\r
+       },\r
+\r
+       trim : function(s) {\r
+               return (s ? '' + s : '').replace(/^\s*|\s*$/g, '');\r
+       },\r
+\r
+       // #endif\r
+\r
+       create : function(s, p) {\r
+               var t = this, sp, ns, cn, scn, c, de = 0;\r
+\r
+               // Parse : <prefix> <class>:<super class>\r
+               s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);\r
+               cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name\r
+\r
+               // Create namespace for new class\r
+               ns = t.createNS(s[3].replace(/\.\w+$/, ''));\r
+\r
+               // Class already exists\r
+               if (ns[cn])\r
+                       return;\r
+\r
+               // Make pure static class\r
+               if (s[2] == 'static') {\r
+                       ns[cn] = p;\r
+\r
+                       if (this.onCreate)\r
+                               this.onCreate(s[2], s[3], ns[cn]);\r
+\r
+                       return;\r
+               }\r
+\r
+               // Create default constructor\r
+               if (!p[cn]) {\r
+                       p[cn] = function() {};\r
+                       de = 1;\r
+               }\r
+\r
+               // Add constructor and methods\r
+               ns[cn] = p[cn];\r
+               t.extend(ns[cn].prototype, p);\r
+\r
+               // Extend\r
+               if (s[5]) {\r
+                       sp = t.resolve(s[5]).prototype;\r
+                       scn = s[5].match(/\.(\w+)$/i)[1]; // Class name\r
+\r
+                       // Extend constructor\r
+                       c = ns[cn];\r
+                       if (de) {\r
+                               // Add passthrough constructor\r
+                               ns[cn] = function() {\r
+                                       return sp[scn].apply(this, arguments);\r
+                               };\r
+                       } else {\r
+                               // Add inherit constructor\r
+                               ns[cn] = function() {\r
+                                       this.parent = sp[scn];\r
+                                       return c.apply(this, arguments);\r
+                               };\r
+                       }\r
+                       ns[cn].prototype[cn] = ns[cn];\r
+\r
+                       // Add super methods\r
+                       t.each(sp, function(f, n) {\r
+                               ns[cn].prototype[n] = sp[n];\r
+                       });\r
+\r
+                       // Add overridden methods\r
+                       t.each(p, function(f, n) {\r
+                               // Extend methods if needed\r
+                               if (sp[n]) {\r
+                                       ns[cn].prototype[n] = function() {\r
+                                               this.parent = sp[n];\r
+                                               return f.apply(this, arguments);\r
+                                       };\r
+                               } else {\r
+                                       if (n != cn)\r
+                                               ns[cn].prototype[n] = f;\r
+                               }\r
+                       });\r
+               }\r
+\r
+               // Add static methods\r
+               t.each(p['static'], function(f, n) {\r
+                       ns[cn][n] = f;\r
+               });\r
+\r
+               if (this.onCreate)\r
+                       this.onCreate(s[2], s[3], ns[cn].prototype);\r
+       },\r
+\r
+       walk : function(o, f, n, s) {\r
+               s = s || this;\r
+\r
+               if (o) {\r
+                       if (n)\r
+                               o = o[n];\r
+\r
+                       tinymce.each(o, function(o, i) {\r
+                               if (f.call(s, o, i, n) === false)\r
+                                       return false;\r
+\r
+                               tinymce.walk(o, f, n, s);\r
+                       });\r
+               }\r
+       },\r
+\r
+       createNS : function(n, o) {\r
+               var i, v;\r
+\r
+               o = o || window;\r
+\r
+               n = n.split('.');\r
+               for (i=0; i<n.length; i++) {\r
+                       v = n[i];\r
+\r
+                       if (!o[v])\r
+                               o[v] = {};\r
+\r
+                       o = o[v];\r
+               }\r
+\r
+               return o;\r
+       },\r
+\r
+       resolve : function(n, o) {\r
+               var i, l;\r
+\r
+               o = o || window;\r
+\r
+               n = n.split('.');\r
+               for (i=0, l = n.length; i<l; i++) {\r
+                       o = o[n[i]];\r
+\r
+                       if (!o)\r
+                               break;\r
+               }\r
+\r
+               return o;\r
+       },\r
+\r
+       addUnload : function(f, s) {\r
+               var t = this, w = window;\r
+\r
+               f = {func : f, scope : s || this};\r
+\r
+               if (!t.unloads) {\r
+                       function unload() {\r
+                               var li = t.unloads, o, n;\r
+\r
+                               if (li) {\r
+                                       // Call unload handlers\r
+                                       for (n in li) {\r
+                                               o = li[n];\r
+\r
+                                               if (o && o.func)\r
+                                                       o.func.call(o.scope, 1); // Send in one arg to distinct unload and user destroy\r
+                                       }\r
+\r
+                                       // Detach unload function\r
+                                       if (w.detachEvent) {\r
+                                               w.detachEvent('onbeforeunload', fakeUnload);\r
+                                               w.detachEvent('onunload', unload);\r
+                                       } else if (w.removeEventListener)\r
+                                               w.removeEventListener('unload', unload, false);\r
+\r
+                                       // Destroy references\r
+                                       t.unloads = o = li = w = unload = null;\r
+\r
+                                       // Run garbarge collector on IE\r
+                                       if (window.CollectGarbage)\r
+                                               window.CollectGarbage();\r
+                               }\r
+                       };\r
+\r
+                       function fakeUnload() {\r
+                               var d = document;\r
+\r
+                               // Is there things still loading, then do some magic\r
+                               if (d.readyState == 'interactive') {\r
+                                       function stop() {\r
+                                               // Prevent memory leak\r
+                                               d.detachEvent('onstop', stop);\r
+\r
+                                               // Call unload handler\r
+                                               unload();\r
+\r
+                                               d = null;\r
+                                       };\r
+\r
+                                       // Fire unload when the currently loading page is stopped\r
+                                       d.attachEvent('onstop', stop);\r
+\r
+                                       // Remove onstop listener after a while to prevent the unload function\r
+                                       // to execute if the user presses cancel in an onbeforeunload\r
+                                       // confirm dialog and then presses the browser stop button\r
+                                       window.setTimeout(function() {\r
+                                               d.detachEvent('onstop', stop);\r
+                                       }, 0);\r
+                               }\r
+                       };\r
+\r
+                       // Attach unload handler\r
+                       if (w.attachEvent) {\r
+                               w.attachEvent('onunload', unload);\r
+                               w.attachEvent('onbeforeunload', fakeUnload);\r
+                       } else if (w.addEventListener)\r
+                               w.addEventListener('unload', unload, false);\r
+\r
+                       // Setup initial unload handler array\r
+                       t.unloads = [f];\r
+               } else\r
+                       t.unloads.push(f);\r
+\r
+               return f;\r
+       },\r
+\r
+       removeUnload : function(f) {\r
+               var u = this.unloads, r = null;\r
+\r
+               tinymce.each(u, function(o, i) {\r
+                       if (o && o.func == f) {\r
+                               u.splice(i, 1);\r
+                               r = f;\r
+                               return false;\r
+                       }\r
+               });\r
+\r
+               return r;\r
+       },\r
+\r
+       explode : function(s, d) {\r
+               return tinymce.map(s.split(d || ','), tinymce.trim);\r
+       },\r
+\r
+       _addVer : function(u, s) {\r
+               return u + (u.indexOf('?') == -1 ? '?' : '&') + 'v=' + (tinymce.majorVersion + tinymce.minorVersion).replace(/[^0-9]/g, '');\r
+       }\r
+\r
+       };\r
+\r
+// Required for GZip AJAX loading\r
+window.tinymce = tinymce;\r
+\r
+// Initialize the API\r
+tinymce._init();\r
+\r
+/* file:jscripts/tiny_mce/classes/adapter/jquery/adapter.js */\r
+\r
+\r
+/* file:jscripts/tiny_mce/classes/adapter/prototype/adapter.js */\r
+\r
+\r
+/* file:jscripts/tiny_mce/classes/util/Dispatcher.js */\r
+\r
+tinymce.create('tinymce.util.Dispatcher', {\r
+       scope : null,\r
+       listeners : null,\r
+\r
+       Dispatcher : function(s) {\r
+               this.scope = s || this;\r
+               this.listeners = [];\r
+       },\r
+\r
+       add : function(cb, s) {\r
+               this.listeners.push({cb : cb, scope : s || this.scope});\r
+\r
+               return cb;\r
+       },\r
+\r
+       addToTop : function(cb, s) {\r
+               this.listeners.unshift({cb : cb, scope : s || this.scope});\r
+\r
+               return cb;\r
+       },\r
+\r
+       remove : function(cb) {\r
+               var l = this.listeners, o = null;\r
+\r
+               tinymce.each(l, function(c, i) {\r
+                       if (cb == c.cb) {\r
+                               o = cb;\r
+                               l.splice(i, 1);\r
+                               return false;\r
+                       }\r
+               });\r
+\r
+               return o;\r
+       },\r
+\r
+       dispatch : function() {\r
+               var s, a = arguments, i, li = this.listeners, c;\r
+\r
+               // Needs to be a real loop since the listener count might change while looping\r
+               // And this is also more efficient\r
+               for (i = 0; i<li.length; i++) {\r
+                       c = li[i];\r
+                       s = c.cb.apply(c.scope, a);\r
+\r
+                       if (s === false)\r
+                               break;\r
+               }\r
+\r
+               return s;\r
+       }\r
+\r
+       });\r
+\r
+/* file:jscripts/tiny_mce/classes/util/URI.js */\r
+\r
+(function() {\r
+       var each = tinymce.each;\r
+\r
+       tinymce.create('tinymce.util.URI', {\r
+               URI : function(u, s) {\r
+                       var t = this, o, a, b;\r
+\r
+                       // Default settings\r
+                       s = t.settings = s || {};\r
+\r
+                       // Strange app protocol or local anchor\r
+                       if (/^(mailto|news|javascript|about):/i.test(u) || /^\s*#/.test(u)) {\r
+                               t.source = u;\r
+                               return;\r
+                       }\r
+\r
+                       // Absolute path with no host, fake host and protocol\r
+                       if (u.indexOf('/') === 0 && u.indexOf('//') !== 0)\r
+                               u = (s.base_uri ? s.base_uri.protocol || 'http' : 'http') + '://mce_host' + u;\r
+\r
+                       // Relative path\r
+                       if (u.indexOf('://') === -1 && u.indexOf('//') !== 0)\r
+                               u = (s.base_uri.protocol || 'http') + '://mce_host' + t.toAbsPath(s.base_uri.path, u);\r
+\r
+                       // Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri)\r
+                       u = u.replace(/@@/g, '(mce_at)'); // Zope 3 workaround, they use @@something\r
+                       u = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u);\r
+                       each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], function(v, i) {\r
+                               var s = u[i];\r
+\r
+                               // Zope 3 workaround, they use @@something\r
+                               if (s)\r
+                                       s = s.replace(/\(mce_at\)/g, '@@');\r
+\r
+                               t[v] = s;\r
+                       });\r
+\r
+                       if (b = s.base_uri) {\r
+                               if (!t.protocol)\r
+                                       t.protocol = b.protocol;\r
+\r
+                               if (!t.userInfo)\r
+                                       t.userInfo = b.userInfo;\r
+\r
+                               if (!t.port && t.host == 'mce_host')\r
+                                       t.port = b.port;\r
+\r
+                               if (!t.host || t.host == 'mce_host')\r
+                                       t.host = b.host;\r
+\r
+                               t.source = '';\r
+                       }\r
+\r
+                       //t.path = t.path || '/';\r
+               },\r
+\r
+               setPath : function(p) {\r
+                       var t = this;\r
+\r
+                       p = /^(.*?)\/?(\w+)?$/.exec(p);\r
+\r
+                       // Update path parts\r
+                       t.path = p[0];\r
+                       t.directory = p[1];\r
+                       t.file = p[2];\r
+\r
+                       // Rebuild source\r
+                       t.source = '';\r
+                       t.getURI();\r
+               },\r
+\r
+               toRelative : function(u) {\r
+                       var t = this, o;\r
+\r
+                       u = new tinymce.util.URI(u, {base_uri : t});\r
+\r
+                       // Not on same domain/port or protocol\r
+                       if ((u.host != 'mce_host' && t.host != u.host && u.host) || t.port != u.port || t.protocol != u.protocol)\r
+                               return u.getURI();\r
+\r
+                       o = t.toRelPath(t.path, u.path);\r
+\r
+                       // Add query\r
+                       if (u.query)\r
+                               o += '?' + u.query;\r
+\r
+                       // Add anchor\r
+                       if (u.anchor)\r
+                               o += '#' + u.anchor;\r
+\r
+                       return o;\r
+               },\r
+       \r
+               toAbsolute : function(u, nh) {\r
+                       var u = new tinymce.util.URI(u, {base_uri : this});\r
+\r
+                       return u.getURI(this.host == u.host ? nh : 0);\r
+               },\r
+\r
+               toRelPath : function(base, path) {\r
+                       var items, bp = 0, out = '', i;\r
+\r
+                       // Split the paths\r
+                       base = base.substring(0, base.lastIndexOf('/'));\r
+                       base = base.split('/');\r
+                       items = path.split('/');\r
+\r
+                       if (base.length >= items.length) {\r
+                               for (i = 0; i < base.length; i++) {\r
+                                       if (i >= items.length || base[i] != items[i]) {\r
+                                               bp = i + 1;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       if (base.length < items.length) {\r
+                               for (i = 0; i < items.length; i++) {\r
+                                       if (i >= base.length || base[i] != items[i]) {\r
+                                               bp = i + 1;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       if (bp == 1)\r
+                               return path;\r
+\r
+                       for (i = 0; i < base.length - (bp - 1); i++)\r
+                               out += "../";\r
+\r
+                       for (i = bp - 1; i < items.length; i++) {\r
+                               if (i != bp - 1)\r
+                                       out += "/" + items[i];\r
+                               else\r
+                                       out += items[i];\r
+                       }\r
+\r
+                       return out;\r
+               },\r
+\r
+               toAbsPath : function(base, path) {\r
+                       var i, nb = 0, o = [];\r
+\r
+                       // Split paths\r
+                       base = base.split('/');\r
+                       path = path.split('/');\r
+\r
+                       // Remove empty chunks\r
+                       each(base, function(k) {\r
+                               if (k)\r
+                                       o.push(k);\r
+                       });\r
+\r
+                       base = o;\r
+\r
+                       // Merge relURLParts chunks\r
+                       for (i = path.length - 1, o = []; i >= 0; i--) {\r
+                               // Ignore empty or .\r
+                               if (path[i].length == 0 || path[i] == ".")\r
+                                       continue;\r
+\r
+                               // Is parent\r
+                               if (path[i] == '..') {\r
+                                       nb++;\r
+                                       continue;\r
+                               }\r
+\r
+                               // Move up\r
+                               if (nb > 0) {\r
+                                       nb--;\r
+                                       continue;\r
+                               }\r
+\r
+                               o.push(path[i]);\r
+                       }\r
+\r
+                       i = base.length - nb;\r
+\r
+                       // If /a/b/c or /\r
+                       if (i <= 0)\r
+                               return '/' + o.reverse().join('/');\r
+\r
+                       return '/' + base.slice(0, i).join('/') + '/' + o.reverse().join('/');\r
+               },\r
+\r
+               getURI : function(nh) {\r
+                       var s, t = this;\r
+\r
+                       // Rebuild source\r
+                       if (!t.source || nh) {\r
+                               s = '';\r
+\r
+                               if (!nh) {\r
+                                       if (t.protocol)\r
+                                               s += t.protocol + '://';\r
+\r
+                                       if (t.userInfo)\r
+                                               s += t.userInfo + '@';\r
+\r
+                                       if (t.host)\r
+                                               s += t.host;\r
+\r
+                                       if (t.port)\r
+                                               s += ':' + t.port;\r
+                               }\r
+\r
+                               if (t.path)\r
+                                       s += t.path;\r
+\r
+                               if (t.query)\r
+                                       s += '?' + t.query;\r
+\r
+                               if (t.anchor)\r
+                                       s += '#' + t.anchor;\r
+\r
+                               t.source = s;\r
+                       }\r
+\r
+                       return t.source;\r
+               }\r
+\r
+               });\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/util/Cookie.js */\r
+\r
+(function() {\r
+       var each = tinymce.each;\r
+\r
+       tinymce.create('static tinymce.util.Cookie', {\r
+               getHash : function(n) {\r
+                       var v = this.get(n), h;\r
+\r
+                       if (v) {\r
+                               each(v.split('&'), function(v) {\r
+                                       v = v.split('=');\r
+                                       h = h || {};\r
+                                       h[unescape(v[0])] = unescape(v[1]);\r
+                               });\r
+                       }\r
+\r
+                       return h;\r
+               },\r
+\r
+               setHash : function(n, v, e, p, d, s) {\r
+                       var o = '';\r
+\r
+                       each(v, function(v, k) {\r
+                               o += (!o ? '' : '&') + escape(k) + '=' + escape(v);\r
+                       });\r
+\r
+                       this.set(n, o, e, p, d, s);\r
+               },\r
+\r
+               get : function(n) {\r
+                       var c = document.cookie, e, p = n + "=", b;\r
+\r
+                       // Strict mode\r
+                       if (!c)\r
+                               return;\r
+\r
+                       b = c.indexOf("; " + p);\r
+\r
+                       if (b == -1) {\r
+                               b = c.indexOf(p);\r
+\r
+                               if (b != 0)\r
+                                       return null;\r
+                       } else\r
+                               b += 2;\r
+\r
+                       e = c.indexOf(";", b);\r
+\r
+                       if (e == -1)\r
+                               e = c.length;\r
+\r
+                       return unescape(c.substring(b + p.length, e));\r
+               },\r
+\r
+               set : function(n, v, e, p, d, s) {\r
+                       document.cookie = n + "=" + escape(v) +\r
+                               ((e) ? "; expires=" + e.toGMTString() : "") +\r
+                               ((p) ? "; path=" + escape(p) : "") +\r
+                               ((d) ? "; domain=" + d : "") +\r
+                               ((s) ? "; secure" : "");\r
+               },\r
+\r
+               remove : function(n, p) {\r
+                       var d = new Date();\r
+\r
+                       d.setTime(d.getTime() - 1000);\r
+\r
+                       this.set(n, '', d, p, d);\r
+               }\r
+\r
+               });\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/util/JSON.js */\r
+\r
+tinymce.create('static tinymce.util.JSON', {\r
+       serialize : function(o) {\r
+               var i, v, s = tinymce.util.JSON.serialize, t;\r
+\r
+               if (o == null)\r
+                       return 'null';\r
+\r
+               t = typeof o;\r
+\r
+               if (t == 'string') {\r
+                       v = '\bb\tt\nn\ff\rr\""\'\'\\\\';\r
+\r
+                       return '"' + o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'])/g, function(a, b) {\r
+                               i = v.indexOf(b);\r
+\r
+                               if (i + 1)\r
+                                       return '\\' + v.charAt(i + 1);\r
+\r
+                               a = b.charCodeAt().toString(16);\r
+\r
+                               return '\\u' + '0000'.substring(a.length) + a;\r
+                       }) + '"';\r
+               }\r
+\r
+               if (t == 'object') {\r
+                       if (o instanceof Array) {\r
+                                       for (i=0, v = '['; i<o.length; i++)\r
+                                               v += (i > 0 ? ',' : '') + s(o[i]);\r
+\r
+                                       return v + ']';\r
+                               }\r
+\r
+                               v = '{';\r
+\r
+                               for (i in o)\r
+                                       v += typeof o[i] != 'function' ? (v.length > 1 ? ',"' : '"') + i + '":' + s(o[i]) : '';\r
+\r
+                               return v + '}';\r
+               }\r
+\r
+               return '' + o;\r
+       },\r
+\r
+       parse : function(s) {\r
+               try {\r
+                       return eval('(' + s + ')');\r
+               } catch (ex) {\r
+                       // Ignore\r
+               }\r
+       }\r
+\r
+       });\r
+\r
+/* file:jscripts/tiny_mce/classes/util/XHR.js */\r
+\r
+tinymce.create('static tinymce.util.XHR', {\r
+       send : function(o) {\r
+               var x, t, w = window, c = 0;\r
+\r
+               // Default settings\r
+               o.scope = o.scope || this;\r
+               o.success_scope = o.success_scope || o.scope;\r
+               o.error_scope = o.error_scope || o.scope;\r
+               o.async = o.async === false ? false : true;\r
+               o.data = o.data || '';\r
+\r
+               function get(s) {\r
+                       x = 0;\r
+\r
+                       try {\r
+                               x = new ActiveXObject(s);\r
+                       } catch (ex) {\r
+                       }\r
+\r
+                       return x;\r
+               };\r
+\r
+               x = w.XMLHttpRequest ? new XMLHttpRequest() : get('Microsoft.XMLHTTP') || get('Msxml2.XMLHTTP');\r
+\r
+               if (x) {\r
+                       if (x.overrideMimeType)\r
+                               x.overrideMimeType(o.content_type);\r
+\r
+                       x.open(o.type || (o.data ? 'POST' : 'GET'), o.url, o.async);\r
+\r
+                       if (o.content_type)\r
+                               x.setRequestHeader('Content-Type', o.content_type);\r
+\r
+                       x.send(o.data);\r
+\r
+                       // Wait for response, onReadyStateChange can not be used since it leaks memory in IE\r
+                       t = w.setInterval(function() {\r
+                               if (x.readyState == 4 || c++ > 10000) {\r
+                                       w.clearInterval(t);\r
+\r
+                                       if (o.success && c < 10000 && x.status == 200)\r
+                                               o.success.call(o.success_scope, '' + x.responseText, x, o);\r
+                                       else if (o.error)\r
+                                               o.error.call(o.error_scope, c > 10000 ? 'TIMED_OUT' : 'GENERAL', x, o);\r
+\r
+                                       x = null;\r
+                               }\r
+                       }, 10);\r
+               }\r
+\r
+               }\r
+});\r
+\r
+/* file:jscripts/tiny_mce/classes/util/JSONRequest.js */\r
+\r
+(function() {\r
+       var extend = tinymce.extend, JSON = tinymce.util.JSON, XHR = tinymce.util.XHR;\r
+\r
+       tinymce.create('tinymce.util.JSONRequest', {\r
+               JSONRequest : function(s) {\r
+                       this.settings = extend({\r
+                       }, s);\r
+                       this.count = 0;\r
+               },\r
+\r
+               send : function(o) {\r
+                       var ecb = o.error, scb = o.success;\r
+\r
+                       o = extend(this.settings, o);\r
+\r
+                       o.success = function(c, x) {\r
+                               c = JSON.parse(c);\r
+\r
+                               if (typeof(c) == 'undefined') {\r
+                                       c = {\r
+                                               error : 'JSON Parse error.'\r
+                                       };\r
+                               }\r
+\r
+                               if (c.error)\r
+                                       ecb.call(o.error_scope || o.scope, c.error, x);\r
+                               else\r
+                                       scb.call(o.success_scope || o.scope, c.result);\r
+                       };\r
+\r
+                       o.error = function(ty, x) {\r
+                               ecb.call(o.error_scope || o.scope, ty, x);\r
+                       };\r
+\r
+                       o.data = JSON.serialize({\r
+                               id : o.id || 'c' + (this.count++),\r
+                               method : o.method,\r
+                               params : o.params\r
+                       });\r
+\r
+                       // JSON content type for Ruby on rails. Bug: #1883287\r
+                       o.content_type = 'application/json';\r
+\r
+                       XHR.send(o);\r
+               },\r
+\r
+               'static' : {\r
+                       sendRPC : function(o) {\r
+                               return new tinymce.util.JSONRequest().send(o);\r
+                       }\r
+               }\r
+\r
+               });\r
+}());\r
+/* file:jscripts/tiny_mce/classes/dom/DOMUtils.js */\r
+\r
+(function() {\r
+       // Shorten names\r
+       var each = tinymce.each, is = tinymce.is;\r
+       var isWebKit = tinymce.isWebKit, isIE = tinymce.isIE;\r
+\r
+       tinymce.create('tinymce.dom.DOMUtils', {\r
+               doc : null,\r
+               root : null,\r
+               files : null,\r
+               listeners : {},\r
+               pixelStyles : /^(top|left|bottom|right|width|height|borderWidth)$/,\r
+               cache : {},\r
+               idPattern : /^#[\w]+$/,\r
+               elmPattern : /^[\w_*]+$/,\r
+               elmClassPattern : /^([\w_]*)\.([\w_]+)$/,\r
+\r
+               DOMUtils : function(d, s) {\r
+                       var t = this;\r
+\r
+                       t.doc = d;\r
+                       t.win = window;\r
+                       t.files = {};\r
+                       t.cssFlicker = false;\r
+                       t.counter = 0;\r
+                       t.boxModel = !tinymce.isIE || d.compatMode == "CSS1Compat"; \r
+                       t.stdMode = d.documentMode === 8;\r
+\r
+                       this.settings = s = tinymce.extend({\r
+                               keep_values : false,\r
+                               hex_colors : 1,\r
+                               process_html : 1\r
+                       }, s);\r
+\r
+                       // Fix IE6SP2 flicker and check it failed for pre SP2\r
+                       if (tinymce.isIE6) {\r
+                               try {\r
+                                       d.execCommand('BackgroundImageCache', false, true);\r
+                               } catch (e) {\r
+                                       t.cssFlicker = true;\r
+                               }\r
+                       }\r
+\r
+                       tinymce.addUnload(t.destroy, t);\r
+               },\r
+\r
+               getRoot : function() {\r
+                       var t = this, s = t.settings;\r
+\r
+                       return (s && t.get(s.root_element)) || t.doc.body;\r
+               },\r
+\r
+               getViewPort : function(w) {\r
+                       var d, b;\r
+\r
+                       w = !w ? this.win : w;\r
+                       d = w.document;\r
+                       b = this.boxModel ? d.documentElement : d.body;\r
+\r
+                       // Returns viewport size excluding scrollbars\r
+                       return {\r
+                               x : w.pageXOffset || b.scrollLeft,\r
+                               y : w.pageYOffset || b.scrollTop,\r
+                               w : w.innerWidth || b.clientWidth,\r
+                               h : w.innerHeight || b.clientHeight\r
+                       };\r
+               },\r
+\r
+               getRect : function(e) {\r
+                       var p, t = this, w, h;\r
+\r
+                       e = t.get(e);\r
+                       p = t.getPos(e);\r
+                       w = t.getStyle(e, 'width');\r
+                       h = t.getStyle(e, 'height');\r
+\r
+                       // Non pixel value, then force offset/clientWidth\r
+                       if (w.indexOf('px') === -1)\r
+                               w = 0;\r
+\r
+                       // Non pixel value, then force offset/clientWidth\r
+                       if (h.indexOf('px') === -1)\r
+                               h = 0;\r
+\r
+                       return {\r
+                               x : p.x,\r
+                               y : p.y,\r
+                               w : parseInt(w) || e.offsetWidth || e.clientWidth,\r
+                               h : parseInt(h) || e.offsetHeight || e.clientHeight\r
+                       };\r
+               },\r
+\r
+               getParent : function(n, f, r) {\r
+                       var na, se = this.settings;\r
+\r
+                       n = this.get(n);\r
+\r
+                       if (se.strict_root)\r
+                               r = r || this.getRoot();\r
+\r
+                       // Wrap node name as func\r
+                       if (is(f, 'string')) {\r
+                               na = f.toUpperCase();\r
+\r
+                               f = function(n) {\r
+                                       var s = false;\r
+\r
+                                       // Any element\r
+                                       if (n.nodeType == 1 && na === '*') {\r
+                                               s = true;\r
+                                               return false;\r
+                                       }\r
+\r
+                                       each(na.split(','), function(v) {\r
+                                               if (n.nodeType == 1 && ((se.strict && n.nodeName.toUpperCase() == v) || n.nodeName == v)) {\r
+                                                       s = true;\r
+                                                       return false; // Break loop\r
+                                               }\r
+                                       });\r
+\r
+                                       return s;\r
+                               };\r
+                       }\r
+\r
+                       while (n) {\r
+                               if (n == r)\r
+                                       return null;\r
+\r
+                               if (f(n))\r
+                                       return n;\r
+\r
+                               n = n.parentNode;\r
+                       }\r
+\r
+                       return null;\r
+               },\r
+\r
+               get : function(e) {\r
+                       var n;\r
+\r
+                       if (this.doc && typeof(e) == 'string') {\r
+                               n = e;\r
+                               e = this.doc.getElementById(e);\r
+\r
+                               // IE and Opera returns meta elements when they match the specified input ID, but getElementsByName seems to do the trick\r
+                               if (e && e.id !== n)\r
+                                       return this.doc.getElementsByName(n)[1];\r
+                       }\r
+\r
+                       return e;\r
+               },\r
+\r
+               // #if !jquery\r
+\r
+               select : function(pa, s) {\r
+                       var t = this, cs, c, pl, o = [], x, i, l, n;\r
+\r
+                       s = t.get(s) || t.doc;\r
+\r
+                       // Look for native support and use that if it's found\r
+                       if (s.querySelectorAll) {\r
+                               // Element scope then use temp id\r
+                               // We need to do this to be compatible with other implementations\r
+                               // See bug report: http://bugs.webkit.org/show_bug.cgi?id=17461\r
+                               if (s != t.doc) {\r
+                                       i = s.id;\r
+                                       s.id = '_mc_tmp';\r
+                                       pa = '#_mc_tmp ' + pa;\r
+                               }\r
+\r
+                               // Select elements\r
+                               l = tinymce.grep(s.querySelectorAll(pa));\r
+\r
+                               // Restore old id\r
+                               s.id = i;\r
+\r
+                               return l;\r
+                       }\r
+\r
+                       if (t.settings.strict) {\r
+                               function get(s, n) {\r
+                                       return s.getElementsByTagName(n.toLowerCase());\r
+                               };\r
+                       } else {\r
+                               function get(s, n) {\r
+                                       return s.getElementsByTagName(n);\r
+                               };\r
+                       }\r
+\r
+                       // Simple element pattern. For example: "p" or "*"\r
+                       if (t.elmPattern.test(pa)) {\r
+                               x = get(s, pa);\r
+\r
+                               for (i = 0, l = x.length; i<l; i++)\r
+                                       o.push(x[i]);\r
+\r
+                               return o;\r
+                       }\r
+\r
+                       // Simple class pattern. For example: "p.class" or ".class"\r
+                       if (t.elmClassPattern.test(pa)) {\r
+                               pl = t.elmClassPattern.exec(pa);\r
+                               x = get(s, pl[1] || '*');\r
+                               c = ' ' + pl[2] + ' ';\r
+\r
+                               for (i = 0, l = x.length; i<l; i++) {\r
+                                       n = x[i];\r
+\r
+                                       if (n.className && (' ' + n.className + ' ').indexOf(c) !== -1)\r
+                                               o.push(n);\r
+                               }\r
+\r
+                               return o;\r
+                       }\r
+\r
+                       function collect(n) {\r
+                               if (!n.mce_save) {\r
+                                       n.mce_save = 1;\r
+                                       o.push(n);\r
+                               }\r
+                       };\r
+\r
+                       function collectIE(n) {\r
+                               if (!n.getAttribute('mce_save')) {\r
+                                       n.setAttribute('mce_save', '1');\r
+                                       o.push(n);\r
+                               }\r
+                       };\r
+\r
+                       function find(n, f, r) {\r
+                               var i, l, nl = get(r, n);\r
+\r
+                               for (i = 0, l = nl.length; i < l; i++)\r
+                                       f(nl[i]);\r
+                       };\r
+\r
+                       each(pa.split(','), function(v, i) {\r
+                               v = tinymce.trim(v);\r
+\r
+                               // Simple element pattern, most common in TinyMCE\r
+                               if (t.elmPattern.test(v)) {\r
+                                       each(get(s, v), function(n) {\r
+                                               collect(n);\r
+                                       });\r
+\r
+                                       return;\r
+                               }\r
+\r
+                               // Simple element pattern with class, fairly common in TinyMCE\r
+                               if (t.elmClassPattern.test(v)) {\r
+                                       x = t.elmClassPattern.exec(v);\r
+\r
+                                       each(get(s, x[1]), function(n) {\r
+                                               if (t.hasClass(n, x[2]))\r
+                                                       collect(n);\r
+                                       });\r
+\r
+                                       return;\r
+                               }\r
+\r
+                               if (!(cs = t.cache[pa])) {\r
+                                       cs = 'x=(function(cf, s) {';\r
+                                       pl = v.split(' ');\r
+\r
+                                       each(pl, function(v) {\r
+                                               var p = /^([\w\\*]+)?(?:#([\w\\]+))?(?:\.([\w\\\.]+))?(?:\[\@([\w\\]+)([\^\$\*!]?=)([\w\\]+)\])?(?:\:([\w\\]+))?/i.exec(v);\r
+\r
+                                               // Find elements\r
+                                               p[1] = p[1] || '*';\r
+                                               cs += 'find("' + p[1] + '", function(n) {';\r
+\r
+                                               // Check id\r
+                                               if (p[2])\r
+                                                       cs += 'if (n.id !== "' + p[2] + '") return;';\r
+\r
+                                               // Check classes\r
+                                               if (p[3]) {\r
+                                                       cs += 'var c = " " + n.className + " ";';\r
+                                                       cs += 'if (';\r
+                                                       c = '';\r
+                                                       each(p[3].split('.'), function(v) {\r
+                                                               if (v)\r
+                                                                       c += (c ? '||' : '') + 'c.indexOf(" ' + v + ' ") === -1';\r
+                                                       });\r
+                                                       cs += c + ') return;';\r
+                                               }\r
+                                       });\r
+\r
+                                       cs += 'cf(n);';\r
+\r
+                                       for (i = pl.length - 1; i >= 0; i--)\r
+                                               cs += '}, ' + (i ? 'n' : 's') + ');';\r
+\r
+                                       cs += '})';\r
+\r
+                                       // Compile CSS pattern function\r
+                                       t.cache[pa] = cs = eval(cs);\r
+                               }\r
+\r
+                               // Run selector function\r
+                               cs(isIE ? collectIE : collect, s);\r
+                       });\r
+\r
+                       // Cleanup\r
+                       each(o, function(n) {\r
+                               if (isIE)\r
+                                       n.removeAttribute('mce_save');\r
+                               else\r
+                                       delete n.mce_save;\r
+                       });\r
+\r
+                       return o;\r
+               },\r
+\r
+               // #endif\r
+\r
+               add : function(p, n, a, h, c) {\r
+                       var t = this;\r
+\r
+                       return this.run(p, function(p) {\r
+                               var e, k;\r
+\r
+                               e = is(n, 'string') ? t.doc.createElement(n) : n;\r
+\r
+                               if (a) {\r
+                                       for (k in a) {\r
+                                               if (a.hasOwnProperty(k) && !is(a[k], 'object'))\r
+                                                       t.setAttrib(e, k, '' + a[k]);\r
+                                       }\r
+\r
+                                       if (a.style && !is(a.style, 'string')) {\r
+                                               each(a.style, function(v, n) {\r
+                                                       t.setStyle(e, n, v);\r
+                                               });\r
+                                       }\r
+                               }\r
+\r
+                               if (h) {\r
+                                       if (h.nodeType)\r
+                                               e.appendChild(h);\r
+                                       else\r
+                                               t.setHTML(e, h);\r
+                               }\r
+\r
+                               return !c ? p.appendChild(e) : e;\r
+                       });\r
+               },\r
+\r
+               create : function(n, a, h) {\r
+                       return this.add(this.doc.createElement(n), n, a, h, 1);\r
+               },\r
+\r
+               createHTML : function(n, a, h) {\r
+                       var o = '', t = this, k;\r
+\r
+                       o += '<' + n;\r
+\r
+                       for (k in a) {\r
+                               if (a.hasOwnProperty(k))\r
+                                       o += ' ' + k + '="' + t.encode(a[k]) + '"';\r
+                       }\r
+\r
+                       if (tinymce.is(h))\r
+                               return o + '>' + h + '</' + n + '>';\r
+\r
+                       return o + ' />';\r
+               },\r
+\r
+               remove : function(n, k) {\r
+                       return this.run(n, function(n) {\r
+                               var p, g;\r
+\r
+                               p = n.parentNode;\r
+\r
+                               if (!p)\r
+                                       return null;\r
+\r
+                               if (k) {\r
+                                       each (n.childNodes, function(c) {\r
+                                               p.insertBefore(c.cloneNode(true), n);\r
+                                       });\r
+                               }\r
+\r
+                               // Fix IE psuedo leak\r
+               /*              if (isIE) {\r
+                                       p = n.cloneNode(true);\r
+                                       n.outerHTML = '';\r
+\r
+                                       return p;\r
+                               }*/\r
+\r
+                               return p.removeChild(n);\r
+                       });\r
+               },\r
+\r
+               // #if !jquery\r
+\r
+               setStyle : function(n, na, v) {\r
+                       var t = this;\r
+\r
+                       return t.run(n, function(e) {\r
+                               var s, i;\r
+\r
+                               s = e.style;\r
+\r
+                               // Camelcase it, if needed\r
+                               na = na.replace(/-(\D)/g, function(a, b){\r
+                                       return b.toUpperCase();\r
+                               });\r
+\r
+                               // Default px suffix on these\r
+                               if (t.pixelStyles.test(na) && (tinymce.is(v, 'number') || /^[\-0-9\.]+$/.test(v)))\r
+                                       v += 'px';\r
+\r
+                               switch (na) {\r
+                                       case 'opacity':\r
+                                               // IE specific opacity\r
+                                               if (isIE) {\r
+                                                       s.filter = v === '' ? '' : "alpha(opacity=" + (v * 100) + ")";\r
+\r
+                                                       if (!n.currentStyle || !n.currentStyle.hasLayout)\r
+                                                               s.display = 'inline-block';\r
+                                               }\r
+\r
+                                               // Fix for older browsers\r
+                                               s[na] = s['-moz-opacity'] = s['-khtml-opacity'] = v || '';\r
+                                               break;\r
+\r
+                                       case 'float':\r
+                                               isIE ? s.styleFloat = v : s.cssFloat = v;\r
+                                               break;\r
+                                       \r
+                                       default:\r
+                                               s[na] = v || '';\r
+                               }\r
+\r
+                               // Force update of the style data\r
+                               if (t.settings.update_styles)\r
+                                       t.setAttrib(e, 'mce_style');\r
+                       });\r
+               },\r
+\r
+               getStyle : function(n, na, c) {\r
+                       n = this.get(n);\r
+\r
+                       if (!n)\r
+                               return false;\r
+\r
+                       // Gecko\r
+                       if (this.doc.defaultView && c) {\r
+                               // Remove camelcase\r
+                               na = na.replace(/[A-Z]/g, function(a){\r
+                                       return '-' + a;\r
+                               });\r
+\r
+                               try {\r
+                                       return this.doc.defaultView.getComputedStyle(n, null).getPropertyValue(na);\r
+                               } catch (ex) {\r
+                                       // Old safari might fail\r
+                                       return null;\r
+                               }\r
+                       }\r
+\r
+                       // Camelcase it, if needed\r
+                       na = na.replace(/-(\D)/g, function(a, b){\r
+                               return b.toUpperCase();\r
+                       });\r
+\r
+                       if (na == 'float')\r
+                               na = isIE ? 'styleFloat' : 'cssFloat';\r
+\r
+                       // IE & Opera\r
+                       if (n.currentStyle && c)\r
+                               return n.currentStyle[na];\r
+\r
+                       return n.style[na];\r
+               },\r
+\r
+               setStyles : function(e, o) {\r
+                       var t = this, s = t.settings, ol;\r
+\r
+                       ol = s.update_styles;\r
+                       s.update_styles = 0;\r
+\r
+                       each(o, function(v, n) {\r
+                               t.setStyle(e, n, v);\r
+                       });\r
+\r
+                       // Update style info\r
+                       s.update_styles = ol;\r
+                       if (s.update_styles)\r
+                               t.setAttrib(e, s.cssText);\r
+               },\r
+\r
+               setAttrib : function(e, n, v) {\r
+                       var t = this;\r
+\r
+                       // Strict XML mode\r
+                       if (t.settings.strict)\r
+                               n = n.toLowerCase();\r
+\r
+                       return this.run(e, function(e) {\r
+                               var s = t.settings;\r
+\r
+                               switch (n) {\r
+                                       case "style":\r
+                                               // No mce_style for elements with these since they might get resized by the user\r
+                                               if (s.keep_values && /^(| )(top|left|bottom|right|width|height)/i.test(v)) {\r
+                                                       if (v)\r
+                                                               e.setAttribute('mce_style', v, 2);\r
+                                                       else\r
+                                                               e.removeAttribute('mce_style', 2);\r
+                                               }\r
+\r
+                                               e.style.cssText = v;\r
+                                               break;\r
+\r
+                                       case "class":\r
+                                               e.className = v || ''; // Fix IE null bug\r
+                                               break;\r
+\r
+                                       case "src":\r
+                                       case "href":\r
+                                               if (s.keep_values) {\r
+                                                       if (s.url_converter)\r
+                                                               v = s.url_converter.call(s.url_converter_scope || t, v, n, e);\r
+\r
+                                                       t.setAttrib(e, 'mce_' + n, v, 2);\r
+                                               }\r
+\r
+                                               break;\r
+                               }\r
+\r
+                               if (is(v) && v !== null && v.length !== 0)\r
+                                       e.setAttribute(n, '' + v, 2);\r
+                               else\r
+                                       e.removeAttribute(n, 2);\r
+                       });\r
+               },\r
+\r
+               setAttribs : function(e, o) {\r
+                       var t = this;\r
+\r
+                       return this.run(e, function(e) {\r
+                               each(o, function(v, n) {\r
+                                       t.setAttrib(e, n, v);\r
+                               });\r
+                       });\r
+               },\r
+\r
+               // #endif\r
+\r
+               getAttrib : function(e, n, dv) {\r
+                       var v, t = this;\r
+\r
+                       e = t.get(e);\r
+\r
+                       if (!e || e.nodeType !== 1)\r
+                               return false;\r
+\r
+                       if (!is(dv))\r
+                               dv = "";\r
+\r
+                       // Try the mce variant for these\r
+                       if (/^(src|href|style|coords)$/.test(n)) {\r
+                               v = e.getAttribute("mce_" + n);\r
+\r
+                               if (v)\r
+                                       return v;\r
+                       }\r
+\r
+                       v = e.getAttribute(n, 2);\r
+\r
+                       if (!v) {\r
+                               switch (n) {\r
+                                       case 'class':\r
+                                               v = e.className;\r
+                                               break;\r
+\r
+                                       default:\r
+                                               // Fix for IE crash Bug: #1884376 probably due to invalid DOM structure\r
+                                               if (isIE && n === 'name' && e.nodeName === 'A') {\r
+                                                       v = e.name;\r
+                                                       break;\r
+                                               }\r
+\r
+                                               v = e.attributes[n];\r
+                                               v = v && is(v.nodeValue) ? v.nodeValue : v;\r
+                               }\r
+                       }\r
+\r
+                       switch (n) {\r
+                               case 'style':\r
+                                       v = v || e.style.cssText;\r
+\r
+                                       if (v) {\r
+                                               v = t.serializeStyle(t.parseStyle(v));\r
+\r
+                                               if (t.settings.keep_values && /^(| )(top|left|bottom|right|width|height)/i.test(v))\r
+                                                       e.setAttribute('mce_style', v);\r
+                                       }\r
+\r
+                                       break;\r
+                       }\r
+\r
+                       // Remove Apple and WebKit stuff\r
+                       if (isWebKit && n === "class" && v)\r
+                               v = v.replace(/(apple|webkit)\-[a-z\-]+/gi, '');\r
+\r
+                       // Handle IE issues\r
+                       if (isIE) {\r
+                               switch (n) {\r
+                                       case 'rowspan':\r
+                                       case 'colspan':\r
+                                               // IE returns 1 as default value\r
+                                               if (v === 1)\r
+                                                       v = '';\r
+\r
+                                               break;\r
+\r
+                                       case 'size':\r
+                                               // IE returns +0 as default value for size\r
+                                               if (v === '+0')\r
+                                                       v = '';\r
+\r
+                                               break;\r
+\r
+                                       case 'hspace':\r
+                                               // IE returns -1 as default value\r
+                                               if (v === -1)\r
+                                                       v = '';\r
+\r
+                                               break;\r
+\r
+                                       case 'tabindex':\r
+                                               // IE returns 32768 as default value\r
+                                               if (v === 32768)\r
+                                                       v = '';\r
+\r
+                                               break;\r
+\r
+                                       case 'shape':\r
+                                               v = v.toLowerCase();\r
+                                               break;\r
+\r
+                                       default:\r
+                                               // IE has odd anonymous function for event attributes\r
+                                               if (n.indexOf('on') === 0 && v)\r
+                                                       v = ('' + v).replace(/^function\s+anonymous\(\)\s+\{\s+(.*)\s+\}$/, '$1');\r
+                               }\r
+                       }\r
+\r
+                       return (v && v != '') ? '' + v : dv;\r
+               },\r
+\r
+               getPos : function(n) {\r
+                       var t = this, x = 0, y = 0, e, d = t.doc, r;\r
+\r
+                       n = t.get(n);\r
+\r
+                       // Use getBoundingClientRect on IE, Opera has it but it's not perfect\r
+                       if (n && isIE) {\r
+                               n = n.getBoundingClientRect();\r
+                               e = t.boxModel ? d.documentElement : d.body;\r
+                               x = t.getStyle(t.select('html')[0], 'borderWidth'); // Remove border\r
+                               x = (x == 'medium' || t.boxModel && !t.isIE6) && 2 || x;\r
+                               n.top += t.win.self != t.win.top ? 2 : 0; // IE adds some strange extra cord if used in a frameset\r
+\r
+                               return {x : n.left + e.scrollLeft - x, y : n.top + e.scrollTop - x};\r
+                       }\r
+\r
+                       r = n;\r
+                       while (r) {\r
+                               x += r.offsetLeft || 0;\r
+                               y += r.offsetTop || 0;\r
+                               r = r.offsetParent;\r
+                       }\r
+\r
+                       r = n;\r
+                       while (r) {\r
+                               // Opera 9.25 bug fix, fixed in 9.50\r
+                               if (!/^table-row|inline.*/i.test(t.getStyle(r, "display", 1))) {\r
+                                       x -= r.scrollLeft || 0;\r
+                                       y -= r.scrollTop || 0;\r
+                               }\r
+\r
+                               r = r.parentNode;\r
+\r
+                               if (r == d.body)\r
+                                       break;\r
+                       }\r
+\r
+                       return {x : x, y : y};\r
+               },\r
+\r
+               parseStyle : function(st) {\r
+                       var t = this, s = t.settings, o = {};\r
+\r
+                       if (!st)\r
+                               return o;\r
+\r
+                       function compress(p, s, ot) {\r
+                               var t, r, b, l;\r
+\r
+                               // Get values and check it it needs compressing\r
+                               t = o[p + '-top' + s];\r
+                               if (!t)\r
+                                       return;\r
+\r
+                               r = o[p + '-right' + s];\r
+                               if (t != r)\r
+                                       return;\r
+\r
+                               b = o[p + '-bottom' + s];\r
+                               if (r != b)\r
+                                       return;\r
+\r
+                               l = o[p + '-left' + s];\r
+                               if (b != l)\r
+                                       return;\r
+\r
+                               // Compress\r
+                               o[ot] = l;\r
+                               delete o[p + '-top' + s];\r
+                               delete o[p + '-right' + s];\r
+                               delete o[p + '-bottom' + s];\r
+                               delete o[p + '-left' + s];\r
+                       };\r
+\r
+                       function compress2(ta, a, b, c) {\r
+                               var t;\r
+\r
+                               t = o[a];\r
+                               if (!t)\r
+                                       return;\r
+\r
+                               t = o[b];\r
+                               if (!t)\r
+                                       return;\r
+\r
+                               t = o[c];\r
+                               if (!t)\r
+                                       return;\r
+\r
+                               // Compress\r
+                               o[ta] = o[a] + ' ' + o[b] + ' ' + o[c];\r
+                               delete o[a];\r
+                               delete o[b];\r
+                               delete o[c];\r
+                       };\r
+\r
+                       each(st.split(';'), function(v) {\r
+                               var sv, ur = [];\r
+\r
+                               if (v) {\r
+                                       v = v.replace(/url\([^\)]+\)/g, function(v) {ur.push(v);return 'url(' + ur.length + ')';});\r
+                                       v = v.split(':');\r
+                                       sv = tinymce.trim(v[1]);\r
+                                       sv = sv.replace(/url\(([^\)]+)\)/g, function(a, b) {return ur[parseInt(b) - 1];});\r
+\r
+                                       sv = sv.replace(/rgb\([^\)]+\)/g, function(v) {\r
+                                               return t.toHex(v);\r
+                                       });\r
+\r
+                                       if (s.url_converter) {\r
+                                               sv = sv.replace(/url\([\'\"]?([^\)\'\"]+)[\'\"]?\)/g, function(x, c) {\r
+                                                       return 'url(' + t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), 'style', null)) + ')';\r
+                                               });\r
+                                       }\r
+\r
+                                       o[tinymce.trim(v[0]).toLowerCase()] = sv;\r
+                               }\r
+                       });\r
+\r
+                       compress("border", "", "border");\r
+                       compress("border", "-width", "border-width");\r
+                       compress("border", "-color", "border-color");\r
+                       compress("border", "-style", "border-style");\r
+                       compress("padding", "", "padding");\r
+                       compress("margin", "", "margin");\r
+                       compress2('border', 'border-width', 'border-style', 'border-color');\r
+\r
+                       if (isIE) {\r
+                               // Remove pointless border\r
+                               if (o.border == 'medium none')\r
+                                       o.border = '';\r
+                       }\r
+\r
+                       return o;\r
+               },\r
+\r
+               serializeStyle : function(o) {\r
+                       var s = '';\r
+\r
+                       each(o, function(v, k) {\r
+                               if (k && v) {\r
+                                       switch (k) {\r
+                                               case 'color':\r
+                                               case 'background-color':\r
+                                                       v = v.toLowerCase();\r
+                                                       break;\r
+                                       }\r
+\r
+                                       s += (s ? ' ' : '') + k + ': ' + v + ';';\r
+                               }\r
+                       });\r
+\r
+                       return s;\r
+               },\r
+\r
+               loadCSS : function(u) {\r
+                       var t = this, d = t.doc;\r
+\r
+                       if (!u)\r
+                               u = '';\r
+\r
+                       each(u.split(','), function(u) {\r
+                               if (t.files[u])\r
+                                       return;\r
+\r
+                               t.files[u] = true;\r
+                               t.add(t.select('head')[0], 'link', {rel : 'stylesheet', href : tinymce._addVer(u)});\r
+                       });\r
+               },\r
+\r
+               // #if !jquery\r
+\r
+               addClass : function(e, c) {\r
+                       return this.run(e, function(e) {\r
+                               var o;\r
+\r
+                               if (!c)\r
+                                       return 0;\r
+\r
+                               if (this.hasClass(e, c))\r
+                                       return e.className;\r
+\r
+                               o = this.removeClass(e, c);\r
+\r
+                               return e.className = (o != '' ? (o + ' ') : '') + c;\r
+                       });\r
+               },\r
+\r
+               removeClass : function(e, c) {\r
+                       var t = this, re;\r
+\r
+                       return t.run(e, function(e) {\r
+                               var v;\r
+\r
+                               if (t.hasClass(e, c)) {\r
+                                       if (!re)\r
+                                               re = new RegExp("(^|\\s+)" + c + "(\\s+|$)", "g");\r
+\r
+                                       v = e.className.replace(re, ' ');\r
+\r
+                                       return e.className = tinymce.trim(v != ' ' ? v : '');\r
+                               }\r
+\r
+                               return e.className;\r
+                       });\r
+               },\r
+\r
+               hasClass : function(n, c) {\r
+                       n = this.get(n);\r
+\r
+                       if (!n || !c)\r
+                               return false;\r
+\r
+                       return (' ' + n.className + ' ').indexOf(' ' + c + ' ') !== -1;\r
+               },\r
+\r
+               show : function(e) {\r
+                       return this.setStyle(e, 'display', 'block');\r
+               },\r
+\r
+               hide : function(e) {\r
+                       return this.setStyle(e, 'display', 'none');\r
+               },\r
+\r
+               isHidden : function(e) {\r
+                       e = this.get(e);\r
+\r
+                       return e.style.display == 'none' || this.getStyle(e, 'display') == 'none';\r
+               },\r
+\r
+               // #endif\r
+\r
+               uniqueId : function(p) {\r
+                       return (!p ? 'mce_' : p) + (this.counter++);\r
+               },\r
+\r
+               setHTML : function(e, h) {\r
+                       var t = this;\r
+\r
+                       return this.run(e, function(e) {\r
+                               var x, i, nl, n, p, x;\r
+\r
+                               h = t.processHTML(h);\r
+\r
+                               if (isIE) {\r
+                                       function set() {\r
+                                               try {\r
+                                                       // IE will remove comments from the beginning\r
+                                                       // unless you padd the contents with something\r
+                                                       e.innerHTML = '<br />' + h;\r
+                                                       e.removeChild(e.firstChild);\r
+                                               } catch (ex) {\r
+                                                       // IE sometimes produces an unknown runtime error on innerHTML if it's an block element within a block element for example a div inside a p\r
+                                                       // This seems to fix this problem\r
+\r
+                                                       // Remove all child nodes\r
+                                                       while (e.firstChild)\r
+                                                               e.firstChild.removeNode();\r
+\r
+                                                       // Create new div with HTML contents and a BR infront to keep comments\r
+                                                       x = t.create('div');\r
+                                                       x.innerHTML = '<br />' + h;\r
+\r
+                                                       // Add all children from div to target\r
+                                                       each (x.childNodes, function(n, i) {\r
+                                                               // Skip br element\r
+                                                               if (i)\r
+                                                                       e.appendChild(n);\r
+                                                       });\r
+                                               }\r
+                                       };\r
+\r
+                                       // IE has a serious bug when it comes to paragraphs it can produce an invalid\r
+                                       // DOM tree if contents like this <p><ul><li>Item 1</li></ul></p> is inserted\r
+                                       // It seems to be that IE doesn't like a root block element placed inside another root block element\r
+                                       if (t.settings.fix_ie_paragraphs)\r
+                                               h = h.replace(/<p><\/p>|<p([^>]+)><\/p>|<p[^\/+]\/>/gi, '<p$1 mce_keep="true">&nbsp;</p>');\r
+\r
+                                       set();\r
+\r
+                                       if (t.settings.fix_ie_paragraphs) {\r
+                                               // Check for odd paragraphs this is a sign of a broken DOM\r
+                                               nl = e.getElementsByTagName("p");\r
+                                               for (i = nl.length - 1, x = 0; i >= 0; i--) {\r
+                                                       n = nl[i];\r
+\r
+                                                       if (!n.hasChildNodes()) {\r
+                                                               if (!n.mce_keep) {\r
+                                                                       x = 1; // Is broken\r
+                                                                       break;\r
+                                                               }\r
+\r
+                                                               n.removeAttribute('mce_keep');\r
+                                                       }\r
+                                               }\r
+                                       }\r
+\r
+                                       // Time to fix the madness IE left us\r
+                                       if (x) {\r
+                                               // So if we replace the p elements with divs and mark them and then replace them back to paragraphs\r
+                                               // after we use innerHTML we can fix the DOM tree\r
+                                               h = h.replace(/<p([^>]+)>|<p>/g, '<div$1 mce_tmp="1">');\r
+                                               h = h.replace(/<\/p>/g, '</div>');\r
+\r
+                                               // Set the new HTML with DIVs\r
+                                               set();\r
+\r
+                                               // Replace all DIV elements with he mce_tmp attibute back to paragraphs\r
+                                               // This is needed since IE has a annoying bug see above for details\r
+                                               // This is a slow process but it has to be done. :(\r
+                                               if (t.settings.fix_ie_paragraphs) {\r
+                                                       nl = e.getElementsByTagName("DIV");\r
+                                                       for (i = nl.length - 1; i >= 0; i--) {\r
+                                                               n = nl[i];\r
+\r
+                                                               // Is it a temp div\r
+                                                               if (n.mce_tmp) {\r
+                                                                       // Create new paragraph\r
+                                                                       p = t.doc.createElement('p');\r
+\r
+                                                                       // Copy all attributes\r
+                                                                       n.cloneNode(false).outerHTML.replace(/([a-z0-9\-_]+)=/gi, function(a, b) {\r
+                                                                               var v;\r
+\r
+                                                                               if (b !== 'mce_tmp') {\r
+                                                                                       v = n.getAttribute(b);\r
+\r
+                                                                                       if (!v && b === 'class')\r
+                                                                                               v = n.className;\r
+\r
+                                                                                       p.setAttribute(b, v);\r
+                                                                               }\r
+                                                                       });\r
+\r
+                                                                       // Append all children to new paragraph\r
+                                                                       for (x = 0; x<n.childNodes.length; x++)\r
+                                                                               p.appendChild(n.childNodes[x].cloneNode(true));\r
+\r
+                                                                       // Replace div with new paragraph\r
+                                                                       n.swapNode(p);\r
+                                                               }\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               } else\r
+                                       e.innerHTML = h;\r
+\r
+                               return h;\r
+                       });\r
+               },\r
+\r
+               processHTML : function(h) {\r
+                       var t = this, s = t.settings;\r
+\r
+                       if (!s.process_html)\r
+                               return h;\r
+\r
+                       // Convert strong and em to b and i in FF since it can't handle them\r
+                       if (tinymce.isGecko) {\r
+                               h = h.replace(/<(\/?)strong>|<strong( [^>]+)>/gi, '<$1b$2>');\r
+                               h = h.replace(/<(\/?)em>|<em( [^>]+)>/gi, '<$1i$2>');\r
+                       } else if (isIE)\r
+                               h = h.replace(/&apos;/g, '&#39;'); // IE can't handle apos\r
+\r
+                       // Fix some issues\r
+                       h = h.replace(/<a( )([^>]+)\/>|<a\/>/gi, '<a$1$2></a>'); // Force open\r
+\r
+                       // Store away src and href in mce_src and mce_href since browsers mess them up\r
+                       if (s.keep_values) {\r
+                               // Wrap scripts in comments for serialization purposes\r
+                               if (h.indexOf('<script') !== -1) {\r
+                                       h = h.replace(/<script>/g, '<script type="text/javascript">');\r
+                                       h = h.replace(/<script(|[^>]+)>(\s*<!--|\/\/\s*<\[CDATA\[)?[\r\n]*/g, '<mce:script$1><!--\n');\r
+                                       h = h.replace(/\s*(\/\/\s*-->|\/\/\s*]]>)?<\/script>/g, '\n// --></mce:script>');\r
+                                       h = h.replace(/<mce:script(|[^>]+)><!--\n\/\/ --><\/mce:script>/g, '<mce:script$1></mce:script>');\r
+                               }\r
+\r
+                               // Process all tags with src, href or style\r
+                               h = h.replace(/<([\w:]+) [^>]*(src|href|style|coords)[^>]*>/gi, function(a, n) {\r
+                                       function handle(m, b, c) {\r
+                                               var u = c;\r
+\r
+                                               // Tag already got a mce_ version\r
+                                               if (a.indexOf('mce_' + b) != -1)\r
+                                                       return m;\r
+\r
+                                               if (b == 'style') {\r
+                                                       // Why did I need this one?\r
+                                                       //if (isIE)\r
+                                                       //      u = t.serializeStyle(t.parseStyle(u));\r
+\r
+                                                       // No mce_style for elements with these since they might get resized by the user\r
+                                                       if (/^(| )(top|left|bottom|right|width|height)/i.test(c))\r
+                                                               return m;\r
+\r
+                                                       if (s.hex_colors) {\r
+                                                               u = u.replace(/rgb\([^\)]+\)/g, function(v) {\r
+                                                                       return t.toHex(v);\r
+                                                               });\r
+                                                       }\r
+\r
+                                                       if (s.url_converter) {\r
+                                                               u = u.replace(/url\([\'\"]?([^\)\'\"]+)\)/g, function(x, c) {\r
+                                                                       return 'url(' + t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n)) + ')';\r
+                                                               });\r
+                                                       }\r
+                                               } else if (b != 'coords') {\r
+                                                       if (s.url_converter)\r
+                                                               u = t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n));\r
+                                               }\r
+\r
+                                               return ' ' + b + '="' + c + '" mce_' + b + '="' + u + '"';\r
+                                       };\r
+\r
+                                       a = a.replace(/ (src|href|style|coords)=[\"]([^\"]+)[\"]/gi, handle); // W3C\r
+                                       a = a.replace(/ (src|href|style|coords)=[\']([^\']+)[\']/gi, handle); // W3C\r
+\r
+                                       return a.replace(/ (src|href|style|coords)=([^\s\"\'>]+)/gi, handle); // IE\r
+                               });\r
+                       }\r
+\r
+                       return h;\r
+               },\r
+\r
+               getOuterHTML : function(e) {\r
+                       var d;\r
+\r
+                       e = this.get(e);\r
+\r
+                       if (!e)\r
+                               return null;\r
+\r
+                       if (isIE)\r
+                               return e.outerHTML;\r
+\r
+                       d = (e.ownerDocument || this.doc).createElement("body");\r
+                       d.appendChild(e.cloneNode(true));\r
+\r
+                       return d.innerHTML;\r
+               },\r
+\r
+               setOuterHTML : function(e, h, d) {\r
+                       var t = this;\r
+\r
+                       return this.run(e, function(e) {\r
+                               var n, tp;\r
+\r
+                               e = t.get(e);\r
+                               d = d || e.ownerDocument || t.doc;\r
+\r
+                               if (isIE && e.nodeType == 1)\r
+                                       e.outerHTML = h;\r
+                               else {\r
+                                       tp = d.createElement("body");\r
+                                       tp.innerHTML = h;\r
+\r
+                                       n = tp.lastChild;\r
+                                       while (n) {\r
+                                               t.insertAfter(n.cloneNode(true), e);\r
+                                               n = n.previousSibling;\r
+                                       }\r
+\r
+                                       t.remove(e);\r
+                               }\r
+                       });\r
+               },\r
+\r
+               decode : function(s) {\r
+                       var e;\r
+\r
+                       // Look for entities to decode\r
+                       if (/&[^;]+;/.test(s)) {\r
+                               // Decode the entities using a div element not super efficient but less code\r
+                               e = this.doc.createElement("div");\r
+                               e.innerHTML = s;\r
+\r
+                               return !e.firstChild ? s : e.firstChild.nodeValue;\r
+                       }\r
+\r
+                       return s;\r
+               },\r
+\r
+               encode : function(s) {\r
+                       return s ? ('' + s).replace(/[<>&\"]/g, function (c, b) {\r
+                               switch (c) {\r
+                                       case '&':\r
+                                               return '&amp;';\r
+\r
+                                       case '"':\r
+                                               return '&quot;';\r
+\r
+                                       case '<':\r
+                                               return '&lt;';\r
+\r
+                                       case '>':\r
+                                               return '&gt;';\r
+                               }\r
+\r
+                               return c;\r
+                       }) : s;\r
+               },\r
+\r
+               // #if !jquery\r
+\r
+               insertAfter : function(n, r) {\r
+                       var t = this;\r
+\r
+                       r = t.get(r);\r
+\r
+                       return this.run(n, function(n) {\r
+                               var p, ns;\r
+\r
+                               p = r.parentNode;\r
+                               ns = r.nextSibling;\r
+\r
+                               if (ns)\r
+                                       p.insertBefore(n, ns);\r
+                               else\r
+                                       p.appendChild(n);\r
+\r
+                               return n;\r
+                       });\r
+               },\r
+\r
+               // #endif\r
+\r
+               isBlock : function(n) {\r
+                       if (n.nodeType && n.nodeType !== 1)\r
+                               return false;\r
+\r
+                       n = n.nodeName || n;\r
+\r
+                       return /^(H[1-6]|HR|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP)$/.test(n);\r
+               },\r
+\r
+               // #if !jquery\r
+\r
+               replace : function(n, o, k) {\r
+                       if (is(o, 'array'))\r
+                               n = n.cloneNode(true);\r
+\r
+                       return this.run(o, function(o) {\r
+                               if (k) {\r
+                                       each(o.childNodes, function(c) {\r
+                                               n.appendChild(c.cloneNode(true));\r
+                                       });\r
+                               }\r
+\r
+                               // Fix IE psuedo leak for elements since replacing elements if fairly common\r
+                               // Will break parentNode for some unknown reason\r
+       /*                      if (isIE && o.nodeType === 1) {\r
+                                       o.parentNode.insertBefore(n, o);\r
+                                       o.outerHTML = '';\r
+                                       return n;\r
+                               }*/\r
+\r
+                               return o.parentNode.replaceChild(n, o);\r
+                       });\r
+               },\r
+\r
+               // #endif\r
+\r
+               toHex : function(s) {\r
+                       var c = /^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(s);\r
+\r
+                       function hex(s) {\r
+                               s = parseInt(s).toString(16);\r
+\r
+                               return s.length > 1 ? s : '0' + s; // 0 -> 00\r
+                       };\r
+\r
+                       if (c) {\r
+                               s = '#' + hex(c[1]) + hex(c[2]) + hex(c[3]);\r
+\r
+                               return s;\r
+                       }\r
+\r
+                       return s;\r
+               },\r
+\r
+               getClasses : function() {\r
+                       var t = this, cl = [], i, lo = {}, f = t.settings.class_filter, ov;\r
+\r
+                       if (t.classes)\r
+                               return t.classes;\r
+\r
+                       function addClasses(s) {\r
+                               // IE style imports\r
+                               each(s.imports, function(r) {\r
+                                       addClasses(r);\r
+                               });\r
+\r
+                               each(s.cssRules || s.rules, function(r) {\r
+                                       // Real type or fake it on IE\r
+                                       switch (r.type || 1) {\r
+                                               // Rule\r
+                                               case 1:\r
+                                                       if (r.selectorText) {\r
+                                                               each(r.selectorText.split(','), function(v) {\r
+                                                                       v = v.replace(/^\s*|\s*$|^\s\./g, "");\r
+\r
+                                                                       // Is internal or it doesn't contain a class\r
+                                                                       if (/\.mce/.test(v) || !/\.[\w\-]+$/.test(v))\r
+                                                                               return;\r
+\r
+                                                                       // Remove everything but class name\r
+                                                                       ov = v;\r
+                                                                       v = v.replace(/.*\.([a-z0-9_\-]+).*/i, '$1');\r
+\r
+                                                                       // Filter classes\r
+                                                                       if (f && !(v = f(v, ov)))\r
+                                                                               return;\r
+\r
+                                                                       if (!lo[v]) {\r
+                                                                               cl.push({'class' : v});\r
+                                                                               lo[v] = 1;\r
+                                                                       }\r
+                                                               });\r
+                                                       }\r
+                                                       break;\r
+\r
+                                               // Import\r
+                                               case 3:\r
+                                                       addClasses(r.styleSheet);\r
+                                                       break;\r
+                                       }\r
+                               });\r
+                       };\r
+\r
+                       try {\r
+                               each(t.doc.styleSheets, addClasses);\r
+                       } catch (ex) {\r
+                               // Ignore\r
+                       }\r
+\r
+                       if (cl.length > 0)\r
+                               t.classes = cl;\r
+\r
+                       return cl;\r
+               },\r
+\r
+               run : function(e, f, s) {\r
+                       var t = this, o;\r
+\r
+                       if (t.doc && typeof(e) === 'string')\r
+                               e = t.doc.getElementById(e);\r
+\r
+                       if (!e)\r
+                               return false;\r
+\r
+                       s = s || this;\r
+                       if (!e.nodeType && (e.length || e.length === 0)) {\r
+                               o = [];\r
+\r
+                               each(e, function(e, i) {\r
+                                       if (e) {\r
+                                               if (typeof(e) == 'string')\r
+                                                       e = t.doc.getElementById(e);\r
+\r
+                                               o.push(f.call(s, e, i));\r
+                                       }\r
+                               });\r
+\r
+                               return o;\r
+                       }\r
+\r
+                       return f.call(s, e);\r
+               },\r
+\r
+               getAttribs : function(n) {\r
+                       var o;\r
+\r
+                       n = this.get(n);\r
+\r
+                       if (!n)\r
+                               return [];\r
+\r
+                       if (isIE) {\r
+                               o = [];\r
+\r
+                               // Object will throw exception in IE\r
+                               if (n.nodeName == 'OBJECT')\r
+                                       return n.attributes;\r
+\r
+                               // It's crazy that this is faster in IE but it's because it returns all attributes all the time\r
+                               n.cloneNode(false).outerHTML.replace(/([a-z0-9\:\-_]+)=/gi, function(a, b) {\r
+                                       o.push({specified : 1, nodeName : b});\r
+                               });\r
+\r
+                               return o;\r
+                       }\r
+\r
+                       return n.attributes;\r
+               },\r
+\r
+               destroy : function(s) {\r
+                       var t = this;\r
+\r
+                       t.win = t.doc = t.root = null;\r
+\r
+                       // Manual destroy then remove unload handler\r
+                       if (!s)\r
+                               tinymce.removeUnload(t.destroy);\r
+               }\r
+\r
+               /*\r
+               walk : function(n, f, s) {\r
+                       var d = this.doc, w;\r
+\r
+                       if (d.createTreeWalker) {\r
+                               w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);\r
+\r
+                               while ((n = w.nextNode()) != null)\r
+                                       f.call(s || this, n);\r
+                       } else\r
+                               tinymce.walk(n, f, 'childNodes', s);\r
+               }\r
+               */\r
+\r
+               /*\r
+               toRGB : function(s) {\r
+                       var c = /^\s*?#([0-9A-F]{2})([0-9A-F]{1,2})([0-9A-F]{2})?\s*?$/.exec(s);\r
+\r
+                       if (c) {\r
+                               // #FFF -> #FFFFFF\r
+                               if (!is(c[3]))\r
+                                       c[3] = c[2] = c[1];\r
+\r
+                               return "rgb(" + parseInt(c[1], 16) + "," + parseInt(c[2], 16) + "," + parseInt(c[3], 16) + ")";\r
+                       }\r
+\r
+                       return s;\r
+               }\r
+               */\r
+\r
+               });\r
+\r
+       // Setup page DOM\r
+       tinymce.DOM = new tinymce.dom.DOMUtils(document, {process_html : 0});\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/dom/Event.js */\r
+\r
+(function() {\r
+       // Shorten names\r
+       var each = tinymce.each, DOM = tinymce.DOM, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit, Event;\r
+\r
+       tinymce.create('static tinymce.dom.Event', {\r
+               inits : [],\r
+               events : [],\r
+\r
+               // #if !jquery\r
+\r
+               add : function(o, n, f, s) {\r
+                       var cb, t = this, el = t.events, r;\r
+\r
+                       // Handle array\r
+                       if (o && o instanceof Array) {\r
+                               r = [];\r
+\r
+                               each(o, function(o) {\r
+                                       o = DOM.get(o);\r
+                                       r.push(t.add(o, n, f, s));\r
+                               });\r
+\r
+                               return r;\r
+                       }\r
+\r
+                       o = DOM.get(o);\r
+\r
+                       if (!o)\r
+                               return;\r
+\r
+                       // Setup event callback\r
+                       cb = function(e) {\r
+                               e = e || window.event;\r
+\r
+                               // Patch in target in IE it's W3C valid\r
+                               if (e && !e.target && isIE)\r
+                                       e.target = e.srcElement;\r
+\r
+                               if (!s)\r
+                                       return f(e);\r
+\r
+                               return f.call(s, e);\r
+                       };\r
+\r
+                       if (n == 'unload') {\r
+                               tinymce.unloads.unshift({func : cb});\r
+                               return cb;\r
+                       }\r
+\r
+                       if (n == 'init') {\r
+                               if (t.domLoaded)\r
+                                       cb();\r
+                               else\r
+                                       t.inits.push(cb);\r
+\r
+                               return cb;\r
+                       }\r
+\r
+                       // Store away listener reference\r
+                       el.push({\r
+                               obj : o,\r
+                               name : n,\r
+                               func : f,\r
+                               cfunc : cb,\r
+                               scope : s\r
+                       });\r
+\r
+                       t._add(o, n, cb);\r
+\r
+                       return f;\r
+               },\r
+\r
+               remove : function(o, n, f) {\r
+                       var t = this, a = t.events, s = false, r;\r
+\r
+                       // Handle array\r
+                       if (o && o instanceof Array) {\r
+                               r = [];\r
+\r
+                               each(o, function(o) {\r
+                                       o = DOM.get(o);\r
+                                       r.push(t.remove(o, n, f));\r
+                               });\r
+\r
+                               return r;\r
+                       }\r
+\r
+                       o = DOM.get(o);\r
+\r
+                       each(a, function(e, i) {\r
+                               if (e.obj == o && e.name == n && (!f || (e.func == f || e.cfunc == f))) {\r
+                                       a.splice(i, 1);\r
+                                       t._remove(o, n, e.cfunc);\r
+                                       s = true;\r
+                                       return false;\r
+                               }\r
+                       });\r
+\r
+                       return s;\r
+               },\r
+\r
+               clear : function(o) {\r
+                       var t = this, a = t.events, i, e;\r
+\r
+                       if (o) {\r
+                               o = DOM.get(o);\r
+\r
+                               for (i = a.length - 1; i >= 0; i--) {\r
+                                       e = a[i];\r
+\r
+                                       if (e.obj === o) {\r
+                                               t._remove(e.obj, e.name, e.cfunc);\r
+                                               e.obj = e.cfunc = null;\r
+                                               a.splice(i, 1);\r
+                                       }\r
+                               }\r
+                       }\r
+               },\r
+\r
+               // #endif\r
+\r
+               cancel : function(e) {\r
+                       if (!e)\r
+                               return false;\r
+\r
+                       this.stop(e);\r
+                       return this.prevent(e);\r
+               },\r
+\r
+               stop : function(e) {\r
+                       if (e.stopPropagation)\r
+                               e.stopPropagation();\r
+                       else\r
+                               e.cancelBubble = true;\r
+\r
+                       return false;\r
+               },\r
+\r
+               prevent : function(e) {\r
+                       if (e.preventDefault)\r
+                               e.preventDefault();\r
+                       else\r
+                               e.returnValue = false;\r
+\r
+                       return false;\r
+               },\r
+\r
+               _unload : function() {\r
+                       var t = Event;\r
+\r
+                       each(t.events, function(e, i) {\r
+                               t._remove(e.obj, e.name, e.cfunc);\r
+                               e.obj = e.cfunc = null;\r
+                       });\r
+\r
+                       t.events = [];\r
+                       t = null;\r
+               },\r
+\r
+               _add : function(o, n, f) {\r
+                       if (o.attachEvent)\r
+                               o.attachEvent('on' + n, f);\r
+                       else if (o.addEventListener)\r
+                               o.addEventListener(n, f, false);\r
+                       else\r
+                               o['on' + n] = f;\r
+               },\r
+\r
+               _remove : function(o, n, f) {\r
+                       if (o) {\r
+                               try {\r
+                                       if (o.detachEvent)\r
+                                               o.detachEvent('on' + n, f);\r
+                                       else if (o.removeEventListener)\r
+                                               o.removeEventListener(n, f, false);\r
+                                       else\r
+                                               o['on' + n] = null;\r
+                               } catch (ex) {\r
+                                       // Might fail with permission denined on IE so we just ignore that\r
+                               }\r
+                       }\r
+               },\r
+\r
+               _pageInit : function() {\r
+                       var e = Event;\r
+\r
+                       e._remove(window, 'DOMContentLoaded', e._pageInit);\r
+                       e.domLoaded = true;\r
+\r
+                       each(e.inits, function(c) {\r
+                               c();\r
+                       });\r
+\r
+                       e.inits = [];\r
+               },\r
+\r
+               _wait : function() {\r
+                       var t;\r
+\r
+                       // No need since the document is already loaded\r
+                       if (window.tinyMCE_GZ && tinyMCE_GZ.loaded)\r
+                               return;\r
+\r
+                       if (isIE && document.location.protocol != 'https:') {\r
+                               // Fake DOMContentLoaded on IE\r
+                               document.write('<script id=__ie_onload defer src=\'javascript:""\';><\/script>');\r
+                               DOM.get("__ie_onload").onreadystatechange = function() {\r
+                                       if (this.readyState == "complete") {\r
+                                               Event._pageInit();\r
+                                               DOM.get("__ie_onload").onreadystatechange = null; // Prevent leak\r
+                                       }\r
+                               };\r
+                       } else {\r
+                               Event._add(window, 'DOMContentLoaded', Event._pageInit, Event);\r
+\r
+                               if (isIE || isWebKit) {\r
+                                       t = setInterval(function() {\r
+                                               if (/loaded|complete/.test(document.readyState)) {\r
+                                                       clearInterval(t);\r
+                                                       Event._pageInit();\r
+                                               }\r
+                                       }, 10);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               });\r
+\r
+       // Shorten name\r
+       Event = tinymce.dom.Event;\r
+\r
+       // Dispatch DOM content loaded event for IE and Safari\r
+       Event._wait();\r
+       tinymce.addUnload(Event._unload);\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/dom/Element.js */\r
+\r
+(function() {\r
+       var each = tinymce.each;\r
+\r
+       tinymce.create('tinymce.dom.Element', {\r
+               Element : function(id, s) {\r
+                       var t = this, dom, el;\r
+\r
+                       s = s || {};\r
+                       t.id = id;\r
+                       t.dom = dom = s.dom || tinymce.DOM;\r
+                       t.settings = s;\r
+\r
+                       // Only IE leaks DOM references, this is a lot faster\r
+                       if (!tinymce.isIE)\r
+                               el = t.dom.get(t.id);\r
+\r
+                       each([\r
+                               'getPos',\r
+                               'getRect',\r
+                               'getParent',\r
+                               'add',\r
+                               'setStyle',\r
+                               'getStyle',\r
+                               'setStyles',\r
+                               'setAttrib',\r
+                               'setAttribs',\r
+                               'getAttrib',\r
+                               'addClass',\r
+                               'removeClass',\r
+                               'hasClass',\r
+                               'getOuterHTML',\r
+                               'setOuterHTML',\r
+                               'remove',\r
+                               'show',\r
+                               'hide',\r
+                               'isHidden',\r
+                               'setHTML',\r
+                               'get'\r
+                       ], function(k) {\r
+                               t[k] = function() {\r
+                                       var a = arguments, o;\r
+\r
+                                       // Opera fails\r
+                                       if (tinymce.isOpera) {\r
+                                               a = [id];\r
+\r
+                                               each(arguments, function(v) {\r
+                                                       a.push(v);\r
+                                               });\r
+                                       } else\r
+                                               Array.prototype.unshift.call(a, el || id);\r
+\r
+                                       o = dom[k].apply(dom, a);\r
+                                       t.update(k);\r
+\r
+                                       return o;\r
+                               };\r
+                       });\r
+               },\r
+\r
+               on : function(n, f, s) {\r
+                       return tinymce.dom.Event.add(this.id, n, f, s);\r
+               },\r
+\r
+               getXY : function() {\r
+                       return {\r
+                               x : parseInt(this.getStyle('left')),\r
+                               y : parseInt(this.getStyle('top'))\r
+                       };\r
+               },\r
+\r
+               getSize : function() {\r
+                       var n = this.dom.get(this.id);\r
+\r
+                       return {\r
+                               w : parseInt(this.getStyle('width') || n.clientWidth),\r
+                               h : parseInt(this.getStyle('height') || n.clientHeight)\r
+                       };\r
+               },\r
+\r
+               moveTo : function(x, y) {\r
+                       this.setStyles({left : x, top : y});\r
+               },\r
+\r
+               moveBy : function(x, y) {\r
+                       var p = this.getXY();\r
+\r
+                       this.moveTo(p.x + x, p.y + y);\r
+               },\r
+\r
+               resizeTo : function(w, h) {\r
+                       this.setStyles({width : w, height : h});\r
+               },\r
+\r
+               resizeBy : function(w, h) {\r
+                       var s = this.getSize();\r
+\r
+                       this.resizeTo(s.w + w, s.h + h);\r
+               },\r
+\r
+               update : function(k) {\r
+                       var t = this, b, dom = t.dom;\r
+\r
+                       if (tinymce.isIE6 && t.settings.blocker) {\r
+                               k = k || '';\r
+\r
+                               // Ignore getters\r
+                               if (k.indexOf('get') === 0 || k.indexOf('has') === 0 || k.indexOf('is') === 0)\r
+                                       return;\r
+\r
+                               // Remove blocker on remove\r
+                               if (k == 'remove') {\r
+                                       dom.remove(t.blocker);\r
+                                       return;\r
+                               }\r
+\r
+                               if (!t.blocker) {\r
+                                       t.blocker = dom.uniqueId();\r
+                                       b = dom.add(t.settings.container || dom.getRoot(), 'iframe', {id : t.blocker, style : 'position:absolute;', frameBorder : 0, src : 'javascript:""'});\r
+                                       dom.setStyle(b, 'opacity', 0);\r
+                               } else\r
+                                       b = dom.get(t.blocker);\r
+\r
+                               dom.setStyle(b, 'left', t.getStyle('left', 1));\r
+                               dom.setStyle(b, 'top', t.getStyle('top', 1));\r
+                               dom.setStyle(b, 'width', t.getStyle('width', 1));\r
+                               dom.setStyle(b, 'height', t.getStyle('height', 1));\r
+                               dom.setStyle(b, 'display', t.getStyle('display', 1));\r
+                               dom.setStyle(b, 'zIndex', parseInt(t.getStyle('zIndex', 1) || 0) - 1);\r
+                       }\r
+               }\r
+\r
+               });\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/dom/Selection.js */\r
+\r
+(function() {\r
+       // Shorten names\r
+       var is = tinymce.is, isIE = tinymce.isIE, each = tinymce.each;\r
+\r
+       tinymce.create('tinymce.dom.Selection', {\r
+               Selection : function(dom, win, serializer) {\r
+                       var t = this;\r
+\r
+                       t.dom = dom;\r
+                       t.win = win;\r
+                       t.serializer = serializer;\r
+\r
+                       // Prevent leaks\r
+                       tinymce.addUnload(t.destroy, t);\r
+               },\r
+\r
+               getContent : function(s) {\r
+                       var t = this, r = t.getRng(), e = t.dom.create("body"), se = t.getSel(), wb, wa, n;\r
+\r
+                       s = s || {};\r
+                       wb = wa = '';\r
+                       s.get = true;\r
+                       s.format = s.format || 'html';\r
+\r
+                       if (s.format == 'text')\r
+                               return t.isCollapsed() ? '' : (r.text || (se.toString ? se.toString() : ''));\r
+\r
+                       if (r.cloneContents) {\r
+                               n = r.cloneContents();\r
+\r
+                               if (n)\r
+                                       e.appendChild(n);\r
+                       } else if (is(r.item) || is(r.htmlText))\r
+                               e.innerHTML = r.item ? r.item(0).outerHTML : r.htmlText;\r
+                       else\r
+                               e.innerHTML = r.toString();\r
+\r
+                       // Keep whitespace before and after\r
+                       if (/^\s/.test(e.innerHTML))\r
+                               wb = ' ';\r
+\r
+                       if (/\s+$/.test(e.innerHTML))\r
+                               wa = ' ';\r
+\r
+                       s.getInner = true;\r
+\r
+                       return t.isCollapsed() ? '' : wb + t.serializer.serialize(e, s) + wa;\r
+               },\r
+\r
+               setContent : function(h, s) {\r
+                       var t = this, r = t.getRng(), d;\r
+\r
+                       s = s || {format : 'html'};\r
+                       s.set = true;\r
+                       h = t.dom.processHTML(h);\r
+\r
+                       if (r.insertNode) {\r
+                               d = t.win.document;\r
+\r
+                               // Gecko has a bug where if you insert &nbsp; using InsertHTML it will insert a space instead\r
+                               // So we simply check if the input is HTML or text and then insert text using the insertNode method\r
+                               if (tinymce.isGecko && h.indexOf('<') == -1) {\r
+                                       r.deleteContents();\r
+                                       r.insertNode(t.getRng().createContextualFragment(h + '<span id="__caret">_</span>'));\r
+                                       t.select(t.dom.get('__caret'));\r
+                                       t.getRng().deleteContents();\r
+                                       return;\r
+                               }\r
+\r
+                               // Use insert HTML if it exists (places cursor after content)\r
+                               try {\r
+                                       // This might fail with an exception see bug #1893736\r
+                                       if (d.queryCommandEnabled('InsertHTML'))\r
+                                               return d.execCommand('InsertHTML', false, h);\r
+                               } catch (ex) {\r
+                                       // Use old school method\r
+                                       r.deleteContents();\r
+                                       r.insertNode(t.getRng().createContextualFragment(h));\r
+                               }\r
+                       } else {\r
+                               if (r.item)\r
+                                       r.item(0).outerHTML = h;\r
+                               else\r
+                                       r.pasteHTML(h);\r
+                       }\r
+               },\r
+\r
+               getStart : function() {\r
+                       var t = this, r = t.getRng(), e;\r
+\r
+                       if (isIE) {\r
+                               if (r.item)\r
+                                       return r.item(0);\r
+\r
+                               r = r.duplicate();\r
+                               r.collapse(1);\r
+                               e = r.parentElement();\r
+\r
+                               if (e.nodeName == 'BODY')\r
+                                       return e.firstChild;\r
+\r
+                               return e;\r
+                       } else {\r
+                               e = r.startContainer;\r
+\r
+                               if (e.nodeName == 'BODY')\r
+                                       return e.firstChild;\r
+\r
+                               return t.dom.getParent(e, function(n) {return n.nodeType == 1;});\r
+                       }\r
+               },\r
+\r
+               getEnd : function() {\r
+                       var t = this, r = t.getRng(), e;\r
+\r
+                       if (isIE) {\r
+                               if (r.item)\r
+                                       return r.item(0);\r
+\r
+                               r = r.duplicate();\r
+                               r.collapse(0);\r
+                               e = r.parentElement();\r
+\r
+                               if (e.nodeName == 'BODY')\r
+                                       return e.lastChild;\r
+\r
+                               return e;\r
+                       } else {\r
+                               e = r.endContainer;\r
+\r
+                               if (e.nodeName == 'BODY')\r
+                                       return e.lastChild;\r
+\r
+                               return t.dom.getParent(e, function(n) {return n.nodeType == 1;});\r
+                       }\r
+               },\r
+\r
+               getBookmark : function(si) {\r
+                       var t = this, r = t.getRng(), tr, sx, sy, vp = t.dom.getViewPort(t.win), e, sp, bp, le, c = -0xFFFFFF, s, ro = t.dom.getRoot(), wb = 0, wa = 0, nv;\r
+                       sx = vp.x;\r
+                       sy = vp.y;\r
+\r
+                       // Simple bookmark fast but not as persistent\r
+                       if (si == 'simple')\r
+                               return {rng : r, scrollX : sx, scrollY : sy};\r
+\r
+                       // Handle IE\r
+                       if (isIE) {\r
+                               // Control selection\r
+                               if (r.item) {\r
+                                       e = r.item(0);\r
+\r
+                                       each(t.dom.select(e.nodeName), function(n, i) {\r
+                                               if (e == n) {\r
+                                                       sp = i;\r
+                                                       return false;\r
+                                               }\r
+                                       });\r
+\r
+                                       return {\r
+                                               tag : e.nodeName,\r
+                                               index : sp,\r
+                                               scrollX : sx,\r
+                                               scrollY : sy\r
+                                       };\r
+                               }\r
+\r
+                               // Text selection\r
+                               tr = t.dom.doc.body.createTextRange();\r
+                               tr.moveToElementText(ro);\r
+                               tr.collapse(true);\r
+                               bp = Math.abs(tr.move('character', c));\r
+\r
+                               tr = r.duplicate();\r
+                               tr.collapse(true);\r
+                               sp = Math.abs(tr.move('character', c));\r
+\r
+                               tr = r.duplicate();\r
+                               tr.collapse(false);\r
+                               le = Math.abs(tr.move('character', c)) - sp;\r
+\r
+                               return {\r
+                                       start : sp - bp,\r
+                                       length : le,\r
+                                       scrollX : sx,\r
+                                       scrollY : sy\r
+                               };\r
+                       }\r
+\r
+                       // Handle W3C\r
+                       e = t.getNode();\r
+                       s = t.getSel();\r
+\r
+                       if (!s)\r
+                               return null;\r
+\r
+                       // Image selection\r
+                       if (e && e.nodeName == 'IMG') {\r
+                               return {\r
+                                       scrollX : sx,\r
+                                       scrollY : sy\r
+                               };\r
+                       }\r
+\r
+                       // Text selection\r
+\r
+                       function getPos(r, sn, en) {\r
+                               var w = t.dom.doc.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};\r
+\r
+                               while ((n = w.nextNode()) != null) {\r
+                                       if (n == sn)\r
+                                               d.start = p;\r
+\r
+                                       if (n == en) {\r
+                                               d.end = p;\r
+                                               return d;\r
+                                       }\r
+\r
+                                       p += tinymce.trim(n.nodeValue || '').length;\r
+                               }\r
+\r
+                               return null;\r
+                       };\r
+\r
+                       // Caret or selection\r
+                       if (s.anchorNode == s.focusNode && s.anchorOffset == s.focusOffset) {\r
+                               e = getPos(ro, s.anchorNode, s.focusNode);\r
+\r
+                               if (!e)\r
+                                       return {scrollX : sx, scrollY : sy};\r
+\r
+                               // Count whitespace before\r
+                               (s.anchorNode.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});\r
+\r
+                               return {\r
+                                       start : Math.max(e.start + s.anchorOffset - wb, 0),\r
+                                       end : Math.max(e.end + s.focusOffset - wb, 0),\r
+                                       scrollX : sx,\r
+                                       scrollY : sy,\r
+                                       beg : s.anchorOffset - wb == 0\r
+                               };\r
+                       } else {\r
+                               e = getPos(ro, r.startContainer, r.endContainer);\r
+\r
+                               // Count whitespace before start and end container\r
+                               (r.startContainer.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});\r
+                               (r.endContainer.nodeValue || '').replace(/^\s+/, function(a) {wa = a.length;});\r
+\r
+                               if (!e)\r
+                                       return {scrollX : sx, scrollY : sy};\r
+\r
+                               return {\r
+                                       start : Math.max(e.start + r.startOffset - wb, 0),\r
+                                       end : Math.max(e.end + r.endOffset - wa, 0),\r
+                                       scrollX : sx,\r
+                                       scrollY : sy,\r
+                                       beg : r.startOffset - wb == 0\r
+                               };\r
+                       }\r
+               },\r
+\r
+               moveToBookmark : function(b) {\r
+                       var t = this, r = t.getRng(), s = t.getSel(), ro = t.dom.getRoot(), sd, nvl, nv;\r
+\r
+                       function getPos(r, sp, ep) {\r
+                               var w = t.dom.doc.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {}, o, v, wa, wb;\r
+\r
+                               while ((n = w.nextNode()) != null) {\r
+                                       wa = wb = 0;\r
+\r
+                                       nv = n.nodeValue || '';\r
+                                       nv.replace(/^\s+[^\s]/, function(a) {wb = a.length - 1;});\r
+                                       nv.replace(/[^\s]\s+$/, function(a) {wa = a.length - 1;});\r
+\r
+                                       nvl = tinymce.trim(nv).length;\r
+                                       p += nvl;\r
+\r
+                                       if (p >= sp && !d.startNode) {\r
+                                               o = sp - (p - nvl);\r
+\r
+                                               // Fix for odd quirk in FF\r
+                                               if (b.beg && o >= nvl)\r
+                                                       continue;\r
+\r
+                                               d.startNode = n;\r
+                                               d.startOffset = o + wb;\r
+                                       }\r
+\r
+                                       if (p >= ep) {\r
+                                               d.endNode = n;\r
+                                               d.endOffset = ep - (p - nvl) + wb;\r
+                                               return d;\r
+                                       }\r
+                               }\r
+\r
+                               return null;\r
+                       };\r
+\r
+                       if (!b)\r
+                               return false;\r
+\r
+                       t.win.scrollTo(b.scrollX, b.scrollY);\r
+\r
+                       // Handle explorer\r
+                       if (isIE) {\r
+                               // Handle simple\r
+                               if (r = b.rng) {\r
+                                       try {\r
+                                               r.select();\r
+                                       } catch (ex) {\r
+                                               // Ignore\r
+                                       }\r
+\r
+                                       return true;\r
+                               }\r
+\r
+                               t.win.focus();\r
+\r
+                               // Handle control bookmark\r
+                               if (b.tag) {\r
+                                       r = ro.createControlRange();\r
+\r
+                                       each(t.dom.select(b.tag), function(n, i) {\r
+                                               if (i == b.index)\r
+                                                       r.addElement(n);\r
+                                       });\r
+                               } else {\r
+                                       // Try/catch needed since this operation breaks when TinyMCE is placed in hidden divs/tabs\r
+                                       try {\r
+                                               // Incorrect bookmark\r
+                                               if (b.start < 0)\r
+                                                       return true;\r
+\r
+                                               r = s.createRange();\r
+                                               r.moveToElementText(ro);\r
+                                               r.collapse(true);\r
+                                               r.moveStart('character', b.start);\r
+                                               r.moveEnd('character', b.length);\r
+                                       } catch (ex2) {\r
+                                               return true;\r
+                                       }\r
+                               }\r
+\r
+                               try {\r
+                                       r.select();\r
+                               } catch (ex) {\r
+                                       // Needed for some odd IE bug #1843306\r
+                               }\r
+\r
+                               return true;\r
+                       }\r
+\r
+                       // Handle W3C\r
+                       if (!s)\r
+                               return false;\r
+\r
+                       // Handle simple\r
+                       if (b.rng) {\r
+                               s.removeAllRanges();\r
+                               s.addRange(b.rng);\r
+                       } else {\r
+                               if (is(b.start) && is(b.end)) {\r
+                                       try {\r
+                                               sd = getPos(ro, b.start, b.end);\r
+\r
+                                               if (sd) {\r
+                                                       r = t.dom.doc.createRange();\r
+                                                       r.setStart(sd.startNode, sd.startOffset);\r
+                                                       r.setEnd(sd.endNode, sd.endOffset);\r
+                                                       s.removeAllRanges();\r
+                                                       s.addRange(r);\r
+                                               }\r
+\r
+                                               if (!tinymce.isOpera)\r
+                                                       t.win.focus();\r
+                                       } catch (ex) {\r
+                                               // Ignore\r
+                                       }\r
+                               }\r
+                       }\r
+               },\r
+\r
+               select : function(n, c) {\r
+                       var t = this, r = t.getRng(), s = t.getSel(), b, fn, ln, d = t.win.document;\r
+\r
+                       function first(n) {\r
+                               return n ? d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false).nextNode() : null;\r
+                       };\r
+\r
+                       function last(n) {\r
+                               var c, o, w;\r
+\r
+                               if (!n)\r
+                                       return null;\r
+\r
+                               w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);\r
+                               while (c = w.nextNode())\r
+                                       o = c;\r
+\r
+                               return o;\r
+                       };\r
+\r
+                       if (isIE) {\r
+                               try {\r
+                                       b = d.body;\r
+\r
+                                       if (/^(IMG|TABLE)$/.test(n.nodeName)) {\r
+                                               r = b.createControlRange();\r
+                                               r.addElement(n);\r
+                                       } else {\r
+                                               r = b.createTextRange();\r
+                                               r.moveToElementText(n);\r
+                                       }\r
+\r
+                                       r.select();\r
+                               } catch (ex) {\r
+                                       // Throws illigal agrument in IE some times\r
+                               }\r
+                       } else {\r
+                               if (c) {\r
+                                       fn = first(n);\r
+                                       ln = last(n);\r
+\r
+                                       if (fn && ln) {\r
+                                               //console.debug(fn, ln);\r
+                                               r = d.createRange();\r
+                                               r.setStart(fn, 0);\r
+                                               r.setEnd(ln, ln.nodeValue.length);\r
+                                       } else\r
+                                               r.selectNode(n);\r
+                               } else\r
+                                       r.selectNode(n);\r
+\r
+                               t.setRng(r);\r
+                       }\r
+\r
+                       return n;\r
+               },\r
+\r
+               isCollapsed : function() {\r
+                       var t = this, r = t.getRng(), s = t.getSel();\r
+\r
+                       if (!r || r.item)\r
+                               return false;\r
+\r
+                       return !s || r.boundingWidth == 0 || s.isCollapsed;\r
+               },\r
+\r
+               collapse : function(b) {\r
+                       var t = this, r = t.getRng(), n;\r
+\r
+                       // Control range on IE\r
+                       if (r.item) {\r
+                               n = r.item(0);\r
+                               r = this.win.document.body.createTextRange();\r
+                               r.moveToElementText(n);\r
+                       }\r
+\r
+                       r.collapse(!!b);\r
+                       t.setRng(r);\r
+               },\r
+\r
+               getSel : function() {\r
+                       var t = this, w = this.win;\r
+\r
+                       return w.getSelection ? w.getSelection() : w.document.selection;\r
+               },\r
+\r
+               getRng : function() {\r
+                       var t = this, s = t.getSel(), r;\r
+\r
+                       try {\r
+                               if (s)\r
+                                       r = s.rangeCount > 0 ? s.getRangeAt(0) : (s.createRange ? s.createRange() : t.win.document.createRange());\r
+                       } catch (ex) {\r
+                               // IE throws unspecified error here if TinyMCE is placed in a frame/iframe\r
+                       }\r
+\r
+                       // No range found then create an empty one\r
+                       // This can occur when the editor is placed in a hidden container element on Gecko\r
+                       // Or on IE when there was an exception\r
+                       if (!r)\r
+                               r = isIE ? t.win.document.body.createTextRange() : t.win.document.createRange();\r
+\r
+                       return r;\r
+               },\r
+\r
+               setRng : function(r) {\r
+                       var s;\r
+\r
+                       if (!isIE) {\r
+                               s = this.getSel();\r
+\r
+                               if (s) {\r
+                                       s.removeAllRanges();\r
+                                       s.addRange(r);\r
+                               }\r
+                       } else {\r
+                               try {\r
+                                       r.select();\r
+                               } catch (ex) {\r
+                                       // Needed for some odd IE bug #1843306\r
+                               }\r
+                       }\r
+               },\r
+\r
+               setNode : function(n) {\r
+                       var t = this;\r
+\r
+                       t.setContent(t.dom.getOuterHTML(n));\r
+\r
+                       return n;\r
+               },\r
+\r
+               getNode : function() {\r
+                       var t = this, r = t.getRng(), s = t.getSel(), e;\r
+\r
+                       if (!isIE) {\r
+                               // Range maybe lost after the editor is made visible again\r
+                               if (!r)\r
+                                       return t.dom.getRoot();\r
+\r
+                               e = r.commonAncestorContainer;\r
+\r
+                               // Handle selection a image or other control like element such as anchors\r
+                               if (!r.collapsed) {\r
+                                       if (r.startContainer == r.endContainer || (tinymce.isWebKit && r.startContainer == r.endContainer.parentNode)) {\r
+                                               if (r.startOffset - r.endOffset < 2 || tinymce.isWebKit) {\r
+                                                       if (r.startContainer.hasChildNodes())\r
+                                                               e = r.startContainer.childNodes[r.startOffset];\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               return t.dom.getParent(e, function(n) {\r
+                                       return n.nodeType == 1;\r
+                               });\r
+                       }\r
+\r
+                       return r.item ? r.item(0) : r.parentElement();\r
+               },\r
+\r
+               destroy : function(s) {\r
+                       var t = this;\r
+\r
+                       t.win = null;\r
+\r
+                       // Manual destroy then remove unload handler\r
+                       if (!s)\r
+                               tinymce.removeUnload(t.destroy);\r
+               }\r
+\r
+               });\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/dom/XMLWriter.js */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.dom.XMLWriter', {\r
+               node : null,\r
+\r
+               XMLWriter : function(s) {\r
+                       // Get XML document\r
+                       function getXML() {\r
+                               var i = document.implementation;\r
+\r
+                               if (!i || !i.createDocument) {\r
+                                       // Try IE objects\r
+                                       try {return new ActiveXObject('MSXML2.DOMDocument');} catch (ex) {}\r
+                                       try {return new ActiveXObject('Microsoft.XmlDom');} catch (ex) {}\r
+                               } else\r
+                                       return i.createDocument('', '', null);\r
+                       };\r
+\r
+                       this.doc = getXML();\r
+                       \r
+                       // Since Opera and WebKit doesn't escape > into &gt; we need to do it our self to normalize the output for all browsers\r
+                       this.valid = tinymce.isOpera || tinymce.isWebKit;\r
+\r
+                       this.reset();\r
+               },\r
+\r
+               reset : function() {\r
+                       var t = this, d = t.doc;\r
+\r
+                       if (d.firstChild)\r
+                               d.removeChild(d.firstChild);\r
+\r
+                       t.node = d.appendChild(d.createElement("html"));\r
+               },\r
+\r
+               writeStartElement : function(n) {\r
+                       var t = this;\r
+\r
+                       t.node = t.node.appendChild(t.doc.createElement(n));\r
+               },\r
+\r
+               writeAttribute : function(n, v) {\r
+                       if (this.valid)\r
+                               v = v.replace(/>/g, '%MCGT%');\r
+\r
+                       this.node.setAttribute(n, v);\r
+               },\r
+\r
+               writeEndElement : function() {\r
+                       this.node = this.node.parentNode;\r
+               },\r
+\r
+               writeFullEndElement : function() {\r
+                       var t = this, n = t.node;\r
+\r
+                       n.appendChild(t.doc.createTextNode(""));\r
+                       t.node = n.parentNode;\r
+               },\r
+\r
+               writeText : function(v) {\r
+                       if (this.valid)\r
+                               v = v.replace(/>/g, '%MCGT%');\r
+\r
+                       this.node.appendChild(this.doc.createTextNode(v));\r
+               },\r
+\r
+               writeCDATA : function(v) {\r
+                       this.node.appendChild(this.doc.createCDATA(v));\r
+               },\r
+\r
+               writeComment : function(v) {\r
+                       this.node.appendChild(this.doc.createComment(v.replace(/\-\-/g, ' ')));\r
+               },\r
+\r
+               getContent : function() {\r
+                       var h;\r
+\r
+                       h = this.doc.xml || new XMLSerializer().serializeToString(this.doc);\r
+                       h = h.replace(/<\?[^?]+\?>|<html>|<\/html>|<html\/>|<!DOCTYPE[^>]+>/g, '');\r
+                       h = h.replace(/ ?\/>/g, ' />');\r
+\r
+                       if (this.valid)\r
+                               h = h.replace(/\%MCGT%/g, '&gt;');\r
+\r
+                       return h;\r
+               }\r
+\r
+               });\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/dom/StringWriter.js */\r
+\r
+(function() {\r
+       tinymce.create('tinymce.dom.StringWriter', {\r
+               str : null,\r
+               tags : null,\r
+               count : 0,\r
+               settings : null,\r
+               indent : null,\r
+\r
+               StringWriter : function(s) {\r
+                       this.settings = tinymce.extend({\r
+                               indent_char : ' ',\r
+                               indentation : 1\r
+                       }, s);\r
+\r
+                       this.reset();\r
+               },\r
+\r
+               reset : function() {\r
+                       this.indent = '';\r
+                       this.str = "";\r
+                       this.tags = [];\r
+                       this.count = 0;\r
+               },\r
+\r
+               writeStartElement : function(n) {\r
+                       this._writeAttributesEnd();\r
+                       this.writeRaw('<' + n);\r
+                       this.tags.push(n);\r
+                       this.inAttr = true;\r
+                       this.count++;\r
+                       this.elementCount = this.count;\r
+               },\r
+\r
+               writeAttribute : function(n, v) {\r
+                       var t = this;\r
+\r
+                       t.writeRaw(" " + t.encode(n) + '="' + t.encode(v) + '"');\r
+               },\r
+\r
+               writeEndElement : function() {\r
+                       var n;\r
+\r
+                       if (this.tags.length > 0) {\r
+                               n = this.tags.pop();\r
+\r
+                               if (this._writeAttributesEnd(1))\r
+                                       this.writeRaw('</' + n + '>');\r
+\r
+                               if (this.settings.indentation > 0)\r
+                                       this.writeRaw('\n');\r
+                       }\r
+               },\r
+\r
+               writeFullEndElement : function() {\r
+                       if (this.tags.length > 0) {\r
+                               this._writeAttributesEnd();\r
+                               this.writeRaw('</' + this.tags.pop() + '>');\r
+\r
+                               if (this.settings.indentation > 0)\r
+                                       this.writeRaw('\n');\r
+                       }\r
+               },\r
+\r
+               writeText : function(v) {\r
+                       this._writeAttributesEnd();\r
+                       this.writeRaw(this.encode(v));\r
+                       this.count++;\r
+               },\r
+\r
+               writeCDATA : function(v) {\r
+                       this._writeAttributesEnd();\r
+                       this.writeRaw('<![CDATA[' + v + ']]>');\r
+                       this.count++;\r
+               },\r
+\r
+               writeComment : function(v) {\r
+                       this._writeAttributesEnd();\r
+                       this.writeRaw('<!-- ' + v + '-->');\r
+                       this.count++;\r
+               },\r
+\r
+               writeRaw : function(v) {\r
+                       this.str += v;\r
+               },\r
+\r
+               encode : function(s) {\r
+                       return s.replace(/[<>&"]/g, function(v) {\r
+                               switch (v) {\r
+                                       case '<':\r
+                                               return '&lt;';\r
+\r
+                                       case '>':\r
+                                               return '&gt;';\r
+\r
+                                       case '&':\r
+                                               return '&amp;';\r
+\r
+                                       case '"':\r
+                                               return '&quot;';\r
+                               }\r
+\r
+                               return v;\r
+                       });\r
+               },\r
+\r
+               getContent : function() {\r
+                       return this.str;\r
+               },\r
+\r
+               _writeAttributesEnd : function(s) {\r
+                       if (!this.inAttr)\r
+                               return;\r
+\r
+                       this.inAttr = false;\r
+\r
+                       if (s && this.elementCount == this.count) {\r
+                               this.writeRaw(' />');\r
+                               return false;\r
+                       }\r
+\r
+                       this.writeRaw('>');\r
+\r
+                       return true;\r
+               }\r
+\r
+               });\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/dom/Serializer.js */\r
+\r
+(function() {\r
+       // Shorten names\r
+       var extend = tinymce.extend, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher, isIE = tinymce.isIE, isGecko = tinymce.isGecko;\r
+\r
+       // Returns only attribites that have values not all attributes in IE\r
+       function getIEAtts(n) {\r
+               var o = [];\r
+\r
+               // Object will throw exception in IE\r
+               if (n.nodeName == 'OBJECT')\r
+                       return n.attributes;\r
+\r
+               n.cloneNode(false).outerHTML.replace(/([a-z0-9\:\-_]+)=/gi, function(a, b) {\r
+                       o.push({specified : 1, nodeName : b});\r
+               });\r
+\r
+               return o;\r
+       };\r
+\r
+       function wildcardToRE(s) {\r
+               return s.replace(/([?+*])/g, '.$1');\r
+       };\r
+\r
+       tinymce.create('tinymce.dom.Serializer', {\r
+               Serializer : function(s) {\r
+                       var t = this;\r
+\r
+                       t.key = 0;\r
+                       t.onPreProcess = new Dispatcher(t);\r
+                       t.onPostProcess = new Dispatcher(t);\r
+\r
+                       if (tinymce.relaxedDomain && tinymce.isGecko) {\r
+                               // Gecko has a bug where we can't create a new XML document if domain relaxing is used\r
+                               t.writer = new tinymce.dom.StringWriter();\r
+                       } else {\r
+                               try {\r
+                                       t.writer = new tinymce.dom.XMLWriter();\r
+                               } catch (ex) {\r
+                                       // IE might throw exception if ActiveX is disabled so we then switch to the slightly slower StringWriter\r
+                                       t.writer = new tinymce.dom.StringWriter();\r
+                               }\r
+                       }\r
+\r
+                       // Default settings\r
+                       t.settings = s = extend({\r
+                               dom : tinymce.DOM,\r
+                               valid_nodes : 0,\r
+                               node_filter : 0,\r
+                               attr_filter : 0,\r
+                               invalid_attrs : /^(mce_|_moz_)/,\r
+                               closed : /(br|hr|input|meta|img|link|param)/,\r
+                               entity_encoding : 'named',\r
+                               entities : '160,nbsp,161,iexcl,162,cent,163,pound,164,curren,165,yen,166,brvbar,167,sect,168,uml,169,copy,170,ordf,171,laquo,172,not,173,shy,174,reg,175,macr,176,deg,177,plusmn,178,sup2,179,sup3,180,acute,181,micro,182,para,183,middot,184,cedil,185,sup1,186,ordm,187,raquo,188,frac14,189,frac12,190,frac34,191,iquest,192,Agrave,193,Aacute,194,Acirc,195,Atilde,196,Auml,197,Aring,198,AElig,199,Ccedil,200,Egrave,201,Eacute,202,Ecirc,203,Euml,204,Igrave,205,Iacute,206,Icirc,207,Iuml,208,ETH,209,Ntilde,210,Ograve,211,Oacute,212,Ocirc,213,Otilde,214,Ouml,215,times,216,Oslash,217,Ugrave,218,Uacute,219,Ucirc,220,Uuml,221,Yacute,222,THORN,223,szlig,224,agrave,225,aacute,226,acirc,227,atilde,228,auml,229,aring,230,aelig,231,ccedil,232,egrave,233,eacute,234,ecirc,235,euml,236,igrave,237,iacute,238,icirc,239,iuml,240,eth,241,ntilde,242,ograve,243,oacute,244,ocirc,245,otilde,246,ouml,247,divide,248,oslash,249,ugrave,250,uacute,251,ucirc,252,uuml,253,yacute,254,thorn,255,yuml,402,fnof,913,Alpha,914,Beta,915,Gamma,916,Delta,917,Epsilon,918,Zeta,919,Eta,920,Theta,921,Iota,922,Kappa,923,Lambda,924,Mu,925,Nu,926,Xi,927,Omicron,928,Pi,929,Rho,931,Sigma,932,Tau,933,Upsilon,934,Phi,935,Chi,936,Psi,937,Omega,945,alpha,946,beta,947,gamma,948,delta,949,epsilon,950,zeta,951,eta,952,theta,953,iota,954,kappa,955,lambda,956,mu,957,nu,958,xi,959,omicron,960,pi,961,rho,962,sigmaf,963,sigma,964,tau,965,upsilon,966,phi,967,chi,968,psi,969,omega,977,thetasym,978,upsih,982,piv,8226,bull,8230,hellip,8242,prime,8243,Prime,8254,oline,8260,frasl,8472,weierp,8465,image,8476,real,8482,trade,8501,alefsym,8592,larr,8593,uarr,8594,rarr,8595,darr,8596,harr,8629,crarr,8656,lArr,8657,uArr,8658,rArr,8659,dArr,8660,hArr,8704,forall,8706,part,8707,exist,8709,empty,8711,nabla,8712,isin,8713,notin,8715,ni,8719,prod,8721,sum,8722,minus,8727,lowast,8730,radic,8733,prop,8734,infin,8736,ang,8743,and,8744,or,8745,cap,8746,cup,8747,int,8756,there4,8764,sim,8773,cong,8776,asymp,8800,ne,8801,equiv,8804,le,8805,ge,8834,sub,8835,sup,8836,nsub,8838,sube,8839,supe,8853,oplus,8855,otimes,8869,perp,8901,sdot,8968,lceil,8969,rceil,8970,lfloor,8971,rfloor,9001,lang,9002,rang,9674,loz,9824,spades,9827,clubs,9829,hearts,9830,diams,338,OElig,339,oelig,352,Scaron,353,scaron,376,Yuml,710,circ,732,tilde,8194,ensp,8195,emsp,8201,thinsp,8204,zwnj,8205,zwj,8206,lrm,8207,rlm,8211,ndash,8212,mdash,8216,lsquo,8217,rsquo,8218,sbquo,8220,ldquo,8221,rdquo,8222,bdquo,8224,dagger,8225,Dagger,8240,permil,8249,lsaquo,8250,rsaquo,8364,euro',\r
+                               valid_elements : '*[*]',\r
+                               extended_valid_elements : 0,\r
+                               valid_child_elements : 0,\r
+                               invalid_elements : 0,\r
+                               fix_table_elements : 0,\r
+                               fix_list_elements : true,\r
+                               fix_content_duplication : true,\r
+                               convert_fonts_to_spans : false,\r
+                               font_size_classes : 0,\r
+                               font_size_style_values : 0,\r
+                               apply_source_formatting : 0,\r
+                               indent_mode : 'simple',\r
+                               indent_char : '\t',\r
+                               indent_levels : 1,\r
+                               remove_linebreaks : 1\r
+                       }, s);\r
+\r
+                       t.dom = s.dom;\r
+\r
+                       if (s.fix_list_elements) {\r
+                               t.onPreProcess.add(function(se, o) {\r
+                                       var nl, x, a = ['ol', 'ul'], i, n, p, r = /^(OL|UL)$/, np;\r
+\r
+                                       function prevNode(e, n) {\r
+                                               var a = n.split(','), i;\r
+\r
+                                               while ((e = e.previousSibling) != null) {\r
+                                                       for (i=0; i<a.length; i++) {\r
+                                                               if (e.nodeName == a[i])\r
+                                                                       return e;\r
+                                                       }\r
+                                               }\r
+\r
+                                               return null;\r
+                                       };\r
+\r
+                                       for (x=0; x<a.length; x++) {\r
+                                               nl = t.dom.select(a[x], o.node);\r
+\r
+                                               for (i=0; i<nl.length; i++) {\r
+                                                       n = nl[i];\r
+                                                       p = n.parentNode;\r
+\r
+                                                       if (r.test(p.nodeName)) {\r
+                                                               np = prevNode(n, 'LI');\r
+\r
+                                                               if (!np) {\r
+                                                                       np = t.dom.create('li');\r
+                                                                       np.innerHTML = '&nbsp;';\r
+                                                                       np.appendChild(n);\r
+                                                                       p.insertBefore(np, p.firstChild);\r
+                                                               } else\r
+                                                                       np.appendChild(n);\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               });\r
+                       }\r
+\r
+                       if (s.fix_table_elements) {\r
+                               t.onPreProcess.add(function(se, o) {\r
+                                       each(t.dom.select('table', o.node), function(e) {\r
+                                               var pa = t.dom.getParent(e, 'H1,H2,H3,H4,H5,H6,P'), pa2, n, tm, pl = [], i, ns;\r
+\r
+                                               if (pa) {\r
+                                                       pa2 = pa.cloneNode(false);\r
+\r
+                                                       pl.push(e);\r
+                                                       for (n = e; n = n.parentNode;) {\r
+                                                               pl.push(n);\r
+\r
+                                                               if (n == pa)\r
+                                                                       break;\r
+                                                       }\r
+\r
+                                                       tm = pa2;\r
+                                                       for (i = pl.length - 1; i >= 0; i--) {\r
+                                                               if (i == pl.length - 1) {\r
+                                                                       while (ns = pl[i - 1].nextSibling)\r
+                                                                               tm.appendChild(ns.parentNode.removeChild(ns));\r
+                                                               } else {\r
+                                                                       n = pl[i].cloneNode(false);\r
+\r
+                                                                       if (i != 0) {\r
+                                                                               while (ns = pl[i - 1].nextSibling)\r
+                                                                                       n.appendChild(ns.parentNode.removeChild(ns));\r
+                                                                       }\r
+\r
+                                                                       tm = tm.appendChild(n);\r
+                                                               }\r
+                                                       }\r
+\r
+                                                       e = t.dom.insertAfter(e.parentNode.removeChild(e), pa);\r
+                                                       t.dom.insertAfter(e, pa);\r
+                                                       t.dom.insertAfter(pa2, e);\r
+                                               }\r
+                                       });\r
+                               });\r
+                       }\r
+               },\r
+\r
+               setEntities : function(s) {\r
+                       var t = this, a, i, l = {}, re = '', v;\r
+\r
+                       // No need to setup more than once\r
+                       if (t.entityLookup)\r
+                               return;\r
+\r
+                       // Build regex and lookup array\r
+                       a = s.split(',');\r
+                       for (i = 0; i < a.length; i += 2) {\r
+                               v = a[i];\r
+\r
+                               // Don't add default &amp; &quot; etc.\r
+                               if (v == 34 || v == 38 || v == 60 || v == 62)\r
+                                       continue;\r
+\r
+                               l[String.fromCharCode(a[i])] = a[i + 1];\r
+\r
+                               v = parseInt(a[i]).toString(16);\r
+                               re += '\\u' + '0000'.substring(v.length) + v;\r
+                       }\r
+\r
+                       if (!re) {\r
+                               t.settings.entity_encoding = 'raw';\r
+                               return;\r
+                       }\r
+\r
+                       t.entitiesRE = new RegExp('[' + re + ']', 'g');\r
+                       t.entityLookup = l;\r
+               },\r
+\r
+               setValidChildRules : function(s) {\r
+                       this.childRules = null;\r
+                       this.addValidChildRules(s);\r
+               },\r
+\r
+               addValidChildRules : function(s) {\r
+                       var t = this, inst, intr, bloc;\r
+\r
+                       if (!s)\r
+                               return;\r
+\r
+                       inst = 'A|BR|SPAN|BDO|MAP|OBJECT|IMG|TT|I|B|BIG|SMALL|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|#text|#comment';\r
+                       intr = 'A|BR|SPAN|BDO|OBJECT|APPLET|IMG|MAP|IFRAME|TT|I|B|U|S|STRIKE|BIG|SMALL|FONT|BASEFONT|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|INPUT|SELECT|TEXTAREA|LABEL|BUTTON|#text|#comment';\r
+                       bloc = 'H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP';\r
+\r
+                       each(s.split(','), function(s) {\r
+                               var p = s.split(/\[|\]/), re;\r
+\r
+                               s = '';\r
+                               each(p[1].split('|'), function(v) {\r
+                                       if (s)\r
+                                               s += '|';\r
+\r
+                                       switch (v) {\r
+                                               case '%itrans':\r
+                                                       v = intr;\r
+                                                       break;\r
+\r
+                                               case '%itrans_na':\r
+                                                       v = intr.substring(2);\r
+                                                       break;\r
+\r
+                                               case '%istrict':\r
+                                                       v = inst;\r
+                                                       break;\r
+\r
+                                               case '%istrict_na':\r
+                                                       v = inst.substring(2);\r
+                                                       break;\r
+\r
+                                               case '%btrans':\r
+                                                       v = bloc;\r
+                                                       break;\r
+\r
+                                               case '%bstrict':\r
+                                                       v = bloc;\r
+                                                       break;\r
+                                       }\r
+\r
+                                       s += v;\r
+                               });\r
+                               re = new RegExp('^(' + s.toLowerCase() + ')$', 'i');\r
+\r
+                               each(p[0].split('/'), function(s) {\r
+                                       t.childRules = t.childRules || {};\r
+                                       t.childRules[s] = re;\r
+                               });\r
+                       });\r
+\r
+                       // Build regex\r
+                       s = '';\r
+                       each(t.childRules, function(v, k) {\r
+                               if (s)\r
+                                       s += '|';\r
+\r
+                               s += k;\r
+                       });\r
+\r
+                       t.parentElementsRE = new RegExp('^(' + s.toLowerCase() + ')$', 'i');\r
+\r
+                       /*console.debug(t.parentElementsRE.toString());\r
+                       each(t.childRules, function(v) {\r
+                               console.debug(v.toString());\r
+                       });*/\r
+               },\r
+\r
+               setRules : function(s) {\r
+                       var t = this;\r
+\r
+                       t._setup();\r
+                       t.rules = {};\r
+                       t.wildRules = [];\r
+                       t.validElements = {};\r
+\r
+                       return t.addRules(s);\r
+               },\r
+\r
+               addRules : function(s) {\r
+                       var t = this, dr;\r
+\r
+                       if (!s)\r
+                               return;\r
+\r
+                       t._setup();\r
+\r
+                       each(s.split(','), function(s) {\r
+                               var p = s.split(/\[|\]/), tn = p[0].split('/'), ra, at, wat, va = [];\r
+\r
+                               // Extend with default rules\r
+                               if (dr)\r
+                                       at = tinymce.extend([], dr.attribs);\r
+\r
+                               // Parse attributes\r
+                               if (p.length > 1) {\r
+                                       each(p[1].split('|'), function(s) {\r
+                                               var ar = {}, i;\r
+\r
+                                               at = at || [];\r
+\r
+                                               // Parse attribute rule\r
+                                               s = s.replace(/::/g, '~');\r
+                                               s = /^([!\-])?([\w*.?~_\-]+|)([=:<])?(.+)?$/.exec(s);\r
+                                               s[2] = s[2].replace(/~/g, ':');\r
+\r
+                                               // Add required attributes\r
+                                               if (s[1] == '!') {\r
+                                                       ra = ra || [];\r
+                                                       ra.push(s[2]);\r
+                                               }\r
+\r
+                                               // Remove inherited attributes\r
+                                               if (s[1] == '-') {\r
+                                                       for (i = 0; i <at.length; i++) {\r
+                                                               if (at[i].name == s[2]) {\r
+                                                                       at.splice(i, 1);\r
+                                                                       return;\r
+                                                               }\r
+                                                       }\r
+                                               }\r
+\r
+                                               switch (s[3]) {\r
+                                                       // Add default attrib values\r
+                                                       case '=':\r
+                                                               ar.defaultVal = s[4] || '';\r
+                                                               break;\r
+\r
+                                                       // Add forced attrib values\r
+                                                       case ':':\r
+                                                               ar.forcedVal = s[4];\r
+                                                               break;\r
+\r
+                                                       // Add validation values\r
+                                                       case '<':\r
+                                                               ar.validVals = s[4].split('?');\r
+                                                               break;\r
+                                               }\r
+\r
+                                               if (/[*.?]/.test(s[2])) {\r
+                                                       wat = wat || [];\r
+                                                       ar.nameRE = new RegExp('^' + wildcardToRE(s[2]) + '$');\r
+                                                       wat.push(ar);\r
+                                               } else {\r
+                                                       ar.name = s[2];\r
+                                                       at.push(ar);\r
+                                               }\r
+\r
+                                               va.push(s[2]);\r
+                                       });\r
+                               }\r
+\r
+                               // Handle element names\r
+                               each(tn, function(s, i) {\r
+                                       var pr = s.charAt(0), x = 1, ru = {};\r
+\r
+                                       // Extend with default rule data\r
+                                       if (dr) {\r
+                                               if (dr.noEmpty)\r
+                                                       ru.noEmpty = dr.noEmpty;\r
+\r
+                                               if (dr.fullEnd)\r
+                                                       ru.fullEnd = dr.fullEnd;\r
+\r
+                                               if (dr.padd)\r
+                                                       ru.padd = dr.padd;\r
+                                       }\r
+\r
+                                       // Handle prefixes\r
+                                       switch (pr) {\r
+                                               case '-':\r
+                                                       ru.noEmpty = true;\r
+                                                       break;\r
+\r
+                                               case '+':\r
+                                                       ru.fullEnd = true;\r
+                                                       break;\r
+\r
+                                               case '#':\r
+                                                       ru.padd = true;\r
+                                                       break;\r
+\r
+                                               default:\r
+                                                       x = 0;\r
+                                       }\r
+\r
+                                       tn[i] = s = s.substring(x);\r
+                                       t.validElements[s] = 1;\r
+\r
+                                       // Add element name or element regex\r
+                                       if (/[*.?]/.test(tn[0])) {\r
+                                               ru.nameRE = new RegExp('^' + wildcardToRE(tn[0]) + '$');\r
+                                               t.wildRules = t.wildRules || {};\r
+                                               t.wildRules.push(ru);\r
+                                       } else {\r
+                                               ru.name = tn[0];\r
+\r
+                                               // Store away default rule\r
+                                               if (tn[0] == '@')\r
+                                                       dr = ru;\r
+\r
+                                               t.rules[s] = ru;\r
+                                       }\r
+\r
+                                       ru.attribs = at;\r
+\r
+                                       if (ra)\r
+                                               ru.requiredAttribs = ra;\r
+\r
+                                       if (wat) {\r
+                                               // Build valid attributes regexp\r
+                                               s = '';\r
+                                               each(va, function(v) {\r
+                                                       if (s)\r
+                                                               s += '|';\r
+\r
+                                                       s += '(' + wildcardToRE(v) + ')';\r
+                                               });\r
+                                               ru.validAttribsRE = new RegExp('^' + s.toLowerCase() + '$');\r
+                                               ru.wildAttribs = wat;\r
+                                       }\r
+                               });\r
+                       });\r
+\r
+                       // Build valid elements regexp\r
+                       s = '';\r
+                       each(t.validElements, function(v, k) {\r
+                               if (s)\r
+                                       s += '|';\r
+\r
+                               if (k != '@')\r
+                                       s += k;\r
+                       });\r
+                       t.validElementsRE = new RegExp('^(' + wildcardToRE(s.toLowerCase()) + ')$');\r
+\r
+                       //console.debug(t.validElementsRE.toString());\r
+                       //console.dir(t.rules);\r
+                       //console.dir(t.wildRules);\r
+               },\r
+\r
+               findRule : function(n) {\r
+                       var t = this, rl = t.rules, i, r;\r
+\r
+                       t._setup();\r
+\r
+                       // Exact match\r
+                       r = rl[n];\r
+                       if (r)\r
+                               return r;\r
+\r
+                       // Try wildcards\r
+                       rl = t.wildRules;\r
+                       for (i = 0; i < rl.length; i++) {\r
+                               if (rl[i].nameRE.test(n))\r
+                                       return rl[i];\r
+                       }\r
+\r
+                       return null;\r
+               },\r
+\r
+               findAttribRule : function(ru, n) {\r
+                       var i, wa = ru.wildAttribs;\r
+\r
+                       for (i = 0; i < wa.length; i++) {\r
+                               if (wa[i].nameRE.test(n))\r
+                                       return wa[i];\r
+                       }\r
+\r
+                       return null;\r
+               },\r
+\r
+               serialize : function(n, o) {\r
+                       var h, t = this;\r
+\r
+                       t._setup();\r
+                       o = o || {};\r
+                       o.format = o.format || 'html';\r
+                       t.processObj = o;\r
+                       n = n.cloneNode(true);\r
+                       t.key = '' + (parseInt(t.key) + 1);\r
+\r
+                       // Pre process\r
+                       if (!o.no_events) {\r
+                               o.node = n;\r
+                               t.onPreProcess.dispatch(t, o);\r
+                       }\r
+\r
+                       // Serialize HTML DOM into a string\r
+                       t.writer.reset();\r
+                       t._serializeNode(n, o.getInner);\r
+\r
+                       // Post process\r
+                       o.content = t.writer.getContent();\r
+\r
+                       if (!o.no_events)\r
+                               t.onPostProcess.dispatch(t, o);\r
+\r
+                       t._postProcess(o);\r
+                       o.node = null;\r
+\r
+                       return tinymce.trim(o.content);\r
+               },\r
+\r
+               // Internal functions\r
+\r
+               _postProcess : function(o) {\r
+                       var t = this, s = t.settings, h = o.content, sc = [], p;\r
+\r
+                       if (o.format == 'html') {\r
+                               // Protect some elements\r
+                               p = t._protect({\r
+                                       content : h,\r
+                                       patterns : [\r
+                                               {pattern : /(<script[^>]*>)(.*?)(<\/script>)/g},\r
+                                               {pattern : /(<style[^>]*>)(.*?)(<\/style>)/g},\r
+                                               {pattern : /(<pre[^>]*>)(.*?)(<\/pre>)/g, encode : 1}\r
+                                       ]\r
+                               });\r
+\r
+                               h = p.content;\r
+\r
+                               // Entity encode\r
+                               if (s.entity_encoding !== 'raw')\r
+                                       h = t._encode(h);\r
+\r
+                               // Use BR instead of &nbsp; padded P elements inside editor and use <p>&nbsp;</p> outside editor\r
+/*                             if (o.set)\r
+                                       h = h.replace(/<p>\s+(&nbsp;|&#160;|\u00a0|<br \/>)\s+<\/p>/g, '<p><br /></p>');\r
+                               else\r
+                                       h = h.replace(/<p>\s+(&nbsp;|&#160;|\u00a0|<br \/>)\s+<\/p>/g, '<p>$1</p>');*/\r
+\r
+                               // Since Gecko and Safari keeps whitespace in the DOM we need to\r
+                               // remove it inorder to match other browsers. But I think Gecko and Safari is right.\r
+                               // This process is only done when getting contents out from the editor.\r
+                               if (!o.set) {\r
+                                       // We need to replace paragraph whitespace with an nbsp before indentation to keep the \u00a0 char\r
+                                       h = h.replace(/<p>\s+<\/p>|<p([^>]+)>\s+<\/p>/g, s.entity_encoding == 'numeric' ? '<p$1>&#160;</p>' : '<p$1>&nbsp;</p>');\r
+\r
+                                       if (s.remove_linebreaks) {\r
+                                               h = h.replace(/\r?\n|\r/g, ' ');\r
+                                               h = h.replace(/(<[^>]+>)\s+/g, '$1 ');\r
+                                               h = h.replace(/\s+(<\/[^>]+>)/g, ' $1');\r
+                                               h = h.replace(/<(p|h[1-6]|blockquote|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object) ([^>]+)>\s+/g, '<$1 $2>'); // Trim block start\r
+                                               h = h.replace(/<(p|h[1-6]|blockquote|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>\s+/g, '<$1>'); // Trim block start\r
+                                               h = h.replace(/\s+<\/(p|h[1-6]|blockquote|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>/g, '</$1>'); // Trim block end\r
+                                       }\r
+\r
+                                       // Simple indentation\r
+                                       if (s.apply_source_formatting && s.indent_mode == 'simple') {\r
+                                               // Add line breaks before and after block elements\r
+                                               h = h.replace(/<(\/?)(ul|hr|table|meta|link|tbody|tr|object|body|head|html|map)(|[^>]+)>\s*/g, '\n<$1$2$3>\n');\r
+                                               h = h.replace(/\s*<(p|h[1-6]|blockquote|div|title|style|pre|script|td|li|area)(|[^>]+)>/g, '\n<$1$2>');\r
+                                               h = h.replace(/<\/(p|h[1-6]|blockquote|div|title|style|pre|script|td|li)>\s*/g, '</$1>\n');\r
+                                               h = h.replace(/\n\n/g, '\n');\r
+                                       }\r
+                               }\r
+\r
+                               h = t._unprotect(h, p);\r
+\r
+                               // Restore the \u00a0 character if raw mode is enabled\r
+                               if (s.entity_encoding == 'raw')\r
+                                       h = h.replace(/<p>&nbsp;<\/p>|<p([^>]+)>&nbsp;<\/p>/g, '<p$1>\u00a0</p>');\r
+                       }\r
+\r
+                       o.content = h;\r
+               },\r
+\r
+               _serializeNode : function(n, inn) {\r
+                       var t = this, s = t.settings, w = t.writer, hc, el, cn, i, l, a, at, no, v, nn, ru, ar, iv;\r
+\r
+                       if (!s.node_filter || s.node_filter(n)) {\r
+                               switch (n.nodeType) {\r
+                                       case 1: // Element\r
+                                               if (n.hasAttribute ? n.hasAttribute('mce_bogus') : n.getAttribute('mce_bogus'))\r
+                                                       return;\r
+\r
+                                               iv = false;\r
+                                               hc = n.hasChildNodes();\r
+                                               nn = n.getAttribute('mce_name') || n.nodeName.toLowerCase();\r
+\r
+                                               // Add correct prefix on IE\r
+                                               if (isIE) {\r
+                                                       if (n.scopeName !== 'HTML' && n.scopeName !== 'html')\r
+                                                               nn = n.scopeName + ':' + nn;\r
+                                               }\r
+\r
+                                               // Remove mce prefix on IE needed for the abbr element\r
+                                               if (nn.indexOf('mce:') === 0)\r
+                                                       nn = nn.substring(4);\r
+\r
+                                               // Check if valid\r
+                                               if (!t.validElementsRE.test(nn) || (t.invalidElementsRE && t.invalidElementsRE.test(nn)) || inn) {\r
+                                                       iv = true;\r
+                                                       break;\r
+                                               }\r
+\r
+                                               if (isIE) {\r
+                                                       // Fix IE content duplication (DOM can have multiple copies of the same node)\r
+                                                       if (s.fix_content_duplication) {\r
+                                                               if (n.mce_serialized == t.key)\r
+                                                                       return;\r
+\r
+                                                               n.mce_serialized = t.key;\r
+                                                       }\r
+\r
+                                                       // IE sometimes adds a / infront of the node name\r
+                                                       if (nn.charAt(0) == '/')\r
+                                                               nn = nn.substring(1);\r
+                                               } else if (isGecko) {\r
+                                                       // Ignore br elements\r
+                                                       if (n.nodeName === 'BR' && n.getAttribute('type') == '_moz')\r
+                                                               return;\r
+                                               }\r
+\r
+                                               // Check if valid child\r
+                                               if (t.childRules) {\r
+                                                       if (t.parentElementsRE.test(t.elementName)) {\r
+                                                               if (!t.childRules[t.elementName].test(nn)) {\r
+                                                                       iv = true;\r
+                                                                       break;\r
+                                                               }\r
+                                                       }\r
+\r
+                                                       t.elementName = nn;\r
+                                               }\r
+\r
+                                               ru = t.findRule(nn);\r
+                                               nn = ru.name || nn;\r
+\r
+                                               // Skip empty nodes or empty node name in IE\r
+                                               if ((!hc && ru.noEmpty) || (isIE && !nn)) {\r
+                                                       iv = true;\r
+                                                       break;\r
+                                               }\r
+\r
+                                               // Check required\r
+                                               if (ru.requiredAttribs) {\r
+                                                       a = ru.requiredAttribs;\r
+\r
+                                                       for (i = a.length - 1; i >= 0; i--) {\r
+                                                               if (this.dom.getAttrib(n, a[i]) !== '')\r
+                                                                       break;\r
+                                                       }\r
+\r
+                                                       // None of the required was there\r
+                                                       if (i == -1) {\r
+                                                               iv = true;\r
+                                                               break;\r
+                                                       }\r
+                                               }\r
+\r
+                                               w.writeStartElement(nn);\r
+\r
+                                               // Add ordered attributes\r
+                                               if (ru.attribs) {\r
+                                                       for (i=0, at = ru.attribs, l = at.length; i<l; i++) {\r
+                                                               a = at[i];\r
+                                                               v = t._getAttrib(n, a);\r
+\r
+                                                               if (v !== null)\r
+                                                                       w.writeAttribute(a.name, v);\r
+                                                       }\r
+                                               }\r
+\r
+                                               // Add wild attributes\r
+                                               if (ru.validAttribsRE) {\r
+                                                       at = isIE ? getIEAtts(n) : n.attributes;\r
+                                                       for (i=at.length-1; i>-1; i--) {\r
+                                                               no = at[i];\r
+\r
+                                                               if (no.specified) {\r
+                                                                       a = no.nodeName.toLowerCase();\r
+\r
+                                                                       if (s.invalid_attrs.test(a) || !ru.validAttribsRE.test(a))\r
+                                                                               continue;\r
+\r
+                                                                       ar = t.findAttribRule(ru, a);\r
+                                                                       v = t._getAttrib(n, ar, a);\r
+\r
+                                                                       if (v !== null)\r
+                                                                               w.writeAttribute(a, v);\r
+                                                               }\r
+                                                       }\r
+                                               }\r
+\r
+                                               // Padd empty nodes with a &nbsp;\r
+                                               if (!hc && ru.padd)\r
+                                                       w.writeText('\u00a0');\r
+\r
+                                               break;\r
+\r
+                                       case 3: // Text\r
+                                               // Check if valid child\r
+                                               if (t.childRules && t.parentElementsRE.test(t.elementName)) {\r
+                                                       if (!t.childRules[t.elementName].test(n.nodeName))\r
+                                                               return;\r
+                                               }\r
+\r
+                                               return w.writeText(n.nodeValue);\r
+\r
+                                       case 4: // CDATA\r
+                                               return w.writeCDATA(n.nodeValue);\r
+\r
+                                       case 8: // Comment\r
+                                               return w.writeComment(n.nodeValue);\r
+                               }\r
+                       } else if (n.nodeType == 1)\r
+                               hc = n.hasChildNodes();\r
+\r
+                       if (hc) {\r
+                               cn = n.firstChild;\r
+\r
+                               while (cn) {\r
+                                       t._serializeNode(cn);\r
+                                       t.elementName = nn;\r
+                                       cn = cn.nextSibling;\r
+                               }\r
+                       }\r
+\r
+                       // Write element end\r
+                       if (!iv) {\r
+                               if (hc || !s.closed.test(nn))\r
+                                       w.writeFullEndElement();\r
+                               else\r
+                                       w.writeEndElement();\r
+                       }\r
+               },\r
+\r
+               _protect : function(o) {\r
+                       var t = this;\r
+\r
+                       o.items = o.items || [];\r
+\r
+                       function enc(s) {\r
+                               return s.replace(/[\r\n\\]/g, function(c) {\r
+                                       if (c === '\n')\r
+                                               return '\\n';\r
+                                       else if (c === '\\')\r
+                                               return '\\\\';\r
+\r
+                                       return '\\r';\r
+                               });\r
+                       };\r
+\r
+                       function dec(s) {\r
+                               return s.replace(/\\[\\rn]/g, function(c) {\r
+                                       if (c === '\\n')\r
+                                               return '\n';\r
+                                       else if (c === '\\\\')\r
+                                               return '\\';\r
+\r
+                                       return '\r';\r
+                               });\r
+                       };\r
+\r
+                       each(o.patterns, function(p) {\r
+                               o.content = dec(enc(o.content).replace(p.pattern, function(x, a, b, c) {\r
+                                       b = dec(b);\r
+\r
+                                       if (p.encode)\r
+                                               b = t._encode(b);\r
+\r
+                                       o.items.push(b);\r
+                                       return a + '<!--mce:' + (o.items.length - 1) + '-->' + c;\r
+                               }));\r
+                       });\r
+\r
+                       return o;\r
+               },\r
+\r
+               _unprotect : function(h, o) {\r
+                       h = h.replace(/\<!--mce:([0-9]+)--\>/g, function(a, b) {\r
+                               return o.items[parseInt(b)];\r
+                       });\r
+\r
+                       o.items = [];\r
+\r
+                       return h;\r
+               },\r
+\r
+               _encode : function(h) {\r
+                       var t = this, s = t.settings, l;\r
+\r
+                       // Entity encode\r
+                       if (s.entity_encoding !== 'raw') {\r
+                               if (s.entity_encoding.indexOf('named') != -1) {\r
+                                       t.setEntities(s.entities);\r
+                                       l = t.entityLookup;\r
+\r
+                                       h = h.replace(t.entitiesRE, function(a) {\r
+                                               var v;\r
+\r
+                                               if (v = l[a])\r
+                                                       a = '&' + v + ';';\r
+\r
+                                               return a;\r
+                                       });\r
+                               }\r
+\r
+                               if (s.entity_encoding.indexOf('numeric') != -1) {\r
+                                       h = h.replace(/[\u007E-\uFFFF]/g, function(a) {\r
+                                               return '&#' + a.charCodeAt(0) + ';';\r
+                                       });\r
+                               }\r
+                       }\r
+\r
+                       return h;\r
+               },\r
+\r
+               _setup : function() {\r
+                       var t = this, s = this.settings;\r
+\r
+                       if (t.done)\r
+                               return;\r
+\r
+                       t.done = 1;\r
+\r
+                       t.setRules(s.valid_elements);\r
+                       t.addRules(s.extended_valid_elements);\r
+                       t.addValidChildRules(s.valid_child_elements);\r
+\r
+                       if (s.invalid_elements)\r
+                               t.invalidElementsRE = new RegExp('^(' + wildcardToRE(s.invalid_elements.replace(',', '|').toLowerCase()) + ')$');\r
+\r
+                       if (s.attrib_value_filter)\r
+                               t.attribValueFilter = s.attribValueFilter;\r
+               },\r
+\r
+               _getAttrib : function(n, a, na) {\r
+                       var i, v;\r
+\r
+                       na = na || a.name;\r
+\r
+                       if (a.forcedVal && (v = a.forcedVal)) {\r
+                               if (v === '{$uid}')\r
+                                       return this.dom.uniqueId();\r
+\r
+                               return v;\r
+                       }\r
+\r
+                       v = this.dom.getAttrib(n, na);\r
+\r
+                       switch (na) {\r
+                               case 'rowspan':\r
+                               case 'colspan':\r
+                                       // Whats the point? Remove usless attribute value\r
+                                       if (v == '1')\r
+                                               v = '';\r
+\r
+                                       break;\r
+                       }\r
+\r
+                       if (this.attribValueFilter)\r
+                               v = this.attribValueFilter(na, v, n);\r
+\r
+                       if (a.validVals) {\r
+                               for (i = a.validVals.length - 1; i >= 0; i--) {\r
+                                       if (v == a.validVals[i])\r
+                                               break;\r
+                               }\r
+\r
+                               if (i == -1)\r
+                                       return null;\r
+                       }\r
+\r
+                       if (v === '' && typeof(a.defaultVal) != 'undefined') {\r
+                               v = a.defaultVal;\r
+\r
+                               if (v === '{$uid}')\r
+                                       return this.dom.uniqueId();\r
+\r
+                               return v;\r
+                       } else {\r
+                               // Remove internal mceItemXX classes when content is extracted from editor\r
+                               if (na == 'class' && this.processObj.get)\r
+                                       v = v.replace(/\s?mceItem\w+\s?/g, '');\r
+                       }\r
+\r
+                       if (v === '')\r
+                               return null;\r
+\r
+\r
+                       return v;\r
+               }\r
+\r
+               });\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/dom/ScriptLoader.js */\r
+\r
+(function() {\r
+       var each = tinymce.each;\r
+\r
+       tinymce.create('tinymce.dom.ScriptLoader', {\r
+               ScriptLoader : function(s) {\r
+                       this.settings = s || {};\r
+                       this.queue = [];\r
+                       this.lookup = {};\r
+               },\r
+\r
+               isDone : function(u) {\r
+                       return this.lookup[u] ? this.lookup[u].state == 2 : 0;\r
+               },\r
+\r
+               markDone : function(u) {\r
+                       this.lookup[u] = {state : 2, url : u};\r
+               },\r
+\r
+               add : function(u, cb, s, pr) {\r
+                       var t = this, lo = t.lookup, o;\r
+\r
+                       if (o = lo[u]) {\r
+                               // Is loaded fire callback\r
+                               if (cb && o.state == 2)\r
+                                       cb.call(s || this);\r
+\r
+                               return o;\r
+                       }\r
+\r
+                       o = {state : 0, url : u, func : cb, scope : s || this};\r
+\r
+                       if (pr)\r
+                               t.queue.unshift(o);\r
+                       else\r
+                               t.queue.push(o);\r
+\r
+                       lo[u] = o;\r
+\r
+                       return o;\r
+               },\r
+\r
+               load : function(u, cb, s) {\r
+                       var t = this, o;\r
+\r
+                       if (o = t.lookup[u]) {\r
+                               // Is loaded fire callback\r
+                               if (cb && o.state == 2)\r
+                                       cb.call(s || t);\r
+\r
+                               return o;\r
+                       }\r
+\r
+                       function loadScript(u) {\r
+                               if (tinymce.dom.Event.domLoaded || t.settings.strict_mode) {\r
+                                       tinymce.util.XHR.send({\r
+                                               url : tinymce._addVer(u),\r
+                                               error : t.settings.error,\r
+                                               async : false,\r
+                                               success : function(co) {\r
+                                                       t.eval(co);\r
+                                               }\r
+                                       });\r
+                               } else\r
+                                       document.write('<script type="text/javascript" src="' + tinymce._addVer(u) + '"></script>');\r
+                       };\r
+\r
+                       if (!tinymce.is(u, 'string')) {\r
+                               each(u, function(u) {\r
+                                       loadScript(u);\r
+                               });\r
+\r
+                               if (cb)\r
+                                       cb.call(s || t);\r
+                       } else {\r
+                               loadScript(u);\r
+\r
+                               if (cb)\r
+                                       cb.call(s || t);\r
+                       }\r
+               },\r
+\r
+               loadQueue : function(cb, s) {\r
+                       var t = this;\r
+\r
+                       if (!t.queueLoading) {\r
+                               t.queueLoading = 1;\r
+                               t.queueCallbacks = [];\r
+\r
+                               t.loadScripts(t.queue, function() {\r
+                                       t.queueLoading = 0;\r
+\r
+                                       if (cb)\r
+                                               cb.call(s || t);\r
+\r
+                                       each(t.queueCallbacks, function(o) {\r
+                                               o.func.call(o.scope);\r
+                                       });\r
+                               });\r
+                       } else if (cb)\r
+                               t.queueCallbacks.push({func : cb, scope : s || t});\r
+               },\r
+\r
+               eval : function(co) {\r
+                       var w = window;\r
+\r
+                       // Evaluate script\r
+                       if (!w.execScript) {\r
+                               try {\r
+                                       eval.call(w, co);\r
+                               } catch (ex) {\r
+                                       eval(co, w); // Firefox 3.0a8\r
+                               }\r
+                       } else\r
+                               w.execScript(co); // IE\r
+               },\r
+\r
+               loadScripts : function(sc, cb, s) {\r
+                       var t = this, lo = t.lookup;\r
+\r
+                       function done(o) {\r
+                               o.state = 2; // Has been loaded\r
+\r
+                               // Run callback\r
+                               if (o.func)\r
+                                       o.func.call(o.scope || t);\r
+                       };\r
+\r
+                       function allDone() {\r
+                               var l;\r
+\r
+                               // Check if all files are loaded\r
+                               l = sc.length;\r
+                               each(sc, function(o) {\r
+                                       o = lo[o.url];\r
+\r
+                                       if (o.state === 2) {// It has finished loading\r
+                                               done(o);\r
+                                               l--;\r
+                                       } else\r
+                                               load(o);\r
+                               });\r
+\r
+                               // They are all loaded\r
+                               if (l === 0 && cb) {\r
+                                       cb.call(s || t);\r
+                                       cb = 0;\r
+                               }\r
+                       };\r
+\r
+                       function load(o) {\r
+                               if (o.state > 0)\r
+                                       return;\r
+\r
+                               o.state = 1; // Is loading\r
+\r
+                               tinymce.util.XHR.send({\r
+                                       url : o.url,\r
+                                       error : t.settings.error,\r
+                                       success : function(co) {\r
+                                               t.eval(co);\r
+                                               done(o);\r
+                                               allDone();\r
+                                       }\r
+                               });\r
+                       };\r
+\r
+                       each(sc, function(o) {\r
+                               var u = o.url;\r
+\r
+                               // Add to queue if needed\r
+                               if (!lo[u]) {\r
+                                       lo[u] = o;\r
+                                       t.queue.push(o);\r
+                               } else\r
+                                       o = lo[u];\r
+\r
+                               // Is already loading or has been loaded\r
+                               if (o.state > 0)\r
+                                       return;\r
+\r
+                               if (!tinymce.dom.Event.domLoaded && !t.settings.strict_mode) {\r
+                                       var ix, ol = '';\r
+\r
+                                       // Add onload events\r
+                                       if (cb || o.func) {\r
+                                               o.state = 1; // Is loading\r
+\r
+                                               ix = tinymce.dom.ScriptLoader._addOnLoad(function() {\r
+                                                       done(o);\r
+                                                       allDone();\r
+                                               });\r
+\r
+                                               if (tinymce.isIE)\r
+                                                       ol = ' onreadystatechange="';\r
+                                               else\r
+                                                       ol = ' onload="';\r
+\r
+                                               ol += 'tinymce.dom.ScriptLoader._onLoad(this,\'' + u + '\',' + ix + ');"';\r
+                                       }\r
+\r
+                                       document.write('<script type="text/javascript" src="' + tinymce._addVer(u) + '"' + ol + '></script>');\r
+\r
+                                       if (!o.func)\r
+                                               done(o);\r
+                               } else\r
+                                       load(o);\r
+                       });\r
+\r
+                       allDone();\r
+               },\r
+\r
+               // Static methods\r
+               'static' : {\r
+                       _addOnLoad : function(f) {\r
+                               var t = this;\r
+\r
+                               t._funcs = t._funcs || [];\r
+                               t._funcs.push(f);\r
+\r
+                               return t._funcs.length - 1;\r
+                       },\r
+\r
+                       _onLoad : function(e, u, ix) {\r
+                               if (!tinymce.isIE || e.readyState == 'complete')\r
+                                       this._funcs[ix].call(this);\r
+                       }\r
+               }\r
+\r
+               });\r
+\r
+       // Global script loader\r
+       tinymce.ScriptLoader = new tinymce.dom.ScriptLoader();\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/ui/Control.js */\r
+\r
+(function() {\r
+       // Shorten class names\r
+       var DOM = tinymce.DOM, is = tinymce.is;\r
+\r
+       tinymce.create('tinymce.ui.Control', {\r
+               Control : function(id, s) {\r
+                       this.id = id;\r
+                       this.settings = s = s || {};\r
+                       this.rendered = false;\r
+                       this.onRender = new tinymce.util.Dispatcher(this);\r
+                       this.classPrefix = '';\r
+                       this.scope = s.scope || this;\r
+                       this.disabled = 0;\r
+                       this.active = 0;\r
+               },\r
+\r
+               setDisabled : function(s) {\r
+                       var e;\r
+\r
+                       if (s != this.disabled) {\r
+                               e = DOM.get(this.id);\r
+\r
+                               // Add accessibility title for unavailable actions\r
+                               if (e && this.settings.unavailable_prefix) {\r
+                                       if (s) {\r
+                                               this.prevTitle = e.title;\r
+                                               e.title = this.settings.unavailable_prefix + ": " + e.title;\r
+                                       } else\r
+                                               e.title = this.prevTitle;\r
+                               }\r
+\r
+                               this.setState('Disabled', s);\r
+                               this.setState('Enabled', !s);\r
+                               this.disabled = s;\r
+                       }\r
+               },\r
+\r
+               isDisabled : function() {\r
+                       return this.disabled;\r
+               },\r
+\r
+               setActive : function(s) {\r
+                       if (s != this.active) {\r
+                               this.setState('Active', s);\r
+                               this.active = s;\r
+                       }\r
+               },\r
+\r
+               isActive : function() {\r
+                       return this.active;\r
+               },\r
+\r
+               setState : function(c, s) {\r
+                       var n = DOM.get(this.id);\r
+\r
+                       c = this.classPrefix + c;\r
+\r
+                       if (s)\r
+                               DOM.addClass(n, c);\r
+                       else\r
+                               DOM.removeClass(n, c);\r
+               },\r
+\r
+               isRendered : function() {\r
+                       return this.rendered;\r
+               },\r
+\r
+               renderHTML : function() {\r
+               },\r
+\r
+               renderTo : function(n) {\r
+                       DOM.setHTML(n, this.renderHTML());\r
+               },\r
+\r
+               postRender : function() {\r
+                       var t = this, b;\r
+\r
+                       // Set pending states\r
+                       if (is(t.disabled)) {\r
+                               b = t.disabled;\r
+                               t.disabled = -1;\r
+                               t.setDisabled(b);\r
+                       }\r
+\r
+                       if (is(t.active)) {\r
+                               b = t.active;\r
+                               t.active = -1;\r
+                               t.setActive(b);\r
+                       }\r
+               },\r
+\r
+               remove : function() {\r
+                       DOM.remove(this.id);\r
+                       this.destroy();\r
+               },\r
+\r
+               destroy : function() {\r
+                       tinymce.dom.Event.clear(this.id);\r
+               }\r
+\r
+               });\r
+})();\r
+/* file:jscripts/tiny_mce/classes/ui/Container.js */\r
+\r
+tinymce.create('tinymce.ui.Container:tinymce.ui.Control', {\r
+       Container : function(id, s) {\r
+               this.parent(id, s);\r
+               this.controls = [];\r
+               this.lookup = {};\r
+       },\r
+\r
+       add : function(c) {\r
+               this.lookup[c.id] = c;\r
+               this.controls.push(c);\r
+\r
+               return c;\r
+       },\r
+\r
+       get : function(n) {\r
+               return this.lookup[n];\r
+       }\r
+\r
+       });\r
+\r
+\r
+/* file:jscripts/tiny_mce/classes/ui/Separator.js */\r
+\r
+tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {\r
+       Separator : function(id, s) {\r
+               this.parent(id, s);\r
+               this.classPrefix = 'mceSeparator';\r
+       },\r
+\r
+       renderHTML : function() {\r
+               return tinymce.DOM.createHTML('span', {'class' : this.classPrefix});\r
+       }\r
+\r
+       });\r
+\r
+/* file:jscripts/tiny_mce/classes/ui/MenuItem.js */\r
+\r
+(function() {\r
+       var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;\r
+\r
+       tinymce.create('tinymce.ui.MenuItem:tinymce.ui.Control', {\r
+               MenuItem : function(id, s) {\r
+                       this.parent(id, s);\r
+                       this.classPrefix = 'mceMenuItem';\r
+               },\r
+\r
+               setSelected : function(s) {\r
+                       this.setState('Selected', s);\r
+                       this.selected = s;\r
+               },\r
+\r
+               isSelected : function() {\r
+                       return this.selected;\r
+               },\r
+\r
+               postRender : function() {\r
+                       var t = this;\r
+                       \r
+                       t.parent();\r
+\r
+                       // Set pending state\r
+                       if (is(t.selected))\r
+                               t.setSelected(t.selected);\r
+               }\r
+\r
+               });\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/ui/Menu.js */\r
+\r
+(function() {\r
+       var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;\r
+\r
+       tinymce.create('tinymce.ui.Menu:tinymce.ui.MenuItem', {\r
+               Menu : function(id, s) {\r
+                       var t = this;\r
+\r
+                       t.parent(id, s);\r
+                       t.items = {};\r
+                       t.collapsed = false;\r
+                       t.menuCount = 0;\r
+                       t.onAddItem = new tinymce.util.Dispatcher(this);\r
+               },\r
+\r
+               expand : function(d) {\r
+                       var t = this;\r
+\r
+                       if (d) {\r
+                               walk(t, function(o) {\r
+                                       if (o.expand)\r
+                                               o.expand();\r
+                               }, 'items', t);\r
+                       }\r
+\r
+                       t.collapsed = false;\r
+               },\r
+\r
+               collapse : function(d) {\r
+                       var t = this;\r
+\r
+                       if (d) {\r
+                               walk(t, function(o) {\r
+                                       if (o.collapse)\r
+                                               o.collapse();\r
+                               }, 'items', t);\r
+                       }\r
+\r
+                       t.collapsed = true;\r
+               },\r
+\r
+               isCollapsed : function() {\r
+                       return this.collapsed;\r
+               },\r
+\r
+               add : function(o) {\r
+                       if (!o.settings)\r
+                               o = new tinymce.ui.MenuItem(o.id || DOM.uniqueId(), o);\r
+\r
+                       this.onAddItem.dispatch(this, o);\r
+\r
+                       return this.items[o.id] = o;\r
+               },\r
+\r
+               addSeparator : function() {\r
+                       return this.add({separator : true});\r
+               },\r
+\r
+               addMenu : function(o) {\r
+                       if (!o.collapse)\r
+                               o = this.createMenu(o);\r
+\r
+                       this.menuCount++;\r
+\r
+                       return this.add(o);\r
+               },\r
+\r
+               hasMenus : function() {\r
+                       return this.menuCount !== 0;\r
+               },\r
+\r
+               remove : function(o) {\r
+                       delete this.items[o.id];\r
+               },\r
+\r
+               removeAll : function() {\r
+                       var t = this;\r
+\r
+                       walk(t, function(o) {\r
+                               if (o.removeAll)\r
+                                       o.removeAll();\r
+                               else\r
+                                       o.remove();\r
+\r
+                               o.destroy();\r
+                       }, 'items', t);\r
+\r
+                       t.items = {};\r
+               },\r
+\r
+               createMenu : function(o) {\r
+                       var m = new tinymce.ui.Menu(o.id || DOM.uniqueId(), o);\r
+\r
+                       m.onAddItem.add(this.onAddItem.dispatch, this.onAddItem);\r
+\r
+                       return m;\r
+               }\r
+\r
+               });\r
+})();\r
+/* file:jscripts/tiny_mce/classes/ui/DropMenu.js */\r
+\r
+(function() {\r
+       var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, Event = tinymce.dom.Event, Element = tinymce.dom.Element;\r
+\r
+       tinymce.create('tinymce.ui.DropMenu:tinymce.ui.Menu', {\r
+               DropMenu : function(id, s) {\r
+                       s = s || {};\r
+                       s.container = s.container || DOM.doc.body;\r
+                       s.offset_x = s.offset_x || 0;\r
+                       s.offset_y = s.offset_y || 0;\r
+                       s.vp_offset_x = s.vp_offset_x || 0;\r
+                       s.vp_offset_y = s.vp_offset_y || 0;\r
+\r
+                       if (is(s.icons) && !s.icons)\r
+                               s['class'] += ' mceNoIcons';\r
+\r
+                       this.parent(id, s);\r
+                       this.onShowMenu = new tinymce.util.Dispatcher(this);\r
+                       this.onHideMenu = new tinymce.util.Dispatcher(this);\r
+                       this.classPrefix = 'mceMenu';\r
+\r
+                       // Fix for odd IE bug: #1903622\r
+                       this.fixIE = tinymce.isIE && DOM.win.top != DOM.win;\r
+               },\r
+\r
+               createMenu : function(s) {\r
+                       var t = this, cs = t.settings, m;\r
+\r
+                       s.container = s.container || cs.container;\r
+                       s.parent = t;\r
+                       s.constrain = s.constrain || cs.constrain;\r
+                       s['class'] = s['class'] || cs['class'];\r
+                       s.vp_offset_x = s.vp_offset_x || cs.vp_offset_x;\r
+                       s.vp_offset_y = s.vp_offset_y || cs.vp_offset_y;\r
+                       m = new tinymce.ui.DropMenu(s.id || DOM.uniqueId(), s);\r
+\r
+                       m.onAddItem.add(t.onAddItem.dispatch, t.onAddItem);\r
+\r
+                       return m;\r
+               },\r
+\r
+               update : function() {\r
+                       var t = this, s = t.settings, tb = DOM.get('menu_' + t.id + '_tbl'), co = DOM.get('menu_' + t.id + '_co'), tw, th;\r
+\r
+                       tw = s.max_width ? Math.min(tb.clientWidth, s.max_width) : tb.clientWidth;\r
+                       th = s.max_height ? Math.min(tb.clientHeight, s.max_height) : tb.clientHeight;\r
+\r
+                       if (!DOM.boxModel)\r
+                               t.element.setStyles({width : tw + 2, height : th + 2});\r
+                       else\r
+                               t.element.setStyles({width : tw, height : th});\r
+\r
+                       if (s.max_width)\r
+                               DOM.setStyle(co, 'width', tw);\r
+\r
+                       if (s.max_height) {\r
+                               DOM.setStyle(co, 'height', th);\r
+\r
+                               if (tb.clientHeight < s.max_height)\r
+                                       DOM.setStyle(co, 'overflow', 'hidden');\r
+                       }\r
+               },\r
+\r
+               showMenu : function(x, y, px) {\r
+                       var t = this, s = t.settings, co, vp = DOM.getViewPort(), w, h, mx, my, ot = 2, dm, tb, cp = t.classPrefix;\r
+\r
+                       t.collapse(1);\r
+\r
+                       if (t.isMenuVisible)\r
+                               return;\r
+\r
+                       if (!t.rendered) {\r
+                               co = DOM.add(t.settings.container, t.renderNode());\r
+\r
+                               each(t.items, function(o) {\r
+                                       o.postRender();\r
+                               });\r
+\r
+                               t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});\r
+                       } else\r
+                               co = DOM.get('menu_' + t.id);\r
+\r
+                       // Move layer out of sight unless it's Opera since it scrolls to top of page due to an bug\r
+                       if (!tinymce.isOpera)\r
+                               DOM.setStyles(co, {left : -0xFFFF , top : -0xFFFF});\r
+\r
+                       DOM.show(co);\r
+                       t.update();\r
+\r
+                       x += s.offset_x || 0;\r
+                       y += s.offset_y || 0;\r
+                       vp.w -= 4;\r
+                       vp.h -= 4;\r
+\r
+                       // Move inside viewport if not submenu\r
+                       if (s.constrain) {\r
+                               w = co.clientWidth - ot;\r
+                               h = co.clientHeight - ot;\r
+                               mx = vp.x + vp.w;\r
+                               my = vp.y + vp.h;\r
+\r
+                               if ((x + s.vp_offset_x + w) > mx)\r
+                                       x = px ? px - w : Math.max(0, (mx - s.vp_offset_x) - w);\r
+\r
+                               if ((y + s.vp_offset_y + h) > my)\r
+                                       y = Math.max(0, (my - s.vp_offset_y) - h);\r
+                       }\r
+\r
+                       DOM.setStyles(co, {left : x , top : y});\r
+                       t.element.update();\r
+\r
+                       t.isMenuVisible = 1;\r
+                       t.mouseClickFunc = Event.add(co, t.fixIE ? 'mousedown' : 'click', function(e) {\r
+                               var m;\r
+\r
+                               e = e.target;\r
+\r
+                               if (e && (e = DOM.getParent(e, 'TR')) && !DOM.hasClass(e, cp + 'ItemSub')) {\r
+                                       m = t.items[e.id];\r
+\r
+                                       if (m.isDisabled())\r
+                                               return;\r
+\r
+                                       dm = t;\r
+\r
+                                       // Wait a while to fix IE bug where it looses the selection if the user clicks on a menu\r
+                                       // item when the editor is placed within an frame or iframe\r
+                                       DOM.win.setTimeout(function() {\r
+                                               while (dm) {\r
+                                                       if (dm.hideMenu)\r
+                                                               dm.hideMenu();\r
+\r
+                                                       dm = dm.settings.parent;\r
+                                               }\r
+                                       }, 0);\r
+\r
+                                       if (m.settings.onclick)\r
+                                               m.settings.onclick(e);\r
+\r
+                                       return Event.cancel(e); // Cancel to fix onbeforeunload problem\r
+                               }\r
+                       });\r
+\r
+                       if (t.hasMenus()) {\r
+                               t.mouseOverFunc = Event.add(co, 'mouseover', function(e) {\r
+                                       var m, r, mi;\r
+\r
+                                       e = e.target;\r
+                                       if (e && (e = DOM.getParent(e, 'TR'))) {\r
+                                               m = t.items[e.id];\r
+\r
+                                               if (t.lastMenu)\r
+                                                       t.lastMenu.collapse(1);\r
+\r
+                                               if (m.isDisabled())\r
+                                                       return;\r
+\r
+                                               if (e && DOM.hasClass(e, cp + 'ItemSub')) {\r
+                                                       //p = DOM.getPos(s.container);\r
+                                                       r = DOM.getRect(e);\r
+                                                       m.showMenu((r.x + r.w - ot), r.y - ot, r.x);\r
+                                                       t.lastMenu = m;\r
+                                                       DOM.addClass(DOM.get(m.id).firstChild, cp + 'ItemActive');\r
+                                               }\r
+                                       }\r
+                               });\r
+                       }\r
+\r
+                       t.onShowMenu.dispatch(t);\r
+\r
+                       if (s.keyboard_focus) {\r
+                               Event.add(co, 'keydown', t._keyHandler, t);\r
+                               DOM.select('a', 'menu_' + t.id)[0].focus(); // Select first link\r
+                       }\r
+               },\r
+\r
+               hideMenu : function(c) {\r
+                       var t = this, co = DOM.get('menu_' + t.id), e;\r
+\r
+                       if (!t.isMenuVisible)\r
+                               return;\r
+\r
+                       Event.remove(co, 'mouseover', t.mouseOverFunc);\r
+                       Event.remove(co, t.fixIE ? 'mousedown' : 'click', t.mouseClickFunc);\r
+                       Event.remove(co, 'keydown', t._keyHandler);\r
+                       DOM.hide(co);\r
+                       t.isMenuVisible = 0;\r
+\r
+                       if (!c)\r
+                               t.collapse(1);\r
+\r
+                       if (t.element)\r
+                               t.element.hide();\r
+\r
+                       if (e = DOM.get(t.id))\r
+                               DOM.removeClass(e.firstChild, t.classPrefix + 'ItemActive');\r
+\r
+                       t.onHideMenu.dispatch(t);\r
+               },\r
+\r
+               add : function(o) {\r
+                       var t = this, co;\r
+\r
+                       o = t.parent(o);\r
+\r
+                       if (t.isRendered && (co = DOM.get('menu_' + t.id)))\r
+                               t._add(DOM.select('tbody', co)[0], o);\r
+\r
+                       return o;\r
+               },\r
+\r
+               collapse : function(d) {\r
+                       this.parent(d);\r
+                       this.hideMenu(1);\r
+               },\r
+\r
+               remove : function(o) {\r
+                       DOM.remove(o.id);\r
+                       this.destroy();\r
+\r
+                       return this.parent(o);\r
+               },\r
+\r
+               destroy : function() {\r
+                       var t = this, co = DOM.get('menu_' + t.id);\r
+\r
+                       Event.remove(co, 'mouseover', t.mouseOverFunc);\r
+                       Event.remove(co, 'click', t.mouseClickFunc);\r
+\r
+                       if (t.element)\r
+                               t.element.remove();\r
+\r
+                       DOM.remove(co);\r
+               },\r
+\r
+               renderNode : function() {\r
+                       var t = this, s = t.settings, n, tb, co, w;\r
+\r
+                       w = DOM.create('div', {id : 'menu_' + t.id, 'class' : s['class'], 'style' : 'position:absolute;left:0;top:0;z-index:200000'});\r
+                       co = DOM.add(w, 'div', {id : 'menu_' + t.id + '_co', 'class' : t.classPrefix + (s['class'] ? ' ' + s['class'] : '')});\r
+                       t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});\r
+\r
+                       if (s.menu_line)\r
+                               DOM.add(co, 'span', {'class' : t.classPrefix + 'Line'});\r
+\r
+//                     n = DOM.add(co, 'div', {id : 'menu_' + t.id + '_co', 'class' : 'mceMenuContainer'});\r
+                       n = DOM.add(co, 'table', {id : 'menu_' + t.id + '_tbl', border : 0, cellPadding : 0, cellSpacing : 0});\r
+                       tb = DOM.add(n, 'tbody');\r
+\r
+                       each(t.items, function(o) {\r
+                               t._add(tb, o);\r
+                       });\r
+\r
+                       t.rendered = true;\r
+\r
+                       return w;\r
+               },\r
+\r
+               // Internal functions\r
+\r
+               _keyHandler : function(e) {\r
+                       // Accessibility feature\r
+                       if (e.keyCode == 27)\r
+                               this.hideMenu();\r
+               },\r
+\r
+               _add : function(tb, o) {\r
+                       var n, s = o.settings, a, ro, it, cp = this.classPrefix;\r
+\r
+                       if (s.separator) {\r
+                               ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'ItemSeparator'});\r
+                               DOM.add(ro, 'td', {'class' : cp + 'ItemSeparator'});\r
+\r
+                               if (n = ro.previousSibling)\r
+                                       DOM.addClass(n, 'mceLast');\r
+\r
+                               return;\r
+                       }\r
+\r
+                       n = ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'Item ' + cp + 'ItemEnabled'});\r
+                       n = it = DOM.add(n, 'td');\r
+                       n = a = DOM.add(n, 'a', {href : 'javascript:;', onclick : "return false;", onmousedown : 'return false;'});\r
+\r
+                       DOM.addClass(it, s['class']);\r
+//                     n = DOM.add(n, 'span', {'class' : 'item'});\r
+                       DOM.add(n, 'span', {'class' : 'mceIcon' + (s.icon ? ' mce_' + s.icon : '')});\r
+                       n = DOM.add(n, s.element || 'span', {'class' : 'mceText', title : o.settings.title}, o.settings.title);\r
+\r
+                       if (o.settings.style)\r
+                               DOM.setAttrib(n, 'style', o.settings.style);\r
+\r
+                       if (tb.childNodes.length == 1)\r
+                               DOM.addClass(ro, 'mceFirst');\r
+\r
+                       if ((n = ro.previousSibling) && DOM.hasClass(n, cp + 'ItemSeparator'))\r
+                               DOM.addClass(ro, 'mceFirst');\r
+\r
+                       if (o.collapse)\r
+                               DOM.addClass(ro, cp + 'ItemSub');\r
+\r
+                       if (n = ro.previousSibling)\r
+                               DOM.removeClass(n, 'mceLast');\r
+\r
+                       DOM.addClass(ro, 'mceLast');\r
+               }\r
+\r
+               });\r
+})();\r
+/* file:jscripts/tiny_mce/classes/ui/Button.js */\r
+\r
+(function() {\r
+       var DOM = tinymce.DOM;\r
+\r
+       tinymce.create('tinymce.ui.Button:tinymce.ui.Control', {\r
+               Button : function(id, s) {\r
+                       this.parent(id, s);\r
+                       this.classPrefix = 'mceButton';\r
+               },\r
+\r
+               renderHTML : function() {\r
+                       var cp = this.classPrefix, s = this.settings, h, l;\r
+\r
+                       l = DOM.encode(s.label || '');\r
+                       h = '<a id="' + this.id + '" href="javascript:;" class="' + cp + ' ' + cp + 'Enabled ' + s['class'] + (l ? ' ' + cp + 'Labeled' : '') +'" onmousedown="return false;" onclick="return false;" title="' + DOM.encode(s.title) + '">';\r
+\r
+                       if (s.image)\r
+                               h += '<img class="mceIcon" src="' + s.image + '" />' + l + '</a>';\r
+                       else\r
+                               h += '<span class="mceIcon ' + s['class'] + '"></span>' + (l ? '<span class="' + cp + 'Label">' + l + '</span>' : '') + '</a>';\r
+\r
+                       return h;\r
+               },\r
+\r
+               postRender : function() {\r
+                       var t = this, s = t.settings;\r
+\r
+                       tinymce.dom.Event.add(t.id, 'click', function(e) {\r
+                               if (!t.isDisabled())\r
+                                       return s.onclick.call(s.scope, e);\r
+                       });\r
+               }\r
+\r
+               });\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/ui/ListBox.js */\r
+\r
+(function() {\r
+       var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;\r
+\r
+       tinymce.create('tinymce.ui.ListBox:tinymce.ui.Control', {\r
+               ListBox : function(id, s) {\r
+                       var t = this;\r
+\r
+                       t.parent(id, s);\r
+                       t.items = [];\r
+                       t.onChange = new Dispatcher(t);\r
+                       t.onPostRender = new Dispatcher(t);\r
+                       t.onAdd = new Dispatcher(t);\r
+                       t.onRenderMenu = new tinymce.util.Dispatcher(this);\r
+                       t.classPrefix = 'mceListBox';\r
+               },\r
+\r
+               select : function(v) {\r
+                       var t = this, e, fv;\r
+\r
+                       // Do we need to do something?\r
+                       if (v != t.selectedValue) {\r
+                               e = DOM.get(t.id + '_text');\r
+                               t.selectedValue = v;\r
+\r
+                               // Find item\r
+                               each(t.items, function(o) {\r
+                                       if (o.value == v) {\r
+                                               DOM.setHTML(e, DOM.encode(o.title));\r
+                                               fv = 1;\r
+                                               return false;\r
+                                       }\r
+                               });\r
+\r
+                               // If no item was found then present title\r
+                               if (!fv) {\r
+                                       DOM.setHTML(e, DOM.encode(t.settings.title));\r
+                                       DOM.addClass(e, 'mceTitle');\r
+                                       e = 0;\r
+                                       return;\r
+                               } else\r
+                                       DOM.removeClass(e, 'mceTitle');\r
+                       }\r
+\r
+                       e = 0;\r
+               },\r
+\r
+               add : function(n, v, o) {\r
+                       var t = this;\r
+\r
+                       o = o || {};\r
+                       o = tinymce.extend(o, {\r
+                               title : n,\r
+                               value : v\r
+                       });\r
+\r
+                       t.items.push(o);\r
+                       t.onAdd.dispatch(t, o);\r
+               },\r
+\r
+               getLength : function() {\r
+                       return this.items.length;\r
+               },\r
+\r
+               renderHTML : function() {\r
+                       var h = '', t = this, s = t.settings, cp = t.classPrefix;\r
+\r
+                       h = '<table id="' + t.id + '" cellpadding="0" cellspacing="0" class="' + cp + ' ' + cp + 'Enabled' + (s['class'] ? (' ' + s['class']) : '') + '"><tbody><tr>';\r
+                       h += '<td>' + DOM.createHTML('a', {id : t.id + '_text', href : 'javascript:;', 'class' : 'mceText', onclick : "return false;", onmousedown : 'return false;'}, DOM.encode(t.settings.title)) + '</td>';\r
+                       h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', tabindex : -1, href : 'javascript:;', 'class' : 'mceOpen', onclick : "return false;", onmousedown : 'return false;'}, '<span></span>') + '</td>';\r
+                       h += '</tr></tbody></table>';\r
+\r
+                       return h;\r
+               },\r
+\r
+               showMenu : function() {\r
+                       var t = this, p1, p2, e = DOM.get(this.id), m;\r
+\r
+                       if (t.isDisabled() || t.items.length == 0)\r
+                               return;\r
+\r
+                       if (t.menu && t.menu.isMenuVisible)\r
+                               return t.hideMenu();\r
+\r
+                       if (!t.isMenuRendered) {\r
+                               t.renderMenu();\r
+                               t.isMenuRendered = true;\r
+                       }\r
+\r
+                       p1 = DOM.getPos(this.settings.menu_container);\r
+                       p2 = DOM.getPos(e);\r
+\r
+                       m = t.menu;\r
+                       m.settings.offset_x = p2.x;\r
+                       m.settings.offset_y = p2.y;\r
+                       m.settings.keyboard_focus = t._focused;\r
+\r
+                       // Select in menu\r
+                       if (t.oldID)\r
+                               m.items[t.oldID].setSelected(0);\r
+\r
+                       each(t.items, function(o) {\r
+                               if (o.value === t.selectedValue) {\r
+                                       m.items[o.id].setSelected(1);\r
+                                       t.oldID = o.id;\r
+                               }\r
+                       });\r
+\r
+                       m.showMenu(0, e.clientHeight);\r
+\r
+                       Event.add(DOM.doc, 'mousedown', t.hideMenu, t);\r
+                       DOM.addClass(t.id, t.classPrefix + 'Selected');\r
+               },\r
+\r
+               hideMenu : function(e) {\r
+                       var t = this;\r
+\r
+                       // Prevent double toogles by canceling the mouse click event to the button\r
+                       if (e && e.type == "mousedown" && (e.target.id == t.id + '_text' || e.target.id == t.id + '_open'))\r
+                               return;\r
+\r
+                       if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceMenu');})) {\r
+                               DOM.removeClass(t.id, t.classPrefix + 'Selected');\r
+                               Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);\r
+\r
+                               if (t.menu)\r
+                                       t.menu.hideMenu();\r
+                       }\r
+               },\r
+\r
+               renderMenu : function() {\r
+                       var t = this, m;\r
+\r
+                       m = t.settings.control_manager.createDropMenu(t.id + '_menu', {\r
+                               menu_line : 1,\r
+                               'class' : t.classPrefix + 'Menu mceNoIcons',\r
+                               max_width : 150,\r
+                               max_height : 150\r
+                       });\r
+\r
+                       m.onHideMenu.add(t.hideMenu, t);\r
+\r
+                       m.add({\r
+                               title : t.settings.title,\r
+                               'class' : 'mceMenuItemTitle'\r
+                       }).setDisabled(1);\r
+\r
+                       each(t.items, function(o) {\r
+                               o.id = DOM.uniqueId();\r
+                               o.onclick = function() {\r
+                                       if (t.settings.onselect(o.value) !== false)\r
+                                               t.select(o.value); // Must be runned after\r
+                               };\r
+\r
+                               m.add(o);\r
+                       });\r
+\r
+                       t.onRenderMenu.dispatch(t, m);\r
+                       t.menu = m;\r
+               },\r
+\r
+               postRender : function() {\r
+                       var t = this, cp = t.classPrefix;\r
+\r
+                       Event.add(t.id, 'click', t.showMenu, t);\r
+                       Event.add(t.id + '_text', 'focus', function() {t._focused = 1;});\r
+                       Event.add(t.id + '_text', 'blur', function() {t._focused = 0;});\r
+\r
+                       // Old IE doesn't have hover on all elements\r
+                       if (tinymce.isIE6 || !DOM.boxModel) {\r
+                               Event.add(t.id, 'mouseover', function() {\r
+                                       if (!DOM.hasClass(t.id, cp + 'Disabled'))\r
+                                               DOM.addClass(t.id, cp + 'Hover');\r
+                               });\r
+\r
+                               Event.add(t.id, 'mouseout', function() {\r
+                                       if (!DOM.hasClass(t.id, cp + 'Disabled'))\r
+                                               DOM.removeClass(t.id, cp + 'Hover');\r
+                               });\r
+                       }\r
+\r
+                       t.onPostRender.dispatch(t, DOM.get(t.id));\r
+               },\r
+\r
+               destroy : function() {\r
+                       this.parent();\r
+\r
+                       Event.clear(this.id + '_text');\r
+               }\r
+\r
+               });\r
+})();\r
+/* file:jscripts/tiny_mce/classes/ui/NativeListBox.js */\r
+\r
+(function() {\r
+       var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;\r
+\r
+       tinymce.create('tinymce.ui.NativeListBox:tinymce.ui.ListBox', {\r
+               NativeListBox : function(id, s) {\r
+                       this.parent(id, s);\r
+                       this.classPrefix = 'mceNativeListBox';\r
+               },\r
+\r
+               setDisabled : function(s) {\r
+                       DOM.get(this.id).disabled = s;\r
+               },\r
+\r
+               isDisabled : function() {\r
+                       return DOM.get(this.id).disabled;\r
+               },\r
+\r
+               select : function(v) {\r
+                       var e = DOM.get(this.id), ol = e.options;\r
+\r
+                       v = '' + (v || '');\r
+\r
+                       e.selectedIndex = 0;\r
+                       each(ol, function(o, i) {\r
+                               if (o.value == v) {\r
+                                       e.selectedIndex = i;\r
+                                       return false;\r
+                               }\r
+                       });\r
+               },\r
+\r
+               add : function(n, v, a) {\r
+                       var o, t = this;\r
+\r
+                       a = a || {};\r
+                       a.value = v;\r
+\r
+                       if (t.isRendered())\r
+                               DOM.add(DOM.get(this.id), 'option', a, n);\r
+\r
+                       o = {\r
+                               title : n,\r
+                               value : v,\r
+                               attribs : a\r
+                       };\r
+\r
+                       t.items.push(o);\r
+                       t.onAdd.dispatch(t, o);\r
+               },\r
+\r
+               getLength : function() {\r
+                       return DOM.get(this.id).options.length - 1;\r
+               },\r
+\r
+               renderHTML : function() {\r
+                       var h, t = this;\r
+\r
+                       h = DOM.createHTML('option', {value : ''}, '-- ' + t.settings.title + ' --');\r
+\r
+                       each(t.items, function(it) {\r
+                               h += DOM.createHTML('option', {value : it.value}, it.title);\r
+                       });\r
+\r
+                       h = DOM.createHTML('select', {id : t.id, 'class' : 'mceNativeListBox'}, h);\r
+\r
+                       return h;\r
+               },\r
+\r
+               postRender : function() {\r
+                       var t = this, ch;\r
+\r
+                       t.rendered = true;\r
+\r
+                       function onChange(e) {\r
+                               var v = e.target.options[e.target.selectedIndex].value;\r
+\r
+                               t.onChange.dispatch(t, v);\r
+\r
+                               if (t.settings.onselect)\r
+                                       t.settings.onselect(v);\r
+                       };\r
+\r
+                       Event.add(t.id, 'change', onChange);\r
+\r
+                       // Accessibility keyhandler\r
+                       Event.add(t.id, 'keydown', function(e) {\r
+                               var bf;\r
+\r
+                               Event.remove(t.id, 'change', ch);\r
+\r
+                               bf = Event.add(t.id, 'blur', function() {\r
+                                       Event.add(t.id, 'change', onChange);\r
+                                       Event.remove(t.id, 'blur', bf);\r
+                               });\r
+\r
+                               if (e.keyCode == 13 || e.keyCode == 32) {\r
+                                       onChange(e);\r
+                                       return Event.cancel(e);\r
+                               }\r
+                       });\r
+\r
+                       t.onPostRender.dispatch(t, DOM.get(t.id));\r
+               }\r
+\r
+               });\r
+})();\r
+/* file:jscripts/tiny_mce/classes/ui/MenuButton.js */\r
+\r
+(function() {\r
+       var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;\r
+\r
+       tinymce.create('tinymce.ui.MenuButton:tinymce.ui.Button', {\r
+               MenuButton : function(id, s) {\r
+                       this.parent(id, s);\r
+                       this.onRenderMenu = new tinymce.util.Dispatcher(this);\r
+                       s.menu_container = s.menu_container || DOM.doc.body;\r
+               },\r
+\r
+               showMenu : function() {\r
+                       var t = this, p1, p2, e = DOM.get(t.id), m;\r
+\r
+                       if (t.isDisabled())\r
+                               return;\r
+\r
+                       if (!t.isMenuRendered) {\r
+                               t.renderMenu();\r
+                               t.isMenuRendered = true;\r
+                       }\r
+\r
+                       if (t.isMenuVisible)\r
+                               return t.hideMenu();\r
+\r
+                       p1 = DOM.getPos(t.settings.menu_container);\r
+                       p2 = DOM.getPos(e);\r
+\r
+                       m = t.menu;\r
+                       m.settings.offset_x = p2.x;\r
+                       m.settings.offset_y = p2.y;\r
+                       m.settings.vp_offset_x = p2.x;\r
+                       m.settings.vp_offset_y = p2.y;\r
+                       m.settings.keyboard_focus = t._focused;\r
+                       m.showMenu(0, e.clientHeight);\r
+\r
+                       Event.add(DOM.doc, 'mousedown', t.hideMenu, t);\r
+                       t.setState('Selected', 1);\r
+\r
+                       t.isMenuVisible = 1;\r
+               },\r
+\r
+               renderMenu : function() {\r
+                       var t = this, m;\r
+\r
+                       m = t.settings.control_manager.createDropMenu(t.id + '_menu', {\r
+                               menu_line : 1,\r
+                               'class' : this.classPrefix + 'Menu',\r
+                               icons : t.settings.icons\r
+                       });\r
+\r
+                       m.onHideMenu.add(t.hideMenu, t);\r
+\r
+                       t.onRenderMenu.dispatch(t, m);\r
+                       t.menu = m;\r
+               },\r
+\r
+               hideMenu : function(e) {\r
+                       var t = this;\r
+\r
+                       // Prevent double toogles by canceling the mouse click event to the button\r
+                       if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id || e.id === t.id + '_open';}))\r
+                               return;\r
+\r
+                       if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceMenu');})) {\r
+                               t.setState('Selected', 0);\r
+                               Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);\r
+                               if (t.menu)\r
+                                       t.menu.hideMenu();\r
+                       }\r
+\r
+                       t.isMenuVisible = 0;\r
+               },\r
+\r
+               postRender : function() {\r
+                       var t = this, s = t.settings;\r
+\r
+                       Event.add(t.id, 'click', function() {\r
+                               if (!t.isDisabled()) {\r
+                                       if (s.onclick)\r
+                                               s.onclick(t.value);\r
+\r
+                                       t.showMenu();\r
+                               }\r
+                       });\r
+               }\r
+\r
+               });\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/ui/SplitButton.js */\r
+\r
+(function() {\r
+       var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;\r
+\r
+       tinymce.create('tinymce.ui.SplitButton:tinymce.ui.MenuButton', {\r
+               SplitButton : function(id, s) {\r
+                       this.parent(id, s);\r
+                       this.classPrefix = 'mceSplitButton';\r
+               },\r
+\r
+               renderHTML : function() {\r
+                       var h, t = this, s = t.settings, h1;\r
+\r
+                       h = '<tbody><tr>';\r
+\r
+                       if (s.image)\r
+                               h1 = DOM.createHTML('img ', {src : s.image, 'class' : 'mceAction ' + s['class']});\r
+                       else\r
+                               h1 = DOM.createHTML('span', {'class' : 'mceAction ' + s['class']}, '');\r
+\r
+                       h += '<td>' + DOM.createHTML('a', {id : t.id + '_action', href : 'javascript:;', 'class' : 'mceAction ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>';\r
+       \r
+                       h1 = DOM.createHTML('span', {'class' : 'mceOpen ' + s['class']});\r
+                       h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', href : 'javascript:;', 'class' : 'mceOpen ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>';\r
+\r
+                       h += '</tr></tbody>';\r
+\r
+                       return DOM.createHTML('table', {id : t.id, 'class' : 'mceSplitButton mceSplitButtonEnabled ' + s['class'], cellpadding : '0', cellspacing : '0', onmousedown : 'return false;', title : s.title}, h);\r
+               },\r
+\r
+               postRender : function() {\r
+                       var t = this, s = t.settings;\r
+\r
+                       if (s.onclick) {\r
+                               Event.add(t.id + '_action', 'click', function() {\r
+                                       if (!t.isDisabled())\r
+                                               s.onclick(t.value);\r
+                               });\r
+                       }\r
+\r
+                       Event.add(t.id + '_open', 'click', t.showMenu, t);\r
+                       Event.add(t.id + '_open', 'focus', function() {t._focused = 1;});\r
+                       Event.add(t.id + '_open', 'blur', function() {t._focused = 0;});\r
+\r
+                       // Old IE doesn't have hover on all elements\r
+                       if (tinymce.isIE6 || !DOM.boxModel) {\r
+                               Event.add(t.id, 'mouseover', function() {\r
+                                       if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))\r
+                                               DOM.addClass(t.id, 'mceSplitButtonHover');\r
+                               });\r
+\r
+                               Event.add(t.id, 'mouseout', function() {\r
+                                       if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))\r
+                                               DOM.removeClass(t.id, 'mceSplitButtonHover');\r
+                               });\r
+                       }\r
+               },\r
+\r
+               destroy : function() {\r
+                       this.parent();\r
+\r
+                       Event.clear(this.id + '_action');\r
+                       Event.clear(this.id + '_open');\r
+               }\r
+\r
+               });\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/ui/ColorSplitButton.js */\r
+\r
+(function() {\r
+       var DOM = tinymce.DOM, Event = tinymce.dom.Event, is = tinymce.is, each = tinymce.each;\r
+\r
+       tinymce.create('tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton', {\r
+               ColorSplitButton : function(id, s) {\r
+                       var t = this;\r
+\r
+                       t.parent(id, s);\r
+\r
+                       t.settings = s = tinymce.extend({\r
+                               colors : '000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF',\r
+                               grid_width : 8,\r
+                               default_color : '#888888'\r
+                       }, t.settings);\r
+\r
+                       t.value = s.default_color;\r
+               },\r
+\r
+               showMenu : function() {\r
+                       var t = this, r, p, e, p2;\r
+\r
+                       if (t.isDisabled())\r
+                               return;\r
+\r
+                       if (!t.isMenuRendered) {\r
+                               t.renderMenu();\r
+                               t.isMenuRendered = true;\r
+                       }\r
+\r
+                       if (t.isMenuVisible)\r
+                               return t.hideMenu();\r
+\r
+                       e = DOM.get(t.id);\r
+                       DOM.show(t.id + '_menu');\r
+                       DOM.addClass(e, 'mceSplitButtonSelected');\r
+                       p2 = DOM.getPos(e);\r
+                       DOM.setStyles(t.id + '_menu', {\r
+                               left : p2.x,\r
+                               top : p2.y + e.clientHeight,\r
+                               zIndex : 200000\r
+                       });\r
+                       e = 0;\r
+\r
+                       Event.add(DOM.doc, 'mousedown', t.hideMenu, t);\r
+\r
+                       if (t._focused) {\r
+                               t._keyHandler = Event.add(t.id + '_menu', 'keydown', function(e) {\r
+                                       if (e.keyCode == 27)\r
+                                               t.hideMenu();\r
+                               });\r
+\r
+                               DOM.select('a', t.id + '_menu')[0].focus(); // Select first link\r
+                       }\r
+\r
+                       t.isMenuVisible = 1;\r
+               },\r
+\r
+               hideMenu : function(e) {\r
+                       var t = this;\r
+\r
+                       // Prevent double toogles by canceling the mouse click event to the button\r
+                       if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';}))\r
+                               return;\r
+\r
+                       if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceSplitButtonMenu');})) {\r
+                               DOM.removeClass(t.id, 'mceSplitButtonSelected');\r
+                               Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);\r
+                               Event.remove(t.id + '_menu', 'keydown', t._keyHandler);\r
+                               DOM.hide(t.id + '_menu');\r
+                       }\r
+\r
+                       t.isMenuVisible = 0;\r
+               },\r
+\r
+               renderMenu : function() {\r
+                       var t = this, m, i = 0, s = t.settings, n, tb, tr, w;\r
+\r
+                       w = DOM.add(s.menu_container, 'div', {id : t.id + '_menu', 'class' : s['menu_class'] + ' ' + s['class'], style : 'position:absolute;left:0;top:-1000px;'});\r
+                       m = DOM.add(w, 'div', {'class' : s['class'] + ' mceSplitButtonMenu'});\r
+                       DOM.add(m, 'span', {'class' : 'mceMenuLine'});\r
+\r
+                       n = DOM.add(m, 'table', {'class' : 'mceColorSplitMenu'});\r
+                       tb = DOM.add(n, 'tbody');\r
+\r
+                       // Generate color grid\r
+                       i = 0;\r
+                       each(is(s.colors, 'array') ? s.colors : s.colors.split(','), function(c) {\r
+                               c = c.replace(/^#/, '');\r
+\r
+                               if (!i--) {\r
+                                       tr = DOM.add(tb, 'tr');\r
+                                       i = s.grid_width - 1;\r
+                               }\r
+\r
+                               n = DOM.add(tr, 'td');\r
+\r
+                               n = DOM.add(n, 'a', {\r
+                                       href : 'javascript:;',\r
+                                       style : {\r
+                                               backgroundColor : '#' + c\r
+                                       },\r
+                                       mce_color : '#' + c\r
+                               });\r
+                       });\r
+\r
+                       if (s.more_colors_func) {\r
+                               n = DOM.add(tb, 'tr');\r
+                               n = DOM.add(n, 'td', {colspan : s.grid_width, 'class' : 'mceMoreColors'});\r
+                               n = DOM.add(n, 'a', {id : t.id + '_more', href : 'javascript:;', onclick : 'return false;', 'class' : 'mceMoreColors'}, s.more_colors_title);\r
+\r
+                               Event.add(n, 'click', function(e) {\r
+                                       s.more_colors_func.call(s.more_colors_scope || this);\r
+                                       return Event.cancel(e); // Cancel to fix onbeforeunload problem\r
+                               });\r
+                       }\r
+\r
+                       DOM.addClass(m, 'mceColorSplitMenu');\r
+\r
+                       Event.add(t.id + '_menu', 'click', function(e) {\r
+                               var c;\r
+\r
+                               e = e.target;\r
+\r
+                               if (e.nodeName == 'A' && (c = e.getAttribute('mce_color')))\r
+                                       t.setColor(c);\r
+                       });\r
+\r
+                       return w;\r
+               },\r
+\r
+               setColor : function(c) {\r
+                       var t = this;\r
+\r
+                       DOM.setStyle(t.id + '_preview', 'backgroundColor', c);\r
+\r
+                       t.value = c;\r
+                       t.hideMenu();\r
+                       t.settings.onselect(c);\r
+               },\r
+\r
+               postRender : function() {\r
+                       var t = this, id = t.id;\r
+\r
+                       t.parent();\r
+                       DOM.add(id + '_action', 'div', {id : id + '_preview', 'class' : 'mceColorPreview'});\r
+               },\r
+\r
+               destroy : function() {\r
+                       this.parent();\r
+\r
+                       Event.clear(this.id + '_menu');\r
+                       Event.clear(this.id + '_more');\r
+                       DOM.remove(this.id + '_menu');\r
+               }\r
+\r
+               });\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/ui/Toolbar.js */\r
+\r
+tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {\r
+       renderHTML : function() {\r
+               var t = this, h = '', c, co, dom = tinymce.DOM, s = t.settings, i, pr, nx, cl;\r
+\r
+               cl = t.controls;\r
+               for (i=0; i<cl.length; i++) {\r
+                       // Get current control, prev control, next control and if the control is a list box or not\r
+                       co = cl[i];\r
+                       pr = cl[i - 1];\r
+                       nx = cl[i + 1];\r
+\r
+                       // Add toolbar start\r
+                       if (i === 0) {\r
+                               c = 'mceToolbarStart';\r
+\r
+                               if (co.Button)\r
+                                       c += ' mceToolbarStartButton';\r
+                               else if (co.SplitButton)\r
+                                       c += ' mceToolbarStartSplitButton';\r
+                               else if (co.ListBox)\r
+                                       c += ' mceToolbarStartListBox';\r
+\r
+                               h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->'));\r
+                       }\r
+\r
+                       // Add toolbar end before list box and after the previous button\r
+                       // This is to fix the o2k7 editor skins\r
+                       if (pr && co.ListBox) {\r
+                               if (pr.Button || pr.SplitButton)\r
+                                       h += dom.createHTML('td', {'class' : 'mceToolbarEnd'}, dom.createHTML('span', null, '<!-- IE -->'));\r
+                       }\r
+\r
+                       // Render control HTML\r
+\r
+                       // IE 8 quick fix, needed to propertly generate a hit area for anchors\r
+                       if (dom.stdMode)\r
+                               h += '<td style="position: relative">' + co.renderHTML() + '</td>';\r
+                       else\r
+                               h += '<td>' + co.renderHTML() + '</td>';\r
+\r
+                       // Add toolbar start after list box and before the next button\r
+                       // This is to fix the o2k7 editor skins\r
+                       if (nx && co.ListBox) {\r
+                               if (nx.Button || nx.SplitButton)\r
+                                       h += dom.createHTML('td', {'class' : 'mceToolbarStart'}, dom.createHTML('span', null, '<!-- IE -->'));\r
+                       }\r
+               }\r
+\r
+               c = 'mceToolbarEnd';\r
+\r
+               if (co.Button)\r
+                       c += ' mceToolbarEndButton';\r
+               else if (co.SplitButton)\r
+                       c += ' mceToolbarEndSplitButton';\r
+               else if (co.ListBox)\r
+                       c += ' mceToolbarEndListBox';\r
+\r
+               h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->'));\r
+\r
+               return dom.createHTML('table', {id : t.id, 'class' : 'mceToolbar' + (s['class'] ? ' ' + s['class'] : ''), cellpadding : '0', cellspacing : '0', align : t.settings.align || ''}, '<tbody><tr>' + h + '</tr></tbody>');\r
+       }\r
+\r
+       });\r
+\r
+/* file:jscripts/tiny_mce/classes/AddOnManager.js */\r
+\r
+(function() {\r
+       var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each;\r
+\r
+       tinymce.create('tinymce.AddOnManager', {\r
+               items : [],\r
+               urls : {},\r
+               lookup : {},\r
+               onAdd : new Dispatcher(this),\r
+\r
+               get : function(n) {\r
+                       return this.lookup[n];\r
+               },\r
+\r
+               requireLangPack : function(n) {\r
+                       var u, s;\r
+\r
+                       if (tinymce.EditorManager.settings) {\r
+                               u = this.urls[n] + '/langs/' + tinymce.EditorManager.settings.language + '.js';\r
+                               s = tinymce.EditorManager.settings;\r
+\r
+                               if (s) {\r
+                                       if (!tinymce.dom.Event.domLoaded && !s.strict_mode)\r
+                                               tinymce.ScriptLoader.load(u);\r
+                                       else\r
+                                               tinymce.ScriptLoader.add(u);\r
+                               }\r
+                       }\r
+               },\r
+\r
+               add : function(id, o) {\r
+                       this.items.push(o);\r
+                       this.lookup[id] = o;\r
+                       this.onAdd.dispatch(this, id, o);\r
+\r
+                       return o;\r
+               },\r
+\r
+               load : function(n, u, cb, s) {\r
+                       var t = this;\r
+\r
+                       if (t.urls[n])\r
+                               return;\r
+\r
+                       if (u.indexOf('/') != 0 && u.indexOf('://') == -1)\r
+                               u = tinymce.baseURL + '/' +  u;\r
+\r
+                       t.urls[n] = u.substring(0, u.lastIndexOf('/'));\r
+                       tinymce.ScriptLoader.add(u, cb, s);\r
+               }\r
+\r
+               });\r
+\r
+       // Create plugin and theme managers\r
+       tinymce.PluginManager = new tinymce.AddOnManager();\r
+       tinymce.ThemeManager = new tinymce.AddOnManager();\r
+}());\r
+/* file:jscripts/tiny_mce/classes/EditorManager.js */\r
+\r
+(function() {\r
+       // Shorten names\r
+       var each = tinymce.each, extend = tinymce.extend, DOM = tinymce.DOM, Event = tinymce.dom.Event, ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, explode = tinymce.explode;\r
+\r
+       tinymce.create('static tinymce.EditorManager', {\r
+               editors : {},\r
+               i18n : {},\r
+               activeEditor : null,\r
+\r
+               preInit : function() {\r
+                       var t = this, lo = window.location;\r
+\r
+                       // Setup some URLs where the editor API is located and where the document is\r
+                       tinymce.documentBaseURL = lo.href.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');\r
+                       if (!/[\/\\]$/.test(tinymce.documentBaseURL))\r
+                               tinymce.documentBaseURL += '/';\r
+\r
+                       tinymce.baseURL = new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.baseURL);\r
+                       tinymce.EditorManager.baseURI = new tinymce.util.URI(tinymce.baseURL);\r
+\r
+                       // Setup document domain\r
+                       if (tinymce.EditorManager.baseURI.host != lo.hostname && lo.hostname)\r
+                               document.domain = tinymce.relaxedDomain = lo.hostname.replace(/.*\.(.+\..+)$/, '$1');\r
+\r
+                       // Add before unload listener\r
+                       // This was required since IE was leaking memory if you added and removed beforeunload listeners\r
+                       // with attachEvent/detatchEvent so this only adds one listener and instances can the attach to the onBeforeUnload event\r
+                       t.onBeforeUnload = new tinymce.util.Dispatcher(t);\r
+\r
+                       // Must be on window or IE will leak if the editor is placed in frame or iframe\r
+                       Event.add(window, 'beforeunload', function(e) {\r
+                               t.onBeforeUnload.dispatch(t, e);\r
+                       });\r
+               },\r
+\r
+               init : function(s) {\r
+                       var t = this, pl, sl = tinymce.ScriptLoader, c, e;\r
+\r
+                       function execCallback(se, n, s) {\r
+                               var f = se[n];\r
+\r
+                               if (!f)\r
+                                       return;\r
+\r
+                               if (tinymce.is(f, 'string')) {\r
+                                       s = f.replace(/\.\w+$/, '');\r
+                                       s = s ? tinymce.resolve(s) : 0;\r
+                                       f = tinymce.resolve(f);\r
+                               }\r
+\r
+                               return f.apply(s || this, Array.prototype.slice.call(arguments, 2));\r
+                       };\r
+\r
+                       s = extend({\r
+                               theme : "simple",\r
+                               language : "en",\r
+                               strict_loading_mode : document.contentType == 'application/xhtml+xml'\r
+                       }, s);\r
+\r
+                       t.settings = s;\r
+\r
+                       // If page not loaded and strict mode isn't enabled then load them\r
+                       if (!Event.domLoaded && !s.strict_loading_mode) {\r
+                               // Load language\r
+                               if (s.language)\r
+                                       sl.add(tinymce.baseURL + '/langs/' + s.language + '.js');\r
+\r
+                               // Load theme\r
+                               if (s.theme && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme])\r
+                                       ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js');\r
+\r
+                               // Load plugins\r
+                               if (s.plugins) {\r
+                                       pl = explode(s.plugins);\r
+\r
+                                       // Load compat2x first\r
+                                       if (tinymce.inArray(pl, 'compat2x') != -1)\r
+                                               PluginManager.load('compat2x', 'plugins/compat2x/editor_plugin' + tinymce.suffix + '.js');\r
+\r
+                                       // Load rest if plugins\r
+                                       each(pl, function(v) {\r
+                                               if (v && v.charAt(0) != '-' && !PluginManager.urls[v]) {\r
+                                                       // Skip safari plugin for other browsers\r
+                                                       if (!tinymce.isWebKit && v == 'safari')\r
+                                                               return;\r
+\r
+                                                       PluginManager.load(v, 'plugins/' + v + '/editor_plugin' + tinymce.suffix + '.js');\r
+                                               }\r
+                                       });\r
+                               }\r
+\r
+                               sl.loadQueue();\r
+                       }\r
+\r
+                       // Legacy call\r
+                       Event.add(document, 'init', function() {\r
+                               var l, co;\r
+\r
+                               execCallback(s, 'onpageload');\r
+\r
+                               // Verify that it's a valid browser\r
+                               if (s.browsers) {\r
+                                       l = false;\r
+\r
+                                       each(explode(s.browsers), function(v) {\r
+                                               switch (v) {\r
+                                                       case 'ie':\r
+                                                       case 'msie':\r
+                                                               if (tinymce.isIE)\r
+                                                                       l = true;\r
+                                                               break;\r
+\r
+                                                       case 'gecko':\r
+                                                               if (tinymce.isGecko)\r
+                                                                       l = true;\r
+                                                               break;\r
+\r
+                                                       case 'safari':\r
+                                                       case 'webkit':\r
+                                                               if (tinymce.isWebKit)\r
+                                                                       l = true;\r
+                                                               break;\r
+\r
+                                                       case 'opera':\r
+                                                               if (tinymce.isOpera)\r
+                                                                       l = true;\r
+\r
+                                                               break;\r
+                                               }\r
+                                       });\r
+\r
+                                       // Not a valid one\r
+                                       if (!l)\r
+                                               return;\r
+                               }\r
+\r
+                               switch (s.mode) {\r
+                                       case "exact":\r
+                                               l = s.elements || '';\r
+\r
+                                               if(l.length > 0) {\r
+                                                       each(explode(l), function(v) {\r
+                                                               if (DOM.get(v))\r
+                                                                       new tinymce.Editor(v, s).render(1);\r
+                                                               else {\r
+                                                                       c = 0;\r
+\r
+                                                                       each(document.forms, function(f) {\r
+                                                                               each(f.elements, function(e) {\r
+                                                                                       if (e.name === v) {\r
+                                                                                               v = 'mce_editor_' + c;\r
+                                                                                               DOM.setAttrib(e, 'id', v);\r
+                                                                                               new tinymce.Editor(v, s).render(1);\r
+                                                                                       }\r
+                                                                               });\r
+                                                                       });\r
+                                                               }\r
+                                                       });\r
+                                               }\r
+                                               break;\r
+\r
+                                       case "textareas":\r
+                                       case "specific_textareas":\r
+                                               function hasClass(n, c) {\r
+                                                       return new RegExp('\\b' + c + '\\b', 'g').test(n.className);\r
+                                               };\r
+\r
+                                               each(DOM.select('textarea'), function(v) {\r
+                                                       if (s.editor_deselector && hasClass(v, s.editor_deselector))\r
+                                                               return;\r
+\r
+                                                       if (!s.editor_selector || hasClass(v, s.editor_selector)) {\r
+                                                               // Can we use the name\r
+                                                               e = DOM.get(v.name);\r
+                                                               if (!v.id && !e)\r
+                                                                       v.id = v.name;\r
+\r
+                                                               // Generate unique name if missing or already exists\r
+                                                               if (!v.id || t.get(v.id))\r
+                                                                       v.id = DOM.uniqueId();\r
+\r
+                                                               new tinymce.Editor(v.id, s).render(1);\r
+                                                       }\r
+                                               });\r
+                                               break;\r
+                               }\r
+\r
+                               // Call onInit when all editors are initialized\r
+                               if (s.oninit) {\r
+                                       l = co = 0;\r
+\r
+                                       each (t.editors, function(ed) {\r
+                                               co++;\r
+\r
+                                               if (!ed.initialized) {\r
+                                                       // Wait for it\r
+                                                       ed.onInit.add(function() {\r
+                                                               l++;\r
+\r
+                                                               // All done\r
+                                                               if (l == co)\r
+                                                                       execCallback(s, 'oninit');\r
+                                                       });\r
+                                               } else\r
+                                                       l++;\r
+\r
+                                               // All done\r
+                                               if (l == co)\r
+                                                       execCallback(s, 'oninit');                                      \r
+                                       });\r
+                               }\r
+                       });\r
+               },\r
+\r
+               get : function(id) {\r
+                       return this.editors[id];\r
+               },\r
+\r
+               getInstanceById : function(id) {\r
+                       return this.get(id);\r
+               },\r
+\r
+               add : function(e) {\r
+                       this.editors[e.id] = e;\r
+                       this._setActive(e);\r
+\r
+                       return e;\r
+               },\r
+\r
+               remove : function(e) {\r
+                       var t = this;\r
+\r
+                       // Not in the collection\r
+                       if (!t.editors[e.id])\r
+                               return null;\r
+\r
+                       delete t.editors[e.id];\r
+\r
+                       // Select another editor since the active one was removed\r
+                       if (t.activeEditor == e) {\r
+                               each(t.editors, function(e) {\r
+                                       t._setActive(e);\r
+                                       return false; // Break\r
+                               });\r
+                       }\r
+\r
+                       e.destroy();\r
+\r
+                       return e;\r
+               },\r
+\r
+               execCommand : function(c, u, v) {\r
+                       var t = this, ed = t.get(v), w;\r
+\r
+                       // Manager commands\r
+                       switch (c) {\r
+                               case "mceFocus":\r
+                                       ed.focus();\r
+                                       return true;\r
+\r
+                               case "mceAddEditor":\r
+                               case "mceAddControl":\r
+                                       if (!t.get(v))\r
+                                               new tinymce.Editor(v, t.settings).render();\r
+\r
+                                       return true;\r
+\r
+                               case "mceAddFrameControl":\r
+                                       w = v.window;\r
+\r
+                                       // Add tinyMCE global instance and tinymce namespace to specified window\r
+                                       w.tinyMCE = tinyMCE;\r
+                                       w.tinymce = tinymce;\r
+\r
+                                       tinymce.DOM.doc = w.document;\r
+                                       tinymce.DOM.win = w;\r
+\r
+                                       ed = new tinymce.Editor(v.element_id, v);\r
+                                       ed.render();\r
+\r
+                                       // Fix IE memory leaks\r
+                                       if (tinymce.isIE) {\r
+                                               function clr() {\r
+                                                       ed.destroy();\r
+                                                       w.detachEvent('onunload', clr);\r
+                                                       w = w.tinyMCE = w.tinymce = null; // IE leak\r
+                                               };\r
+\r
+                                               w.attachEvent('onunload', clr);\r
+                                       }\r
+\r
+                                       v.page_window = null;\r
+\r
+                                       return true;\r
+\r
+                               case "mceRemoveEditor":\r
+                               case "mceRemoveControl":\r
+                                       ed.remove();\r
+                                       return true;\r
+\r
+                               case 'mceToggleEditor':\r
+                                       if (!ed) {\r
+                                               t.execCommand('mceAddControl', 0, v);\r
+                                               return true;\r
+                                       }\r
+\r
+                                       if (ed.isHidden())\r
+                                               ed.show();\r
+                                       else\r
+                                               ed.hide();\r
+\r
+                                       return true;\r
+                       }\r
+\r
+                       // Run command on active editor\r
+                       if (t.activeEditor)\r
+                               return t.activeEditor.execCommand(c, u, v);\r
+\r
+                       return false;\r
+               },\r
+\r
+               execInstanceCommand : function(id, c, u, v) {\r
+                       var ed = this.get(id);\r
+\r
+                       if (ed)\r
+                               return ed.execCommand(c, u, v);\r
+\r
+                       return false;\r
+               },\r
+\r
+               triggerSave : function() {\r
+                       each(this.editors, function(e) {\r
+                               e.save();\r
+                       });\r
+               },\r
+\r
+               addI18n : function(p, o) {\r
+                       var lo, i18n = this.i18n;\r
+\r
+                       if (!tinymce.is(p, 'string')) {\r
+                               each(p, function(o, lc) {\r
+                                       each(o, function(o, g) {\r
+                                               each(o, function(o, k) {\r
+                                                       if (g === 'common')\r
+                                                               i18n[lc + '.' + k] = o;\r
+                                                       else\r
+                                                               i18n[lc + '.' + g + '.' + k] = o;\r
+                                               });\r
+                                       });\r
+                               });\r
+                       } else {\r
+                               each(o, function(o, k) {\r
+                                       i18n[p + '.' + k] = o;\r
+                               });\r
+                       }\r
+               },\r
+\r
+               // Private methods\r
+\r
+               _setActive : function(e) {\r
+                       this.selectedInstance = this.activeEditor = e;\r
+               }\r
+\r
+               });\r
+\r
+       tinymce.EditorManager.preInit();\r
+})();\r
+\r
+// Short for editor manager window.tinyMCE is needed when TinyMCE gets loaded though a XHR call\r
+var tinyMCE = window.tinyMCE = tinymce.EditorManager;\r
+\r
+/* file:jscripts/tiny_mce/classes/Editor.js */\r
+\r
+(function() {\r
+       var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, Dispatcher = tinymce.util.Dispatcher;\r
+       var each = tinymce.each, isGecko = tinymce.isGecko, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit;\r
+       var is = tinymce.is, ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, EditorManager = tinymce.EditorManager;\r
+       var inArray = tinymce.inArray, grep = tinymce.grep, explode = tinymce.explode;\r
+\r
+       tinymce.create('tinymce.Editor', {\r
+               Editor : function(id, s) {\r
+                       var t = this;\r
+\r
+                       t.id = t.editorId = id;\r
+                       t.execCommands = {};\r
+                       t.queryStateCommands = {};\r
+                       t.queryValueCommands = {};\r
+                       t.plugins = {};\r
+\r
+                       // Add events to the editor\r
+                       each([\r
+                               'onPreInit',\r
+                               'onBeforeRenderUI',\r
+                               'onPostRender',\r
+                               'onInit',\r
+                               'onRemove',\r
+                               'onActivate',\r
+                               'onDeactivate',\r
+                               'onClick',\r
+                               'onEvent',\r
+                               'onMouseUp',\r
+                               'onMouseDown',\r
+                               'onDblClick',\r
+                               'onKeyDown',\r
+                               'onKeyUp',\r
+                               'onKeyPress',\r
+                               'onContextMenu',\r
+                               'onSubmit',\r
+                               'onReset',\r
+                               'onPaste',\r
+                               'onPreProcess',\r
+                               'onPostProcess',\r
+                               'onBeforeSetContent',\r
+                               'onBeforeGetContent',\r
+                               'onSetContent',\r
+                               'onGetContent',\r
+                               'onLoadContent',\r
+                               'onSaveContent',\r
+                               'onNodeChange',\r
+                               'onChange',\r
+                               'onBeforeExecCommand',\r
+                               'onExecCommand',\r
+                               'onUndo',\r
+                               'onRedo',\r
+                               'onVisualAid',\r
+                               'onSetProgressState'\r
+                       ], function(e) {\r
+                               t[e] = new Dispatcher(t);\r
+                       });\r
+\r
+                       // Default editor config\r
+                       t.settings = s = extend({\r
+                               id : id,\r
+                               language : 'en',\r
+                               docs_language : 'en',\r
+                               theme : 'simple',\r
+                               skin : 'default',\r
+                               delta_width : 0,\r
+                               delta_height : 0,\r
+                               popup_css : '',\r
+                               plugins : '',\r
+                               document_base_url : tinymce.documentBaseURL,\r
+                               add_form_submit_trigger : 1,\r
+                               submit_patch : 1,\r
+                               add_unload_trigger : 1,\r
+                               convert_urls : 1,\r
+                               relative_urls : 1,\r
+                               remove_script_host : 1,\r
+                               table_inline_editing : 0,\r
+                               object_resizing : 1,\r
+                               cleanup : 1,\r
+                               accessibility_focus : 1,\r
+                               custom_shortcuts : 1,\r
+                               custom_undo_redo_keyboard_shortcuts : 1,\r
+                               custom_undo_redo_restore_selection : 1,\r
+                               custom_undo_redo : 1,\r
+                               doctype : '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">',\r
+                               visual_table_class : 'mceItemTable',\r
+                               visual : 1,\r
+                               inline_styles : true,\r
+                               convert_fonts_to_spans : true,\r
+                               font_size_style_values : 'xx-small,x-small,small,medium,large,x-large,xx-large',\r
+                               apply_source_formatting : 1,\r
+                               directionality : 'ltr',\r
+                               forced_root_block : 'p',\r
+                               valid_elements : '@[id|class|style|title|dir<ltr?rtl|lang|xml::lang|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],a[rel|rev|charset|hreflang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur],strong/b,em/i,strike,u,#p[align],-ol[type|compact],-ul[type|compact],-li,br,img[longdesc|usemap|src|border|alt=|title|hspace|vspace|width|height|align],-sub,-sup,-blockquote,-table[border=0|cellspacing|cellpadding|width|frame|rules|height|align|summary|bgcolor|background|bordercolor],-tr[rowspan|width|height|align|valign|bgcolor|background|bordercolor],tbody,thead,tfoot,#td[colspan|rowspan|width|height|align|valign|bgcolor|background|bordercolor|scope],#th[colspan|rowspan|width|height|align|valign|scope],caption,-div,-span,-code,-pre,address,-h1,-h2,-h3,-h4,-h5,-h6,hr[size|noshade],-font[face|size|color],dd,dl,dt,cite,abbr,acronym,del[datetime|cite],ins[datetime|cite],object[classid|width|height|codebase|*],param[name|value|_value],embed[type|width|height|src|*],script[src|type],map[name],area[shape|coords|href|alt|target],bdo,button,col[align|char|charoff|span|valign|width],colgroup[align|char|charoff|span|valign|width],dfn,fieldset,form[action|accept|accept-charset|enctype|method],input[accept|alt|checked|disabled|maxlength|name|readonly|size|src|type|value],kbd,label[for],legend,noscript,optgroup[label|disabled],option[disabled|label|selected|value],q[cite],samp,select[disabled|multiple|name|size],small,textarea[cols|rows|disabled|name|readonly],tt,var,big',\r
+                               hidden_input : 1,\r
+                               padd_empty_editor : 1,\r
+                               render_ui : 1,\r
+                               init_theme : 1,\r
+                               force_p_newlines : 1,\r
+                               indentation : '30px'\r
+                       }, s);\r
+\r
+                       // Setup URIs\r
+                       t.documentBaseURI = new tinymce.util.URI(s.document_base_url || tinymce.documentBaseURL, {\r
+                               base_uri : tinyMCE.baseURI\r
+                       });\r
+                       t.baseURI = EditorManager.baseURI;\r
+\r
+                       // Call setup\r
+                       t.execCallback('setup', t);\r
+               },\r
+\r
+               render : function(nst) {\r
+                       var t = this, s = t.settings, id = t.id, sl = tinymce.ScriptLoader;\r
+\r
+                       // Page is not loaded yet, wait for it\r
+                       if (!Event.domLoaded) {\r
+                               Event.add(document, 'init', function() {\r
+                                       t.render();\r
+                               });\r
+                               return;\r
+                       }\r
+\r
+                       // Force strict loading mode if render us called by user and not internally\r
+                       if (!nst) {\r
+                               s.strict_loading_mode = 1;\r
+                               tinyMCE.settings = s;\r
+                       }\r
+\r
+                       // Element not found, then skip initialization\r
+                       if (!t.getElement())\r
+                               return;\r
+\r
+                       if (s.strict_loading_mode) {\r
+                               sl.settings.strict_mode = s.strict_loading_mode;\r
+                               tinymce.DOM.settings.strict = 1;\r
+                       }\r
+\r
+                       // Add hidden input for non input elements inside form elements\r
+                       if (!/TEXTAREA|INPUT/i.test(t.getElement().nodeName) && s.hidden_input && DOM.getParent(id, 'form'))\r
+                               DOM.insertAfter(DOM.create('input', {type : 'hidden', name : id}), id);\r
+\r
+                       t.windowManager = new tinymce.WindowManager(t);\r
+\r
+                       if (s.encoding == 'xml') {\r
+                               t.onGetContent.add(function(ed, o) {\r
+                                       if (o.get)\r
+                                               o.content = DOM.encode(o.content);\r
+                               });\r
+                       }\r
+\r
+                       if (s.add_form_submit_trigger) {\r
+                               t.onSubmit.addToTop(function() {\r
+                                       if (t.initialized) {\r
+                                               t.save();\r
+                                               t.isNotDirty = 1;\r
+                                       }\r
+                               });\r
+                       }\r
+\r
+                       if (s.add_unload_trigger) {\r
+                               t._beforeUnload = tinyMCE.onBeforeUnload.add(function() {\r
+                                       if (t.initialized && !t.destroyed && !t.isHidden())\r
+                                               t.save({format : 'raw', no_events : true});\r
+                               });\r
+                       }\r
+\r
+                       tinymce.addUnload(t.destroy, t);\r
+\r
+                       if (s.submit_patch) {\r
+                               t.onBeforeRenderUI.add(function() {\r
+                                       var n = t.getElement().form;\r
+\r
+                                       if (!n)\r
+                                               return;\r
+\r
+                                       // Already patched\r
+                                       if (n._mceOldSubmit)\r
+                                               return;\r
+\r
+                                       // Check page uses id="submit" or name="submit" for it's submit button\r
+                                       if (!n.submit.nodeType && !n.submit.length) {\r
+                                               t.formElement = n;\r
+                                               n._mceOldSubmit = n.submit;\r
+                                               n.submit = function() {\r
+                                                       // Save all instances\r
+                                                       EditorManager.triggerSave();\r
+                                                       t.isNotDirty = 1;\r
+\r
+                                                       return this._mceOldSubmit(this);\r
+                                               };\r
+                                       }\r
+\r
+                                       n = null;\r
+                               });\r
+                       }\r
+\r
+                       // Load scripts\r
+                       function loadScripts() {\r
+                               if (s.language)\r
+                                       sl.add(tinymce.baseURL + '/langs/' + s.language + '.js');\r
+\r
+                               if (s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme])\r
+                                       ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js');\r
+\r
+                               each(explode(s.plugins), function(p) {\r
+                                       if (p && p.charAt(0) != '-' && !PluginManager.urls[p]) {\r
+                                               // Skip safari plugin for other browsers\r
+                                               if (!isWebKit && p == 'safari')\r
+                                                       return;\r
+\r
+                                               PluginManager.load(p, 'plugins/' + p + '/editor_plugin' + tinymce.suffix + '.js');\r
+                                       }\r
+                               });\r
+\r
+                               // Init when que is loaded\r
+                               sl.loadQueue(function() {\r
+                                       if (s.ask) {\r
+                                               function ask() {\r
+                                                       t.windowManager.confirm(t.getLang('edit_confirm'), function(s) {\r
+                                                               if (s)\r
+                                                                       t.init();\r
+                                                               else\r
+                                                                       Event.remove(t.id, 'focus', ask);\r
+                                                       });\r
+                                               };\r
+\r
+                                               Event.add(t.id, 'focus', ask);\r
+                                               return;\r
+                                       }\r
+\r
+                                       if (!t.removed)\r
+                                               t.init();\r
+                               });\r
+                       };\r
+\r
+                       // Load compat2x first\r
+                       if (s.plugins.indexOf('compat2x') != -1) {\r
+                               PluginManager.load('compat2x', 'plugins/compat2x/editor_plugin' + tinymce.suffix + '.js');\r
+                               sl.loadQueue(loadScripts);\r
+                       } else\r
+                               loadScripts();\r
+               },\r
+\r
+               init : function() {\r
+                       var n, t = this, s = t.settings, w, h, e = t.getElement(), o, ti, u, bi, bc, re;\r
+\r
+                       EditorManager.add(t);\r
+\r
+                       // Create theme\r
+                       s.theme = s.theme.replace(/-/, '');\r
+                       o = ThemeManager.get(s.theme);\r
+                       t.theme = new o();\r
+\r
+                       if (t.theme.init && s.init_theme)\r
+                               t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, ''));\r
+\r
+                       // Create all plugins\r
+                       each(explode(s.plugins.replace(/\-/g, '')), function(p) {\r
+                               var c = PluginManager.get(p), u = PluginManager.urls[p] || tinymce.documentBaseURL.replace(/\/$/, ''), po;\r
+\r
+                               if (c) {\r
+                                       po = new c(t, u);\r
+\r
+                                       t.plugins[p] = po;\r
+\r
+                                       if (po.init)\r
+                                               po.init(t, u);\r
+                               }\r
+                       });\r
+\r
+                       // Setup popup CSS path(s)\r
+                       if (s.popup_css)\r
+                               s.popup_css = t.documentBaseURI.toAbsolute(s.popup_css);\r
+                       else\r
+                               s.popup_css = t.baseURI.toAbsolute("themes/" + s.theme + "/skins/" + s.skin + "/dialog.css");\r
+\r
+                       if (s.popup_css_add)\r
+                               s.popup_css += ',' + t.documentBaseURI.toAbsolute(s.popup_css_add);\r
+\r
+                       // Setup control factory\r
+                       t.controlManager = new tinymce.ControlManager(t);\r
+                       t.undoManager = new tinymce.UndoManager(t);\r
+\r
+                       // Pass through\r
+                       t.undoManager.onAdd.add(function(um, l) {\r
+                               return t.onChange.dispatch(t, l, um);\r
+                       });\r
+\r
+                       t.undoManager.onUndo.add(function(um, l) {\r
+                               return t.onUndo.dispatch(t, l, um);\r
+                       });\r
+\r
+                       t.undoManager.onRedo.add(function(um, l) {\r
+                               return t.onRedo.dispatch(t, l, um);\r
+                       });\r
+\r
+                       if (s.custom_undo_redo) {\r
+                               t.onExecCommand.add(function(ed, cmd, ui, val, a) {\r
+                                       if (cmd != 'Undo' && cmd != 'Redo' && cmd != 'mceRepaint' && (!a || !a.skip_undo))\r
+                                               t.undoManager.add();\r
+                               });\r
+                       }\r
+\r
+                       t.onExecCommand.add(function(ed, c) {\r
+                               // Don't refresh the select lists until caret move\r
+                               if (!/^(FontName|FontSize)$/.test(c))\r
+                                       t.nodeChanged();\r
+                       });\r
+\r
+                       // Remove ghost selections on images and tables in Gecko\r
+                       if (isGecko) {\r
+                               function repaint(a, o) {\r
+                                       if (!o || !o.initial)\r
+                                               t.execCommand('mceRepaint');\r
+                               };\r
+\r
+                               t.onUndo.add(repaint);\r
+                               t.onRedo.add(repaint);\r
+                               t.onSetContent.add(repaint);\r
+                       }\r
+\r
+                       // Enables users to override the control factory\r
+                       t.onBeforeRenderUI.dispatch(t, t.controlManager);\r
+\r
+                       // Measure box\r
+                       if (s.render_ui) {\r
+                               w = s.width || e.style.width || e.clientWidth;\r
+                               h = s.height || e.style.height || e.clientHeight;\r
+                               t.orgDisplay = e.style.display;\r
+                               re = /^[0-9\.]+(|px)$/i;\r
+\r
+                               if (re.test('' + w))\r
+                                       w = Math.max(parseInt(w) + (o.deltaWidth || 0), 100);\r
+\r
+                               if (re.test('' + h))\r
+                                       h = Math.max(parseInt(h) + (o.deltaHeight || 0), 100);\r
+\r
+                               // Render UI\r
+                               o = t.theme.renderUI({\r
+                                       targetNode : e,\r
+                                       width : w,\r
+                                       height : h,\r
+                                       deltaWidth : s.delta_width,\r
+                                       deltaHeight : s.delta_height\r
+                               });\r
+\r
+                               t.editorContainer = o.editorContainer;\r
+                       }\r
+\r
+                       \r
+                       // Resize editor\r
+                       DOM.setStyles(o.sizeContainer || o.editorContainer, {\r
+                               width : w,\r
+                               height : h\r
+                       });\r
+\r
+                       h = (o.iframeHeight || h) + ((h + '').indexOf('%') == -1 ? (o.deltaHeight || 0) : '');\r
+                       if (h < 100)\r
+                               h = 100;\r
+\r
+                       t.iframeHTML = s.doctype + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + t.documentBaseURI.getURI() + '"></base>';\r
+                       t.iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';\r
+\r
+                       if (tinymce.relaxedDomain)\r
+                               t.iframeHTML += '<script type="text/javascript">document.domain = "' + tinymce.relaxedDomain + '";</script>';\r
+\r
+                       bi = s.body_id || 'tinymce';\r
+                       if (bi.indexOf('=') != -1) {\r
+                               bi = t.getParam('body_id', '', 'hash');\r
+                               bi = bi[t.id] || bi;\r
+                       }\r
+\r
+                       bc = s.body_class || '';\r
+                       if (bc.indexOf('=') != -1) {\r
+                               bc = t.getParam('body_class', '', 'hash');\r
+                               bc = bc[t.id] || '';\r
+                       }\r
+\r
+                       t.iframeHTML += '</head><body id="' + bi + '" class="mceContentBody ' + bc + '"></body></html>';\r
+\r
+                       // Domain relaxing enabled, then set document domain\r
+                       if (tinymce.relaxedDomain) {\r
+                               // We need to write the contents here in IE since multiple writes messes up refresh button and back button\r
+                               if (isIE)\r
+                                       u = 'javascript:(function(){document.open();document.domain="' + document.domain + '";var ed = window.parent.tinyMCE.get("' + t.id + '");document.write(ed.iframeHTML);document.close();ed.setupIframe();})()';\r
+                               else if (tinymce.isOpera)\r
+                                       u = 'javascript:(function(){document.open();document.domain="' + document.domain + '";document.close();ed.setupIframe();})()';                                  \r
+                       }\r
+\r
+                       // Create iframe\r
+                       n = DOM.add(o.iframeContainer, 'iframe', {\r
+                               id : t.id + "_ifr",\r
+                               src : u || 'javascript:""', // Workaround for HTTPS warning in IE6/7\r
+                               frameBorder : '0',\r
+                               style : {\r
+                                       width : '100%',\r
+                                       height : h\r
+                               }\r
+                       });\r
+\r
+                       t.contentAreaContainer = o.iframeContainer;\r
+                       DOM.get(o.editorContainer).style.display = t.orgDisplay;\r
+                       DOM.get(t.id).style.display = 'none';\r
+\r
+                       // Safari 2.x requires us to wait for the load event and load a real HTML doc\r
+                       if (tinymce.isOldWebKit) {\r
+                               Event.add(n, 'load', t.setupIframe, t);\r
+                               n.src = tinymce.baseURL + '/plugins/safari/blank.htm';\r
+                       } else {\r
+                               if (!isIE || !tinymce.relaxedDomain)\r
+                                       t.setupIframe();\r
+\r
+                               e = n = o = null; // Cleanup\r
+                       }\r
+               },\r
+\r
+               setupIframe : function() {\r
+                       var t = this, s = t.settings, e = DOM.get(t.id), d = t.getDoc(), h, b;\r
+\r
+                       // Setup iframe body\r
+                       if (!isIE || !tinymce.relaxedDomain) {\r
+                               d.open();\r
+                               d.write(t.iframeHTML);\r
+                               d.close();\r
+                       }\r
+\r
+                       // Design mode needs to be added here Ctrl+A will fail otherwise\r
+                       if (!isIE) {\r
+                               try {\r
+                                       d.designMode = 'On';\r
+                               } catch (ex) {\r
+                                       // Will fail on Gecko if the editor is placed in an hidden container element\r
+                                       // The design mode will be set ones the editor is focused\r
+                               }\r
+                       }\r
+\r
+                       // IE needs to use contentEditable or it will display non secure items for HTTPS\r
+                       if (isIE) {\r
+                               // It will not steal focus if we hide it while setting contentEditable\r
+                               b = t.getBody();\r
+                               DOM.hide(b);\r
+                               b.contentEditable = true;\r
+                               DOM.show(b);\r
+                       }\r
+\r
+                       // Setup objects\r
+                       t.dom = new tinymce.DOM.DOMUtils(t.getDoc(), {\r
+                               keep_values : true,\r
+                               url_converter : t.convertURL,\r
+                               url_converter_scope : t,\r
+                               hex_colors : s.force_hex_style_colors,\r
+                               class_filter : s.class_filter,\r
+                               update_styles : 1,\r
+                               fix_ie_paragraphs : 1\r
+                       });\r
+\r
+                       t.serializer = new tinymce.dom.Serializer({\r
+                               entity_encoding : s.entity_encoding,\r
+                               entities : s.entities,\r
+                               valid_elements : s.verify_html === false ? '*[*]' : s.valid_elements,\r
+                               extended_valid_elements : s.extended_valid_elements,\r
+                               valid_child_elements : s.valid_child_elements,\r
+                               invalid_elements : s.invalid_elements,\r
+                               fix_table_elements : s.fix_table_elements,\r
+                               fix_list_elements : s.fix_list_elements,\r
+                               fix_content_duplication : s.fix_content_duplication,\r
+                               convert_fonts_to_spans : s.convert_fonts_to_spans,\r
+                               font_size_classes  : s.font_size_classes,\r
+                               font_size_style_values : s.font_size_style_values,\r
+                               apply_source_formatting : s.apply_source_formatting,\r
+                               remove_linebreaks : s.remove_linebreaks,\r
+                               dom : t.dom\r
+                       });\r
+\r
+                       t.selection = new tinymce.dom.Selection(t.dom, t.getWin(), t.serializer);\r
+                       t.forceBlocks = new tinymce.ForceBlocks(t, {\r
+                               forced_root_block : s.forced_root_block\r
+                       });\r
+                       t.editorCommands = new tinymce.EditorCommands(t);\r
+\r
+                       // Pass through\r
+                       t.serializer.onPreProcess.add(function(se, o) {\r
+                               return t.onPreProcess.dispatch(t, o, se);\r
+                       });\r
+\r
+                       t.serializer.onPostProcess.add(function(se, o) {\r
+                               return t.onPostProcess.dispatch(t, o, se);\r
+                       });\r
+\r
+                       t.onPreInit.dispatch(t);\r
+\r
+                       if (!s.gecko_spellcheck)\r
+                               t.getBody().spellcheck = 0;\r
+\r
+                       t._addEvents();\r
+\r
+                       t.controlManager.onPostRender.dispatch(t, t.controlManager);\r
+                       t.onPostRender.dispatch(t);\r
+\r
+                       if (s.directionality)\r
+                               t.getBody().dir = s.directionality;\r
+\r
+                       if (s.nowrap)\r
+                               t.getBody().style.whiteSpace = "nowrap";\r
+\r
+                       if (s.auto_resize)\r
+                               t.onNodeChange.add(t.resizeToContent, t);\r
+\r
+                       if (s.custom_elements) {\r
+                               function handleCustom(ed, o) {\r
+                                       each(explode(s.custom_elements), function(v) {\r
+                                               var n;\r
+\r
+                                               if (v.indexOf('~') === 0) {\r
+                                                       v = v.substring(1);\r
+                                                       n = 'span';\r
+                                               } else\r
+                                                       n = 'div';\r
+\r
+                                               o.content = o.content.replace(new RegExp('<(' + v + ')([^>]*)>', 'g'), '<' + n + ' mce_name="$1"$2>');\r
+                                               o.content = o.content.replace(new RegExp('</(' + v + ')>', 'g'), '</' + n + '>');\r
+                                       });\r
+                               };\r
+\r
+                               t.onBeforeSetContent.add(handleCustom);\r
+                               t.onPostProcess.add(function(ed, o) {\r
+                                       if (o.set)\r
+                                               handleCustom(ed, o)\r
+                               });\r
+                       }\r
+\r
+                       if (s.handle_node_change_callback) {\r
+                               t.onNodeChange.add(function(ed, cm, n) {\r
+                                       t.execCallback('handle_node_change_callback', t.id, n, -1, -1, true, t.selection.isCollapsed());\r
+                               });\r
+                       }\r
+\r
+                       if (s.save_callback) {\r
+                               t.onSaveContent.add(function(ed, o) {\r
+                                       var h = t.execCallback('save_callback', t.id, o.content, t.getBody());\r
+\r
+                                       if (h)\r
+                                               o.content = h;\r
+                               });\r
+                       }\r
+\r
+                       if (s.onchange_callback) {\r
+                               t.onChange.add(function(ed, l) {\r
+                                       t.execCallback('onchange_callback', t, l);\r
+                               });\r
+                       }\r
+\r
+                       if (s.convert_newlines_to_brs) {\r
+                               t.onBeforeSetContent.add(function(ed, o) {\r
+                                       if (o.initial)\r
+                                               o.content = o.content.replace(/\r?\n/g, '<br />');\r
+                               });\r
+                       }\r
+\r
+                       if (s.fix_nesting && isIE) {\r
+                               t.onBeforeSetContent.add(function(ed, o) {\r
+                                       o.content = t._fixNesting(o.content);\r
+                               });\r
+                       }\r
+\r
+                       if (s.preformatted) {\r
+                               t.onPostProcess.add(function(ed, o) {\r
+                                       o.content = o.content.replace(/^\s*<pre.*?>/, '');\r
+                                       o.content = o.content.replace(/<\/pre>\s*$/, '');\r
+\r
+                                       if (o.set)\r
+                                               o.content = '<pre class="mceItemHidden">' + o.content + '</pre>';\r
+                               });\r
+                       }\r
+\r
+                       if (s.verify_css_classes) {\r
+                               t.serializer.attribValueFilter = function(n, v) {\r
+                                       var s, cl;\r
+\r
+                                       if (n == 'class') {\r
+                                               // Build regexp for classes\r
+                                               if (!t.classesRE) {\r
+                                                       cl = t.dom.getClasses();\r
+\r
+                                                       if (cl.length > 0) {\r
+                                                               s = '';\r
+\r
+                                                               each (cl, function(o) {\r
+                                                                       s += (s ? '|' : '') + o['class'];\r
+                                                               });\r
+\r
+                                                               t.classesRE = new RegExp('(' + s + ')', 'gi');\r
+                                                       }\r
+                                               }\r
+\r
+                                               return !t.classesRE || /(\bmceItem\w+\b|\bmceTemp\w+\b)/g.test(v) || t.classesRE.test(v) ? v : '';\r
+                                       }\r
+\r
+                                       return v;\r
+                               };\r
+                       }\r
+\r
+                       if (s.convert_fonts_to_spans)\r
+                               t._convertFonts();\r
+\r
+                       if (s.inline_styles)\r
+                               t._convertInlineElements();\r
+\r
+                       if (s.cleanup_callback) {\r
+                               t.onBeforeSetContent.add(function(ed, o) {\r
+                                       o.content = t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o);\r
+                               });\r
+\r
+                               t.onPreProcess.add(function(ed, o) {\r
+                                       if (o.set)\r
+                                               t.execCallback('cleanup_callback', 'insert_to_editor_dom', o.node, o);\r
+\r
+                                       if (o.get)\r
+                                               t.execCallback('cleanup_callback', 'get_from_editor_dom', o.node, o);\r
+                               });\r
+\r
+                               t.onPostProcess.add(function(ed, o) {\r
+                                       if (o.set)\r
+                                               o.content = t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o);\r
+\r
+                                       if (o.get)                                              \r
+                                               o.content = t.execCallback('cleanup_callback', 'get_from_editor', o.content, o);\r
+                               });\r
+                       }\r
+\r
+                       if (s.save_callback) {\r
+                               t.onGetContent.add(function(ed, o) {\r
+                                       if (o.save)\r
+                                               o.content = t.execCallback('save_callback', t.id, o.content, t.getBody());\r
+                               });\r
+                       }\r
+\r
+                       if (s.handle_event_callback) {\r
+                               t.onEvent.add(function(ed, e, o) {\r
+                                       if (t.execCallback('handle_event_callback', e, ed, o) === false)\r
+                                               Event.cancel(e);\r
+                               });\r
+                       }\r
+\r
+                       t.onSetContent.add(function() {\r
+                               // Safari needs some time, it will crash the browser when a link is created otherwise\r
+                               // I think this crash issue is resolved in the latest 3.0.4\r
+                               //window.setTimeout(function() {\r
+                                       t.addVisual(t.getBody());\r
+                               //}, 1);\r
+                       });\r
+\r
+                       // Remove empty contents\r
+                       if (s.padd_empty_editor) {\r
+                               t.onPostProcess.add(function(ed, o) {\r
+                                       o.content = o.content.replace(/^<p>(&nbsp;|#160;|\s|\u00a0)<\/p>$/, '');\r
+                               });\r
+                       }\r
+\r
+                       if (isGecko) {\r
+                               try {\r
+                                       // Design mode must be set here once again to fix a bug where\r
+                                       // Ctrl+A/Delete/Backspace didn't work if the editor was added using mceAddControl then removed then added again\r
+                                       d.designMode = 'Off';\r
+                                       d.designMode = 'On';\r
+                               } catch (ex) {\r
+                                       // Will fail on Gecko if the editor is placed in an hidden container element\r
+                                       // The design mode will be set ones the editor is focused\r
+                               }\r
+                       }\r
+\r
+                       // A small timeout was needed since firefox will remove. Bug: #1838304\r
+                       setTimeout(function () {\r
+                               if (t.removed)\r
+                                       return;\r
+\r
+                               t.load({initial : true, format : (s.cleanup_on_startup ? 'html' : 'raw')});\r
+                               t.startContent = t.getContent({format : 'raw'});\r
+                               t.undoManager.add({initial : true});\r
+                               t.initialized = true;\r
+\r
+                               t.onInit.dispatch(t);\r
+                               t.execCallback('setupcontent_callback', t.id, t.getBody(), t.getDoc());\r
+                               t.execCallback('init_instance_callback', t);\r
+                               t.focus(true);\r
+                               t.nodeChanged({initial : 1});\r
+\r
+                               // Load specified content CSS last\r
+                               if (s.content_css) {\r
+                                       tinymce.each(explode(s.content_css), function(u) {\r
+                                               t.dom.loadCSS(t.documentBaseURI.toAbsolute(u));\r
+                                       });\r
+                               }\r
+\r
+                               // Handle auto focus\r
+                               if (s.auto_focus) {\r
+                                       setTimeout(function () {\r
+                                               var ed = EditorManager.get(s.auto_focus);\r
+\r
+                                               ed.selection.select(ed.getBody(), 1);\r
+                                               ed.selection.collapse(1);\r
+                                               ed.getWin().focus();\r
+                                       }, 100);\r
+                               }\r
+                       }, 1);\r
+       \r
+                       e = null;\r
+               },\r
+\r
+               \r
+               focus : function(sf) {\r
+                       var oed, t = this;\r
+\r
+                       if (!sf) {\r
+                               t.getWin().focus();\r
+\r
+                                                       }\r
+\r
+                       if (EditorManager.activeEditor != t) {\r
+                               if ((oed = EditorManager.activeEditor) != null)\r
+                                       oed.onDeactivate.dispatch(oed, t);\r
+\r
+                               t.onActivate.dispatch(t, oed);\r
+                       }\r
+\r
+                       EditorManager._setActive(t);\r
+               },\r
+\r
+               execCallback : function(n) {\r
+                       var t = this, f = t.settings[n], s;\r
+\r
+                       if (!f)\r
+                               return;\r
+\r
+                       // Look through lookup\r
+                       if (t.callbackLookup && (s = t.callbackLookup[n])) {\r
+                               f = s.func;\r
+                               s = s.scope;\r
+                       }\r
+\r
+                       if (is(f, 'string')) {\r
+                               s = f.replace(/\.\w+$/, '');\r
+                               s = s ? tinymce.resolve(s) : 0;\r
+                               f = tinymce.resolve(f);\r
+                               t.callbackLookup = t.callbackLookup || {};\r
+                               t.callbackLookup[n] = {func : f, scope : s};\r
+                       }\r
+\r
+                       return f.apply(s || t, Array.prototype.slice.call(arguments, 1));\r
+               },\r
+\r
+               translate : function(s) {\r
+                       var c = this.settings.language, i18n = EditorManager.i18n;\r
+\r
+                       if (!s)\r
+                               return '';\r
+\r
+                       return i18n[c + '.' + s] || s.replace(/{\#([^}]+)\}/g, function(a, b) {\r
+                               return i18n[c + '.' + b] || '{#' + b + '}';\r
+                       });\r
+               },\r
+\r
+               getLang : function(n, dv) {\r
+                       return EditorManager.i18n[this.settings.language + '.' + n] || (is(dv) ? dv : '{#' + n + '}');\r
+               },\r
+\r
+               getParam : function(n, dv, ty) {\r
+                       var tr = tinymce.trim, v = is(this.settings[n]) ? this.settings[n] : dv, o;\r
+\r
+                       if (ty === 'hash') {\r
+                               o = {};\r
+\r
+                               if (is(v, 'string')) {\r
+                                       each(v.indexOf('=') > 0 ? v.split(/[;,](?![^=;,]*(?:[;,]|$))/) : v.split(','), function(v) {\r
+                                               v = v.split('=');\r
+\r
+                                               if (v.length > 1)\r
+                                                       o[tr(v[0])] = tr(v[1]);\r
+                                               else\r
+                                                       o[tr(v[0])] = tr(v);\r
+                                       });\r
+                               } else\r
+                                       o = v;\r
+\r
+                               return o;\r
+                       }\r
+\r
+                       return v;\r
+               },\r
+\r
+               nodeChanged : function(o) {\r
+                       var t = this, s = t.selection, n = s.getNode() || t.getBody();\r
+\r
+                       // Fix for bug #1896577 it seems that this can not be fired while the editor is loading\r
+                       if (t.initialized) {\r
+                               t.onNodeChange.dispatch(\r
+                                       t,\r
+                                       o ? o.controlManager || t.controlManager : t.controlManager,\r
+                                       isIE && n.ownerDocument != t.getDoc() ? t.getBody() : n, // Fix for IE initial state\r
+                                       s.isCollapsed(),\r
+                                       o\r
+                               );\r
+                       }\r
+               },\r
+\r
+               addButton : function(n, s) {\r
+                       var t = this;\r
+\r
+                       t.buttons = t.buttons || {};\r
+                       t.buttons[n] = s;\r
+               },\r
+\r
+               addCommand : function(n, f, s) {\r
+                       this.execCommands[n] = {func : f, scope : s || this};\r
+               },\r
+\r
+               addQueryStateHandler : function(n, f, s) {\r
+                       this.queryStateCommands[n] = {func : f, scope : s || this};\r
+               },\r
+\r
+               addQueryValueHandler : function(n, f, s) {\r
+                       this.queryValueCommands[n] = {func : f, scope : s || this};\r
+               },\r
+\r
+               addShortcut : function(pa, desc, cmd_func, sc) {\r
+                       var t = this, c;\r
+\r
+                       if (!t.settings.custom_shortcuts)\r
+                               return false;\r
+\r
+                       t.shortcuts = t.shortcuts || {};\r
+\r
+                       if (is(cmd_func, 'string')) {\r
+                               c = cmd_func;\r
+\r
+                               cmd_func = function() {\r
+                                       t.execCommand(c, false, null);\r
+                               };\r
+                       }\r
+\r
+                       if (is(cmd_func, 'object')) {\r
+                               c = cmd_func;\r
+\r
+                               cmd_func = function() {\r
+                                       t.execCommand(c[0], c[1], c[2]);\r
+                               };\r
+                       }\r
+\r
+                       each(explode(pa), function(pa) {\r
+                               var o = {\r
+                                       func : cmd_func,\r
+                                       scope : sc || this,\r
+                                       desc : desc,\r
+                                       alt : false,\r
+                                       ctrl : false,\r
+                                       shift : false\r
+                               };\r
+\r
+                               each(explode(pa, '+'), function(v) {\r
+                                       switch (v) {\r
+                                               case 'alt':\r
+                                               case 'ctrl':\r
+                                               case 'shift':\r
+                                                       o[v] = true;\r
+                                                       break;\r
+\r
+                                               default:\r
+                                                       o.charCode = v.charCodeAt(0);\r
+                                                       o.keyCode = v.toUpperCase().charCodeAt(0);\r
+                                       }\r
+                               });\r
+\r
+                               t.shortcuts[(o.ctrl ? 'ctrl' : '') + ',' + (o.alt ? 'alt' : '') + ',' + (o.shift ? 'shift' : '') + ',' + o.keyCode] = o;\r
+                       });\r
+\r
+                       return true;\r
+               },\r
+\r
+               execCommand : function(cmd, ui, val, a) {\r
+                       var t = this, s = 0, o, st;\r
+\r
+                       if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(cmd) && (!a || !a.skip_focus))\r
+                               t.focus();\r
+\r
+                       o = {};\r
+                       t.onBeforeExecCommand.dispatch(t, cmd, ui, val, o);\r
+                       if (o.terminate)\r
+                               return false;\r
+\r
+                       // Comamnd callback\r
+                       if (t.execCallback('execcommand_callback', t.id, t.selection.getNode(), cmd, ui, val)) {\r
+                               t.onExecCommand.dispatch(t, cmd, ui, val, a);\r
+                               return true;\r
+                       }\r
+\r
+                       // Registred commands\r
+                       if (o = t.execCommands[cmd]) {\r
+                               st = o.func.call(o.scope, ui, val);\r
+\r
+                               // Fall through on true\r
+                               if (st !== true) {\r
+                                       t.onExecCommand.dispatch(t, cmd, ui, val, a);\r
+                                       return st;\r
+                               }\r
+                       }\r
+\r
+                       // Plugin commands\r
+                       each(t.plugins, function(p) {\r
+                               if (p.execCommand && p.execCommand(cmd, ui, val)) {\r
+                                       t.onExecCommand.dispatch(t, cmd, ui, val, a);\r
+                                       s = 1;\r
+                                       return false;\r
+                               }\r
+                       });\r
+\r
+                       if (s)\r
+                               return true;\r
+\r
+                       // Theme commands\r
+                       if (t.theme.execCommand && t.theme.execCommand(cmd, ui, val)) {\r
+                               t.onExecCommand.dispatch(t, cmd, ui, val, a);\r
+                               return true;\r
+                       }\r
+\r
+                       // Editor commands\r
+                       if (t.editorCommands.execCommand(cmd, ui, val)) {\r
+                               t.onExecCommand.dispatch(t, cmd, ui, val, a);\r
+                               return true;\r
+                       }\r
+\r
+                       // Browser commands\r
+                       t.getDoc().execCommand(cmd, ui, val);\r
+                       t.onExecCommand.dispatch(t, cmd, ui, val, a);\r
+               },\r
+\r
+               queryCommandState : function(c) {\r
+                       var t = this, o, s;\r
+\r
+                       // Is hidden then return undefined\r
+                       if (t._isHidden())\r
+                               return;\r
+\r
+                       // Registred commands\r
+                       if (o = t.queryStateCommands[c]) {\r
+                               s = o.func.call(o.scope);\r
+\r
+                               // Fall though on true\r
+                               if (s !== true)\r
+                                       return s;\r
+                       }\r
+\r
+                       // Registred commands\r
+                       o = t.editorCommands.queryCommandState(c);\r
+                       if (o !== -1)\r
+                               return o;\r
+\r
+                       // Browser commands\r
+                       try {\r
+                               return this.getDoc().queryCommandState(c);\r
+                       } catch (ex) {\r
+                               // Fails sometimes see bug: 1896577\r
+                       }\r
+               },\r
+\r
+               queryCommandValue : function(c) {\r
+                       var t = this, o, s;\r
+\r
+                       // Is hidden then return undefined\r
+                       if (t._isHidden())\r
+                               return;\r
+\r
+                       // Registred commands\r
+                       if (o = t.queryValueCommands[c]) {\r
+                               s = o.func.call(o.scope);\r
+\r
+                               // Fall though on true\r
+                               if (s !== true)\r
+                                       return s;\r
+                       }\r
+\r
+                       // Registred commands\r
+                       o = t.editorCommands.queryCommandValue(c);\r
+                       if (is(o))\r
+                               return o;\r
+\r
+                       // Browser commands\r
+                       try {\r
+                               return this.getDoc().queryCommandValue(c);\r
+                       } catch (ex) {\r
+                               // Fails sometimes see bug: 1896577\r
+                       }\r
+               },\r
+\r
+               show : function() {\r
+                       var t = this;\r
+\r
+                       DOM.show(t.getContainer());\r
+                       DOM.hide(t.id);\r
+                       t.load();\r
+               },\r
+\r
+               hide : function() {\r
+                       var t = this, d = t.getDoc();\r
+\r
+                       // Fixed bug where IE has a blinking cursor left from the editor\r
+                       if (isIE && d)\r
+                               d.execCommand('SelectAll');\r
+\r
+                       // We must save before we hide so Safari doesn't crash\r
+                       t.save();\r
+                       DOM.hide(t.getContainer());\r
+                       DOM.setStyle(t.id, 'display', t.orgDisplay);\r
+               },\r
+\r
+               isHidden : function() {\r
+                       return !DOM.isHidden(this.id);\r
+               },\r
+\r
+               setProgressState : function(b, ti, o) {\r
+                       this.onSetProgressState.dispatch(this, b, ti, o);\r
+\r
+                       return b;\r
+               },\r
+\r
+               resizeToContent : function() {\r
+                       var t = this;\r
+\r
+                       DOM.setStyle(t.id + "_ifr", 'height', t.getBody().scrollHeight);\r
+               },\r
+\r
+               load : function(o) {\r
+                       var t = this, e = t.getElement(), h;\r
+\r
+                       o = o || {};\r
+                       o.load = true;\r
+\r
+                       h = t.setContent(is(e.value) ? e.value : e.innerHTML, o);\r
+                       o.element = e;\r
+\r
+                       if (!o.no_events)\r
+                               t.onLoadContent.dispatch(t, o);\r
+\r
+                       o.element = e = null;\r
+\r
+                       return h;\r
+               },\r
+\r
+               save : function(o) {\r
+                       var t = this, e = t.getElement(), h, f;\r
+\r
+                       if (!t.initialized)\r
+                               return;\r
+\r
+                       o = o || {};\r
+                       o.save = true;\r
+\r
+                       o.element = e;\r
+                       h = o.content = t.getContent(o);\r
+\r
+                       if (!o.no_events)\r
+                               t.onSaveContent.dispatch(t, o);\r
+\r
+                       h = o.content;\r
+\r
+                       if (!/TEXTAREA|INPUT/i.test(e.nodeName)) {\r
+                               e.innerHTML = h;\r
+\r
+                               // Update hidden form element\r
+                               if (f = DOM.getParent(t.id, 'form')) {\r
+                                       each(f.elements, function(e) {\r
+                                               if (e.name == t.id) {\r
+                                                       e.value = h;\r
+                                                       return false;\r
+                                               }\r
+                                       });\r
+                               }\r
+                       } else\r
+                               e.value = h;\r
+\r
+                       o.element = e = null;\r
+\r
+                       return h;\r
+               },\r
+\r
+               setContent : function(h, o) {\r
+                       var t = this;\r
+\r
+                       o = o || {};\r
+                       o.format = o.format || 'html';\r
+                       o.set = true;\r
+                       o.content = h;\r
+\r
+                       if (!o.no_events)\r
+                               t.onBeforeSetContent.dispatch(t, o);\r
+\r
+                       // Padd empty content in Gecko and Safari. Commands will otherwise fail on the content\r
+                       // It will also be impossible to place the caret in the editor unless there is a BR element present\r
+                       if (!tinymce.isIE && (h.length === 0 || /^\s+$/.test(h))) {\r
+                               o.content = t.dom.setHTML(t.getBody(), '<br mce_bogus="1" />', 1);\r
+                               o.format = 'raw';\r
+                       }\r
+\r
+                       o.content = t.dom.setHTML(t.getBody(), tinymce.trim(o.content));\r
+\r
+                       if (o.format != 'raw' && t.settings.cleanup) {\r
+                               o.getInner = true;\r
+                               o.content = t.dom.setHTML(t.getBody(), t.serializer.serialize(t.getBody(), o));\r
+                       }\r
+\r
+                       if (!o.no_events)\r
+                               t.onSetContent.dispatch(t, o);\r
+\r
+                       return o.content;\r
+               },\r
+\r
+               getContent : function(o) {\r
+                       var t = this, h;\r
+\r
+                       o = o || {};\r
+                       o.format = o.format || 'html';\r
+                       o.get = true;\r
+\r
+                       if (!o.no_events)\r
+                               t.onBeforeGetContent.dispatch(t, o);\r
+\r
+                       if (o.format != 'raw' && t.settings.cleanup) {\r
+                               o.getInner = true;\r
+                               h = t.serializer.serialize(t.getBody(), o);\r
+                       } else\r
+                               h = t.getBody().innerHTML;\r
+\r
+                       h = h.replace(/^\s*|\s*$/g, '');\r
+                       o = {content : h};\r
+                       t.onGetContent.dispatch(t, o);\r
+\r
+                       return o.content;\r
+               },\r
+\r
+               isDirty : function() {\r
+                       var t = this;\r
+\r
+                       return tinymce.trim(t.startContent) != tinymce.trim(t.getContent({format : 'raw', no_events : 1})) && !t.isNotDirty;\r
+               },\r
+\r
+               getContainer : function() {\r
+                       var t = this;\r
+\r
+                       if (!t.container)\r
+                               t.container = DOM.get(t.editorContainer || t.id + '_parent');\r
+\r
+                       return t.container;\r
+               },\r
+\r
+               getContentAreaContainer : function() {\r
+                       return this.contentAreaContainer;\r
+               },\r
+\r
+               getElement : function() {\r
+                       return DOM.get(this.settings.content_element || this.id);\r
+               },\r
+\r
+               getWin : function() {\r
+                       var t = this, e;\r
+\r
+                       if (!t.contentWindow) {\r
+                               e = DOM.get(t.id + "_ifr");\r
+\r
+                               if (e)\r
+                                       t.contentWindow = e.contentWindow;\r
+                       }\r
+\r
+                       return t.contentWindow;\r
+               },\r
+\r
+               getDoc : function() {\r
+                       var t = this, w;\r
+\r
+                       if (!t.contentDocument) {\r
+                               w = t.getWin();\r
+\r
+                               if (w)\r
+                                       t.contentDocument = w.document;\r
+                       }\r
+\r
+                       return t.contentDocument;\r
+               },\r
+\r
+               getBody : function() {\r
+                       return this.bodyElement || this.getDoc().body;\r
+               },\r
+\r
+               convertURL : function(u, n, e) {\r
+                       var t = this, s = t.settings;\r
+\r
+                       // Use callback instead\r
+                       if (s.urlconverter_callback)\r
+                               return t.execCallback('urlconverter_callback', u, e, true, n);\r
+\r
+                       // Don't convert link href since thats the CSS files that gets loaded into the editor also skip local file URLs\r
+                       if (!s.convert_urls || (e && e.nodeName == 'LINK') || u.indexOf('file:') === 0)\r
+                               return u;\r
+\r
+                       // Convert to relative\r
+                       if (s.relative_urls)\r
+                               return t.documentBaseURI.toRelative(u);\r
+\r
+                       // Convert to absolute\r
+                       u = t.documentBaseURI.toAbsolute(u, s.remove_script_host);\r
+\r
+                       return u;\r
+               },\r
+\r
+               addVisual : function(e) {\r
+                       var t = this, s = t.settings;\r
+\r
+                       e = e || t.getBody();\r
+\r
+                       if (!is(t.hasVisual))\r
+                               t.hasVisual = s.visual;\r
+\r
+                       each(t.dom.select('table,a', e), function(e) {\r
+                               var v;\r
+\r
+                               switch (e.nodeName) {\r
+                                       case 'TABLE':\r
+                                               v = t.dom.getAttrib(e, 'border');\r
+\r
+                                               if (!v || v == '0') {\r
+                                                       if (t.hasVisual)\r
+                                                               t.dom.addClass(e, s.visual_table_class);\r
+                                                       else\r
+                                                               t.dom.removeClass(e, s.visual_table_class);\r
+                                               }\r
+\r
+                                               return;\r
+\r
+                                       case 'A':\r
+                                               v = t.dom.getAttrib(e, 'name');\r
+\r
+                                               if (v) {\r
+                                                       if (t.hasVisual)\r
+                                                               t.dom.addClass(e, 'mceItemAnchor');\r
+                                                       else\r
+                                                               t.dom.removeClass(e, 'mceItemAnchor');\r
+                                               }\r
+\r
+                                               return;\r
+                               }\r
+                       });\r
+\r
+                       t.onVisualAid.dispatch(t, e, t.hasVisual);\r
+               },\r
+\r
+               remove : function() {\r
+                       var t = this, e = t.getContainer();\r
+\r
+                       t.removed = 1; // Cancels post remove event execution\r
+                       t.hide();\r
+\r
+                       t.execCallback('remove_instance_callback', t);\r
+                       t.onRemove.dispatch(t);\r
+\r
+                       // Clear all execCommand listeners this is required to avoid errors if the editor was removed inside another command\r
+                       t.onExecCommand.listeners = [];\r
+\r
+                       EditorManager.remove(t);\r
+                       DOM.remove(e);\r
+               },\r
+\r
+               destroy : function(s) {\r
+                       var t = this;\r
+\r
+                       // One time is enough\r
+                       if (t.destroyed)\r
+                               return;\r
+\r
+                       if (!s) {\r
+                               tinymce.removeUnload(t.destroy);\r
+                               tinyMCE.onBeforeUnload.remove(t._beforeUnload);\r
+\r
+                               // Manual destroy\r
+                               if (t.theme.destroy)\r
+                                       t.theme.destroy();\r
+\r
+                               // Destroy controls, selection and dom\r
+                               t.controlManager.destroy();\r
+                               t.selection.destroy();\r
+                               t.dom.destroy();\r
+\r
+                               // Remove all events\r
+\r
+                               // Don't clear the window or document if content editable\r
+                               // is enabled since other instances might still be present\r
+                               if (!t.settings.content_editable) {\r
+                                       Event.clear(t.getWin());\r
+                                       Event.clear(t.getDoc());\r
+                               }\r
+\r
+                               Event.clear(t.getBody());\r
+                               Event.clear(t.formElement);\r
+                       }\r
+\r
+                       if (t.formElement) {\r
+                               t.formElement.submit = t.formElement._mceOldSubmit;\r
+                               t.formElement._mceOldSubmit = null;\r
+                       }\r
+\r
+                       t.contentAreaContainer = t.formElement = t.container = t.settings.content_element = t.bodyElement = t.contentDocument = t.contentWindow = null;\r
+\r
+                       if (t.selection)\r
+                               t.selection = t.selection.win = t.selection.dom = t.selection.dom.doc = null;\r
+\r
+                       t.destroyed = 1;\r
+               },\r
+\r
+               // Internal functions\r
+\r
+               _addEvents : function() {\r
+                       // 'focus', 'blur', 'dblclick', 'beforedeactivate', submit, reset\r
+                       var t = this, i, s = t.settings, lo = {\r
+                               mouseup : 'onMouseUp',\r
+                               mousedown : 'onMouseDown',\r
+                               click : 'onClick',\r
+                               keyup : 'onKeyUp',\r
+                               keydown : 'onKeyDown',\r
+                               keypress : 'onKeyPress',\r
+                               submit : 'onSubmit',\r
+                               reset : 'onReset',\r
+                               contextmenu : 'onContextMenu',\r
+                               dblclick : 'onDblClick',\r
+                               paste : 'onPaste' // Doesn't work in all browsers yet\r
+                       };\r
+\r
+                       function eventHandler(e, o) {\r
+                               var ty = e.type;\r
+\r
+                               // Don't fire events when it's removed\r
+                               if (t.removed)\r
+                                       return;\r
+\r
+                               // Generic event handler\r
+                               if (t.onEvent.dispatch(t, e, o) !== false) {\r
+                                       // Specific event handler\r
+                                       t[lo[e.fakeType || e.type]].dispatch(t, e, o);\r
+                               }\r
+                       };\r
+\r
+                       // Add DOM events\r
+                       each(lo, function(v, k) {\r
+                               switch (k) {\r
+                                       case 'contextmenu':\r
+                                               if (tinymce.isOpera) {\r
+                                                       // Fake contextmenu on Opera\r
+                                                       Event.add(t.getDoc(), 'mousedown', function(e) {\r
+                                                               if (e.ctrlKey) {\r
+                                                                       e.fakeType = 'contextmenu';\r
+                                                                       eventHandler(e);\r
+                                                               }\r
+                                                       });\r
+                                               } else\r
+                                                       Event.add(t.getDoc(), k, eventHandler);\r
+                                               break;\r
+\r
+                                       case 'paste':\r
+                                               Event.add(t.getBody(), k, function(e) {\r
+                                                       var tx, h, el, r;\r
+\r
+                                                       // Get plain text data\r
+                                                       if (e.clipboardData)\r
+                                                               tx = e.clipboardData.getData('text/plain');\r
+                                                       else if (tinymce.isIE)\r
+                                                               tx = t.getWin().clipboardData.getData('Text');\r
+\r
+                                                       // Get HTML data\r
+                                                       /*if (tinymce.isIE) {\r
+                                                               el = DOM.add(DOM.doc.body, 'div', {style : 'visibility:hidden;overflow:hidden;position:absolute;width:1px;height:1px'});\r
+                                                               r = DOM.doc.body.createTextRange();\r
+                                                               r.moveToElementText(el);\r
+                                                               r.execCommand('Paste');\r
+                                                               h = el.innerHTML;\r
+                                                               DOM.remove(el);\r
+                                                       }*/\r
+\r
+                                                       eventHandler(e, {text : tx, html : h});\r
+                                               });\r
+                                               break;\r
+\r
+                                       case 'submit':\r
+                                       case 'reset':\r
+                                               Event.add(t.getElement().form || DOM.getParent(t.id, 'form'), k, eventHandler);\r
+                                               break;\r
+\r
+                                       default:\r
+                                               Event.add(s.content_editable ? t.getBody() : t.getDoc(), k, eventHandler);\r
+                               }\r
+                       });\r
+\r
+                       Event.add(s.content_editable ? t.getBody() : (isGecko ? t.getDoc() : t.getWin()), 'focus', function(e) {\r
+                               t.focus(true);\r
+                       });\r
+\r
+                       \r
+                       // Fixes bug where a specified document_base_uri could result in broken images\r
+                       // This will also fix drag drop of images in Gecko\r
+                       if (tinymce.isGecko) {\r
+                               // Convert all images to absolute URLs\r
+/*                             t.onSetContent.add(function(ed, o) {\r
+                                       each(ed.dom.select('img'), function(e) {\r
+                                               var v;\r
+\r
+                                               if (v = e.getAttribute('mce_src'))\r
+                                                       e.src = t.documentBaseURI.toAbsolute(v);\r
+                                       })\r
+                               });*/\r
+\r
+                               Event.add(t.getDoc(), 'DOMNodeInserted', function(e) {\r
+                                       var v;\r
+\r
+                                       e = e.target;\r
+\r
+                                       if (e.nodeType === 1 && e.nodeName === 'IMG' && (v = e.getAttribute('mce_src')))\r
+                                               e.src = t.documentBaseURI.toAbsolute(v);\r
+                               });\r
+                       }\r
+\r
+                       // Set various midas options in Gecko\r
+                       if (isGecko) {\r
+                               function setOpts() {\r
+                                       var t = this, d = t.getDoc(), s = t.settings;\r
+\r
+                                       if (isGecko) {\r
+                                               if (t._isHidden()) {\r
+                                                       try {\r
+                                                               if (!s.content_editable)\r
+                                                                       d.designMode = 'On';\r
+                                                       } catch (ex) {\r
+                                                               // Fails if it's hidden\r
+                                                       }\r
+                                               }\r
+\r
+                                               try {\r
+                                                       // Try new Gecko method\r
+                                                       d.execCommand("styleWithCSS", 0, false);\r
+                                               } catch (ex) {\r
+                                                       // Use old method\r
+                                                       if (!t._isHidden())\r
+                                                               d.execCommand("useCSS", 0, true);\r
+                                               }\r
+\r
+                                               if (!s.table_inline_editing)\r
+                                                       try {d.execCommand('enableInlineTableEditing', false, false);} catch (ex) {}\r
+\r
+                                               if (!s.object_resizing)\r
+                                                       try {d.execCommand('enableObjectResizing', false, false);} catch (ex) {}\r
+                                       }\r
+                               };\r
+\r
+                               t.onBeforeExecCommand.add(setOpts);\r
+                               t.onMouseDown.add(setOpts);\r
+                       }\r
+\r
+                       // Add node change handlers\r
+                       t.onMouseUp.add(t.nodeChanged);\r
+                       t.onClick.add(t.nodeChanged);\r
+                       t.onKeyUp.add(function(ed, e) {\r
+                               if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45 || e.keyCode == 46 || e.keyCode == 8 || e.ctrlKey)\r
+                                       t.nodeChanged();\r
+                       });\r
+\r
+                       // Add reset handler\r
+                       t.onReset.add(function() {\r
+                               t.setContent(t.startContent, {format : 'raw'});\r
+                       });\r
+\r
+                       if (t.getParam('tab_focus')) {\r
+                               function tabCancel(ed, e) {\r
+                                       if (e.keyCode === 9)\r
+                                               return Event.cancel(e);\r
+                               };\r
+\r
+                               function tabHandler(ed, e) {\r
+                                       var x, i, f, el, v;\r
+\r
+                                       function find(d) {\r
+                                               f = DOM.getParent(ed.id, 'form');\r
+                                               el = f.elements;\r
+\r
+                                               if (f) {\r
+                                                       each(el, function(e, i) {\r
+                                                               if (e.id == ed.id) {\r
+                                                                       x = i;\r
+                                                                       return false;\r
+                                                               }\r
+                                                       });\r
+\r
+                                                       if (d > 0) {\r
+                                                               for (i = x + 1; i < el.length; i++) {\r
+                                                                       if (el[i].type != 'hidden')\r
+                                                                               return el[i];\r
+                                                               }\r
+                                                       } else {\r
+                                                               for (i = x - 1; i >= 0; i--) {\r
+                                                                       if (el[i].type != 'hidden')\r
+                                                                               return el[i];\r
+                                                               }\r
+                                                       }\r
+                                               }\r
+\r
+                                               return null;\r
+                                       };\r
+\r
+                                       if (e.keyCode === 9) {\r
+                                               v = explode(ed.getParam('tab_focus'));\r
+\r
+                                               if (v.length == 1) {\r
+                                                       v[1] = v[0];\r
+                                                       v[0] = ':prev';\r
+                                               }\r
+\r
+                                               // Find element to focus\r
+                                               if (e.shiftKey) {\r
+                                                       if (v[0] == ':prev')\r
+                                                               el = find(-1);\r
+                                                       else\r
+                                                               el = DOM.get(v[0]);\r
+                                               } else {\r
+                                                       if (v[1] == ':next')\r
+                                                               el = find(1);\r
+                                                       else\r
+                                                               el = DOM.get(v[1]);\r
+                                               }\r
+\r
+                                               if (el) {\r
+                                                       if (ed = EditorManager.get(el.id || el.name))\r
+                                                               ed.focus();\r
+                                                       else\r
+                                                               window.setTimeout(function() {window.focus();el.focus();}, 10);\r
+\r
+                                                       return Event.cancel(e);\r
+                                               }\r
+                                       }\r
+                               };\r
+\r
+                               t.onKeyUp.add(tabCancel);\r
+\r
+                               if (isGecko) {\r
+                                       t.onKeyPress.add(tabHandler);\r
+                                       t.onKeyDown.add(tabCancel);\r
+                               } else\r
+                                       t.onKeyDown.add(tabHandler);\r
+                       }\r
+\r
+                       // Add shortcuts\r
+                       if (s.custom_shortcuts) {\r
+                               if (s.custom_undo_redo_keyboard_shortcuts) {\r
+                                       t.addShortcut('ctrl+z', t.getLang('undo_desc'), 'Undo');\r
+                                       t.addShortcut('ctrl+y', t.getLang('redo_desc'), 'Redo');\r
+                               }\r
+\r
+                               // Add default shortcuts for gecko\r
+                               if (isGecko) {\r
+                                       t.addShortcut('ctrl+b', t.getLang('bold_desc'), 'Bold');\r
+                                       t.addShortcut('ctrl+i', t.getLang('italic_desc'), 'Italic');\r
+                                       t.addShortcut('ctrl+u', t.getLang('underline_desc'), 'Underline');\r
+                               }\r
+\r
+                               // BlockFormat shortcuts keys\r
+                               for (i=1; i<=6; i++)\r
+                                       t.addShortcut('ctrl+' + i, '', ['FormatBlock', false, '<h' + i + '>']);\r
+\r
+                               t.addShortcut('ctrl+7', '', ['FormatBlock', false, '<p>']);\r
+                               t.addShortcut('ctrl+8', '', ['FormatBlock', false, '<div>']);\r
+                               t.addShortcut('ctrl+9', '', ['FormatBlock', false, '<address>']);\r
+\r
+                               function find(e) {\r
+                                       var v = null;\r
+\r
+                                       if (!e.altKey && !e.ctrlKey && !e.metaKey)\r
+                                               return v;\r
+\r
+                                       each(t.shortcuts, function(o) {\r
+                                               if (o.ctrl != e.ctrlKey && (!tinymce.isMac || o.ctrl == e.metaKey))\r
+                                                       return;\r
+\r
+                                               if (o.alt != e.altKey)\r
+                                                       return;\r
+\r
+                                               if (o.shift != e.shiftKey)\r
+                                                       return;\r
+\r
+                                               if (e.keyCode == o.keyCode || (e.charCode && e.charCode == o.charCode)) {\r
+                                                       v = o;\r
+                                                       return false;\r
+                                               }\r
+                                       });\r
+\r
+                                       return v;\r
+                               };\r
+\r
+                               t.onKeyUp.add(function(ed, e) {\r
+                                       var o = find(e);\r
+\r
+                                       if (o)\r
+                                               return Event.cancel(e);\r
+                               });\r
+\r
+                               t.onKeyPress.add(function(ed, e) {\r
+                                       var o = find(e);\r
+\r
+                                       if (o)\r
+                                               return Event.cancel(e);\r
+                               });\r
+\r
+                               t.onKeyDown.add(function(ed, e) {\r
+                                       var o = find(e);\r
+\r
+                                       if (o) {\r
+                                               o.func.call(o.scope);\r
+                                               return Event.cancel(e);\r
+                                       }\r
+                               });\r
+                       }\r
+\r
+                       if (tinymce.isIE) {\r
+                               // Fix so resize will only update the width and height attributes not the styles of an image\r
+                               // It will also block mceItemNoResize items\r
+                               Event.add(t.getDoc(), 'controlselect', function(e) {\r
+                                       var re = t.resizeInfo, cb;\r
+\r
+                                       e = e.target;\r
+\r
+                                       // Don't do this action for non image elements\r
+                                       if (e.nodeName !== 'IMG')\r
+                                               return;\r
+\r
+                                       if (re)\r
+                                               Event.remove(re.node, re.ev, re.cb);\r
+\r
+                                       if (!t.dom.hasClass(e, 'mceItemNoResize')) {\r
+                                               ev = 'resizeend';\r
+                                               cb = Event.add(e, ev, function(e) {\r
+                                                       var v;\r
+\r
+                                                       e = e.target;\r
+\r
+                                                       if (v = t.dom.getStyle(e, 'width')) {\r
+                                                               t.dom.setAttrib(e, 'width', v.replace(/[^0-9%]+/g, ''));\r
+                                                               t.dom.setStyle(e, 'width', '');\r
+                                                       }\r
+\r
+                                                       if (v = t.dom.getStyle(e, 'height')) {\r
+                                                               t.dom.setAttrib(e, 'height', v.replace(/[^0-9%]+/g, ''));\r
+                                                               t.dom.setStyle(e, 'height', '');\r
+                                                       }\r
+                                               });\r
+                                       } else {\r
+                                               ev = 'resizestart';\r
+                                               cb = Event.add(e, 'resizestart', Event.cancel, Event);\r
+                                       }\r
+\r
+                                       re = t.resizeInfo = {\r
+                                               node : e,\r
+                                               ev : ev,\r
+                                               cb : cb\r
+                                       };\r
+                               });\r
+\r
+                               t.onKeyDown.add(function(ed, e) {\r
+                                       switch (e.keyCode) {\r
+                                               case 8:\r
+                                                       // Fix IE control + backspace browser bug\r
+                                                       if (t.selection.getRng().item) {\r
+                                                               t.selection.getRng().item(0).removeNode();\r
+                                                               return Event.cancel(e);\r
+                                                       }\r
+                                       }\r
+                               });\r
+                       }\r
+\r
+                       if (tinymce.isOpera) {\r
+                               t.onClick.add(function(ed, e) {\r
+                                       Event.prevent(e);\r
+                               });\r
+                       }\r
+\r
+                       // Add custom undo/redo handlers\r
+                       if (s.custom_undo_redo) {\r
+                               function addUndo() {\r
+                                       t.undoManager.typing = 0;\r
+                                       t.undoManager.add();\r
+                               };\r
+\r
+                               // Add undo level on editor blur\r
+                               if (tinymce.isIE) {\r
+                                       Event.add(t.getWin(), 'blur', function(e) {\r
+                                               var n;\r
+\r
+                                               // Check added for fullscreen bug\r
+                                               if (t.selection) {\r
+                                                       n = t.selection.getNode();\r
+\r
+                                                       // Add undo level is selection was lost to another document\r
+                                                       if (!t.removed && n.ownerDocument && n.ownerDocument != t.getDoc())\r
+                                                               addUndo();\r
+                                               }\r
+                                       });\r
+                               } else {\r
+                                       Event.add(t.getDoc(), 'blur', function() {\r
+                                               if (t.selection && !t.removed)\r
+                                                       addUndo();\r
+                                       });\r
+                               }\r
+\r
+                               t.onMouseDown.add(addUndo);\r
+\r
+                               t.onKeyUp.add(function(ed, e) {\r
+                                       if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45 || e.ctrlKey) {\r
+                                               t.undoManager.typing = 0;\r
+                                               t.undoManager.add();\r
+                                       }\r
+                               });\r
+\r
+                               t.onKeyDown.add(function(ed, e) {\r
+                                       // Is caracter positon keys\r
+                                       if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) {\r
+                                               if (t.undoManager.typing) {\r
+                                                       t.undoManager.add();\r
+                                                       t.undoManager.typing = 0;\r
+                                               }\r
+\r
+                                               return;\r
+                                       }\r
+\r
+                                       if (!t.undoManager.typing) {\r
+                                               t.undoManager.add();\r
+                                               t.undoManager.typing = 1;\r
+                                       }\r
+                               });\r
+                       }\r
+               },\r
+\r
+               _convertInlineElements : function() {\r
+                       var t = this, s = t.settings, dom = t.dom, v, e, na, st, sp;\r
+\r
+                       function convert(ed, o) {\r
+                               if (!s.inline_styles)\r
+                                       return;\r
+\r
+                               if (o.get) {\r
+                                       each(t.dom.select('table,u,strike', o.node), function(n) {\r
+                                               switch (n.nodeName) {\r
+                                                       case 'TABLE':\r
+                                                               if (v = dom.getAttrib(n, 'height')) {\r
+                                                                       dom.setStyle(n, 'height', v);\r
+                                                                       dom.setAttrib(n, 'height', '');\r
+                                                               }\r
+                                                               break;\r
+\r
+                                                       case 'U':\r
+                                                       case 'STRIKE':\r
+                                                               //sp = dom.create('span', {style : dom.getAttrib(n, 'style')});\r
+                                                               n.style.textDecoration = n.nodeName == 'U' ? 'underline' : 'line-through';\r
+                                                               dom.setAttrib(n, 'mce_style', '');\r
+                                                               dom.setAttrib(n, 'mce_name', 'span');\r
+                                                               break;\r
+                                               }\r
+                                       });\r
+                               } else if (o.set) {\r
+                                       each(t.dom.select('table,span', o.node).reverse(), function(n) {\r
+                                               if (n.nodeName == 'TABLE') {\r
+                                                       if (v = dom.getStyle(n, 'height'))\r
+                                                               dom.setAttrib(n, 'height', v.replace(/[^0-9%]+/g, ''));\r
+                                               } else {\r
+                                                       // Convert spans to elements\r
+                                                       if (n.style.textDecoration == 'underline')\r
+                                                               na = 'u';\r
+                                                       else if (n.style.textDecoration == 'line-through')\r
+                                                               na = 'strike';\r
+                                                       else\r
+                                                               na = '';\r
+\r
+                                                       if (na) {\r
+                                                               n.style.textDecoration = '';\r
+                                                               dom.setAttrib(n, 'mce_style', '');\r
+\r
+                                                               e = dom.create(na, {\r
+                                                                       style : dom.getAttrib(n, 'style')\r
+                                                               });\r
+\r
+                                                               dom.replace(e, n, 1);\r
+                                                       }\r
+                                               }\r
+                                       });\r
+                               }\r
+                       };\r
+\r
+                       t.onPreProcess.add(convert);\r
+\r
+                       if (!s.cleanup_on_startup) {\r
+                               t.onSetContent.add(function(ed, o) {\r
+                                       if (o.initial)\r
+                                               convert(t, {node : t.getBody(), set : 1});\r
+                               });\r
+                       }\r
+               },\r
+\r
+               _convertFonts : function() {\r
+                       var t = this, s = t.settings, dom = t.dom, fz, fzn, sl, cl;\r
+\r
+                       // No need\r
+                       if (!s.inline_styles)\r
+                               return;\r
+\r
+                       // Font pt values and font size names\r
+                       fz = [8, 10, 12, 14, 18, 24, 36];\r
+                       fzn = ['xx-small', 'x-small','small','medium','large','x-large', 'xx-large'];\r
+\r
+                       if (sl = s.font_size_style_values)\r
+                               sl = explode(sl);\r
+\r
+                       if (cl = s.font_size_classes)\r
+                               cl = explode(cl);\r
+\r
+                       function convertToFonts(no) {\r
+                               var n, f, nl, x, i, v, st;\r
+\r
+                               // Convert spans to fonts on non WebKit browsers\r
+                               if (tinymce.isWebKit || !s.inline_styles)\r
+                                       return;\r
+\r
+                               nl = t.dom.select('span', no);\r
+                               for (x = nl.length - 1; x >= 0; x--) {\r
+                                       n = nl[x];\r
+\r
+                                       f = dom.create('font', {\r
+                                               color : dom.toHex(dom.getStyle(n, 'color')),\r
+                                               face : dom.getStyle(n, 'fontFamily'),\r
+                                               style : dom.getAttrib(n, 'style'),\r
+                                               'class' : dom.getAttrib(n, 'class')\r
+                                       });\r
+\r
+                                       // Clear color and font family\r
+                                       st = f.style;\r
+                                       if (st.color || st.fontFamily) {\r
+                                               st.color = st.fontFamily = '';\r
+                                               dom.setAttrib(f, 'mce_style', ''); // Remove cached style data\r
+                                       }\r
+\r
+                                       if (sl) {\r
+                                               i = inArray(sl, dom.getStyle(n, 'fontSize'));\r
+\r
+                                               if (i != -1) {\r
+                                                       dom.setAttrib(f, 'size', '' + (i + 1 || 1));\r
+                                                       f.style.fontSize = '';\r
+                                               }\r
+                                       } else if (cl) {\r
+                                               i = inArray(cl, dom.getAttrib(n, 'class'));\r
+                                               v = dom.getStyle(n, 'fontSize');\r
+\r
+                                               if (i == -1 && v.indexOf('pt') > 0)\r
+                                                       i = inArray(fz, parseInt(v));\r
+\r
+                                               if (i == -1)\r
+                                                       i = inArray(fzn, v);\r
+\r
+                                               if (i != -1) {\r
+                                                       dom.setAttrib(f, 'size', '' + (i + 1 || 1));\r
+                                                       f.style.fontSize = '';\r
+                                               }\r
+                                       }\r
+\r
+                                       if (f.color || f.face || f.size) {\r
+                                               f.style.fontFamily = '';\r
+                                               dom.setAttrib(f, 'mce_style', '');\r
+                                               dom.replace(f, n, 1);\r
+                                       }\r
+\r
+                                       f = n = null;\r
+                               }\r
+                       };\r
+\r
+                       // Run on setup\r
+                       t.onSetContent.add(function(ed, o) {\r
+                               convertToFonts(ed.getBody());\r
+                       });\r
+\r
+                       // Run on cleanup\r
+                       t.onPreProcess.add(function(ed, o) {\r
+                               var n, sp, nl, x;\r
+\r
+                               // Keep unit tests happy\r
+                               if (!s.inline_styles)\r
+                                       return;\r
+\r
+                               if (o.get) {\r
+                                       nl = t.dom.select('font', o.node);\r
+                                       for (x = nl.length - 1; x >= 0; x--) {\r
+                                               n = nl[x];\r
+\r
+                                               sp = dom.create('span', {\r
+                                                       style : dom.getAttrib(n, 'style'),\r
+                                                       'class' : dom.getAttrib(n, 'class')\r
+                                               });\r
+\r
+                                               dom.setStyles(sp, {\r
+                                                       fontFamily : dom.getAttrib(n, 'face'),\r
+                                                       color : dom.getAttrib(n, 'color'),\r
+                                                       backgroundColor : n.style.backgroundColor\r
+                                               });\r
+\r
+                                               if (n.size) {\r
+                                                       if (sl)\r
+                                                               dom.setStyle(sp, 'fontSize', sl[parseInt(n.size) - 1]);\r
+                                                       else\r
+                                                               dom.setAttrib(sp, 'class', cl[parseInt(n.size) - 1]);\r
+                                               }\r
+\r
+                                               dom.setAttrib(sp, 'mce_style', '');\r
+                                               dom.replace(sp, n, 1);\r
+                                       }\r
+                               }\r
+                       });\r
+               },\r
+\r
+               _isHidden : function() {\r
+                       var s;\r
+\r
+                       if (!isGecko)\r
+                               return 0;\r
+\r
+                       // Weird, wheres that cursor selection?\r
+                       s = this.selection.getSel();\r
+                       return (!s || !s.rangeCount || s.rangeCount == 0);\r
+               },\r
+\r
+               // Fix for bug #1867292\r
+               _fixNesting : function(s) {\r
+                       var d = [], i;\r
+\r
+                       s = s.replace(/<(\/)?([^\s>]+)[^>]*?>/g, function(a, b, c) {\r
+                               var e;\r
+\r
+                               // Handle end element\r
+                               if (b === '/') {\r
+                                       if (!d.length)\r
+                                               return '';\r
+\r
+                                       if (c !== d[d.length - 1].tag) {\r
+                                               for (i=d.length - 1; i>=0; i--) {\r
+                                                       if (d[i].tag === c) {\r
+                                                               d[i].close = 1;\r
+                                                               break;\r
+                                                       }\r
+                                               }\r
+\r
+                                               return '';\r
+                                       } else {\r
+                                               d.pop();\r
+\r
+                                               if (d.length && d[d.length - 1].close) {\r
+                                                       a = a + '</' + d[d.length - 1].tag + '>';\r
+                                                       d.pop();\r
+                                               }\r
+                                       }\r
+                               } else {\r
+                                       // Ignore these\r
+                                       if (/^(br|hr|input|meta|img|link|param)$/i.test(c))\r
+                                               return a;\r
+\r
+                                       // Ignore closed ones\r
+                                       if (/\/>$/.test(a))\r
+                                               return a;\r
+\r
+                                       d.push({tag : c}); // Push start element\r
+                               }\r
+\r
+                               return a;\r
+                       });\r
+\r
+                       // End all open tags\r
+                       for (i=d.length - 1; i>=0; i--)\r
+                               s += '</' + d[i].tag + '>';\r
+\r
+                       return s;\r
+               }\r
+\r
+               });\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/EditorCommands.js */\r
+\r
+(function() {\r
+       var each = tinymce.each, isIE = tinymce.isIE, isGecko = tinymce.isGecko, isOpera = tinymce.isOpera, isWebKit = tinymce.isWebKit;\r
+\r
+       tinymce.create('tinymce.EditorCommands', {\r
+               EditorCommands : function(ed) {\r
+                       this.editor = ed;\r
+               },\r
+\r
+               execCommand : function(cmd, ui, val) {\r
+                       var t = this, ed = t.editor, f;\r
+\r
+                       switch (cmd) {\r
+                               case 'Cut':\r
+                               case 'Copy':\r
+                               case 'Paste':\r
+                                       try {\r
+                                               ed.getDoc().execCommand(cmd, ui, val);\r
+                                       } catch (ex) {\r
+                                               if (isGecko) {\r
+                                                       ed.windowManager.confirm(ed.getLang('clipboard_msg'), function(s) {\r
+                                                               if (s)\r
+                                                                       window.open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', 'mceExternal');\r
+                                                       });\r
+                                               } else\r
+                                                       ed.windowManager.alert(ed.getLang('clipboard_no_support'));\r
+                                       }\r
+\r
+                                       return true;\r
+\r
+                               // Ignore these\r
+                               case 'mceResetDesignMode':\r
+                               case 'mceBeginUndoLevel':\r
+                                       return true;\r
+\r
+                               // Ignore these\r
+                               case 'unlink':\r
+                                       t.UnLink();\r
+                                       return true;\r
+\r
+                               // Bundle these together\r
+                               case 'JustifyLeft':\r
+                               case 'JustifyCenter':\r
+                               case 'JustifyRight':\r
+                               case 'JustifyFull':\r
+                                       t.mceJustify(cmd, cmd.substring(7).toLowerCase());\r
+                                       return true;\r
+\r
+                               case 'mceEndUndoLevel':\r
+                               case 'mceAddUndoLevel':\r
+                                       ed.undoManager.add();\r
+                                       return true;\r
+\r
+                               default:\r
+                                       f = this[cmd];\r
+\r
+                                       if (f) {\r
+                                               f.call(this, ui, val);\r
+                                               return true;\r
+                                       }\r
+                       }\r
+\r
+                       return false;\r
+               },\r
+\r
+               Indent : function() {\r
+                       var ed = this.editor, d = ed.dom, s = ed.selection, e, iv, iu;\r
+\r
+                       // Setup indent level\r
+                       iv = ed.settings.indentation;\r
+                       iu = /[a-z%]+$/i.exec(iv);\r
+                       iv = parseInt(iv);\r
+\r
+                       if (ed.settings.inline_styles && (!this.queryStateInsertUnorderedList() && !this.queryStateInsertOrderedList())) {\r
+                               each(this._getSelectedBlocks(), function(e) {\r
+                                       d.setStyle(e, 'paddingLeft', (parseInt(e.style.paddingLeft || 0) + iv) + iu);\r
+                               });\r
+\r
+                               return;\r
+                       }\r
+\r
+                       ed.getDoc().execCommand('Indent', false, null);\r
+\r
+                       if (isIE) {\r
+                               d.getParent(s.getNode(), function(n) {\r
+                                       if (n.nodeName == 'BLOCKQUOTE') {\r
+                                               n.dir = n.style.cssText = '';\r
+                                       }\r
+                               });\r
+                       }\r
+               },\r
+\r
+               Outdent : function() {\r
+                       var ed = this.editor, d = ed.dom, s = ed.selection, e, v, iv, iu;\r
+\r
+                       // Setup indent level\r
+                       iv = ed.settings.indentation;\r
+                       iu = /[a-z%]+$/i.exec(iv);\r
+                       iv = parseInt(iv);\r
+\r
+                       if (ed.settings.inline_styles && (!this.queryStateInsertUnorderedList() && !this.queryStateInsertOrderedList())) {\r
+                               each(this._getSelectedBlocks(), function(e) {\r
+                                       v = Math.max(0, parseInt(e.style.paddingLeft || 0) - iv);\r
+                                       d.setStyle(e, 'paddingLeft', v ? v + iu : '');\r
+                               });\r
+\r
+                               return;\r
+                       }\r
+\r
+                       ed.getDoc().execCommand('Outdent', false, null);\r
+               },\r
+\r
+               mceSetAttribute : function(u, v) {\r
+                       var ed = this.editor, d = ed.dom, e;\r
+\r
+                       if (e = d.getParent(ed.selection.getNode(), d.isBlock))\r
+                               d.setAttrib(e, v.name, v.value);\r
+               },\r
+\r
+               mceSetContent : function(u, v) {\r
+                       this.editor.setContent(v);\r
+               },\r
+\r
+               mceToggleVisualAid : function() {\r
+                       var ed = this.editor;\r
+\r
+                       ed.hasVisual = !ed.hasVisual;\r
+                       ed.addVisual();\r
+               },\r
+\r
+               mceReplaceContent : function(u, v) {\r
+                       var s = this.editor.selection;\r
+\r
+                       s.setContent(v.replace(/\{\$selection\}/g, s.getContent({format : 'text'})));\r
+               },\r
+\r
+               mceInsertLink : function(u, v) {\r
+                       var ed = this.editor, s = ed.selection, e = ed.dom.getParent(s.getNode(), 'A');\r
+\r
+                       if (tinymce.is(v, 'string'))\r
+                               v = {href : v};\r
+\r
+                       function set(e) {\r
+                               each(v, function(v, k) {\r
+                                       ed.dom.setAttrib(e, k, v);\r
+                               });\r
+                       };\r
+\r
+                       if (!e) {\r
+                               ed.execCommand('CreateLink', false, 'javascript:mctmp(0);');\r
+                               each(ed.dom.select('a'), function(e) {\r
+                                       if (e.href == 'javascript:mctmp(0);')\r
+                                               set(e);\r
+                               });\r
+                       } else {\r
+                               if (v.href)\r
+                                       set(e);\r
+                               else\r
+                                       ed.dom.remove(e, 1);\r
+                       }\r
+               },\r
+\r
+               UnLink : function() {\r
+                       var ed = this.editor, s = ed.selection;\r
+\r
+                       if (s.isCollapsed())\r
+                               s.select(s.getNode());\r
+\r
+                       ed.getDoc().execCommand('unlink', false, null);\r
+                       s.collapse(0);\r
+               },\r
+\r
+               FontName : function(u, v) {\r
+                       var t = this, ed = t.editor, s = ed.selection, e;\r
+\r
+                       if (!v) {\r
+                               if (s.isCollapsed())\r
+                                       s.select(s.getNode());\r
+\r
+                               t.RemoveFormat();\r
+                       } else\r
+                               ed.getDoc().execCommand('FontName', false, v);\r
+               },\r
+\r
+               queryCommandValue : function(c) {\r
+                       var f = this['queryValue' + c];\r
+\r
+                       if (f)\r
+                               return f.call(this, c);\r
+\r
+                       return false;\r
+               },\r
+\r
+               queryCommandState : function(cmd) {\r
+                       var f;\r
+\r
+                       switch (cmd) {\r
+                               // Bundle these together\r
+                               case 'JustifyLeft':\r
+                               case 'JustifyCenter':\r
+                               case 'JustifyRight':\r
+                               case 'JustifyFull':\r
+                                       return this.queryStateJustify(cmd, cmd.substring(7).toLowerCase());\r
+\r
+                               default:\r
+                                       if (f = this['queryState' + cmd])\r
+                                               return f.call(this, cmd);\r
+                       }\r
+\r
+                       return -1;\r
+               },\r
+\r
+               _queryState : function(c) {\r
+                       try {\r
+                               return this.editor.getDoc().queryCommandState(c);\r
+                       } catch (ex) {\r
+                               // Ignore exception\r
+                       }\r
+               },\r
+\r
+               _queryVal : function(c) {\r
+                       try {\r
+                               return this.editor.getDoc().queryCommandValue(c);\r
+                       } catch (ex) {\r
+                               // Ignore exception\r
+                       }\r
+               },\r
+\r
+               queryValueFontSize : function() {\r
+                       var ed = this.editor, v = 0, p;\r
+\r
+                       if (isOpera || isWebKit) {\r
+                               if (p = ed.dom.getParent(ed.selection.getNode(), 'FONT'))\r
+                                       v = p.size;\r
+\r
+                               return v;\r
+                       }\r
+\r
+                       return this._queryVal('FontSize');\r
+               },\r
+\r
+               queryValueFontName : function() {\r
+                       var ed = this.editor, v = 0, p;\r
+\r
+                       if (p = ed.dom.getParent(ed.selection.getNode(), 'FONT'))\r
+                               v = p.face;\r
+\r
+                       if (!v)\r
+                               v = this._queryVal('FontName');\r
+\r
+                       return v;\r
+               },\r
+\r
+               mceJustify : function(c, v) {\r
+                       var ed = this.editor, se = ed.selection, n = se.getNode(), nn = n.nodeName, bl, nb, dom = ed.dom, rm;\r
+\r
+                       if (ed.settings.inline_styles && this.queryStateJustify(c, v))\r
+                               rm = 1;\r
+\r
+                       bl = dom.getParent(n, ed.dom.isBlock);\r
+\r
+                       if (nn == 'IMG') {\r
+                               if (v == 'full')\r
+                                       return;\r
+\r
+                               if (rm) {\r
+                                       if (v == 'center')\r
+                                               dom.setStyle(n.parentNode, 'textAlign', '');\r
+\r
+                                       dom.setStyle(n, 'float', '');\r
+                                       this.mceRepaint();\r
+                                       return;\r
+                               }\r
+\r
+                               if (v == 'center') {\r
+                                       // Do not change table elements\r
+                                       if (/^(TD|TH)$/.test(bl.nodeName))\r
+                                               bl = 0;\r
+\r
+                                       if (!bl || bl.childNodes.length > 1) {\r
+                                               nb = dom.create('p');\r
+                                               nb.appendChild(n.cloneNode(false));\r
+\r
+                                               if (bl)\r
+                                                       dom.insertAfter(nb, bl);\r
+                                               else\r
+                                                       dom.insertAfter(nb, n);\r
+\r
+                                               dom.remove(n);\r
+                                               n = nb.firstChild;\r
+                                               bl = nb;\r
+                                       }\r
+\r
+                                       dom.setStyle(bl, 'textAlign', v);\r
+                                       dom.setStyle(n, 'float', '');\r
+                               } else {\r
+                                       dom.setStyle(n, 'float', v);\r
+                                       dom.setStyle(n.parentNode, 'textAlign', '');\r
+                               }\r
+\r
+                               this.mceRepaint();\r
+                               return;\r
+                       }\r
+\r
+                       // Handle the alignment outselfs, less quirks in all browsers\r
+                       if (ed.settings.inline_styles && ed.settings.forced_root_block) {\r
+                               if (rm)\r
+                                       v = '';\r
+\r
+                               each(this._getSelectedBlocks(dom.getParent(se.getStart(), dom.isBlock), dom.getParent(se.getEnd(), dom.isBlock)), function(e) {\r
+                                       dom.setAttrib(e, 'align', '');\r
+                                       dom.setStyle(e, 'textAlign', v == 'full' ? 'justify' : v);\r
+                               });\r
+\r
+                               return;\r
+                       } else if (!rm)\r
+                               ed.getDoc().execCommand(c, false, null);\r
+\r
+                       if (ed.settings.inline_styles) {\r
+                               if (rm) {\r
+                                       dom.getParent(ed.selection.getNode(), function(n) {\r
+                                               if (n.style && n.style.textAlign)\r
+                                                       dom.setStyle(n, 'textAlign', '');\r
+                                       });\r
+\r
+                                       return;\r
+                               }\r
+\r
+                               each(dom.select('*'), function(n) {\r
+                                       var v = n.align;\r
+\r
+                                       if (v) {\r
+                                               if (v == 'full')\r
+                                                       v = 'justify';\r
+\r
+                                               dom.setStyle(n, 'textAlign', v);\r
+                                               dom.setAttrib(n, 'align', '');\r
+                                       }\r
+                               });\r
+                       }\r
+               },\r
+\r
+               mceSetCSSClass : function(u, v) {\r
+                       this.mceSetStyleInfo(0, {command : 'setattrib', name : 'class', value : v});\r
+               },\r
+\r
+               getSelectedElement : function() {\r
+                       var t = this, ed = t.editor, dom = ed.dom, se = ed.selection, r = se.getRng(), r1, r2, sc, ec, so, eo, e, sp, ep, re;\r
+\r
+                       if (se.isCollapsed() || r.item)\r
+                               return se.getNode();\r
+\r
+                       // Setup regexp\r
+                       re = ed.settings.merge_styles_invalid_parents;\r
+                       if (tinymce.is(re, 'string'))\r
+                               re = new RegExp(re, 'i');\r
+\r
+                       if (isIE) {\r
+                               r1 = r.duplicate();\r
+                               r1.collapse(true);\r
+                               sc = r1.parentElement();\r
+\r
+                               r2 = r.duplicate();\r
+                               r2.collapse(false);\r
+                               ec = r2.parentElement();\r
+\r
+                               if (sc != ec) {\r
+                                       r1.move('character', 1);\r
+                                       sc = r1.parentElement();\r
+                               }\r
+\r
+                               if (sc == ec) {\r
+                                       r1 = r.duplicate();\r
+                                       r1.moveToElementText(sc);\r
+\r
+                                       if (r1.compareEndPoints('StartToStart', r) == 0 && r1.compareEndPoints('EndToEnd', r) == 0)\r
+                                               return re && re.test(sc.nodeName) ? null : sc;\r
+                               }\r
+                       } else {\r
+                               function getParent(n) {\r
+                                       return dom.getParent(n, function(n) {return n.nodeType == 1;});\r
+                               };\r
+\r
+                               sc = r.startContainer;\r
+                               ec = r.endContainer;\r
+                               so = r.startOffset;\r
+                               eo = r.endOffset;\r
+\r
+                               if (!r.collapsed) {\r
+                                       if (sc == ec) {\r
+                                               if (so - eo < 2) {\r
+                                                       if (sc.hasChildNodes()) {\r
+                                                               sp = sc.childNodes[so];\r
+                                                               return re && re.test(sp.nodeName) ? null : sp;\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               if (sc.nodeType != 3 || ec.nodeType != 3)\r
+                                       return null;\r
+\r
+                               if (so == 0) {\r
+                                       sp = getParent(sc);\r
+\r
+                                       if (sp && sp.firstChild != sc)\r
+                                               sp = null;\r
+                               }\r
+\r
+                               if (so == sc.nodeValue.length) {\r
+                                       e = sc.nextSibling;\r
+\r
+                                       if (e && e.nodeType == 1)\r
+                                               sp = sc.nextSibling;\r
+                               }\r
+\r
+                               if (eo == 0) {\r
+                                       e = ec.previousSibling;\r
+\r
+                                       if (e && e.nodeType == 1)\r
+                                               ep = e;\r
+                               }\r
+\r
+                               if (eo == ec.nodeValue.length) {\r
+                                       ep = getParent(ec);\r
+\r
+                                       if (ep && ep.lastChild != ec)\r
+                                               ep = null;\r
+                               }\r
+\r
+                               // Same element\r
+                               if (sp == ep)\r
+                                       return re && sp && re.test(sp.nodeName) ? null : sp;\r
+                       }\r
+\r
+                       return null;\r
+               },\r
+\r
+               InsertHorizontalRule : function() {\r
+                       // Fix for Gecko <hr size="1" /> issue and IE bug rep(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]");\r
+                       if (isGecko || isIE)\r
+                               this.editor.selection.setContent('<hr />');\r
+                       else\r
+                               this.editor.getDoc().execCommand('InsertHorizontalRule', false, '');\r
+               },\r
+\r
+               RemoveFormat : function() {\r
+                       var t = this, ed = t.editor, s = ed.selection, b;\r
+\r
+                       // Safari breaks tables\r
+                       if (isWebKit)\r
+                               s.setContent(s.getContent({format : 'raw'}).replace(/(<(span|b|i|strong|em|strike) [^>]+>|<(span|b|i|strong|em|strike)>|<\/(span|b|i|strong|em|strike)>|)/g, ''), {format : 'raw'});\r
+                       else\r
+                               ed.getDoc().execCommand('RemoveFormat', false, null);\r
+\r
+                       t.mceSetStyleInfo(0, {command : 'removeformat'});\r
+                       ed.addVisual();\r
+               },\r
+\r
+               mceSetStyleInfo : function(u, v) {\r
+                       var t = this, ed = t.editor, d = ed.getDoc(), dom = ed.dom, e, b, s = ed.selection, nn = v.wrapper || 'span', b = s.getBookmark(), re;\r
+\r
+                       function set(n, e) {\r
+                               if (n.nodeType == 1) {\r
+                                       switch (v.command) {\r
+                                               case 'setattrib':\r
+                                                       return dom.setAttrib(n, v.name, v.value);\r
+\r
+                                               case 'setstyle':\r
+                                                       return dom.setStyle(n, v.name, v.value);\r
+\r
+                                               case 'removeformat':\r
+                                                       return dom.setAttrib(n, 'class', '');\r
+                                       }\r
+                               }\r
+                       };\r
+\r
+                       // Setup regexp\r
+                       re = ed.settings.merge_styles_invalid_parents;\r
+                       if (tinymce.is(re, 'string'))\r
+                               re = new RegExp(re, 'i');\r
+\r
+                       // Set style info on selected element\r
+                       if (e = t.getSelectedElement())\r
+                               set(e, 1);\r
+                       else {\r
+                               // Generate wrappers and set styles on them\r
+                               d.execCommand('FontName', false, '__');\r
+                               each(isWebKit ? dom.select('span') : dom.select('font'), function(n) {\r
+                                       var sp, e;\r
+\r
+                                       if (dom.getAttrib(n, 'face') == '__' || n.style.fontFamily === '__') {\r
+                                               sp = dom.create(nn, {mce_new : '1'});\r
+\r
+                                               set(sp);\r
+\r
+                                               each (n.childNodes, function(n) {\r
+                                                       sp.appendChild(n.cloneNode(true));\r
+                                               });\r
+\r
+                                               dom.replace(sp, n);\r
+                                       }\r
+                               });\r
+                       }\r
+\r
+                       // Remove wrappers inside new ones\r
+                       each(dom.select(nn).reverse(), function(n) {\r
+                               var p = n.parentNode;\r
+\r
+                               // Check if it's an old span in a new wrapper\r
+                               if (!dom.getAttrib(n, 'mce_new')) {\r
+                                       // Find new wrapper\r
+                                       p = dom.getParent(n, function(n) {\r
+                                               return n.nodeType == 1 && dom.getAttrib(n, 'mce_new');\r
+                                       });\r
+\r
+                                       if (p)\r
+                                               dom.remove(n, 1);\r
+                               }\r
+                       });\r
+\r
+                       // Merge wrappers with parent wrappers\r
+                       each(dom.select(nn).reverse(), function(n) {\r
+                               var p = n.parentNode;\r
+\r
+                               if (!p || !dom.getAttrib(n, 'mce_new'))\r
+                                       return;\r
+\r
+                               // Has parent of the same type and only child\r
+                               if (p.nodeName == nn.toUpperCase() && p.childNodes.length == 1)\r
+                                       return dom.remove(p, 1);\r
+\r
+                               // Has parent that is more suitable to have the class and only child\r
+                               if (n.nodeType == 1 && (!re || !re.test(p.nodeName)) && p.childNodes.length == 1) {\r
+                                       set(p); // Set style info on parent instead\r
+                                       dom.setAttrib(n, 'class', '');\r
+                               }\r
+                       });\r
+\r
+                       // Remove empty wrappers\r
+                       each(dom.select(nn).reverse(), function(n) {\r
+                               if (dom.getAttrib(n, 'mce_new') || (dom.getAttribs(n).length <= 1 && n.className === '')) {\r
+                                       if (!dom.getAttrib(n, 'class') && !dom.getAttrib(n, 'style'))\r
+                                               return dom.remove(n, 1);\r
+\r
+                                       dom.setAttrib(n, 'mce_new', ''); // Remove mce_new marker\r
+                               }\r
+                       });\r
+\r
+                       s.moveToBookmark(b);\r
+               },\r
+\r
+               queryStateJustify : function(c, v) {\r
+                       var ed = this.editor, n = ed.selection.getNode(), dom = ed.dom;\r
+\r
+                       if (n && n.nodeName == 'IMG') {\r
+                               if (dom.getStyle(n, 'float') == v)\r
+                                       return 1;\r
+\r
+                               return n.parentNode.style.textAlign == v;\r
+                       }\r
+\r
+                       n = dom.getParent(ed.selection.getStart(), function(n) {\r
+                               return n.nodeType == 1 && n.style.textAlign;\r
+                       });\r
+\r
+                       if (v == 'full')\r
+                               v = 'justify';\r
+\r
+                       if (ed.settings.inline_styles)\r
+                               return (n && n.style.textAlign == v);\r
+\r
+                       return this._queryState(c);\r
+               },\r
+\r
+               HiliteColor : function(ui, val) {\r
+                       var t = this, ed = t.editor, d = ed.getDoc();\r
+\r
+                       function set(s) {\r
+                               if (!isGecko)\r
+                                       return;\r
+\r
+                               try {\r
+                                       // Try new Gecko method\r
+                                       d.execCommand("styleWithCSS", 0, s);\r
+                               } catch (ex) {\r
+                                       // Use old\r
+                                       d.execCommand("useCSS", 0, !s);\r
+                               }\r
+                       };\r
+\r
+                       if (isGecko || isOpera) {\r
+                               set(true);\r
+                               d.execCommand('hilitecolor', false, val);\r
+                               set(false);\r
+                       } else\r
+                               d.execCommand('BackColor', false, val);\r
+               },\r
+\r
+               Undo : function() {\r
+                       var ed = this.editor;\r
+\r
+                       if (ed.settings.custom_undo_redo) {\r
+                               ed.undoManager.undo();\r
+                               ed.nodeChanged();\r
+                       } else\r
+                               ed.getDoc().execCommand('Undo', false, null);\r
+               },\r
+\r
+               Redo : function() {\r
+                       var ed = this.editor;\r
+\r
+                       if (ed.settings.custom_undo_redo) {\r
+                               ed.undoManager.redo();\r
+                               ed.nodeChanged();\r
+                       } else\r
+                               ed.getDoc().execCommand('Redo', false, null);\r
+               },\r
+\r
+               FormatBlock : function(ui, val) {\r
+                       var t = this, ed = t.editor;\r
+\r
+                       val = ed.settings.forced_root_block ? (val || '<p>') : val;\r
+\r
+                       if (/^(P|DIV|H[1-6]|ADDRESS|BLOCKQUOTE|PRE)$/.test(ed.selection.getNode().nodeName))\r
+                               t.mceRemoveNode();\r
+\r
+                       if (val.indexOf('<') == -1)\r
+                               val = '<' + val + '>';\r
+\r
+                       if (tinymce.isGecko)\r
+                               val = val.replace(/<(div|blockquote|code|dt|dd|dl|samp)>/gi, '$1');\r
+\r
+                       ed.getDoc().execCommand('FormatBlock', false, val);\r
+               },\r
+\r
+               mceCleanup : function() {\r
+                       var ed = this.editor, s = ed.selection, b = s.getBookmark();\r
+                       ed.setContent(ed.getContent());\r
+                       s.moveToBookmark(b);\r
+               },\r
+\r
+               mceRemoveNode : function(ui, val) {\r
+                       var ed = this.editor, s = ed.selection, b, n = val || s.getNode();\r
+\r
+                       // Make sure that the body node isn't removed\r
+                       if (n == ed.getBody())\r
+                               return;\r
+\r
+                       b = s.getBookmark();\r
+                       ed.dom.remove(n, 1);\r
+                       s.moveToBookmark(b);\r
+                       ed.nodeChanged();\r
+               },\r
+\r
+               mceSelectNodeDepth : function(ui, val) {\r
+                       var ed = this.editor, s = ed.selection, c = 0;\r
+\r
+                       ed.dom.getParent(s.getNode(), function(n) {\r
+                               if (n.nodeType == 1 && c++ == val) {\r
+                                       s.select(n);\r
+                                       ed.nodeChanged();\r
+                                       return false;\r
+                               }\r
+                       }, ed.getBody());\r
+               },\r
+\r
+               mceSelectNode : function(u, v) {\r
+                       this.editor.selection.select(v);\r
+               },\r
+\r
+               mceInsertContent : function(ui, val) {\r
+                       this.editor.selection.setContent(val);\r
+               },\r
+\r
+               mceInsertRawHTML : function(ui, val) {\r
+                       var ed = this.editor;\r
+\r
+                       ed.selection.setContent('tiny_mce_marker');\r
+                       ed.setContent(ed.getContent().replace(/tiny_mce_marker/g, val));\r
+               },\r
+\r
+               mceRepaint : function() {\r
+                       var s, b, e = this.editor;\r
+\r
+                       if (tinymce.isGecko) {\r
+                               try {\r
+                                       s = e.selection;\r
+                                       b = s.getBookmark(true);\r
+\r
+                                       if (s.getSel())\r
+                                               s.getSel().selectAllChildren(e.getBody());\r
+\r
+                                       s.collapse(true);\r
+                                       s.moveToBookmark(b);\r
+                               } catch (ex) {\r
+                                       // Ignore\r
+                               }\r
+                       }\r
+               },\r
+\r
+               queryStateUnderline : function() {\r
+                       var ed = this.editor, n = ed.selection.getNode();\r
+\r
+                       if (n && n.nodeName == 'A')\r
+                               return false;\r
+\r
+                       return this._queryState('Underline');\r
+               },\r
+\r
+               queryStateOutdent : function() {\r
+                       var ed = this.editor, n;\r
+\r
+                       if (ed.settings.inline_styles) {\r
+                               if ((n = ed.dom.getParent(ed.selection.getStart(), ed.dom.isBlock)) && parseInt(n.style.paddingLeft) > 0)\r
+                                       return true;\r
+\r
+                               if ((n = ed.dom.getParent(ed.selection.getEnd(), ed.dom.isBlock)) && parseInt(n.style.paddingLeft) > 0)\r
+                                       return true;\r
+                       } else\r
+                               return !!ed.dom.getParent(ed.selection.getNode(), 'BLOCKQUOTE');\r
+\r
+                       return this.queryStateInsertUnorderedList() || this.queryStateInsertOrderedList();\r
+               },\r
+\r
+               queryStateInsertUnorderedList : function() {\r
+                       return this.editor.dom.getParent(this.editor.selection.getNode(), 'UL');\r
+               },\r
+\r
+               queryStateInsertOrderedList : function() {\r
+                       return this.editor.dom.getParent(this.editor.selection.getNode(), 'OL');\r
+               },\r
+\r
+               queryStatemceBlockQuote : function() {\r
+                       return !!this.editor.dom.getParent(this.editor.selection.getStart(), function(n) {return n.nodeName === 'BLOCKQUOTE';});\r
+               },\r
+\r
+               mceBlockQuote : function() {\r
+                       var t = this, ed = t.editor, s = ed.selection, dom = ed.dom, sb, eb, n, bm, bq, r, bq2, i, nl;\r
+\r
+                       function getBQ(e) {\r
+                               return dom.getParent(e, function(n) {return n.nodeName === 'BLOCKQUOTE';});\r
+                       };\r
+\r
+                       // Get start/end block\r
+                       sb = dom.getParent(s.getStart(), dom.isBlock);\r
+                       eb = dom.getParent(s.getEnd(), dom.isBlock);\r
+\r
+                       // Remove blockquote(s)\r
+                       if (bq = getBQ(sb)) {\r
+                               if (sb != eb || sb.childNodes.length > 1 || (sb.childNodes.length == 1 && sb.firstChild.nodeName != 'BR'))\r
+                                       bm = s.getBookmark();\r
+\r
+                               // Move all elements after the end block into new bq\r
+                               if (getBQ(eb)) {\r
+                                       bq2 = bq.cloneNode(false);\r
+\r
+                                       while (n = eb.nextSibling)\r
+                                               bq2.appendChild(n.parentNode.removeChild(n));\r
+                               }\r
+\r
+                               // Add new bq after\r
+                               if (bq2)\r
+                                       dom.insertAfter(bq2, bq);\r
+\r
+                               // Move all selected blocks after the current bq\r
+                               nl = t._getSelectedBlocks(sb, eb);\r
+                               for (i = nl.length - 1; i >= 0; i--) {\r
+                                       dom.insertAfter(nl[i], bq);\r
+                               }\r
+\r
+                               // Empty bq, then remove it\r
+                               if (/^\s*$/.test(bq.innerHTML))\r
+                                       dom.remove(bq, 1); // Keep children so boomark restoration works correctly\r
+\r
+                               // Empty bq, then remote it\r
+                               if (bq2 && /^\s*$/.test(bq2.innerHTML))\r
+                                       dom.remove(bq2, 1); // Keep children so boomark restoration works correctly\r
+\r
+                               if (!bm) {\r
+                                       // Move caret inside empty block element\r
+                                       if (!isIE) {\r
+                                               r = ed.getDoc().createRange();\r
+                                               r.setStart(sb, 0);\r
+                                               r.setEnd(sb, 0);\r
+                                               s.setRng(r);\r
+                                       } else {\r
+                                               s.select(sb);\r
+                                               s.collapse(0);\r
+\r
+                                               // IE misses the empty block some times element so we must move back the caret\r
+                                               if (dom.getParent(s.getStart(), dom.isBlock) != sb) {\r
+                                                       r = s.getRng();\r
+                                                       r.move('character', -1);\r
+                                                       r.select();\r
+                                               }\r
+                                       }\r
+                               } else\r
+                                       t.editor.selection.moveToBookmark(bm);\r
+\r
+                               return;\r
+                       }\r
+\r
+                       // Since IE can start with a totally empty document we need to add the first bq and paragraph\r
+                       if (isIE && !sb && !eb) {\r
+                               t.editor.getDoc().execCommand('Indent');\r
+                               n = getBQ(s.getNode());\r
+                               n.style.margin = n.dir = ''; // IE adds margin and dir to bq\r
+                               return;\r
+                       }\r
+\r
+                       if (!sb || !eb)\r
+                               return;\r
+\r
+                       // If empty paragraph node then do not use bookmark\r
+                       if (sb != eb || sb.childNodes.length > 1 || (sb.childNodes.length == 1 && sb.firstChild.nodeName != 'BR'))\r
+                               bm = s.getBookmark();\r
+\r
+                       // Move selected block elements into a bq\r
+                       each(t._getSelectedBlocks(getBQ(s.getStart()), getBQ(s.getEnd())), function(e) {\r
+                               // Found existing BQ add to this one\r
+                               if (e.nodeName == 'BLOCKQUOTE' && !bq) {\r
+                                       bq = e;\r
+                                       return;\r
+                               }\r
+\r
+                               // No BQ found, create one\r
+                               if (!bq) {\r
+                                       bq = dom.create('blockquote');\r
+                                       e.parentNode.insertBefore(bq, e);\r
+                               }\r
+\r
+                               // Add children from existing BQ\r
+                               if (e.nodeName == 'BLOCKQUOTE' && bq) {\r
+                                       n = e.firstChild;\r
+\r
+                                       while (n) {\r
+                                               bq.appendChild(n.cloneNode(true));\r
+                                               n = n.nextSibling;\r
+                                       }\r
+\r
+                                       dom.remove(e);\r
+                                       return;\r
+                               }\r
+\r
+                               // Add non BQ element to BQ\r
+                               bq.appendChild(dom.remove(e));\r
+                       });\r
+\r
+                       if (!bm) {\r
+                               // Move caret inside empty block element\r
+                               if (!isIE) {\r
+                                       r = ed.getDoc().createRange();\r
+                                       r.setStart(sb, 0);\r
+                                       r.setEnd(sb, 0);\r
+                                       s.setRng(r);\r
+                               } else {\r
+                                       s.select(sb);\r
+                                       s.collapse(1);\r
+                               }\r
+                       } else\r
+                               s.moveToBookmark(bm);\r
+               },\r
+/*\r
+               _mceBlockQuote : function() {\r
+                       var t = this, s = t.editor.selection, b = s.getBookmark(), bq, dom = t.editor.dom;\r
+\r
+                       function findBQ(e) {\r
+                               return dom.getParent(e, function(n) {return n.nodeName === 'BLOCKQUOTE';});\r
+                       };\r
+\r
+                       // Remove blockquote(s)\r
+                       if (findBQ(s.getStart())) {\r
+                               each(t._getSelectedBlocks(findBQ(s.getStart()), findBQ(s.getEnd())), function(e) {\r
+                                       // Found BQ lets remove it\r
+                                       if (e.nodeName == 'BLOCKQUOTE')\r
+                                               dom.remove(e, 1);\r
+                               });\r
+\r
+                               t.editor.selection.moveToBookmark(b);\r
+                               return;\r
+                       }\r
+\r
+                       each(t._getSelectedBlocks(findBQ(s.getStart()), findBQ(s.getEnd())), function(e) {\r
+                               var n;\r
+\r
+                               // Found existing BQ add to this one\r
+                               if (e.nodeName == 'BLOCKQUOTE' && !bq) {\r
+                                       bq = e;\r
+                                       return;\r
+                               }\r
+\r
+                               // No BQ found, create one\r
+                               if (!bq) {\r
+                                       bq = dom.create('blockquote');\r
+                                       e.parentNode.insertBefore(bq, e);\r
+                               }\r
+\r
+                               // Add children from existing BQ\r
+                               if (e.nodeName == 'BLOCKQUOTE' && bq) {\r
+                                       n = e.firstChild;\r
+\r
+                                       while (n) {\r
+                                               bq.appendChild(n.cloneNode(true));\r
+                                               n = n.nextSibling;\r
+                                       }\r
+\r
+                                       dom.remove(e);\r
+\r
+                                       return;\r
+                               }\r
+\r
+                               // Add non BQ element to BQ\r
+                               bq.appendChild(dom.remove(e));\r
+                       });\r
+\r
+                       t.editor.selection.moveToBookmark(b);\r
+               },\r
+*/\r
+               _getSelectedBlocks : function(st, en) {\r
+                       var ed = this.editor, dom = ed.dom, s = ed.selection, sb, eb, n, bl = [];\r
+\r
+                       sb = dom.getParent(st || s.getStart(), dom.isBlock);\r
+                       eb = dom.getParent(en || s.getEnd(), dom.isBlock);\r
+\r
+                       if (sb)\r
+                               bl.push(sb);\r
+\r
+                       if (sb && eb && sb != eb) {\r
+                               n = sb;\r
+\r
+                               while ((n = n.nextSibling) && n != eb) {\r
+                                       if (dom.isBlock(n))\r
+                                               bl.push(n);\r
+                               }\r
+                       }\r
+\r
+                       if (eb && sb != eb)\r
+                               bl.push(eb);\r
+\r
+                       return bl;\r
+               }\r
+       });\r
+})();\r
+\r
+\r
+/* file:jscripts/tiny_mce/classes/UndoManager.js */\r
+\r
+tinymce.create('tinymce.UndoManager', {\r
+       index : 0,\r
+       data : null,\r
+       typing : 0,\r
+\r
+       UndoManager : function(ed) {\r
+               var t = this, Dispatcher = tinymce.util.Dispatcher;\r
+\r
+               t.editor = ed;\r
+               t.data = [];\r
+               t.onAdd = new Dispatcher(this);\r
+               t.onUndo = new Dispatcher(this);\r
+               t.onRedo = new Dispatcher(this);\r
+       },\r
+\r
+       add : function(l) {\r
+               var t = this, i, ed = t.editor, b, s = ed.settings, la;\r
+\r
+               l = l || {};\r
+               l.content = l.content || ed.getContent({format : 'raw', no_events : 1});\r
+\r
+               // Add undo level if needed\r
+               l.content = l.content.replace(/^\s*|\s*$/g, '');\r
+               la = t.data[t.index > 0 ? t.index - 1 : 0];\r
+               if (!l.initial && la && l.content == la.content)\r
+                       return null;\r
+\r
+               // Time to compress\r
+               if (s.custom_undo_redo_levels) {\r
+                       if (t.data.length > s.custom_undo_redo_levels) {\r
+                               for (i = 0; i < t.data.length - 1; i++)\r
+                                       t.data[i] = t.data[i + 1];\r
+\r
+                               t.data.length--;\r
+                               t.index = t.data.length;\r
+                       }\r
+               }\r
+\r
+               if (s.custom_undo_redo_restore_selection && !l.initial)\r
+                       l.bookmark = b = l.bookmark || ed.selection.getBookmark();\r
+\r
+               if (t.index < t.data.length && t.data[t.index].initial)\r
+                       t.index++;\r
+\r
+               // Only initial marked undo levels should be allowed as first item\r
+               // This to workaround a bug with Firefox and the blur event\r
+               if (t.data.length === 0 && !l.initial)\r
+                       return null;\r
+\r
+               // Add level\r
+               t.data.length = t.index + 1;\r
+               t.data[t.index++] = l;\r
+\r
+               if (l.initial)\r
+                       t.index = 0;\r
+\r
+               // Set initial bookmark use first real undo level\r
+               if (t.data.length == 2 && t.data[0].initial)\r
+                       t.data[0].bookmark = b;\r
+\r
+               t.onAdd.dispatch(t, l);\r
+               ed.isNotDirty = 0;\r
+\r
+               //console.dir(t.data);\r
+\r
+               return l;\r
+       },\r
+\r
+       undo : function() {\r
+               var t = this, ed = t.editor, l = l, i;\r
+\r
+               if (t.typing) {\r
+                       t.add();\r
+                       t.typing = 0;\r
+               }\r
+\r
+               if (t.index > 0) {\r
+                       // If undo on last index then take snapshot\r
+                       if (t.index == t.data.length && t.index > 1) {\r
+                               i = t.index;\r
+                               t.typing = 0;\r
+\r
+                               if (!t.add())\r
+                                       t.index = i;\r
+\r
+                               --t.index;\r
+                       }\r
+\r
+                       l = t.data[--t.index];\r
+                       ed.setContent(l.content, {format : 'raw'});\r
+                       ed.selection.moveToBookmark(l.bookmark);\r
+\r
+                       t.onUndo.dispatch(t, l);\r
+               }\r
+\r
+               return l;\r
+       },\r
+\r
+       redo : function() {\r
+               var t = this, ed = t.editor, l = null;\r
+\r
+               if (t.index < t.data.length - 1) {\r
+                       l = t.data[++t.index];\r
+                       ed.setContent(l.content, {format : 'raw'});\r
+                       ed.selection.moveToBookmark(l.bookmark);\r
+\r
+                       t.onRedo.dispatch(t, l);\r
+               }\r
+\r
+               return l;\r
+       },\r
+\r
+       clear : function() {\r
+               var t = this;\r
+\r
+               t.data = [];\r
+               t.index = 0;\r
+               t.typing = 0;\r
+               t.add({initial : true});\r
+       },\r
+\r
+       hasUndo : function() {\r
+               return this.index != 0 || this.typing;\r
+       },\r
+\r
+       hasRedo : function() {\r
+               return this.index < this.data.length - 1;\r
+       }\r
+\r
+       });\r
+/* file:jscripts/tiny_mce/classes/ForceBlocks.js */\r
+\r
+(function() {\r
+       // Shorten names\r
+       var Event, isIE, isGecko, isOpera, each, extend;\r
+\r
+       Event = tinymce.dom.Event;\r
+       isIE = tinymce.isIE;\r
+       isGecko = tinymce.isGecko;\r
+       isOpera = tinymce.isOpera;\r
+       each = tinymce.each;\r
+       extend = tinymce.extend;\r
+\r
+       tinymce.create('tinymce.ForceBlocks', {\r
+               ForceBlocks : function(ed) {\r
+                       var t = this, s = ed.settings, elm;\r
+\r
+                       t.editor = ed;\r
+                       t.dom = ed.dom;\r
+                       elm = (s.forced_root_block || 'p').toLowerCase();\r
+                       s.element = elm.toUpperCase();\r
+\r
+                       ed.onPreInit.add(t.setup, t);\r
+\r
+                       t.reOpera = new RegExp('(\\u00a0|&#160;|&nbsp;)<\/' + elm + '>', 'gi');\r
+                       t.rePadd = new RegExp('<p( )([^>]+)><\\\/p>|<p( )([^>]+)\\\/>|<p( )([^>]+)>\\s+<\\\/p>|<p><\\\/p>|<p\\\/>|<p>\\s+<\\\/p>'.replace(/p/g, elm), 'gi');\r
+                       t.reNbsp2BR1 = new RegExp('<p( )([^>]+)>[\\s\\u00a0]+<\\\/p>|<p>[\\s\\u00a0]+<\\\/p>'.replace(/p/g, elm), 'gi');\r
+                       t.reNbsp2BR2 = new RegExp('<p( )([^>]+)>(&nbsp;|&#160;)<\\\/p>|<p>(&nbsp;|&#160;)<\\\/p>'.replace(/p/g, elm), 'gi');\r
+                       t.reBR2Nbsp = new RegExp('<p( )([^>]+)>\\s*<br \\\/>\\s*<\\\/p>|<p>\\s*<br \\\/>\\s*<\\\/p>'.replace(/p/g, elm), 'gi');\r
+                       t.reTrailBr = new RegExp('\\s*<br \\/>\\s*<\\\/p>'.replace(/p/g, elm), 'gi');\r
+\r
+                       function padd(ed, o) {\r
+                               if (isOpera)\r
+                                       o.content = o.content.replace(t.reOpera, '</' + elm + '>');\r
+\r
+                               o.content = o.content.replace(t.rePadd, '<' + elm + '$1$2$3$4$5$6>\u00a0</' + elm + '>');\r
+\r
+                               if (!isIE && !isOpera && o.set) {\r
+                                       // Use &nbsp; instead of BR in padded paragraphs\r
+                                       o.content = o.content.replace(t.reNbsp2BR1, '<' + elm + '$1$2><br /></' + elm + '>');\r
+                                       o.content = o.content.replace(t.reNbsp2BR2, '<' + elm + '$1$2><br /></' + elm + '>');\r
+                               } else {\r
+                                       o.content = o.content.replace(t.reBR2Nbsp, '<' + elm + '$1$2>\u00a0</' + elm + '>');\r
+                                       o.content = o.content.replace(t.reTrailBr, '</' + elm + '>');\r
+                               }\r
+                       };\r
+\r
+                       ed.onBeforeSetContent.add(padd);\r
+                       ed.onPostProcess.add(padd);\r
+\r
+                       if (s.forced_root_block) {\r
+                               ed.onInit.add(t.forceRoots, t);\r
+                               ed.onSetContent.add(t.forceRoots, t);\r
+                               ed.onBeforeGetContent.add(t.forceRoots, t);\r
+                       }\r
+               },\r
+\r
+               setup : function() {\r
+                       var t = this, ed = t.editor, s = ed.settings;\r
+\r
+                       // Force root blocks when typing and when getting output\r
+                       if (s.forced_root_block) {\r
+                               ed.onKeyUp.add(t.forceRoots, t);\r
+                               ed.onPreProcess.add(t.forceRoots, t);\r
+                       }\r
+\r
+                       if (s.force_br_newlines) {\r
+                               // Force IE to produce BRs on enter\r
+                               if (isIE) {\r
+                                       ed.onKeyPress.add(function(ed, e) {\r
+                                               var n, s = ed.selection;\r
+\r
+                                               if (e.keyCode == 13 && s.getNode().nodeName != 'LI') {\r
+                                                       s.setContent('<br id="__" /> ', {format : 'raw'});\r
+                                                       n = ed.dom.get('__');\r
+                                                       n.removeAttribute('id');\r
+                                                       s.select(n);\r
+                                                       s.collapse();\r
+                                                       return Event.cancel(e);\r
+                                               }\r
+                                       });\r
+                               }\r
+\r
+                               return;\r
+                       }\r
+\r
+                       if (!isIE && s.force_p_newlines) {\r
+/*                             ed.onPreProcess.add(function(ed, o) {\r
+                                       each(ed.dom.select('br', o.node), function(n) {\r
+                                               var p = n.parentNode;\r
+\r
+                                               // Replace <p><br /></p> with <p>&nbsp;</p>\r
+                                               if (p && p.nodeName == 'p' && (p.childNodes.length == 1 || p.lastChild == n)) {\r
+                                                       p.replaceChild(ed.getDoc().createTextNode('\u00a0'), n);\r
+                                               }\r
+                                       });\r
+                               });*/\r
+\r
+                               ed.onKeyPress.add(function(ed, e) {\r
+                                       if (e.keyCode == 13 && !e.shiftKey) {\r
+                                               if (!t.insertPara(e))\r
+                                                       Event.cancel(e);\r
+                                       }\r
+                               });\r
+\r
+                               if (isGecko) {\r
+                                       ed.onKeyDown.add(function(ed, e) {\r
+                                               if ((e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey)\r
+                                                       t.backspaceDelete(e, e.keyCode == 8);\r
+                                       });\r
+                               }\r
+                       }\r
+\r
+                       function ren(rn, na) {\r
+                               var ne = ed.dom.create(na);\r
+\r
+                               each(rn.attributes, function(a) {\r
+                                       if (a.specified && a.nodeValue)\r
+                                               ne.setAttribute(a.nodeName.toLowerCase(), a.nodeValue);\r
+                               });\r
+\r
+                               each(rn.childNodes, function(n) {\r
+                                       ne.appendChild(n.cloneNode(true));\r
+                               });\r
+\r
+                               rn.parentNode.replaceChild(ne, rn);\r
+\r
+                               return ne;\r
+                       };\r
+\r
+                       // Replaces IE:s auto generated paragraphs with the specified element name\r
+                       if (isIE && s.element != 'P') {\r
+                               ed.onKeyPress.add(function(ed, e) {\r
+                                       t.lastElm = ed.selection.getNode().nodeName;\r
+                               });\r
+\r
+                               ed.onKeyUp.add(function(ed, e) {\r
+                                       var bl, sel = ed.selection, n = sel.getNode(), b = ed.getBody();\r
+\r
+                                       if (b.childNodes.length === 1 && n.nodeName == 'P') {\r
+                                               n = ren(n, s.element);\r
+                                               sel.select(n);\r
+                                               sel.collapse();\r
+                                               ed.nodeChanged();\r
+                                       } else if (e.keyCode == 13 && !e.shiftKey && t.lastElm != 'P') {\r
+                                               bl = ed.dom.getParent(n, 'P');\r
+\r
+                                               if (bl) {\r
+                                                       ren(bl, s.element);\r
+                                                       ed.nodeChanged();\r
+                                               }\r
+                                       }\r
+                               });\r
+                       }\r
+               },\r
+\r
+               find : function(n, t, s) {\r
+                       var ed = this.editor, w = ed.getDoc().createTreeWalker(n, 4, null, false), c = -1;\r
+\r
+                       while (n = w.nextNode()) {\r
+                               c++;\r
+\r
+                               // Index by node\r
+                               if (t == 0 && n == s)\r
+                                       return c;\r
+\r
+                               // Node by index\r
+                               if (t == 1 && c == s)\r
+                                       return n;\r
+                       }\r
+\r
+                       return -1;\r
+               },\r
+\r
+               forceRoots : function(ed, e) {\r
+                       var t = this, ed = t.editor, b = ed.getBody(), d = ed.getDoc(), se = ed.selection, s = se.getSel(), r = se.getRng(), si = -2, ei, so, eo, tr, c = -0xFFFFFF;\r
+                       var nx, bl, bp, sp, le, nl = b.childNodes, i;\r
+\r
+                       // Fix for bug #1863847\r
+                       if (e && e.keyCode == 13)\r
+                               return true;\r
+\r
+                       // Wrap non blocks into blocks\r
+                       for (i = nl.length - 1; i >= 0; i--) {\r
+                               nx = nl[i];\r
+\r
+                               // Is text or non block element\r
+                               if (nx.nodeType == 3 || (!t.dom.isBlock(nx) && nx.nodeType != 8)) {\r
+                                       if (!bl) {\r
+                                               // Create new block but ignore whitespace\r
+                                               if (nx.nodeType != 3 || /[^\s]/g.test(nx.nodeValue)) {\r
+                                                       // Store selection\r
+                                                       if (si == -2 && r) {\r
+                                                               if (!isIE) {\r
+                                                                       so = r.startOffset;\r
+                                                                       eo = r.endOffset;\r
+                                                                       si = t.find(b, 0, r.startContainer);\r
+                                                                       ei = t.find(b, 0, r.endContainer);\r
+                                                               } else {\r
+                                                                       tr = d.body.createTextRange();\r
+                                                                       tr.moveToElementText(b);\r
+                                                                       tr.collapse(1);\r
+                                                                       bp = tr.move('character', c) * -1;\r
+\r
+                                                                       tr = r.duplicate();\r
+                                                                       tr.collapse(1);\r
+                                                                       sp = tr.move('character', c) * -1;\r
+\r
+                                                                       tr = r.duplicate();\r
+                                                                       tr.collapse(0);\r
+                                                                       le = (tr.move('character', c) * -1) - sp;\r
+\r
+                                                                       si = sp - bp;\r
+                                                                       ei = le;\r
+                                                               }\r
+                                                       }\r
+\r
+                                                       bl = ed.dom.create(ed.settings.forced_root_block);\r
+                                                       bl.appendChild(nx.cloneNode(1));\r
+                                                       nx.parentNode.replaceChild(bl, nx);\r
+                                               }\r
+                                       } else {\r
+                                               if (bl.hasChildNodes())\r
+                                                       bl.insertBefore(nx, bl.firstChild);\r
+                                               else\r
+                                                       bl.appendChild(nx);\r
+                                       }\r
+                               } else\r
+                                       bl = null; // Time to create new block\r
+                       }\r
+\r
+                       // Restore selection\r
+                       if (si != -2) {\r
+                               if (!isIE) {\r
+                                       bl = d.getElementsByTagName(ed.settings.element)[0];\r
+                                       r = d.createRange();\r
+\r
+                                       // Select last location or generated block\r
+                                       if (si != -1)\r
+                                               r.setStart(t.find(b, 1, si), so);\r
+                                       else\r
+                                               r.setStart(bl, 0);\r
+\r
+                                       // Select last location or generated block\r
+                                       if (ei != -1)\r
+                                               r.setEnd(t.find(b, 1, ei), eo);\r
+                                       else\r
+                                               r.setEnd(bl, 0);\r
+\r
+                                       if (s) {\r
+                                               s.removeAllRanges();\r
+                                               s.addRange(r);\r
+                                       }\r
+                               } else {\r
+                                       try {\r
+                                               r = s.createRange();\r
+                                               r.moveToElementText(b);\r
+                                               r.collapse(1);\r
+                                               r.moveStart('character', si);\r
+                                               r.moveEnd('character', ei);\r
+                                               r.select();\r
+                                       } catch (ex) {\r
+                                               // Ignore\r
+                                       }\r
+                               }\r
+                       }\r
+               },\r
+\r
+               getParentBlock : function(n) {\r
+                       var d = this.dom;\r
+\r
+                       return d.getParent(n, d.isBlock);\r
+               },\r
+\r
+               insertPara : function(e) {\r
+                       var t = this, ed = t.editor, dom = ed.dom, d = ed.getDoc(), se = ed.settings, s = ed.selection.getSel(), r = s.getRangeAt(0), b = d.body;\r
+                       var rb, ra, dir, sn, so, en, eo, sb, eb, bn, bef, aft, sc, ec, n, vp = dom.getViewPort(ed.getWin()), y, ch;\r
+\r
+                       function isEmpty(n) {\r
+                               n = n.innerHTML;\r
+                               n = n.replace(/<(img|hr|table)/gi, '-'); // Keep these convert them to - chars\r
+                               n = n.replace(/<[^>]+>/g, ''); // Remove all tags\r
+\r
+                               return n.replace(/[ \t\r\n]+/g, '') == '';\r
+                       };\r
+\r
+                       // If root blocks are forced then use Operas default behavior since it's really good\r
+// Removed due to bug: #1853816\r
+//                     if (se.forced_root_block && isOpera)\r
+//                             return true;\r
+\r
+                       // Setup before range\r
+                       rb = d.createRange();\r
+\r
+                       // If is before the first block element and in body, then move it into first block element\r
+                       rb.setStart(s.anchorNode, s.anchorOffset);\r
+                       rb.collapse(true);\r
+\r
+                       // Setup after range\r
+                       ra = d.createRange();\r
+\r
+                       // If is before the first block element and in body, then move it into first block element\r
+                       ra.setStart(s.focusNode, s.focusOffset);\r
+                       ra.collapse(true);\r
+\r
+                       // Setup start/end points\r
+                       dir = rb.compareBoundaryPoints(rb.START_TO_END, ra) < 0;\r
+                       sn = dir ? s.anchorNode : s.focusNode;\r
+                       so = dir ? s.anchorOffset : s.focusOffset;\r
+                       en = dir ? s.focusNode : s.anchorNode;\r
+                       eo = dir ? s.focusOffset : s.anchorOffset;\r
+\r
+                       // If selection is in empty table cell\r
+                       if (sn === en && /^(TD|TH)$/.test(sn.nodeName)) {\r
+                               dom.remove(sn.firstChild); // Remove BR\r
+\r
+                               // Create two new block elements\r
+                               ed.dom.add(sn, se.element, null, '<br />');\r
+                               aft = ed.dom.add(sn, se.element, null, '<br />');\r
+\r
+                               // Move caret into the last one\r
+                               r = d.createRange();\r
+                               r.selectNodeContents(aft);\r
+                               r.collapse(1);\r
+                               ed.selection.setRng(r);\r
+\r
+                               return false;\r
+                       }\r
+\r
+                       // If the caret is in an invalid location in FF we need to move it into the first block\r
+                       if (sn == b && en == b && b.firstChild && ed.dom.isBlock(b.firstChild)) {\r
+                               sn = en = sn.firstChild;\r
+                               so = eo = 0;\r
+                               rb = d.createRange();\r
+                               rb.setStart(sn, 0);\r
+                               ra = d.createRange();\r
+                               ra.setStart(en, 0);\r
+                       }\r
+\r
+                       // Never use body as start or end node\r
+                       sn = sn.nodeName == "HTML" ? d.body : sn; // Fix for Opera bug: https://bugs.opera.com/show_bug.cgi?id=273224&comments=yes\r
+                       sn = sn.nodeName == "BODY" ? sn.firstChild : sn;\r
+                       en = en.nodeName == "HTML" ? d.body : en; // Fix for Opera bug: https://bugs.opera.com/show_bug.cgi?id=273224&comments=yes\r
+                       en = en.nodeName == "BODY" ? en.firstChild : en;\r
+\r
+                       // Get start and end blocks\r
+                       sb = t.getParentBlock(sn);\r
+                       eb = t.getParentBlock(en);\r
+                       bn = sb ? sb.nodeName : se.element; // Get block name to create\r
+\r
+                       // Return inside list use default browser behavior\r
+                       if (t.dom.getParent(sb, function(n) { return /OL|UL|PRE/.test(n.nodeName); }))\r
+                               return true;\r
+\r
+                       // If caption or absolute layers then always generate new blocks within\r
+                       if (sb && (sb.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(sb.style.position))) {\r
+                               bn = se.element;\r
+                               sb = null;\r
+                       }\r
+\r
+                       // If caption or absolute layers then always generate new blocks within\r
+                       if (eb && (eb.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(eb.style.position))) {\r
+                               bn = se.element;\r
+                               eb = null;\r
+                       }\r
+\r
+                       // Use P instead\r
+                       if (/(TD|TABLE|TH|CAPTION)/.test(bn) || (sb && bn == "DIV" && /left|right/gi.test(sb.style.cssFloat))) {\r
+                               bn = se.element;\r
+                               sb = eb = null;\r
+                       }\r
+\r
+                       // Setup new before and after blocks\r
+                       bef = (sb && sb.nodeName == bn) ? sb.cloneNode(0) : ed.dom.create(bn);\r
+                       aft = (eb && eb.nodeName == bn) ? eb.cloneNode(0) : ed.dom.create(bn);\r
+\r
+                       // Remove id from after clone\r
+                       aft.removeAttribute('id');\r
+\r
+                       // Is header and cursor is at the end, then force paragraph under\r
+                       if (/^(H[1-6])$/.test(bn) && sn.nodeValue && so == sn.nodeValue.length)\r
+                               aft = ed.dom.create(se.element);\r
+\r
+                       // Find start chop node\r
+                       n = sc = sn;\r
+                       do {\r
+                               if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName))\r
+                                       break;\r
+\r
+                               sc = n;\r
+                       } while ((n = n.previousSibling ? n.previousSibling : n.parentNode));\r
+\r
+                       // Find end chop node\r
+                       n = ec = en;\r
+                       do {\r
+                               if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName))\r
+                                       break;\r
+\r
+                               ec = n;\r
+                       } while ((n = n.nextSibling ? n.nextSibling : n.parentNode));\r
+\r
+                       // Place first chop part into before block element\r
+                       if (sc.nodeName == bn)\r
+                               rb.setStart(sc, 0);\r
+                       else\r
+                               rb.setStartBefore(sc);\r
+\r
+                       rb.setEnd(sn, so);\r
+                       bef.appendChild(rb.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari\r
+\r
+                       // Place secnd chop part within new block element\r
+                       try {\r
+                               ra.setEndAfter(ec);\r
+                       } catch(ex) {\r
+                               //console.debug(s.focusNode, s.focusOffset);\r
+                       }\r
+\r
+                       ra.setStart(en, eo);\r
+                       aft.appendChild(ra.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari\r
+\r
+                       // Create range around everything\r
+                       r = d.createRange();\r
+                       if (!sc.previousSibling && sc.parentNode.nodeName == bn) {\r
+                               r.setStartBefore(sc.parentNode);\r
+                       } else {\r
+                               if (rb.startContainer.nodeName == bn && rb.startOffset == 0)\r
+                                       r.setStartBefore(rb.startContainer);\r
+                               else\r
+                                       r.setStart(rb.startContainer, rb.startOffset);\r
+                       }\r
+\r
+                       if (!ec.nextSibling && ec.parentNode.nodeName == bn)\r
+                               r.setEndAfter(ec.parentNode);\r
+                       else\r
+                               r.setEnd(ra.endContainer, ra.endOffset);\r
+\r
+                       // Delete and replace it with new block elements\r
+                       r.deleteContents();\r
+\r
+                       if (isOpera)\r
+                               ed.getWin().scrollTo(0, vp.y);\r
+\r
+                       // Never wrap blocks in blocks\r
+                       if (bef.firstChild && bef.firstChild.nodeName == bn)\r
+                               bef.innerHTML = bef.firstChild.innerHTML;\r
+\r
+                       if (aft.firstChild && aft.firstChild.nodeName == bn)\r
+                               aft.innerHTML = aft.firstChild.innerHTML;\r
+\r
+                       // Padd empty blocks\r
+                       if (isEmpty(bef))\r
+                               bef.innerHTML = '<br />';\r
+\r
+                       if (isEmpty(aft))\r
+                               aft.innerHTML = isOpera ? '&nbsp;' : '<br />'; // Extra space for Opera so that the caret can move there\r
+\r
+                       // Opera needs this one backwards\r
+                       if (isOpera) {\r
+                               r.insertNode(bef);\r
+                               r.insertNode(aft);\r
+                       } else {\r
+                               r.insertNode(aft);\r
+                               r.insertNode(bef);\r
+                       }\r
+\r
+                       // Normalize\r
+                       aft.normalize();\r
+                       bef.normalize();\r
+\r
+                       // Move cursor and scroll into view\r
+                       r = d.createRange();\r
+                       r.selectNodeContents(aft);\r
+                       r.collapse(1);\r
+                       s.removeAllRanges();\r
+                       s.addRange(r);\r
+\r
+                       // scrollIntoView seems to scroll the parent window in most browsers now including FF 3.0b4 so it's time to stop using it and do it our selfs\r
+                       y = ed.dom.getPos(aft).y;\r
+                       ch = aft.clientHeight;\r
+\r
+                       // Is element within viewport\r
+                       if (y < vp.y || y + ch > vp.y + vp.h) {\r
+                               ed.getWin().scrollTo(0, y < vp.y ? y : y - vp.h + ch);\r
+                               //console.debug('SCROLL!', 'vp.y: ' + vp.y, 'y' + y, 'vp.h' + vp.h, 'clientHeight' + aft.clientHeight, 'yyy: ' + (y < vp.y ? y : y - vp.h + aft.clientHeight));\r
+                       }\r
+\r
+                       return false;\r
+               },\r
+\r
+               backspaceDelete : function(e, bs) {\r
+                       var t = this, ed = t.editor, b = ed.getBody(), n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n, w, tn;\r
+\r
+                       // The caret sometimes gets stuck in Gecko if you delete empty paragraphs\r
+                       // This workaround removes the element by hand and moves the caret to the previous element\r
+                       if (sc && ed.dom.isBlock(sc) && !/^(TD|TH)$/.test(sc.nodeName) && bs) {\r
+                               if (sc.childNodes.length == 0 || (sc.childNodes.length == 1 && sc.firstChild.nodeName == 'BR')) {\r
+                                       // Find previous block element\r
+                                       n = sc;\r
+                                       while ((n = n.previousSibling) && !ed.dom.isBlock(n)) ;\r
+\r
+                                       if (n) {\r
+                                               if (sc != b.firstChild) {\r
+                                                       // Find last text node\r
+                                                       w = ed.dom.doc.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);\r
+                                                       while (tn = w.nextNode())\r
+                                                               n = tn;\r
+\r
+                                                       // Place caret at the end of last text node\r
+                                                       r = ed.getDoc().createRange();\r
+                                                       r.setStart(n, n.nodeValue ? n.nodeValue.length : 0);\r
+                                                       r.setEnd(n, n.nodeValue ? n.nodeValue.length : 0);\r
+                                                       se.setRng(r);\r
+\r
+                                                       // Remove the target container\r
+                                                       ed.dom.remove(sc);\r
+                                               }\r
+\r
+                                               return Event.cancel(e);\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       // Gecko generates BR elements here and there, we don't like those so lets remove them\r
+                       function handler(e) {\r
+                               e = e.target;\r
+\r
+                               // A new BR was created in a block element, remove it\r
+                               if (e && e.parentNode && e.nodeName == 'BR' && (n = t.getParentBlock(e))) {\r
+                                       Event.remove(b, 'DOMNodeInserted', handler);\r
+\r
+                                       // Only remove BR elements that got inserted in the middle of the text\r
+                                       if (e.previousSibling || e.nextSibling)\r
+                                               ed.dom.remove(e);\r
+                               }\r
+                       };\r
+\r
+                       // Listen for new nodes\r
+                       Event._add(b, 'DOMNodeInserted', handler);\r
+\r
+                       // Remove listener\r
+                       window.setTimeout(function() {\r
+                               Event._remove(b, 'DOMNodeInserted', handler);\r
+                       }, 1);\r
+               }\r
+       });\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/ControlManager.js */\r
+\r
+(function() {\r
+       // Shorten names\r
+       var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, extend = tinymce.extend;\r
+\r
+       tinymce.create('tinymce.ControlManager', {\r
+               ControlManager : function(ed, s) {\r
+                       var t = this, i;\r
+\r
+                       s = s || {};\r
+                       t.editor = ed;\r
+                       t.controls = {};\r
+                       t.onAdd = new tinymce.util.Dispatcher(t);\r
+                       t.onPostRender = new tinymce.util.Dispatcher(t);\r
+                       t.prefix = s.prefix || ed.id + '_';\r
+                       t._cls = {};\r
+\r
+                       t.onPostRender.add(function() {\r
+                               each(t.controls, function(c) {\r
+                                       c.postRender();\r
+                               });\r
+                       });\r
+               },\r
+\r
+               get : function(id) {\r
+                       return this.controls[this.prefix + id] || this.controls[id];\r
+               },\r
+\r
+               setActive : function(id, s) {\r
+                       var c = null;\r
+\r
+                       if (c = this.get(id))\r
+                               c.setActive(s);\r
+\r
+                       return c;\r
+               },\r
+\r
+               setDisabled : function(id, s) {\r
+                       var c = null;\r
+\r
+                       if (c = this.get(id))\r
+                               c.setDisabled(s);\r
+\r
+                       return c;\r
+               },\r
+\r
+               add : function(c) {\r
+                       var t = this;\r
+\r
+                       if (c) {\r
+                               t.controls[c.id] = c;\r
+                               t.onAdd.dispatch(c, t);\r
+                       }\r
+\r
+                       return c;\r
+               },\r
+\r
+               createControl : function(n) {\r
+                       var c, t = this, ed = t.editor;\r
+\r
+                       each(ed.plugins, function(p) {\r
+                               if (p.createControl) {\r
+                                       c = p.createControl(n, t);\r
+\r
+                                       if (c)\r
+                                               return false;\r
+                               }\r
+                       });\r
+\r
+                       switch (n) {\r
+                               case "|":\r
+                               case "separator":\r
+                                       return t.createSeparator();\r
+                       }\r
+\r
+                       if (!c && ed.buttons && (c = ed.buttons[n]))\r
+                               return t.createButton(n, c);\r
+\r
+                       return t.add(c);\r
+               },\r
+\r
+               createDropMenu : function(id, s, cc) {\r
+                       var t = this, ed = t.editor, c, bm, v, cls;\r
+\r
+                       s = extend({\r
+                               'class' : 'mceDropDown',\r
+                               constrain : ed.settings.constrain_menus\r
+                       }, s);\r
+\r
+                       s['class'] = s['class'] + ' ' + ed.getParam('skin') + 'Skin';\r
+                       if (v = ed.getParam('skin_variant'))\r
+                               s['class'] += ' ' + ed.getParam('skin') + 'Skin' + v.substring(0, 1).toUpperCase() + v.substring(1);\r
+\r
+                       id = t.prefix + id;\r
+                       cls = cc || t._cls.dropmenu || tinymce.ui.DropMenu;\r
+                       c = t.controls[id] = new cls(id, s);\r
+                       c.onAddItem.add(function(c, o) {\r
+                               var s = o.settings;\r
+\r
+                               s.title = ed.getLang(s.title, s.title);\r
+\r
+                               if (!s.onclick) {\r
+                                       s.onclick = function(v) {\r
+                                               ed.execCommand(s.cmd, s.ui || false, s.value);\r
+                                       };\r
+                               }\r
+                       });\r
+\r
+                       ed.onRemove.add(function() {\r
+                               c.destroy();\r
+                       });\r
+\r
+                       // Fix for bug #1897785, #1898007\r
+                       if (tinymce.isIE) {\r
+                               c.onShowMenu.add(function() {\r
+                                       var s = ed.selection, n = s.getNode();\r
+\r
+                                       if (n.nodeName == 'IMG')\r
+                                               bm = s.getBookmark();\r
+                                       else\r
+                                               bm = 0;\r
+                               });\r
+\r
+                               c.onHideMenu.add(function() {\r
+                                       if (bm)\r
+                                               ed.selection.moveToBookmark(bm);\r
+                               });\r
+                       }\r
+\r
+                       return t.add(c);\r
+               },\r
+\r
+               createListBox : function(id, s, cc) {\r
+                       var t = this, ed = t.editor, cmd, c, cls;\r
+\r
+                       if (t.get(id))\r
+                               return null;\r
+\r
+                       s.title = ed.translate(s.title);\r
+                       s.scope = s.scope || ed;\r
+\r
+                       if (!s.onselect) {\r
+                               s.onselect = function(v) {\r
+                                       ed.execCommand(s.cmd, s.ui || false, v || s.value);\r
+                               };\r
+                       }\r
+\r
+                       s = extend({\r
+                               title : s.title,\r
+                               'class' : 'mce_' + id,\r
+                               scope : s.scope,\r
+                               control_manager : t\r
+                       }, s);\r
+\r
+                       id = t.prefix + id;\r
+\r
+                       if (ed.settings.use_native_selects)\r
+                               c = new tinymce.ui.NativeListBox(id, s);\r
+                       else {\r
+                               cls = cc || t._cls.listbox || tinymce.ui.ListBox;\r
+                               c = new cls(id, s);\r
+                       }\r
+\r
+                       t.controls[id] = c;\r
+\r
+                       // Fix focus problem in Safari\r
+                       if (tinymce.isWebKit) {\r
+                               c.onPostRender.add(function(c, n) {\r
+                                       // Store bookmark on mousedown\r
+                                       Event.add(n, 'mousedown', function() {\r
+                                               ed.bookmark = ed.selection.getBookmark('simple');\r
+                                       });\r
+\r
+                                       // Restore on focus, since it might be lost\r
+                                       Event.add(n, 'focus', function() {\r
+                                               ed.selection.moveToBookmark(ed.bookmark);\r
+                                               ed.bookmark = null;\r
+                                       });\r
+                               });\r
+                       }\r
+\r
+                       if (c.hideMenu)\r
+                               ed.onMouseDown.add(c.hideMenu, c);\r
+\r
+                       return t.add(c);\r
+               },\r
+\r
+               createButton : function(id, s, cc) {\r
+                       var t = this, ed = t.editor, o, c, cls;\r
+\r
+                       if (t.get(id))\r
+                               return null;\r
+\r
+                       s.title = ed.translate(s.title);\r
+                       s.label = ed.translate(s.label);\r
+                       s.scope = s.scope || ed;\r
+\r
+                       if (!s.onclick && !s.menu_button) {\r
+                               s.onclick = function() {\r
+                                       ed.execCommand(s.cmd, s.ui || false, s.value);\r
+                               };\r
+                       }\r
+\r
+                       s = extend({\r
+                               title : s.title,\r
+                               'class' : 'mce_' + id,\r
+                               unavailable_prefix : ed.getLang('unavailable', ''),\r
+                               scope : s.scope,\r
+                               control_manager : t\r
+                       }, s);\r
+\r
+                       id = t.prefix + id;\r
+\r
+                       if (s.menu_button) {\r
+                               cls = cc || t._cls.menubutton || tinymce.ui.MenuButton;\r
+                               c = new cls(id, s);\r
+                               ed.onMouseDown.add(c.hideMenu, c);\r
+                       } else {\r
+                               cls = t._cls.button || tinymce.ui.Button;\r
+                               c = new cls(id, s);\r
+                       }\r
+\r
+                       return t.add(c);\r
+               },\r
+\r
+               createMenuButton : function(id, s) {\r
+                       s = s || {};\r
+                       s.menu_button = 1;\r
+\r
+                       return this.createButton(id, s);\r
+               },\r
+\r
+               createSplitButton : function(id, s, cc) {\r
+                       var t = this, ed = t.editor, cmd, c, cls;\r
+\r
+                       if (t.get(id))\r
+                               return null;\r
+\r
+                       s.title = ed.translate(s.title);\r
+                       s.scope = s.scope || ed;\r
+\r
+                       if (!s.onclick) {\r
+                               s.onclick = function(v) {\r
+                                       ed.execCommand(s.cmd, s.ui || false, v || s.value);\r
+                               };\r
+                       }\r
+\r
+                       if (!s.onselect) {\r
+                               s.onselect = function(v) {\r
+                                       ed.execCommand(s.cmd, s.ui || false, v || s.value);\r
+                               };\r
+                       }\r
+\r
+                       s = extend({\r
+                               title : s.title,\r
+                               'class' : 'mce_' + id,\r
+                               scope : s.scope,\r
+                               control_manager : t\r
+                       }, s);\r
+\r
+                       id = t.prefix + id;\r
+                       cls = cc || t._cls.splitbutton || tinymce.ui.SplitButton;\r
+                       c = t.add(new cls(id, s));\r
+                       ed.onMouseDown.add(c.hideMenu, c);\r
+\r
+                       return c;\r
+               },\r
+\r
+               createColorSplitButton : function(id, s, cc) {\r
+                       var t = this, ed = t.editor, cmd, c, cls;\r
+\r
+                       if (t.get(id))\r
+                               return null;\r
+\r
+                       s.title = ed.translate(s.title);\r
+                       s.scope = s.scope || ed;\r
+\r
+                       if (!s.onclick) {\r
+                               s.onclick = function(v) {\r
+                                       ed.execCommand(s.cmd, s.ui || false, v || s.value);\r
+                               };\r
+                       }\r
+\r
+                       if (!s.onselect) {\r
+                               s.onselect = function(v) {\r
+                                       ed.execCommand(s.cmd, s.ui || false, v || s.value);\r
+                               };\r
+                       }\r
+\r
+                       s = extend({\r
+                               title : s.title,\r
+                               'class' : 'mce_' + id,\r
+                               'menu_class' : ed.getParam('skin') + 'Skin',\r
+                               scope : s.scope,\r
+                               more_colors_title : ed.getLang('more_colors')\r
+                       }, s);\r
+\r
+                       id = t.prefix + id;\r
+                       cls = cc || t._cls.colorsplitbutton || tinymce.ui.ColorSplitButton;\r
+                       c = new cls(id, s);\r
+                       ed.onMouseDown.add(c.hideMenu, c);\r
+\r
+                       // Remove the menu element when the editor is removed\r
+                       ed.onRemove.add(function() {\r
+                               c.destroy();\r
+                       });\r
+\r
+                       return t.add(c);\r
+               },\r
+\r
+               createToolbar : function(id, s, cc) {\r
+                       var c, t = this, cls;\r
+\r
+                       id = t.prefix + id;\r
+                       cls = cc || t._cls.toolbar || tinymce.ui.Toolbar;\r
+                       c = new cls(id, s);\r
+\r
+                       if (t.get(id))\r
+                               return null;\r
+\r
+                       return t.add(c);\r
+               },\r
+\r
+               createSeparator : function(cc) {\r
+                       var cls = cc || this._cls.separator || tinymce.ui.Separator;\r
+\r
+                       return new cls();\r
+               },\r
+\r
+               setControlType : function(n, c) {\r
+                       return this._cls[n.toLowerCase()] = c;\r
+               },\r
+\r
+               destroy : function() {\r
+                       each(this.controls, function(c) {\r
+                               c.destroy();\r
+                       });\r
+\r
+                       this.controls = null;\r
+               }\r
+\r
+               });\r
+})();\r
+\r
+/* file:jscripts/tiny_mce/classes/WindowManager.js */\r
+\r
+(function() {\r
+       var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each, isIE = tinymce.isIE, isOpera = tinymce.isOpera;\r
+\r
+       tinymce.create('tinymce.WindowManager', {\r
+               WindowManager : function(ed) {\r
+                       var t = this;\r
+\r
+                       t.editor = ed;\r
+                       t.onOpen = new Dispatcher(t);\r
+                       t.onClose = new Dispatcher(t);\r
+                       t.params = {};\r
+                       t.features = {};\r
+               },\r
+\r
+               open : function(s, p) {\r
+                       var t = this, f = '', x, y, mo = t.editor.settings.dialog_type == 'modal', w, sw, sh, vp = tinymce.DOM.getViewPort(), u;\r
+\r
+                       // Default some options\r
+                       s = s || {};\r
+                       p = p || {};\r
+                       sw = isOpera ? vp.w : screen.width; // Opera uses windows inside the Opera window\r
+                       sh = isOpera ? vp.h : screen.height;\r
+                       s.name = s.name || 'mc_' + new Date().getTime();\r
+                       s.width = parseInt(s.width || 320);\r
+                       s.height = parseInt(s.height || 240);\r
+                       s.resizable = true;\r
+                       s.left = s.left || parseInt(sw / 2.0) - (s.width / 2.0);\r
+                       s.top = s.top || parseInt(sh / 2.0) - (s.height / 2.0);\r
+                       p.inline = false;\r
+                       p.mce_width = s.width;\r
+                       p.mce_height = s.height;\r
+                       p.mce_auto_focus = s.auto_focus;\r
+\r
+                       if (mo) {\r
+                               if (isIE) {\r
+                                       s.center = true;\r
+                                       s.help = false;\r
+                                       s.dialogWidth = s.width + 'px';\r
+                                       s.dialogHeight = s.height + 'px';\r
+                                       s.scroll = s.scrollbars || false;\r
+                               } else\r
+                                       s.modal = s.alwaysRaised = s.dialog = s.centerscreen = s.dependent = true;\r
+                       }\r
+\r
+                       // Build features string\r
+                       each(s, function(v, k) {\r
+                               if (tinymce.is(v, 'boolean'))\r
+                                       v = v ? 'yes' : 'no';\r
+\r
+                               if (!/^(name|url)$/.test(k)) {\r
+                                       if (isIE && mo)\r
+                                               f += (f ? ';' : '') + k + ':' + v;\r
+                                       else\r
+                                               f += (f ? ',' : '') + k + '=' + v;\r
+                               }\r
+                       });\r
+\r
+                       t.features = s;\r
+                       t.params = p;\r
+                       t.onOpen.dispatch(t, s, p);\r
+\r
+                       u = s.url || s.file;\r
+                       if (tinymce.relaxedDomain)\r
+                               u += (u.indexOf('?') == -1 ? '?' : '&') + 'mce_rdomain=' + tinymce.relaxedDomain;\r
+\r
+                       u = tinymce._addVer(u);\r
+\r
+                       try {\r
+                               if (isIE && mo) {\r
+                                       w = 1;\r
+                                       window.showModalDialog(u, window, f);\r
+                               } else\r
+                                       w = window.open(u, s.name, f);\r
+                       } catch (ex) {\r
+                               // Ignore\r
+                       }\r
+\r
+                       if (!w)\r
+                               alert(t.editor.getLang('popup_blocked'));\r
+               },\r
+\r
+               close : function(w) {\r
+                       w.close();\r
+                       this.onClose.dispatch(this);\r
+               },\r
+\r
+               createInstance : function(cl, a, b, c, d, e) {\r
+                       var f = tinymce.resolve(cl);\r
+\r
+                       return new f(a, b, c, d, e);\r
+               },\r
+\r
+               confirm : function(t, cb, s) {\r
+                       cb.call(s || this, confirm(this._decode(this.editor.getLang(t, t))));\r
+               },\r
+\r
+               alert : function(tx, cb, s) {\r
+                       var t = this;\r
+       \r
+                       alert(t._decode(t.editor.getLang(tx, tx)));\r
+\r
+                       if (cb)\r
+                               cb.call(s || t);\r
+               },\r
+\r
+               // Internal functions\r
+\r
+               _decode : function(s) {\r
+                       return tinymce.DOM.decode(s).replace(/\\n/g, '\n');\r
+               }\r
+\r
+               });\r
+}());
\ No newline at end of file
diff --git a/jscripts/tiny_mce/utils/editable_selects.js b/jscripts/tiny_mce/utils/editable_selects.js
new file mode 100644 (file)
index 0000000..9b40922
--- /dev/null
@@ -0,0 +1,61 @@
+/**\r
+ * $Id: editable_selects.js 520 2008-01-07 16:30:32Z spocke $\r
+ *\r
+ * Makes select boxes editable.\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+var TinyMCE_EditableSelects = {\r
+       editSelectElm : null,\r
+\r
+       init : function() {\r
+               var nl = document.getElementsByTagName("select"), i, d = document, o;\r
+\r
+               for (i=0; i<nl.length; i++) {\r
+                       if (nl[i].className.indexOf('mceEditableSelect') != -1) {\r
+                               o = new Option('(value)', '__mce_add_custom__');\r
+\r
+                               o.className = 'mceAddSelectValue';\r
+\r
+                               nl[i].options[nl[i].options.length] = o;\r
+                               nl[i].onchange = TinyMCE_EditableSelects.onChangeEditableSelect;\r
+                       }\r
+               }\r
+       },\r
+\r
+       onChangeEditableSelect : function(e) {\r
+               var d = document, ne, se = window.event ? window.event.srcElement : e.target;\r
+\r
+               if (se.options[se.selectedIndex].value == '__mce_add_custom__') {\r
+                       ne = d.createElement("input");\r
+                       ne.id = se.id + "_custom";\r
+                       ne.name = se.name + "_custom";\r
+                       ne.type = "text";\r
+\r
+                       ne.style.width = se.offsetWidth + 'px';\r
+                       se.parentNode.insertBefore(ne, se);\r
+                       se.style.display = 'none';\r
+                       ne.focus();\r
+                       ne.onblur = TinyMCE_EditableSelects.onBlurEditableSelectInput;\r
+                       TinyMCE_EditableSelects.editSelectElm = se;\r
+               }\r
+       },\r
+\r
+       onBlurEditableSelectInput : function() {\r
+               var se = TinyMCE_EditableSelects.editSelectElm;\r
+\r
+               if (se) {\r
+                       if (se.previousSibling.value != '') {\r
+                               addSelectValue(document.forms[0], se.id, se.previousSibling.value, se.previousSibling.value);\r
+                               selectByValue(document.forms[0], se.id, se.previousSibling.value);\r
+                       } else\r
+                               selectByValue(document.forms[0], se.id, '');\r
+\r
+                       se.style.display = 'inline';\r
+                       se.parentNode.removeChild(se.previousSibling);\r
+                       TinyMCE_EditableSelects.editSelectElm = null;\r
+               }\r
+       }\r
+};\r
diff --git a/jscripts/tiny_mce/utils/form_utils.js b/jscripts/tiny_mce/utils/form_utils.js
new file mode 100644 (file)
index 0000000..c1f1409
--- /dev/null
@@ -0,0 +1,199 @@
+/**\r
+ * $Id: form_utils.js 673 2008-03-06 13:26:20Z spocke $\r
+ *\r
+ * Various form utilitiy functions.\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+var themeBaseURL = tinyMCEPopup.editor.baseURI.toAbsolute('themes/' + tinyMCEPopup.getParam("theme"));\r
+\r
+function getColorPickerHTML(id, target_form_element) {\r
+       var h = "";\r
+\r
+       h += '<a id="' + id + '_link" href="javascript:;" onclick="tinyMCEPopup.pickColor(event,\'' + target_form_element +'\');" onmousedown="return false;" class="pickcolor">';\r
+       h += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '"></span></a>';\r
+\r
+       return h;\r
+}\r
+\r
+function updateColor(img_id, form_element_id) {\r
+       document.getElementById(img_id).style.backgroundColor = document.forms[0].elements[form_element_id].value;\r
+}\r
+\r
+function setBrowserDisabled(id, state) {\r
+       var img = document.getElementById(id);\r
+       var lnk = document.getElementById(id + "_link");\r
+\r
+       if (lnk) {\r
+               if (state) {\r
+                       lnk.setAttribute("realhref", lnk.getAttribute("href"));\r
+                       lnk.removeAttribute("href");\r
+                       tinyMCEPopup.dom.addClass(img, 'disabled');\r
+               } else {\r
+                       if (lnk.getAttribute("realhref"))\r
+                               lnk.setAttribute("href", lnk.getAttribute("realhref"));\r
+\r
+                       tinyMCEPopup.dom.removeClass(img, 'disabled');\r
+               }\r
+       }\r
+}\r
+\r
+function getBrowserHTML(id, target_form_element, type, prefix) {\r
+       var option = prefix + "_" + type + "_browser_callback", cb, html;\r
+\r
+       cb = tinyMCEPopup.getParam(option, tinyMCEPopup.getParam("file_browser_callback"));\r
+\r
+       if (!cb)\r
+               return "";\r
+\r
+       html = "";\r
+       html += '<a id="' + id + '_link" href="javascript:openBrowser(\'' + id + '\',\'' + target_form_element + '\', \'' + type + '\',\'' + option + '\');" onmousedown="return false;" class="browse">';\r
+       html += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '"></span></a>';\r
+\r
+       return html;\r
+}\r
+\r
+function openBrowser(img_id, target_form_element, type, option) {\r
+       var img = document.getElementById(img_id);\r
+\r
+       if (img.className != "mceButtonDisabled")\r
+               tinyMCEPopup.openBrowser(target_form_element, type, option);\r
+}\r
+\r
+function selectByValue(form_obj, field_name, value, add_custom, ignore_case) {\r
+       if (!form_obj || !form_obj.elements[field_name])\r
+               return;\r
+\r
+       var sel = form_obj.elements[field_name];\r
+\r
+       var found = false;\r
+       for (var i=0; i<sel.options.length; i++) {\r
+               var option = sel.options[i];\r
+\r
+               if (option.value == value || (ignore_case && option.value.toLowerCase() == value.toLowerCase())) {\r
+                       option.selected = true;\r
+                       found = true;\r
+               } else\r
+                       option.selected = false;\r
+       }\r
+\r
+       if (!found && add_custom && value != '') {\r
+               var option = new Option(value, value);\r
+               option.selected = true;\r
+               sel.options[sel.options.length] = option;\r
+               sel.selectedIndex = sel.options.length - 1;\r
+       }\r
+\r
+       return found;\r
+}\r
+\r
+function getSelectValue(form_obj, field_name) {\r
+       var elm = form_obj.elements[field_name];\r
+\r
+       if (elm == null || elm.options == null)\r
+               return "";\r
+\r
+       return elm.options[elm.selectedIndex].value;\r
+}\r
+\r
+function addSelectValue(form_obj, field_name, name, value) {\r
+       var s = form_obj.elements[field_name];\r
+       var o = new Option(name, value);\r
+       s.options[s.options.length] = o;\r
+}\r
+\r
+function addClassesToList(list_id, specific_option) {\r
+       // Setup class droplist\r
+       var styleSelectElm = document.getElementById(list_id);\r
+       var styles = tinyMCEPopup.getParam('theme_advanced_styles', false);\r
+       styles = tinyMCEPopup.getParam(specific_option, styles);\r
+\r
+       if (styles) {\r
+               var stylesAr = styles.split(';');\r
+\r
+               for (var i=0; i<stylesAr.length; i++) {\r
+                       if (stylesAr != "") {\r
+                               var key, value;\r
+\r
+                               key = stylesAr[i].split('=')[0];\r
+                               value = stylesAr[i].split('=')[1];\r
+\r
+                               styleSelectElm.options[styleSelectElm.length] = new Option(key, value);\r
+                       }\r
+               }\r
+       } else {\r
+               tinymce.each(tinyMCEPopup.editor.dom.getClasses(), function(o) {\r
+                       styleSelectElm.options[styleSelectElm.length] = new Option(o.title || o['class'], o['class']);\r
+               });\r
+       }\r
+}\r
+\r
+function isVisible(element_id) {\r
+       var elm = document.getElementById(element_id);\r
+\r
+       return elm && elm.style.display != "none";\r
+}\r
+\r
+function convertRGBToHex(col) {\r
+       var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi");\r
+\r
+       var rgb = col.replace(re, "$1,$2,$3").split(',');\r
+       if (rgb.length == 3) {\r
+               r = parseInt(rgb[0]).toString(16);\r
+               g = parseInt(rgb[1]).toString(16);\r
+               b = parseInt(rgb[2]).toString(16);\r
+\r
+               r = r.length == 1 ? '0' + r : r;\r
+               g = g.length == 1 ? '0' + g : g;\r
+               b = b.length == 1 ? '0' + b : b;\r
+\r
+               return "#" + r + g + b;\r
+       }\r
+\r
+       return col;\r
+}\r
+\r
+function convertHexToRGB(col) {\r
+       if (col.indexOf('#') != -1) {\r
+               col = col.replace(new RegExp('[^0-9A-F]', 'gi'), '');\r
+\r
+               r = parseInt(col.substring(0, 2), 16);\r
+               g = parseInt(col.substring(2, 4), 16);\r
+               b = parseInt(col.substring(4, 6), 16);\r
+\r
+               return "rgb(" + r + "," + g + "," + b + ")";\r
+       }\r
+\r
+       return col;\r
+}\r
+\r
+function trimSize(size) {\r
+       return size.replace(/([0-9\.]+)px|(%|in|cm|mm|em|ex|pt|pc)/, '$1$2');\r
+}\r
+\r
+function getCSSSize(size) {\r
+       size = trimSize(size);\r
+\r
+       if (size == "")\r
+               return "";\r
+\r
+       // Add px\r
+       if (/^[0-9]+$/.test(size))\r
+               size += 'px';\r
+\r
+       return size;\r
+}\r
+\r
+function getStyle(elm, attrib, style) {\r
+       var val = tinyMCEPopup.dom.getAttrib(elm, attrib);\r
+\r
+       if (val != '')\r
+               return '' + val;\r
+\r
+       if (typeof(style) == 'undefined')\r
+               style = attrib;\r
+\r
+       return tinyMCEPopup.dom.getStyle(elm, style);\r
+}\r
diff --git a/jscripts/tiny_mce/utils/mctabs.js b/jscripts/tiny_mce/utils/mctabs.js
new file mode 100644 (file)
index 0000000..284501e
--- /dev/null
@@ -0,0 +1,76 @@
+/**\r
+ * $Id: mctabs.js 758 2008-03-30 13:53:29Z spocke $\r
+ *\r
+ * Moxiecode DHTML Tabs script.\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+function MCTabs() {\r
+       this.settings = [];\r
+};\r
+\r
+MCTabs.prototype.init = function(settings) {\r
+       this.settings = settings;\r
+};\r
+\r
+MCTabs.prototype.getParam = function(name, default_value) {\r
+       var value = null;\r
+\r
+       value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name];\r
+\r
+       // Fix bool values\r
+       if (value == "true" || value == "false")\r
+               return (value == "true");\r
+\r
+       return value;\r
+};\r
+\r
+MCTabs.prototype.displayTab = function(tab_id, panel_id) {\r
+       var panelElm, panelContainerElm, tabElm, tabContainerElm, selectionClass, nodes, i;\r
+\r
+       panelElm= document.getElementById(panel_id);\r
+       panelContainerElm = panelElm ? panelElm.parentNode : null;\r
+       tabElm = document.getElementById(tab_id);\r
+       tabContainerElm = tabElm ? tabElm.parentNode : null;\r
+       selectionClass = this.getParam('selection_class', 'current');\r
+\r
+       if (tabElm && tabContainerElm) {\r
+               nodes = tabContainerElm.childNodes;\r
+\r
+               // Hide all other tabs\r
+               for (i = 0; i < nodes.length; i++) {\r
+                       if (nodes[i].nodeName == "LI")\r
+                               nodes[i].className = '';\r
+               }\r
+\r
+               // Show selected tab\r
+               tabElm.className = 'current';\r
+       }\r
+\r
+       if (panelElm && panelContainerElm) {\r
+               nodes = panelContainerElm.childNodes;\r
+\r
+               // Hide all other panels\r
+               for (i = 0; i < nodes.length; i++) {\r
+                       if (nodes[i].nodeName == "DIV")\r
+                               nodes[i].className = 'panel';\r
+               }\r
+\r
+               // Show selected panel\r
+               panelElm.className = 'current';\r
+       }\r
+};\r
+\r
+MCTabs.prototype.getAnchor = function() {\r
+       var pos, url = document.location.href;\r
+\r
+       if ((pos = url.lastIndexOf('#')) != -1)\r
+               return url.substring(pos + 1);\r
+\r
+       return "";\r
+};\r
+\r
+// Global instance\r
+var mcTabs = new MCTabs();\r
diff --git a/jscripts/tiny_mce/utils/validate.js b/jscripts/tiny_mce/utils/validate.js
new file mode 100644 (file)
index 0000000..cde4c97
--- /dev/null
@@ -0,0 +1,219 @@
+/**\r
+ * $Id: validate.js 758 2008-03-30 13:53:29Z spocke $\r
+ *\r
+ * Various form validation methods.\r
+ *\r
+ * @author Moxiecode\r
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ */\r
+\r
+/**\r
+       // String validation:\r
+\r
+       if (!Validator.isEmail('myemail'))\r
+               alert('Invalid email.');\r
+\r
+       // Form validation:\r
+\r
+       var f = document.forms['myform'];\r
+\r
+       if (!Validator.isEmail(f.myemail))\r
+               alert('Invalid email.');\r
+*/\r
+\r
+var Validator = {\r
+       isEmail : function(s) {\r
+               return this.test(s, '^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+@[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$');\r
+       },\r
+\r
+       isAbsUrl : function(s) {\r
+               return this.test(s, '^(news|telnet|nttp|file|http|ftp|https)://[-A-Za-z0-9\\.]+\\/?.*$');\r
+       },\r
+\r
+       isSize : function(s) {\r
+               return this.test(s, '^[0-9]+(%|in|cm|mm|em|ex|pt|pc|px)?$');\r
+       },\r
+\r
+       isId : function(s) {\r
+               return this.test(s, '^[A-Za-z_]([A-Za-z0-9_])*$');\r
+       },\r
+\r
+       isEmpty : function(s) {\r
+               var nl, i;\r
+\r
+               if (s.nodeName == 'SELECT' && s.selectedIndex < 1)\r
+                       return true;\r
+\r
+               if (s.type == 'checkbox' && !s.checked)\r
+                       return true;\r
+\r
+               if (s.type == 'radio') {\r
+                       for (i=0, nl = s.form.elements; i<nl.length; i++) {\r
+                               if (nl[i].type == "radio" && nl[i].name == s.name && nl[i].checked)\r
+                                       return false;\r
+                       }\r
+\r
+                       return true;\r
+               }\r
+\r
+               return new RegExp('^\\s*$').test(s.nodeType == 1 ? s.value : s);\r
+       },\r
+\r
+       isNumber : function(s, d) {\r
+               return !isNaN(s.nodeType == 1 ? s.value : s) && (!d || !this.test(s, '^-?[0-9]*\\.[0-9]*$'));\r
+       },\r
+\r
+       test : function(s, p) {\r
+               s = s.nodeType == 1 ? s.value : s;\r
+\r
+               return s == '' || new RegExp(p).test(s);\r
+       }\r
+};\r
+\r
+var AutoValidator = {\r
+       settings : {\r
+               id_cls : 'id',\r
+               int_cls : 'int',\r
+               url_cls : 'url',\r
+               number_cls : 'number',\r
+               email_cls : 'email',\r
+               size_cls : 'size',\r
+               required_cls : 'required',\r
+               invalid_cls : 'invalid',\r
+               min_cls : 'min',\r
+               max_cls : 'max'\r
+       },\r
+\r
+       init : function(s) {\r
+               var n;\r
+\r
+               for (n in s)\r
+                       this.settings[n] = s[n];\r
+       },\r
+\r
+       validate : function(f) {\r
+               var i, nl, s = this.settings, c = 0;\r
+\r
+               nl = this.tags(f, 'label');\r
+               for (i=0; i<nl.length; i++)\r
+                       this.removeClass(nl[i], s.invalid_cls);\r
+\r
+               c += this.validateElms(f, 'input');\r
+               c += this.validateElms(f, 'select');\r
+               c += this.validateElms(f, 'textarea');\r
+\r
+               return c == 3;\r
+       },\r
+\r
+       invalidate : function(n) {\r
+               this.mark(n.form, n);\r
+       },\r
+\r
+       reset : function(e) {\r
+               var t = ['label', 'input', 'select', 'textarea'];\r
+               var i, j, nl, s = this.settings;\r
+\r
+               if (e == null)\r
+                       return;\r
+\r
+               for (i=0; i<t.length; i++) {\r
+                       nl = this.tags(e.form ? e.form : e, t[i]);\r
+                       for (j=0; j<nl.length; j++)\r
+                               this.removeClass(nl[j], s.invalid_cls);\r
+               }\r
+       },\r
+\r
+       validateElms : function(f, e) {\r
+               var nl, i, n, s = this.settings, st = true, va = Validator, v;\r
+\r
+               nl = this.tags(f, e);\r
+               for (i=0; i<nl.length; i++) {\r
+                       n = nl[i];\r
+\r
+                       this.removeClass(n, s.invalid_cls);\r
+\r
+                       if (this.hasClass(n, s.required_cls) && va.isEmpty(n))\r
+                               st = this.mark(f, n);\r
+\r
+                       if (this.hasClass(n, s.number_cls) && !va.isNumber(n))\r
+                               st = this.mark(f, n);\r
+\r
+                       if (this.hasClass(n, s.int_cls) && !va.isNumber(n, true))\r
+                               st = this.mark(f, n);\r
+\r
+                       if (this.hasClass(n, s.url_cls) && !va.isAbsUrl(n))\r
+                               st = this.mark(f, n);\r
+\r
+                       if (this.hasClass(n, s.email_cls) && !va.isEmail(n))\r
+                               st = this.mark(f, n);\r
+\r
+                       if (this.hasClass(n, s.size_cls) && !va.isSize(n))\r
+                               st = this.mark(f, n);\r
+\r
+                       if (this.hasClass(n, s.id_cls) && !va.isId(n))\r
+                               st = this.mark(f, n);\r
+\r
+                       if (this.hasClass(n, s.min_cls, true)) {\r
+                               v = this.getNum(n, s.min_cls);\r
+\r
+                               if (isNaN(v) || parseInt(n.value) < parseInt(v))\r
+                                       st = this.mark(f, n);\r
+                       }\r
+\r
+                       if (this.hasClass(n, s.max_cls, true)) {\r
+                               v = this.getNum(n, s.max_cls);\r
+\r
+                               if (isNaN(v) || parseInt(n.value) > parseInt(v))\r
+                                       st = this.mark(f, n);\r
+                       }\r
+               }\r
+\r
+               return st;\r
+       },\r
+\r
+       hasClass : function(n, c, d) {\r
+               return new RegExp('\\b' + c + (d ? '[0-9]+' : '') + '\\b', 'g').test(n.className);\r
+       },\r
+\r
+       getNum : function(n, c) {\r
+               c = n.className.match(new RegExp('\\b' + c + '([0-9]+)\\b', 'g'))[0];\r
+               c = c.replace(/[^0-9]/g, '');\r
+\r
+               return c;\r
+       },\r
+\r
+       addClass : function(n, c, b) {\r
+               var o = this.removeClass(n, c);\r
+               n.className = b ? c + (o != '' ? (' ' + o) : '') : (o != '' ? (o + ' ') : '') + c;\r
+       },\r
+\r
+       removeClass : function(n, c) {\r
+               c = n.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' ');\r
+               return n.className = c != ' ' ? c : '';\r
+       },\r
+\r
+       tags : function(f, s) {\r
+               return f.getElementsByTagName(s);\r
+       },\r
+\r
+       mark : function(f, n) {\r
+               var s = this.settings;\r
+\r
+               this.addClass(n, s.invalid_cls);\r
+               this.markLabels(f, n, s.invalid_cls);\r
+\r
+               return false;\r
+       },\r
+\r
+       markLabels : function(f, n, ic) {\r
+               var nl, i;\r
+\r
+               nl = this.tags(f, "label");\r
+               for (i=0; i<nl.length; i++) {\r
+                       if (nl[i].getAttribute("for") == n.id || nl[i].htmlFor == n.id)\r
+                               this.addClass(nl[i], ic);\r
+               }\r
+\r
+               return null;\r
+       }\r
+};\r
diff --git a/jscripts/wz_jsgraphics.js b/jscripts/wz_jsgraphics.js
new file mode 100644 (file)
index 0000000..07e0194
--- /dev/null
@@ -0,0 +1,943 @@
+/* This notice must be untouched at all times.\r
+\r
+wz_jsgraphics.js    v. 2.36\r
+The latest version is available at\r
+http://www.walterzorn.com\r
+or http://www.devira.com\r
+or http://www.walterzorn.de\r
+\r
+Copyright (c) 2002-2008 Walter Zorn. All rights reserved.\r
+Created 3. 11. 2002 by Walter Zorn (Web: http://www.walterzorn.com )\r
+Last modified: 21. 6. 2006\r
+\r
+Performance optimizations for Internet Explorer\r
+by Thomas Frank and John Holdsworth.\r
+fillPolygon method implemented by Matthieu Haller.\r
+\r
+High Performance JavaScript Graphics Library.\r
+Provides methods\r
+- to draw lines, rectangles, ellipses, polygons\r
+       with specifiable line thickness,\r
+- to fill rectangles and ellipses\r
+- to draw text.\r
+NOTE: Operations, functions and branching have rather been optimized\r
+to efficiency and speed than to shortness of source code.\r
+\r
+LICENSE: LGPL\r
+\r
+This library is free software; you can redistribute it and/or\r
+modify it under the terms of the GNU Lesser General Public\r
+License (LGPL) as published by the Free Software Foundation; either\r
+version 2.1 of the License, or (at your option) any later version.\r
+\r
+This library is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+Lesser General Public License for more details.\r
+\r
+You should have received a copy of the GNU Lesser General Public\r
+License along with this library; if not, write to the Free Software\r
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA,\r
+or see http://www.gnu.org/copyleft/lesser.html\r
+*/\r
+\r
+\r
+var jg_ihtm, jg_ie, jg_fast, jg_dom, jg_moz,\r
+jg_n4 = (document.layers && typeof document.classes != "undefined");\r
+\r
+\r
+function chkDHTM(x, i)\r
+{\r
+       x = document.body || null;\r
+       jg_ie = x && typeof x.insertAdjacentHTML != "undefined";\r
+       jg_dom = (x && !jg_ie &&\r
+               typeof x.appendChild != "undefined" &&\r
+               typeof document.createRange != "undefined" &&\r
+               typeof (i = document.createRange()).setStartBefore != "undefined" &&\r
+               typeof i.createContextualFragment != "undefined");\r
+       jg_ihtm = !jg_ie && !jg_dom && x && typeof x.innerHTML != "undefined";\r
+       jg_fast = jg_ie && document.all && !window.opera;\r
+       jg_moz = jg_dom && typeof x.style.MozOpacity != "undefined";\r
+}\r
+\r
+\r
+function pntDoc()\r
+{\r
+       this.wnd.document.write(jg_fast? this.htmRpc() : this.htm);\r
+       this.htm = '';\r
+}\r
+\r
+\r
+function pntCnvDom()\r
+{\r
+       var x = this.wnd.document.createRange();\r
+       x.setStartBefore(this.cnv);\r
+       x = x.createContextualFragment(jg_fast? this.htmRpc() : this.htm);\r
+       if(this.cnv) this.cnv.appendChild(x);\r
+       this.htm = '';\r
+}\r
+\r
+\r
+function pntCnvIe()\r
+{\r
+       if(this.cnv) this.cnv.insertAdjacentHTML("BeforeEnd", jg_fast? this.htmRpc() : this.htm);\r
+       this.htm = '';\r
+}\r
+\r
+\r
+function pntCnvIhtm()\r
+{\r
+       if(this.cnv) this.cnv.innerHTML += this.htm;\r
+       this.htm = '';\r
+}\r
+\r
+\r
+function pntCnv()\r
+{\r
+       this.htm = '';\r
+}\r
+\r
+\r
+function mkDiv(x, y, w, h)\r
+{\r
+       this.htm += '<div style="position:absolute;'+\r
+               'left:' + x + 'px;'+\r
+               'top:' + y + 'px;'+\r
+               'width:' + w + 'px;'+\r
+               'height:' + h + 'px;'+\r
+               'clip:rect(0,'+w+'px,'+h+'px,0);'+\r
+               'background-color:' + this.color +\r
+               (!jg_moz? ';overflow:hidden' : '')+\r
+               ';"><\/div>';\r
+}\r
+\r
+\r
+function mkDivIe(x, y, w, h)\r
+{\r
+       this.htm += '%%'+this.color+';'+x+';'+y+';'+w+';'+h+';';\r
+}\r
+\r
+\r
+function mkDivPrt(x, y, w, h)\r
+{\r
+       this.htm += '<div style="position:absolute;'+\r
+               'border-left:' + w + 'px solid ' + this.color + ';'+\r
+               'left:' + x + 'px;'+\r
+               'top:' + y + 'px;'+\r
+               'width:0px;'+\r
+               'height:' + h + 'px;'+\r
+               'clip:rect(0,'+w+'px,'+h+'px,0);'+\r
+               'background-color:' + this.color +\r
+               (!jg_moz? ';overflow:hidden' : '')+\r
+               ';"><\/div>';\r
+}\r
+\r
+\r
+function mkLyr(x, y, w, h)\r
+{\r
+       this.htm += '<layer '+\r
+               'left="' + x + '" '+\r
+               'top="' + y + '" '+\r
+               'width="' + w + '" '+\r
+               'height="' + h + '" '+\r
+               'bgcolor="' + this.color + '"><\/layer>\n';\r
+}\r
+\r
+\r
+var regex =  /%%([^;]+);([^;]+);([^;]+);([^;]+);([^;]+);/g;\r
+function htmRpc()\r
+{\r
+       return this.htm.replace(\r
+               regex,\r
+               '<div style="overflow:hidden;position:absolute;background-color:'+\r
+               '$1;left:$2;top:$3;width:$4;height:$5"></div>\n');\r
+}\r
+\r
+\r
+function htmPrtRpc()\r
+{\r
+       return this.htm.replace(\r
+               regex,\r
+               '<div style="overflow:hidden;position:absolute;background-color:'+\r
+               '$1;left:$2;top:$3;width:$4;height:$5;border-left:$4px solid $1"></div>\n');\r
+}\r
+\r
+\r
+function mkLin(x1, y1, x2, y2)\r
+{\r
+       if (x1 > x2)\r
+       {\r
+               var _x2 = x2;\r
+               var _y2 = y2;\r
+               x2 = x1;\r
+               y2 = y1;\r
+               x1 = _x2;\r
+               y1 = _y2;\r
+       }\r
+       var dx = x2-x1, dy = Math.abs(y2-y1),\r
+       x = x1, y = y1,\r
+       yIncr = (y1 > y2)? -1 : 1;\r
+\r
+       if (dx >= dy)\r
+       {\r
+               var pr = dy<<1,\r
+               pru = pr - (dx<<1),\r
+               p = pr-dx,\r
+               ox = x;\r
+               while ((dx--) > 0)\r
+               {\r
+                       ++x;\r
+                       if (p > 0)\r
+                       {\r
+                               this.mkDiv(ox, y, x-ox, 1);\r
+                               y += yIncr;\r
+                               p += pru;\r
+                               ox = x;\r
+                       }\r
+                       else p += pr;\r
+               }\r
+               this.mkDiv(ox, y, x2-ox+1, 1);\r
+       }\r
+\r
+       else\r
+       {\r
+               var pr = dx<<1,\r
+               pru = pr - (dy<<1),\r
+               p = pr-dy,\r
+               oy = y;\r
+               if (y2 <= y1)\r
+               {\r
+                       while ((dy--) > 0)\r
+                       {\r
+                               if (p > 0)\r
+                               {\r
+                                       this.mkDiv(x++, y, 1, oy-y+1);\r
+                                       y += yIncr;\r
+                                       p += pru;\r
+                                       oy = y;\r
+                               }\r
+                               else\r
+                               {\r
+                                       y += yIncr;\r
+                                       p += pr;\r
+                               }\r
+                       }\r
+                       this.mkDiv(x2, y2, 1, oy-y2+1);\r
+               }\r
+               else\r
+               {\r
+                       while ((dy--) > 0)\r
+                       {\r
+                               y += yIncr;\r
+                               if (p > 0)\r
+                               {\r
+                                       this.mkDiv(x++, oy, 1, y-oy);\r
+                                       p += pru;\r
+                                       oy = y;\r
+                               }\r
+                               else p += pr;\r
+                       }\r
+                       this.mkDiv(x2, oy, 1, y2-oy+1);\r
+               }\r
+       }\r
+}\r
+\r
+\r
+function mkLin2D(x1, y1, x2, y2)\r
+{\r
+       if (x1 > x2)\r
+       {\r
+               var _x2 = x2;\r
+               var _y2 = y2;\r
+               x2 = x1;\r
+               y2 = y1;\r
+               x1 = _x2;\r
+               y1 = _y2;\r
+       }\r
+       var dx = x2-x1, dy = Math.abs(y2-y1),\r
+       x = x1, y = y1,\r
+       yIncr = (y1 > y2)? -1 : 1;\r
+\r
+       var s = this.stroke;\r
+       if (dx >= dy)\r
+       {\r
+               if (dx > 0 && s-3 > 0)\r
+               {\r
+                       var _s = (s*dx*Math.sqrt(1+dy*dy/(dx*dx))-dx-(s>>1)*dy) / dx;\r
+                       _s = (!(s-4)? Math.ceil(_s) : Math.round(_s)) + 1;\r
+               }\r
+               else var _s = s;\r
+               var ad = Math.ceil(s/2);\r
+\r
+               var pr = dy<<1,\r
+               pru = pr - (dx<<1),\r
+               p = pr-dx,\r
+               ox = x;\r
+               while ((dx--) > 0)\r
+               {\r
+                       ++x;\r
+                       if (p > 0)\r
+                       {\r
+                               this.mkDiv(ox, y, x-ox+ad, _s);\r
+                               y += yIncr;\r
+                               p += pru;\r
+                               ox = x;\r
+                       }\r
+                       else p += pr;\r
+               }\r
+               this.mkDiv(ox, y, x2-ox+ad+1, _s);\r
+       }\r
+\r
+       else\r
+       {\r
+               if (s-3 > 0)\r
+               {\r
+                       var _s = (s*dy*Math.sqrt(1+dx*dx/(dy*dy))-(s>>1)*dx-dy) / dy;\r
+                       _s = (!(s-4)? Math.ceil(_s) : Math.round(_s)) + 1;\r
+               }\r
+               else var _s = s;\r
+               var ad = Math.round(s/2);\r
+\r
+               var pr = dx<<1,\r
+               pru = pr - (dy<<1),\r
+               p = pr-dy,\r
+               oy = y;\r
+               if (y2 <= y1)\r
+               {\r
+                       ++ad;\r
+                       while ((dy--) > 0)\r
+                       {\r
+                               if (p > 0)\r
+                               {\r
+                                       this.mkDiv(x++, y, _s, oy-y+ad);\r
+                                       y += yIncr;\r
+                                       p += pru;\r
+                                       oy = y;\r
+                               }\r
+                               else\r
+                               {\r
+                                       y += yIncr;\r
+                                       p += pr;\r
+                               }\r
+                       }\r
+                       this.mkDiv(x2, y2, _s, oy-y2+ad);\r
+               }\r
+               else\r
+               {\r
+                       while ((dy--) > 0)\r
+                       {\r
+                               y += yIncr;\r
+                               if (p > 0)\r
+                               {\r
+                                       this.mkDiv(x++, oy, _s, y-oy+ad);\r
+                                       p += pru;\r
+                                       oy = y;\r
+                               }\r
+                               else p += pr;\r
+                       }\r
+                       this.mkDiv(x2, oy, _s, y2-oy+ad+1);\r
+               }\r
+       }\r
+}\r
+\r
+\r
+function mkLinDott(x1, y1, x2, y2)\r
+{\r
+       if (x1 > x2)\r
+       {\r
+               var _x2 = x2;\r
+               var _y2 = y2;\r
+               x2 = x1;\r
+               y2 = y1;\r
+               x1 = _x2;\r
+               y1 = _y2;\r
+       }\r
+       var dx = x2-x1, dy = Math.abs(y2-y1),\r
+       x = x1, y = y1,\r
+       yIncr = (y1 > y2)? -1 : 1,\r
+       drw = true;\r
+       if (dx >= dy)\r
+       {\r
+               var pr = dy<<1,\r
+               pru = pr - (dx<<1),\r
+               p = pr-dx;\r
+               while ((dx--) > 0)\r
+               {\r
+                       if (drw) this.mkDiv(x, y, 1, 1);\r
+                       drw = !drw;\r
+                       if (p > 0)\r
+                       {\r
+                               y += yIncr;\r
+                               p += pru;\r
+                       }\r
+                       else p += pr;\r
+                       ++x;\r
+               }\r
+               if (drw) this.mkDiv(x, y, 1, 1);\r
+       }\r
+\r
+       else\r
+       {\r
+               var pr = dx<<1,\r
+               pru = pr - (dy<<1),\r
+               p = pr-dy;\r
+               while ((dy--) > 0)\r
+               {\r
+                       if (drw) this.mkDiv(x, y, 1, 1);\r
+                       drw = !drw;\r
+                       y += yIncr;\r
+                       if (p > 0)\r
+                       {\r
+                               ++x;\r
+                               p += pru;\r
+                       }\r
+                       else p += pr;\r
+               }\r
+               if (drw) this.mkDiv(x, y, 1, 1);\r
+       }\r
+}\r
+\r
+\r
+function mkOv(left, top, width, height)\r
+{\r
+       var a = width>>1, b = height>>1,\r
+       wod = width&1, hod = (height&1)+1,\r
+       cx = left+a, cy = top+b,\r
+       x = 0, y = b,\r
+       ox = 0, oy = b,\r
+       aa = (a*a)<<1, bb = (b*b)<<1,\r
+       st = (aa>>1)*(1-(b<<1)) + bb,\r
+       tt = (bb>>1) - aa*((b<<1)-1),\r
+       w, h;\r
+       while (y > 0)\r
+       {\r
+               if (st < 0)\r
+               {\r
+                       st += bb*((x<<1)+3);\r
+                       tt += (bb<<1)*(++x);\r
+               }\r
+               else if (tt < 0)\r
+               {\r
+                       st += bb*((x<<1)+3) - (aa<<1)*(y-1);\r
+                       tt += (bb<<1)*(++x) - aa*(((y--)<<1)-3);\r
+                       w = x-ox;\r
+                       h = oy-y;\r
+                       if (w&2 && h&2)\r
+                       {\r
+                               this.mkOvQds(cx, cy, -x+2, ox+wod, -oy, oy-1+hod, 1, 1);\r
+                               this.mkOvQds(cx, cy, -x+1, x-1+wod, -y-1, y+hod, 1, 1);\r
+                       }\r
+                       else this.mkOvQds(cx, cy, -x+1, ox+wod, -oy, oy-h+hod, w, h);\r
+                       ox = x;\r
+                       oy = y;\r
+               }\r
+               else\r
+               {\r
+                       tt -= aa*((y<<1)-3);\r
+                       st -= (aa<<1)*(--y);\r
+               }\r
+       }\r
+       this.mkDiv(cx-a, cy-oy, a-ox+1, (oy<<1)+hod);\r
+       this.mkDiv(cx+ox+wod, cy-oy, a-ox+1, (oy<<1)+hod);\r
+}\r
+\r
+\r
+function mkOv2D(left, top, width, height)\r
+{\r
+       var s = this.stroke;\r
+       width += s-1;\r
+       height += s-1;\r
+       var a = width>>1, b = height>>1,\r
+       wod = width&1, hod = (height&1)+1,\r
+       cx = left+a, cy = top+b,\r
+       x = 0, y = b,\r
+       aa = (a*a)<<1, bb = (b*b)<<1,\r
+       st = (aa>>1)*(1-(b<<1)) + bb,\r
+       tt = (bb>>1) - aa*((b<<1)-1);\r
+\r
+       if (s-4 < 0 && (!(s-2) || width-51 > 0 && height-51 > 0))\r
+       {\r
+               var ox = 0, oy = b,\r
+               w, h,\r
+               pxl, pxr, pxt, pxb, pxw;\r
+               while (y > 0)\r
+               {\r
+                       if (st < 0)\r
+                       {\r
+                               st += bb*((x<<1)+3);\r
+                               tt += (bb<<1)*(++x);\r
+                       }\r
+                       else if (tt < 0)\r
+                       {\r
+                               st += bb*((x<<1)+3) - (aa<<1)*(y-1);\r
+                               tt += (bb<<1)*(++x) - aa*(((y--)<<1)-3);\r
+                               w = x-ox;\r
+                               h = oy-y;\r
+\r
+                               if (w-1)\r
+                               {\r
+                                       pxw = w+1+(s&1);\r
+                                       h = s;\r
+                               }\r
+                               else if (h-1)\r
+                               {\r
+                                       pxw = s;\r
+                                       h += 1+(s&1);\r
+                               }\r
+                               else pxw = h = s;\r
+                               this.mkOvQds(cx, cy, -x+1, ox-pxw+w+wod, -oy, -h+oy+hod, pxw, h);\r
+                               ox = x;\r
+                               oy = y;\r
+                       }\r
+                       else\r
+                       {\r
+                               tt -= aa*((y<<1)-3);\r
+                               st -= (aa<<1)*(--y);\r
+                       }\r
+               }\r
+               this.mkDiv(cx-a, cy-oy, s, (oy<<1)+hod);\r
+               this.mkDiv(cx+a+wod-s+1, cy-oy, s, (oy<<1)+hod);\r
+       }\r
+\r
+       else\r
+       {\r
+               var _a = (width-((s-1)<<1))>>1,\r
+               _b = (height-((s-1)<<1))>>1,\r
+               _x = 0, _y = _b,\r
+               _aa = (_a*_a)<<1, _bb = (_b*_b)<<1,\r
+               _st = (_aa>>1)*(1-(_b<<1)) + _bb,\r
+               _tt = (_bb>>1) - _aa*((_b<<1)-1),\r
+\r
+               pxl = new Array(),\r
+               pxt = new Array(),\r
+               _pxb = new Array();\r
+               pxl[0] = 0;\r
+               pxt[0] = b;\r
+               _pxb[0] = _b-1;\r
+               while (y > 0)\r
+               {\r
+                       if (st < 0)\r
+                       {\r
+                               st += bb*((x<<1)+3);\r
+                               tt += (bb<<1)*(++x);\r
+                               pxl[pxl.length] = x;\r
+                               pxt[pxt.length] = y;\r
+                       }\r
+                       else if (tt < 0)\r
+                       {\r
+                               st += bb*((x<<1)+3) - (aa<<1)*(y-1);\r
+                               tt += (bb<<1)*(++x) - aa*(((y--)<<1)-3);\r
+                               pxl[pxl.length] = x;\r
+                               pxt[pxt.length] = y;\r
+                       }\r
+                       else\r
+                       {\r
+                               tt -= aa*((y<<1)-3);\r
+                               st -= (aa<<1)*(--y);\r
+                       }\r
+\r
+                       if (_y > 0)\r
+                       {\r
+                               if (_st < 0)\r
+                               {\r
+                                       _st += _bb*((_x<<1)+3);\r
+                                       _tt += (_bb<<1)*(++_x);\r
+                                       _pxb[_pxb.length] = _y-1;\r
+                               }\r
+                               else if (_tt < 0)\r
+                               {\r
+                                       _st += _bb*((_x<<1)+3) - (_aa<<1)*(_y-1);\r
+                                       _tt += (_bb<<1)*(++_x) - _aa*(((_y--)<<1)-3);\r
+                                       _pxb[_pxb.length] = _y-1;\r
+                               }\r
+                               else\r
+                               {\r
+                                       _tt -= _aa*((_y<<1)-3);\r
+                                       _st -= (_aa<<1)*(--_y);\r
+                                       _pxb[_pxb.length-1]--;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               var ox = 0, oy = b,\r
+               _oy = _pxb[0],\r
+               l = pxl.length,\r
+               w, h;\r
+               for (var i = 0; i < l; i++)\r
+               {\r
+                       if (typeof _pxb[i] != "undefined")\r
+                       {\r
+                               if (_pxb[i] < _oy || pxt[i] < oy)\r
+                               {\r
+                                       x = pxl[i];\r
+                                       this.mkOvQds(cx, cy, -x+1, ox+wod, -oy, _oy+hod, x-ox, oy-_oy);\r
+                                       ox = x;\r
+                                       oy = pxt[i];\r
+                                       _oy = _pxb[i];\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               x = pxl[i];\r
+                               this.mkDiv(cx-x+1, cy-oy, 1, (oy<<1)+hod);\r
+                               this.mkDiv(cx+ox+wod, cy-oy, 1, (oy<<1)+hod);\r
+                               ox = x;\r
+                               oy = pxt[i];\r
+                       }\r
+               }\r
+               this.mkDiv(cx-a, cy-oy, 1, (oy<<1)+hod);\r
+               this.mkDiv(cx+ox+wod, cy-oy, 1, (oy<<1)+hod);\r
+       }\r
+}\r
+\r
+\r
+function mkOvDott(left, top, width, height)\r
+{\r
+       var a = width>>1, b = height>>1,\r
+       wod = width&1, hod = height&1,\r
+       cx = left+a, cy = top+b,\r
+       x = 0, y = b,\r
+       aa2 = (a*a)<<1, aa4 = aa2<<1, bb = (b*b)<<1,\r
+       st = (aa2>>1)*(1-(b<<1)) + bb,\r
+       tt = (bb>>1) - aa2*((b<<1)-1),\r
+       drw = true;\r
+       while (y > 0)\r
+       {\r
+               if (st < 0)\r
+               {\r
+                       st += bb*((x<<1)+3);\r
+                       tt += (bb<<1)*(++x);\r
+               }\r
+               else if (tt < 0)\r
+               {\r
+                       st += bb*((x<<1)+3) - aa4*(y-1);\r
+                       tt += (bb<<1)*(++x) - aa2*(((y--)<<1)-3);\r
+               }\r
+               else\r
+               {\r
+                       tt -= aa2*((y<<1)-3);\r
+                       st -= aa4*(--y);\r
+               }\r
+               if (drw) this.mkOvQds(cx, cy, -x, x+wod, -y, y+hod, 1, 1);\r
+               drw = !drw;\r
+       }\r
+}\r
+\r
+\r
+function mkRect(x, y, w, h)\r
+{\r
+       var s = this.stroke;\r
+       this.mkDiv(x, y, w, s);\r
+       this.mkDiv(x+w, y, s, h);\r
+       this.mkDiv(x, y+h, w+s, s);\r
+       this.mkDiv(x, y+s, s, h-s);\r
+}\r
+\r
+\r
+function mkRectDott(x, y, w, h)\r
+{\r
+       this.drawLine(x, y, x+w, y);\r
+       this.drawLine(x+w, y, x+w, y+h);\r
+       this.drawLine(x, y+h, x+w, y+h);\r
+       this.drawLine(x, y, x, y+h);\r
+}\r
+\r
+\r
+function jsgFont()\r
+{\r
+       this.PLAIN = 'font-weight:normal;';\r
+       this.BOLD = 'font-weight:bold;';\r
+       this.ITALIC = 'font-style:italic;';\r
+       this.ITALIC_BOLD = this.ITALIC + this.BOLD;\r
+       this.BOLD_ITALIC = this.ITALIC_BOLD;\r
+}\r
+var Font = new jsgFont();\r
+\r
+\r
+function jsgStroke()\r
+{\r
+       this.DOTTED = -1;\r
+}\r
+var Stroke = new jsgStroke();\r
+\r
+\r
+function jsGraphics(id, wnd)\r
+{\r
+       this.setColor = new Function('arg', 'this.color = arg.toLowerCase();');\r
+\r
+       this.setStroke = function(x)\r
+       {\r
+               this.stroke = x;\r
+               if (!(x+1))\r
+               {\r
+                       this.drawLine = mkLinDott;\r
+                       this.mkOv = mkOvDott;\r
+                       this.drawRect = mkRectDott;\r
+               }\r
+               else if (x-1 > 0)\r
+               {\r
+                       this.drawLine = mkLin2D;\r
+                       this.mkOv = mkOv2D;\r
+                       this.drawRect = mkRect;\r
+               }\r
+               else\r
+               {\r
+                       this.drawLine = mkLin;\r
+                       this.mkOv = mkOv;\r
+                       this.drawRect = mkRect;\r
+               }\r
+       };\r
+\r
+\r
+       this.setPrintable = function(arg)\r
+       {\r
+               this.printable = arg;\r
+               if (jg_fast)\r
+               {\r
+                       this.mkDiv = mkDivIe;\r
+                       this.htmRpc = arg? htmPrtRpc : htmRpc;\r
+               }\r
+               else this.mkDiv = jg_n4? mkLyr : arg? mkDivPrt : mkDiv;\r
+       };\r
+\r
+\r
+       this.setFont = function(fam, sz, sty)\r
+       {\r
+               this.ftFam = fam;\r
+               this.ftSz = sz;\r
+               this.ftSty = sty || Font.PLAIN;\r
+       };\r
+\r
+\r
+       this.drawPolyline = this.drawPolyLine = function(x, y, s)\r
+       {\r
+               for (var i=0 ; i<x.length-1 ; i++ )\r
+                       this.drawLine(x[i], y[i], x[i+1], y[i+1]);\r
+       };\r
+\r
+\r
+       this.fillRect = function(x, y, w, h)\r
+       {\r
+               this.mkDiv(x, y, w, h);\r
+       };\r
+\r
+\r
+       this.drawPolygon = function(x, y)\r
+       {\r
+               this.drawPolyline(x, y);\r
+               this.drawLine(x[x.length-1], y[x.length-1], x[0], y[0]);\r
+       };\r
+\r
+\r
+       this.drawEllipse = this.drawOval = function(x, y, w, h)\r
+       {\r
+               this.mkOv(x, y, w, h);\r
+       };\r
+\r
+\r
+       this.fillEllipse = this.fillOval = function(left, top, w, h)\r
+       {\r
+               var a = (w -= 1)>>1, b = (h -= 1)>>1,\r
+               wod = (w&1)+1, hod = (h&1)+1,\r
+               cx = left+a, cy = top+b,\r
+               x = 0, y = b,\r
+               ox = 0, oy = b,\r
+               aa2 = (a*a)<<1, aa4 = aa2<<1, bb = (b*b)<<1,\r
+               st = (aa2>>1)*(1-(b<<1)) + bb,\r
+               tt = (bb>>1) - aa2*((b<<1)-1),\r
+               pxl, dw, dh;\r
+               if (w+1) while (y > 0)\r
+               {\r
+                       if (st < 0)\r
+                       {\r
+                               st += bb*((x<<1)+3);\r
+                               tt += (bb<<1)*(++x);\r
+                       }\r
+                       else if (tt < 0)\r
+                       {\r
+                               st += bb*((x<<1)+3) - aa4*(y-1);\r
+                               pxl = cx-x;\r
+                               dw = (x<<1)+wod;\r
+                               tt += (bb<<1)*(++x) - aa2*(((y--)<<1)-3);\r
+                               dh = oy-y;\r
+                               this.mkDiv(pxl, cy-oy, dw, dh);\r
+                               this.mkDiv(pxl, cy+y+hod, dw, dh);\r
+                               ox = x;\r
+                               oy = y;\r
+                       }\r
+                       else\r
+                       {\r
+                               tt -= aa2*((y<<1)-3);\r
+                               st -= aa4*(--y);\r
+                       }\r
+               }\r
+               this.mkDiv(cx-a, cy-oy, w+1, (oy<<1)+hod);\r
+       };\r
+\r
+\r
+/* fillPolygon method, implemented by Matthieu Haller.\r
+This javascript function is an adaptation of the gdImageFilledPolygon for Walter Zorn lib.\r
+C source of GD 1.8.4 found at http://www.boutell.com/gd/\r
+\r
+THANKS to Kirsten Schulz for the polygon fixes!\r
+\r
+The intersection finding technique of this code could be improved\r
+by remembering the previous intertersection, and by using the slope.\r
+That could help to adjust intersections to produce a nice\r
+interior_extrema. */\r
+       this.fillPolygon = function(array_x, array_y)\r
+       {\r
+               var i;\r
+               var y;\r
+               var miny, maxy;\r
+               var x1, y1;\r
+               var x2, y2;\r
+               var ind1, ind2;\r
+               var ints;\r
+\r
+               var n = array_x.length;\r
+\r
+               if (!n) return;\r
+\r
+\r
+               miny = array_y[0];\r
+               maxy = array_y[0];\r
+               for (i = 1; i < n; i++)\r
+               {\r
+                       if (array_y[i] < miny)\r
+                               miny = array_y[i];\r
+\r
+                       if (array_y[i] > maxy)\r
+                               maxy = array_y[i];\r
+               }\r
+               for (y = miny; y <= maxy; y++)\r
+               {\r
+                       var polyInts = new Array();\r
+                       ints = 0;\r
+                       for (i = 0; i < n; i++)\r
+                       {\r
+                               if (!i)\r
+                               {\r
+                                       ind1 = n-1;\r
+                                       ind2 = 0;\r
+                               }\r
+                               else\r
+                               {\r
+                                       ind1 = i-1;\r
+                                       ind2 = i;\r
+                               }\r
+                               y1 = array_y[ind1];\r
+                               y2 = array_y[ind2];\r
+                               if (y1 < y2)\r
+                               {\r
+                                       x1 = array_x[ind1];\r
+                                       x2 = array_x[ind2];\r
+                               }\r
+                               else if (y1 > y2)\r
+                               {\r
+                                       y2 = array_y[ind1];\r
+                                       y1 = array_y[ind2];\r
+                                       x2 = array_x[ind1];\r
+                                       x1 = array_x[ind2];\r
+                               }\r
+                               else continue;\r
+\r
+                                // modified 11. 2. 2004 Walter Zorn\r
+                               if ((y >= y1) && (y < y2))\r
+                                       polyInts[ints++] = Math.round((y-y1) * (x2-x1) / (y2-y1) + x1);\r
+\r
+                               else if ((y == maxy) && (y > y1) && (y <= y2))\r
+                                       polyInts[ints++] = Math.round((y-y1) * (x2-x1) / (y2-y1) + x1);\r
+                       }\r
+                       polyInts.sort(integer_compare);\r
+                       for (i = 0; i < ints; i+=2)\r
+                               this.mkDiv(polyInts[i], y, polyInts[i+1]-polyInts[i]+1, 1);\r
+               }\r
+       };\r
+\r
+\r
+       this.drawString = function(txt, x, y)\r
+       {\r
+               this.htm += '<div style="position:absolute;white-space:nowrap;'+\r
+                       'left:' + x + 'px;'+\r
+                       'top:' + y + 'px;'+\r
+                       'font-family:' +  this.ftFam + ';'+\r
+                       'font-size:' + this.ftSz + ';'+\r
+                       'color:' + this.color + ';' + this.ftSty + '">'+\r
+                       txt +\r
+                       '<\/div>';\r
+       };\r
+\r
+\r
+/* drawStringRect() added by Rick Blommers.\r
+Allows to specify the size of the text rectangle and to align the\r
+text both horizontally (e.g. right) and vertically within that rectangle */\r
+       this.drawStringRect = function(txt, x, y, width, halign)\r
+       {\r
+               this.htm += '<div style="position:absolute;overflow:hidden;'+\r
+                       'left:' + x + 'px;'+\r
+                       'top:' + y + 'px;'+\r
+                       'width:'+width +'px;'+\r
+                       'text-align:'+halign+';'+\r
+                       'font-family:' +  this.ftFam + ';'+\r
+                       'font-size:' + this.ftSz + ';'+\r
+                       'color:' + this.color + ';' + this.ftSty + '">'+\r
+                       txt +\r
+                       '<\/div>';\r
+       };\r
+\r
+\r
+       this.drawImage = function(imgSrc, x, y, w, h, a)\r
+       {\r
+               this.htm += '<div style="position:absolute;'+\r
+                       'left:' + x + 'px;'+\r
+                       'top:' + y + 'px;'+\r
+                       'width:' +  w + 'px;'+\r
+                       'height:' + h + 'px;">'+\r
+                       '<img src="' + imgSrc + '" width="' + w + '" height="' + h + '"' + (a? (' '+a) : '') + '>'+\r
+                       '<\/div>';\r
+       };\r
+\r
+\r
+       this.clear = function()\r
+       {\r
+               this.htm = "";\r
+               if (this.cnv) this.cnv.innerHTML = this.defhtm;\r
+       };\r
+\r
+\r
+       this.mkOvQds = function(cx, cy, xl, xr, yt, yb, w, h)\r
+       {\r
+               this.mkDiv(xr+cx, yt+cy, w, h);\r
+               this.mkDiv(xr+cx, yb+cy, w, h);\r
+               this.mkDiv(xl+cx, yb+cy, w, h);\r
+               this.mkDiv(xl+cx, yt+cy, w, h);\r
+       };\r
+\r
+       this.setStroke(1);\r
+       this.setFont('verdana,geneva,helvetica,sans-serif', String.fromCharCode(0x31, 0x32, 0x70, 0x78), Font.PLAIN);\r
+       this.color = '#000000';\r
+       this.htm = '';\r
+       this.wnd = wnd || window;\r
+\r
+       if (!(jg_ie || jg_dom || jg_ihtm)) chkDHTM();\r
+       if (typeof id != 'string' || !id) this.paint = pntDoc;\r
+       else\r
+       {\r
+               this.cnv = document.all? (this.wnd.document.all[id] || null)\r
+                       : document.getElementById? (this.wnd.document.getElementById(id) || null)\r
+                       : null;\r
+               this.defhtm = (this.cnv && this.cnv.innerHTML)? this.cnv.innerHTML : '';\r
+               this.paint = jg_dom? pntCnvDom : jg_ie? pntCnvIe : jg_ihtm? pntCnvIhtm : pntCnv;\r
+       }\r
+\r
+       this.setPrintable(false);\r
+}\r
+\r
+\r
+\r
+function integer_compare(x,y)\r
+{\r
+       return (x < y) ? -1 : ((x > y)*1);\r
+}\r
+\r
diff --git a/license/gpl_licence.txt b/license/gpl_licence.txt
new file mode 100644 (file)
index 0000000..a8ab76e
--- /dev/null
@@ -0,0 +1,280 @@
+                 GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/links/add.php b/links/add.php
new file mode 100644 (file)
index 0000000..30807c0
--- /dev/null
@@ -0,0 +1,139 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+if (!$_SESSION['enroll']) {\r
+       $msg->addInfo('NOT_ENROLLED');\r
+       require(AT_INCLUDE_PATH.'header.inc.php');\r
+       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+\r
+require (AT_INCLUDE_PATH.'lib/links.inc.php');\r
+\r
+if (!manage_links()) {\r
+       $_pages['links/index.php']['children']  = array('links/add.php');\r
+}\r
+\r
+if (!isset($_POST['url'])) {\r
+       $_POST['url'] = "http://";\r
+}\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.AT_BASE_HREF.'links/index.php');\r
+       exit;\r
+} else if (isset($_POST['add_link']) && isset($_POST['submit'])) {\r
+       $missing_fields = array();\r
+       if ($_POST['cat'] == 0 || $_POST['cat'] == '') {\r
+               $missing_fields[] = _AT('category');\r
+       }\r
+       if (trim($_POST['title']) == '') {\r
+               $missing_fields[] = _AT('title');\r
+       }\r
+       if (trim($_POST['url']) == '' || $_POST['url'] == 'http://') {\r
+               $missing_fields[] = _AT('url');\r
+       }\r
+       if (trim($_POST['description']) == '') {\r
+               $missing_fields[] = _AT('description');\r
+       }\r
+\r
+       if ($missing_fields) {\r
+               $missing_fields = implode(', ', $missing_fields);\r
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));\r
+       }\r
+\r
+\r
+       if (!$msg->containsErrors() && isset($_POST['submit'])) {\r
+\r
+               $_POST['cat'] = intval($_POST['cat']);\r
+               $_POST['title']  = $addslashes($_POST['title']);\r
+               $_POST['url'] == $addslashes($_POST['url']);\r
+               $_POST['description']  = $addslashes($_POST['description']);\r
+\r
+               $name = get_display_name($_SESSION['member_id']);\r
+               $email = '';\r
+\r
+               $approved = 0; //not approved for student submissions\r
+\r
+               $sql    = "INSERT INTO ".TABLE_PREFIX."links VALUES (NULL, $_POST[cat], '$_POST[url]', '$_POST[title]', '$_POST[description]', $approved, '$name', '$email', NOW(), 0)";\r
+               mysql_query($sql, $db);\r
+       \r
+               $msg->addFeedback('LINK_ADDED');\r
+\r
+               header('Location: '.AT_BASE_HREF.'links/index.php');\r
+               exit;\r
+       } else {\r
+               $_POST['title']  = stripslashes($_POST['title']);\r
+               $_POST['url'] == stripslashes($_POST['url']);\r
+               $_POST['description']  = stripslashes($_POST['description']);\r
+       }\r
+}\r
+$onload = 'document.form.title.focus();';\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$categories = get_link_categories();\r
+\r
+if (empty($categories)) {\r
+       $msg->addInfo('NO_LINK_CATEGORIES');\r
+       $msg->printInfos();\r
+\r
+} else {\r
+?>\r
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">\r
+<input type="hidden" name="add_link" value="true" />\r
+\r
+<div class="input-form">\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php echo _AT('title'); ?></label><br />\r
+               <input type="text" name="title" size="40" id="title" value="<?php echo $_POST['title']; ?>"/>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="cat"><?php echo _AT('category'); ?></label><br />\r
+               <select name="cat" id="cat"><?php\r
+                       if ($pcat_id) {\r
+                               $current_cat_id = $pcat_id;\r
+                               $exclude = false; /* don't exclude the children */\r
+                       } else {\r
+                               $current_cat_id = $cat_id;\r
+                               $exclude = true; /* exclude the children */\r
+                       }\r
+                       select_link_categories($categories, 0, $_POST['cat'], FALSE);\r
+                       ?>\r
+               </select>\r
+       </div>\r
+       \r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="url"><?php echo _AT('url'); ?></label><br />\r
+               <input type="text" name="url" size="40" id="url" value="<?php echo $_POST['url']; ?>" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="description"><?php echo _AT('description'); ?></label><br />\r
+               <textarea name="description" cols="55" rows="2" id="description" ><?php echo $_POST['description']; ?></textarea>\r
+       </div>\r
+       \r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('submit'); ?>" accesskey="s" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?> " />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php \r
+}      \r
+require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/links/index.php b/links/index.php
new file mode 100644 (file)
index 0000000..ec63735
--- /dev/null
@@ -0,0 +1,194 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+require (AT_INCLUDE_PATH.'lib/links.inc.php');
+
+if (!manage_links()) {
+       $_pages['links/index.php']['children']  = array('links/add.php');
+}
+
+if (isset($_GET['view'])) {
+       $_GET['view'] = intval($_GET['view']);
+       //add to the num hits
+       $sql = "SELECT Url, hits FROM ".TABLE_PREFIX."links WHERE link_id=$_GET[view]";
+       $results = mysql_query($sql,$db);
+
+       if ($row = mysql_fetch_assoc($results)) { 
+               if (!authenticate(AT_PRIV_LINKS, AT_PRIV_RETURN)) {
+
+                       $row['hits']++;
+                       $sql = "UPDATE ".TABLE_PREFIX."links SET hits=$row[hits] WHERE link_id=$_GET[view]";
+                       mysql_query($sql,$db);
+               }
+
+               //redirect
+               header('Location: ' . $row['Url']);
+               exit;
+       }
+}
+
+require (AT_INCLUDE_PATH.'header.inc.php');
+
+if ($_GET['reset_filter']) {
+       unset($_GET);
+}
+
+$_GET['cat_parent_id'] = intval($_GET['cat_parent_id']);
+
+//get appropriate categories
+$categories = get_link_categories();
+
+//ascending decscending columns...
+$page_string = '';
+$orders = array('asc' => 'desc', 'desc' => 'asc');
+$cols   = array('LinkName' => 1, 'name' => 1, 'description' => 1);
+
+if (isset($_GET['asc'])) {
+       $order = 'asc';
+       $col   = isset($cols[$_GET['asc']]) ? $_GET['asc'] : 'LinkName';
+} else if (isset($_GET['desc'])) {
+       $order = 'desc';
+       $col   = isset($cols[$_GET['desc']]) ? $_GET['desc'] : 'LinkName';
+} else {
+       // no order set
+       $order = 'asc';
+       $col   = 'LinkName';
+}
+
+//search
+if ($_GET['search']) {
+       $_GET['search'] = trim($_GET['search']);
+       $page_string .= SEP.'search='.urlencode($_GET['search']);
+       $search = $addslashes($_GET['search']);
+       $search = str_replace(array('%','_'), array('\%', '\_'), $search);
+       $search = '%'.$search.'%';
+       $search = "((LinkName LIKE '$search') OR (description LIKE '$search'))";
+} else {
+       $search = '1';
+}
+
+//view links of a child category
+if ($_GET['cat_parent_id']) {
+    $children = get_child_categories ($_GET['cat_parent_id'], $categories);
+    $cat_sql = "C.cat_id IN ($children $_GET[cat_parent_id])";
+       $parent_id = intval($_GET['cat_parent_id']);
+} else {
+    $cat_sql = '1';   
+    $parent_id = 0;    
+}
+
+//get links
+$tmp_groups = implode(',', $_SESSION['groups']);
+
+if (!empty($tmp_groups)) {
+       $sql = "SELECT * FROM ".TABLE_PREFIX."links L INNER JOIN ".TABLE_PREFIX."links_categories C USING (cat_id) WHERE ((owner_id=$_SESSION[course_id] AND owner_type=".LINK_CAT_COURSE.") OR (owner_id IN ($tmp_groups) AND owner_type=".LINK_CAT_GROUP.")) AND L.Approved=1 AND $search AND $cat_sql ORDER BY $col $order";
+} else {
+       $sql = "SELECT * FROM ".TABLE_PREFIX."links L INNER JOIN ".TABLE_PREFIX."links_categories C USING (cat_id) WHERE (owner_id=$_SESSION[course_id] AND owner_type=".LINK_CAT_COURSE.") AND L.Approved=1 AND $search AND $cat_sql ORDER BY $col $order";
+}
+$result = mysql_query($sql, $db);
+$num_results = mysql_num_rows($result);
+
+?>
+<?php if ($num_results > 0 || isset($_GET['filter'])): ?>
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+
+<div class="input-form">
+        <div class="row">
+                       <h3><?php echo _AT('results_found', $num_results); ?></h3>
+               </div>
+
+        <div class="row">
+                       <label for="category_parent"><?php echo _AT('select_cat'); ?></label>
+               <br />
+                       <?php if (!empty($categories)): ?>
+                               <select name="cat_parent_id" id="category_parent"><?php
+                                               if ($parent_id) {
+                                                       $current_cat_id = $parent_id;
+                                                       $exclude = false; /* don't exclude the children */
+                                               } else {
+                                                       $current_cat_id = $cat_id;
+                                                       $exclude = true; /* exclude the children */
+                                               }
+
+                                               echo '<option value="0">&nbsp;&nbsp;&nbsp; '._AT('cats_all').' &nbsp;&nbsp;&nbsp;</option>';
+                                               select_link_categories($categories, 0, $current_cat_id, FALSE);
+                                       ?>
+                               </select>
+                       <?php endif; ?>
+               </div>
+
+               <div class="row">
+                       <label for="search"><?php echo _AT('search'); ?> (<?php echo _AT('title').', '._AT('description'); ?>)</label><br />
+                       <input type="text" name="search" id="search" size="20" value="<?php echo htmlspecialchars($_GET['search']); ?>" />
+               </div>
+
+
+               <div class="row buttons">
+                       <input type="submit" name="filter" value="<?php echo _AT('filter'); ?>" />
+                       <input type="submit" name="reset_filter" value="<?php echo _AT('reset_filter'); ?>" />
+               </div>
+</div>
+</form>
+<?php endif; ?>
+
+<table class="data static" summary="" rules="cols">
+<colgroup>
+       <?php if ($col == 'LinkName'): ?>
+               <col class="sort" />
+               <col span="2" />
+       <?php elseif($col == 'name'): ?>
+               <col />
+               <col class="sort" />
+               <col />
+       <?php elseif($col == 'description'): ?>
+               <col span="2" />
+               <col class="sort" />
+       <?php endif; ?>
+</colgroup>
+<thead>
+<tr>
+       <th scope="col"><a href="<?php echo url_rewrite('links/index.php?'.$orders[$order].'=LinkName'.$page_string); ?>"><?php echo _AT('title');          ?></a></th>
+       <th scope="col"><a href="<?php echo url_rewrite('links/index.php?'.$orders[$order].'=name'.$page_string); ?>"><?php echo _AT('category');           ?></a></th>
+       <th scope="col"><a href="<?php echo url_rewrite('links/index.php?'.$orders[$order].'=description'.$page_string); ?>"><?php echo _AT('description'); ?></a></th>
+</tr>
+</thead>
+<tbody>
+       <?php if ($row = mysql_fetch_assoc($result)) : ?>
+       <?php
+       do {
+               ?>
+               <tr onmousedown="document.form['m<?php echo $row['link_id']; ?>'].checked = true;">
+                       <td><a href="<?php echo url_rewrite('links/index.php?view='.$row['link_id']); ?>" target="_new" title="<?php echo AT_print($row['LinkName'], 'links.LinkName'); ?>"><?php echo AT_print($row['LinkName'], 'links.LinkName'); ?></a></td>
+                       <td><?php 
+                               if (empty($row['name'])) {
+                                       $row['name'] = get_group_name($row['owner_id']);
+                               }
+                               echo AT_print($row['name'], 'links.name'); 
+                       ?></td>
+                       <td><?php echo AT_print($row['Description'], 'links.Description'); ?></td>
+               </tr>
+       <?php 
+               } while ($row = mysql_fetch_assoc($result)); ?>
+       <?php else: ?>
+               <tr>
+                       <td colspan="3"><?php echo _AT('none_found'); ?></td>
+               </tr>
+       <?php endif; ?>
+</tbody>
+</table>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/login.php b/login.php
new file mode 100644 (file)
index 0000000..8c6ee6f
--- /dev/null
+++ b/login.php
@@ -0,0 +1,164 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+$_user_location        = 'public';
+define('AT_INCLUDE_PATH', 'include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+if (isset($_GET['course'])) {
+       $_GET['course'] = intval($_GET['course']);
+} else {
+       $_GET['course'] = 0;
+}
+
+// check if we have a cookie
+if (!$msg->containsFeedbacks()) {
+       if (isset($_COOKIE['ATLogin'])) {
+               $cookie_login = $_COOKIE['ATLogin'];
+       }
+       if (isset($_COOKIE['ATPass'])) {
+               $cookie_pass  = $_COOKIE['ATPass'];
+       }
+}
+
+if (!isset($_SESSION['token']) || !$_SESSION['token']) {
+       $_SESSION['token'] = sha1(mt_rand());
+}
+
+if (isset($cookie_login, $cookie_pass) && !isset($_POST['submit'])) {
+       /* auto login */
+       $this_login             = $cookie_login;
+       $this_password  = $cookie_pass;
+       $auto_login             = 1;
+       $used_cookie    = true;
+} else if (isset($_POST['submit'])) {
+       /* form post login */
+       $this_password = $_POST['form_password_hidden'];
+       $this_login             = $_POST['form_login'];
+       $auto_login             = isset($_POST['auto']) ? intval($_POST['auto']) : 0;
+       $used_cookie    = false;
+}
+
+if (isset($this_login, $this_password)) {
+       if (version_compare(PHP_VERSION, '5.1.0', '>=')) {
+               session_regenerate_id(TRUE);
+       }
+
+
+       if ($_GET['course']) {
+               $_POST['form_course_id'] = intval($_GET['course']);
+       } else {
+               $_POST['form_course_id'] = intval($_POST['form_course_id']);
+       }
+       $this_login    = $addslashes($this_login);
+       $this_password = $addslashes($this_password);
+
+       if ($used_cookie) {
+               // check if that cookie is valid
+               //$sql = "SELECT member_id, login, first_name, second_name, last_name, preferences, password AS pass, language, status FROM ".TABLE_PREFIX."members WHERE login='$this_login' AND password='$this_password'";
+               $sql = "SELECT member_id, login, first_name, second_name, last_name, preferences,password AS pass, language, status FROM ".TABLE_PREFIX."members WHERE login='$this_login' AND password='$this_password'";
+       } else {
+//echo DB_PASSWORD;
+//exit;
+               $sql = "SELECT member_id, login, first_name, second_name, last_name, preferences, language, status, password AS pass FROM ".TABLE_PREFIX."members WHERE (login='$this_login' OR email='$this_login') AND password='$this_password'";
+       }
+       $result = mysql_query($sql, $db);
+
+       if (($row = mysql_fetch_assoc($result)) && ($row['status'] == AT_STATUS_UNCONFIRMED)) {
+               $msg->addError('NOT_CONFIRMED');
+       } else if ($row && $row['status'] == AT_STATUS_DISABLED) {
+               $msg->addError('ACCOUNT_DISABLED');
+       } else if ($row) {
+               $_SESSION['valid_user'] = true;
+               $_SESSION['member_id']  = intval($row['member_id']);
+               $_SESSION['login']              = $row['login'];
+               assign_session_prefs(unserialize(stripslashes($row['preferences'])));
+               $_SESSION['is_guest']   = 0;
+               $_SESSION['lang']               = $row['language'];
+               $_SESSION['course_id']  = 0;
+
+               if ($auto_login == 1) {
+                       $parts = parse_url($_base_href);
+                       // update the cookie.. increment to another 2 days
+                       $cookie_expire = time()+172800;
+                       setcookie('ATLogin', $this_login, $cookie_expire, $parts['path'], $parts['host'], 0);
+                       setcookie('ATPass',  $row['pass'],  $cookie_expire, $parts['path'], $parts['host'], 0);
+               }
+
+               $sql = "UPDATE ".TABLE_PREFIX."members SET creation_date=creation_date, last_login=NOW() WHERE member_id=$_SESSION[member_id]";
+               mysql_query($sql, $db);
+
+               $msg->addFeedback('LOGIN_SUCCESS');
+               header('Location: bounce.php?course='.$_POST['form_course_id']);
+               exit;
+       } else {
+               // check if it's an admin login.
+               $sql = "SELECT login, `privileges`, language FROM ".TABLE_PREFIX."admins WHERE login='$this_login' AND password='$this_password' AND `privileges`>0";
+               $result = mysql_query($sql, $db);
+
+               if ($row = mysql_fetch_assoc($result)) {
+                       $sql = "UPDATE ".TABLE_PREFIX."admins SET last_login=NOW() WHERE login='$this_login'";
+                       mysql_query($sql, $db);
+
+                       $_SESSION['login']              = $row['login'];
+                       $_SESSION['valid_user'] = true;
+                       $_SESSION['course_id']  = -1;
+                       $_SESSION['privileges'] = intval($row['privileges']);
+                       $_SESSION['lang'] = $row['language'];
+
+                       write_to_log(AT_ADMIN_LOG_UPDATE, 'admins', mysql_affected_rows($db), $sql);
+
+                       $msg->addFeedback('LOGIN_SUCCESS');
+
+                       header('Location: admin/index.php');
+                       exit;
+
+               } else {
+                       $msg->addError('INVALID_LOGIN');
+               }
+       }
+}
+
+$_SESSION['session_test'] = TRUE;
+
+if (isset($_SESSION['member_id'])) {
+       $sql = "DELETE FROM ".TABLE_PREFIX."users_online WHERE member_id=$_SESSION[member_id]";
+       $result = @mysql_query($sql, $db);
+}
+
+unset($_SESSION['login']);
+unset($_SESSION['valid_user']);
+unset($_SESSION['member_id']);
+unset($_SESSION['is_admin']);
+unset($_SESSION['course_id']);
+unset($_SESSION['is_super_admin']);
+
+$_SESSION['prefs']['PREF_FORM_FOCUS'] = 1;
+
+/*****************************/
+/* template starts down here */
+
+$onload = 'document.form.form_login.focus();';
+
+$savant->assign('course_id', $_GET['course']);
+
+if (isset($_GET['course']) && $_GET['course']) {
+       $savant->assign('title',  ' '._AT('to1').' '.$system_courses[$_GET['course']]['title']);
+} else {
+       $savant->assign('title',  ' ');
+}
+
+header('P3P: CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA"');
+$savant->display('login.tmpl.php');
+?>
diff --git a/logout.php b/logout.php
new file mode 100644 (file)
index 0000000..e30137c
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                             */
+/*                                                              */
+/* 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.                */
+/****************************************************************/
+// $Id$
+
+$_user_location        = 'public';
+define('AT_INCLUDE_PATH', 'include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+$sql = "DELETE FROM ".TABLE_PREFIX."users_online WHERE member_id=$_SESSION[member_id]";
+@mysql_query($sql, $db);
+
+unset($_SESSION['login']);
+unset($_SESSION['valid_user']);
+unset($_SESSION['member_id']);
+unset($_SESSION['is_admin']);
+unset($_SESSION['course_id']);
+unset($_SESSION['prefs']);
+
+$msg->addFeedback('LOGOUT');
+header('Location: login.php');
+exit;
+
+?>
\ No newline at end of file
diff --git a/mods/_core/backups/module.php b/mods/_core/backups/module.php
new file mode 100644 (file)
index 0000000..40e1c62
--- /dev/null
@@ -0,0 +1,61 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_ADMIN_PRIV_BACKUPS', $this->getAdminPrivilege());\r
+\r
+if (admin_authenticate(AT_ADMIN_PRIV_BACKUPS, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+       if (admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+               $this->_pages['admin/courses.php']['children'] = array('admin/backup/index.php');\r
+               $this->_pages['admin/backup/index.php']['parent']    = 'admin/courses.php';\r
+       } else {\r
+               $this->_pages[AT_NAV_ADMIN] = array('admin/backup/index.php');\r
+               $this->_pages['admin/backup/index.php']['parent'] = AT_NAV_ADMIN;\r
+       }\r
+\r
+       $this->_pages['admin/backup/index.php']['title_var'] = 'backups';\r
+       $this->_pages['admin/backup/index.php']['guide']     = 'admin/?p=backups.php';\r
+       $this->_pages['admin/backup/index.php']['children']  = array('admin/backup/create.php');\r
+\r
+               $this->_pages['admin/backup/create.php']['title_var'] = 'create_backup';\r
+               $this->_pages['admin/backup/create.php']['parent']    = 'admin/backup/index.php';\r
+               $this->_pages['admin/backup/create.php']['guide']     = 'admin/?p=backups.php';\r
+\r
+               // this item is a bit iffy:\r
+               $this->_pages['admin/backup/restore.php']['title_var'] = 'restore';\r
+               $this->_pages['admin/backup/restore.php']['parent']    = 'admin/backup/index.php';\r
+               $this->_pages['admin/backup/restore.php']['guide']     = 'admin/?p=backups.php';\r
+\r
+               $this->_pages['admin/backup/delete.php']['title_var'] = 'delete';\r
+               $this->_pages['admin/backup/delete.php']['parent']    = 'admin/backup/index.php';\r
+\r
+               $this->_pages['admin/backup/edit.php']['title_var'] = 'edit';\r
+               $this->_pages['admin/backup/edit.php']['parent']    = 'admin/backup/index.php';\r
+}\r
+//instructor pages\r
+$this->_pages['tools/backup/index.php']['title_var'] = 'backups';\r
+$this->_pages['tools/backup/index.php']['guide']     = 'instructor/?p=backups.php';\r
+$this->_pages['tools/backup/index.php']['parent']    = 'tools/index.php';\r
+$this->_pages['tools/backup/index.php']['children']  = array('tools/backup/create.php', 'tools/backup/upload.php');\r
+\r
+       $this->_pages['tools/backup/create.php']['title_var'] = 'create';\r
+       $this->_pages['tools/backup/create.php']['parent']    = 'tools/backup/index.php';\r
+       $this->_pages['tools/backup/create.php']['guide']     = 'instructor/?p=creating_restoring.php';\r
+\r
+       $this->_pages['tools/backup/upload.php']['title_var']  = 'upload';\r
+       $this->_pages['tools/backup/upload.php']['parent'] = 'tools/backup/index.php';\r
+       $this->_pages['tools/backup/upload.php']['guide'] = 'instructor/?p=downloading_uploading.php';\r
+\r
+       $this->_pages['tools/backup/restore.php']['title_var']  = 'restore';\r
+       $this->_pages['tools/backup/restore.php']['parent'] = 'tools/backup/index.php';\r
+       $this->_pages['tools/backup/restore.php']['guide'] = 'instructor/?p=creating_restoring.php';\r
+\r
+       $this->_pages['tools/backup/edit.php']['title_var']  = 'edit';\r
+       $this->_pages['tools/backup/edit.php']['parent'] = 'tools/backup/index.php';\r
+       $this->_pages['tools/backup/edit.php']['guide'] = 'instructor/?p=editing_deleting.php';\r
+\r
+       $this->_pages['tools/backup/delete.php']['title_var']  = 'delete';\r
+       $this->_pages['tools/backup/delete.php']['parent'] = 'tools/backup/index.php';                          \r
+       $this->_pages['tools/backup/delete.php']['guide'] = 'instructor/?p=editing_deleting.php';\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/backups/module.xml b/mods/_core/backups/module.xml
new file mode 100644 (file)
index 0000000..1dd9c80
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Backups</name> \r
+    <description lang="en">Allows instructors and administrators to create and restore course backups.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege>existing</instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-22</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_core/backups/module_delete.php b/mods/_core/backups/module_delete.php
new file mode 100644 (file)
index 0000000..a702984
--- /dev/null
@@ -0,0 +1,14 @@
+<?php\r
+\r
+function backups_delete($course) {\r
+       global $db;\r
+\r
+       $path = AT_BACKUP_DIR . $course . '/';\r
+       clr_dir($path);\r
+\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."backups WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/cats_categories/module.php b/mods/_core/cats_categories/module.php
new file mode 100644 (file)
index 0000000..8fab66b
--- /dev/null
@@ -0,0 +1,30 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_ADMIN_PRIV_CATEGORIES', $this->getAdminPrivilege());\r
+\r
+if (admin_authenticate(AT_ADMIN_PRIV_CATEGORIES, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+       if (admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+               $this->_pages['admin/courses.php']['children'] = array('admin/course_categories.php');\r
+               $this->_pages['admin/course_categories.php']['parent']    = 'admin/courses.php';\r
+       } else {\r
+               $this->_pages[AT_NAV_ADMIN] = array('admin/course_categories.php');\r
+               $this->_pages['admin/course_categories.php']['parent'] = AT_NAV_ADMIN;\r
+       }\r
+\r
+$this->_pages['admin/course_categories.php']['title_var'] = 'cats_categories';\r
+$this->_pages['admin/course_categories.php']['guide']     = 'admin/?p=categories.php';\r
+$this->_pages['admin/course_categories.php']['children']  = array('admin/create_category.php');\r
+\r
+       $this->_pages['admin/create_category.php']['title_var'] = 'create_category';\r
+       $this->_pages['admin/create_category.php']['parent']    = 'admin/course_categories.php';\r
+\r
+       $this->_pages['admin/edit_category.php']['title_var'] = 'edit_category';\r
+       $this->_pages['admin/edit_category.php']['parent']    = 'admin/course_categories.php';\r
+\r
+       $this->_pages['admin/delete_category.php']['title_var'] = 'delete_category';\r
+       $this->_pages['admin/delete_category.php']['parent']    = 'admin/course_categories.php';\r
+\r
+}\r
+?>
\ No newline at end of file
diff --git a/mods/_core/cats_categories/module.xml b/mods/_core/cats_categories/module.xml
new file mode 100644 (file)
index 0000000..fb10b7a
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Course Categories</name> \r
+    <description lang="en">Administrators can create categories for courses, making courses easier to find and organise in the Browse Courses page. If "Theme Specific Categories" is enabled in the system configuration, all courses within a specific category will be displayed with a common theme. </description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege></instructor_privilege>\r
+                       <admin_privilege>create</admin_privilege> \r
+               </privileges>\r
+        <date>2005-09-19</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_core/content/module.php b/mods/_core/content/module.php
new file mode 100644 (file)
index 0000000..6c3e738
--- /dev/null
@@ -0,0 +1,33 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+if (!defined('AT_PRIV_CONTENT')) {\r
+       define('AT_PRIV_CONTENT', $this->getPrivilege());\r
+}\r
+\r
+//side menu dropdowns\r
+$this->_stacks['menu_menu'] = array('title_var'=>'menu_menu', 'file'=>AT_INCLUDE_PATH.'html/dropdowns/menu_menu.inc.php');\r
+$this->_stacks['related_topics'] = array('title_var'=>'related_topics', 'file'=>AT_INCLUDE_PATH.'html/dropdowns/related_topics.inc.php');\r
+$this->_stacks['search'] = array('title_var'=>'search', 'file'=>AT_INCLUDE_PATH.'html/dropdowns/search.inc.php');\r
+\r
+\r
+$this->_pages['search.php']['title_var']      = 'search';\r
+\r
+$this->_pages['tools/content/index.php']['title_var'] = 'content';\r
+$this->_pages['tools/content/index.php']['parent']    = 'tools/index.php';\r
+$this->_pages['tools/content/index.php']['guide']     = 'instructor/?p=content.php';\r
+$this->_pages['tools/content/index.php']['children']  = array('editor/add_content.php', 'tools/ims/index.php');\r
+\r
+       $this->_pages['editor/add_content.php']['title_var']    = 'add_content';\r
+       $this->_pages['editor/add_content.php']['parent']   = 'tools/content/index.php';\r
+       $this->_pages['editor/add_content.php']['guide']     = 'instructor/?p=creating_editing_content.php';\r
+\r
+       $this->_pages['editor/edit_content.php']['title_var'] = 'edit_content';\r
+       $this->_pages['editor/edit_content.php']['parent']    = 'tools/content/index.php';\r
+       $this->_pages['editor/edit_content.php']['guide']     = 'instructor/?p=creating_editing_content.php';\r
+\r
+       $this->_pages['editor/delete_content.php']['title_var'] = 'delete_content';\r
+       $this->_pages['editor/delete_content.php']['parent']    = 'tools/content/index.php';\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/content/module.xml b/mods/_core/content/module.xml
new file mode 100644 (file)
index 0000000..750bcc5
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Content Pages</name> \r
+    <description lang="en">Displays the course material via content pages, created and editable by the instructor.  Instructors and students are also able to export specific content pages. Statistics of which content pages students have viewed are also avaiable in "My Tracker".</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege>create</instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-25</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_core/content/module_backup.php b/mods/_core/content/module_backup.php
new file mode 100644 (file)
index 0000000..e7f56c8
--- /dev/null
@@ -0,0 +1,54 @@
+<?php\r
+\r
+$sql = array();\r
+\r
+$sql['content'] = 'SELECT content_id, content_parent_id, ordering, last_modified, revision, formatting, release_date, keywords, content_path, title, text, head, use_customized_head FROM '.TABLE_PREFIX.'content WHERE course_id=? ORDER BY content_parent_id, ordering';\r
+\r
+$sql['related_content'] = 'SELECT R.content_id, R.related_content_id FROM '.TABLE_PREFIX.'related_content R, '.TABLE_PREFIX.'content C WHERE C.course_id=? AND R.content_id=C.content_id ORDER BY R.content_id ASC';\r
+\r
+function related_content_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0] = $table_id_map['content'][$row[0]];\r
+       $new_row[1] = $table_id_map['content'][$row[1]];\r
+\r
+       return $new_row;\r
+}\r
+\r
+function content_convert($row, $course_id, $table_id_map, $version) {\r
+       static $order;\r
+\r
+       if (!isset($order)) {\r
+               global $db;\r
+               $sql     = 'SELECT MAX(ordering) AS ordering FROM '.TABLE_PREFIX.'content WHERE content_parent_id=0 AND course_id='.$course_id;\r
+               $result  = mysql_query($sql, $db);\r
+               $tmp_row = mysql_fetch_assoc($result);\r
+               $order   = $tmp_row['ordering'] + 1;\r
+       }\r
+\r
+       $new_row = array();\r
+       $new_row[0] = $row[0];\r
+       $new_row[1] = $course_id;\r
+       if ($row[1] == 0) {\r
+               $new_row[2] = 0;\r
+               $new_row[3] = $order;\r
+               $order++;\r
+       } else {\r
+               $new_row[2] = $table_id_map['content'][$row[1]];\r
+               $new_row[3] = $row[2];\r
+       }\r
+\r
+       $new_row[4] = $row[3];\r
+       $new_row[5] = $row[4];\r
+       $new_row[6] = $row[5];\r
+       $new_row[7] = $row[6];\r
+       $new_row[8] = $row[7];\r
+       $new_row[9] = $row[8];\r
+       $new_row[10] = $row[9];\r
+       $new_row[11] = $row[10];\r
+       $new_row[12] = $row[11];\r
+       $new_row[13] = $row[12];\r
+\r
+       return $new_row;\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/content/module_delete.php b/mods/_core/content/module_delete.php
new file mode 100644 (file)
index 0000000..6f06fa9
--- /dev/null
@@ -0,0 +1,25 @@
+<?php\r
+\r
+function content_delete($course) {\r
+       global $db;\r
+\r
+       // related_content + content:\r
+       $sql    = "SELECT content_id FROM ".TABLE_PREFIX."content WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+       while ($row = mysql_fetch_array($result)) {\r
+               $sql    = "DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$row[0]";\r
+               $result2 = mysql_query($sql, $db);\r
+\r
+               $sql3    = "DELETE FROM ".TABLE_PREFIX."member_track WHERE content_id=$row[0]";\r
+               $result3 = mysql_query($sql3, $db);\r
+       }\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."content WHERE course_id=$course";\r
+       $result = mysql_query($sql,$db);\r
+\r
+       $sql = "OPTIMIZE TABLE ".TABLE_PREFIX."content";\r
+       $result = @mysql_query($sql, $db);\r
+\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/content_packaging/module.php b/mods/_core/content_packaging/module.php
new file mode 100644 (file)
index 0000000..feb40ba
--- /dev/null
@@ -0,0 +1,18 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+// if this module is to be made available to students on the Home or Main Navigation\r
+$_student_tool = 'export.php';\r
+\r
+//instructors\r
+$this->_pages['tools/ims/index.php']['title_var'] = 'content_packaging';\r
+$this->_pages['tools/ims/index.php']['parent']    = 'tools/content/index.php';\r
+$this->_pages['tools/ims/index.php']['guide']     = 'instructor/?p=content_packages.php';\r
+\r
+//students\r
+$this->_pages['export.php']['title_var'] = 'export_content';\r
+$this->_pages['export.php']['img']       = 'images/home-export_content.gif';\r
+$this->_pages['export.php']['guide']     = 'general/?p=export_content.php';\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/content_packaging/module.xml b/mods/_core/content_packaging/module.xml
new file mode 100644 (file)
index 0000000..636e6b3
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Import/Export Content</name> \r
+    <description lang="en">Instructors can import or export content packages.  Students can export content into content packages for offline viewing or reference.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+        <use_privilege>true</use_privilege> \r
+        <date>2005-08-25</date> \r
+        <state>stable</state> \r
+        <notes></notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_core/courses/module.php b/mods/_core/courses/module.php
new file mode 100644 (file)
index 0000000..8863f5c
--- /dev/null
@@ -0,0 +1,41 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+if (!defined('AT_PRIV_ADMIN')) {\r
+       define('AT_PRIV_ADMIN', $this->getPrivilege());\r
+}\r
+if (!defined('AT_ADMIN_PRIV_COURSES')) {\r
+       define('AT_ADMIN_PRIV_COURSES', $this->getAdminPrivilege());\r
+}\r
+\r
+\r
+// for admin\r
+if (admin_authenticate(AT_ADMIN_PRIV_COURSES, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+\r
+       $this->_pages[AT_NAV_ADMIN] = array('admin/courses.php');\r
+\r
+       $this->_pages['admin/courses.php']['title_var'] = 'courses';\r
+       $this->_pages['admin/courses.php']['parent']    = AT_NAV_ADMIN;\r
+       $this->_pages['admin/courses.php']['guide']     = 'admin/?p=courses.php';\r
+       $this->_pages['admin/courses.php']['children']  = array('admin/create_course.php', 'admin/modules/default_mods.php', 'admin/modules/default_side.php');\r
+\r
+               $this->_pages['admin/instructor_login.php']['title_var'] = 'view';\r
+               $this->_pages['admin/instructor_login.php']['parent']    = 'admin/courses.php';\r
+\r
+               $this->_pages['admin/create_course.php']['title_var'] = 'create_course';\r
+               $this->_pages['admin/create_course.php']['parent']    = 'admin/courses.php';\r
+               $this->_pages['admin/create_course.php']['guide']     = 'admin/?p=creating_courses.php';\r
+\r
+               $_pages['admin/modules/default_mods.php']['title_var'] = 'default_modules';\r
+               $_pages['admin/modules/default_mods.php']['parent']    = 'admin/courses.php';\r
+               $_pages['admin/modules/default_mods.php']['guide']     = 'admin/?p=default_student_tools.php';\r
+\r
+               $_pages['admin/modules/default_side.php']['title_var'] = 'default_side_menu';\r
+               $_pages['admin/modules/default_side.php']['parent']    = 'admin/courses.php';\r
+               $_pages['admin/modules/default_side.php']['guide']     = 'admin/?p=default_side_menu.php';\r
+\r
+}\r
+//what about delete course (in properties) ?\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/courses/module.xml b/mods/_core/courses/module.xml
new file mode 100644 (file)
index 0000000..5fb3735
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Courses Admin</name> \r
+    <description lang="en">Allows administrators to manage the courses on a system. </description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege></instructor_privilege>\r
+                       <admin_privilege>create</admin_privilege> \r
+               </privileges>\r
+        <date>2005-09-12</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_core/enrolment/module.php b/mods/_core/enrolment/module.php
new file mode 100644 (file)
index 0000000..7eb6a26
--- /dev/null
@@ -0,0 +1,54 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_PRIV_ENROLLMENT', $this->getPrivilege());\r
+define('AT_ADMIN_PRIV_ENROLLMENT', $this->getAdminPrivilege());\r
+\r
+$this->_stacks['users_online'] = array('title_var'=>'users_online', 'file'=>AT_INCLUDE_PATH.'html/dropdowns/users_online.inc.php');\r
+\r
+if (admin_authenticate(AT_ADMIN_PRIV_ENROLLMENT, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+       $this->_pages[AT_NAV_ADMIN] = array('admin/enrollment/index.php');\r
+       $this->_pages['admin/enrollment/index.php']['parent'] = AT_NAV_ADMIN;\r
+\r
+       $this->_pages['admin/enrollment/index.php']['title_var'] = 'enrollment';\r
+       $this->_pages['admin/enrollment/index.php']['parent']    = AT_NAV_ADMIN;\r
+       $this->_pages['admin/enrollment/index.php']['guide']     = 'admin/?p=enrollment.php';\r
+\r
+       $this->_pages['admin/enrollment/enroll_edit.php']['title_var']    = 'enrollment';\r
+       $this->_pages['admin/enrollment/enroll_edit.php']['parent']   = 'admin/enrollment/index.php';\r
+\r
+       $this->_pages['admin/enrollment/privileges.php']['title_var'] = 'privileges';\r
+       $this->_pages['admin/enrollment/privileges.php']['parent']    = 'admin/enrollment/index.php';\r
+       $this->_pages['admin/enrollment/privileges.php']['guide']     = 'admin/?p=enrollment_privileges.php';\r
+\r
+       // linked from users.php\r
+       $this->_pages['admin/user_enrollment.php']['title_var'] = 'enrollment';\r
+       $this->_pages['admin/user_enrollment.php']['parent']    = 'admin/users.php';\r
+}\r
+\r
+$this->_pages['tools/enrollment/index.php']['title_var'] = 'enrollment';\r
+$this->_pages['tools/enrollment/index.php']['parent']    = 'tools/index.php';\r
+$this->_pages['tools/enrollment/index.php']['guide']     = 'instructor/?p=enrollment.php';\r
+$this->_pages['tools/enrollment/index.php']['children'] = array('tools/enrollment/export_course_list.php', 'tools/enrollment/import_course_list.php', 'tools/enrollment/create_course_list.php');\r
+\r
+       $this->_pages['tools/enrollment/export_course_list.php']['title_var'] = 'list_export_course_list';\r
+       $this->_pages['tools/enrollment/export_course_list.php']['parent']    = 'tools/enrollment/index.php';\r
+\r
+       $this->_pages['tools/enrollment/import_course_list.php']['title_var'] = 'list_import_course_list';\r
+       $this->_pages['tools/enrollment/import_course_list.php']['parent']    = 'tools/enrollment/index.php';\r
+\r
+       $this->_pages['tools/enrollment/create_course_list.php']['title_var'] = 'list_create_course_list';\r
+       $this->_pages['tools/enrollment/create_course_list.php']['parent']    = 'tools/enrollment/index.php';\r
+\r
+       $this->_pages['tools/enrollment/verify_list.php']['title_var']  = 'course_list';\r
+       $this->_pages['tools/enrollment/verify_list.php']['parent'] = 'tools/enrollment/index.php';\r
+\r
+       $this->_pages['tools/enrollment/privileges.php']['title_var']  = 'privileges';\r
+       $this->_pages['tools/enrollment/privileges.php']['parent'] = 'tools/enrollment/index.php';\r
+       $this->_pages['tools/enrollment/privileges.php']['guide']     = 'instructor/?p=enrollment_privileges.php';\r
+       \r
+       $this->_pages['tools/enrollment/enroll_edit.php']['title_var']    = 'enrollment';\r
+       $this->_pages['tools/enrollment/enroll_edit.php']['parent']   = 'tools/enrollment/index.php';\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/enrolment/module.xml b/mods/_core/enrolment/module.xml
new file mode 100644 (file)
index 0000000..617b7e4
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Enrollment</name> \r
+    <description lang="en">Instructors can manage those enrolled in a course and set individual privileges.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege>create</instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-25</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_core/enrolment/module_delete.php b/mods/_core/enrolment/module_delete.php
new file mode 100644 (file)
index 0000000..237f5ec
--- /dev/null
@@ -0,0 +1,13 @@
+<?php\r
+\r
+function enrolment_delete($course) {\r
+       global $db;\r
+\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."course_enrollment WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."auto_enroll_courses WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/file_manager/module.php b/mods/_core/file_manager/module.php
new file mode 100644 (file)
index 0000000..5d07c1c
--- /dev/null
@@ -0,0 +1,30 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_PRIV_FILES', $this->getPrivilege());\r
+\r
+$this->_pages['tools/filemanager/index.php']['title_var'] = 'file_manager';\r
+$this->_pages['tools/filemanager/index.php']['parent']    = 'tools/index.php';\r
+$this->_pages['tools/filemanager/index.php']['guide']     = 'instructor/?p=file_manager.php';\r
+$this->_pages['tools/filemanager/index.php']['children']  = array('tools/filemanager/new.php');\r
+\r
+       $this->_pages['tools/filemanager/new.php']['title_var'] = 'create_new_file';\r
+       $this->_pages['tools/filemanager/new.php']['parent']    = 'tools/filemanager/index.php';\r
+\r
+       $this->_pages['tools/filemanager/zip.php']['title_var'] = 'zip_file_manager';\r
+       $this->_pages['tools/filemanager/zip.php']['parent']    = 'tools/filemanager/index.php';\r
+\r
+       $this->_pages['tools/filemanager/rename.php']['title_var'] = 'rename';\r
+       $this->_pages['tools/filemanager/rename.php']['parent']    = 'tools/filemanager/index.php';\r
+\r
+       $this->_pages['tools/filemanager/move.php']['title_var'] = 'move';\r
+       $this->_pages['tools/filemanager/move.php']['parent']    = 'tools/filemanager/index.php';\r
+\r
+       $this->_pages['tools/filemanager/edit.php']['title_var'] = 'edit';\r
+       $this->_pages['tools/filemanager/edit.php']['parent']    = 'tools/filemanager/index.php';\r
+\r
+       $this->_pages['tools/filemanager/delete.php']['title_var'] = 'delete';\r
+       $this->_pages['tools/filemanager/delete.php']['parent']    = 'tools/filemanager/index.php';\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/file_manager/module.xml b/mods/_core/file_manager/module.xml
new file mode 100644 (file)
index 0000000..70bed1c
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">File Manager</name> \r
+    <description lang="en">Allows an instructor to upload and manage files for a course.  Files can then be made available to students by linking them into content pages.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege>create</instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-25</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_core/file_manager/module_backup.php b/mods/_core/file_manager/module_backup.php
new file mode 100644 (file)
index 0000000..73f7e86
--- /dev/null
@@ -0,0 +1,6 @@
+<?php\r
+\r
+$dirs = array();\r
+$dirs['content/'] = AT_CONTENT_DIR . '?' . DIRECTORY_SEPARATOR; // course_id gets added to the end\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/file_manager/module_delete.php b/mods/_core/file_manager/module_delete.php
new file mode 100644 (file)
index 0000000..ca285b5
--- /dev/null
@@ -0,0 +1,9 @@
+<?php\r
+\r
+function file_manager_delete($course) {\r
+       $path = AT_CONTENT_DIR . $course . '/';\r
+       clr_dir($path);\r
+\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/glossary/module.php b/mods/_core/glossary/module.php
new file mode 100644 (file)
index 0000000..8fedb8b
--- /dev/null
@@ -0,0 +1,30 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_PRIV_GLOSSARY', $this->getPrivilege());\r
+\r
+//side menu\r
+$this->_stacks['glossary'] = array('title_var'=>'glossary', 'file'=>AT_INCLUDE_PATH.'html/dropdowns/glossary.inc.php');\r
+\r
+// if this module is to be made available to students on the Home or Main Navigation\r
+$_student_tool = 'glossary/index.php';\r
+\r
+$this->_pages['tools/glossary/index.php']['title_var'] = 'glossary';\r
+$this->_pages['tools/glossary/index.php']['parent']    = 'tools/index.php';\r
+$this->_pages['tools/glossary/index.php']['children']  = array('tools/glossary/add.php');\r
+\r
+       $this->_pages['tools/glossary/add.php']['title_var']  = 'add_glossary';\r
+       $this->_pages['tools/glossary/add.php']['parent'] = 'tools/glossary/index.php';\r
+\r
+       $this->_pages['tools/glossary/edit.php']['title_var']  = 'edit_glossary';\r
+       $this->_pages['tools/glossary/edit.php']['parent'] = 'tools/glossary/index.php';\r
+\r
+       $this->_pages['tools/glossary/delete.php']['title_var']  = 'delete_glossary';\r
+       $this->_pages['tools/glossary/delete.php']['parent'] = 'tools/glossary/index.php';\r
+\r
+//student pages\r
+$this->_pages['glossary/index.php']['title_var'] = 'glossary';\r
+$this->_pages['glossary/index.php']['img']       = 'images/home-glossary.gif';\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/glossary/module.xml b/mods/_core/glossary/module.xml
new file mode 100644 (file)
index 0000000..ce27d99
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Glossary</name> \r
+    <description lang="en">This module allows the ability to define course-related words in a glossary.  Glossary terms can provide a mouse-over definition within course content using special tags.  Glossary terms can also be added as a step in the content creation/editing process.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege>create</instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-25</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_core/glossary/module_backup.php b/mods/_core/glossary/module_backup.php
new file mode 100644 (file)
index 0000000..1c03487
--- /dev/null
@@ -0,0 +1,22 @@
+<?php\r
+\r
+$sql = array();\r
+\r
+$sql['glossary'] = 'SELECT word_id, word, definition, related_word_id FROM '.TABLE_PREFIX.'glossary WHERE course_id=? ORDER BY word_id ASC';\r
+\r
+\r
+function glossary_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0] = $row[0];\r
+       $new_row[1] = $course_id;\r
+       $new_row[2] = $row[1];\r
+       $new_row[3] = $row[2];\r
+       if ($row[3] != 0) {\r
+               $new_row[4] = $table_id_map['glossary'][$row[3]];\r
+       } else {\r
+               $new_row[4] = 0;\r
+       }\r
+\r
+       return $new_row;\r
+}\r
+?>
\ No newline at end of file
diff --git a/mods/_core/glossary/module_delete.php b/mods/_core/glossary/module_delete.php
new file mode 100644 (file)
index 0000000..61c64ec
--- /dev/null
@@ -0,0 +1,11 @@
+<?php\r
+\r
+function glossary_delete($course) {\r
+       global $db;\r
+\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."glossary WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/groups/module.php b/mods/_core/groups/module.php
new file mode 100644 (file)
index 0000000..33ba3ce
--- /dev/null
@@ -0,0 +1,43 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_PRIV_GROUPS', $this->getPrivilege());\r
+\r
+$_student_tool = 'groups.php';\r
+\r
+\r
+$this->_pages['tools/groups/index.php']['title_var'] = 'groups';\r
+$this->_pages['tools/groups/index.php']['parent']    = 'tools/index.php';\r
+$this->_pages['tools/groups/index.php']['children']  = array('tools/groups/create.php');\r
+$this->_pages['tools/groups/index.php']['guide']  = 'instructor/?p=groups.php';\r
+\r
+       $this->_pages['tools/groups/edit_group.php']['title_var'] = 'edit';\r
+       $this->_pages['tools/groups/edit_group.php']['parent']    = 'tools/groups/index.php';\r
+\r
+       $this->_pages['tools/groups/delete_group.php']['title_var'] = 'delete';\r
+       $this->_pages['tools/groups/delete_group.php']['parent']    = 'tools/groups/index.php';\r
+\r
+       $this->_pages['tools/groups/edit_type.php']['title_var'] = 'edit';\r
+       $this->_pages['tools/groups/edit_type.php']['parent']    = 'tools/groups/index.php';\r
+\r
+       $this->_pages['tools/groups/delete_type.php']['title_var'] = 'delete';\r
+       $this->_pages['tools/groups/delete_type.php']['parent']    = 'tools/groups/index.php';\r
+\r
+       $this->_pages['tools/groups/create.php']['title_var'] = 'create_groups';\r
+       $this->_pages['tools/groups/create.php']['parent']    = 'tools/groups/index.php';\r
+\r
+               $this->_pages['tools/groups/create_manual.php']['title_var'] = 'groups_create_manual';\r
+               $this->_pages['tools/groups/create_manual.php']['parent']    = 'tools/groups/create.php';\r
+\r
+               $this->_pages['tools/groups/create_automatic.php']['title_var'] = 'groups_create_automatic';\r
+               $this->_pages['tools/groups/create_automatic.php']['parent']    = 'tools/groups/create.php';\r
+\r
+       $this->_pages['tools/groups/members.php']['title_var'] = 'group_members';\r
+       $this->_pages['tools/groups/members.php']['parent']    = 'tools/groups/index.php';\r
+\r
+// student stuff\r
+$this->_pages['groups.php']['title_var'] = 'groups';\r
+$this->_pages['groups.php']['img']       = 'images/home-acollab.gif';\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/groups/module.xml b/mods/_core/groups/module.xml
new file mode 100644 (file)
index 0000000..36a30af
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Groups</name> \r
+    <description lang="en">Allows an instructor to assign students to groups.  Tests can then be given to students within certain groups.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege></instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-25</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_core/groups/module_backup.php b/mods/_core/groups/module_backup.php
new file mode 100644 (file)
index 0000000..305c5e5
--- /dev/null
@@ -0,0 +1,33 @@
+<?php\r
+\r
+$sql = array();\r
+$sql['groups_types'] = 'SELECT type_id, title FROM '.TABLE_PREFIX.'groups_types WHERE course_id=? ORDER BY title';\r
+\r
+$sql['groups'] = 'SELECT G.type_id, G.title, G.description, G.modules FROM '.TABLE_PREFIX.'groups G INNER JOIN '.TABLE_PREFIX.'groups_types T USING (type_id) WHERE T.course_id=? ORDER BY T.type_id, G.title';\r
+\r
+\r
+function groups_types_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0] = $row[0];\r
+       $new_row[1] = $course_id;\r
+       $new_row[2] = $row[1];\r
+\r
+       return $new_row;\r
+}\r
+\r
+function groups_convert($row, $course_id, $table_id_map, $version) {\r
+       if (version_compare($version, '1.5.3', '<')) {\r
+               // groups prior to 1.5.3 are not compatible (due to the group types).\r
+               // backwards compatibility breaks prior to 1.5.3\r
+               return array();\r
+       }\r
+       $new_row = array();\r
+       $new_row[0] = 0;\r
+       $new_row[1] = $table_id_map['groups_types'][$row[0]];\r
+       $new_row[2] = $row[1];\r
+       $new_row[3] = $row[2];\r
+       $new_row[4] = $row[3];\r
+\r
+       return $new_row;\r
+}\r
+?>
\ No newline at end of file
diff --git a/mods/_core/groups/module_delete.php b/mods/_core/groups/module_delete.php
new file mode 100644 (file)
index 0000000..39982a5
--- /dev/null
@@ -0,0 +1,26 @@
+<?php\r
+\r
+function groups_delete($course) {\r
+       global $db;\r
+\r
+       $sql    = "SELECT G.group_id FROM ".TABLE_PREFIX."groups G INNER JOIN ".TABLE_PREFIX."groups_types T USING (type_id) WHERE T.course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               $sql    = "DELETE FROM ".TABLE_PREFIX."groups_members WHERE group_id=$row[group_id]";\r
+               $result2 = mysql_query($sql, $db);\r
+\r
+               $sql    = "DELETE FROM ".TABLE_PREFIX."tests_groups WHERE group_id=$row[group_id]";\r
+               $result2 = mysql_query($sql, $db);\r
+\r
+               $sql    = "DELETE FROM ".TABLE_PREFIX."groups WHERE group_id=$row[group_id]";\r
+               $result2 = mysql_query($sql, $db);\r
+       }\r
+\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."groups_types WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       // -- remove assoc between tests and groups:\r
+\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/languages/module.php b/mods/_core/languages/module.php
new file mode 100644 (file)
index 0000000..a2068ab
--- /dev/null
@@ -0,0 +1,41 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_ADMIN_PRIV_LANGUAGES', $this->getAdminPrivilege());\r
+\r
+if (admin_authenticate(AT_ADMIN_PRIV_LANGUAGES, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+       if (admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+               $this->_pages['admin/config_edit.php']['children']  = array('admin/language.php');\r
+               $this->_pages['admin/language.php']['parent'] = 'admin/config_edit.php';\r
+       } else {\r
+               $this->_pages[AT_NAV_ADMIN] = array('admin/language.php');\r
+               $this->_pages['admin/language.php']['parent'] = AT_NAV_ADMIN;\r
+       }\r
+\r
+       //admin\r
+       $this->_pages['admin/language.php']['title_var'] = 'languages';\r
+       $this->_pages['admin/language.php']['guide']     = 'admin/?p=languages.php';\r
+       $this->_pages['admin/language.php']['children']  = array('admin/language_import.php', 'admin/language_editor.php', 'admin/language_translate.php');\r
+\r
+               $this->_pages['admin/language_add.php']['title_var'] = 'add_language';\r
+               $this->_pages['admin/language_add.php']['parent']    = 'admin/language.php';\r
+\r
+               $this->_pages['admin/language_edit.php']['title_var'] = 'edit_language';\r
+               $this->_pages['admin/language_edit.php']['parent']    = 'admin/language.php';\r
+\r
+               $this->_pages['admin/language_delete.php']['title_var'] = 'delete_language';\r
+               $this->_pages['admin/language_delete.php']['parent']    = 'admin/language.php';\r
+\r
+       $this->_pages['admin/language_import.php']['title_var'] = 'import';\r
+       $this->_pages['admin/language_import.php']['parent']    = 'admin/language.php';\r
+\r
+       $this->_pages['admin/language_translate.php']['title_var'] = 'translate';\r
+       $this->_pages['admin/language_translate.php']['parent']    = 'admin/language.php';\r
+\r
+       $this->_pages['admin/language_editor.php']['title_var'] = 'editor';\r
+       $this->_pages['admin/language_editor.php']['parent']    = 'admin/language.php';\r
+\r
+       $this->_pages['admin/language_term.php']['title_var'] = 'editor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/mods/_core/languages/module.xml b/mods/_core/languages/module.xml
new file mode 100644 (file)
index 0000000..dfa1704
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Languages</name> \r
+    <description lang="en">Allows administrators to manage languages.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege></instructor_privilege>\r
+                       <admin_privilege>create</admin_privilege> \r
+               </privileges>\r
+        <date>2005-09-19</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_core/languages/module_cron.php b/mods/_core/languages/module_cron.php
new file mode 100644 (file)
index 0000000..6bfe8c5
--- /dev/null
@@ -0,0 +1,28 @@
+<?php\r
+\r
+// this cron checks for new available languages and installs them if found.\r
+function languages_cron() {\r
+       global $_config;\r
+       if (!$_config['auto_install_languages']) { return; }\r
+\r
+\r
+       global $languageManager;\r
+\r
+       require(AT_INCLUDE_PATH.'classes/Language/RemoteLanguageManager.class.php');\r
+       require(AT_INCLUDE_PATH.'classes/pclzip.lib.php');\r
+\r
+       $remoteLanguageManager =& new RemoteLanguageManager();\r
+\r
+       $languages = $remoteLanguageManager->getAvailableLanguages();\r
+\r
+       foreach ($languages as $codes) {\r
+               $language = current($codes);\r
+               if (($language->getStatus() == AT_LANG_STATUS_PUBLISHED) && !$languageManager->exists($language->getCode())) {\r
+                       // language does not exist\r
+\r
+                       $remoteLanguageManager->import($language->getCode());\r
+               }\r
+       }\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/properties/module.php b/mods/_core/properties/module.php
new file mode 100644 (file)
index 0000000..6d49f6c
--- /dev/null
@@ -0,0 +1,46 @@
+<?php\r
+/** snippit to use when extending Modules\r
+class PropertiesModule extends Module {\r
+\r
+       function PropertiesModule($row) {\r
+               parent::Module($row);\r
+\r
+               define('AT_PRIV_ADMIN', $row['privilege']);\r
+       }\r
+\r
+       function delete() {\r
+\r
+       }\r
+}\r
+return;\r
+**/\r
+\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+if (!defined('AT_PRIV_ADMIN')) {\r
+       define('AT_PRIV_ADMIN', $this->getPrivilege());\r
+}\r
+\r
+//admin pages\r
+$this->_pages['admin/edit_course.php']['title_var'] = 'course_properties';\r
+$this->_pages['admin/edit_course.php']['parent']    = 'admin/courses.php';\r
+\r
+$this->_pages['admin/delete_course.php']['title_var'] = 'delete_course';\r
+$this->_pages['admin/delete_course.php']['parent']    = 'admin/courses.php';\r
+\r
+\r
+//instructor pages\r
+$this->_pages['tools/course_properties.php']['title_var'] = 'properties';\r
+$this->_pages['tools/course_properties.php']['parent']    = 'tools/index.php';\r
+$this->_pages['tools/course_properties.php']['children']  = array('tools/delete_course.php', 'tools/access.php');\r
+$this->_pages['tools/course_properties.php']['guide']     = 'instructor/?p=properties.php';\r
+\r
+       $this->_pages['tools/delete_course.php']['title_var'] = 'delete_course';\r
+       $this->_pages['tools/delete_course.php']['parent']    = 'tools/course_properties.php';\r
+\r
+       $this->_pages['tools/access.php']['title_var'] = 'authenticated_access';\r
+       $this->_pages['tools/access.php']['parent']    = 'tools/course_properties.php';\r
+       $this->_pages['tools/access.php']['guide']     = 'instructor/?p=authenticated_access.php';\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/properties/module.xml b/mods/_core/properties/module.xml
new file mode 100644 (file)
index 0000000..21f8865
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Course Properties</name> \r
+    <description lang="en">Allows instructors and administrators to delete a course, or manage its various properties such as title, description, access level, course icon and more. </description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege>existing</instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-22</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_core/properties/module_delete.php b/mods/_core/properties/module_delete.php
new file mode 100644 (file)
index 0000000..87053bc
--- /dev/null
@@ -0,0 +1,11 @@
+<?php\r
+\r
+function properties_delete($course) {\r
+       global $db;\r
+\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."course_access WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_core/themes/module.php b/mods/_core/themes/module.php
new file mode 100644 (file)
index 0000000..c04c574
--- /dev/null
@@ -0,0 +1,25 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_ADMIN_PRIV_THEMES', $this->getAdminPrivilege());\r
+\r
+if (admin_authenticate(AT_ADMIN_PRIV_THEMES, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+       if (admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+               $this->_pages['admin/config_edit.php']['children']      = array('admin/themes/index.php');\r
+               $this->_pages['admin/themes/index.php']['parent'] = 'admin/config_edit.php';\r
+       } else {\r
+               $this->_pages[AT_NAV_ADMIN] = array('admin/themes/index.php');\r
+               $this->_pages['admin/themes/index.php']['parent'] = AT_NAV_ADMIN;\r
+       }\r
+\r
+\r
+       //admin\r
+       $this->_pages['admin/themes/index.php']['title_var'] = 'themes';\r
+       $this->_pages['admin/themes/index.php']['guide']     = 'admin/?p=themes.php';\r
+\r
+       $this->_pages['admin/themes/delete.php']['title_var'] = 'delete';\r
+       $this->_pages['admin/themes/delete.php']['parent']    = 'admin/themes/index.php';\r
+\r
+}\r
+?>
\ No newline at end of file
diff --git a/mods/_core/themes/module.xml b/mods/_core/themes/module.xml
new file mode 100644 (file)
index 0000000..4533e75
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Themes</name> \r
+    <description lang="en">Allows administrators themes.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege></instructor_privilege>\r
+                       <admin_privilege>create</admin_privilege> \r
+               </privileges>\r
+        <date>2005-09-19</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_core/users/module.php b/mods/_core/users/module.php
new file mode 100644 (file)
index 0000000..3f153aa
--- /dev/null
@@ -0,0 +1,90 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_ADMIN_PRIV_USERS', $this->getAdminPrivilege());\r
+\r
+// for admin\r
+if (admin_authenticate(AT_ADMIN_PRIV_USERS, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+\r
+       $this->_pages[AT_NAV_ADMIN] = array('admin/users.php');\r
+\r
+       $this->_pages['admin/users.php']['title_var'] = 'users';\r
+       $this->_pages['admin/users.php']['parent']    = AT_NAV_ADMIN;\r
+       $this->_pages['admin/users.php']['guide']     = 'admin/?p=users.php';\r
+       $this->_pages['admin/users.php']['children']  = array('admin/create_user.php', 'admin/instructor_requests.php', 'admin/master_list.php', 'admin/admin_email.php');\r
+\r
+       if (admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+               $this->_pages['admin/users.php']['children'][]  = 'admin/admins/index.php';\r
+\r
+               $this->_pages['admin/admins/index.php']['title_var'] = 'administrators';\r
+               $this->_pages['admin/admins/index.php']['parent']    = 'admin/users.php';\r
+               $this->_pages['admin/admins/index.php']['guide']     = 'admin/?p=administrators.php';\r
+               $this->_pages['admin/admins/index.php']['children']  = array('admin/admins/create.php', 'admin/admins/log.php');\r
+\r
+                       $this->_pages['admin/admins/log.php']['title_var'] = 'admin_log';\r
+                       $this->_pages['admin/admins/log.php']['parent']    = 'admin/admins/index.php';\r
+                       $this->_pages['admin/admins/log.php']['children']  = array('admin/admins/reset_log.php');\r
+\r
+                               $this->_pages['admin/admins/reset_log.php']['title_var'] = 'reset_log';\r
+                               $this->_pages['admin/admins/reset_log.php']['parent']    = 'admin/admins/log.php';\r
+\r
+                               $this->_pages['admin/admins/detail_log.php']['title_var'] = 'details';\r
+                               $this->_pages['admin/admins/detail_log.php']['parent']    = 'admin/admins/log.php';\r
+\r
+                       $this->_pages['admin/admins/create.php']['title_var'] = 'create_admin';\r
+                       $this->_pages['admin/admins/create.php']['parent']    = 'admin/admins/index.php';\r
+\r
+                       $this->_pages['admin/admins/edit.php']['title_var'] = 'edit_admin';\r
+                       $this->_pages['admin/admins/edit.php']['parent']    = 'admin/admins/index.php';\r
+\r
+                       $this->_pages['admin/admins/password.php']['title_var'] = 'password';\r
+                       $this->_pages['admin/admins/password.php']['parent']    = 'admin/admins/index.php';\r
+\r
+                       $this->_pages['admin/admins/delete.php']['title_var'] = 'delete_admin';\r
+                       $this->_pages['admin/admins/delete.php']['parent']    = 'admin/admins/index.php';\r
+       }\r
+\r
+               $this->_pages['admin/admin_email.php']['title_var'] = 'admin_email';\r
+               $this->_pages['admin/admin_email.php']['parent']    = 'admin/users.php';\r
+               $this->_pages['admin/admin_email.php']['guide']     = 'admin/?p=email_users.php';\r
+\r
+               $this->_pages['admin/create_user.php']['title_var'] = 'create_user';\r
+               $this->_pages['admin/create_user.php']['parent']    = 'admin/users.php';\r
+\r
+               $this->_pages['admin/default_preferences.php']['title_var'] = 'default_preferences';\r
+               $this->_pages['admin/default_preferences.php']['parent']    = 'admin/config_edit.php';\r
+               $this->_pages['admin/default_preferences.php']['guide']     = 'admin/?p=default_preferences.php';\r
+               $this->_pages['admin/config_edit.php']['children'] = array('admin/default_preferences.php');\r
+\r
+               $this->_pages['admin/password_user.php']['title_var'] = 'password';\r
+               $this->_pages['admin/password_user.php']['parent']    = 'admin/users.php';\r
+\r
+               $this->_pages['admin/instructor_requests.php']['title_var'] = 'instructor_requests';\r
+               $this->_pages['admin/instructor_requests.php']['parent']    = 'admin/users.php';\r
+               $this->_pages['admin/instructor_requests.php']['guide']     = 'admin/?p=instructor_requests.php';\r
+\r
+                       $this->_pages['admin/admin_deny.php']['title_var'] = 'deny_instructor_request';\r
+                       $this->_pages['admin/admin_deny.php']['parent']    = 'admin/instructor_requests.php';\r
+\r
+               $this->_pages['admin/master_list.php']['title_var'] = 'master_student_list';\r
+               $this->_pages['admin/master_list.php']['parent']    = 'admin/users.php';\r
+               $this->_pages['admin/master_list.php']['guide']     = 'admin/?p=master_student_list.php';\r
+\r
+                       $this->_pages['admin/master_list_edit.php']['title_var'] = 'edit';\r
+                       $this->_pages['admin/master_list_edit.php']['parent']    = 'admin/master_list.php';\r
+\r
+                       $this->_pages['admin/master_list_delete.php']['title_var'] = 'delete';\r
+                       $this->_pages['admin/master_list_delete.php']['parent']    = 'admin/master_list.php';\r
+\r
+               $this->_pages['admin/edit_user.php']['title_var'] = 'edit_user';\r
+               $this->_pages['admin/edit_user.php']['parent']    = 'admin/users.php';\r
+\r
+       $this->_pages['admin/admin_delete.php']['title_var'] = 'delete_user';\r
+       $this->_pages['admin/admin_delete.php']['parent']    = 'admin/users.php';\r
+\r
+       $this->_pages['admin/user_status.php']['title_var'] = 'status';\r
+       $this->_pages['admin/user_status.php']['parent']    = 'admin/users.php';\r
+\r
+}\r
+?>
\ No newline at end of file
diff --git a/mods/_core/users/module.xml b/mods/_core/users/module.xml
new file mode 100644 (file)
index 0000000..6e71574
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Users</name> \r
+    <description lang="en">Allows administrators to manage the users on a system. </description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege></instructor_privilege>\r
+                       <admin_privilege>create</admin_privilege> \r
+               </privileges>\r
+        <date>2005-09-12</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/announcements/module.php b/mods/_standard/announcements/module.php
new file mode 100644 (file)
index 0000000..1eaf29b
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_PRIV_ANNOUNCEMENTS', $this->getPrivilege());\r
+\r
+$this->_pages['tools/news/index.php']['title_var'] = 'announcements';\r
+$this->_pages['tools/news/index.php']['guide']     = 'instructor/?p=announcements.php';\r
+$this->_pages['tools/news/index.php']['parent']    = 'tools/index.php';\r
+$this->_pages['tools/news/index.php']['children']  = array('editor/add_news.php');\r
+\r
+       $this->_pages['editor/add_news.php']['title_var']  = 'add_announcement';\r
+       $this->_pages['editor/add_news.php']['parent'] = 'tools/news/index.php';\r
+\r
+       $this->_pages['editor/edit_news.php']['title_var']  = 'edit_announcement';\r
+       $this->_pages['editor/edit_news.php']['parent'] = 'tools/news/index.php';\r
+\r
+       $this->_pages['editor/delete_news.php']['title_var']  = 'delete_announcement';\r
+       $this->_pages['editor/delete_news.php']['parent'] = 'tools/news/index.php';\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/announcements/module.xml b/mods/_standard/announcements/module.xml
new file mode 100644 (file)
index 0000000..7bcc3de
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Announcements</name> \r
+    <description lang="en">Announcements are useful for posting important information to students on the course Home page.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege>create</instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-25</date> \r
+        <state>stable</state> \r
+        <notes>This is a standard module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/announcements/module_backup.php b/mods/_standard/announcements/module_backup.php
new file mode 100644 (file)
index 0000000..5fb48e0
--- /dev/null
@@ -0,0 +1,33 @@
+<?php\r
+\r
+$sql = array();\r
+$sql['news'] = 'SELECT date, formatting, title, body FROM '.TABLE_PREFIX.'news WHERE course_id=? ORDER BY news_id ASC';\r
+\r
+\r
+// ??\r
+// not sure what to call this.\r
+// it takes a CSV row and returns a valid SQL row (ie. all the correct fields).\r
+\r
+function news_convert($row, $course_id, $table_id_map, $version) {\r
+       static $member_id;\r
+\r
+       if (!isset($member_id)) {\r
+               global $db;\r
+               $sql        = "SELECT member_id FROM ".TABLE_PREFIX."courses WHERE course_id=$course_id";\r
+               $result     = mysql_query($sql, $db);\r
+               $member_row = mysql_fetch_assoc($result);\r
+               $member_id  = $member_row['member_id'];\r
+       }\r
+       $new_row = array();\r
+       $new_row[0] = 0;\r
+       $new_row[1] = $course_id;\r
+       $new_row[2] = $member_id;\r
+       $new_row[3] = $row[0];\r
+       $new_row[4] = $row[1];\r
+       $new_row[5] = $row[2];\r
+       $new_row[6] = $row[3];\r
+\r
+       return $new_row;\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/announcements/module_delete.php b/mods/_standard/announcements/module_delete.php
new file mode 100644 (file)
index 0000000..a5d85a7
--- /dev/null
@@ -0,0 +1,20 @@
+<?php\r
+\r
+function announcements_delete($course) {\r
+       global $db;\r
+\r
+       /* announcement RSS: */\r
+       if (file_exists(AT_CONTENT_DIR . 'feeds/' . $course . '/RSS1.0.xml')) {\r
+               @unlink(AT_CONTENT_DIR . 'feeds/' . $course . '/RSS1.0.xml');\r
+       }\r
+       if (file_exists(AT_CONTENT_DIR . 'feeds/' . $course . '/RSS2.0.xml')) {\r
+               @unlink(AT_CONTENT_DIR . 'feeds/' . $course . '/RSS2.0.xml');\r
+       }\r
+\r
+       //announcements\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."news WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/assignments/module.php b/mods/_standard/assignments/module.php
new file mode 100644 (file)
index 0000000..8e53c38
--- /dev/null
@@ -0,0 +1,70 @@
+<?php\r
+/*******\r
+ * doesn't allow this file to be loaded with a browser.\r
+ */\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+/******\r
+ * this file must only be included within a Module obj\r
+ */\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+/*******\r
+ * assign the instructor and admin privileges to the constants.\r
+ */\r
+define('AT_PRIV_ASSIGNMENTS', $this->getPrivilege());\r
+\r
+/*******\r
+ * create a side menu box/stack.\r
+ */\r
+//$this->_stacks['hello_world'] = array('title_var'=>'hello_world', 'file'=>'hello_world/side_menu.inc.php');\r
+// ** possible alternative: **\r
+// $this->addStack('hello_world', array('title_var' => 'hello_world', 'file' => './side_menu.inc.php');\r
+\r
+/*******\r
+ * if this module is to be made available to students on the Home or Main Navigation.\r
+ */\r
+//$_student_tool = 'assignments/index.php';\r
+// ** possible alternative: **\r
+// $this->addTool('./index.php');\r
+\r
+/*******\r
+ * add the admin pages when needed.\r
+ */\r
+/*\r
+if (admin_authenticate(AT_ADMIN_PRIV_HELLO_WORLD, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+       $this->_pages[AT_NAV_ADMIN] = array('hello_world/index_admin.php');\r
+       $this->_pages['hello_world/index_admin.php']['parent']    = AT_NAV_ADMIN;\r
+       $this->_pages['hello_world/index_admin.php']['title_var'] = 'hello_world';\r
+}\r
+*/\r
+/*******\r
+ * instructor Manage section:\r
+ */\r
+$this->_pages['assignments/index_instructor.php']['title_var'] = 'assignments';\r
+$this->_pages['assignments/index_instructor.php']['parent']   = 'tools/index.php';\r
+$this->_pages['assignments/index_instructor.php']['children'] = array('assignments/add_assignment.php');\r
+$this->_pages['assignments/index_instructor.php']['guide']     = 'instructor/?p=assignments.php';\r
+\r
+       $this->_pages['assignments/add_assignment.php']['title_var'] = 'add_assignment';\r
+       $this->_pages['assignments/add_assignment.php']['parent']    = 'assignments/index_instructor.php';\r
+\r
+       $this->_pages['assignments/edit_assignment.php']['title_var'] = 'edit';\r
+       $this->_pages['assignments/edit_assignment.php']['parent']    = 'assignments/index_instructor.php';\r
+\r
+       $this->_pages['assignments/delete_assignment.php']['title_var'] = 'delete';\r
+       $this->_pages['assignments/delete_assignment.php']['parent']    = 'assignments/index_instructor.php';\r
+\r
+/*******\r
+ * student page.\r
+ */\r
+ /*\r
+$this->_pages['assignments/index.php']['title_var'] = 'assignments';\r
+$this->_pages['assignments/index.php']['img']       = 'assignments/assignments.gif';\r
+\r
+$this->_pages['assignments/index.php']['children'] = array('assignments/assignment_details.php');\r
+\r
+       $this->_pages['assignments/assignment_details.php']['title_var'] = 'am_display_assignments';\r
+       $this->_pages['assignments/assignment_details.php']['parent']    = 'assignments/index.php';\r
+*/\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/assignments/module.sql b/mods/_standard/assignments/module.sql
new file mode 100644 (file)
index 0000000..4427a4d
--- /dev/null
@@ -0,0 +1,33 @@
+# sql file for reading list module\r
+\r
+CREATE TABLE `assignments` (\r
+       `assignment_id` MEDIUMINT(6) UNSIGNED NOT NULL AUTO_INCREMENT DEFAULT 0,\r
+       `course_id` MEDIUMINT UNSIGNED NOT NULL ,\r
+       `title` VARCHAR(60) NOT NULL,\r
+       `assign_to` MEDIUMINT UNSIGNED DEFAULT 0,\r
+       `date_due` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',\r
+       `date_cutoff` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',\r
+       `multi_submit` TINYINT DEFAULT '0',\r
+       PRIMARY KEY  (`assignment_id`),\r
+       INDEX (`course_id`)\r
+) TYPE = MYISAM;\r
+\r
+REPLACE INTO `language_text` VALUES ('en', '_msgs','AT_CONFIRM_DELETE_ASSIGNMENT','Do you wish to delete this assignment: <strong>%s</strong>?',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_DUE_DATE_EMPTY','Due date is not set.',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_ASSIGNMENT_NOT_FOUND','Assignment not found.',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_ASSIGNMENT_DELETED','Assignment Deleted',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_ASSIGNMENT_UPDATED','Assignment Updated',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_module','assignments','Assignments',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_module','add_assignment','Add Assignment',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_module','edit_assignment','Edit Assignment',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_module','delete_assignment','Delete Assignment',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_module','due_date','Due Date',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_module','accept_late_submissions','Accept Late Submissions',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_module','allow_re_submissions','Allow Re-Submissions',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_module','assign_to','Assign To',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_module','time','Time',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_module','always','Always',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_module','until','Until',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_module','all_students','Everyone',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_module','options','Options',NOW(),'');\r
+REPLACE INTO `language_text` VALUES ('en', '_module','specific_groups','Specific Groups',NOW(),'');\r
diff --git a/mods/_standard/assignments/module.xml b/mods/_standard/assignments/module.xml
new file mode 100644 (file)
index 0000000..5b36538
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Assignments</name> \r
+    <description lang="en">Allows students and groups to submit assignments.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>BSD</license> \r
+       <release> \r
+        <version>0.1</version> \r
+        <date>2006-02-27</date> \r
+        <state>stable</state> \r
+        <notes></notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/assignments/module_backup.php b/mods/_standard/assignments/module_backup.php
new file mode 100644 (file)
index 0000000..2cde372
--- /dev/null
@@ -0,0 +1,19 @@
+<?php\r
+\r
+$sql = array();\r
+$sql['assignments']  = 'SELECT assignment_id, title, assign_to, date_due, date_cutoff, multi_submit FROM '.TABLE_PREFIX.'assignments WHERE course_id=?';\r
+\r
+function assignments_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0]  = $row[0]; // assignment_id\r
+       $new_row[1]  = $course_id;\r
+       $new_row[2]  = $row[1]; // title\r
+       $new_row[3]  = $row[2]; // assign_to\r
+       $new_row[4]  = $row[3]; // date_due\r
+       $new_row[5]  = $row[4]; // date_cutoff\r
+       $new_row[6]  = $row[5]; // multi_submit\r
+\r
+       return $new_row;\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/assignments/module_delete.php b/mods/_standard/assignments/module_delete.php
new file mode 100644 (file)
index 0000000..92ed42c
--- /dev/null
@@ -0,0 +1,10 @@
+<?php\r
+\r
+function assignments_delete($course) {\r
+       global $db;\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."assignments WHERE course_id=$course";\r
+       mysql_query($sql, $db);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/assignments/module_groups.php b/mods/_standard/assignments/module_groups.php
new file mode 100644 (file)
index 0000000..d876915
--- /dev/null
@@ -0,0 +1,12 @@
+<?php\r
+\r
+// create group\r
+function assignments_create_group($group_id) {\r
+}\r
+\r
+\r
+// delete group\r
+function assignments_delete_group($group_id) {\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/blogs/module.php b/mods/_standard/blogs/module.php
new file mode 100644 (file)
index 0000000..f912d7c
--- /dev/null
@@ -0,0 +1,77 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('BLOGS_GROUP', 1);\r
+\r
+define('BLOGS_AUTH_NONE',  0);\r
+define('BLOGS_AUTH_READ',  1);\r
+define('BLOGS_AUTH_WRITE', 2); \r
+define('BLOGS_AUTH_RW',    3); // to save time\r
+\r
+\r
+// if this module is to be made available to students on the Home or Main Navigation\r
+$_group_tool = $_student_tool = 'blogs/index.php';\r
+\r
+$_pages['blogs/index.php']['title_var'] = 'blogs';\r
+$_pages['blogs/index.php']['img']       = 'images/home-blogs.gif';\r
+\r
+if (isset($_REQUEST['oid'])) {\r
+       $_pages['blogs/edit_post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id']]['title_var'] = 'edit';\r
+       $_pages['blogs/edit_post.php']['title_var']   = 'edit';\r
+       $_pages['blogs/edit_post.php']['parent']      = 'blogs/post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id'];\r
+\r
+       $_pages['blogs/delete_post.php?ot='.BLOGS_GROUP.SEP.'oid='.$_REQUEST['oid'].SEP.'id='.$_REQUEST['id']]['title_var'] = 'delete';\r
+       $_pages['blogs/delete_post.php']['title_var'] = 'delete';\r
+}\r
+$_pages['blogs/delete_comment.php']['title_var'] = 'delete';\r
+\r
+\r
+function blogs_get_group_url($group_id) {\r
+       return 'blogs/view.php?ot='.BLOGS_GROUP.SEP.'oid='.$group_id;\r
+}\r
+\r
+/**\r
+ * given an owner_type and owner_id\r
+ * returns false if user cannot read or write to this workspace\r
+ * returns BLOGS_AUTH_READ if the user can read\r
+ * returns BLOGS_AUTH_WRITE if the user can write\r
+ */\r
+function blogs_authenticate($owner_type, $owner_id) {\r
+       // ensure that this group is in the course\r
+       if ($owner_type == BLOGS_GROUP) {\r
+               if (isset($_SESSION['groups'][$owner_id])) {\r
+                       return BLOGS_AUTH_RW;\r
+               }\r
+\r
+               global $db;\r
+               $sql = "SELECT type_id FROM ".TABLE_PREFIX."groups WHERE group_id=$owner_id";\r
+               $result = mysql_query($sql, $db);\r
+               if (!$row = mysql_fetch_assoc($result)) {\r
+                       return BLOGS_AUTH_NONE;\r
+               }\r
+\r
+               $sql = "SELECT type_id FROM ".TABLE_PREFIX."groups_types WHERE type_id=$row[type_id] AND course_id=$_SESSION[course_id]";\r
+               $result = mysql_query($sql, $db);\r
+               if (!$row = mysql_fetch_assoc($result)) {\r
+                       return BLOGS_AUTH_NONE;\r
+               }\r
+\r
+               return BLOGS_AUTH_READ;\r
+       }\r
+       return BLOGS_AUTH_NONE;\r
+}\r
+\r
+function blogs_get_blog_name($owner_type, $owner_id) {\r
+       if ($owner_type == BLOGS_GROUP) {\r
+               // get group name\r
+               global $db;\r
+\r
+               $sql = "SELECT title FROM ".TABLE_PREFIX."groups WHERE group_id=$owner_id";\r
+               $result = mysql_query($sql, $db);\r
+               $row = mysql_fetch_assoc($result);\r
+\r
+               return $row['title'];\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/blogs/module.xml b/mods/_standard/blogs/module.xml
new file mode 100644 (file)
index 0000000..22009d8
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Blogs</name> \r
+    <description lang="en">Creates blogs for groups as well as all registered users.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+        <use_privilege>true</use_privilege> \r
+        <date>2005-08-25</date> \r
+        <state>stable</state> \r
+        <notes></notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/blogs/module_delete.php b/mods/_standard/blogs/module_delete.php
new file mode 100644 (file)
index 0000000..484443b
--- /dev/null
@@ -0,0 +1,7 @@
+<?php\r
+\r
+function blogs_delete($course) {\r
+       // course blogs are not implemented\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/blogs/module_groups.php b/mods/_standard/blogs/module_groups.php
new file mode 100644 (file)
index 0000000..2a68efa
--- /dev/null
@@ -0,0 +1,29 @@
+<?php\r
+\r
+// create group\r
+function blogs_create_group($group_id) {\r
+\r
+       // nothing has to happen when a group is created\r
+}\r
+\r
+\r
+// delete group\r
+function blogs_delete_group($group_id) {\r
+       global $db;\r
+\r
+       // deleting a group involves deleting all the blog entries and comments for that group\r
+\r
+       // for each entry, delete the comments\r
+       $sql = "SELECT post_id FROM ".TABLE_PREFIX."blog_posts WHERE owner_type=".BLOGS_GROUP." AND owner_id=$group_id";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               $sql = "DELETE FROM ".TABLE_PREFIX."blog_posts_comments WHERE post_id=$row[post_id]";\r
+               mysql_query($sql, $db);\r
+       }\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."blog_posts WHERE owner_type=".BLOG_GROUP." AND owner_id=$group_id";\r
+       mysql_query($sql, $db);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/calendar/module.php b/mods/_standard/calendar/module.php
new file mode 100644 (file)
index 0000000..07ddcfd
--- /dev/null
@@ -0,0 +1,30 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_PRIV_CALENDAR', $this->getPrivilege());\r
+\r
+// if this module is to be made available to students on the Home or Main Navigation\r
+$_student_tool = 'calendar/index.php';\r
+\r
+// register this module as a calendar source, must implement calendar_get_entries()\r
+// register_hook('calendar_source', this);\r
+\r
+/*\r
+- reading list (start and end dates)\r
+- tests (start and end dates)\r
+- assignments (due and late submission dates)\r
+- announcements (post date)\r
+- calendar (implements course, group, multiple calendars for system as well as the display of the calendar)\r
+\r
+each above module implements in module_calendar.php\r
+mixed calendar_get_entries(int $start_timestamp, int $end_timestamp, mixed $owner_type, mixed $owner_id);\r
+\r
+loop through all registered modules calling their run_hook('calendar_source', $owner_type, $owner_id) method, \r
+which then includes and runs the calendar_get_entries() function.\r
+\r
+the calendar display doesn't have to know which modules implement calendar_get_entries().\r
+*/\r
+\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/calendar/module.xml b/mods/_standard/calendar/module.xml
new file mode 100644 (file)
index 0000000..634d252
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Calendar</name> \r
+    <description lang="en">Supports multiple calendars for site-wide, course-specific, and individuals.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege>create</instructor_privilege>\r
+                       <admin_privilege>create</admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-22</date> \r
+        <state>stable</state> \r
+        <notes>This is a standard module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/calendar/module_backup.php b/mods/_standard/calendar/module_backup.php
new file mode 100644 (file)
index 0000000..c5faa9e
--- /dev/null
@@ -0,0 +1,9 @@
+<?php\r
+/* each table to be backed up. includes the sql entry and fields */\r
+\r
+$sql = array();\r
+$sql['calendars'] = '';\r
+$sql['calendars_entries'] = '';\r
+\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/calendar/module_delete.php b/mods/_standard/calendar/module_delete.php
new file mode 100644 (file)
index 0000000..a09b918
--- /dev/null
@@ -0,0 +1,19 @@
+<?php\r
+\r
+function calendar_delete($course) {\r
+       global $db;\r
+\r
+       $sql    = "SELECT poll_id FROM ".TABLE_PREFIX."polls WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+       if (!$result) {\r
+               return;\r
+       }\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               $sql     = "DELETE FROM ".TABLE_PREFIX."polls_members WHERE poll_id=$row[poll_id]";\r
+               @mysql_query($sql, $db);\r
+       }\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."polls WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/calendar/module_groups.php b/mods/_standard/calendar/module_groups.php
new file mode 100644 (file)
index 0000000..2076839
--- /dev/null
@@ -0,0 +1,15 @@
+<?php\r
+\r
+// create group\r
+function calendar_create_group($group_id) {\r
+\r
+       // nothing has to happen when a group is created\r
+}\r
+\r
+\r
+// delete group\r
+function calendar_delete_group($group_id) {\r
+\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/chat/module.php b/mods/_standard/chat/module.php
new file mode 100644 (file)
index 0000000..a440b66
--- /dev/null
@@ -0,0 +1,36 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_PRIV_CHAT', $this->getPrivilege());\r
+\r
+// if this module is to be made available to students on the Home or Main Navigation\r
+$_student_tool = 'chat/index.php';\r
+\r
+$this->_pages['tools/chat/index.php']['title_var'] = 'chat';\r
+$this->_pages['tools/chat/index.php']['parent']    = 'tools/index.php';\r
+$this->_pages['tools/chat/index.php']['children']  = array('tools/chat/start_transcript.php');\r
+$this->_pages['tools/chat/index.php']['guide']     = 'instructor/?p=chat.php';\r
+\r
+       $this->_pages['tools/chat/start_transcript.php']['title_var']  = 'chat_start_transcript';\r
+       $this->_pages['tools/chat/start_transcript.php']['parent'] = 'tools/chat/index.php';\r
+\r
+       $this->_pages['tools/chat/delete_transcript.php']['title_var']  = 'chat_delete_transcript';\r
+       $this->_pages['tools/chat/delete_transcript.php']['parent'] = 'tools/chat/index.php';\r
+\r
+       $this->_pages['tools/chat/view_transcript.php']['title_var']  = 'chat_transcript';\r
+       $this->_pages['tools/chat/view_transcript.php']['parent'] = 'tools/chat/index.php';\r
+\r
+$this->_pages['chat/index.php']['title_var'] = 'chat';\r
+$this->_pages['chat/index.php']['img']       = 'images/home-chat.gif';\r
+\r
+       $this->_pages['chat/chat_frame.php']['title_var'] = 'chat';\r
+       $this->_pages['chat/chat_frame.php']['parent']    = 'chat/index.php';\r
+\r
+       $this->_pages['chat/view_transcript.php']['title_var'] = 'chat_transcript';\r
+       $this->_pages['chat/view_transcript']['parent']        = 'chat/index.php';\r
+\r
+$this->_pages['chat/chat.php']['title_var'] = 'chat';\r
+\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/chat/module.xml b/mods/_standard/chat/module.xml
new file mode 100644 (file)
index 0000000..a39b106
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Chat</name> \r
+    <description lang="en">AChat is an accessible chat forum for real time discussions.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege>create</instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-29</date> \r
+        <state>stable</state> \r
+        <notes>This is a standard module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/chat/module_delete.php b/mods/_standard/chat/module_delete.php
new file mode 100644 (file)
index 0000000..c4f6538
--- /dev/null
@@ -0,0 +1,13 @@
+<?php\r
+\r
+function chat_delete($course) {\r
+       global $db;\r
+\r
+       $path = AT_CONTENT_DIR . 'chat/' . $course . '/';\r
+       if (is_dir($path)) {\r
+               clr_dir($path);\r
+       }\r
+\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/course_email/module.php b/mods/_standard/course_email/module.php
new file mode 100644 (file)
index 0000000..67180d0
--- /dev/null
@@ -0,0 +1,12 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_PRIV_COURSE_EMAIL', $this->getPrivilege());\r
+\r
+$this->_pages['tools/course_email.php']['title_var'] = 'course_email';\r
+$this->_pages['tools/course_email.php']['parent']    = 'tools/index.php';\r
+$this->_pages['tools/course_email.php']['guide']     = 'instructor/?p=course_email.php';\r
+\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/course_email/module.xml b/mods/_standard/course_email/module.xml
new file mode 100644 (file)
index 0000000..145636d
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Course Email</name> \r
+    <description lang="en">Allows instructors to mass-email all members of a course.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege>create</instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-25</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/directory/module.php b/mods/_standard/directory/module.php
new file mode 100644 (file)
index 0000000..7b8f6c7
--- /dev/null
@@ -0,0 +1,11 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+// if this module is to be made available to students on the Home or Main Navigation\r
+$_student_tool = 'directory.php';\r
+\r
+$this->_pages['directory.php']['title_var'] = 'directory';\r
+$this->_pages['directory.php']['img']       = 'images/home-directory.gif';\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/directory/module.xml b/mods/_standard/directory/module.xml
new file mode 100644 (file)
index 0000000..b75b683
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Directory</name> \r
+    <description lang="en">Lists members of a course.  Status, online status, and a link to his/her individual profile page is given for each member.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege></instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-25</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/faq/module.php b/mods/_standard/faq/module.php
new file mode 100644 (file)
index 0000000..04642bd
--- /dev/null
@@ -0,0 +1,40 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_PRIV_FAQ', $this->getPrivilege());\r
+\r
+// if this module is to be made available to students on the Home or Main Navigation\r
+$_student_tool = 'faq/index.php';\r
+\r
+\r
+// instructor Manage section:\r
+$this->_pages['faq/index_instructor.php']['title_var'] = 'faq';\r
+$this->_pages['faq/index_instructor.php']['parent']    = 'tools/index.php';\r
+$this->_pages['faq/index_instructor.php']['children']  = array('faq/add_topic.php', 'faq/add_question.php');\r
+$this->_pages['faq/index_instructor.php']['guide']     = 'instructor/?p=faq.php';\r
+\r
+\r
+       $this->_pages['faq/add_topic.php']['title_var'] = 'add_topic';\r
+       $this->_pages['faq/add_topic.php']['parent']    = 'faq/index_instructor.php';\r
+\r
+       $this->_pages['faq/delete_topic.php']['title_var'] = 'delete';\r
+       $this->_pages['faq/delete_topic.php']['parent']    = 'faq/index_instructor.php';\r
+\r
+       $this->_pages['faq/edit_topic.php']['title_var'] = 'edit';\r
+       $this->_pages['faq/edit_topic.php']['parent']    = 'faq/index_instructor.php';\r
+\r
+       $this->_pages['faq/add_question.php']['title_var'] = 'add_question';\r
+       $this->_pages['faq/add_question.php']['parent']    = 'faq/index_instructor.php';\r
+\r
+       $this->_pages['faq/delete_question.php']['title_var'] = 'delete';\r
+       $this->_pages['faq/delete_question.php']['parent']    = 'faq/index_instructor.php';\r
+\r
+       $this->_pages['faq/edit_question.php']['title_var'] = 'edit';\r
+       $this->_pages['faq/edit_question.php']['parent']    = 'faq/index_instructor.php';\r
+\r
+// student page:\r
+$this->_pages['faq/index.php']['title_var'] = 'faq';\r
+$this->_pages['faq/index.php']['img']       = 'faq/icon.gif';\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/faq/module.xml b/mods/_standard/faq/module.xml
new file mode 100644 (file)
index 0000000..2f75b74
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Frequently Asked Questions (FAQ)</name> \r
+    <description lang="en">Adds course-specific FAQs which instructors can manage.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+        <date>2005-10-12</date> \r
+        <state>stable</state> \r
+        <notes></notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/faq/module_backup.php b/mods/_standard/faq/module_backup.php
new file mode 100644 (file)
index 0000000..b36b541
--- /dev/null
@@ -0,0 +1,29 @@
+<?php\r
+/* each table to be backed up. includes the sql entry and fields */\r
+\r
+$sql = array();\r
+$sql['faq_topics']  = 'SELECT topic_id, name FROM '.TABLE_PREFIX.'faq_topics WHERE course_id=? ORDER BY name';\r
+$sql['faq_entries'] = 'SELECT E.topic_id, E.revised_date, E.approved, E.question, E.answer FROM '.TABLE_PREFIX.'faq_entries E INNER JOIN '.TABLE_PREFIX.'faq_topics T USING (topic_id) WHERE T.course_id=? ORDER BY T.name, E.question';\r
+\r
+function faq_topics_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0]  = $row[0];\r
+       $new_row[1]  = $course_id;\r
+       $new_row[2]  = $row[1];\r
+\r
+       return $new_row;\r
+}\r
+\r
+function faq_entries_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0]  = 0;\r
+       $new_row[1]  = $table_id_map['faq_topics'][$row[0]];\r
+       $new_row[2]  = $row[1];\r
+       $new_row[3]  = $row[2];\r
+       $new_row[4]  = $row[3];\r
+       $new_row[5]  = $row[4];\r
+\r
+       return $new_row;\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/faq/module_delete.php b/mods/_standard/faq/module_delete.php
new file mode 100644 (file)
index 0000000..69bd5d0
--- /dev/null
@@ -0,0 +1,17 @@
+<?php\r
+\r
+function faq_delete($course) {\r
+       global $db;\r
+\r
+       $sql = "SELECT topic_id FROM ".TABLE_PREFIX."faq_topics WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               $sql = "DELETE FROM ".TABLE_PREFIX."faq_entries WHERE topic_id=$row[topic_id]";\r
+               mysql_query($sql, $db);\r
+       }\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."faq_topics WHERE course_id=$course";\r
+       mysql_query($sql, $db);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/file_storage/module.php b/mods/_standard/file_storage/module.php
new file mode 100644 (file)
index 0000000..0db7f14
--- /dev/null
@@ -0,0 +1,55 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_PRIV_FILE_STORAGE',       $this->getPrivilege() );\r
+// define('AT_ADMIN_PRIV_FILE_STORAGE',       $this->getAdminPrivilege() );\r
+\r
+\r
+// if this module is to be made available to students on the Home or Main Navigation\r
+$_group_tool = $_student_tool = 'file_storage/index.php';\r
+\r
+\r
+//student pages\r
+$this->_pages['file_storage/index.php']['title_var']  = 'file_storage';\r
+$this->_pages['file_storage/index.php']['img']        = 'images/home-file_storage.gif';\r
+$this->_pages['file_storage/index.php']['guide']     = 'general/?p=file_storage.php';\r
+\r
+$this->_pages['file_storage/revisions.php']['title_var'] = 'revisions';\r
+$this->_pages['file_storage/revisions.php']['parent'] = 'file_storage/index.php';\r
+$this->_pages['file_storage/revisions.php']['children'] = array(); // empty array creates a "back to" link to index.php\r
+\r
+$this->_pages['file_storage/comments.php']['title_var'] = 'comments';\r
+$this->_pages['file_storage/comments.php']['parent'] = 'file_storage/index.php';\r
+$this->_pages['file_storage/comments.php']['children'] = array(); // empty array creates a "back to" link to index.php\r
+\r
+$this->_pages['file_storage/edit.php']['title_var'] = 'edit';\r
+$this->_pages['file_storage/edit.php']['parent'] = 'file_storage/index.php';\r
+$this->_pages['file_storage/edit.php']['children'] = array(); // empty array creates a "back to" link to index.php\r
+\r
+$this->_pages['file_storage/edit_folder.php']['title_var'] = 'edit';\r
+$this->_pages['file_storage/edit_folder.php']['parent'] = 'file_storage/index.php';\r
+$this->_pages['file_storage/edit_folder.php']['children'] = array(); // empty array creates a "back to" link to index.php\r
+\r
+$this->_pages['file_storage/move.php']['title_var'] = 'move';\r
+$this->_pages['file_storage/move.php']['parent'] = 'file_storage/index.php';\r
+$this->_pages['file_storage/move.php']['children'] = array(); // empty array creates a "back to" link to index.php\r
+\r
+$this->_pages['file_storage/assignment.php']['title_var'] = 'hand_in';\r
+$this->_pages['file_storage/assignment.php']['parent'] = 'file_storage/index.php';\r
+$this->_pages['file_storage/assignment.php']['children'] = array(); // empty array creates a "back to" link to index.php\r
+\r
+$this->_pages['file_storage/new.php']['title_var'] = 'new_file';\r
+$this->_pages['file_storage/new.php']['parent'] = 'file_storage/index.php';\r
+$this->_pages['file_storage/new.php']['children'] = array(); // empty array creates a "back to" link to index.php\r
+\r
+$this->_pages['file_storage/delete_revision.php']['title_var'] = 'delete';\r
+$this->_pages['file_storage/delete_revision.php']['parent'] = 'file_storage/index.php';\r
+\r
+$this->_pages['file_storage/delete_comment.php']['title_var'] = 'delete';\r
+//$this->_pages['file_storage/delete_comment.php']['parent'] = 'file_storage/comments.php';\r
+\r
+function file_storage_get_group_url($group_id) {\r
+       return 'file_storage/index.php?ot='.WORKSPACE_GROUP.SEP.'oid='.$group_id;\r
+}\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/file_storage/module.xml b/mods/_standard/file_storage/module.xml
new file mode 100644 (file)
index 0000000..08f0277
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">File Storage</name> \r
+    <description lang="en">Personal, group, and course drafting room. Is required when using the Assignment Manager.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege>create</instructor_privilege>\r
+                       <admin_privilege>create</admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-26</date> \r
+        <state>stable</state> \r
+        <notes>This is a standard module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/file_storage/module_delete.php b/mods/_standard/file_storage/module_delete.php
new file mode 100644 (file)
index 0000000..0f095bb
--- /dev/null
@@ -0,0 +1,19 @@
+<?php\r
+\r
+function file_storage_delete($course) {\r
+       global $db;\r
+\r
+       require(AT_INCLUDE_PATH.'lib/file_storage.inc.php');\r
+\r
+       // delete course files:\r
+       fs_delete_workspace(WORKSPACE_COURSE, $course);\r
+\r
+       // delete private student files:\r
+       $sql = "SELECT member_id FROM ".TABLE_PREFIX."course_enrollment WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+       while ($student_row = mysql_fetch_assoc($result)) {\r
+               fs_delete_workspace(WORKSPACE_PERSONAL, $student_row['member_id']);\r
+       }\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/file_storage/module_groups.php b/mods/_standard/file_storage/module_groups.php
new file mode 100644 (file)
index 0000000..bf110b0
--- /dev/null
@@ -0,0 +1,24 @@
+<?php\r
+\r
+// create group\r
+function file_storage_create_group($group_id) {\r
+       global $db;\r
+\r
+       $sql = "REPLACE INTO ".TABLE_PREFIX."file_storage_groups VALUES ($group_id)";\r
+       mysql_query($sql, $db);\r
+}\r
+\r
+\r
+// delete group\r
+function file_storage_delete_group($group_id) {\r
+       global $db;\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."file_storage_groups WHERE group_id=$group_id";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       require_once(AT_INCLUDE_PATH.'lib/file_storage.inc.php');\r
+       fs_delete_workspace(WORKSPACE_GROUP, $group_id);\r
+}\r
+\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/forums/module.php b/mods/_standard/forums/module.php
new file mode 100644 (file)
index 0000000..337604e
--- /dev/null
@@ -0,0 +1,66 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_PRIV_FORUMS',       $this->getPrivilege() );\r
+define('AT_ADMIN_PRIV_FORUMS', $this->getAdminPrivilege() );\r
+\r
+\r
+// if this module is to be made available to students on the Home or Main Navigation\r
+$_group_tool = $_student_tool = 'forum/list.php';\r
+\r
+//side dropdown\r
+$this->_stacks['posts'] = array('title_var'=>'posts','file'=>AT_INCLUDE_PATH.'html/dropdowns/posts.inc.php');\r
+\r
+//instructor pages\r
+$this->_pages['tools/forums/index.php']['title_var'] = 'forums';\r
+$this->_pages['tools/forums/index.php']['parent']    = 'tools/index.php';\r
+$this->_pages['tools/forums/index.php']['guide']     = 'instructor/?p=forums.php';\r
+$this->_pages['tools/forums/index.php']['children']  = array('editor/add_forum.php');\r
+\r
+       $this->_pages['editor/add_forum.php']['title_var']  = 'create_forum';\r
+       $this->_pages['editor/add_forum.php']['parent'] = 'tools/forums/index.php';\r
+\r
+       $this->_pages['editor/delete_forum.php']['title_var']  = 'delete_forum';\r
+       $this->_pages['editor/delete_forum.php']['parent'] = 'tools/forums/index.php';\r
+\r
+       $this->_pages['editor/edit_forum.php']['title_var']  = 'edit_forum';\r
+       $this->_pages['editor/edit_forum.php']['parent'] = 'tools/forums/index.php';\r
+\r
+//student pages\r
+$this->_pages['forum/list.php']['title_var']  = 'forums';\r
+$this->_pages['forum/list.php']['img']        = 'images/home-forums.gif';\r
+\r
+// for admin\r
+if (admin_authenticate(AT_ADMIN_PRIV_FORUMS, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+       if (admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+               $this->_pages['admin/courses.php']['children'] = array('admin/forums.php');\r
+               $this->_pages['admin/forums.php']['parent']    = 'admin/courses.php';\r
+       } else {\r
+               $this->_pages[AT_NAV_ADMIN] = array('admin/forums.php');\r
+               $this->_pages['admin/forums.php']['parent'] = AT_NAV_ADMIN;\r
+       }\r
+\r
+       $this->_pages['admin/forums.php']['title_var'] = 'forums';\r
+       $this->_pages['admin/forums.php']['guide']     = 'admin/?p=forums.php';\r
+       $this->_pages['admin/forums.php']['children']  = array('admin/forum_add.php');\r
+\r
+               $this->_pages['admin/forum_add.php']['title_var'] = 'create_forum';\r
+               $this->_pages['admin/forum_add.php']['parent']    = 'admin/forums.php';\r
+\r
+               $this->_pages['admin/forum_edit.php']['title_var'] = 'edit_forum';\r
+               $this->_pages['admin/forum_edit.php']['parent']    = 'admin/forums.php';\r
+\r
+               $this->_pages['admin/forum_delete.php']['title_var'] = 'delete_forum';\r
+               $this->_pages['admin/forum_delete.php']['parent']    = 'admin/forums.php';\r
+}\r
+\r
+function forums_get_group_url($group_id) {\r
+       global $db;\r
+       $sql = "SELECT forum_id FROM ".TABLE_PREFIX."forums_groups WHERE group_id=$group_id";\r
+       $result = mysql_query($sql, $db);\r
+       $row = mysql_fetch_assoc($result);\r
+\r
+       return 'forum/index.php?fid='.$row['forum_id'];\r
+}\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/forums/module.xml b/mods/_standard/forums/module.xml
new file mode 100644 (file)
index 0000000..e3bbf85
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Forums</name> \r
+    <description lang="en">Instructors may create and manage forums for course discussion.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege>create</instructor_privilege>\r
+                       <admin_privilege>create</admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-26</date> \r
+        <state>stable</state> \r
+        <notes>This is a standard module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/forums/module_delete.php b/mods/_standard/forums/module_delete.php
new file mode 100644 (file)
index 0000000..3650a29
--- /dev/null
@@ -0,0 +1,74 @@
+<?php\r
+\r
+function forums_delete($course) {\r
+       global $db;\r
+\r
+       $sql = "SELECT * FROM ".TABLE_PREFIX."forums_courses WHERE course_id=$course";\r
+       $f_result = mysql_query($sql, $db);\r
+       while ($forum = mysql_fetch_assoc($f_result)) {\r
+               $forum_id = $forum['forum_id'];\r
+               $sql = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."forums_courses WHERE forum_id=$forum_id";\r
+               $result = mysql_query($sql, $db);\r
+               $row = mysql_fetch_assoc($result);\r
+               if ($row['cnt'] == 1) {\r
+                       $sql    = "SELECT post_id FROM ".TABLE_PREFIX."forums_threads WHERE forum_id=$forum_id";\r
+                       $result = mysql_query($sql, $db);\r
+                       while ($row = mysql_fetch_assoc($result)) {\r
+                               $sql     = "DELETE FROM ".TABLE_PREFIX."forums_accessed WHERE post_id=$row[post_id]";\r
+                               $result2 = mysql_query($sql, $db);\r
+                       }\r
+\r
+                       $sql    = "DELETE FROM ".TABLE_PREFIX."forums_subscriptions WHERE forum_id=$forum_id";\r
+                       $result = mysql_query($sql, $db);\r
+\r
+                       $sql    = "DELETE FROM ".TABLE_PREFIX."forums_threads WHERE forum_id=$forum_id";\r
+                       $result = mysql_query($sql, $db);\r
+\r
+                       $sql    = "DELETE FROM ".TABLE_PREFIX."forums WHERE forum_id=$forum_id";\r
+                       $result = mysql_query($sql, $db);\r
+                       \r
+                       $sql = "DELETE FROM ".TABLE_PREFIX."forums_courses WHERE forum_id=$forum_id";\r
+                       $result = mysql_query($sql, $db);\r
+\r
+               } else if ($row['cnt'] > 1) {\r
+                       // this is a shared forum:\r
+                       // debug('unsubscribe all the students who will not be able to access this forum anymore.');\r
+                       $sql     = "SELECT course_id FROM ".TABLE_PREFIX."forums_courses WHERE forum_id=$forum[forum_id] AND course_id <> $course";\r
+                       $result2 = mysql_query($sql, $db);\r
+                       while ($row2 = mysql_fetch_assoc($result2)) {\r
+                               $courses[] = $row2['course_id'];\r
+                       }\r
+                       $courses_list = implode(',', $courses);\r
+\r
+                       // list of all the students who are in other courses as well\r
+                       $sql     = "SELECT member_id FROM ".TABLE_PREFIX."course_enrollment WHERE course_id IN ($courses_list)";\r
+                       $result2 = mysql_query($sql, $db);\r
+                       while ($row2 = mysql_fetch_assoc($result2)) {\r
+                               $students[] = $row2['member_id'];\r
+                       }\r
+\r
+                       $students_list = implode(',', $students);\r
+                       \r
+                       if ($students_list) {\r
+                               // remove the subscriptions\r
+                               $sql    = "SELECT post_id FROM ".TABLE_PREFIX."forums_threads WHERE forum_id=$forum[forum_id]";\r
+                               $result2 = mysql_query($sql, $db);\r
+                               while ($row2 = mysql_fetch_array($result2)) {\r
+                                       $sql     = "DELETE FROM ".TABLE_PREFIX."forums_accessed WHERE post_id=$row2[post_id] AND member_id NOT IN ($students_list)";\r
+                                       $result3 = mysql_query($sql, $db);\r
+                               }\r
+\r
+                               $sql     = "DELETE FROM ".TABLE_PREFIX."forums_subscriptions WHERE forum_id=$forum[forum_id] AND member_id NOT IN ($students_list)";\r
+                               $result3 = mysql_query($sql, $db);\r
+                       }\r
+\r
+                       $sql = "DELETE FROM ".TABLE_PREFIX."forums_courses WHERE forum_id=$forum[forum_id] AND course_id=$course";\r
+                       $result = mysql_query($sql, $db);\r
+               }\r
+       }\r
+\r
+       $sql = "OPTIMIZE TABLE ".TABLE_PREFIX."forums_threads";\r
+       $result = mysql_query($sql, $db);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/forums/module_groups.php b/mods/_standard/forums/module_groups.php
new file mode 100644 (file)
index 0000000..d30f9be
--- /dev/null
@@ -0,0 +1,31 @@
+<?php\r
+\r
+// create group\r
+function forums_create_group($group_id) {\r
+       global $db;\r
+\r
+       $sql    = "INSERT INTO ".TABLE_PREFIX."forums VALUES (NULL,'', '', 0, 0, NOW(), 0)";\r
+       $result = mysql_query($sql,$db);\r
+\r
+       $sql    = "INSERT INTO ".TABLE_PREFIX."forums_groups VALUES (LAST_INSERT_ID(),  $group_id)";\r
+       $result = mysql_query($sql,$db);\r
+}\r
+\r
+\r
+// delete group\r
+function forums_delete_group($group_id) {\r
+       global $db;\r
+\r
+       require_once(AT_INCLUDE_PATH . 'lib/forums.inc.php');\r
+\r
+       $sql = "SELECT forum_id FROM ".TABLE_PREFIX."forums_groups WHERE group_id=$group_id";\r
+       $result = mysql_query($sql, $db);\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               delete_forum($row['forum_id']);\r
+       }\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."forums_groups WHERE group_id=$group_id";\r
+       $result = mysql_query($sql, $db);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/google_search/SOAP_Google.php b/mods/_standard/google_search/SOAP_Google.php
new file mode 100644 (file)
index 0000000..4ad5612
--- /dev/null
@@ -0,0 +1,114 @@
+<?php\r
+require(AT_INCLUDE_PATH . 'classes/nusoap.php');\r
+\r
+class SOAP_Google { \r
+       /**    * @var    string    * @access private    */    var $_licenseKey = "";\r
+\r
+           /**    * @var    object    * @access private    */    var $_soapClient = NULL;\r
+\r
+               /**\r
+    * Constructor.\r
+    *\r
+    * @param  string\r
+    * @access public\r
+    */\r
+    function SOAP_Google($licenseKey) {\r
+        $this->_licenseKey = $licenseKey;\r
+\r
+        $this->_soapClient = new nusoapclient("http://api.google.com/search/beta2");\r
+    }\r
+\r
+/**\r
+    * Retrieves a page by URL from the Google Cache.\r
+    *\r
+    * @param  string\r
+    * @return mixed\r
+    * @access public\r
+    */\r
+    function getCachedPage($url) {\r
+        $result = $this->_performAPICall(\r
+          "doGetCachedPage",\r
+\r
+          array(\r
+            "key" => $this->_licenseKey,\r
+            "url" => $url\r
+          )\r
+        );\r
+\r
+        if ($result) {\r
+            $result = base64_decode($result);\r
+        }\r
+\r
+        return $result;\r
+    }\r
+\r
+    /**\r
+    * Retrieves a spelling suggestion for a phrase.\r
+    *\r
+    * @param  string\r
+    * @return mixed\r
+    * @access public\r
+    */\r
+    function getSpellingSuggestion($phrase) {\r
+        return $this->_performAPICall(\r
+          "doSpellingSuggestion",\r
+\r
+          array(\r
+            "key"    => $this->_licenseKey,\r
+            "phrase" => $phrase\r
+          )\r
+        );\r
+    }\r
+\r
+    /**\r
+    * Performs a web search.\r
+    *\r
+    * @param  array\r
+    * @return mixed\r
+    * @access public\r
+    */\r
+    function search($parameters = array()) {\r
+        if (!isset($parameters["query"])) {\r
+            return false;\r
+        }\r
+\r
+        return $this->_performAPICall(\r
+          "doGoogleSearch",\r
+\r
+          array(\r
+            "key"         => $this->_licenseKey,\r
+            "q"           => $parameters["query"],\r
+            "start"       => isset($parameters["start"])      ? $parameters["start"]      : 0,\r
+            "maxResults"  => isset($parameters["maxResults"]) ? $parameters["maxResults"] : 10,\r
+            "filter"      => isset($parameters["filter"])     ? $parameters["filter"]     : false,\r
+            "restrict"    => isset($parameters["restrict"])   ? $parameters["restrict"]   : "",\r
+            "safeSearch"  => isset($parameters["safeSearch"]) ? $parameters["safeSearch"] : false,\r
+            "lr"          => isset($parameters["lr"])         ? $parameters["lr"]         : "",\r
+            "ie"          => isset($parameters["ie"])         ? $parameters["ie"]         : "",\r
+            "oe"          => isset($parameters["oe"])         ? $parameters["oe"]         : ""\r
+          )\r
+        );\r
+    }\r
+\r
+    /**\r
+    * @param  string\r
+    * @param  array\r
+    * @return mixed\r
+    * @access private\r
+    */\r
+    function _performAPICall($apiCall, $parameters) {\r
+                       $result = $this->_soapClient->call(\r
+                         $apiCall,\r
+                         $parameters,\r
+                         "urn:GoogleSearch"\r
+                       );\r
+\r
+               // if (!PEAR::isError($result)) {\r
+               if (is_array($result)) {\r
+            return $result;\r
+        } else {\r
+            return false;\r
+        }\r
+    }\r
+}\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/google_search/module.css b/mods/_standard/google_search/module.css
new file mode 100644 (file)
index 0000000..8a56670
--- /dev/null
@@ -0,0 +1,55 @@
+/* Load the defaulted google search css */\r
+@import url('http://www.google.com/uds/css/gsearch.css');  \r
+\r
+/* Overwrite google defaulted form styles */ \r
+td {\r
+vertical-align : top;\r
+}\r
+td.search-form {\r
+width : 400px;\r
+}\r
+td.gsc-clear-button {\r
+padding-left: 0px;\r
+}\r
+input.gsc-search-button {\r
+       border: 1px solid #999;\r
+       background-color: white;\r
+       padding: 2px;\r
+       padding-left: 10px;\r
+       padding-right: 10px;\r
+}\r
+input.gsc-search-button:hover {\r
+       background-color: #f5f5ff;\r
+       border: 1px solid blue;\r
+       cursor: pointer;\r
+}\r
+\r
+#results .header {\r
+font-size : 16px;\r
+font-weight : bold;\r
+margin-bottom : .25em;\r
+margin-top : 1em;\r
+}\r
+#results .gs-result {\r
+  margin-bottom : .5em;\r
+  margin-left: 1em;\r
+  width: 600px;\r
+}\r
+#results div.gs-text-box{\r
+       float: left;\r
+}\r
+#results div.gs-watermark {\r
+display : none;\r
+}\r
+\r
+/* Styles for the tabbed menu */\r
+#searcher table{\r
+       margin-left: 5px;\r
+       width: 500px;\r
+}\r
+#searcher div.selector{\r
+  border-bottom: solid 1px #e9e9e9;\r
+  margin-top: 0px;\r
+}\r
+\r
+/* Styles for buttons */\r
diff --git a/mods/_standard/google_search/module.php b/mods/_standard/google_search/module.php
new file mode 100644 (file)
index 0000000..cc33b01
--- /dev/null
@@ -0,0 +1,24 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+$_student_tool = 'google_search/index.php';\r
+\r
+if (admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+       $this->_pages['admin/config_edit.php']['children'] = array('google_search/admin/module_prefs.php');\r
+\r
+       $this->_pages['google_search/admin/module_prefs.php']['title_var'] = 'google_key';\r
+       $this->_pages['google_search/admin/module_prefs.php']['parent']    = 'admin/config_edit.php';\r
+       $this->_pages['google_search/admin/module_prefs.php']['guide']     = 'admin/?p=google_key.php';\r
+\r
+}\r
+\r
+\r
+//side menu\r
+$this->_stacks['google_search'] = array('title_var'=>'google_search', 'file'=>dirname(__FILE__).'/side_menu.inc.php');\r
+\r
+\r
+$this->_pages['google_search/index.php']['title_var'] = 'google_search';\r
+$this->_pages['google_search/index.php']['img']       = 'google_search/google.gif';\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/google_search/module.xml b/mods/_standard/google_search/module.xml
new file mode 100644 (file)
index 0000000..ecfd1cc
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Google Search</name> \r
+    <description lang="en">Allows one to search Google and have the results displayed within ATutor.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege></instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-10-11</date> \r
+        <state>stable</state> \r
+        <notes></notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/google_search/side_menu.inc.php b/mods/_standard/google_search/side_menu.inc.php
new file mode 100644 (file)
index 0000000..0fa6f9b
--- /dev/null
@@ -0,0 +1,31 @@
+<?php\r
+global $savant, $_config, $stripslashes;\r
+ob_start(); \r
+?>\r
+\r
+<?php if ($_config['gsearch']): ?>\r
+       <form action="<?php echo $_base_path; ?>google_search/index.php" method="get" name="gsearchform">\r
+<?php else: ?>\r
+       <form action="http://www.google.com/search" method="get" target="_new">\r
+       <input type="hidden" name="l" value="<?php echo $_SESSION['lang']; ?>" />\r
+<?php endif; ?>\r
+\r
+<?php if (!$_config['gsearch']): ?>\r
+       <?php echo _AT('google_new_window'); ?>\r
+<?php endif; ?>\r
+\r
+<input type="hidden" name="search" value="1" />\r
+\r
+<input type="text" name="q" class="formfield" size="20" value="<?php echo $stripslashes(htmlspecialchars($_GET['q'])); ?>" /><br /><br />\r
+<input type="hidden" name="submit" value="<?php echo _AT('search'); ?>" />\r
+<input type="submit" class="button" />\r
+</form>\r
+\r
+<?php\r
+$savant->assign('dropdown_contents', ob_get_contents());\r
+ob_end_clean();\r
+\r
+$savant->assign('title', _AT('google_search'));\r
+$savant->display('include/box.tmpl.php');\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/links/module.php b/mods/_standard/links/module.php
new file mode 100644 (file)
index 0000000..a4f5fa8
--- /dev/null
@@ -0,0 +1,84 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_PRIV_LINKS', $this->getPrivilege());\r
+\r
+// if this module is to be made available to students on the Home or Main Navigation\r
+$_group_tool = $_student_tool = 'links/index.php';\r
+\r
+/*$this->_pages['tools/links/index.php']['title_var'] = 'links';\r
+$this->_pages['tools/links/index.php']['parent']    = 'tools/index.php';\r
+$this->_pages['tools/links/index.php']['children'] = array('tools/links/add.php', 'tools/links/categories.php', 'tools/links/categories_create.php');\r
+$this->_pages['tools/links/index.php']['guide'] = 'instructor/?p=links.php';\r
+\r
+       $this->_pages['tools/links/add.php']['title_var']  = 'add_link';\r
+       $this->_pages['tools/links/add.php']['parent'] = 'tools/links/index.php';\r
+\r
+       $this->_pages['tools/links/edit.php']['title_var']  = 'edit_link';\r
+       $this->_pages['tools/links/edit.php']['parent'] = 'tools/links/index.php';\r
+\r
+       $this->_pages['tools/links/delete.php']['title_var']  = 'delete_link';\r
+       $this->_pages['tools/links/delete.php']['parent'] = 'tools/links/index.php';\r
+\r
+       $this->_pages['tools/links/categories.php']['title_var']  = 'categories';\r
+       $this->_pages['tools/links/categories.php']['parent'] = 'tools/links/index.php';\r
+\r
+       $this->_pages['tools/links/categories_create.php']['title_var']  = 'create_category';\r
+       $this->_pages['tools/links/categories_create.php']['parent'] = 'tools/links/index.php';\r
+\r
+       $this->_pages['tools/links/categories_edit.php']['title_var']  = 'edit_category';\r
+       $this->_pages['tools/links/categories_edit.php']['parent'] = 'tools/links/categories.php';\r
+\r
+       $this->_pages['tools/links/categories_delete.php']['title_var']  = 'delete_category';\r
+       $this->_pages['tools/links/categories_delete.php']['parent'] = 'tools/links/categories.php';\r
+*/\r
+\r
+//instructor & group pages\r
+$this->_pages['tools/links/index.php']['title_var'] = 'manage_links';\r
+$this->_pages['tools/links/index.php']['parent']    = 'links/index.php';\r
+$this->_pages['tools/links/index.php']['children'] = array('tools/links/add.php', 'tools/links/categories.php', 'tools/links/categories_create.php');\r
+$this->_pages['tools/links/index.php']['guide'] = 'instructor/?p=links.php';\r
+\r
+       $this->_pages['tools/links/add.php']['title_var']  = 'add_link';\r
+       $this->_pages['tools/links/add.php']['parent'] = 'tools/links/index.php';\r
+\r
+       $this->_pages['tools/links/edit.php']['title_var']  = 'edit_link';\r
+       $this->_pages['tools/links/edit.php']['parent'] = 'tools/links/index.php';\r
+\r
+       $this->_pages['tools/links/delete.php']['title_var']  = 'delete_link';\r
+       $this->_pages['tools/links/delete.php']['parent'] = 'tools/links/index.php';\r
+\r
+       $this->_pages['tools/links/categories.php']['title_var']  = 'categories';\r
+       $this->_pages['tools/links/categories.php']['parent'] = 'tools/links/index.php';\r
+\r
+       $this->_pages['tools/links/categories_create.php']['title_var']  = 'create_category';\r
+       $this->_pages['tools/links/categories_create.php']['parent'] = 'tools/links/index.php';\r
+\r
+       $this->_pages['tools/links/categories_edit.php']['title_var']  = 'edit_category';\r
+       $this->_pages['tools/links/categories_edit.php']['parent'] = 'tools/links/categories.php';\r
+\r
+       $this->_pages['tools/links/categories_delete.php']['title_var']  = 'delete_category';\r
+       $this->_pages['tools/links/categories_delete.php']['parent'] = 'tools/links/categories.php';\r
+\r
+//student pages\r
+$this->_pages['links/index.php']['title_var'] = 'links';\r
+$this->_pages['links/index.php']['children']  = array('links/add.php', 'tools/links/index.php');\r
+$this->_pages['links/index.php']['img']       = 'images/home-links.gif';\r
+\r
+       $this->_pages['links/add.php']['title_var'] = 'suggest_link';\r
+       $this->_pages['links/add.php']['parent']    = 'links/index.php';\r
+\r
+\r
+function links_get_group_url($group_id) {\r
+       global $db;\r
+       $sql = "SELECT cat_id FROM ".TABLE_PREFIX."links_categories WHERE owner_id=$group_id and owner_type=".LINK_CAT_GROUP;\r
+       $result = mysql_query($sql, $db);\r
+       if ($row = mysql_fetch_assoc($result)) {\r
+               return 'links/index.php?cat_parent_id='.$row['cat_id'].'&search=&filter=Filter';\r
+       } \r
+\r
+       return 'links/index.php';\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/links/module.xml b/mods/_standard/links/module.xml
new file mode 100644 (file)
index 0000000..9cc52f3
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Links</name> \r
+    <description lang="en">It may be a useful resource to provide a list of external links to websites related to course material.  Link categories can be defined and students may suggest links.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege>create</instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-22</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/links/module_backup.php b/mods/_standard/links/module_backup.php
new file mode 100644 (file)
index 0000000..4103689
--- /dev/null
@@ -0,0 +1,39 @@
+<?php\r
+\r
+$sql = array();\r
+\r
+$sql['links_categories'] = 'SELECT cat_id, name, parent_id FROM '.TABLE_PREFIX.'links_categories WHERE owner_id=? AND owner_type='.LINK_CAT_COURSE.' ORDER BY cat_id ASC';\r
+\r
+$sql['links'] = 'SELECT L.cat_id, Url, LinkName, Description, Approved, SubmitName, SubmitEmail, SubmitDate, hits FROM '.TABLE_PREFIX.'links L INNER JOIN '.TABLE_PREFIX.'links_categories C  USING (cat_id) WHERE C.owner_id=? AND C.owner_type='.LINK_CAT_COURSE.' ORDER BY link_id ASC';\r
+\r
+\r
+function links_categories_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0] = $row[0];\r
+       $new_row[1] = LINK_CAT_COURSE;\r
+       $new_row[2] = $course_id;\r
+       $new_row[3] = $row[1];\r
+       $new_row[4] = $row[2];\r
+\r
+       return $new_row;\r
+}\r
+\r
+function links_convert($row, $course_id, $table_id_map, $version) {\r
+       static $i;\r
+\r
+       $new_row = array();\r
+       $new_row[0] = 0;\r
+       $new_row[1] = $table_id_map['links_categories'][$row[0]];\r
+       $new_row[2] = $row[1];\r
+       $new_row[3] = $row[2];\r
+       $new_row[4] = $row[3];\r
+       $new_row[5] = $row[4];\r
+       $new_row[6] = $row[5];\r
+       $new_row[7] = $row[6];\r
+       $new_row[8] = $row[7];\r
+       $new_row[9] = $row[8];\r
+\r
+       return $new_row;\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/links/module_delete.php b/mods/_standard/links/module_delete.php
new file mode 100644 (file)
index 0000000..7a77e7f
--- /dev/null
@@ -0,0 +1,16 @@
+<?php\r
+\r
+function links_delete($course) {\r
+       global $db;\r
+\r
+       $sql    = "SELECT cat_id FROM ".TABLE_PREFIX."links_categories WHERE owner_id=$course AND owner_type=".LINK_CAT_COURSE;\r
+       $result = mysql_query($sql, $db);\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               $sql = "DELETE FROM ".TABLE_PREFIX."links WHERE cat_id=$row[cat_id]";\r
+               mysql_query($sql, $db);\r
+       }\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."links_categories WHERE owner_id=$course AND owner_type=".LINK_CAT_COURSE;\r
+       mysql_query($sql, $db);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/links/module_groups.php b/mods/_standard/links/module_groups.php
new file mode 100644 (file)
index 0000000..402da94
--- /dev/null
@@ -0,0 +1,27 @@
+<?php\r
+\r
+// create group\r
+function links_create_group($group_id) {\r
+       global $db;\r
+\r
+       $sql    = "INSERT INTO ".TABLE_PREFIX."links_categories VALUES (NULL, ".LINK_CAT_GROUP.", $group_id, '', 0)";\r
+       $result = mysql_query($sql,$db);\r
+}\r
+\r
+\r
+// delete group\r
+function links_delete_group($group_id) {\r
+       global $db;\r
+\r
+       $sql    = "SELECT cat_id FROM ".TABLE_PREFIX."links_categories WHERE owner_type=".LINK_CAT_GROUP." AND owner_id=$group_id";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               $sql = "DELETE FROM ".TABLE_PREFIX."links WHERE cat_id=$row[cat_id]";\r
+               $result2 = mysql_query($sql, $db);\r
+       }\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."links_categories WHERE owner_type=".LINK_CAT_GROUP." AND owner_id=$group_id";\r
+       $result = mysql_query($sql, $db);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/patcher/README b/mods/_standard/patcher/README
new file mode 100644 (file)
index 0000000..85ca7da
--- /dev/null
@@ -0,0 +1,52 @@
+Patcher ReadMe
+
+This module can be installed with ATutor to 
+1) install the patches available at update.atutor.ca.
+2) Create your own ATutor patch for ATutor community
+3) For additional documentation see: http://wiki.atutor.ca/display/atutorwiki/Patcher+Module+Documentation
+
+* How to install Patcher
+1. Copy the downloaded file into the ATutor mods/ directory and unzip it there. 
+
+On Windows systems use and application like WinZip the extract the file into the mods/ directory
+
+On Unix/Linux systems use the command:
+
+tar xzvf atutor_userplane.tar.gz
+
+2. Login to ATutor as the administrator and run Install Module under the Modules tab, Select the Userplane module, which should be listed as available to be installed when the module has been unzipped into the modes directory
+
+3. Once the module has been installed, and enabled, click on the administrator's Patcher Tab to install the patches available at update.atutor.ca
+
+By default, the Patcher tab displays all patches available to public for your ATutor version. If you are given a name to install a special patch desigened for you. Enter the given name in "Name" input box, click "Get My Patch" button, the page will list the patches available for the given name. Select the patch you want to install and click "Install" button.
+
+If there are multiple patches available for your ATutor version, the patches have to be installed in sequence. Only the radio button of the patch with the lowest sequence number is enabled to be selected to install. Once it's installed, the radio button of the patch with the next lowest sequence number is enabled.
+
+* Patch installation process:
+1. Check files/folder priviledge: 
+   If the write priviledge is not given to the script on the files/folders that will be modified or overwritten, a message will be prompted to grant priviledge
+2. Compare files with SVN
+   The files that are to be modified or overwritten will be compared with ATutor SVN, if the local copy of user's file is customized, a warning will be prompted to let user decide if they want to proceed with installation. If yes is chosen, the user has to take responsibility that the installation may break their customization.
+3. Backup files
+   The files that are modified or overwritten during the installation will have a backup on the original copy. At the end of the installation, the list of all the backup files are displayed. Users are strongly recommended to fully test ATutor after the patch installation. If users are not happy with the result, they can always revert back the old ATutor by copying back the backup files. If users are happy with the result, it's also recommended to remove the backup files since they occupy hard disk space.
+
+* How to create your own ATutor patch
+1. Page "My Own Patches"
+   List all patches that are created by the login user
+   
+2. Page "Create Patch"
+- Atutor Patch ID: Required field. Must be a unique ID if the created patch is to be published at update.atutor.ca
+
+- ATutor Version to Apply: Required field. 
+
+- Description: Patch description
+
+- SQL Statement: Database operations for this patch. Please be careful on alter table command. The change on tables' structure could break other code.
+
+- Dependent Patches: The patches that need to be installed prior to the installation of this patch.
+
+- Files: File operations. Other than the name and location of the file, the information to be provided for different actions are different. For example, a file upload is required for add & overwrite action, "code to replace from" and "code to replace to" are required for alter action. If you need to delete lines from a file, please use "alter" action and leave "code to replace to" blank.
+
+3. Page "Edit Patch"
+Fields are same as "Create Patch".
+
diff --git a/mods/_standard/patcher/classes/Patch.class.php b/mods/_standard/patcher/classes/Patch.class.php
new file mode 100644 (file)
index 0000000..19de1d0
--- /dev/null
@@ -0,0 +1,775 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: Patch.class.php 7208 2008-02-08 16:07:24Z cindy $
+
+/**
+* Patch
+* Class for patch installation
+* @access      public
+* @author      Cindy Qi Li
+* @package     Patch
+*/
+
+define('AT_INCLUDE_PATH', '../../../include/');
+
+require_once(AT_INCLUDE_PATH. "../mods/_standard/patcher/include/common.inc.php");
+
+class Patch {
+
+       // all private
+       var $patch_array = array();           // the patch data
+       var $patch_summary_array = array();   // patch summary information 
+       var $patch_id;                        // current patches.patches_id
+       var $patch_file_id;                   // current patches_files.patches_files_id
+       
+       var $need_access_to_folders = array();// folders that need to have write permission
+       var $need_access_to_files = array();  // files that need to have write permission
+       var $backup_files = array();          // backup files
+       var $patch_files = array();           // patch files
+
+       var $errors = array();                // error messages
+       var $baseURL;                         // patch folder at update.atutor.ca
+       var $backup_suffix;                   // suffix appended for backup files
+       var $patch_suffix;                    // suffix appended for patch files copied from update.atutor.ca
+       var $skipFilesModified = false;       // if set to true, report error for files that have been modified by user
+       var $module_content_dir;              // content folder used to create patch.sql
+
+       // constant, URL of user's ATutor release version in SVN 
+       var $svn_tag_folder = 'http://atutorsvn.atrc.utoronto.ca/repos/atutor/tags/';
+       var $sql_file = 'patch.sql';
+       var $relative_to_atutor_root = '../../../';   // relative path from mods/_standard/patcher to root
+
+       /**
+       * Constructor: Initialize object members
+       * @access  public
+       * @param   $patch_array The name of the file to find charset definition
+       *          $patch_summary_array
+       *          $skipFilesModified
+       * @author  Cindy Qi Li
+       */
+       function Patch($patch_array, $patch_summary_array, $skipFilesModified, $patch_folder) 
+       {
+               // add relative path to move to ATutor root folder
+               for ($i = 0; $i < count($patch_array[files]); $i++)
+               {
+                       $patch_array[files][$i]['location'] = $this->relative_to_atutor_root . $patch_array[files][$i]['location'];
+               }
+               
+               $this->patch_array = $patch_array; 
+               $this->patch_summary_array = $patch_summary_array;
+               
+               $this->baseURL = $patch_folder;
+               $this ->backup_suffix = $patch_array['atutor_patch_id'] . ".old";
+               $this ->patch_suffix = $patch_array['atutor_patch_id'];
+               $this->skipFilesModified = $skipFilesModified;
+               
+               $this->module_content_dir = AT_CONTENT_DIR . "patcher";
+
+               session_start();
+               
+               if (!is_array($_SESSION['remove_permission'])) $_SESSION['remove_permission']=array();
+               
+       }
+
+       /**
+       * Main process to apply patch.
+       * @access  public
+       * @return  true  if patch is successfully applied
+       *          false if failed
+       * @author  Cindy Qi Li
+       */
+       function applyPatch() 
+       {
+               // Checks on 
+               // 1. if svn server is up
+               // 2. if the local file is customized by user
+               // 3. if script has write priviledge on local file/folder
+               // 4. if dependent patches have been installed
+               if (!$this->pingDomain($this->svn_tag_folder)) return false;
+               
+               if (!$this->checkDependentPatches()) return false;
+
+               if (!$this->checkAppliedVersion()) return false;
+
+               if (!$this->skipFilesModified && $this->hasFilesModified()) return false;
+               
+               if (!$this->checkPriviledge()) return false;
+               // End of check
+
+               if (strlen(trim($this->patch_array['sql'])) > 0) $this->runSQL();
+
+               // Start applying patch
+               $this->createPatchesRecord($this->patch_summary_array);
+
+               // if no file action defined, update database and return true
+               if (!is_array($this->patch_array[files])) 
+               {
+                       $updateInfo = array("status"=>"Installed");
+                       updatePatchesRecord($this->patch_id, $updateInfo);
+       
+                       return true;
+               }
+               
+               foreach ($this->patch_array[files] as $row_num => $patch_file)
+               {
+                       $this->createPatchesFilesRecord($this->patch_array['files'][$row_num]);
+
+                       if ($patch_file['action'] == 'alter')
+                       {
+                               $this->alterFile($row_num);
+                       }
+                       else if ($patch_file['action'] == 'add')
+                       {
+                               $this->addFile($row_num);
+                       }
+                       else if ($patch_file['action'] == 'delete')
+                       {
+                               $this->deleteFile($row_num);
+                       }
+                       else if ($patch_file['action'] == 'overwrite')
+                       {
+                               $this->overwriteFile($row_num);
+                       }
+               }
+               
+               // if only has backup files info, patch is considered successfully installed
+               // if has permission to remove, considered partly installed
+               $updateInfo = array();
+
+               if (count($this->backup_files) > 0)
+               {
+                       foreach($this->backup_files as $backup_file)
+                               $backup_files .= $backup_file. '|';
+               
+                       $updateInfo = array("backup_files"=>mysql_real_escape_string($backup_files));
+               }
+       
+               if (count($this->patch_files) > 0)
+               {
+                       foreach($this->patch_files as $patch_file)
+                               $patch_files .= $patch_file. '|';
+               
+                       $updateInfo = array_merge($updateInfo, array("patch_files"=>mysql_real_escape_string($patch_files)));
+               }
+       
+               if (is_array($_SESSION['remove_permission']) && count($_SESSION['remove_permission']))
+               {
+                       foreach($_SESSION['remove_permission'] as $remove_permission_file)
+                               $remove_permission_files .= $remove_permission_file. '|';
+
+                       $updateInfo = array_merge($updateInfo, array("remove_permission_files"=>mysql_real_escape_string($remove_permission_files), "status"=>"Partly Installed"));
+               }
+               else
+               {
+                       $updateInfo = array_merge($updateInfo, array("status"=>"Installed"));
+               } 
+
+               updatePatchesRecord($this->patch_id, $updateInfo);
+               
+               unset($_SESSION['remove_permission']);
+
+               return true;
+       }
+
+       /**
+       * return patch array
+       * @access  public
+       * @return  patch array
+       * @author  Cindy Qi Li
+       */
+       function getPatchArray() 
+       {
+               return $this->patch_array;
+       }
+       
+       /**
+       * return patch id processed by this object
+       * @access  public
+       * @return  patch id
+       * @author  Cindy Qi Li
+       */
+       function getPatchID() 
+       {
+               return $this->patch_id;
+       }
+       
+       /**
+       * Check if script has write permission to the files and folders that need to be written
+       * if no permission, warn user to give permission
+       * @access  private
+       * @return  true  if there are files or folders that script has no permission
+       *          false if permissions are in place
+       * @author  Cindy Qi Li
+       */
+       function checkPriviledge()
+       {
+               global $id, $who;
+               
+               // no file action is defined, return true;
+               if (!is_array($this->patch_array[files])) return true;
+               
+               foreach ($this->patch_array[files] as $row_num => $patch_file)
+               {
+                       $real_location = realpath($patch_file['location']);
+                       if (!is_writable($patch_file['location']) && !in_array($real_location, $this->need_access_to_folders))
+                       {
+                               $this->need_access_to_folders[] = $real_location;
+
+                               if (!in_array($real_location, $_SESSION['remove_permission']))
+                                       $_SESSION['remove_permission'][] = $real_location;
+                       }
+
+                       if ($patch_file['action'] == 'alter' || $patch_file['action'] == 'delete' || $patch_file['action'] == 'overwrite')
+                       {
+                               $file = $patch_file['location'] . "/" . $patch_file['name'];
+
+                               $real_file = realpath($file);
+                               if (file_exists($file) && !is_writable($file) && !in_array($real_file, $this->need_access_to_files))
+                               {
+                                       $this->need_access_to_files[] = $real_file;
+
+                                       if (!in_array($real_file, $_SESSION['remove_permission']) && $patch_file['action'] <> 'delete')
+                                               $_SESSION['remove_permission'][] = $real_file;
+                               }
+                       }
+               }
+               
+               if (count($this->need_access_to_folders) > 0 || count($this->need_access_to_files) > 0)
+               {
+                       $this->errors[] = _AT('grant_write_permission');
+                       
+                       foreach($this->need_access_to_folders as $folder)
+                       {
+                               $this->errors[0] .= '<strong>'. $folder . "</strong><br>";
+                       }
+
+                       foreach($this->need_access_to_files as $file)
+                       {
+                               $this->errors[0] .= '<strong>'. $file . "</strong><br>";
+                       }
+
+                       $notes = '<form action="'. $_SERVER['PHP_SELF'].'?id='.$id.'&who='. $who .'" method="post" name="skip_files_modified">
+                 <div class="row buttons">
+                               <input type="submit" name="yes" value="'._AT('continue').'" accesskey="y" />
+                               <input type="submit" name="no" value="'. _AT('cancel'). '" />
+                               <input type="hidden" name="install" value="' . $_POST['install'] . '" />
+                               <input type="hidden" name="install_upload" value="' . $_POST['install_upload'] . '" />
+                       </div>
+                       </form>';
+                       
+                       print_errors($this->errors, $notes);
+               
+                       unset($this->errors);
+                       return false;
+               }
+               
+               return true;
+       }
+       
+       /**
+       * Check if ATutor version is same as "applied version" defined in the patch.
+       * @access  private
+       * @return  true  if versions match
+       *          false if versions don't match
+       * @author  Cindy Qi Li
+       */
+       function checkAppliedVersion()
+       {
+               global $msg;
+               
+               if ($this->patch_summary_array["applied_version"] <> VERSION)
+               {
+                               $this->errors[] = _AT("version_not_match", $this->patch_summary_array["applied_version"]);
+                               
+                               $notes = '
+                         <form action="'. $_SERVER['PHP_SELF'].'?id='.$_POST['id'].'&who='. $_POST['who'] .'" method="post" name="skip_files_modified">
+                         <div class="row buttons">
+                                       <input type="submit" name="ignore_version" value="'._AT('yes').'" accesskey="y" />
+                                       <input type="submit" name="not_ignore_version" value="'. _AT('no'). '" />
+                                       <input type="hidden" name="install" value="' . $_POST['install'] . '" />
+                                       <input type="hidden" name="install_upload" value="' . $_POST['install_upload'] . '" />
+                               </div>
+                               </form>';
+
+                       print_errors($this->errors, $notes);
+               
+                       unset($this->errors);
+                       
+                       return false;
+               }
+
+               return true;
+       }
+
+       /**
+       * Check if all the dependent patches have been installed.
+       * @access  private
+       * @return  true  if all the dependent patches have been installed
+       *          false if any dependent patch has not been installed.
+       * @author  Cindy Qi Li
+       */
+       function checkDependentPatches()
+       {
+               global $msg;
+               
+               $dependent_patches_installed = true;
+               
+               // if no dependent patch defined, return true
+               if (!is_array($this->patch_summary_array["dependent_patches"])) return true;
+               
+               foreach($this->patch_summary_array["dependent_patches"] as $num => $dependent_patch)
+               {
+                       if (!is_patch_installed($dependent_patch))
+                       {
+                               $dependent_patches_installed = false;
+                               $dependent_patches .= $dependent_patch. ", ";
+                       }
+               }
+               
+               if (!$dependent_patches_installed)
+               {
+                       $errors = array('PATCH_DEPENDENCY', substr($dependent_patches, 0, -2));
+                       $msg->addError($errors);
+                       return false;
+               }
+               
+               return true;
+       }
+       
+       /**
+       * Loop thru all the patch files that will be overwitten or altered, 
+       * to find out if they are modified by user. If it's modified, warn user.
+       * @access  private
+       * @return  true  if there are files being modified
+       *          false if no file is modified
+       * @author  Cindy Qi Li
+       */
+       function hasFilesModified()
+       {
+               $overwrite_modified_files = false;
+               $alter_modified_files = false;
+               $has_not_exist_files = false;
+               
+               // no file action is defined, return nothing is modified (false)
+               if (!is_array($this->patch_array[files])) return false;
+               
+               foreach ($this->patch_array[files] as $row_num => $patch_file)
+               {
+                       if ($patch_file["action"]=='alter' || $patch_file["action"]=='overwrite')
+                       {
+                               if (!file_exists($patch_file['location'] . $patch_file['name']))
+                               {
+                                       $not_exist_files .= $patch_file['location'] . $patch_file['name'] . '<br>';
+                                       $has_not_exist_files = true;
+                               }
+                               else if ($this->isFileModified($patch_file['location'], $patch_file['name']))
+                               {
+                                       if ($patch_file['action']=='overwrite')
+                                       {
+                                               $overwrite_files .= realpath($patch_file['location'] . $patch_file['name']) . '<br>';
+                                               $overwrite_modified_files = true;
+                                       }
+                                       if ($patch_file['action']=='alter')
+                                       {
+                                               $alter_files .= realpath($patch_file['location'] . $patch_file['name']) . '<br>';
+                                               $alter_modified_files = true;
+                                       }
+                               }
+                       }
+               }
+
+               if ($has_not_exist_files) $this->errors[] = _AT('patch_local_file_not_exist'). $not_exist_files;
+               if ($overwrite_modified_files)    $this->errors[] = _AT('patcher_overwrite_modified_files') . $overwrite_files;
+               if ($alter_modified_files)    $this->errors[] = _AT('patcher_alter_modified_files') . $alter_files;
+               if (count($this->errors) > 0)
+               {
+                       if ($has_not_exist_files)
+                               $notes = '';
+                       else
+                               $notes = '
+                         <form action="'. $_SERVER['PHP_SELF'].'?id='.$_POST['id'].'&who='. $_POST['who'] .'" method="post" name="skip_files_modified">
+                         <div class="row buttons">
+                                       <input type="submit" name="yes" value="'._AT('yes').'" accesskey="y" />
+                                       <input type="submit" name="no" value="'. _AT('no'). '" />
+                                       <input type="hidden" name="install" value="' . $_POST['install'] . '" />
+                                       <input type="hidden" name="install_upload" value="' . $_POST['install_upload'] . '" />
+                               </div>
+                               </form>';
+
+                       print_errors($this->errors, $notes);
+               
+                       unset($this->errors);
+                       return true;
+               }
+               
+               return false;
+       }
+
+       /**
+       * Compare user's local file with SVN backup for user's ATutor version,
+       * if different, check table at_patches_files to see if user's local file
+       * was altered by previous patch installation. If it is, return false 
+       * (not modified), otherwise, return true (modified).
+       * @access  private
+       * @param   $folder  folder of the file to be compared
+       *          $file    name of the file to be compared
+       * @return  true     if the file is modified
+       *          false    if the file is not modified
+       * @author  Cindy Qi Li
+       */
+       function isFileModified($folder, $file)
+       {
+               global $db;
+
+               $svn_file = $this->svn_tag_folder . 'atutor_' . str_replace('.', '_', VERSION) .
+                           str_replace(substr($this->relative_to_atutor_root, 0, -1), '' , $folder) .$file;
+               $local_file = $folder.$file;
+
+               // check if the local file has been modified by user. if it is, don't overwrite
+               if ($this->compareFiles($svn_file, $local_file) <> 0)
+               {
+                       // check if the file was changed by previous installed patches
+                       $sql = "SELECT count(*) num_of_updates FROM " . TABLE_PREFIX. "patches patches, " . TABLE_PREFIX."patches_files patches_files " .
+                              "WHERE patches.applied_version = '" . VERSION . "' ".
+                              "  AND patches.status = 'Installed' " .
+                              "  AND patches.patches_id = patches_files.patches_id " .
+                              "  AND patches_files.name = '" . $file . "'";
+                       
+                       $result = mysql_query($sql, $db) or die(mysql_error());
+                       $row = mysql_fetch_assoc($result);
+                       
+                       if ($row["num_of_updates"] == 0) return true;
+               }
+               return false;
+       }
+
+       /**
+       * Run SQL defined in patch.xml
+       * @access  private
+       * @author  Cindy Qi Li
+       */
+       function runSQL()
+       {
+               // run sql
+               // As sqlutility.class.php reads sql from a file, write sql to module content folder
+               $patch_sql_file = $this->module_content_dir . '/' . $this->sql_file;
+
+               $fp = fopen($patch_sql_file, 'w');
+               fwrite($fp, trim($this->patch_array['sql']));
+               fclose($fp);
+
+               require(AT_INCLUDE_PATH . 'classes/sqlutility.class.php');
+               $sqlUtility =& new SqlUtility();
+       
+               $sqlUtility->queryFromFile($patch_sql_file, TABLE_PREFIX);
+               
+               @unlink($patch_sql_file);
+               
+               return true;
+       }
+               
+       /**
+       * Copy file from update.atutor.ca to user's computer
+       * @access  private
+       * @param   $row_num     row number of patch record to be processed
+       * @author  Cindy Qi Li
+       */
+       function addFile($row_num)
+       {
+               $this->copyFile($this->baseURL . preg_replace('/.php$/', '.new', $this->patch_array['files'][$row_num]['name']), $this->patch_array['files'][$row_num]['location'].$this->patch_array['files'][$row_num]['name']);
+               
+               return true;
+       }
+       
+       /**
+       * Delete file, backup before deletion
+       * @access  private
+       * @param   $row_num     row number of patch record to be processed
+       * @author  Cindy Qi Li
+       */
+       function deleteFile($row_num)
+       {
+               $local_file = $this->patch_array['files'][$row_num]['location'].$this->patch_array['files'][$row_num]['name'];
+               $backup_file = $local_file . "." . $this->backup_suffix;
+               
+               if (file_exists($local_file))
+               {
+                       // move file to backup
+                       $this->copyFile($local_file, $backup_file);
+                       $this->backup_files[] = realpath($backup_file);
+                       @unlink($local_file);
+               }
+               
+               return true;
+               
+       }
+       
+       /**
+       * Alter file based on <action_detail>
+       * If user's local file is modified and user agrees to proceed with applying patch,
+       * alter user's local file.
+       * @access  private
+       * @param   $row_num     row number of patch record to be processed
+       * @author  Cindy Qi Li
+       */
+       function alterFile($row_num)
+       {
+               $local_file = $this->patch_array['files'][$row_num]['location'].$this->patch_array['files'][$row_num]['name'];
+               
+               // backup user's file
+               $backup_file = $local_file . "." . $this->backup_suffix;
+               $this->copyFile($local_file, $backup_file);
+               $this->backup_files[] = realpath($backup_file);
+               
+               $local_file_content = file_get_contents($local_file);
+
+               // Modify user's file
+               foreach ($this->patch_array['files'][$row_num]['action_detail'] as $garbage => $alter_file_action)
+               {
+                       if ($alter_file_action['type'] == 'delete')
+                       {
+                               $local_file_content = $this->strReplace($alter_file_action['code_from'], '', $local_file_content);
+                       }
+
+                       if ($alter_file_action['type'] == 'replace')
+                               $local_file_content = $this->strReplace($alter_file_action['code_from'], $alter_file_action['code_to'], $local_file_content);
+
+                       $this->createPatchesFilesActionsRecord($alter_file_action);
+               }
+
+               $fp = fopen($local_file, 'w');
+               fwrite($fp, $local_file_content);
+               fclose($fp);
+
+               return true;
+       }
+       
+       /**
+       * Fetch file from update.atutor.ca and overwrite user's local file if the local file is not modified
+       * If user's local file is modified and user agrees to proceed with applying patch,
+       * copy the new file to user's local for them to merge manually.
+       * @access  private
+       * @param   $row_num     row number of patch record to be processed
+       * @author  Cindy Qi Li
+       */
+       function overwriteFile($row_num)
+       {
+               $local_file = $this->patch_array['files'][$row_num]['location'].$this->patch_array['files'][$row_num]['name'];
+               $patch_file = $this->baseURL . preg_replace('/.php$/', '.new', $this->patch_array['files'][$row_num]['name']);
+               
+               // if local file is modified and user agrees to proceed with applying patch,
+               // copy the new file to user's local for them to merge manually
+               if ($this->skipFilesModified && $this->isFileModified($this->patch_array['files'][$row_num]['location'], $this->patch_array['files'][$row_num]['name']))
+               {
+                       $local_patch_file = $local_file . "." . $this->patch_suffix;
+
+                       $this->copyFile($patch_file, $local_patch_file);
+                       
+                       $this->patch_files[] = realpath($local_patch_file);
+               }
+               else
+               {
+                       $backup_file = $local_file . "." . $this->backup_suffix;
+                       
+                       // backup user's file
+                       $this->copyFile($local_file, $backup_file);
+                       $this->backup_files[] = realpath($backup_file);
+                       
+                       // overwrite user's file
+                       $this->copyFile($patch_file, $local_file);
+               }
+               
+               return true;
+       }
+       
+       /**
+       * Copy file $src to $dest. $src can be a local file or a remote file
+       * @access  private
+       * @param   $src location of the source file
+       *          $dest        location of the destination file
+       * @author  Cindy Qi Li
+       */
+       function copyFile($src, $dest)
+       {
+               $content = file_get_contents($src);
+               $fp = fopen($dest, 'w');
+               fwrite($fp, $content);
+               fclose($fp);
+               
+               return true;
+       }
+       
+       /**
+       * Compare files $src against $dest
+       * @access  private
+       * @param   $src location of the source file
+       *          $dest        location of the destination file
+       * @return  Returns < 0 if $src is less than $dest ; > 0 if $src is greater than $dest, and 0 if they are equal.
+       * @author  Cindy Qi Li
+       */
+       function compareFiles($src, $dest)
+       {
+               // use preg_replace to delete 
+               // 1. the line starting with // $Id:
+               // 2. the line starting with $lm = '$LastChangedDate, ending with ;
+               // These lines are created by SVN. It could be different in different copies of the same file.
+               $pattern = '/\/\/ \$Id.*\$|\$lm = \'\$LastChangedDate.*;/';
+               
+               $src_content = preg_replace($pattern, '', file_get_contents($src));
+               $dest_content = preg_replace($pattern, '', file_get_contents($dest));
+               
+               return strcasecmp($src_content, $dest_content);
+       }
+       
+       /**
+       * Replace single/multiple lines of string. 
+       * This function handles different new line character at windows/unix platform
+       * @access  private
+       * @param   $search      String to replace from
+       *          $replace     String to replace to
+       *          $subject Subject to be handled  
+       * @return  return replaced string, if nothing is replaced, return original subject
+       * @author  Cindy Qi Li
+       */
+       function strReplace($search, $replace, $subject)
+       {
+               $new_line_array = array("\n", "\r", "\n\r", "\r\n");
+               
+               foreach ($new_line_array as $new_line)
+               {
+                       if (preg_match('/'.preg_quote($new_line).'/', $search) > 0)   $search_new_line = $new_line;
+                       if (preg_match('/'.preg_quote($new_line).'/', $replace) > 0)   $replace_new_line = $new_line;
+                       if (preg_match('/'.preg_quote($new_line).'/', $subject) > 0)   $subject_new_line = $new_line;
+               }
+
+               // replace new line chars in $search & $replace to new line in $subject
+               if ($search_new_line <> "" && $search_new_line <> $subject_new_line) 
+                       $search = preg_replace('/'.preg_quote($search_new_line).'/', $subject_new_line, $search);
+               
+               if ($replace_new_line <> "" && $replace_new_line <> $subject_new_line) 
+                       $replace = preg_replace('/'.preg_quote($replace_new_line).'/', $subject_new_line, $replace);
+               
+               return preg_replace('/'. preg_quote($search, '/') .'/', $replace, $subject);
+       }
+       
+       /**
+       * Check if the server is down
+       * @access  private
+       * @param   $domain      Server Domain
+       * @return  return false if server is down, otherwise, return true
+       * @author  Cindy Qi Li
+       */
+       function pingDomain($domain)
+       {
+    $file = @fopen ($domain, 'r');
+
+    if (!$file) 
+    {
+       return false;
+    }
+    return true;
+       }
+
+       /**
+       * Insert record into table patches
+       * @access  private
+       * @param   $patch_summary_array Patch summary information
+       * @author  Cindy Qi Li
+       */
+       function createPatchesRecord($patch_summary_array)
+       {
+               global $db;
+               
+               $sql = "INSERT INTO " . TABLE_PREFIX. "patches " .
+                                        "(atutor_patch_id, 
+                                          applied_version,
+                                          patch_folder,
+                                          description,
+                                          available_to,
+                                          sql_statement,
+                                          status)
+                                         VALUES
+                                         ('".$patch_summary_array["atutor_patch_id"]."',
+                                          '".$patch_summary_array["applied_version"]."',
+                                          '".mysql_real_escape_string($patch_summary_array["patch_folder"])."',
+                                          '".mysql_real_escape_string($patch_summary_array["description"])."',
+                                          '".$patch_summary_array["available_to"]."',
+                                          '',
+                                          '".$patch_summary_array["status"]."'
+                                          )";
+
+               $result = mysql_query($sql, $db) or die(mysql_error());
+               
+               $this->patch_id = mysql_insert_id();
+               
+               return true;
+       }
+
+       /**
+       * Insert record into table patches_files
+       * @access  private
+       * @param   $patch_files_array   Patch information
+       * @author  Cindy Qi Li
+       */
+       function createPatchesFilesRecord($patch_files_array)
+       {
+               global $db;
+               
+               $sql = "INSERT INTO " . TABLE_PREFIX. "patches_files " .
+                                        "(patches_id, 
+                                          action,
+                                          name,
+                                          location)
+                                         VALUES
+                                         (".$this->patch_id.",
+                                          '".$patch_files_array['action']."',
+                                          '".mysql_real_escape_string($patch_files_array['name'])."',
+                                          '".mysql_real_escape_string($patch_files_array['location'])."'
+                                          )";
+
+               $result = mysql_query($sql, $db) or die(mysql_error());
+               
+               $this->patch_file_id = mysql_insert_id();
+
+               return true;
+       }
+
+       /**
+       * Insert record into table patches_files_actions
+       * @access  private
+       * @param   $patch_files_actions_array   alter file actions and contents
+       * @author  Cindy Qi Li
+       */
+       function createPatchesFilesActionsRecord($patch_files_actions_array)
+       {
+               global $db;
+               
+               $sql = "INSERT INTO " . TABLE_PREFIX. "patches_files_actions " .
+                                        "(patches_files_id, 
+                                          action,
+                                          code_from,
+                                          code_to)
+                                         VALUES
+                                         (".$this->patch_file_id.",
+                                          '".$patch_files_actions_array['type']."',
+                                          '".mysql_real_escape_string($patch_files_actions_array['code_from'])."',
+                                          '".mysql_real_escape_string($patch_files_actions_array['code_to'])."'
+                                          )";
+
+               $result = mysql_query($sql, $db) or die(mysql_error());
+               
+               return true;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/mods/_standard/patcher/classes/PatchCreator.class.php b/mods/_standard/patcher/classes/PatchCreator.class.php
new file mode 100644 (file)
index 0000000..bd21511
--- /dev/null
@@ -0,0 +1,386 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: PatchCreator.class.php 7208 2008-02-08 16:07:24Z cindy $
+
+/**
+* Patch
+* Class to create a zipped patch package
+* zipped patch package contains patch.xml, the files to be added, overwritten
+* @access      public
+* @author      Cindy Qi Li
+* @package     PatchCreator
+*/
+
+define('AT_INCLUDE_PATH', '../../../../include/');
+require_once (AT_INCLUDE_PATH.'vitals.inc.php');
+
+require_once(AT_INCLUDE_PATH. "../mods/_standard/patcher/include/patch_xml_template.inc.php");
+
+class PatchCreator {
+
+       // all private
+       var $patch_info_array = array();           // the patch info data
+       var $patch_xml_file;                                                                                     // location of patch.xml
+       var $current_patch_id;                     // current myown_patches.myown_patch_id
+       var $version_folder;                                                                                     // version folder. underneath patcher content folder, to hold all patch folders and corresponding upload files
+       var $patch_folder;                                                                                         // patch folder. underneath version folder, to hold all upload files
+
+       /**
+       * Constructor: Initialize object members
+       * @author  Cindy Qi Li
+       * @access  public
+       * @param   $patch_info_array    All information to create a patch. Example:
+       * Array
+       * (
+       *     [atutor_patch_id] => Patch001
+       *     [atutor_version_to_apply] => 1.6
+       *     [description] => this is a sample patch info array
+       *     [sql_statement] => 
+       *     [dependent_patches] => Array
+       *     (
+       *         [0] => P2
+       *         [1] => P3
+       *     )
+       *     [files] => Array
+       *         (
+       *             [0] => Array
+       *                 (
+       *                     [file_name] => script1.php
+       *                     [action] => add
+       *                     [directory] => admin/
+       *                     [upload_tmp_name] => C:\xampp\tmp\php252.tmp
+       *                 )
+       * 
+       *             [1] => Array
+       *                 (
+       *                     [file_name] => script2.php
+       *                     [action] => delete
+       *                     [directory] => tools/
+       *                 )
+       *         )
+       * 
+       * )
+       */
+       
+       function PatchCreator($patch_info_array, $patch_id)
+       {
+               // add slashes if magic_quotes_gpc is off
+               if (!get_magic_quotes_gpc())
+               {
+                       $patch_info_array["description"] = addslashes($patch_info_array["description"]);
+                       $patch_info_array["sql_statement"] = addslashes($patch_info_array["sql_statement"]);
+                       
+                       for ($i = 0; $i < count($patch_info_array["files"]); $i++)
+                       {
+                               $patch_info_array["files"][$i]["directory"] = addslashes($patch_info_array["files"][$i]["directory"]);
+                               $patch_info_array["files"][$i]["upload_tmp_name"] = addslashes($patch_info_array["files"][$i]["upload_tmp_name"]);
+                               $patch_info_array["files"][$i]["code_from"] = addslashes($patch_info_array["files"][$i]["code_from"]);
+                               $patch_info_array["files"][$i]["code_to"] = addslashes($patch_info_array["files"][$i]["code_to"]);
+                       }
+               }
+               
+               $this->patch_info_array = $patch_info_array; 
+               $this->current_patch_id = $patch_id;
+               
+               $this->patch_xml_file = AT_CONTENT_DIR . "patcher/patch.xml";
+
+               $this->version_folder = AT_CONTENT_DIR . "patcher/" . str_replace('.', '_', $this->patch_info_array["atutor_version_to_apply"]) . "/";
+               $this->patch_folder = $this->version_folder . $this->patch_info_array["atutor_patch_id"] . "/";
+       }
+
+       /**
+       * Create Patch
+       * @access  public
+       * @return  true if created successfully
+       *          false if error happens
+       * @author  Cindy Qi Li
+       */
+       function create_patch()
+       {
+               // save patch info into database & save uploaded files into content folder
+               $this->saveInfo();
+               
+               // create patch.xml into $this->patch_xml_file
+               $fp = fopen($this->patch_xml_file,'w');
+               fwrite($fp,$this->createXML());
+               fclose($fp);
+               
+               // create zip package and force download
+               $this->createZIP();
+
+               // clean up
+               unlink($this->patch_xml_file);
+               
+               return true;
+       }
+
+       /**
+       * Save patch info into database & save uploaded files into content folder
+       * @access  public
+       * @return  xml string
+       * @author  Cindy Qi Li
+       */
+       function saveInfo() 
+       {
+               global $db;
+               
+               if ($this->current_patch_id == 0)
+               {
+                       $sql = "INSERT INTO ".TABLE_PREFIX."myown_patches 
+                              (atutor_patch_id, 
+                               applied_version,
+                               description,
+                               sql_statement,
+                               status,
+                               last_modified)
+                               VALUES ('".$this->patch_info_array["atutor_patch_id"]."', 
+                                       '".$this->patch_info_array["atutor_version_to_apply"]."', 
+                                       '".$this->patch_info_array["description"]."', 
+                                       '".$this->patch_info_array["sql_statement"]."', 
+                                       'Created',
+                                       now())";
+               }
+               else
+               {
+                       $sql = "UPDATE ".TABLE_PREFIX."myown_patches 
+                                  SET atutor_patch_id = '". $this->patch_info_array["atutor_patch_id"] ."',
+                                      applied_version = '". $this->patch_info_array["atutor_version_to_apply"] ."',
+                                      description = '". $this->patch_info_array["description"] ."',
+                                      sql_statement = '". $this->patch_info_array["sql_statement"] ."',
+                                      status = 'Created',
+                                      last_modified = now()
+                                WHERE myown_patch_id = ". $this->current_patch_id;
+               }
+
+               $result = mysql_query($sql, $db) or die(mysql_error());
+               
+               if ($this->current_patch_id == 0)
+               {
+                       $this->current_patch_id = mysql_insert_id();
+               }
+               else // delete records for current_patch_id in tables myown_patches_dependent & myown_patches_files
+               {
+                       $sql = "DELETE FROM ".TABLE_PREFIX."myown_patches_dependent WHERE myown_patch_id = " . $this->current_patch_id;
+                       $result = mysql_query($sql, $db) or die(mysql_error());
+                       
+                       $sql = "DELETE FROM ".TABLE_PREFIX."myown_patches_files WHERE myown_patch_id = " . $this->current_patch_id;
+                       $result = mysql_query($sql, $db) or die(mysql_error());
+               }
+               
+               // insert records into table myown_patches_dependent
+               if (is_array($this->patch_info_array["dependent_patches"]))
+               {
+                       foreach ($this->patch_info_array["dependent_patches"] as $dependent_patch)
+                       {
+                               $sql = "INSERT INTO ".TABLE_PREFIX."myown_patches_dependent 
+                              (myown_patch_id, 
+                               dependent_patch_id)
+                               VALUES ('".$this->current_patch_id."', 
+                                       '".$dependent_patch."')";
+
+                               $result = mysql_query($sql, $db) or die(mysql_error());
+                       }
+               }
+               
+               // insert records into table myown_patches_files
+               if (is_array($this->patch_info_array["files"]))
+               {
+                       foreach ($this->patch_info_array["files"] as $file_info)
+                       {
+                               if ($file_info["upload_tmp_name"] <> "")
+                                       $upload_to = $this->saveFile($file_info);
+                               else
+                                       $upload_to = "";
+                                       
+                               $sql = "INSERT INTO ".TABLE_PREFIX."myown_patches_files
+                              (myown_patch_id, 
+                               action,
+                               name,
+                               location,
+                               code_from,
+                               code_to,
+                               uploaded_file)
+                               VALUES ('".$this->current_patch_id."', 
+                                       '".$file_info["action"]."', 
+                                       '".$file_info["file_name"]."', 
+                                       '".$file_info["directory"]."', 
+                                       '".$file_info["code_from"]."', 
+                                       '".$file_info["code_to"]."',
+                                       '".addslashes($upload_to)."')";
+
+                               $result = mysql_query($sql, $db) or die(mysql_error());
+                       }
+               }
+       }
+
+       /**
+       * Save upload file into content folder
+       * @access  private
+       * @return  xml string
+       * @author  Cindy Qi Li
+       */
+       function saveFile($file_info) 
+       {
+               // mkdir() function cannot create folder recursively, so have to acomplish the creation of patch folder by 2 steps.
+               if (!file_exists($this->version_folder))        mkdir($this->version_folder);
+               if (!file_exists($this->patch_folder))  mkdir($this->patch_folder);
+               
+               $upload_to = $this->patch_folder . $file_info['file_name'];
+               
+               // copy uploaded file into content folder
+               copy($file_info["upload_tmp_name"], $upload_to);
+               
+               return realpath($upload_to);
+       }
+
+       /**
+       * Create patch.xml.
+       * @access  private
+       * @return  xml string
+       * @author  Cindy Qi Li
+       */
+       function createXML() 
+       {
+               global $patch_xml, $dependent_patch_xml;
+               global $patch_action_detail_xml, $patch_file_xml;
+               
+               // generate content of <dependent_patches> section
+               if (is_array($this->patch_info_array["dependent_patches"]))
+               {
+                       foreach ($this->patch_info_array["dependent_patches"] as $dependent_patch)
+                               $dependent_patches .= str_replace('{DEPENDENT_PATCH}', $dependent_patch, $dependent_patch_xml);
+               }
+               
+               // generate content of <files> section
+               if (is_array($this->patch_info_array["files"]))
+               {
+                       foreach ($this->patch_info_array["files"] as $file_info)
+                       {
+                               $action_details = "";
+                               
+                               if ($file_info["action"] == "alter")
+                               {
+                                       $action_details .= str_replace(array('{TYPE}', '{CODE_FROM}', '{CODE_TO}'), 
+                                                                         array('replace', 
+                                                                                               htmlspecialchars(stripslashes($file_info["code_from"]), ENT_QUOTES), 
+                                                                                               htmlspecialchars(stripslashes($file_info["code_to"]), ENT_QUOTES)),
+                                                                         $patch_action_detail_xml);
+                               }
+                               
+                               $xml_files .= str_replace(array('{ACTION}', '{NAME}', '{LOCATION}', '{ACTION_DETAILS}'), 
+                                                                         array($file_info["action"], $file_info["file_name"], $file_info["directory"], $action_details),
+                                                                         $patch_file_xml);
+                       }
+               }
+
+               // generate patch.xml
+               return str_replace(array('{ATUTOR_PATCH_ID}', 
+                                        '{APPLIED_VERSION}', 
+                                        '{DESCRIPTION}', 
+                                        '{SQL}', 
+                                        '{DEPENDENT_PATCHES}',
+                                        '{FILES}'), 
+                                                                array($this->patch_info_array["atutor_patch_id"], 
+                                                                      $this->patch_info_array["atutor_version_to_apply"], 
+                                                                      htmlspecialchars(stripslashes($this->htmlNewLine($this->patch_info_array["description"])), ENT_QUOTES), 
+                                                                      htmlspecialchars(stripslashes($this->patch_info_array["sql_statement"]), ENT_QUOTES), 
+                                                                      $dependent_patches,
+                                                                      $xml_files),
+                                                                $patch_xml);
+       }
+
+       /**
+       * Create xml for section <files> in patch.xml.
+       * @access  private
+       * @return  xml string
+       * @author  Cindy Qi Li
+       */
+       function createXMLFiles($file_info)
+       {
+               
+               $action_details = "";
+               
+               if ($file_info["action"] == "alter")
+               {
+                       $action_details .= str_replace(array('{TYPE}', '{CODE_FROM}', '{CODE_TO}'), 
+                                                         array('replace', 
+                                                                               htmlspecialchars(stripslashes($file_info["code_from"]), ENT_QUOTES), 
+                                                                               htmlspecialchars(stripslashes($file_info["code_to"]), ENT_QUOTES)),
+                                                         $patch_action_detail_xml);
+               }
+               
+               return str_replace(array('{ACTION}', '{NAME}', '{LOCATION}', '{ACTION_DETAILS}'), 
+                                                         array($file_info["action"], $file_info["file_name"], $file_info["directory"], $action_details),
+                                                         $patch_file_xml);
+       }
+       
+       /**
+       * Create zip file which contains patch.xml and the files to be added, overwritten, altered; and force to download
+       * @access  private
+       * @return  true   if successful
+       *          false  if errors
+       * @author  Cindy Qi Li
+       */
+       function createZIP() 
+       {
+               require_once(AT_INCLUDE_PATH . '/classes/zipfile.class.php');
+
+               $zipfile =& new zipfile();
+       
+               $zipfile->add_file(file_get_contents($this->patch_xml_file), 'patch.xml');
+
+               if (is_array($this->patch_info_array["files"]))
+               {
+                       foreach ($this->patch_info_array["files"] as $file_info)
+                       {
+                               if ($file_info["upload_tmp_name"] <> '')
+                               {
+                                       $file_name = preg_replace('/.php$/', '.new', $file_info['file_name']);
+                                       $zipfile->add_file(file_get_contents($file_info['upload_tmp_name']), $file_name);
+                               }
+                       }
+               }
+
+               $zipfile->send_file($this->patch_info_array["atutor_patch_id"]);
+       }
+
+       /**
+       * replace new line string to html tag <br>
+       * @access  private
+       * @return  converted string
+       * @author  Cindy Qi Li
+       */
+       function htmlNewLine($str)
+       {
+               $new_line_array = array("\n", "\r", "\n\r", "\r\n");
+
+               $found_match = false;
+               
+               if (strlen(trim($str))==0) return "";
+               
+               foreach ($new_line_array as $new_line)
+                       if (preg_match('/'.preg_quote($new_line).'/', $str) > 0)
+                       {
+                               $search_new_line = $new_line;
+                               $found_match = true;
+                       }
+                
+               if ($found_match)
+                       return preg_replace('/'. preg_quote($search_new_line) .'/', "<br>", $str);
+               else
+                       return $str;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/mods/_standard/patcher/classes/PatchListParser.class.php b/mods/_standard/patcher/classes/PatchListParser.class.php
new file mode 100644 (file)
index 0000000..2a1c803
--- /dev/null
@@ -0,0 +1,128 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: PatchListParser.class.php 7208 2008-02-08 16:07:24Z cindy $
+
+/**
+* PatchListParser
+* Class for parsing XML patch list info
+* @access      public
+* @author      Cindy Qi Li
+* @package     Patch
+*/
+class PatchListParser {
+
+       // all private
+       var $parser; // the XML handler
+       var $patch_rows = array(); // the patch data
+       var $character_data; // tmp variable for storing the data
+       var $element_path; // array of element paths (basically a stack)
+       var $row_num;
+       var $dependent_patches_num;
+
+       function PatchListParser() {
+               $this->parser = xml_parser_create(''); 
+
+               xml_set_object($this->parser, $this);
+               xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false); /* conform to W3C specs */
+               xml_set_element_handler($this->parser, 'startElement', 'endElement');
+               xml_set_character_data_handler($this->parser, 'characterData');
+       }
+
+       // public
+       function parse($xml_data) {
+               $this->element_path   = array();
+               $this->patch_rows  = array();
+               $this->character_data = '';
+               $this->row_num        = 0;
+               xml_parse($this->parser, $xml_data, TRUE);
+       }
+
+       // private
+       function startElement($parser, $name, $attributes) 
+       {
+               array_push($this->element_path, $name);
+   }
+
+       // private
+       /* called when an element ends */
+       /* removed the current element from the $path */
+       function endElement($parser, $name) {
+               if ($this->element_path == array('patch_list', 'patch', 'atutor_patch_id')) 
+               {
+                       $this->patch_rows[$this->row_num]['atutor_patch_id'] = trim($this->character_data);
+               } 
+               else if ($this->element_path === array('patch_list', 'patch', 'applied_version')) 
+               {
+                       $this->patch_rows[$this->row_num]['applied_version'] = trim($this->character_data);
+               } 
+               else if ($this->element_path === array('patch_list', 'patch', 'patch_folder')) 
+               {
+                       $this->patch_rows[$this->row_num]['patch_folder'] = trim($this->character_data);
+               } 
+               else if ($this->element_path === array('patch_list', 'patch', 'description')) 
+               {
+                       $this->patch_rows[$this->row_num]['description'] = trim($this->character_data);
+               } 
+               else if ($this->element_path === array('patch_list', 'patch', 'available_to')) 
+               {
+                       $this->patch_rows[$this->row_num]['available_to'] = trim($this->character_data);
+               } 
+               else if ($this->element_path === array('patch_list', 'patch', 'dependent_patches', 'dependent_patch')) 
+               {
+                       $this->patch_rows[$this->row_num]['dependent_patches'][$this->dependent_patches_num++] = trim($this->character_data);
+               }
+               else if ($this->element_path === array('patch_list', 'patch')) 
+               {
+                       $this->row_num++;
+                       $this->dependent_patches_num = 0;
+               }
+
+               array_pop($this->element_path);
+               $this->character_data = '';
+       }
+
+       // private
+       function characterData($parser, $data){
+               $this->character_data .= $data;
+       }
+
+       // public
+       function getNumPathes() 
+       {
+               return count($this->patch_rows);
+       }
+
+       // public
+       function getParsedArray() 
+       {
+               return $this->patch_rows;
+       }
+
+       // public
+       // return parsed array only for given name & version
+       function getMyParsedArrayForVersion($version, $who='public') 
+       {
+               $my_array = array();
+
+               // filter out the patch for given version
+               foreach ($this->patch_rows as $key => $row) 
+               {
+           if ($row['applied_version'] == $version && $row['available_to']==$who)
+               array_push($my_array, $row);
+               }
+               
+               return $my_array;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/mods/_standard/patcher/classes/PatchParser.class.php b/mods/_standard/patcher/classes/PatchParser.class.php
new file mode 100644 (file)
index 0000000..a9b646c
--- /dev/null
@@ -0,0 +1,139 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: PatchParser.class.php 7208 2008-02-08 16:07:24Z greg $
+
+/**
+* PatchParser
+* Class for parsing XML patch info (patch.xml)
+* @access      public
+* @author      Cindy Qi Li
+* @package     Patch
+*/
+class PatchParser {
+
+       // all private
+       var $parser; // the XML handler
+       var $patch_row = array(); // the patch data
+       var $character_data; // tmp variable for storing the data
+       var $element_path; // array of element paths (basically a stack)
+       var $file_num;
+       var $action_detail_num;
+       var $dependent_patches_num;
+
+       function PatchParser() {
+               $this->parser = xml_parser_create(''); 
+
+               xml_set_object($this->parser, $this);
+               xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false); /* conform to W3C specs */
+               xml_set_element_handler($this->parser, 'startElement', 'endElement');
+               xml_set_character_data_handler($this->parser, 'characterData');
+       }
+
+       // public
+       function parse($xml_data) {
+               $this->element_path   = array();
+               $this->patch_row  = array();
+               $this->character_data = '';
+               $this->file_num = 0;
+               $this->action_detail_num = 0;
+               $this->dependent_patches_num = 0;
+               
+               xml_parse($this->parser, $xml_data, TRUE);
+       }
+
+       // private
+       function startElement($parser, $name, $attributes) 
+       {
+               array_push($this->element_path, $name);
+  }
+
+       // private
+       /* called when an element ends */
+       /* removed the current element from the $path */
+       function endElement($parser, $name)
+       {
+               if ($this->element_path == array('patch', 'atutor_patch_id')) 
+               {
+                       $this->patch_row['atutor_patch_id'] = trim($this->character_data);
+               }
+               if ($this->element_path == array('patch', 'applied_version')) 
+               {
+                       $this->patch_row['applied_version'] = trim($this->character_data);
+               }
+               if ($this->element_path == array('patch', 'sequence')) 
+               {
+                       $this->patch_row['sequence'] = trim($this->character_data);
+               }
+               if ($this->element_path == array('patch', 'description')) 
+               {
+                       $this->patch_row['description'] = trim($this->character_data);
+               }
+               if ($this->element_path === array('patch', 'dependent_patches', 'dependent_patch')) 
+               {
+                       $this->patch_row['dependent_patches'][$this->dependent_patches_num++] = trim($this->character_data);
+               }
+               if ($this->element_path == array('patch', 'sql')) 
+               {
+                       $this->patch_row['sql'] = trim($this->character_data);
+               }
+               else if ($this->element_path === array('patch', 'files', 'file', 'action')) 
+               {
+                       $this->patch_row['files'][$this->file_num]['action'] = trim($this->character_data);
+               } 
+               else if ($this->element_path === array('patch', 'files', 'file', 'name')) 
+               {
+                       $this->patch_row['files'][$this->file_num]['name'] = trim($this->character_data);
+               } 
+               else if ($this->element_path === array('patch', 'files', 'file', 'location')) 
+               {
+                       $this->patch_row['files'][$this->file_num]['location'] = trim($this->character_data);
+               } 
+               else if ($this->element_path === array('patch', 'files', 'file', 'action_detail', 'type')) 
+               {
+                       $this->patch_row['files'][$this->file_num]['action_detail'][$this->action_detail_num]['type'] = trim($this->character_data);
+               } 
+               else if ($this->element_path === array('patch', 'files', 'file', 'action_detail', 'code_from')) 
+               {
+                       $this->patch_row['files'][$this->file_num]['action_detail'][$this->action_detail_num]['code_from'] = trim($this->character_data);
+               } 
+               else if ($this->element_path === array('patch', 'files', 'file', 'action_detail', 'code_to')) 
+               {
+                       $this->patch_row['files'][$this->file_num]['action_detail'][$this->action_detail_num]['code_to'] = trim($this->character_data);
+               } 
+               else if ($this->element_path === array('patch', 'files', 'file')) 
+               {
+                       $this->file_num++;
+               }
+               else if ($this->element_path === array('patch', 'files', 'file', 'action_detail')) 
+               {
+                       $this->action_detail_num++;
+               }
+
+               array_pop($this->element_path);
+               $this->character_data = '';
+       }
+
+       // private
+  function characterData($parser, $data)
+  {
+               $this->character_data .= $data;
+       }
+
+       // public
+       function getParsedArray() 
+       {
+               return $this->patch_row;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/mods/_standard/patcher/include/common.inc.php b/mods/_standard/patcher/include/common.inc.php
new file mode 100644 (file)
index 0000000..4095f48
--- /dev/null
@@ -0,0 +1,132 @@
+<?php\r
+function print_errors( $errors, $notes='' ) {\r
+       ?>\r
+       <div class="input-form">\r
+       <table border="0" class="errbox" cellpadding="3" cellspacing="2" width="100%" summary="" align="center">\r
+       <tr class="errbox">\r
+               <td>\r
+               <h3 class="err"><img src="images/bad.gif" align="top" alt="" class="img" /> Warning</h3>\r
+               <?php\r
+                       echo '<ul>';\r
+                       foreach ($errors as $p) {\r
+                               echo '<li>'.$p.'</li>';\r
+                       }\r
+                       echo '</ul>';\r
+               ?>\r
+               </td>\r
+       </tr>\r
+       <tr>\r
+               <td>\r
+               <?php echo $notes; ?>\r
+               </td>\r
+       </tr>\r
+       </table>\r
+       </div>\r
+<?php\r
+}\r
+\r
+function print_feedback( $feedback, $notes='' ) {\r
+       ?>\r
+       <div class="input-form">\r
+       <table border="0" class="fbkbox" cellpadding="3" cellspacing="2" width="100%" summary="" align="center">\r
+       <tr class="fbkbox">\r
+       <td><h3 class="feedback2"><img src="images/feedback.gif" align="top" alt="" class="img" /> The patch has been installed successfully!</h3>\r
+               <?php\r
+                       echo '<ul>';\r
+                       foreach ($feedback as $p) {\r
+                               echo '<li>'.$p.'</li>';\r
+                       }\r
+                       echo '</ul>';\r
+               ?></td>\r
+       </tr>\r
+       <tr>\r
+               <td>\r
+               <?php echo $notes; ?>\r
+               </td>\r
+       </tr>\r
+       </table>\r
+       </div>\r
+<?php\r
+}\r
+\r
+\r
+/**\r
+* update patches.remove_permission_files & patches.backup_files\r
+* @access  private\r
+* @author  Cindy Qi Li\r
+*/\r
+function updatePatchesRecord($patch_id, $updateInfo)\r
+{\r
+       global $db;\r
+       \r
+       $sql_prefix = "Update ". TABLE_PREFIX. "patches set ";\r
+       \r
+       foreach ($updateInfo as $key => $value)\r
+       {\r
+               $sql_middle .= $key . "='" . $value . "', ";\r
+       }\r
+       \r
+       $sql = substr($sql_prefix . $sql_middle, 0, -2) . " where patches_id = " . $patch_id;\r
+\r
+       $result = mysql_query($sql, $db) or die(mysql_error());\r
+       \r
+       return true;\r
+}\r
+\r
+/**\r
+* This function deletes $dir recrusively without deleting $dir itself.\r
+* @access  public\r
+* @param   string $charsets_array      The name of the directory where all files and folders under needs to be deleted\r
+* @author  Cindy Qi Li\r
+*/\r
+function clear_dir($dir) {\r
+       include_once(AT_INCLUDE_PATH . '/lib/filemanager.inc.php');\r
+       \r
+       if(!$opendir = @opendir($dir)) {\r
+               return false;\r
+       }\r
+       \r
+       while(($readdir=readdir($opendir)) !== false) {\r
+               if (($readdir !== '..') && ($readdir !== '.')) {\r
+                       $readdir = trim($readdir);\r
+\r
+                       clearstatcache(); /* especially needed for Windows machines: */\r
+\r
+                       if (is_file($dir.'/'.$readdir)) {\r
+                               if(!@unlink($dir.'/'.$readdir)) {\r
+                                       return false;\r
+                               }\r
+                       } else if (is_dir($dir.'/'.$readdir)) {\r
+                               /* calls lib function to clear subdirectories recrusively */\r
+                               if(!clr_dir($dir.'/'.$readdir)) {\r
+                                       return false;\r
+                               }\r
+                       }\r
+               }\r
+       } /* end while */\r
+\r
+       @closedir($opendir);\r
+       \r
+       return true;\r
+}\r
+\r
+/**\r
+ * Check if the patch has been installed\r
+ */\r
+function is_patch_installed($patch_id)\r
+{\r
+       global $db;\r
+       \r
+       // Only displays the patches that are not installed\r
+       $sql = "select count(*) num_of_installed from ".TABLE_PREFIX."patches " .\r
+              "where atutor_patch_id = '" . $patch_id ."'".\r
+              " and status like '%Installed'";\r
+\r
+       $result = mysql_query($sql, $db) or die(mysql_error());\r
+       $row = mysql_fetch_assoc($result);\r
+       \r
+       if ($row["num_of_installed"] > 0) return true;\r
+       else return false;\r
+}\r
+\r
+?>\r
diff --git a/mods/_standard/patcher/include/json.inc.php b/mods/_standard/patcher/include/json.inc.php
new file mode 100644 (file)
index 0000000..db8ff76
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+// my simple JSON encode/decode function, similar to PHP5.2 
+function json_encode_result($phpdata) {
+       if(gettype($phpdata) == "resource") 
+               return php2js_sqlresult($phpdata);
+       else if(is_array($phpdata)) 
+               return php2js_array($phpdata);
+       else
+               return php2js_object($phpdata);
+}
+
+
+//function json_decode($jsonata) {
+//     return $phpdata;
+//}
+
+
+// convert a PHP object to javascript object
+function php2js_object($phpobj) {
+       $str = ""; 
+       
+       if (!is_array($phpobj)) return "[]";
+       
+       foreach($phpobj as $col => $val) {
+         if($str == "")
+           $str = $col .":'" . escapeString($val) . "'";
+         else
+           $str = $str . "," . $col .":'" . escapeString($val) . "'";
+       }
+       
+       return "{" . $str . "}";
+}
+
+// convert a PHP object to javascript object
+function php2js_array($phparr) {
+       $str = "";
+
+  if (!is_array($phparr)) return "[]";
+
+       foreach ($phparr as $e) {
+         if($str == "") 
+                       $str = php2js_object($e) ;
+         else
+           $str = $str . "," . php2js_object($e);
+       }
+       
+       return "[" . $str . "]";
+}
+
+// convert a SQL result object to javascript object
+function php2js_sqlresult($phpsql) {
+       // Printing results
+       $rows = array();
+       while ($line = mysql_fetch_assoc($phpsql)) {
+               $rows[] = $line;
+       }
+       mysql_free_result($phpsql);
+       return php2js_array($rows);
+}
+
+function escapeString($string) {
+    $escape = array(
+    "\r\n" => '\n',
+    "\r"   => '\n',
+    "\n"   => '\n',
+    "/"    => '\/'
+    );
+
+    return str_replace(array_keys($escape), array_values($escape), addslashes($string));
+}      
+
+?>
\ No newline at end of file
diff --git a/mods/_standard/patcher/include/patch_xml_template.inc.php b/mods/_standard/patcher/include/patch_xml_template.inc.php
new file mode 100644 (file)
index 0000000..c6c4777
--- /dev/null
@@ -0,0 +1,44 @@
+<?php\r
+\r
+$patch_xml =\r
+'<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<patch>\r
+       <atutor_patch_id>{ATUTOR_PATCH_ID}</atutor_patch_id>\r
+       <applied_version>{APPLIED_VERSION}</applied_version>\r
+       <description>{DESCRIPTION}</description>\r
+       <dependent_patches>\r
+{DEPENDENT_PATCHES}\r
+       </dependent_patches>\r
+\r
+       <sql>\r
+{SQL}\r
+       </sql>\r
+\r
+       <files>\r
+{FILES}\r
+       </files>\r
+</patch>';\r
+\r
+$dependent_patch_xml = \r
+'              <dependent_patch>{DEPENDENT_PATCH}</dependent_patch>\r
+';     \r
+\r
+$patch_file_xml = \r
+'              <file>\r
+                       <action>{ACTION}</action>\r
+                       <name>{NAME}</name>\r
+                       <location>{LOCATION}</location>\r
+{ACTION_DETAILS}\r
+               </file>\r
+\r
+';     \r
+\r
+$patch_action_detail_xml = \r
+'                      <action_detail>\r
+                               <type>{TYPE}</type>\r
+                               <code_from>{CODE_FROM}</code_from>\r
+                               <code_to>{CODE_TO}</code_to>\r
+                       </action_detail>\r
+\r
+';\r
+?>\r
diff --git a/mods/_standard/patcher/index_admin.php b/mods/_standard/patcher/index_admin.php
new file mode 100644 (file)
index 0000000..b9e6a0f
--- /dev/null
@@ -0,0 +1,435 @@
+<?php\r
+define('AT_INCLUDE_PATH', '../../../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_PATCHER);\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+require_once('include/common.inc.php');\r
+\r
+set_time_limit(0);\r
+\r
+/**\r
+ * Generate html of each patch row at main patch page\r
+ */\r
+function print_patch_row($patch_row, $row_id, $enable_radiotton)\r
+{\r
+       global $id, $patch_id;   // current selected patch\r
+       global $dependent_patches;\r
+\r
+       if ($dependent_patches =="")\r
+               $description = $patch_row["description"];\r
+       else\r
+               $description = $patch_row["description"] . _AT('patch_dependent_patch_not_installed') . "<span style='color: red'>" . $dependent_patches . "</span>";\r
+?>\r
+       <tr <?php if ($enable_radiotton) echo 'onmousedown="document.form[\'m'. $row_id.'\'].checked = true; rowselect(this);"'; ?> id="r_<?php echo $row_id; ?>">\r
+               <td><input type="radio" name="id" value="<?php echo $row_id; ?>" id="m<?php echo $row_id; ?>" <?php if (!$enable_radiotton) echo "disabled "; if (strcmp($row_id, $id) == 0 || strcmp($row_id, $patch_id) == 0) echo "checked "?> /></td>\r
+               <td><label for="m<?php echo $row_id; ?>"><?php echo $patch_row["atutor_patch_id"]; ?></label></td>\r
+               <td><?php echo $description; ?></td>\r
+               <td><?php if (!isset($patch_row['status'])) echo "Uninstalled"; else echo $patch_row["status"]; ?></td>\r
+               <td><?php echo $patch_row["available_to"]; ?></td>\r
+               <td>\r
+               <?php \r
+               if (preg_match('/Installed/', $patch_row["status"]) > 0 && ($patch_row["remove_permission_files"]<> "" || $patch_row["backup_files"]<>"" || $patch_row["patch_files"]<> ""))\r
+                       echo '\r
+                 <div class="row buttons">\r
+                               <input type="button" align="center" name="info" value="'._AT('view_message').'" onClick="location.href=\''. $_SERVER['PHP_SELF'] .'?patch_id='.$row_id.'\'" />\r
+                       </div>';\r
+               ?>\r
+               </td>\r
+       </tr>\r
+<?php\r
+}\r
+\r
+// split a string by given delimiter and return an array\r
+function get_array_by_delimiter($subject, $delimiter)\r
+{\r
+       return preg_split('/'.preg_quote($delimiter).'/', $subject, -1, PREG_SPLIT_NO_EMPTY);\r
+}\r
+\r
+$skipFilesModified = false;\r
+\r
+if ($_POST['yes'])  $skipFilesModified = true;\r
+\r
+require_once('classes/PatchListParser.class.php');\r
+\r
+if (trim($_POST['who']) != '') $who = trim($_POST['who']);\r
+elseif (trim($_REQUEST['who']) != '') $who = trim($_REQUEST['who']);\r
+else $who = "public";\r
+\r
+// check the connection to server update.atutor.ca\r
+$update_server = "update.atutor.ca"; \r
+\r
+$file = fsockopen ($update_server, 80, $errno, $errstr, 15);\r
+\r
+if (!$file) \r
+{\r
+       print '<span style="color: red"><b>Error: Cannot connect to patch server: '. $update_server . '</b></span>';\r
+       exit;\r
+}\r
+\r
+// get patch list\r
+$patch_folder = "http://" . $update_server . '/patch/' . str_replace('.', '_', VERSION) . '/';\r
+\r
+$patch_list_xml = @file_get_contents($patch_folder . 'patch_list.xml');\r
+\r
+if ($patch_list_xml) \r
+{\r
+       $patchListParser =& new PatchListParser();\r
+       $patchListParser->parse($patch_list_xml);\r
+       $patch_list_array = $patchListParser->getMyParsedArrayForVersion(VERSION);\r
+}\r
+// end of get patch list\r
+\r
+$module_content_folder = AT_CONTENT_DIR . "patcher";\r
+               \r
+if ($_POST['install_upload'] && $_POST['uploading'])\r
+{\r
+       include_once(AT_INCLUDE_PATH . '/classes/pclzip.lib.php');\r
+       \r
+       // clean up module content folder\r
+       clear_dir($module_content_folder);\r
+       \r
+       // 1. unzip uploaded file to module's content directory\r
+       $archive = new PclZip($_FILES['patchfile']['tmp_name']);\r
+\r
+       if ($archive->extract(PCLZIP_OPT_PATH, $module_content_folder) == 0)\r
+       {\r
+    clear_dir($module_content_folder);\r
+    $msg->addError('CANNOT_UNZIP');\r
+  }\r
+}\r
+\r
+// Installation process\r
+if ($_POST['install'] || $_POST['install_upload'] && !isset($_POST["not_ignore_version"]))\r
+{\r
+       \r
+       if (isset($_POST['id'])) $id=$_POST['id'];\r
+       else $id = $_REQUEST['id'];\r
+\r
+       if ($_POST['install'] && $id == "")\r
+       {\r
+               $msg->addError('CHOOSE_UNINSTALLED_PATCH');\r
+       }\r
+       else\r
+       {\r
+               if ($_POST['install'])\r
+               {\r
+                       $patchURL = $patch_folder . $patch_list_array[$id][patch_folder] . "/";\r
+               }\r
+               else if ($_POST['install_upload'])\r
+               {\r
+                       $patchURL = $module_content_folder . "/";\r
+               }\r
+                       \r
+               $patch_xml = @file_get_contents($patchURL . 'patch.xml');\r
+               \r
+               if ($patch_xml === FALSE) \r
+               {\r
+                       $msg->addError('PATCH_XML_NOT_FOUND');\r
+               }\r
+               else\r
+               {\r
+                       require_once('classes/PatchParser.class.php');\r
+                       require_once('classes/Patch.class.php');\r
+                       \r
+                       $patchParser =& new PatchParser();\r
+                       $patchParser->parse($patch_xml);\r
+                       \r
+                       $patch_array = $patchParser->getParsedArray();\r
+\r
+                       if ($_POST["ignore_version"]) $patch_array["applied_version"] = VERSION;\r
+                       \r
+                       if ($_POST["install_upload"])\r
+                       {\r
+                               $current_patch_list = array('atutor_patch_id' => $patch_array['atutor_patch_id'],\r
+                                                                                                                                               'applied_version' => $patch_array['applied_version'],\r
+                                                                                                                                               'patch_folder' => $patchURL,\r
+                                                                                                                                               'available_to' => 'private',\r
+                                                                                                                                               'description' => $patch_array['description'],\r
+                                                                                                                                               'dependent_patches' => $patch_array['dependent_patches']);\r
+                       }\r
+\r
+                       if ($_POST["install"])\r
+                       {\r
+                               $current_patch_list = $patch_list_array[$id];\r
+                       }\r
+\r
+                       if ($_POST["install_upload"] && is_patch_installed($patch_array["atutor_patch_id"]))\r
+                               $msg->addError('PATCH_ALREADY_INSTALLED');\r
+                       else\r
+                       {\r
+                               $patch = & new Patch($patch_array, $current_patch_list, $skipFilesModified, $patchURL);\r
+                       \r
+                               if ($patch->applyPatch())  $patch_id = $patch->getPatchID();\r
+                       }\r
+               }\r
+       }\r
+}\r
+// end of patch installation\r
+\r
+// display permission and backup files message\r
+if (isSet($_REQUEST['patch_id']))  $patch_id = $_REQUEST['patch_id'];\r
+elseif ($_POST['patch_id']) $patch_id=$_POST['patch_id'];\r
+\r
+if ($patch_id > 0)\r
+{\r
+       // clicking on button "Done" at displaying remove permission info page\r
+       if ($_POST['done'])\r
+       {\r
+               $permission_files = array();\r
+               \r
+               if (is_array($_SESSION['remove_permission']))\r
+               {\r
+                       foreach ($_SESSION['remove_permission'] as $file)\r
+                       {\r
+                               if (is_writable($file))  $permission_files[] = $file;\r
+                       }\r
+               }\r
+               \r
+               if (count($permission_files) == 0)\r
+               {\r
+                       $updateInfo = array("remove_permission_files"=>"", "status"=>"Installed");\r
+               \r
+                       updatePatchesRecord($patch_id, $updateInfo);\r
+               }\r
+               else\r
+               {\r
+                       foreach($permission_files as $permission_file)\r
+                               $remove_permission_files .= $permission_file. '|';\r
+               \r
+                       $updateInfo = array("remove_permission_files"=>preg_quote($remove_permission_files), "status"=>"Partly Installed");\r
+                       \r
+                       updatePatchesRecord($patch_id, $updateInfo);\r
+               }\r
+       \r
+       }\r
+       \r
+       // display remove permission info\r
+       unset($_SESSION['remove_permission']);\r
+\r
+       $sql = "SELECT * FROM ".TABLE_PREFIX."patches \r
+                WHERE patches_id = " . $patch_id;\r
+\r
+       $result = mysql_query($sql, $db) or die(mysql_error());\r
+       $row = mysql_fetch_assoc($result);\r
+       \r
+       if ($row["remove_permission_files"]<> "")\r
+       {\r
+               $remove_permission_files = $_SESSION['remove_permission'] = get_array_by_delimiter($row["remove_permission_files"], "|");\r
+\r
+               if (count($_SESSION['remove_permission']) > 0)\r
+               {\r
+                       if ($_POST['done']) $msg->printErrors('REMOVE_WRITE_PERMISSION');\r
+                       else $msg->printInfos('PATCH_INSTALLED_AND_REMOVE_PERMISSION');\r
+                       \r
+                       $feedbacks[] = _AT('remove_write_permission');\r
+                       \r
+                       foreach($remove_permission_files as $remove_permission_file)\r
+                               if ($remove_permission_file <> "") $feedbacks[count($feedbacks)-1] .= "<strong>" . $remove_permission_file . "</strong><br>";\r
+\r
+                       $notes = '<form action="'. $_SERVER['PHP_SELF'].'?patch_id='.$patch_id.'" method="post" name="remove_permission">\r
+                 <div class="row buttons">\r
+                               <input type="hidden" name="patch_id" value="'.$patch_id.'" />\r
+                               <input type="submit" name="done" value="'._AT('done').'" accesskey="d" />\r
+                       </div>\r
+                       </form>';\r
+               }\r
+\r
+               print_errors($feedbacks, $notes);\r
+       }\r
+\r
+       // display backup file info after remove permission step\r
+       if ($row["remove_permission_files"] == "")\r
+       {\r
+               $msg->printFeedbacks('PATCH_INSTALLED_SUCCESSFULLY');\r
+               \r
+               if ($row["backup_files"]<> "")\r
+               {\r
+                       $backup_files = get_array_by_delimiter($row["backup_files"], "|");\r
+       \r
+                       if (count($backup_files) > 0)\r
+                       {\r
+                               $feedbacks[] = _AT('patcher_show_backup_files');\r
+                               \r
+                               foreach($backup_files as $backup_file)\r
+                                       if ($backup_file <> "") $feedbacks[count($feedbacks)-1] .= "<strong>" . $backup_file . "</strong><br>";\r
+                       }\r
+               }\r
+\r
+               if ($row["patch_files"]<> "")\r
+               {\r
+                       $patch_files = get_array_by_delimiter($row["patch_files"], "|");\r
+       \r
+                       if (count($patch_files) > 0)\r
+                       {\r
+                               $feedbacks[] = _AT('patcher_show_patch_files');\r
+                               \r
+                               foreach($patch_files as $patch_file)\r
+                                       if ($patch_file <> "") $feedbacks[count($feedbacks)-1] .= "<strong>" . $patch_file . "</strong><br>";\r
+                                       \r
+                       }\r
+               }\r
+               \r
+               if (count($feedbacks)> 0)\r
+                       print_feedback($feedbacks);\r
+               else\r
+                       print_feedback(array());\r
+       }\r
+}\r
+\r
+$msg->printErrors();\r
+\r
+?>\r
+\r
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">\r
+<div class="input-form">\r
+\r
+<?php \r
+?>\r
+<table class="data" summary="" style="width: 100%" rules="cols">\r
+<thead>\r
+       <tr>\r
+               <th scope="col">&nbsp;</th>\r
+               <th scope="col"><?php echo _AT('atutor_patch_id');?></th>\r
+               <th scope="col"><?php echo _AT('description');?></th>\r
+               <th scope="col"><?php echo _AT('status');?></th>\r
+               <th scope="col"><?php echo _AT('available_to');?></th>\r
+               <th scope="col"><?php echo _AT('view_message');?></th>\r
+       </tr>\r
+</thead>\r
+       \r
+<tbody>\r
+<?php \r
+// display installed patches\r
+$sql = "select * from ".TABLE_PREFIX."patches " .\r
+       "where applied_version = '" . VERSION . "' ".\r
+       "order by atutor_patch_id";\r
+\r
+$result = mysql_query($sql, $db);\r
+$num_of_patches = mysql_num_rows($result) + count($patch_list_array);\r
+\r
+if ($num_of_patches == 0)\r
+{\r
+?>\r
+\r
+<tr>\r
+       <td colspan="7">\r
+<?php \r
+       echo _AT('none_found');\r
+?>\r
+       </td>\r
+</tr>\r
+\r
+<?php \r
+}\r
+else\r
+{\r
+       while ($row = mysql_fetch_assoc($result))\r
+       {\r
+                       print_patch_row($row, $row['patches_id'], false);\r
+       }\r
+       \r
+       $array_id = 0;\r
+       // display un-installed patches\r
+       if(is_array($patch_list_array))\r
+       {\r
+               foreach ($patch_list_array as $row_num => $new_patch)\r
+               {\r
+                       if (!is_patch_installed($new_patch['atutor_patch_id']))\r
+                       {\r
+                               $dependent_patches_installed = true;\r
+                       \r
+                               // check if the dependent patches are installed\r
+                               if (is_array($new_patch["dependent_patches"]))\r
+                               {\r
+                                       $dependent_patches = "";\r
+                                       foreach ($new_patch["dependent_patches"] as $num => $dependent_patch)\r
+                                       {\r
+                                               if (!is_patch_installed($dependent_patch))\r
+                                               {\r
+                                                       $dependent_patches_installed = false;\r
+                                                       $dependent_patches .= $dependent_patch. ", ";\r
+                                               }\r
+                                       }\r
+                                       \r
+                                       // remove the last comma in the string\r
+                                       if ($dependent_patches <> "") $dependent_patches = substr($dependent_patches, 0, -2);\r
+                               }\r
+       \r
+                               // display patch row\r
+                               if ($dependent_patches_installed)\r
+                                       print_patch_row($new_patch, $array_id++, true);\r
+                               else\r
+                               {\r
+                                       print_patch_row($new_patch, $array_id++, false);\r
+                                       $dependent_patches_installed = true;\r
+                               }\r
+                       }\r
+                       else\r
+                               $array_id++;\r
+               }\r
+       }\r
+\r
+?>\r
+</tbody>\r
+<tfoot>\r
+<tr>\r
+       <td colspan="7">\r
+               <input type="submit" name="install" value="<?php echo _AT('install'); ?>" />\r
+       </td>\r
+</tr>\r
+</tfoot>\r
+\r
+<?php \r
+}\r
+?>\r
+</table>\r
+\r
+</div>\r
+</form>\r
+\r
+<FORM NAME="frm_upload" ENCTYPE="multipart/form-data" METHOD=POST ACTION="<?php echo $_SERVER['PHP_SELF']; ?>" >\r
+       \r
+<div class="input-form">\r
+               <div class="row"><?php echo _AT("upload_patch"); ?></div>\r
+\r
+               <div class="row">\r
+                       <INPUT TYPE="hidden" name="MAX_FILE_SIZE" VALUE="52428800">\r
+                       <INPUT TYPE="file" NAME="patchfile"  SIZE=50>\r
+               </div>\r
+               \r
+               <div class="row buttons">\r
+                       <INPUT TYPE="submit" name="install_upload" value="Install" onClick="javascript: return validate_filename(); " class="submit" />\r
+                       <INPUT TYPE="hidden" name="uploading" value="1">\r
+               </div>\r
+</div>\r
+\r
+</form>\r
+\r
+<SCRIPT LANGUAGE="JavaScript">\r
+<!--\r
+\r
+String.prototype.trim = function() {\r
+       return this.replace(/^\s+|\s+$/g,"");\r
+}\r
+\r
+// This function validates if and only if a zip file is given\r
+function validate_filename() {\r
+  // check file type\r
+  var file = document.frm_upload.patchfile.value;\r
+  if (!file || file.trim()=='') {\r
+    alert('Please give a zip file!');\r
+    return false;\r
+  }\r
+  \r
+  if(file.slice(file.lastIndexOf(".")).toLowerCase() != '.zip') {\r
+    alert('Please upload ZIP file only!');\r
+    return false;\r
+  }\r
+}\r
+\r
+//  End -->\r
+//-->\r
+</script>\r
+\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>\r
diff --git a/mods/_standard/patcher/module.css b/mods/_standard/patcher/module.css
new file mode 100644 (file)
index 0000000..15da013
--- /dev/null
@@ -0,0 +1,11 @@
+div#helloworld {\r
+       border: 1px solid #ccc;\r
+       padding: 10px;\r
+       width: 50%;\r
+       margin-right: auto;\r
+       margin-left: auto;\r
+       background-color: #efefef;\r
+       color: #444;\r
+       margin-top: 30px;\r
+       margin-bottom: 30px;\r
+}
\ No newline at end of file
diff --git a/mods/_standard/patcher/module.php b/mods/_standard/patcher/module.php
new file mode 100644 (file)
index 0000000..90570e0
--- /dev/null
@@ -0,0 +1,43 @@
+<?php\r
+/*******\r
+ * doesn't allow this file to be loaded with a browser.\r
+ */\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+/******\r
+ * this file must only be included within a Module obj\r
+ */\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+/*******\r
+ * assign the instructor and admin privileges to the constants.\r
+ */\r
+define('AT_PRIV_PATCHER',       $this->getPrivilege());\r
+define('AT_ADMIN_PRIV_PATCHER', $this->getAdminPrivilege());\r
+\r
+/*******\r
+ * add the admin pages when needed.\r
+ */\r
+if (admin_authenticate(AT_ADMIN_PRIV_PATCHER, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+       $this->_pages[AT_NAV_ADMIN] = array('mods/_standard/patcher/index_admin.php');\r
+       $this->_pages['mods/_standard/patcher/index_admin.php']['title_var'] = 'patcher';\r
+       $this->_pages['mods/_standard/patcher/index_admin.php']['parent']    = AT_NAV_ADMIN;\r
+\r
+       $this->_pages['mods/_standard/patcher/index_admin.php']['children'] = array('mods/_standard/patcher/myown_patches.php','mods/_standard/patcher/patch_create.php');\r
+       $this->_pages['mods/_standard/patcher/myown_patches.php']['title_var'] = 'myown_patches';\r
+       $this->_pages['mods/_standard/patcher/myown_patches.php']['parent']   = 'mods/_standard/patcher/index_admin.php';\r
+\r
+       $this->_pages['mods/_standard/patcher/myown_patches.php']['children'] = array('mods/_standard/patcher/patch_create.php');\r
+       $this->_pages['mods/_standard/patcher/patch_create.php']['title_var'] = 'create_patch';\r
+       $this->_pages['mods/_standard/patcher/patch_create.php']['parent']   = 'mods/_standard/patcher/myown_patches.php';\r
+\r
+       $this->_pages['mods/_standard/patcher/patch_edit.php']['title_var'] = 'edit_patch';\r
+       $this->_pages['mods/_standard/patcher/patch_edit.php']['parent']   = 'mods/_standard/patcher/myown_patches.php';\r
+\r
+       $this->_pages['mods/_standard/patcher/patch_delete.php']['title_var'] = 'delete_patch';\r
+       $this->_pages['mods/_standard/patcher/patch_delete.php']['parent']   = 'mods/_standard/patcher/myown_patches.php';\r
+}\r
+$this->_pages['mods/_standard/patcher/index_admin.php']['guide']     = '../documentation/admin/?p=patcher.php';\r
+$this->_pages['mods/_standard/patcher/patch_create.php']['guide']     = '../documentation/admin/?p=create_patches.php';\r
+\r
+?>\r
diff --git a/mods/_standard/patcher/module.sql b/mods/_standard/patcher/module.sql
new file mode 100644 (file)
index 0000000..914c259
--- /dev/null
@@ -0,0 +1,146 @@
+# --------------------------------------------------------\r
+# Table structure for table `patches`\r
+# since 1.6.1\r
+\r
+CREATE TABLE `patches` (\r
+       `patches_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,\r
+       `atutor_patch_id` VARCHAR(20) NOT NULL default '',\r
+       `applied_version` VARCHAR(10) NOT NULL default '',\r
+       `patch_folder` VARCHAR(250) NOT NULL default '',\r
+  `description` TEXT NOT NULL,\r
+       `available_to` VARCHAR(250) NOT NULL default '',\r
+  `sql_statement` text NOT NULL,\r
+  `status` varchar(20) NOT NULL default '',\r
+  `remove_permission_files` text NOT NULL,\r
+  `backup_files` text NOT NULL,\r
+  `patch_files` text NOT NULL,\r
+       PRIMARY KEY  (`patches_id`)\r
+);\r
+\r
+\r
+# --------------------------------------------------------\r
+# Table structure for table `patches_files`\r
+# since 1.6.1\r
+\r
+CREATE TABLE `patches_files` (\r
+       `patches_files_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,\r
+       `patches_id` MEDIUMINT UNSIGNED NOT NULL default 0,\r
+       `action` VARCHAR(20) NOT NULL default '',\r
+       `name` TEXT NOT NULL,\r
+       `location` VARCHAR(250) NOT NULL default '',\r
+       PRIMARY KEY  (`patches_files_id`)\r
+);\r
+\r
+# --------------------------------------------------------\r
+# Table structure for table `patches_files_actions`\r
+# since 1.6.1\r
+\r
+CREATE TABLE `patches_files_actions` (\r
+       `patches_files_actions_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,\r
+       `patches_files_id` MEDIUMINT UNSIGNED NOT NULL default 0,\r
+       `action` VARCHAR(20) NOT NULL default '',\r
+       `code_from` TEXT NOT NULL,\r
+       `code_to` TEXT NOT NULL,\r
+       PRIMARY KEY  (`patches_files_actions_id`)\r
+);\r
+\r
+# --------------------------------------------------------\r
+# New records for table `language_text`\r
+# since 1.6.1\r
+\r
+INSERT INTO `language_text` VALUES ('en', '_module','patcher','Patcher',NOW(),'');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'get_my_patch', 'Get My Patch', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'atutor_patch_id', 'ATutor Patch ID', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'available_to', 'Available To', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'available_patches', 'Available Patches', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'available_patches_text', 'There are <strong>%s</strong> patches available to install.', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'version_not_match', 'This patch is for ATutor version %s. Does not match with your current ATutor version. The installation of it may break ATutor. Are you sure you want to proceed?', now(), 'warning msg');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PATCH_ALREADY_INSTALLED', 'The selected patch is already installed.', now(), 'error msg');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_CHOOSE_UNINSTALLED_PATCH', 'Please choose an uninstalled patch.', now(), 'error msg');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PATCH_XML_NOT_FOUND', 'Patch XML file is not found.', now(), 'error msg');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_REMOVE_WRITE_PERMISSION', 'Please remove write permission from the listed files.', now(), 'error msg');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_CANNOT_UNZIP', 'Can NOT unzip the uploaded file.', now(), 'error msg');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PATCH_DEPENDENCY', 'Due to patch dependency, please install the listed patches before installing this patch: %s', now(), 'error msg');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_PATCH_INSTALLED_SUCCESSFULLY', 'The patch has been installed successfully.', now(), 'feedback msg');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_INFOS_PATCH_INSTALLED_AND_REMOVE_PERMISSION', 'The patch has been installed. Please remove write permission as instruction.', now(), 'info msg');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'patcher_overwrite_modified_files', \r
+'The listed files are modified locally. If you choose to proceed, the patch file will be copied to your local machine. \r
+You have to manually merge this file and your local copy.<br>', now(), 'patcher');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'patch_local_file_not_exist', \r
+'Cannot proceed. The listed files are not exist in your local machine. If you renamed them to your copy, in order to proceed, please rename back.<br>', now(), 'patcher');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'patcher_alter_modified_files', \r
+'The listed files are modified locally. If you choose to proceed, your local file will be modified. The original\r
+file will be backup before the modification. Please note that the modification on your customized code may break your customization.<br>', now(), 'patcher');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'grant_write_permission', \r
+'Please grant <strong>write</strong> permission to folders and files listed below:<p><strong>Note:</strong> To change permissions on Unix use <kbd>chmod a+rw</kbd> then the file name.</p>', now(), 'patcher');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'remove_write_permission', \r
+'<span style="color:red">Please <strong>REMOVE</strong> write permission on the listed folders and files for your security:</span><p><strong>Note:</strong> To remove permissions on Unix use <kbd>chmod 755</kbd> then the file name..</p>', now(), 'patcher');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'patcher_show_backup_files', \r
+'Below is the list of the backup files created by patch installation. After ensuring ATutor works properly with the patch, you may want to \r
+delete these files. If  ATutor does not work properly with the patch, you can always revert back to the old files by renaming the backup files \r
+to the original file names,  removing the [patch_id].old portion of the file name. <br>', now(), 'patcher');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'patcher_show_patch_files', \r
+'Below is the list of the patch files copied to your computer. \r
+Please manually merge the change between the patch files and your local copy. <br>', now(), 'patcher');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'patch_dependent_patch_not_installed', \r
+'<br><span style="color: red">Waring: Due to patch dependency, please install the listed patches first: </span>', now(), 'patcher');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'upload_patch', \r
+'Upload a zip file to install patch:', now(), 'patcher');\r
+\r
+# --------------------------------------------------------\r
+# New tables for patch creator\r
+# since 1.6.1\r
+CREATE TABLE `myown_patches` (\r
+       `myown_patch_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,\r
+       `atutor_patch_id` VARCHAR(20) NOT NULL default '',\r
+       `applied_version` VARCHAR(10) NOT NULL default '',\r
+  `description` TEXT NOT NULL,\r
+  `sql_statement` text NOT NULL,\r
+  `status` varchar(20) NOT NULL default '',\r
+  `last_modified` datetime NOT NULL,\r
+       PRIMARY KEY  (`myown_patch_id`)\r
+);\r
+\r
+CREATE TABLE `myown_patches_dependent` (\r
+       `myown_patches_dependent_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,\r
+       `myown_patch_id` MEDIUMINT UNSIGNED NOT NULL,\r
+       `dependent_patch_id` VARCHAR(50) NOT NULL default '',\r
+       PRIMARY KEY  (`myown_patches_dependent_id`)\r
+);\r
+\r
+CREATE TABLE `myown_patches_files` (\r
+       `myown_patches_files_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,\r
+       `myown_patch_id` MEDIUMINT UNSIGNED NOT NULL,\r
+       `action` VARCHAR(20) NOT NULL default '',\r
+       `name` VARCHAR(250) NOT NULL,\r
+       `location` VARCHAR(250) NOT NULL default '',\r
+       `code_from` TEXT NOT NULL,\r
+       `code_to` TEXT NOT NULL,\r
+       `uploaded_file` TEXT NOT NULL,\r
+       PRIMARY KEY  (`myown_patches_files_id`)\r
+);\r
+\r
+# --------------------------------------------------------\r
+# New records for table `language_text` (for patch creator)\r
+# since 1.6.1\r
+\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'myown_patches', 'My Own Patches', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'atutor_patch_id', 'ATutor Patch ID', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'atutor_version_to_apply', 'ATutor Version to Apply', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'dependent_patches', 'Dependent Patches', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'dependent_patch_id', 'Dependent Patch ID', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'add_dependent_patch', 'Add A Dependent Patch', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'sql_statement', 'SQL Statement', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'relative_directory', 'Directory is relative directory to ATutor root, for example: docs/images/ or tools/tests/. Leave empty if it is ATutor root directory.', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'create_patch', 'Create Patch', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'edit_patch', 'Edit Patch', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'delete_patch', 'Delete Patch', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'add_a_file', 'Add A File', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'delete_this_file', 'Delete This File', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'replace_file', 'Replace File', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'alter', 'Alter', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'code_to_replace_from', 'Code To Replace From', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_template', 'code_to_replace_to', 'Code To Replace To', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_CHOOSE_ACTION', 'Please choose action for file <strong>%s</strong>', now(), '');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_PATCH_CREATED_SUCCESSFULLY', 'The patch has been created successfully.', now(), 'feedback msg');\r
+INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_CONFIRM_DELETE_MYOWN_PATCH', 'Are you sure you want to <strong>delete</strong> patch <strong>%s</strong>', now(), '');\r
diff --git a/mods/_standard/patcher/module.xml b/mods/_standard/patcher/module.xml
new file mode 100644 (file)
index 0000000..45afb60
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Patcher</name> \r
+    <description lang="en">This module is used by the ATutor administrator to apply patches, either uploaded locally, or imported from update.atutor.ca. Please refer to README for detail usage.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>BSD</license> \r
+       <release> \r
+        <version>0.1</version> \r
+        <date>2008-02-08</date> \r
+        <state>stable</state> \r
+        <notes></notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/patcher/module_install.php b/mods/_standard/patcher/module_install.php
new file mode 100644 (file)
index 0000000..f517c42
--- /dev/null
@@ -0,0 +1,67 @@
+<?php\r
+/*******\r
+ * the line below safe-guards this file from being accessed directly from\r
+ * a web browser. It will only execute if required from within an ATutor script,\r
+ * in our case the Module::install() method.\r
+ */\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+/*******\r
+ * Note: the many options for these variables are used to decrease confusion.\r
+ *       TRUE | FALSE | 1 will be the convention.\r
+ *\r
+ * $_course_privilege\r
+ *     specifies the type of instructor privilege this module uses.\r
+ *     set to empty | FALSE | 0   to disable any privileges.\r
+ *     set to 1 | AT_PRIV_ADMIN   to use the instructor only privilege.\r
+ *     set to TRUE | 'new'        to create a privilege specifically for this module:\r
+ *                                will make this module available as a student privilege.\r
+ *\r
+ * $_admin_privilege\r
+ *    specifies the type of ATutor administrator privilege this module uses.\r
+ *    set to FALSE | AT_ADMIN_PRIV_ADMIN   to use the super administrator only privilege.\r
+ *    set to TRUE | 'new'                  to create a privilege specifically for this module:\r
+ *                                         will make this module available as an administrator privilege.\r
+ *\r
+ *\r
+ * $_cron_interval\r
+ *    if non-zero specifies in minutes how often the module's cron job should be run.\r
+ *    set to 0 or not set to disable.\r
+ */\r
+$_course_privilege = TRUE; // possible values: FALSE | AT_PRIV_ADMIN | TRUE\r
+$_admin_privilege  = TRUE; // possible values: FALSE | TRUE\r
+//$_cron_interval    = 35; // run every 30 minutes\r
+\r
+\r
+/********\r
+ * the following code is used for creating a module-specific directory.\r
+ * it generates appropriate error messages to aid in its creation.\r
+ */\r
+$directory = AT_CONTENT_DIR .'patcher';\r
+\r
+// check if the directory is writeable\r
+if (!is_dir($directory) && !@mkdir($directory)) {\r
+       $msg->addError(array('MODULE_INSTALL', '<li>'.$directory.' does not exist. Please create it.</li>'));\r
+} else if (!is_writable($directory) && @chmod($directory, 0666)) {\r
+       $msg->addError(array('MODULE_INSTALL', '<li>'.$directory.' is not writeable. On Unix issue the command <kbd>chmod a+rw</kbd>.</li>'));\r
+}\r
+\r
+\r
+/******\r
+ * the following code checks if there are any errors (generated previously)\r
+ * then uses the SqlUtility to run any database queries it needs, ie. to create\r
+ * its own tables.\r
+ */\r
+if (!$msg->containsErrors() && file_exists(dirname(__FILE__) . '/module.sql')) {\r
+       // deal with the SQL file:\r
+       require(AT_INCLUDE_PATH . 'classes/sqlutility.class.php');\r
+       $sqlUtility =& new SqlUtility();\r
+\r
+       /*\r
+        * the SQL file could be stored anywhere, and named anything, "module.sql" is simply\r
+        * a convention we're using.\r
+        */\r
+       $sqlUtility->queryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/patcher/myown_patches.php b/mods/_standard/patcher/myown_patches.php
new file mode 100644 (file)
index 0000000..c031496
--- /dev/null
@@ -0,0 +1,99 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id: myown_patches.php 7208 2008-02-20 16:07:24Z cindy $\r
+\r
+define('AT_INCLUDE_PATH', '../../../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_PATCHER);\r
+\r
+if (isset($_POST['remove'], $_POST['myown_patch_id'])) \r
+{\r
+       header('Location: patch_delete.php?myown_patch_id='.$_POST['myown_patch_id']);\r
+       exit;\r
+} \r
+else if (isset($_POST['edit'], $_POST['myown_patch_id'])) \r
+{\r
+       header('Location: patch_edit.php?myown_patch_id='.$_POST['myown_patch_id']);\r
+       exit;\r
+} \r
+else if (!empty($_POST) && !isset($_POST['myown_patch_id'])) {\r
+       $msg->addError('NO_ITEM_SELECTED');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+\r
+?>\r
+<form name="form" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<table summary="" class="data" rules="cols" align="center" style="width: 70%;">\r
+\r
+<thead>\r
+<tr>\r
+       <th scope="col">&nbsp;</th>\r
+       <th scope="col"><?php echo _AT('atutor_patch_id'); ?></th>\r
+       <th scope="col"><?php echo _AT('atutor_version_to_apply'); ?></th>\r
+       <th scope="col"><?php echo _AT('description'); ?></th>\r
+       <th scope="col"><?php echo _AT('last_modified'); ?></th>\r
+</tr>\r
+</thead>\r
+<tfoot>\r
+<tr>\r
+       <td colspan="5">\r
+               <div class="row buttons">\r
+               <input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> \r
+               <input type="submit" name="remove" value="<?php echo _AT('remove'); ?>" /> \r
+               </div>\r
+       </td>\r
+</tr>\r
+<tr>\r
+       <td colspan="5"></td>\r
+</tr>\r
+</tfoot>\r
+<tbody>\r
+<?php\r
+$include_javascript = true;\r
+\r
+$sql = "SELECT * from ".TABLE_PREFIX."myown_patches m order by last_modified desc";\r
+\r
+$result = mysql_query($sql, $db) or die(mysql_error());\r
+\r
+if (mysql_num_rows($result) == 0)\r
+{\r
+?>\r
+       <tr>\r
+               <td colspan="5"><?php echo _AT('none_found'); ?></td>\r
+       </tr>\r
+<?php \r
+}\r
+else\r
+{\r
+       while ($row = mysql_fetch_assoc($result))\r
+       {\r
+       ?>\r
+               <tr onmousedown="document.form['m<?php echo $row['myown_patch_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $row['myown_patch_id']; ?>">\r
+                       <td width="10"><input type="radio" name="myown_patch_id" value="<?php echo $row['myown_patch_id']; ?>" id="m<?php echo $row['myown_patch_id']; ?>" <?php if ($row['myown_patch_id']==$_POST['myown_patch_id']) echo 'checked'; ?> /></td>\r
+                       <td><label for="m<?php echo $row['myown_patch_id']; ?>"><?php echo $row['atutor_patch_id']; ?></label></td>\r
+                       <td><?php echo $row['applied_version']; ?></td>\r
+                       <td><?php echo $row['description']; ?></td>\r
+                       <td><?php echo $row['last_modified']; ?></td>\r
+               </tr>\r
+<?php \r
+       }\r
+}\r
+?>\r
+\r
+</tbody>\r
+</table>\r
+\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>\r
diff --git a/mods/_standard/patcher/patch_create.php b/mods/_standard/patcher/patch_create.php
new file mode 100644 (file)
index 0000000..f82a9b3
--- /dev/null
@@ -0,0 +1,23 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id: index_admin.php 7208 2008-03-13 16:07:24Z cindy $\r
+\r
+define('AT_INCLUDE_PATH', '../../../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_PATCHER);\r
+\r
+// URL called by form action\r
+$url = dirname($_SERVER['PHP_SELF']) . "/patch_creator.php";\r
+\r
+require ('patch_edit_interface.tmpl.php');\r
+?>\r
diff --git a/mods/_standard/patcher/patch_creator.php b/mods/_standard/patcher/patch_creator.php
new file mode 100644 (file)
index 0000000..2d0ac9d
--- /dev/null
@@ -0,0 +1,134 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id: index_admin.php 7208 2008-03-13 16:07:24Z cindy $\r
+\r
+define('AT_INCLUDE_PATH', '../../../include/');\r
+require_once (AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_PATCHER);\r
+\r
+if ($_POST['create'] || $_POST['save'])\r
+{\r
+       if (isset($_REQUEST["myown_patch_id"])) $patch_id = $_REQUEST["myown_patch_id"];\r
+       else $patch_id = 0;\r
+       \r
+       // check missing fields\r
+       if (!isset($_POST["atutor_patch_id"]) || trim($_POST["atutor_patch_id"]) == "")\r
+               $missing_fields[] = _AT("atutor_patch_id");\r
+\r
+       if (!isset($_POST["atutor_version_to_apply"]) || trim($_POST["atutor_version_to_apply"]) == "")\r
+               $missing_fields[] = _AT("atutor_version_to_apply");\r
+\r
+       // only check missing upload file when creating a patch. don't check when save\r
+       if (is_array($_POST['rb_action']) && $_POST['create'])\r
+       {\r
+               foreach ($_POST['rb_action'] as $i=>$action)\r
+               {\r
+                       // must upload a file if action is add or overwrite\r
+                       if ($action == "add" && $_FILES['add_upload_file']['name'][$i] == "" && $_POST['add_uploaded_file'] == "")\r
+                               $missing_fields[] = _AT("upload_file") . " for ". _AT("file_name") . " <strong>" . $_POST['add_filename'][$i] . "</strong>";\r
+       \r
+                       if ($action == "overwrite" && $_FILES['overwrite_upload_file']['name'][$i] == "" && $_POST['overwrite_uploaded_file'] == "")\r
+                               $missing_fields[] = _AT("upload_file") . " for ". _AT("file_name") . " <strong>" . $_POST['overwrite_filename'][$i] . "</strong>";\r
+               }\r
+       }\r
+       // end of checking missing fields\r
+\r
+       if ($missing_fields) \r
+       {\r
+               $missing_fields = implode(', ', $missing_fields);\r
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));\r
+       }\r
+\r
+       if (!(eregi("^[a-zA-Z0-9_.-]([a-zA-Z0-9_.-])*$", $_POST['atutor_patch_id'])))\r
+               $msg->addError('LOGIN_CHARS');\r
+\r
+       // main process\r
+       if (!$msg->containsErrors()) \r
+       {\r
+               $patch_info = array("atutor_patch_id"=>$_POST["atutor_patch_id"],\r
+                             "atutor_version_to_apply"=>$_POST["atutor_version_to_apply"],\r
+                             "description"=>$_POST["description"],\r
+                             "sql_statement"=>$_POST["sql_statement"]);\r
+\r
+               // remove empty dependent patches\r
+               if (is_array($_POST["dependent_patch"]))\r
+               {\r
+                       foreach ($_POST["dependent_patch"] as $dependent_patch)\r
+                               if (trim($dependent_patch) <> "")\r
+                                       $dependent_patches[] = $dependent_patch;\r
+               }\r
+               \r
+               if (is_array($dependent_patches))\r
+                       $patch_info["dependent_patches"] = $dependent_patches;\r
+                       \r
+               if (is_array($_POST['rb_action']))\r
+               {\r
+                       foreach ($_POST['rb_action'] as $i=>$action)\r
+                       {\r
+                               if ($action == "add" && $_POST['add_filename'][$i] <> "")\r
+                               {\r
+                                       if ($_FILES['add_upload_file']['tmp_name'][$i] <> "")\r
+                                               $upload_file = $_FILES['add_upload_file']['tmp_name'][$i];\r
+                                       else\r
+                                               $upload_file = $_POST['add_uploaded_file'][$i];\r
+                                       \r
+                                       $patch_info["files"][] = array("action"=>$action,\r
+                                                                    "file_name"=>$_POST['add_filename'][$i],\r
+                                                              "directory"=>$_POST['add_dir'][$i],\r
+                                                              "upload_tmp_name"=>$upload_file);\r
+                               }\r
+                               \r
+                               if ($action == "alter" && $_POST['alter_filename'][$i] <> "")\r
+                                       $patch_info["files"][] = array("action"=>$action,\r
+                                                                                      "file_name"=>$_POST['alter_filename'][$i],\r
+                                                              "directory"=>$_POST['alter_dir'][$i],\r
+                                                              "code_from"=>$_POST['alter_code_from'][$i],\r
+                                                              "code_to"=>$_POST['alter_code_to'][$i]);\r
+       \r
+                               if ($action == "delete" && $_POST['delete_filename'][$i] <> "")\r
+                                       $patch_info["files"][] = array("action"=>$action,\r
+                                                                    "file_name"=>$_POST['delete_filename'][$i],\r
+                                                              "directory"=>$_POST['delete_dir'][$i]);\r
+       \r
+                               if ($action == "overwrite" && $_POST['overwrite_filename'][$i] <> "")\r
+                               {\r
+                                       if ($_FILES['overwrite_upload_file']['tmp_name'][$i] <> "")\r
+                                               $upload_file = $_FILES['overwrite_upload_file']['tmp_name'][$i];\r
+                                       else\r
+                                               $upload_file = $_POST['overwrite_uploaded_file'][$i];\r
+                                       \r
+                                       $patch_info["files"][] = array("action"=>$action,\r
+                                                                    "file_name"=>$_POST['overwrite_filename'][$i],\r
+                                                              "directory"=>$_POST['overwrite_dir'][$i],\r
+                                                              "upload_tmp_name"=>$upload_file);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               require_once("classes/PatchCreator.class.php");\r
+               \r
+               $patch_creator =& new PatchCreator($patch_info, $patch_id);\r
+               \r
+               if ($_POST['create'])\r
+                       $patch_creator->create_patch();\r
+               else if ($_POST['save'])\r
+               {\r
+                       $patch_creator->saveInfo();\r
+                       header('Location: myown_patches.php');\r
+               }\r
+\r
+       }\r
+}\r
+\r
+$msg->printErrors();\r
+?>\r
diff --git a/mods/_standard/patcher/patch_delete.php b/mods/_standard/patcher/patch_delete.php
new file mode 100644 (file)
index 0000000..bc05818
--- /dev/null
@@ -0,0 +1,71 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id: certificate_delete.php 7208 2008-02-20 16:07:24Z cindy $\r
+\r
+define('AT_INCLUDE_PATH', '../../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_PATCHER);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: myown_patches.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       /* delete has been confirmed, delete this category */\r
+       $myown_patch_id = intval($_POST['myown_patch_id']);\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."myown_patches WHERE myown_patch_id=$myown_patch_id";\r
+       $result = mysql_query($sql, $db) or die(mysql_error());\r
+\r
+       write_to_log(AT_ADMIN_LOG_DELETE, 'myown_patches', mysql_affected_rows($db), $sql);\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."myown_patches_dependent WHERE myown_patch_id=$myown_patch_id";\r
+       $result = mysql_query($sql, $db) or die(mysql_error());\r
+\r
+       write_to_log(AT_ADMIN_LOG_DELETE, 'myown_patches_dependent', mysql_affected_rows($db), $sql);\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."myown_patches_files WHERE myown_patch_id=$myown_patch_id";\r
+       $result = mysql_query($sql, $db) or die(mysql_error());\r
+\r
+       write_to_log(AT_ADMIN_LOG_DELETE, 'myown_patches_files', mysql_affected_rows($db), $sql);\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: myown_patches.php');\r
+       exit;\r
+}\r
+\r
+//require('../../include/header.inc.php');\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$_GET['myown_patch_id'] = intval($_GET['myown_patch_id']); \r
+\r
+$sql = "SELECT myown_patch_id, atutor_patch_id FROM ".TABLE_PREFIX."myown_patches m WHERE m.myown_patch_id=$_GET[myown_patch_id]";\r
+$result = mysql_query($sql,$db) or die(mysql_error());\r
+\r
+if (mysql_num_rows($result) == 0) {\r
+       $msg->printErrors('ITEM_NOT_FOUND');\r
+} else {\r
+       $row = mysql_fetch_assoc($result);\r
+       \r
+       $hidden_vars['atutor_patch_id']= $row['atutor_patch_id'];\r
+       $hidden_vars['myown_patch_id']  = $row['myown_patch_id'];\r
+\r
+       $confirm = array('DELETE_MYOWN_PATCH', $row['atutor_patch_id']);\r
+       $msg->addConfirm($confirm, $hidden_vars);\r
+       \r
+       $msg->printConfirm();\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/patcher/patch_edit.php b/mods/_standard/patcher/patch_edit.php
new file mode 100644 (file)
index 0000000..d62eefe
--- /dev/null
@@ -0,0 +1,42 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id: index_admin.php 7208 2008-03-13 16:07:24Z cindy $\r
+\r
+define('AT_INCLUDE_PATH', '../../../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_PATCHER);\r
\r
+if (!isset($_REQUEST["myown_patch_id"]))\r
+{\r
+       $msg->addError('NO_ITEM_SELECTED');\r
+       exit;\r
+}\r
+\r
+$myown_patch_id = $_REQUEST["myown_patch_id"];\r
+\r
+// URL called by form action\r
+$url = dirname($_SERVER['PHP_SELF']) . "/patch_creator.php?myown_patch_id=" . $myown_patch_id;\r
+\r
+$sql_patches = "SELECT * from ".TABLE_PREFIX."myown_patches m where myown_patch_id=". $myown_patch_id;\r
+$result_patches = mysql_query($sql_patches, $db) or die(mysql_error());\r
+$row_patches = mysql_fetch_assoc($result_patches);\r
+\r
+$sql_patch_dependent = "SELECT * from ".TABLE_PREFIX."myown_patches_dependent m where myown_patch_id=". $myown_patch_id;\r
+$result_patch_dependent = mysql_query($sql_patch_dependent, $db) or die(mysql_error());\r
+\r
+$sql_patch_files = "SELECT * from ".TABLE_PREFIX."myown_patches_files m where myown_patch_id=". $myown_patch_id . " order by myown_patches_files_id";\r
+$result_patch_files = mysql_query($sql_patch_files, $db) or die(mysql_error());\r
+\r
+require ('patch_edit_interface.tmpl.php');\r
+\r
+?>\r
diff --git a/mods/_standard/patcher/patch_edit_interface.tmpl.php b/mods/_standard/patcher/patch_edit_interface.tmpl.php
new file mode 100644 (file)
index 0000000..c090d33
--- /dev/null
@@ -0,0 +1,349 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id: patch_edit_interface.tmpl.php 7208 2008-03-13 16:07:24Z cindy $\r
+\r
+require ('include/json.inc.php');\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+?>\r
+\r
+<form enctype="multipart/form-data" action='<?php echo $url; ?>' method="post" name="form" target="messageIFrame">\r
+\r
+<div class="input-form">\r
+\r
+<iframe id="messageIFrame" name="messageIFrame" src='' style='width:1px;height:1px;border:0' onload="show_message()"></iframe>\r
+<div id="messageDIV"></div>\r
+       \r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="atutor_patch_id"><?php echo _AT('atutor_patch_id'); ?></label><br />\r
+               <small>&middot; <?php echo _AT('contain_only'); ?></small><br />\r
+               <input id="atutor_patch_id" name="atutor_patch_id" type="text" maxlength="100" size="30" value="<?php echo $row_patches['atutor_patch_id']; ?>" /><br />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="atutor_version_to_apply"><?php echo _AT('atutor_version_to_apply'); ?></label><br />\r
+               <input id="atutor_version_to_apply" name="atutor_version_to_apply" type="text" maxlength="100" size="30" value="<?php echo $row_patches['applied_version']; ?>" /><br />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <label for="description"><?php echo _AT('description'); ?></label><br />\r
+               <textarea id="description" name="description" cols="40" rows="4"><?php echo $row_patches['description']; ?></textarea><br />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <label for="sql_statement"><?php echo _AT('sql_statement'); ?></label><br />\r
+               <textarea id="sql_statement" name="sql_statement" cols="40" rows="8"><?php echo $row_patches['sql_statement']; ?></textarea><br />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <label for="dependent_patches"><?php echo _AT('dependent_patches'); ?></label><br />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <table id="dependent_patches" class="data" rules="cols" align="left" style="width: 50%;">\r
+               <thead>\r
+               <tr>\r
+                       <th scope="col"><?php echo _AT('dependent_patch_id'); ?></th>\r
+               </tr>\r
+               </thead>\r
+\r
+               <tbody>\r
+<?php\r
+// when edit existing patch\r
+if ($result_patch_dependent)  \r
+{\r
+       $num_of_dependents = mysql_num_rows($result_patch_dependent);\r
+       while ($row_patch_dependent = mysql_fetch_assoc($result_patch_dependent))\r
+       {\r
+       ?>\r
+                       <tr>\r
+                               <td><input id="dependent_patch" name="dependent_patch[]" value="<?php echo $row_patch_dependent['dependent_patch_id']; ?>" type="text" maxlength="100" size="100" style="max-width:100%; display:block" /></td>\r
+                       </tr>\r
+       <?php\r
+       }\r
+}\r
+\r
+// when creating new patch\r
+if ($num_of_dependents == 0)\r
+{\r
+?>\r
+               <tr>\r
+                       <td><input id="dependent_patch" name="dependent_patch[]" type="text" maxlength="100" size="100" style="max-width:100%; display:block" /></td>\r
+               </tr>\r
+               </tbody>\r
+<?php\r
+}\r
+?>\r
+       \r
+               <tfoot>\r
+               <tr>\r
+                       <td colspan="4">\r
+                               <div class="buttons"  style="float:left">\r
+                                       <input type="button" name="add_dependent_patch" value="<?php echo _AT('add_dependent_patch'); ?>" onclick="add_dependent()" />\r
+                               </div>\r
+                       </td>\r
+               </tr>\r
+               </tfoot>\r
+\r
+               </table>\r
+       </div>\r
+       \r
+       <br /><br /><br /><br /><br /><br />\r
+       <div class="row">\r
+               <label for="filesDiv"><?php echo _AT('files'); ?></label><br />\r
+               <small>&middot; <?php echo _AT('relative_directory'); ?></small>\r
+       </div>\r
+\r
+       <div id="filesDiv" class="row">\r
+       </div>\r
+\r
+       <div class="row buttons"  style="float:left">\r
+               <input type="button" name="add_a_file" value="<?php echo _AT('add_a_file'); ?>" onClick="add_file()" />\r
+       </div>\r
+       \r
+       <br /><br />\r
+       \r
+       <div class="row buttons">\r
+               <input type="submit" name="create" value=" <?php echo _AT('create_patch'); ?> " accesskey="c" />\r
+               <input type="submit" name="save" value=" <?php echo _AT('save'); ?> " accesskey="s" onClick="document.form.target=''; "/>\r
+               <input type="button" name="cancel" value=" <?php echo _AT('cancel'); ?> " onClick="location.href='mods/_standard/patcher/myown_patches.php'" />\r
+       </div>\r
+\r
+</div>\r
+</form>\r
+\r
+<script language="JavaScript" type="text/javascript">\r
+//<!--\r
+\r
+myescape = function(/*string*/ str) {\r
+    return str.replace(/(['"\.*+?^${}()|[\]\/\\])/g, "\\$1").replace(/\n/g, '\\n');\r
+}\r
+\r
+function show_message()\r
+{\r
+       var messageDIV = document.getElementById("messageDIV"); \r
+       var i = document.getElementById("messageIFrame"); \r
+       \r
+  if (i.contentDocument) {\r
+      var d = i.contentDocument;\r
+  } else if (i.contentWindow) {\r
+      var d = i.contentWindow.document;\r
+  } else {\r
+      var d = window.frames[id].document;\r
+  }    \r
+       messageDIV.innerHTML = d.body.innerHTML;\r
+}\r
+\r
+function add_dependent() {\r
+  var dependentPatchesTable = document.getElementById("dependent_patches").tBodies[0];\r
+  var dependentPatch = dependentPatchesTable.rows[dependentPatchesTable.rows.length - 1].cloneNode(true);\r
+  dependentPatchesTable.appendChild(dependentPatch);\r
+  dependentPatch.cells[0].firstChild.value='';\r
+  \r
+  var dependents = document.form["dependent_patch[]"];\r
+  dependents[dependents.length - 1].focus();\r
+    // document.form['dependent_patch['+ pos +']'].focus();\r
+}\r
+\r
+var num_of_files = 0;\r
+function add_file(filedata) {\r
+       var newDiv = document.createElement("div");\r
+       \r
+       newDiv.innerHTML = ACTION_HTML_TEMPLATE.replace(/\{1\}/g, num_of_files);\r
+       document.getElementById("filesDiv").appendChild(newDiv);\r
+       \r
+       document.form['rb_action[' +num_of_files +']'][0].focus();\r
+       \r
+       if(filedata) {\r
+               var srcElement = null;\r
+\r
+               if(filedata.action=="add") {\r
+                       // set focus on radio button "add"\r
+                       document.form['rb_action[' +num_of_files +']'][0].checked = true;\r
+                       document.form['rb_action[' +num_of_files +']'][0].focus();\r
+\r
+                       // set value\r
+                       srcElement = document.form['rb_action[' +num_of_files +']'][0];\r
+                       document.form['add_filename[' +num_of_files +']'].value = filedata.name;\r
+                       document.form['add_dir[' +num_of_files +']'].value = filedata.location;\r
+                       \r
+                       // set uploaded file\r
+                       if (filedata.uploaded_file != "")\r
+                       {\r
+                               document.form['add_uploaded_file[' +num_of_files +']'].value = filedata.uploaded_file;\r
+                               var tables = newDiv.getElementsByTagName('TABLE');\r
+                               tables[0].rows[2].style.display='';    // display the row of uploaded file\r
+                               tables[0].rows[2].cells[1].innerHTML=filedata.uploaded_file;    // display uploaded file name\r
+                               tables[0].rows[3].cells[0].innerHTML='<?php echo _AT("replace_file"); ?>';    // change label from "upload file" to "replace file"\r
+                       }\r
+                       \r
+                       // set uploaded file\r
+               } else if(filedata.action=="alter") {\r
+                       document.form['rb_action[' +num_of_files +']'][1].checked = true;\r
+                       document.form['rb_action[' +num_of_files +']'][1].focus();\r
+\r
+                       srcElement = document.form['rb_action[' +num_of_files +']'][1];\r
+                       document.form['alter_filename[' +num_of_files +']'].value = filedata.name;\r
+                       document.form['alter_dir[' +num_of_files +']'].value = filedata.location;\r
+                       document.form['alter_code_from[' +num_of_files +']'].value = filedata.code_from;\r
+                       document.form['alter_code_to[' +num_of_files +']'].value = filedata.code_to;\r
+               } else if(filedata.action=="delete") {\r
+                       document.form['rb_action[' +num_of_files +']'][2].checked = true;\r
+                       document.form['rb_action[' +num_of_files +']'][2].focus();\r
+\r
+                       srcElement = document.form['rb_action[' +num_of_files +']'][2];\r
+                       document.form['delete_filename[' +num_of_files +']'].value = filedata.name;\r
+                       document.form['delete_dir[' +num_of_files +']'].value = filedata.location;\r
+               } if(filedata.action=="overwrite") {\r
+                       document.form['rb_action[' +num_of_files +']'][3].checked = true;\r
+                       document.form['rb_action[' +num_of_files +']'][3].focus();\r
+\r
+                       srcElement = document.form['rb_action[' +num_of_files +']'][3];\r
+                       document.form['overwrite_filename[' +num_of_files +']'].value = filedata.name;\r
+                       document.form['overwrite_dir[' +num_of_files +']'].value = filedata.location;\r
+\r
+                       // set uploaded file\r
+                       if (filedata.uploaded_file != "")\r
+                       {\r
+                               document.form['overwrite_uploaded_file[' +num_of_files +']'].value = filedata.uploaded_file;\r
+                               var tables = newDiv.getElementsByTagName('TABLE');\r
+                               tables[3].rows[2].style.display='';    // display the row of uploaded file\r
+                               tables[3].rows[2].cells[1].innerHTML=filedata.uploaded_file;    // display uploaded file name\r
+                               tables[3].rows[3].cells[0].innerHTML='<?php echo _AT("replace_file"); ?>';    // change label from "upload file" to "replace file"\r
+                       }\r
+                       \r
+               }\r
+               \r
+               show_content({srcElement:srcElement});\r
+       }\r
+\r
+       num_of_files++;\r
+}\r
+\r
+function del_file(evt) {\r
+       var target =(evt.srcElement)?evt.srcElement:evt.currentTarget;\r
+       var div =  target.parentNode.parentNode ;\r
+       div.parentNode.removeChild(div);\r
+}\r
+\r
+function show_content(evt) {\r
+       var target =(evt.srcElement)?evt.srcElement:evt.currentTarget;\r
+       var tables = target.parentNode.parentNode.getElementsByTagName('TABLE');\r
+       tables[0].style.display='none';\r
+       tables[1].style.display='none';\r
+       tables[2].style.display='none';\r
+       tables[3].style.display='none';\r
+       if(target.value == 'add') tables[0].style.display='';\r
+       if(target.value == 'alter') tables[1].style.display='';\r
+       if(target.value == 'delete') tables[2].style.display='';\r
+       if(target.value == 'overwrite') tables[3].style.display='';\r
+}\r
+\r
+var ACTION_HTML_TEMPLATE = ' \\r
+<div style="border-width:thin; border-style:solid; padding: 5px 5px 5px 5px; margin:5px 5px 5px 5px"> \\r
+       <div style="float:left">Action:  \\r
+               <input type="radio" name="rb_action[{1}]" value="add" id="add" checked onclick="show_content(event);" /><label for="add"><?php echo _AT("add"); ?></label> \\r
+               <input type="radio" name="rb_action[{1}]" value="alter" id="alter" onclick="show_content(event);" /><label for="alter"><?php echo _AT("alter"); ?></label> \\r
+               <input type="radio" name="rb_action[{1}]" value="delete" id="delete" onclick="show_content(event);" /><label for="delete"><?php echo _AT("delete"); ?></label> \\r
+               <input type="radio" name="rb_action[{1}]" value="overwrite" id="overwrite" onclick="show_content(event);" /><label for="overwrite"><?php echo _AT("overwrite"); ?></label> \\r
+       </div> \\r
+       <br /><br /> \\r
+       <div> \\r
+       <table style="display:" width="100%"> \\r
+               <tr> \\r
+                       <td width="150px"><?php echo _AT("file_name"); ?></td> \\r
+                       <td><input name="add_filename[{1}]" type="text"  /></td> \\r
+               </tr> \\r
+               <tr> \\r
+                       <td><?php echo _AT("directory"); ?></td> \\r
+                       <td><input name="add_dir[{1}]" type="text"  /></td> \\r
+               </tr> \\r
+               <tr style="display: none"> \\r
+                       <td><?php echo _AT("file"); ?></td> \\r
+                       <td></td> \\r
+                       <td><INPUT TYPE="hidden" NAME="add_uploaded_file[{1}]" SIZE="40" style="max-width:100%" /></td> \\r
+               </tr> \\r
+               <tr> \\r
+                       <td><?php echo _AT("upload_file"); ?></td> \\r
+                       <td><INPUT TYPE="file" NAME="add_upload_file[{1}]" SIZE="40" style="max-width:100%" /></td> \\r
+               </tr> \\r
+       </table> \\r
+       <table style="display: none" width="100%"> \\r
+               <tr> \\r
+                       <td width="150px"><?php echo _AT("file_name"); ?></td> \\r
+                       <td><input name="alter_filename[{1}]" type="text" maxlength="100" size="100" /></td> \\r
+               </tr> \\r
+               <tr> \\r
+                       <td><?php echo _AT("directory"); ?></td> \\r
+                       <td><input name="alter_dir[{1}]" type="text" maxlength="100" size="100" style="max-width:100%" /></td> \\r
+               </tr> \\r
+               <tr> \\r
+                       <td><?php echo _AT("code_to_replace_from"); ?></td> \\r
+                       <td><textarea name="alter_code_from[{1}]" rows="5" cols="120" style="max-width:100%"></textarea></td> \\r
+               </tr> \\r
+               <tr> \\r
+                       <td><?php echo _AT("code_to_replace_to"); ?></td> \\r
+                       <td><textarea name="alter_code_to[{1}]" rows="5" cols="120" style="max-width:100%"></textarea></td> \\r
+               </tr> \\r
+       </table> \\r
+       <table style="display: none" width="100%"> \\r
+               <tr> \\r
+                       <td width="150px"><?php echo _AT("file_name"); ?></td> \\r
+                       <td><input name="delete_filename[{1}]" type="text" maxlength="100" size="100" /></td> \\r
+               </tr> \\r
+               <tr> \\r
+                       <td><?php echo _AT("directory"); ?></td> \\r
+                       <td><input name="delete_dir[{1}]" type="text" maxlength="100" size="100" /></td> \\r
+               </tr> \\r
+       </table> \\r
+       <table style="display: none" width="100%"> \\r
+               <tr> \\r
+                       <td width="150px"><?php echo _AT("file_name"); ?></td> \\r
+                       <td><input name="overwrite_filename[{1}]" type="text" /></td> \\r
+               </tr> \\r
+               <tr> \\r
+                       <td><?php echo _AT("directory"); ?></td> \\r
+                       <td><input name="overwrite_dir[{1}]" type="text" maxlength="100" size="100" /></td> \\r
+               </tr> \\r
+               <tr id="overwrite_uploaded_file" style="display:none"> \\r
+                       <td><?php echo _AT("file"); ?></td> \\r
+                       <td></td> \\r
+                       <td><INPUT type="hidden" NAME="overwrite_uploaded_file[{1}]" SIZE="40" style="max-width:100%" /></td> \\r
+               </tr> \\r
+               <tr> \\r
+                       <td><?php echo _AT("upload_file"); ?></td> \\r
+                       <td><INPUT TYPE="file" NAME="overwrite_upload_file[{1}]" SIZE="40" style="max-width:100%" /></td> \\r
+               </tr> \\r
+       </table> \\r
+       </div> \\r
+       <div class="row buttons" style="float:left"> \\r
+               <input type="button" value="<?php echo _AT("delete_this_file"); ?>" onClick="del_file(event)" /> \\r
+       </div> \\r
+       <br /><br /> \\r
+</div> \\r
+';\r
+\r
+//-->\r
+</script>\r
+\r
+\r
+<script language="JavaScript" type="text/javascript">\r
+       var patch_files = <?php echo json_encode_result($result_patch_files); ?>;\r
+       \r
+       window.onload = function() {\r
+               for(var i=0; i<patch_files.length; i++) {\r
+                       add_file(patch_files[i]);\r
+               }\r
+       }\r
+</script>\r
+       \r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>\r
diff --git a/mods/_standard/patcher/sample_patch.xml b/mods/_standard/patcher/sample_patch.xml
new file mode 100644 (file)
index 0000000..f2007ee
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<patch>\r
+       <atutor_patch_id>00001</atutor_patch_id>\r
+       <applied_version>1.6</applied_version>\r
+       <description>Sample patch XML</description>\r
+       <dependent_patches>\r
+               <dependent_patch>00002</dependent_patch>\r
+               <dependent_patch>00003</dependent_patch>\r
+       </dependent_patches>\r
+       \r
+       <sql>\r
+               ALTER TABLE `tests` ADD `description` TEXT NOT NULL AFTER `title`;\r
+       </sql>\r
+\r
+       <files>\r
+               <file>\r
+                       <action>alter</action>\r
+                       <name>create_test.php</name>\r
+                       <location>tools/tests/</location>\r
+                       <action_detail>\r
+                               <type>delete</type>\r
+                               <code_from></code_from>\r
+                       </action_detail>\r
+                               \r
+                       <action_detail>\r
+                               <type>replace</type>\r
+                               <code_from></code_from>\r
+                               <code_to></code_to>\r
+                       </action_detail>\r
+               </file>\r
+       \r
+               <file>\r
+                       <action>add</action>\r
+                       <name>calendar.gif</name>\r
+                       <location>docs/images/</location>\r
+               </file>\r
+\r
+               <file>\r
+                       <action>delete</action>\r
+                       <name>results_all_csv.php</name>\r
+                       <location>tools/tests/</location>\r
+               </file>\r
+\r
+               <file>\r
+                       <action>overwrite</action>\r
+                       <name>results_all.php</name>\r
+                       <location>tools/tests/</location>\r
+               </file>\r
+       </files>\r
+</patch> \r
diff --git a/mods/_standard/patcher/sample_patch_list.xml b/mods/_standard/patcher/sample_patch_list.xml
new file mode 100644 (file)
index 0000000..13de250
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<patch_list>\r
+       <patch>\r
+               <atutor_patch_id>00001</atutor_patch_id>\r
+               <applied_version>1.6</applied_version>\r
+               <patch_folder>1_6-1</patch_folder>\r
+               <description>Patch No. 1 for ATutor 1.6</description>\r
+               <available_to>public</available_to>\r
+               <dependent_patches></dependent_patches>\r
+       </patch>\r
+       \r
+       <patch>\r
+               <atutor_patch_id>00002</atutor_patch_id>\r
+               <applied_version>1.6</applied_version>\r
+               <patch_folder>1_6-2</patch_folder>\r
+               <description>Patch No. 2 for ATutor 1.6</description>\r
+               <available_to>public</available_to>\r
+               <dependent_patches>\r
+                       <dependent_patch>00001</dependent_patch>\r
+                       <dependent_patch>00003</dependent_patch>\r
+               </dependent_patches>\r
+       </patch>\r
+</patch_list> \r
diff --git a/mods/_standard/patcher/xml_special_chars.txt b/mods/_standard/patcher/xml_special_chars.txt
new file mode 100644 (file)
index 0000000..a720315
--- /dev/null
@@ -0,0 +1,5 @@
+&lt;   <       less than
+&gt;   >       greater than
+&amp;  &       ampersand 
+&apos;         '       apostrophe
+&quot;         "       quotation mark
\ No newline at end of file
diff --git a/mods/_standard/polls/module.php b/mods/_standard/polls/module.php
new file mode 100644 (file)
index 0000000..e5402d1
--- /dev/null
@@ -0,0 +1,31 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_PRIV_POLLS', $this->getPrivilege());\r
+\r
+//side dropdown\r
+$this->_stacks['poll'] = array('title_var'=>'poll','file'=>AT_INCLUDE_PATH.'html/dropdowns/poll.inc.php');\r
+\r
+// if this module is to be made available to students on the Home or Main Navigation\r
+$_student_tool = 'polls/index.php';\r
+\r
+$this->_pages['polls/index.php']['title_var'] = 'polls';\r
+$this->_pages['polls/index.php']['img']       = 'images/home-polls.gif';\r
+\r
+$this->_pages['tools/polls/index.php']['title_var'] = 'polls';\r
+$this->_pages['tools/polls/index.php']['parent']    = 'tools/index.php';\r
+$this->_pages['tools/polls/index.php']['children']  = array('tools/polls/add.php');\r
+$this->_pages['tools/polls/index.php']['guide']     = 'instructor/?p=polls.php';\r
+\r
+       $this->_pages['tools/polls/add.php']['title_var'] = 'add_poll';\r
+       $this->_pages['tools/polls/add.php']['parent']    = 'tools/polls/index.php';\r
+\r
+       $this->_pages['tools/polls/edit.php']['title_var'] = 'edit_poll';\r
+       $this->_pages['tools/polls/edit.php']['parent']    = 'tools/polls/index.php';\r
+\r
+       $this->_pages['tools/polls/delete.php']['title_var'] = 'delete_poll';\r
+       $this->_pages['tools/polls/delete.php']['parent']    = 'tools/polls/index.php';\r
+\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/polls/module.xml b/mods/_standard/polls/module.xml
new file mode 100644 (file)
index 0000000..88a4cee
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Polls</name> \r
+    <description lang="en">Polls are useful for quickly gathering course member opinions. Instructors and students with poll privileges can post a question with up to seven choices for answers.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege>create</instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-22</date> \r
+        <state>stable</state> \r
+        <notes>This is a standard module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/polls/module_backup.php b/mods/_standard/polls/module_backup.php
new file mode 100644 (file)
index 0000000..06d02fd
--- /dev/null
@@ -0,0 +1,32 @@
+<?php\r
+/* each table to be backed up. includes the sql entry and fields */\r
+\r
+$sql = array();\r
+$sql['polls'] = 'SELECT question, created_date, choice1, choice2, choice3, choice4, choice5, choice6, choice7 FROM '.TABLE_PREFIX.'polls WHERE course_id=?';\r
+\r
+function polls_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0]  = 0;\r
+       $new_row[1]  = $course_id;\r
+       $new_row[2]  = $row[0];\r
+       $new_row[3]  = $row[1];\r
+       $new_row[4]  = 0;\r
+       $new_row[5]  = $row[2];\r
+       $new_row[6]  = 0;\r
+       $new_row[7]  = $row[3];\r
+       $new_row[8]  = 0;\r
+       $new_row[9]  = $row[4];\r
+       $new_row[10] = 0;\r
+       $new_row[11] = $row[5];\r
+       $new_row[12] = 0;\r
+       $new_row[13] = $row[6];\r
+       $new_row[14] = 0;\r
+       $new_row[15] = $row[7];\r
+       $new_row[16] = 0;\r
+       $new_row[17] = $row[8];\r
+       $new_row[18] = 0;\r
+\r
+       return $new_row;\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/polls/module_delete.php b/mods/_standard/polls/module_delete.php
new file mode 100644 (file)
index 0000000..4bf4863
--- /dev/null
@@ -0,0 +1,19 @@
+<?php\r
+\r
+function polls_delete($course) {\r
+       global $db;\r
+\r
+       $sql    = "SELECT poll_id FROM ".TABLE_PREFIX."polls WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+       if (!$result || !mysql_num_rows($result)) {\r
+               return;\r
+       }\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               $sql     = "DELETE FROM ".TABLE_PREFIX."polls_members WHERE poll_id=$row[poll_id]";\r
+               mysql_query($sql, $db);\r
+       }\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."polls WHERE course_id=$course";\r
+       mysql_query($sql, $db);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/profile_pictures/module.php b/mods/_standard/profile_pictures/module.php
new file mode 100644 (file)
index 0000000..443f207
--- /dev/null
@@ -0,0 +1,14 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+$this->_pages['users/profile_picture.php']['title_var'] = 'picture';\r
+$this->_pages['users/profile_picture.php']['parent']   = 'users/profile.php';\r
+\r
+$this->_pages['users/profile.php']['children']  = array('users/profile_picture.php');\r
+\r
+if (admin_authenticate(AT_ADMIN_PRIV_USERS, TRUE)) {\r
+       $this->_pages['admin/profile_picture.php']['title_var'] = 'picture';\r
+       $this->_pages['admin/profile_picture.php']['parent']   = 'admin/users.php';\r
+}\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/profile_pictures/module.xml b/mods/_standard/profile_pictures/module.xml
new file mode 100644 (file)
index 0000000..2930d27
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Profile Pictures</name> \r
+    <description lang="en">This modules allows pictures to be included in user profiles.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>BSD</license> \r
+       <release> \r
+        <version>0.1</version> \r
+        <date>2007-02-21</date> \r
+        <state>stable</state> \r
+        <notes></notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/reading_list/module.php b/mods/_standard/reading_list/module.php
new file mode 100644 (file)
index 0000000..507c762
--- /dev/null
@@ -0,0 +1,101 @@
+<?php\r
+/*******\r
+ * doesn't allow this file to be loaded with a browser.\r
+ */\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+/******\r
+ * this file must only be included within a Module obj\r
+ */\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+/*******\r
+ * assign the instructor and admin privileges to the constants.\r
+ */\r
+define('AT_PRIV_READING_LIST',       $this->getPrivilege());\r
+\r
+\r
+/*******\r
+ * if this module is to be made available to students on the Home or Main Navigation.\r
+ */\r
+$_student_tool = 'reading_list/index.php';\r
+\r
+\r
+/*******\r
+ * instructor Manage section:\r
+ */\r
+$this->_pages['reading_list/index_instructor.php']['title_var'] = 'reading_list';\r
+$this->_pages['reading_list/index_instructor.php']['parent']   = 'tools/index.php';\r
+$this->_pages['reading_list/index_instructor.php']['children'] = array('reading_list/display_resources.php');\r
+$this->_pages['reading_list/index_instructor.php']['guide'] = 'instructor/?p=reading_list.php';\r
+\r
+\r
+       $this->_pages['reading_list/add_resource_url.php']['title_var'] = 'rl_add_resource_url';\r
+       $this->_pages['reading_list/add_resource_url.php']['parent']    = 'reading_list/display_resources.php';\r
+\r
+       $this->_pages['reading_list/add_resource_book.php']['title_var'] = 'rl_add_resource_book';\r
+       $this->_pages['reading_list/add_resource_book.php']['parent']    = 'reading_list/display_resources.php';\r
+\r
+       $this->_pages['reading_list/add_resource_handout.php']['title_var'] = 'rl_add_resource_handout';\r
+       $this->_pages['reading_list/add_resource_handout.php']['parent']    = 'reading_list/display_resources.php';\r
+\r
+       $this->_pages['reading_list/add_resource_av.php']['title_var'] = 'rl_add_resource_av';\r
+       $this->_pages['reading_list/add_resource_av.php']['parent']    = 'reading_list/display_resources.php';\r
+\r
+       $this->_pages['reading_list/add_resource_file.php']['title_var'] = 'rl_add_resource_file';\r
+       $this->_pages['reading_list/add_resource_file.php']['parent']    = 'reading_list/display_resources.php';\r
+\r
+       $this->_pages['reading_list/edit_reading_book.php']['title_var'] = 'rl_edit_reading_book';\r
+       $this->_pages['reading_list/edit_reading_book.php']['parent']    = 'reading_list/index_instructor.php';\r
+\r
+       $this->_pages['reading_list/edit_reading_url.php']['title_var'] = 'rl_edit_reading_url';\r
+       $this->_pages['reading_list/edit_reading_url.php']['parent']    = 'reading_list/index_instructor.php';\r
+\r
+       $this->_pages['reading_list/edit_reading_handout.php']['title_var'] = 'rl_edit_reading_handout';\r
+       $this->_pages['reading_list/edit_reading_handout.php']['parent']    = 'reading_list/index_instructor.php';\r
+\r
+       $this->_pages['reading_list/edit_reading_file.php']['title_var'] = 'rl_edit_reading_file';\r
+       $this->_pages['reading_list/edit_reading_file.php']['parent']    = 'reading_list/index_instructor.php';\r
+\r
+       $this->_pages['reading_list/edit_reading_av.php']['title_var'] = 'rl_edit_reading_av';\r
+       $this->_pages['reading_list/edit_reading_av.php']['parent']    = 'reading_list/index_instructor.php';\r
+\r
+       $this->_pages['reading_list/delete_reading.php']['title_var'] = 'rl_delete_reading';\r
+       $this->_pages['reading_list/delete_reading.php']['parent']    = 'reading_list/index_instructor.php';\r
+\r
+       $this->_pages['reading_list/new_reading_book.php']['title_var'] = 'rl_new_reading_book';\r
+       $this->_pages['reading_list/new_reading_book.php']['parent']    = 'reading_list/index_instructor.php';\r
+\r
+       $this->_pages['reading_list/new_reading_url.php']['title_var'] = 'rl_new_reading_url';\r
+       $this->_pages['reading_list/new_reading_url.php']['parent']    = 'reading_list/index_instructor.php';\r
+\r
+       $this->_pages['reading_list/new_reading_av.php']['title_var'] = 'rl_new_reading_av';\r
+       $this->_pages['reading_list/new_reading_av.php']['parent']    = 'reading_list/index_instructor.php';\r
+\r
+       $this->_pages['reading_list/new_reading_handout.php']['title_var'] = 'rl_new_reading_handout';\r
+       $this->_pages['reading_list/new_reading_handout.php']['parent']    = 'reading_list/index_instructor.php';\r
+\r
+       $this->_pages['reading_list/new_reading_file.php']['title_var'] = 'rl_new_reading_file';\r
+       $this->_pages['reading_list/new_reading_file.php']['parent']    = 'reading_list/index_instructor.php';\r
+\r
+       $this->_pages['reading_list/display_resources.php']['title_var'] = 'rl_display_resources';\r
+       $this->_pages['reading_list/display_resources.php']['parent']    = 'reading_list/index_instructor.php';\r
+\r
+       $this->_pages['reading_list/display_resource.php']['title_var'] = 'rl_display_resource';\r
+       $this->_pages['reading_list/display_resource.php']['parent']    = 'reading_list/index.php';\r
+\r
+       $this->_pages['reading_list/delete_resource.php']['title_var'] = 'rl_delete_resource';\r
+       $this->_pages['reading_list/delete_resource.php']['parent']    = 'reading_list/index_instructor.php';\r
+\r
+\r
+/*******\r
+ * student page.\r
+ */\r
+$this->_pages['reading_list/index.php']['title_var'] = 'reading_list';\r
+$this->_pages['reading_list/index.php']['img']       = 'images/home-reading_list.gif';\r
+\r
+$this->_pages['reading_list/index.php']['children'] = array('reading_list/reading_details.php');\r
+\r
+       $this->_pages['reading_list/reading_details.php']['title_var'] = 'rl_display_resources';\r
+       $this->_pages['reading_list/reading_details.php']['parent']    = 'reading_list/index.php';\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/reading_list/module.xml b/mods/_standard/reading_list/module.xml
new file mode 100644 (file)
index 0000000..26ab006
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Reading List</name> \r
+    <description lang="en">Allows the instructor to create a reading list.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>BSD</license> \r
+       <release> \r
+        <version>0.1</version> \r
+        <date>2006-01-12</date> \r
+        <state>stable</state> \r
+        <notes></notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/reading_list/module_backup.php b/mods/_standard/reading_list/module_backup.php
new file mode 100644 (file)
index 0000000..cd84cc8
--- /dev/null
@@ -0,0 +1,36 @@
+<?php\r
+\r
+$sql = array();\r
+$sql['external_resources']  = 'SELECT resource_id, type, title, author, publisher, date, comments, id, url FROM '.TABLE_PREFIX.'external_resources WHERE course_id=?';\r
+\r
+$sql['reading_list']  = 'SELECT resource_id, required, date_start, date_end, comment FROM '.TABLE_PREFIX.'reading_list WHERE course_id=?';\r
+\r
+function external_resources_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0]  = $row[0]; // resource_id\r
+       $new_row[1]  = $course_id;\r
+       $new_row[2]  = $row[1]; // type\r
+       $new_row[3]  = $row[2]; // title\r
+       $new_row[4]  = $row[3]; // author\r
+       $new_row[5]  = $row[4]; // publisher\r
+       $new_row[6]  = $row[5]; // date\r
+       $new_row[7]  = $row[6]; // comments\r
+       $new_row[8]  = $row[7]; // id\r
+       $new_row[9]  = $row[8]; // url\r
+\r
+       return $new_row;\r
+}\r
+\r
+function reading_list_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0]  = 0; // reading_id\r
+       $new_row[1]  = $course_id;\r
+       $new_row[2]  = $table_id_map['external_resources'][$row[0]]; // resource_id\r
+       $new_row[3]  = $row[1]; // required\r
+       $new_row[4]  = $row[2]; // date_start\r
+       $new_row[5]  = $row[3]; // date_end\r
+       $new_row[6]  = $row[4]; // comment\r
+\r
+       return $new_row;\r
+}\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/reading_list/module_delete.php b/mods/_standard/reading_list/module_delete.php
new file mode 100644 (file)
index 0000000..880e951
--- /dev/null
@@ -0,0 +1,13 @@
+<?php\r
+\r
+function reading_list_delete($course) {\r
+       global $db;\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."reading_list WHERE course_id=$course";\r
+       mysql_query($sql, $db);\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."external_resources WHERE course_id=$course";\r
+       mysql_query($sql, $db);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/rss_feeds/load_file.php b/mods/_standard/rss_feeds/load_file.php
new file mode 100644 (file)
index 0000000..f61c3ff
--- /dev/null
@@ -0,0 +1,7 @@
+<?php\r
+\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+print_rss_feed(__FILE__);\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/rss_feeds/module.php b/mods/_standard/rss_feeds/module.php
new file mode 100644 (file)
index 0000000..1d891ee
--- /dev/null
@@ -0,0 +1,112 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_ADMIN_PRIV_RSS', $this->getAdminPrivilege());\r
+\r
+define('AT_FEED_TIMEOUT', 21600);  //feed is cached for this long.  21600 = 6 hours\r
+define('AT_FEED_NUM_RESULTS', 5);\r
+define('AT_FEED_SHOW_DESCRIPTION', FALSE);\r
+\r
+//admin pages\r
+if (admin_authenticate(AT_ADMIN_PRIV_RSS, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+\r
+       if (admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+               $this->_pages['admin/config_edit.php']['children']      = array('admin/rss_feeds/index.php');\r
+               $this->_pages['admin/rss_feeds/index.php']['parent'] = 'admin/config_edit.php';\r
+       } else {\r
+               $this->_pages[AT_NAV_ADMIN] = array('admin/rss_feeds/index.php');\r
+               $this->_pages['admin/rss_feeds/index.php']['parent'] = AT_NAV_ADMIN;\r
+       }\r
+\r
+       $this->_pages['admin/rss_feeds/index.php']['title_var'] = 'rss_feeds';\r
+       $this->_pages['admin/rss_feeds/index.php']['children']  = array('admin/rss_feeds/add_feed.php');\r
+       $this->_pages['admin/rss_feeds/index.php']['guide']     = 'admin/?p=feeds.php';\r
+\r
+               $this->_pages['admin/rss_feeds/add_feed.php']['title_var'] = 'add';\r
+               $this->_pages['admin/rss_feeds/add_feed.php']['parent'] = 'admin/rss_feeds/index.php';\r
+\r
+               $this->_pages['admin/rss_feeds/edit_feed.php']['title_var'] = 'edit';\r
+               $this->_pages['admin/rss_feeds/edit_feed.php']['parent'] = 'admin/rss_feeds/index.php';\r
+\r
+               $this->_pages['admin/rss_feeds/delete_feed.php']['title_var'] = 'delete';\r
+               $this->_pages['admin/rss_feeds/delete_feed.php']['parent'] = 'admin/rss_feeds/index.php';\r
+\r
+               $this->_pages['admin/rss_feeds/preview.php']['title_var'] = 'preview';\r
+               $this->_pages['admin/rss_feeds/preview.php']['parent'] = 'admin/rss_feeds/index.php';\r
+}\r
+\r
+//make the rss files side menu stacks\r
+$rss_files = array();\r
+$dh  = opendir(AT_CONTENT_DIR.'/feeds');\r
+$count = 0;\r
+while (false !== ($file = readdir($dh))) {\r
+       if (strpos($file, '_rss.inc.php')) {\r
+               $feed_id = intval($file);\r
+               if (file_exists(AT_CONTENT_DIR.'feeds/'.$feed_id.'_rss_title.cache')) {\r
+                       $title = @file_get_contents(AT_CONTENT_DIR.'feeds/'.$feed_id.'_rss_title.cache');\r
+                       $this->_stacks[$feed_id.'_rss_title'] = array('title'=>$title, 'file'=>AT_CONTENT_DIR.'feeds/'.$file);\r
+               }\r
+       }\r
+}\r
+\r
+//creates or updates the cache file\r
+function make_cache_file($feed_id) {\r
+       global $db;\r
+       static $rss;\r
+\r
+       if (!isset($rss)) {  \r
+               require_once(AT_INCLUDE_PATH.'classes/lastRSS.php');\r
+               $rss =& new lastRSS; \r
+               $rss->cache_dir = AT_CONTENT_DIR.'feeds/'; \r
+               $rss->num_results = AT_FEED_NUM_RESULTS;\r
+               $rss->description = AT_FEED_SHOW_DESCRIPTION;\r
+       } \r
+\r
+       $sql    = "SELECT url, feed_id FROM ".TABLE_PREFIX."feeds WHERE feed_id=".intval($feed_id);\r
+       $result = mysql_query($sql, $db);\r
+\r
+       if ($row = mysql_fetch_assoc($result)) {\r
+               $output = $rss->get($row['url'], $row['feed_id']);\r
+\r
+               $cache_file = AT_CONTENT_DIR.'feeds/'.$feed_id.'_rss.cache';\r
+               if ($f = @fopen($cache_file, 'w')) {\r
+                       fwrite ($f, $output, strlen($output));\r
+                       fclose($f);\r
+               }\r
+               return 0;\r
+       } else {\r
+               $output = $rss->get($_POST['url'], 0);\r
+               return $output;\r
+       }\r
+}\r
+\r
+function print_rss_feed($file) {\r
+       global $savant;\r
+\r
+       $feed_id = intval(basename($file));\r
+       $cache_file = AT_CONTENT_DIR.'feeds/'.$feed_id.'_rss.cache';\r
+       $title_file = AT_CONTENT_DIR.'feeds/'.$feed_id.'_rss_title.cache';\r
+\r
+       ob_start(); \r
+\r
+       //if file doesn't exist or is more than AT_FEED_TIMEOUT old\r
+       if (!file_exists($cache_file) || ((time() - filemtime($cache_file)) > AT_FEED_TIMEOUT) ) {\r
+               make_cache_file($feed_id);\r
+       }\r
+       if (file_exists($cache_file)) {\r
+               readfile($cache_file);\r
+               echo '<br /><small>'._AT('new_window').'</small>';\r
+       } else {\r
+               echo _AT('no_content_avail');\r
+       }\r
+\r
+       $savant->assign('dropdown_contents', ob_get_contents());\r
+       ob_end_clean();\r
+\r
+       $savant->assign('title', @file_get_contents($title_file));\r
+       $savant->display('include/box.tmpl.php');\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/rss_feeds/module.xml b/mods/_standard/rss_feeds/module.xml
new file mode 100644 (file)
index 0000000..c53487a
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">RSS Feeds</name> \r
+    <description lang="en">An instructor can set up RSS feeds to be displayed in a course's side menu.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+        <date>2005-10-17</date> \r
+        <state>stable</state> \r
+        <notes></notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/sitemap/module.php b/mods/_standard/sitemap/module.php
new file mode 100644 (file)
index 0000000..c2149f3
--- /dev/null
@@ -0,0 +1,12 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+// if this module is to be made available to students on the Home or Main Navigation\r
+$_student_tool = 'sitemap.php';\r
+\r
+$this->_pages['sitemap.php']['title_var'] = 'sitemap';\r
+$this->_pages['sitemap.php']['parent']    = 'index.php';\r
+$this->_pages['sitemap.php']['img']       = 'images/home-site_map.gif';\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/sitemap/module.xml b/mods/_standard/sitemap/module.xml
new file mode 100644 (file)
index 0000000..aed8527
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Site-map</name> \r
+    <description lang="en">A linked tree-list of all the pages in a course.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege></instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-22</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/statistics/module.php b/mods/_standard/statistics/module.php
new file mode 100644 (file)
index 0000000..e251f29
--- /dev/null
@@ -0,0 +1,9 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+$this->_pages['tools/course_stats.php']['title_var'] = 'statistics';\r
+$this->_pages['tools/course_stats.php']['parent']    = 'tools/index.php';\r
+$this->_pages['tools/course_stats.php']['guide']     = 'instructor/?p=statistics.php';\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/statistics/module.xml b/mods/_standard/statistics/module.xml
new file mode 100644 (file)
index 0000000..f25e6da
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Statistics</name> \r
+    <description lang="en">Gives stats on the number of guest and enrolled logins into the course.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege>existing</instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-25</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/statistics/module_backup.php b/mods/_standard/statistics/module_backup.php
new file mode 100644 (file)
index 0000000..e57ab4c
--- /dev/null
@@ -0,0 +1,17 @@
+<?php\r
+\r
+$sql = array();\r
+$sql['course_stats'] = 'SELECT login_date, guests, members FROM '.TABLE_PREFIX.'course_stats WHERE course_id=?';\r
+\r
+\r
+function course_stats_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0] = $course_id;\r
+       $new_row[1] = $row[0];\r
+       $new_row[2] = $row[1];\r
+       $new_row[3] = $row[2];\r
+\r
+       return $new_row;\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/statistics/module_delete.php b/mods/_standard/statistics/module_delete.php
new file mode 100644 (file)
index 0000000..55c6271
--- /dev/null
@@ -0,0 +1,11 @@
+<?php\r
+\r
+function statistics_delete($course) {\r
+       global $db;\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."course_stats WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/student_tools/module.php b/mods/_standard/student_tools/module.php
new file mode 100644 (file)
index 0000000..fc60c20
--- /dev/null
@@ -0,0 +1,16 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_PRIV_STYLES', $this->getPrivilege());\r
+\r
+$this->_pages['tools/modules.php']['title_var'] = 'student_tools';\r
+$this->_pages['tools/modules.php']['parent']    = 'tools/index.php';\r
+$this->_pages['tools/modules.php']['children']  = array('tools/side_menu.php');\r
+$this->_pages['tools/modules.php']['guide']     = 'instructor/?p=student_tools.php';\r
+\r
+       $this->_pages['tools/side_menu.php']['title_var'] = 'side_menu';\r
+       $this->_pages['tools/side_menu.php']['parent']    = 'tools/modules.php';\r
+       $this->_pages['tools/side_menu.php']['guide']     = 'instructor/?p=side_menu.php';\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/student_tools/module.xml b/mods/_standard/student_tools/module.xml
new file mode 100644 (file)
index 0000000..f589884
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Student Tools</name> \r
+    <description lang="en">Allows instructors to set which course tools will be available to students on the home page and/or coruse navigation.  Instructors can also select which available side menu items will be shown for the course.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege>existing</instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-25</date> \r
+        <state>stable</state> \r
+        <notes>This is a core module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/tests/module.php b/mods/_standard/tests/module.php
new file mode 100644 (file)
index 0000000..ceed6b8
--- /dev/null
@@ -0,0 +1,140 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_PRIV_TESTS', $this->getPrivilege());\r
+\r
+// if this module is to be made available to students on the Home or Main Navigation\r
+$_student_tool = 'tools/my_tests.php';\r
+\r
+$this->_pages['tools/tests/index.php']['title_var'] = 'tests';\r
+$this->_pages['tools/tests/index.php']['parent']    = 'tools/index.php';\r
+$this->_pages['tools/tests/index.php']['guide']     = 'instructor/?p=tests_surveys.php';\r
+$this->_pages['tools/tests/index.php']['children']  = array('tools/tests/create_test.php', 'tools/tests/question_db.php', 'tools/tests/question_cats.php');\r
+\r
+$this->_pages['tools/tests/create_test.php']['title_var'] = 'create_test';\r
+$this->_pages['tools/tests/create_test.php']['parent']    = 'tools/tests/index.php';\r
+$this->_pages['tools/tests/create_test.php']['guide']     = 'instructor/?p=creating_tests_surveys.php';\r
+\r
+$this->_pages['tools/tests/question_db.php']['title_var'] = 'question_database';\r
+$this->_pages['tools/tests/question_db.php']['parent']    = 'tools/tests/index.php';\r
+$this->_pages['tools/tests/question_db.php']['guide']     = 'instructor/?p=question_database.php';\r
+\r
+       $this->_pages['tools/tests/create_question_multi.php']['title_var'] = 'create_question_multi';\r
+       $this->_pages['tools/tests/create_question_multi.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+$this->_pages['tools/tests/question_cats.php']['title_var'] = 'question_categories';\r
+$this->_pages['tools/tests/question_cats.php']['parent']    = 'tools/tests/index.php';\r
+$this->_pages['tools/tests/question_cats.php']['children']  = array('tools/tests/question_cats_manage.php');\r
+$this->_pages['tools/tests/question_cats.php']['guide']     = 'instructor/?p=question_categories.php';\r
+\r
+$this->_pages['tools/tests/question_cats_manage.php']['title_var'] = 'create_category';\r
+$this->_pages['tools/tests/question_cats_manage.php']['parent']    = 'tools/tests/question_cats.php';\r
+\r
+$this->_pages['tools/tests/question_cats_delete.php']['title_var'] = 'delete_category';\r
+$this->_pages['tools/tests/question_cats_delete.php']['parent']    = 'tools/tests/question_cats.php';\r
+\r
+$this->_pages['tools/tests/edit_test.php']['title_var'] = 'edit_test';\r
+$this->_pages['tools/tests/edit_test.php']['parent']    = 'tools/tests/index.php';\r
+$this->_pages['tools/tests/edit_test.php']['guide']     = 'instructor/?p=creating_tests_surveys.php';\r
+\r
+$this->_pages['tools/tests/preview.php']['title_var'] = 'preview_questions';\r
+$this->_pages['tools/tests/preview.php']['parent']    = 'tools/tests/index.php';\r
+$this->_pages['tools/tests/preview.php']['guide']     = 'instructor/?p=preview.php';\r
+\r
+$this->_pages['tools/tests/preview_question.php']['title_var'] = 'preview';\r
+$this->_pages['tools/tests/preview_question.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+$this->_pages['tools/tests/results.php']['title_var'] = 'submissions';\r
+$this->_pages['tools/tests/results.php']['parent']    = 'tools/tests/index.php';\r
+\r
+$this->_pages['tools/tests/results_all.php']['guide'] = 'instructor/?p=student_submissions.php';\r
+\r
+//$this->_pages['tools/tests/results_all_quest.php']['title_var']  =  _AT('question')." "._AT('statistics');\r
+//$this->_pages['tools/tests/results_all_quest.php']['parent'] = 'tools/tests/index.php';\r
+$this->_pages['tools/tests/results_all_quest.php']['guide']     = 'instructor/?p=test_statistics.php';\r
+\r
+$this->_pages['tools/tests/delete_test.php']['title_var'] = 'delete_test';\r
+$this->_pages['tools/tests/delete_test.php']['parent']    = 'tools/tests/index.php';\r
+\r
+$this->_pages['tools/view_results.php']['title_var'] = 'view_results';\r
+$this->_pages['tools/view_results.php']['parent']    = 'tools/my_tests.php';\r
+$this->_pages['tools/view_results.php']['children']  = array(); // to create the "back to tests" link\r
+\r
+       // test questions\r
+       $this->_pages['tools/tests/create_question_tf.php']['title_var'] = 'create_new_question';\r
+       $this->_pages['tools/tests/create_question_tf.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/create_question_truefalse.php']['title_var'] = 'create_new_question';\r
+       $this->_pages['tools/tests/create_question_truefalse.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/create_question_multi.php']['title_var'] = 'create_new_question';\r
+       $this->_pages['tools/tests/create_question_multi.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/create_question_multichoice.php']['title_var'] = 'create_new_question';\r
+       $this->_pages['tools/tests/create_question_multichoice.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/create_question_multianswer.php']['title_var'] = 'create_new_question';\r
+       $this->_pages['tools/tests/create_question_multianswer.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/create_question_long.php']['title_var'] = 'create_new_question';\r
+       $this->_pages['tools/tests/create_question_long.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/create_question_likert.php']['title_var'] = 'create_new_question';\r
+       $this->_pages['tools/tests/create_question_likert.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/create_question_matching.php']['title_var'] = 'create_new_question';\r
+       $this->_pages['tools/tests/create_question_matching.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/create_question_matchingdd.php']['title_var'] = 'create_new_question';\r
+       $this->_pages['tools/tests/create_question_matchingdd.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/create_question_ordering.php']['title_var'] = 'create_new_question';\r
+       $this->_pages['tools/tests/create_question_ordering.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/edit_question_tf.php']['title_var'] = 'edit_question';\r
+       $this->_pages['tools/tests/edit_question_tf.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/edit_question_truefalse.php']['title_var'] = 'edit_question';\r
+       $this->_pages['tools/tests/edit_question_truefalse.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/edit_question_multi.php']['title_var'] = 'edit_question';\r
+       $this->_pages['tools/tests/edit_question_multi.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/edit_question_multichoice.php']['title_var'] = 'edit_question';\r
+       $this->_pages['tools/tests/edit_question_multichoice.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/edit_question_multianswer.php']['title_var'] = 'edit_question';\r
+       $this->_pages['tools/tests/edit_question_multianswer.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/edit_question_long.php']['title_var'] = 'edit_question';\r
+       $this->_pages['tools/tests/edit_question_long.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/edit_question_likert.php']['title_var'] = 'edit_question';\r
+       $this->_pages['tools/tests/edit_question_likert.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/edit_question_matching.php']['title_var'] = 'edit_question';\r
+       $this->_pages['tools/tests/edit_question_matching.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/edit_question_matchingdd.php']['title_var'] = 'edit_question';\r
+       $this->_pages['tools/tests/edit_question_matchingdd.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/edit_question_ordering.php']['title_var'] = 'edit_question';\r
+       $this->_pages['tools/tests/edit_question_ordering.php']['parent']    = 'tools/tests/question_db.php';\r
+\r
+       $this->_pages['tools/tests/delete_question.php']['title_var'] = 'delete';\r
+       $this->_pages['tools/tests/delete_question.php']['parent'] = 'tools/tests/question_db.php';\r
+\r
+$this->_pages['tools/take_test.php']['title_var'] = 'take_test';\r
+$this->_pages['tools/take_test.php']['parent']    = 'tools/my_tests.php';\r
+\r
+$this->_pages['tools/take_test_q.php']['title_var'] = 'take_test';\r
+$this->_pages['tools/take_test_q.php']['parent']    = 'tools/my_tests.php';\r
+\r
+$this->_pages['tools/test_intro.php']['title_var'] = 'take_test';\r
+$this->_pages['tools/test_intro.php']['parent']    = 'tools/my_tests.php';\r
+\r
+//student page\r
+$this->_pages['tools/my_tests.php']['title_var'] = 'my_tests';\r
+$this->_pages['tools/my_tests.php']['img']       = 'images/home-tests.gif';\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/tests/module.xml b/mods/_standard/tests/module.xml
new file mode 100644 (file)
index 0000000..2d9d8e7
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Tests</name> \r
+    <description lang="en">This is a large module that allows instructors to create tests and surveys for students with various question types and weights.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege>create</instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-25</date> \r
+        <state>stable</state> \r
+        <notes>This is a standard module.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/tests/module_backup.php b/mods/_standard/tests/module_backup.php
new file mode 100644 (file)
index 0000000..87e9a44
--- /dev/null
@@ -0,0 +1,121 @@
+<?php\r
+\r
+$sql = array();\r
+\r
+$sql['tests'] = 'SELECT test_id, title, format, start_date, end_date, randomize_order, num_questions, instructions, content_id, result_release, random, difficulty, num_takes, anonymous, out_of, guests, display, description, passscore, passpercent, passfeedback, failfeedback FROM '.TABLE_PREFIX.'tests WHERE course_id=? ORDER BY test_id ASC';\r
+\r
+$sql['tests_questions_categories'] = 'SELECT category_id, title FROM '.TABLE_PREFIX.'tests_questions_categories WHERE course_id=?';\r
+\r
+$sql['tests_questions'] = 'SELECT question_id, category_id, type, feedback, question, choice_0, choice_1, choice_2, choice_3, choice_4, choice_5, choice_6, choice_7, choice_8, choice_9, answer_0, answer_1, answer_2, answer_3, answer_4, answer_5, answer_6, answer_7, answer_8, answer_9, option_0, option_1, option_2, option_3, option_4, option_5, option_6, option_7, option_8, option_9, properties, content_id FROM '.TABLE_PREFIX.'tests_questions WHERE course_id=?';\r
+\r
+$sql['tests_questions_assoc'] = 'SELECT TQ.test_id, question_id, weight, ordering, required FROM '.TABLE_PREFIX.'tests_questions_assoc TQ, '.TABLE_PREFIX.'tests T WHERE T.course_id=? AND T.test_id=TQ.test_id ORDER BY TQ.test_id';\r
+\r
+function tests_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0]  = $row[0];\r
+       $new_row[1]  = $course_id;\r
+       $new_row[2]  = $row[1];\r
+       $new_row[3]  = $row[2];\r
+       $new_row[4]  = $row[3];\r
+       $new_row[5]  = $row[4];\r
+       $new_row[6]  = $row[5];\r
+       $new_row[7]  = $row[6];\r
+       $new_row[8]  = $row[7];\r
+       $new_row[9]  = 0;\r
+       $new_row[10] = $row[9]  ? $row[9]  : 0;\r
+       $new_row[11] = $row[10] ? $row[10] : 0;\r
+       $new_row[12] = $row[11] ? $row[11] : 0;\r
+       $new_row[13] = $row[12] ? $row[12] : 0;\r
+       $new_row[14] = $row[13] ? $row[13] : 0;\r
+       $new_row[15] = $row[14] ? $row[14] : 0;\r
+       $new_row[16] = $row[15] ? $row[15] : 0; // `guests`  added 1.5.4\r
+       $new_row[17] = $row[16] ? $row[16] : 0; // `display` added 1.5.6\r
+       $new_row[18]  = $row[17];\r
+       $new_row[19]  = $row[18];\r
+       $new_row[20]  = $row[19];\r
+       $new_row[21]  = $row[20];\r
+       $new_row[22]  = $row[21];\r
+\r
+       return $new_row;\r
+}\r
+\r
+function tests_questions_categories_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0] = $row[0];\r
+       $new_row[1] = $course_id;\r
+       $new_row[2] = $row[1];\r
+\r
+       return $new_row;\r
+}\r
+\r
+function tests_questions_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0]  = $row[0]; // question_id\r
+       $new_row[1]  = $table_id_map['tests_questions_categories'][$row[1]]; // category_id\r
+       $new_row[2]  = $course_id; // course_id, obviously\r
+       $new_row[3]  = $row[2];    // type\r
+       $new_row[4]  = $row[3];    // feedback\r
+       $new_row[5]  = $row[4];    // question\r
+       $new_row[6]  = $row[5];    // choice_0\r
+       $new_row[7]  = $row[6];    // choice_1\r
+       $new_row[8]  = $row[7];    // choice_2\r
+       $new_row[9]  = $row[8];    // choice_3\r
+       $new_row[10] = $row[9];    // choice_4\r
+       $new_row[11] = $row[10];   // choice_5\r
+       $new_row[12] = $row[11];   // choice_6\r
+       $new_row[13] = $row[12];   // choice_7\r
+       $new_row[14] = $row[13];   // choice_8\r
+       $new_row[15] = $row[14];   // choice_9\r
+       $new_row[16] = $row[15];   // answer_0\r
+       $new_row[17] = $row[16];   // answer_1\r
+       $new_row[18] = $row[17];   // answer_2\r
+       $new_row[19] = $row[18];   // answer_3\r
+       $new_row[20] = $row[19];   // answer_4\r
+       $new_row[21] = $row[20];   // answer_5\r
+       $new_row[22] = $row[21];   // answer_6\r
+       $new_row[23] = $row[22];   // answer_7\r
+       $new_row[24] = $row[23];   // answer_8\r
+       $new_row[25] = $row[24];   // answer_9\r
+       if (version_compare($version, '1.5.4', '<')) {\r
+               // option_[0-9] were added in 1.5.4 before properties\r
+               $new_row[26] = '';       // option_0\r
+               $new_row[27] = '';       // option_1\r
+               $new_row[28] = '';       // option_2\r
+               $new_row[29] = '';       // option_3\r
+               $new_row[30] = '';       // option_4\r
+               $new_row[31] = '';       // option_5\r
+               $new_row[32] = '';       // option_6\r
+               $new_row[33] = '';       // option_7\r
+               $new_row[34] = '';       // option_8\r
+               $new_row[35] = '';       // option_9\r
+               $new_row[36] = $row[25]; // properties\r
+               $new_row[37] = $row[26]; // content_id\r
+       } else {\r
+               $new_row[26] = $row[25]; // option_0\r
+               $new_row[27] = $row[26]; // option_1\r
+               $new_row[28] = $row[27]; // option_2\r
+               $new_row[29] = $row[28]; // option_3\r
+               $new_row[30] = $row[29]; // option_4\r
+               $new_row[31] = $row[30]; // option_5\r
+               $new_row[32] = $row[31]; // option_6\r
+               $new_row[33] = $row[32]; // option_7\r
+               $new_row[34] = $row[33]; // option_8\r
+               $new_row[35] = $row[34]; // option_9\r
+               $new_row[36] = $row[35]; // properties\r
+               $new_row[37] = $row[36]; // content_id\r
+       }\r
+\r
+       return $new_row;\r
+}\r
+\r
+function tests_questions_assoc_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0] = $table_id_map['tests'][$row[0]];\r
+       $new_row[1] = $table_id_map['tests_questions'][$row[1]];\r
+       $new_row[2] = $row[2];\r
+       $new_row[3] = $row[3];\r
+       $new_row[4] = $row[4];\r
+\r
+       return $new_row;\r
+}\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/tests/module_delete.php b/mods/_standard/tests/module_delete.php
new file mode 100644 (file)
index 0000000..7f7e490
--- /dev/null
@@ -0,0 +1,33 @@
+<?php\r
+\r
+function tests_delete($course) {\r
+       global $db;\r
+\r
+       $sql    = "SELECT test_id FROM ".TABLE_PREFIX."tests WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               $sql    = "DELETE FROM ".TABLE_PREFIX."tests_questions_assoc WHERE test_id=$row[test_id]";\r
+               $result2 = mysql_query($sql, $db);\r
+       \r
+               $sql2   = "SELECT result_id FROM ".TABLE_PREFIX."tests_results WHERE test_id=$row[test_id]";\r
+               $result2 = mysql_query($sql2, $db);\r
+               while ($row2 = mysql_fetch_assoc($result2)) {\r
+                       $sql3   = "DELETE FROM ".TABLE_PREFIX."tests_answers WHERE result_id=$row2[result_id]";\r
+                       $result3 = mysql_query($sql3, $db);\r
+               }\r
+               $sql    = "DELETE FROM ".TABLE_PREFIX."tests_results WHERE test_id=$row[test_id]";\r
+               $result2 = mysql_query($sql, $db);\r
+       }\r
+\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."tests_questions WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."tests_questions_categories WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."tests WHERE course_id=$course";\r
+       $result = mysql_query($sql, $db);\r
+\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/tests/module_groups.php b/mods/_standard/tests/module_groups.php
new file mode 100644 (file)
index 0000000..a0a0bda
--- /dev/null
@@ -0,0 +1,15 @@
+<?php\r
+\r
+// create group\r
+function tests_create_group($group_id) { }\r
+\r
+\r
+// delete group\r
+function tests_delete_group($group_id) {\r
+       global $db;\r
+\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."tests_groups WHERE group_id=$row[group_id]";\r
+       $result2 = mysql_query($sql, $db);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/tile_search/module.php b/mods/_standard/tile_search/module.php
new file mode 100644 (file)
index 0000000..c74bc7e
--- /dev/null
@@ -0,0 +1,33 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+/* the URL to the WSDL of the TILE repository of choice. */\r
+define('AT_TILE_WSDL', 'http://tile.atutor.ca/tile/services/search?wsdl');\r
+\r
+/* the URL to the content package export servlet of the TILE repository of choice. */\r
+define('AT_TILE_EXPORT', 'http://tile.atutor.ca/tile/servlet/export');\r
+\r
+/* the URL to the content importing servlet of the TILE repository. */\r
+define('AT_TILE_IMPORT', 'http://tile.atutor.ca/tile/servlet/put');\r
+\r
+define('AT_TILE_PREVIEW', 'http://tile.atutor.ca/tile/servlet/view?view=item&');\r
+\r
+// if this module is to be made available to students on the Home or Main Navigation\r
+$_student_tool = 'tile.php';\r
+\r
+$this->_pages['tools/content/index.php']['children'] = array('tools/tile/index.php');\r
+\r
+//instructor pages\r
+$this->_pages['tools/tile/index.php']['title_var']  = 'tile_search';\r
+$this->_pages['tools/tile/index.php']['parent'] = 'tools/content/index.php';\r
+$this->_pages['tools/tile/index.php']['guide'] = 'instructor/?p=tile_repository.php';\r
+\r
+       $this->_pages['tools/tile/import.php']['title_var']    = 'import_content_package';\r
+       $this->_pages['tools/tile/import.php']['parent']   = 'tools/tile/index.php';\r
+\r
+//student pages\r
+$this->_pages['tile.php']['title_var'] = 'tile_search';\r
+$this->_pages['tile.php']['img']       = 'images/home-tile_search.gif';\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/tile_search/module.xml b/mods/_standard/tile_search/module.xml
new file mode 100644 (file)
index 0000000..3ca9c20
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">TILE Search</name> \r
+    <description lang="en">An interface for searching the TILE (The Inclusive Learning Exchange) course repository.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+               <privileges>\r
+                       <instructor_privilege></instructor_privilege>\r
+                       <admin_privilege></admin_privilege> \r
+               </privileges>\r
+        <date>2005-08-29</date> \r
+        <state>stable</state> \r
+        <notes>This is a standard module.  See http://barrierfree.ca/tile/ for more information on TILE.</notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/_standard/tracker/module.php b/mods/_standard/tracker/module.php
new file mode 100644 (file)
index 0000000..20f00ae
--- /dev/null
@@ -0,0 +1,23 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+// if this module is to be made available to students on the Home or Main Navigation\r
+$_student_tool = 'my_stats.php';\r
+\r
+$_pages['my_stats.php']['title_var'] = 'my_tracker';\r
+$_pages['my_stats.php']['img']       = 'images/home-tracker.gif';\r
+\r
+$_pages['tools/content/index.php']['children'][]  = 'tools/tracker/index.php';\r
+\r
+$_pages['tools/tracker/index.php']['title_var'] = 'content_usage';\r
+$_pages['tools/tracker/index.php']['parent']    = 'tools/content/index.php';\r
+$_pages['tools/tracker/index.php']['children']  = array('tools/tracker/student_usage.php', 'tools/tracker/reset.php');\r
+$_pages['tools/tracker/index.php']['guide']     = 'instructor/?p=content_usage.php';           \r
+\r
+       $_pages['tools/tracker/student_usage.php']['title_var']  = 'member_stats';\r
+       $_pages['tools/tracker/student_usage.php']['parent'] = 'tools/tracker/index.php';\r
+\r
+       $_pages['tools/tracker/reset.php']['title_var']  = 'reset';\r
+       $_pages['tools/tracker/reset.php']['parent'] = 'tools/tracker/index.php';\r
+?>
\ No newline at end of file
diff --git a/mods/_standard/tracker/module.xml b/mods/_standard/tracker/module.xml
new file mode 100644 (file)
index 0000000..b533f53
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Content Tracker</name> \r
+    <description lang="en">Statistics of which content pages students have viewed are avaiable in "My Tracker".  Overall content usage is also available to instructors.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+        <use_privilege>true</use_privilege> \r
+        <date>2005-08-25</date> \r
+        <state>stable</state> \r
+        <notes></notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/hello_world/hello_world.jpg b/mods/hello_world/hello_world.jpg
new file mode 100644 (file)
index 0000000..c6cf71b
Binary files /dev/null and b/mods/hello_world/hello_world.jpg differ
diff --git a/mods/hello_world/index.php b/mods/hello_world/index.php
new file mode 100644 (file)
index 0000000..111bd83
--- /dev/null
@@ -0,0 +1,12 @@
+<?php\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+$_custom_css = $_base_path . 'mods/hello_world/module.css'; // use a custom stylesheet\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+?>\r
+\r
+<div id="helloworld">\r
+       Hello Student!! :)\r
+</div>\r
+\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/mods/hello_world/index_admin.php b/mods/hello_world/index_admin.php
new file mode 100644 (file)
index 0000000..f8f43bd
--- /dev/null
@@ -0,0 +1,10 @@
+<?php\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+admin_authenticate(AT_ADMIN_PRIV_HELLO_WORLD);\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+?>\r
+\r
+Hello Administrator!! :)\r
+\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/mods/hello_world/index_instructor.php b/mods/hello_world/index_instructor.php
new file mode 100644 (file)
index 0000000..bf2d484
--- /dev/null
@@ -0,0 +1,10 @@
+<?php\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_HELLO_WORLD);\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+?>\r
+\r
+Hello Instructor!! :)\r
+\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/mods/hello_world/index_mystart.php b/mods/hello_world/index_mystart.php
new file mode 100644 (file)
index 0000000..c3f7b7b
--- /dev/null
@@ -0,0 +1,13 @@
+<?php\r
+$_user_location        = 'users';\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+$_custom_css = $_base_path . 'mods/hello_world/module.css'; // use a custom stylesheet\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+?>\r
+\r
+<div id="helloworld">\r
+       This is a page of the Hello World module that requires a login session, but might contain a tool that is not a course tool :)\r
+</div>\r
+\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/mods/hello_world/index_public.php b/mods/hello_world/index_public.php
new file mode 100644 (file)
index 0000000..fa3f2e6
--- /dev/null
@@ -0,0 +1,15 @@
+<?php\r
+\r
+$_user_location        = 'public';\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+$_custom_css = $_base_path . 'mods/hello_world/module.css'; // use a custom stylesheet\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+?>\r
+\r
+<div id="helloworld">\r
+       This is a public page from the Hello World module, that does not require a login session to view.  :)\r
+</div>\r
+\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/mods/hello_world/module.css b/mods/hello_world/module.css
new file mode 100644 (file)
index 0000000..15da013
--- /dev/null
@@ -0,0 +1,11 @@
+div#helloworld {\r
+       border: 1px solid #ccc;\r
+       padding: 10px;\r
+       width: 50%;\r
+       margin-right: auto;\r
+       margin-left: auto;\r
+       background-color: #efefef;\r
+       color: #444;\r
+       margin-top: 30px;\r
+       margin-bottom: 30px;\r
+}
\ No newline at end of file
diff --git a/mods/hello_world/module.php b/mods/hello_world/module.php
new file mode 100644 (file)
index 0000000..448b4f1
--- /dev/null
@@ -0,0 +1,68 @@
+<?php\r
+/*******\r
+ * doesn't allow this file to be loaded with a browser.\r
+ */\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+/******\r
+ * this file must only be included within a Module obj\r
+ */\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+/*******\r
+ * assign the instructor and admin privileges to the constants.\r
+ */\r
+define('AT_PRIV_HELLO_WORLD',       $this->getPrivilege());\r
+define('AT_ADMIN_PRIV_HELLO_WORLD', $this->getAdminPrivilege());\r
+\r
+/*******\r
+ * create a side menu box/stack.\r
+ */\r
+$this->_stacks['hello_world'] = array('title_var'=>'hello_world', 'file'=>'mods/hello_world/side_menu.inc.php');\r
+// ** possible alternative: **\r
+// $this->addStack('hello_world', array('title_var' => 'hello_world', 'file' => './side_menu.inc.php');\r
+\r
+/*******\r
+ * if this module is to be made available to students on the Home or Main Navigation.\r
+ */\r
+$_group_tool = $_student_tool = 'mods/hello_world/index.php';\r
+\r
+/*******\r
+ * add the admin pages when needed.\r
+ */\r
+if (admin_authenticate(AT_ADMIN_PRIV_HELLO_WORLD, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) {\r
+       $this->_pages[AT_NAV_ADMIN] = array('mods/hello_world/index_admin.php');\r
+       $this->_pages['mods/hello_world/index_admin.php']['title_var'] = 'hello_world';\r
+       $this->_pages['mods/hello_world/index_admin.php']['parent']    = AT_NAV_ADMIN;\r
+}\r
+\r
+/*******\r
+ * instructor Manage section:\r
+ */\r
+$this->_pages['mods/hello_world/index_instructor.php']['title_var'] = 'hello_world';\r
+$this->_pages['mods/hello_world/index_instructor.php']['parent']   = 'tools/index.php';\r
+// ** possible alternative: **\r
+// $this->pages['./index_instructor.php']['title_var'] = 'hello_world';\r
+// $this->pages['./index_instructor.php']['parent']    = 'tools/index.php';\r
+\r
+/*******\r
+ * student page.\r
+ */\r
+$this->_pages['mods/hello_world/index.php']['title_var'] = 'hello_world';\r
+$this->_pages['mods/hello_world/index.php']['img']       = 'mods/hello_world/hello_world.jpg';\r
+\r
+\r
+/* public pages */\r
+$this->_pages[AT_NAV_PUBLIC] = array('mods/hello_world/index_public.php');\r
+$this->_pages['mods/hello_world/index_public.php']['title_var'] = 'hello_world';\r
+$this->_pages['mods/hello_world/index_public.php']['parent'] = AT_NAV_PUBLIC;\r
+\r
+/* my start page pages */\r
+$this->_pages[AT_NAV_START]  = array('mods/hello_world/index_mystart.php');\r
+$this->_pages['mods/hello_world/index_mystart.php']['title_var'] = 'hello_world';\r
+$this->_pages['mods/hello_world/index_mystart.php']['parent'] = AT_NAV_START;\r
+\r
+function hello_world_get_group_url($group_id) {\r
+       return 'mods/hello_world/index.php';\r
+}\r
+?>
\ No newline at end of file
diff --git a/mods/hello_world/module.sql b/mods/hello_world/module.sql
new file mode 100644 (file)
index 0000000..422910d
--- /dev/null
@@ -0,0 +1,9 @@
+# sql file for hello world module\r
+\r
+CREATE TABLE `hello_world` (\r
+   `course_id` mediumint(8) unsigned NOT NULL,\r
+   `value` VARCHAR( 30 ) NOT NULL ,\r
+   PRIMARY KEY ( `course_id` )\r
+);\r
+\r
+INSERT INTO `language_text` VALUES ('en', '_module','hello_world','Hello World',NOW(),'');\r
diff --git a/mods/hello_world/module.xml b/mods/hello_world/module.xml
new file mode 100644 (file)
index 0000000..82ff951
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">Hello World</name> \r
+    <description lang="en">This is a demo module that can be used as a skeleton for developing your own module. It implements all the features that a module can implment, including its own privileges, a directory, course backup/restore and delete, and an SQL file.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>BSD</license> \r
+       <release> \r
+        <version>0.1</version> \r
+        <date>2005-08-22</date> \r
+        <state>stable</state> \r
+        <notes></notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/hello_world/module_backup.php b/mods/hello_world/module_backup.php
new file mode 100644 (file)
index 0000000..7a65f7a
--- /dev/null
@@ -0,0 +1,18 @@
+<?php\r
+/* each table to be backed up. includes the sql entry and fields */\r
+\r
+$dirs = array();\r
+$dirs['hello_world/'] = AT_CONTENT_DIR . 'hello_world' . DIRECTORY_SEPARATOR;\r
+\r
+$sql = array();\r
+$sql['hello_world']  = 'SELECT value FROM '.TABLE_PREFIX.'hello_world WHERE course_id=?';\r
+\r
+function hello_world_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0]  = $course_id;\r
+       $new_row[1]  = $row[0];\r
+\r
+       return $new_row;\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/hello_world/module_cron.php b/mods/hello_world/module_cron.php
new file mode 100644 (file)
index 0000000..6e14600
--- /dev/null
@@ -0,0 +1,13 @@
+<?php\r
+/*******\r
+ * this function named [module_name]_cron is run by the global cron script at the module's specified\r
+ * interval.\r
+ */\r
+\r
+function hello_world_cron() {\r
+       global $db;\r
+\r
+       debug('yay i am running!');\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/hello_world/module_delete.php b/mods/hello_world/module_delete.php
new file mode 100644 (file)
index 0000000..322d3a6
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+/*******\r
+ * this function named [module_name]_delete is called whenever a course content is deleted\r
+ * which includes when restoring a backup with override set, or when deleting an entire course.\r
+ * the function must delete all module-specific material associated with this course.\r
+ * $course is the ID of the course to delete.\r
+ */\r
+\r
+function hello_world_delete($course) {\r
+       global $db;\r
+\r
+       // delete hello_world course table entries\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."hello_world WHERE course_id=$course";\r
+       mysql_query($sql, $db);\r
+\r
+       // delete hello_world course files\r
+       $path = AT_CONTENT_DIR .'hello_world/' . $course .'/';\r
+       clr_dir($path);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/hello_world/module_install.php b/mods/hello_world/module_install.php
new file mode 100644 (file)
index 0000000..9a82811
--- /dev/null
@@ -0,0 +1,67 @@
+<?php\r
+/*******\r
+ * the line below safe-guards this file from being accessed directly from\r
+ * a web browser. It will only execute if required from within an ATutor script,\r
+ * in our case the Module::install() method.\r
+ */\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+/*******\r
+ * Note: the many options for these variables are used to decrease confusion.\r
+ *       TRUE | FALSE | 1 will be the convention.\r
+ *\r
+ * $_course_privilege\r
+ *     specifies the type of instructor privilege this module uses.\r
+ *     set to empty | FALSE | 0   to disable any privileges.\r
+ *     set to 1 | AT_PRIV_ADMIN   to use the instructor only privilege.\r
+ *     set to TRUE | 'new'        to create a privilege specifically for this module:\r
+ *                                will make this module available as a student privilege.\r
+ *\r
+ * $_admin_privilege\r
+ *    specifies the type of ATutor administrator privilege this module uses.\r
+ *    set to FALSE | AT_ADMIN_PRIV_ADMIN   to use the super administrator only privilege.\r
+ *    set to TRUE | 'new'                  to create a privilege specifically for this module:\r
+ *                                         will make this module available as an administrator privilege.\r
+ *\r
+ *\r
+ * $_cron_interval\r
+ *    if non-zero specifies in minutes how often the module's cron job should be run.\r
+ *    set to 0 or not set to disable.\r
+ */\r
+$_course_privilege = TRUE; // possible values: FALSE | AT_PRIV_ADMIN | TRUE\r
+$_admin_privilege  = TRUE; // possible values: FALSE | TRUE\r
+$_cron_interval    = 35; // run every 30 minutes\r
+\r
+\r
+/********\r
+ * the following code is used for creating a module-specific directory.\r
+ * it generates appropriate error messages to aid in its creation.\r
+ */\r
+$directory = AT_CONTENT_DIR .'hello_world';\r
+\r
+// check if the directory is writeable\r
+if (!is_dir($directory) && !@mkdir($directory)) {\r
+       $msg->addError(array('MODULE_INSTALL', '<li>'.$directory.' does not exist. Please create it.</li>'));\r
+} else if (!is_writable($directory) && @chmod($directory, 0666)) {\r
+       $msg->addError(array('MODULE_INSTALL', '<li>'.$directory.' is not writeable. On Unix issue the command <kbd>chmod a+rw</kbd>.</li>'));\r
+}\r
+\r
+\r
+/******\r
+ * the following code checks if there are any errors (generated previously)\r
+ * then uses the SqlUtility to run any database queries it needs, ie. to create\r
+ * its own tables.\r
+ */\r
+if (!$msg->containsErrors() && file_exists(dirname(__FILE__) . '/module.sql')) {\r
+       // deal with the SQL file:\r
+       require(AT_INCLUDE_PATH . 'classes/sqlutility.class.php');\r
+       $sqlUtility =& new SqlUtility();\r
+\r
+       /*\r
+        * the SQL file could be stored anywhere, and named anything, "module.sql" is simply\r
+        * a convention we're using.\r
+        */\r
+       $sqlUtility->queryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/hello_world/side_menu.inc.php b/mods/hello_world/side_menu.inc.php
new file mode 100644 (file)
index 0000000..94e91e8
--- /dev/null
@@ -0,0 +1,13 @@
+<?php \r
+/* start output buffering: */\r
+ob_start(); ?>\r
+\r
+hello world\r
+\r
+<?php\r
+$savant->assign('dropdown_contents', ob_get_contents());\r
+ob_end_clean();\r
+\r
+$savant->assign('title', _AT('hello_world')); // the box title\r
+$savant->display('include/box.tmpl.php');\r
+?>
\ No newline at end of file
diff --git a/mods/index.html b/mods/index.html
new file mode 100644 (file)
index 0000000..945c9b4
--- /dev/null
@@ -0,0 +1 @@
+.
\ No newline at end of file
diff --git a/mods/scorm_packages/module.php b/mods/scorm_packages/module.php
new file mode 100644 (file)
index 0000000..7a298b6
--- /dev/null
@@ -0,0 +1,40 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+if (!isset($this) || (isset($this) && (strtolower(get_class($this)) != 'module'))) { exit(__FILE__ . ' is not a Module'); }\r
+\r
+define('AT_PRIV_CONTENT', $this->getPrivilege());\r
+\r
+define('AT_PACKAGE_TYPES', 'scorm-1.2');\r
+define('AT_PACKAGE_URL_BASE', AT_BASE_HREF . 'sco/'); \r
+\r
+\r
+// if this module is to be made available to students on the Home or Main Navigation\r
+$_student_tool = 'packages/index.php';\r
+\r
+$this->_pages['tools/packages/index.php']['title_var'] = 'packages';\r
+$this->_pages['tools/packages/index.php']['parent']    = 'tools/index.php';\r
+$this->_pages['tools/packages/index.php']['children']  = array('tools/packages/import.php', 'tools/packages/delete.php');\r
+$this->_pages['tools/packages/index.php']['guide']     = 'instructor/?p=scorm_packages.php';\r
+       \r
+       $this->_pages['tools/packages/import.php']['title_var'] = 'import_package';\r
+       $this->_pages['tools/packages/import.php']['parent']    = 'tools/packages/index.php';\r
+       \r
+       $this->_pages['tools/packages/delete.php']['title_var'] = 'delete_package';\r
+       $this->_pages['tools/packages/delete.php']['parent']    = 'tools/packages/index.php';\r
+       \r
+       //$this->_pages['tools/packages/settings.php']['title_var'] = 'package_settings';\r
+       //$this->_pages['tools/packages/settings.php']['parent']    = 'tools/packages/index.php';\r
+\r
+       $this->_pages['tools/packages/scorm-1.2/view.php']['parent']    = 'tools/packages/index.php';\r
+\r
+$this->_pages['packages/index.php']['title_var'] = 'packages';\r
+$this->_pages['packages/index.php']['img']       = 'images/content_pkg.gif';\r
+$this->_pages['packages/index.php']['children']  = array ('packages/preferences.php');\r
+$this->_pages['packages/index.php']['guide']     = 'general/?p=6.2.packages.php';\r
+\r
+       $this->_pages['packages/preferences.php']['title_var'] = 'preferences';\r
+       $this->_pages['packages/preferences.php']['parent']    = 'packages/index.php';\r
+\r
+       $this->_pages['packages/cmidata.php']['title_var'] = 'cmi_data';\r
+       $this->_pages['packages/cmidata.php']['parent']    = 'packages/index.php';\r
+?>\r
diff --git a/mods/scorm_packages/module.sql b/mods/scorm_packages/module.sql
new file mode 100644 (file)
index 0000000..8a479fc
--- /dev/null
@@ -0,0 +1,75 @@
+\r
+# SCORM language : some of it is still in svn and should be moved in here.\r
+\r
+INSERT INTO `language_text` VALUES ('en', '_module','scorm_browse','Browse',NOW(),''); \r
+INSERT INTO `language_text` VALUES ('en', '_module','scorm_credit','Credit',NOW(),''); \r
+INSERT INTO `language_text` VALUES ('en', '_module','scorm_credit_mode','Credit Mode:',NOW(),''); \r
+INSERT INTO `language_text` VALUES ('en', '_module','scorm_credit_mode_info','This is the answer given to the learning objects when they ask whether the learner is taking this particular package for credit.',NOW(),''); \r
+INSERT INTO `language_text` VALUES ('en', '_module','scorm_lesson_mode','Lesson Mode:',NOW(),''); \r
+INSERT INTO `language_text` VALUES ('en', '_module','scorm_lesson_mode_info','This is the answer given to the learning objects when they ask whether the learner is just browsing or not.',NOW(),''); \r
+INSERT INTO `language_text` VALUES ('en', '_module','scorm_normal','Normal',NOW(),''); \r
+INSERT INTO `language_text` VALUES ('en', '_module','scorm_no_credit','No Credit',NOW(),''); \r
+INSERT INTO `language_text` VALUES ('en', '_module','scorm_packages','SCORM Packages',NOW(),''); \r
+INSERT INTO `language_text` VALUES ('en', '_module','scorm_sco_is_running','Running',NOW(),''); \r
+INSERT INTO `language_text` VALUES ('en', '_module','package_scorm_1_2_rte_loading','Loading SCORM-1.2 RTE<br />Please be patient ...',NOW(),'');\r
+INSERT INTO `language_text` VALUES ('en', '_module','packages_auto_advance_info','The first time a Learning Object signalizes that you have completed it, the RTE can start the next Learning Object. You might find this convenient if you want to complete all Learning Objects in a package in a sequential manner.',NOW(),'');\r
+INSERT INTO `language_text` VALUES ('en', '_module','packages_show_rte_communication','Show RTE Communication',NOW(),'');\r
+INSERT INTO `language_text` VALUES ('en', '_module','packages_show_rte_communication_info','You can monitor the communication between Learning Objects and the RTE. You may want to switch on this option for a while just for informational purposes.',NOW(),'');\r
+\r
+INSERT INTO `language_text` VALUES ('en', '_module','AT_ERROR_SCORM_ITEM_HREF_MISSING','The file you tried to import is not a scorm-1.2 package. The required href attribute is missing for some resource(s).',NOW(),''); \r
+INSERT INTO `language_text` VALUES ('en', '_module','AT_ERROR_SCORM_ITEM_SCORMTYPE_MISSING','The file you tried to import is not a scorm-1.2 package. The required adlcp:scormtype is missing for some resource(s).',NOW(),''); \r
+INSERT INTO `language_text` VALUES ('en', '_module','AT_FEEDBACK_SCORM_SETTINGS_SAVED','The package settings have been saved.',NOW(),'');\r
+INSERT INTO `language_text` VALUES ('en', '_module','AT_WARNING_SCORM_ITEM_CLUSTER_HAS_OBJECT','Some node(s) has content attached to it. The next version of the SCORM specification does not allow nodes to have attached content.',NOW(),'');\r
+\r
+\r
+# ----------------\r
+# SCORM RTE tables\r
+\r
+CREATE TABLE `packages` (\r
+      `package_id` mediumint(8) unsigned NOT NULL auto_increment,\r
+      `source`     varchar(255) NOT NULL,\r
+      `time`       datetime NOT NULL,\r
+      `course_id`  mediumint(8) unsigned NOT NULL,\r
+      `ptype`      varchar(63) NOT NULL,\r
+      PRIMARY KEY (package_id)\r
+) TYPE=MyISAM;\r
+\r
+CREATE TABLE `scorm_1_2_org` (\r
+      `org_id`     mediumint(8) unsigned NOT NULL auto_increment,\r
+      `package_id` mediumint(8) unsigned NOT NULL,\r
+\r
+      `title`         varchar(255) NOT NULL,\r
+      `credit`        varchar(15)  not null default 'no-credit',\r
+      `lesson_mode`   varchar(15)  not null default 'browse',\r
+\r
+      PRIMARY KEY (org_id),\r
+      KEY         (package_id)\r
+) TYPE=MyISAM;\r
+\r
+CREATE TABLE `scorm_1_2_item` (\r
+      `item_id`    mediumint(8) unsigned NOT NULL auto_increment,\r
+      `org_id`     mediumint(8) unsigned NOT NULL,\r
+      `idx`             varchar(15)  NOT NULL,\r
+      `title`           varchar(255),\r
+      `href`            varchar(255),\r
+      `scormtype`       varchar(15),\r
+      `prerequisites`   varchar(255),\r
+      `maxtimeallowed`  varchar(255),\r
+      `timelimitaction` varchar(255),\r
+      `datafromlms`     varchar(255),\r
+      `masteryscore`    mediumint(8),\r
+\r
+      PRIMARY KEY (item_id),\r
+      KEY (org_id)\r
+)TYPE=MyISAM;\r
+\r
+\r
+CREATE TABLE `cmi` (\r
+      `cmi_id`        mediumint(8) unsigned NOT NULL auto_increment,\r
+      `item_id`       mediumint(8) unsigned NOT NULL,\r
+      `member_id`     mediumint unsigned NOT NULL ,\r
+      `lvalue`        varchar(63) NOT NULL,\r
+      `rvalue`        blob,\r
+       PRIMARY KEY (cmi_id),\r
+      UNIQUE KEY (item_id, member_id,lvalue)\r
+)TYPE=MyISAM;\r
diff --git a/mods/scorm_packages/module.xml b/mods/scorm_packages/module.xml
new file mode 100644 (file)
index 0000000..3f72ae4
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="ISO-8859-1"?> \r
+<module version="0.1"> \r
+    <name lang="en">SCORM Packages</name> \r
+    <description lang="en">Allows instructors to include SCORM packages in a course.</description> \r
+    <maintainers>\r
+        <maintainer> \r
+            <name>ATutor Team</name> \r
+            <email>info@atutor.ca</email> \r
+        </maintainer>\r
+    </maintainers> \r
+    <url>http://atutor.ca</url> \r
+    <license>GPL</license> \r
+       <release> \r
+        <version>0.1</version> \r
+        <date>2005-08-22</date> \r
+        <state>stable</state> \r
+        <notes></notes> \r
+    </release> \r
+</module>
\ No newline at end of file
diff --git a/mods/scorm_packages/module_install.php b/mods/scorm_packages/module_install.php
new file mode 100644 (file)
index 0000000..b480d65
--- /dev/null
@@ -0,0 +1,26 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+$_course_privilege = 'new'; // 0/false | 1/AT_PRIV_ADMIN | 'new'/TRUE\r
+$_admin_privilege  = 'new'; // 0/false | 1/AT_ADMIN_PRIV_ADMIN | 'new'/TRUE\r
+\r
+$directory = realpath(AT_INCLUDE_PATH . '../') . '/sco'; // a top level directory\r
+\r
+// check if the directory is writeable\r
+if (!is_dir($directory) && !@mkdir($directory)) {\r
+       $msg->addError(array('MODULE_INSTALL', '<li>'.$directory.' does not exist. Please create it.</li>'));\r
+} else {\r
+       @chmod($directory, 0666);\r
+       if (!is_writable($directory)) {\r
+               $msg->addError(array('MODULE_INSTALL', '<li>'.$directory.' is not writeable. On Unix issue the command <kbd>chmod a+rw</kbd>.</li>'));\r
+       }\r
+}\r
+\r
+if (!$msg->containsErrors() && file_exists(dirname(__FILE__) . '/module.sql')) {\r
+    // deal with the SQL file:\r
+    require(AT_INCLUDE_PATH . 'classes/sqlutility.class.php');\r
+    $sqlUtility =& new SqlUtility();\r
+    $sqlUtility->queryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/mods/scorm_packages/possible_module_backup.php b/mods/scorm_packages/possible_module_backup.php
new file mode 100644 (file)
index 0000000..3267cd4
--- /dev/null
@@ -0,0 +1,65 @@
+<?php\r
+\r
+/****\r
+This is what the backup file MIGHT look like.\r
+\r
+*** Problem ***\r
+the org directories within the course directory are determined by the org id. to work correctly the restore would have to rename each org directory to the new org id. that process of renaming a directory after it has been restored is not possible.\r
+\r
+we would need custom code to execute somewhere that would do the conversion by using the $table_id_map data to translate the org ids.\r
+\r
+instead of just copying the directories blindly this module would have to override the directory restoring functionality to rename the org directories as they are copied.\r
+**/\r
+\r
+exit;\r
+\r
+$dirs = array();\r
+$dirs['sco/'] = realpath(AT_INCLUDE_PATH . '../').DIRECTORY_SEPARATOR.'sco'.DIRECTORY_SEPARATOR.'?'.DIRECTORY_SEPARATOR;\r
+\r
+$sql = array();\r
+$sql['packages']  = 'SELECT package_id, source, time, ptype FROM '.TABLE_PREFIX.'packages WHERE course_id=? ORDER BY package_id';\r
+\r
+$sql['scorm_1_2_org']  = 'SELECT O.org_id, O.package_id, O.title, O.credit, O.lesson_mode FROM '.TABLE_PREFIX.'scorm_1_2_org O INNER JOIN '.TABLE_PREFIX.'packages P ON  (O.package_id=P.package_id) WHERE P.course_id=? ORDER BY O.org_id';\r
+\r
+$sql['scorm_1_2_item']  = 'SELECT I.item_id, I.org_id, I.idx, I.title, I.href, I.scormtype, I.prerequisites, I.maxtimeallowed, I.timelimitaction, I.dataformlms, I.masteryscore FROM '.TABLE_PREFIX.'scorm_1_2_item I INNER JOIN '.TABLE_PREFIX.'scorm_1_2_org O ON (I.org_id=O.org_id) INNER JOIN '.TABLE_PREFIX.'packages P ON (O.package_id=P.package_id) WHERE Pcourse_id=? ORDER BY I.item_id';\r
+\r
+function packages_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0]  = $row[0];\r
+       $new_row[1]  = $row[1];\r
+       $new_row[2]  = $row[2];\r
+       $new_row[3]  = $course_id;\r
+       $new_row[4]  = $row[3];\r
+\r
+       return $new_row;\r
+}\r
+\r
+function scorm_1_2_org_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0]  = $row[0];\r
+       $new_row[1]  = $table_id_map['packages'][$row[1]]; // package_id fk\r
+       $new_row[2]  = $row[2];\r
+       $new_row[3]  = $row[3];\r
+       $new_row[4]  = $row[4];\r
+\r
+       return $new_row;\r
+}\r
+\r
+function scorm_1_2_item_convert($row, $course_id, $table_id_map, $version) {\r
+       $new_row = array();\r
+       $new_row[0]  = $row[0];\r
+       $new_row[1]  = $table_id_map['scorm_1_2_org'][$row[1]]; // org_id fk\r
+       $new_row[2]  = $row[2];\r
+       $new_row[3]  = $row[3];\r
+       $new_row[4]  = $row[4];\r
+       $new_row[5]  = $row[5];\r
+       $new_row[6]  = $row[6];\r
+       $new_row[7]  = $row[7];\r
+       $new_row[8]  = $row[8];\r
+       $new_row[9]  = $row[9];\r
+       $new_row[10]  = $row[10];\r
+\r
+       return $new_row;\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/my_stats.php b/my_stats.php
new file mode 100644 (file)
index 0000000..a527613
--- /dev/null
@@ -0,0 +1,61 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', './include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+?>\r
+<table class="data static" rules="cols" summary="">\r
+<thead>\r
+<tr>\r
+       <th scope="col"><?php echo _AT('page'); ?></th>\r
+       <th scope="col"><?php echo _AT('visits'); ?></th>\r
+       <th scope="col"><?php echo _AT('duration'); ?></th>\r
+       <th scope="col"><?php echo _AT('last_accessed'); ?></th>\r
+</tr>\r
+</thead>\r
+<tbody>\r
+<?php\r
+       $sql = "SELECT content_id, COUNT(*) AS unique_hits, SUM(counter) AS total_hits, SEC_TO_TIME(SUM(duration)/SUM(counter)) AS average_duration, SEC_TO_TIME(SUM(duration)) AS total_duration, last_accessed FROM ".TABLE_PREFIX."member_track WHERE course_id=$_SESSION[course_id] AND member_id=$_SESSION[member_id] GROUP BY content_id ORDER BY total_hits DESC";\r
+\r
+       $result = mysql_query($sql, $db);\r
+\r
+       if (mysql_num_rows($result) > 0) {\r
+               while ($row = mysql_fetch_assoc($result)) {\r
+                       if ($row['total'] == '') {\r
+                               $row['total'] = _AT('na');\r
+                       }\r
+\r
+                       echo '<tr>';\r
+                       echo '<td><a href='.AT_BASE_HREF.url_rewrite('content.php?cid='.$row['content_id']). '>' . $contentManager->_menu_info[$row['content_id']]['title'] . '</a></td>';\r
+                       echo '<td>' . $row['total_hits'] . '</td>';\r
+                       echo '<td>' . $row['total_duration'] . '</td>';\r
+                       if ($row['last_accessed'] == '') {\r
+                               echo '<td>' . _AT('na') . '</td>';\r
+                       } else {\r
+                               echo '<td>' . AT_date(_AT('forum_date_format'), $row['last_accessed'], AT_DATE_MYSQL_DATETIME) . '</td>';\r
+                       }\r
+                       echo '</tr>';\r
+               } //end while\r
+\r
+               echo '</tbody>';\r
+\r
+       } else {\r
+               echo '<tr><td colspan="4">' . _AT('none_found') . '</td></tr>';\r
+               echo '</tbody>';\r
+       }\r
+       ?>\r
+</tbody>\r
+</table>\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/overlib.js b/overlib.js
new file mode 100644 (file)
index 0000000..a6239ad
--- /dev/null
@@ -0,0 +1,1274 @@
+//\//////////////////////////////////////////////////////////////////////////////////
+//\  overLIB 3.51  --  This notice must remain untouched at all times.
+//\  Copyright Erik Bosrup 1998-2002. All rights reserved.
+//\
+//\  By Erik Bosrup (erik@bosrup.com).  Last modified 2002-11-01.
+//\  Portions by Dan Steinman (dansteinman.com). Additions by other people are
+//\  listed on the overLIB homepage.
+//\
+//\  Get the latest version at http://www.bosrup.com/web/overlib/
+//\
+//\  This script is published under an open source license. Please read the license
+//\  agreement online at: http://www.bosrup.com/web/overlib/license.html
+//\  If you have questions regarding the license please contact erik@bosrup.com.
+//\
+//\  This script library was originally created for personal use. By request it has
+//\  later been made public. This is free software. Do not sell this as your own
+//\  work, or remove this copyright notice. For full details on copying or changing
+//\  this script please read the license agreement at the link above.
+//\
+//\  Please give credit on sites that use overLIB and submit changes of the script
+//\  so other people can use them as well. This script is free to use, don't abuse.
+//\//////////////////////////////////////////////////////////////////////////////////
+//\mini
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// CONSTANTS
+// Don't touch these. :)
+////////////////////////////////////////////////////////////////////////////////////
+var INARRAY            =       1;
+var CAPARRAY           =       2;
+var STICKY             =       3;
+var BACKGROUND         =       4;
+var NOCLOSE            =       5;
+var CAPTION            =       6;
+var LEFT               =       7;
+var RIGHT              =       8;
+var CENTER             =       9;
+var OFFSETX            =       10;
+var OFFSETY            =       11;
+var FGCOLOR            =       12;
+var BGCOLOR            =       13;
+var TEXTCOLOR          =       14;
+var CAPCOLOR           =       15;
+var CLOSECOLOR         =       16;
+var WIDTH              =       17;
+var BORDER             =       18;
+var STATUS             =       19;
+var AUTOSTATUS         =       20;
+var AUTOSTATUSCAP      =       21;
+var HEIGHT             =       22;
+var CLOSETEXT          =       23;
+var SNAPX              =       24;
+var SNAPY              =       25;
+var FIXX               =       26;
+var FIXY               =       27;
+var FGBACKGROUND       =       28;
+var BGBACKGROUND       =       29;
+var PADX               =       30; // PADX2 out
+var PADY               =       31; // PADY2 out
+var FULLHTML           =       34;
+var ABOVE              =       35;
+var BELOW              =       36;
+var CAPICON            =       37;
+var TEXTFONT           =       38;
+var CAPTIONFONT                =       39;
+var CLOSEFONT          =       40;
+var TEXTSIZE           =       41;
+var CAPTIONSIZE                =       42;
+var CLOSESIZE          =       43;
+var FRAME              =       44;
+var TIMEOUT            =       45;
+var FUNCTION           =       46;
+var DELAY              =       47;
+var HAUTO              =       48;
+var VAUTO              =       49;
+var CLOSECLICK         =       50;
+var CSSOFF             =       51;
+var CSSSTYLE           =       52;
+var CSSCLASS           =       53;
+var FGCLASS            =       54;
+var BGCLASS            =       55;
+var TEXTFONTCLASS      =       56;
+var CAPTIONFONTCLASS   =       57;
+var CLOSEFONTCLASS     =       58;
+var PADUNIT            =       59;
+var HEIGHTUNIT         =       60;
+var WIDTHUNIT          =       61;
+var TEXTSIZEUNIT       =       62;
+var TEXTDECORATION     =       63;
+var TEXTSTYLE          =       64;
+var TEXTWEIGHT         =       65;
+var CAPTIONSIZEUNIT    =       66;
+var CAPTIONDECORATION  =       67;
+var CAPTIONSTYLE       =       68;
+var CAPTIONWEIGHT      =       69;
+var CLOSESIZEUNIT      =       70;
+var CLOSEDECORATION    =       71;
+var CLOSESTYLE         =       72;
+var CLOSEWEIGHT                =       73;
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// DEFAULT CONFIGURATION
+// You don't have to change anything here if you don't want to. All of this can be
+// changed on your html page or through an overLIB call.
+////////////////////////////////////////////////////////////////////////////////////
+
+// Main background color (the large area)
+// Usually a bright color (white, yellow etc)
+if (typeof ol_fgcolor == 'undefined') { var ol_fgcolor = "#CCCCFF";}
+       
+// Border color and color of caption
+// Usually a dark color (black, brown etc)
+if (typeof ol_bgcolor == 'undefined') { var ol_bgcolor = "#333399";}
+       
+// Text color
+// Usually a dark color
+if (typeof ol_textcolor == 'undefined') { var ol_textcolor = "#000000";}
+       
+// Color of the caption text
+// Usually a bright color
+if (typeof ol_capcolor == 'undefined') { var ol_capcolor = "#FFFFFF";}
+       
+// Color of "Close" when using Sticky
+// Usually a semi-bright color
+if (typeof ol_closecolor == 'undefined') { var ol_closecolor = "#9999FF";}
+
+// Font face for the main text
+if (typeof ol_textfont == 'undefined') { var ol_textfont = "Verdana,Arial,Helvetica";}
+
+// Font face for the caption
+if (typeof ol_captionfont == 'undefined') { var ol_captionfont = "Verdana,Arial,Helvetica";}
+
+// Font face for the close text
+if (typeof ol_closefont == 'undefined') { var ol_closefont = "Verdana,Arial,Helvetica";}
+
+// Font size for the main text
+// When using CSS this will be very small.
+if (typeof ol_textsize == 'undefined') { var ol_textsize = "1";}
+
+// Font size for the caption
+// When using CSS this will be very small.
+if (typeof ol_captionsize == 'undefined') { var ol_captionsize = "1";}
+
+// Font size for the close text
+// When using CSS this will be very small.
+if (typeof ol_closesize == 'undefined') { var ol_closesize = "1";}
+
+// Width of the popups in pixels
+// 100-300 pixels is typical
+if (typeof ol_width == 'undefined') { var ol_width = "250";}
+
+// How thick the ol_border should be in pixels
+// 1-3 pixels is typical
+if (typeof ol_border == 'undefined') { var ol_border = "1";}
+
+// How many pixels to the right/left of the cursor to show the popup
+// Values between 3 and 12 are best
+if (typeof ol_offsetx == 'undefined') { var ol_offsetx = 10;}
+       
+// How many pixels to the below the cursor to show the popup
+// Values between 3 and 12 are best
+if (typeof ol_offsety == 'undefined') { var ol_offsety = 10;}
+
+// Default text for popups
+// Should you forget to pass something to overLIB this will be displayed.
+if (typeof ol_text == 'undefined') { var ol_text = "Default Text"; }
+
+// Default caption
+// You should leave this blank or you will have problems making non caps popups.
+if (typeof ol_cap == 'undefined') { var ol_cap = ""; }
+
+// Decides if sticky popups are default.
+// 0 for non, 1 for stickies.
+if (typeof ol_sticky == 'undefined') { var ol_sticky = 0; }
+
+// Default background image. Better left empty unless you always want one.
+if (typeof ol_background == 'undefined') { var ol_background = ""; }
+
+// Text for the closing sticky popups.
+// Normal is "Close".
+if (typeof ol_close == 'undefined') { var ol_close = "Close"; }
+
+// Default vertical alignment for popups.
+// It's best to leave RIGHT here. Other options are LEFT and CENTER.
+if (typeof ol_hpos == 'undefined') { var ol_hpos = RIGHT; }
+
+// Default status bar text when a popup is invoked.
+if (typeof ol_status == 'undefined') { var ol_status = ""; }
+
+// If the status bar automatically should load either text or caption.
+// 0=nothing, 1=text, 2=caption
+if (typeof ol_autostatus == 'undefined') { var ol_autostatus = 0; }
+
+// Default height for popup. Often best left alone.
+if (typeof ol_height == 'undefined') { var ol_height = -1; }
+
+// Horizontal grid spacing that popups will snap to.
+// 0 makes no grid, anything else will cause a snap to that grid spacing.
+if (typeof ol_snapx == 'undefined') { var ol_snapx = 0; }
+
+// Vertical grid spacing that popups will snap to.
+// 0 makes no grid, andthing else will cause a snap to that grid spacing.
+if (typeof ol_snapy == 'undefined') { var ol_snapy = 0; }
+
+// Sets the popups horizontal position to a fixed column.
+// Anything above -1 will cause fixed position.
+if (typeof ol_fixx == 'undefined') { var ol_fixx = -1; }
+
+// Sets the popups vertical position to a fixed row.
+// Anything above -1 will cause fixed position.
+if (typeof ol_fixy == 'undefined') { var ol_fixy = -1; }
+
+// Background image for the popups inside.
+if (typeof ol_fgbackground == 'undefined') { var ol_fgbackground = ""; }
+
+// Background image for the popups frame.
+if (typeof ol_bgbackground == 'undefined') { var ol_bgbackground = ""; }
+
+// How much horizontal left padding text should get by default when BACKGROUND is used.
+if (typeof ol_padxl == 'undefined') { var ol_padxl = 1; }
+
+// How much horizontal right padding text should get by default when BACKGROUND is used.
+if (typeof ol_padxr == 'undefined') { var ol_padxr = 1; }
+
+// How much vertical top padding text should get by default when BACKGROUND is used.
+if (typeof ol_padyt == 'undefined') { var ol_padyt = 1; }
+
+// How much vertical bottom padding text should get by default when BACKGROUND is used.
+if (typeof ol_padyb == 'undefined') { var ol_padyb = 1; }
+
+// If the user by default must supply all html for complete popup control.
+// Set to 1 to activate, 0 otherwise.
+if (typeof ol_fullhtml == 'undefined') { var ol_fullhtml = 0; }
+
+// Default vertical position of the popup. Default should normally be BELOW.
+// ABOVE only works when HEIGHT is defined.
+if (typeof ol_vpos == 'undefined') { var ol_vpos = BELOW; }
+
+// Default height of popup to use when placing the popup above the cursor.
+if (typeof ol_aboveheight == 'undefined') { var ol_aboveheight = 0; }
+
+// Default icon to place next to the popups caption.
+if (typeof ol_capicon == 'undefined') { var ol_capicon = ""; }
+
+// Default frame. We default to current frame if there is no frame defined.
+if (typeof ol_frame == 'undefined') { var ol_frame = self; }
+
+// Default timeout. By default there is no timeout.
+if (typeof ol_timeout == 'undefined') { var ol_timeout = 0; }
+
+// Default javascript funktion. By default there is none.
+if (typeof ol_function == 'undefined') { var ol_function = null; }
+
+// Default timeout. By default there is no timeout.
+if (typeof ol_delay == 'undefined') { var ol_delay = 0; }
+
+// If overLIB should decide the horizontal placement.
+if (typeof ol_hauto == 'undefined') { var ol_hauto = 0; }
+
+// If overLIB should decide the vertical placement.
+if (typeof ol_vauto == 'undefined') { var ol_vauto = 0; }
+
+
+
+// If the user has to click to close stickies.
+if (typeof ol_closeclick == 'undefined') { var ol_closeclick = 0; }
+
+// This variable determines if you want to use CSS or inline definitions.
+// CSSOFF=no CSS    CSSSTYLE=use CSS inline styles    CSSCLASS=use classes
+if (typeof ol_css == 'undefined') { var ol_css = CSSOFF; }
+
+// Main background class (eqv of fgcolor)
+// This is only used if CSS is set to use classes (ol_css = CSSCLASS)
+if (typeof ol_fgclass == 'undefined') { var ol_fgclass = ""; }
+
+// Frame background class (eqv of bgcolor)
+// This is only used if CSS is set to use classes (ol_css = CSSCLASS)
+if (typeof ol_bgclass == 'undefined') { var ol_bgclass = ""; }
+
+// Main font class
+// This is only used if CSS is set to use classes (ol_css = CSSCLASS)
+if (typeof ol_textfontclass == 'undefined') { var ol_textfontclass = ""; }
+
+// Caption font class
+// This is only used if CSS is set to use classes (ol_css = CSSCLASS)
+if (typeof ol_captionfontclass == 'undefined') { var ol_captionfontclass = ""; }
+
+// Close font class
+// This is only used if CSS is set to use classes (ol_css = CSSCLASS)
+if (typeof ol_closefontclass == 'undefined') { var ol_closefontclass = ""; }
+
+// Unit to be used for the text padding above
+// Only used if CSS inline styles are being used (ol_css = CSSSTYLE)
+// Options include "px", "%", "in", "cm"
+if (typeof ol_padunit == 'undefined') { var ol_padunit = "px";}
+
+// Unit to be used for height of popup
+// Only used if CSS inline styles are being used (ol_css = CSSSTYLE)
+// Options include "px", "%", "in", "cm"
+if (typeof ol_heightunit == 'undefined') { var ol_heightunit = "px";}
+
+// Unit to be used for width of popup
+// Only used if CSS inline styles are being used (ol_css = CSSSTYLE)
+// Options include "px", "%", "in", "cm"
+if (typeof ol_widthunit == 'undefined') { var ol_widthunit = "px";}
+
+// Font size unit for the main text
+// Only used if CSS inline styles are being used (ol_css = CSSSTYLE)
+if (typeof ol_textsizeunit == 'undefined') { var ol_textsizeunit = "px";}
+
+// Decoration of the main text ("none", "underline", "line-through" or "blink")
+// Only used if CSS inline styles are being used (ol_css = CSSSTYLE)
+if (typeof ol_textdecoration == 'undefined') { var ol_textdecoration = "none";}
+
+// Font style of the main text ("normal" or "italic")
+// Only used if CSS inline styles are being used (ol_css = CSSSTYLE)
+if (typeof ol_textstyle == 'undefined') { var ol_textstyle = "normal";}
+
+// Font weight of the main text ("normal", "bold", "bolder", "lighter", ect.)
+// Only used if CSS inline styles are being used (ol_css = CSSSTYLE)
+if (typeof ol_textweight == 'undefined') { var ol_textweight = "normal";}
+
+// Font size unit for the caption
+// Only used if CSS inline styles are being used (ol_css = CSSSTYLE)
+if (typeof ol_captionsizeunit == 'undefined') { var ol_captionsizeunit = "px";}
+
+// Decoration of the caption ("none", "underline", "line-through" or "blink")
+// Only used if CSS inline styles are being used (ol_css = CSSSTYLE)
+if (typeof ol_captiondecoration == 'undefined') { var ol_captiondecoration = "none";}
+
+// Font style of the caption ("normal" or "italic")
+// Only used if CSS inline styles are being used (ol_css = CSSSTYLE)
+if (typeof ol_captionstyle == 'undefined') { var ol_captionstyle = "normal";}
+
+// Font weight of the caption ("normal", "bold", "bolder", "lighter", ect.)
+// Only used if CSS inline styles are being used (ol_css = CSSSTYLE)
+if (typeof ol_captionweight == 'undefined') { var ol_captionweight = "bold";}
+
+// Font size unit for the close text
+// Only used if CSS inline styles are being used (ol_css = CSSSTYLE)
+if (typeof ol_closesizeunit == 'undefined') { var ol_closesizeunit = "px";}
+
+// Decoration of the close text ("none", "underline", "line-through" or "blink")
+// Only used if CSS inline styles are being used (ol_css = CSSSTYLE)
+if (typeof ol_closedecoration == 'undefined') { var ol_closedecoration = "none";}
+
+// Font style of the close text ("normal" or "italic")
+// Only used if CSS inline styles are being used (ol_css = CSSSTYLE)
+if (typeof ol_closestyle == 'undefined') { var ol_closestyle = "normal";}
+
+// Font weight of the close text ("normal", "bold", "bolder", "lighter", ect.)
+// Only used if CSS inline styles are being used (ol_css = CSSSTYLE)
+if (typeof ol_closeweight == 'undefined') { var ol_closeweight = "normal";}
+
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// ARRAY CONFIGURATION
+// You don't have to change anything here if you don't want to. The following
+// arrays can be filled with text and html if you don't wish to pass it from
+// your html page.
+////////////////////////////////////////////////////////////////////////////////////
+
+// Array with texts.
+if (typeof ol_texts == 'undefined') { var ol_texts = new Array("Text 0", "Text 1"); }
+
+// Array with captions.
+if (typeof ol_caps == 'undefined') { var ol_caps = new Array("Caption 0", "Caption 1"); }
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// END CONFIGURATION
+// Don't change anything below this line, all configuration is above.
+////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// INIT
+////////////////////////////////////////////////////////////////////////////////////
+
+// Runtime variables init. Used for runtime only, don't change, not for config!
+var o3_text = "";
+var o3_cap = "";
+var o3_sticky = 0;
+var o3_background = "";
+var o3_close = "Close";
+var o3_hpos = RIGHT;
+var o3_offsetx = 2;
+var o3_offsety = 2;
+var o3_fgcolor = "";
+var o3_bgcolor = "";
+var o3_textcolor = "";
+var o3_capcolor = "";
+var o3_closecolor = "";
+var o3_width = 100;
+var o3_border = 1;
+var o3_status = "";
+var o3_autostatus = 0;
+var o3_height = -1;
+var o3_snapx = 0;
+var o3_snapy = 0;
+var o3_fixx = -1;
+var o3_fixy = -1;
+var o3_fgbackground = "";
+var o3_bgbackground = "";
+var o3_padxl = 0;
+var o3_padxr = 0;
+var o3_padyt = 0;
+var o3_padyb = 0;
+var o3_fullhtml = 0;
+var o3_vpos = BELOW;
+var o3_aboveheight = 0;
+var o3_capicon = "";
+var o3_textfont = "Verdana,Arial,Helvetica";
+var o3_captionfont = "Verdana,Arial,Helvetica";
+var o3_closefont = "Verdana,Arial,Helvetica";
+var o3_textsize = "1";
+var o3_captionsize = "1";
+var o3_closesize = "1";
+var o3_frame = self;
+var o3_timeout = 0;
+var o3_timerid = 0;
+var o3_allowmove = 0;
+var o3_function = null; 
+var o3_delay = 0;
+var o3_delayid = 0;
+var o3_hauto = 0;
+var o3_vauto = 0;
+var o3_closeclick = 0;
+
+var o3_css = CSSOFF;
+var o3_fgclass = "";
+var o3_bgclass = "";
+var o3_textfontclass = "";
+var o3_captionfontclass = "";
+var o3_closefontclass = "";
+var o3_padunit = "px";
+var o3_heightunit = "px";
+var o3_widthunit = "px";
+var o3_textsizeunit = "px";
+var o3_textdecoration = "";
+var o3_textstyle = "";
+var o3_textweight = "";
+var o3_captionsizeunit = "px";
+var o3_captiondecoration = "";
+var o3_captionstyle = "";
+var o3_captionweight = "";
+var o3_closesizeunit = "px";
+var o3_closedecoration = "";
+var o3_closestyle = "";
+var o3_closeweight = "";
+
+
+
+// Display state variables
+var o3_x = 0;
+var o3_y = 0;
+var o3_allow = 0;
+var o3_showingsticky = 0;
+var o3_removecounter = 0;
+
+// Our layer
+var over = null;
+var fnRef;
+
+// Decide browser version
+var ns4 = (navigator.appName == 'Netscape' && parseInt(navigator.appVersion) == 4);
+var ns6 = (document.getElementById)? true:false;
+var ie4 = (document.all)? true:false;
+if (ie4) var docRoot = 'document.body';
+var ie5 = false;
+if (ns4) {
+       var oW = window.innerWidth;
+       var oH = window.innerHeight;
+       window.onresize = function () {if (oW!=window.innerWidth||oH!=window.innerHeight) location.reload();}
+}
+
+
+// Microsoft Stupidity Check(tm).
+if (ie4) {
+       if ((navigator.userAgent.indexOf('MSIE 5') > 0) || (navigator.userAgent.indexOf('MSIE 6') > 0)) {
+               if(document.compatMode && document.compatMode == 'CSS1Compat') docRoot = 'document.documentElement';
+               ie5 = true;
+       }
+       if (ns6) {
+               ns6 = false;
+       }
+}
+
+
+// Capture events, alt. diffuses the overlib function.
+if ( (ns4) || (ie4) || (ns6)) {
+       document.onmousemove = mouseMove
+       if (ns4) document.captureEvents(Event.MOUSEMOVE)
+} else {
+       overlib = no_overlib;
+       nd = no_overlib;
+       ver3fix = true;
+}
+
+
+// Fake function for 3.0 users.
+function no_overlib() {
+       return ver3fix;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC FUNCTIONS
+////////////////////////////////////////////////////////////////////////////////////
+
+
+// overlib(arg0, ..., argN)
+// Loads parameters into global runtime variables.
+function overlib() {
+       
+       // Load defaults to runtime.
+       o3_text = ol_text;
+       o3_cap = ol_cap;
+       o3_sticky = ol_sticky;
+       o3_background = ol_background;
+       o3_close = ol_close;
+       o3_hpos = ol_hpos;
+       o3_offsetx = ol_offsetx;
+       o3_offsety = ol_offsety;
+       o3_fgcolor = ol_fgcolor;
+       o3_bgcolor = ol_bgcolor;
+       o3_textcolor = ol_textcolor;
+       o3_capcolor = ol_capcolor;
+       o3_closecolor = ol_closecolor;
+       o3_width = ol_width;
+       o3_border = ol_border;
+       o3_status = ol_status;
+       o3_autostatus = ol_autostatus;
+       o3_height = ol_height;
+       o3_snapx = ol_snapx;
+       o3_snapy = ol_snapy;
+       o3_fixx = ol_fixx;
+       o3_fixy = ol_fixy;
+       o3_fgbackground = ol_fgbackground;
+       o3_bgbackground = ol_bgbackground;
+       o3_padxl = ol_padxl;
+       o3_padxr = ol_padxr;
+       o3_padyt = ol_padyt;
+       o3_padyb = ol_padyb;
+       o3_fullhtml = ol_fullhtml;
+       o3_vpos = ol_vpos;
+       o3_aboveheight = ol_aboveheight;
+       o3_capicon = ol_capicon;
+       o3_textfont = ol_textfont;
+       o3_captionfont = ol_captionfont;
+       o3_closefont = ol_closefont;
+       o3_textsize = ol_textsize;
+       o3_captionsize = ol_captionsize;
+       o3_closesize = ol_closesize;
+       o3_timeout = ol_timeout;
+       o3_function = ol_function;
+       o3_delay = ol_delay;
+       o3_hauto = ol_hauto;
+       o3_vauto = ol_vauto;
+       o3_closeclick = ol_closeclick;
+       
+       o3_css = ol_css;
+       o3_fgclass = ol_fgclass;
+       o3_bgclass = ol_bgclass;
+       o3_textfontclass = ol_textfontclass;
+       o3_captionfontclass = ol_captionfontclass;
+       o3_closefontclass = ol_closefontclass;
+       o3_padunit = ol_padunit;
+       o3_heightunit = ol_heightunit;
+       o3_widthunit = ol_widthunit;
+       o3_textsizeunit = ol_textsizeunit;
+       o3_textdecoration = ol_textdecoration;
+       o3_textstyle = ol_textstyle;
+       o3_textweight = ol_textweight;
+       o3_captionsizeunit = ol_captionsizeunit;
+       o3_captiondecoration = ol_captiondecoration;
+       o3_captionstyle = ol_captionstyle;
+       o3_captionweight = ol_captionweight;
+       o3_closesizeunit = ol_closesizeunit;
+       o3_closedecoration = ol_closedecoration;
+       o3_closestyle = ol_closestyle;
+       o3_closeweight = ol_closeweight;
+       fnRef = '';
+       
+
+       // Special for frame support, over must be reset...
+       if ( (ns4) || (ie4) || (ns6) ) {
+               if (over) cClick();
+               o3_frame = ol_frame;
+               if (ns4) over = o3_frame.document.overDiv
+               if (ie4) over = o3_frame.overDiv.style
+               if (ns6) over = o3_frame.document.getElementById("overDiv");
+       }
+       
+       
+       // What the next argument is expected to be.
+       var parsemode = -1, udf, v = null;
+       
+       var ar = arguments;
+       udf = (!ar.length ? 1 : 0);
+
+       for (i = 0; i < ar.length; i++) {
+
+               if (parsemode < 0) {
+                       // Arg is maintext, unless its a PARAMETER
+                       if (typeof ar[i] == 'number') {
+                               udf = (ar[i] == FUNCTION ? 0 : 1);
+                               i--;
+                       } else {
+                               o3_text = ar[i];
+                       }
+
+                       parsemode = 0;
+               } else {
+                       // Note: NS4 doesn't like switch cases with vars.
+                       if (ar[i] == INARRAY) { udf = 0; o3_text = ol_texts[ar[++i]]; continue; }
+                       if (ar[i] == CAPARRAY) { o3_cap = ol_caps[ar[++i]]; continue; }
+                       if (ar[i] == STICKY) { o3_sticky = 1; continue; }
+                       if (ar[i] == BACKGROUND) { o3_background = ar[++i]; continue; }
+                       if (ar[i] == NOCLOSE) { o3_close = ""; continue; }
+                       if (ar[i] == CAPTION) { o3_cap = ar[++i]; continue; }
+                       if (ar[i] == CENTER || ar[i] == LEFT || ar[i] == RIGHT) { o3_hpos = ar[i]; continue; }
+                       if (ar[i] == OFFSETX) { o3_offsetx = ar[++i]; continue; }
+                       if (ar[i] == OFFSETY) { o3_offsety = ar[++i]; continue; }
+                       if (ar[i] == FGCOLOR) { o3_fgcolor = ar[++i]; continue; }
+                       if (ar[i] == BGCOLOR) { o3_bgcolor = ar[++i]; continue; }
+                       if (ar[i] == TEXTCOLOR) { o3_textcolor = ar[++i]; continue; }
+                       if (ar[i] == CAPCOLOR) { o3_capcolor = ar[++i]; continue; }
+                       if (ar[i] == CLOSECOLOR) { o3_closecolor = ar[++i]; continue; }
+                       if (ar[i] == WIDTH) { o3_width = ar[++i]; continue; }
+                       if (ar[i] == BORDER) { o3_border = ar[++i]; continue; }
+                       if (ar[i] == STATUS) { o3_status = ar[++i]; continue; }
+                       if (ar[i] == AUTOSTATUS) { o3_autostatus = (o3_autostatus == 1) ? 0 : 1; continue; }
+                       if (ar[i] == AUTOSTATUSCAP) { o3_autostatus = (o3_autostatus == 2) ? 0 : 2; continue; }
+                       if (ar[i] == HEIGHT) { o3_height = ar[++i]; o3_aboveheight = ar[i]; continue; } // Same param again.
+                       if (ar[i] == CLOSETEXT) { o3_close = ar[++i]; continue; }
+                       if (ar[i] == SNAPX) { o3_snapx = ar[++i]; continue; }
+                       if (ar[i] == SNAPY) { o3_snapy = ar[++i]; continue; }
+                       if (ar[i] == FIXX) { o3_fixx = ar[++i]; continue; }
+                       if (ar[i] == FIXY) { o3_fixy = ar[++i]; continue; }
+                       if (ar[i] == FGBACKGROUND) { o3_fgbackground = ar[++i]; continue; }
+                       if (ar[i] == BGBACKGROUND) { o3_bgbackground = ar[++i]; continue; }
+                       if (ar[i] == PADX) { o3_padxl = ar[++i]; o3_padxr = ar[++i]; continue; }
+                       if (ar[i] == PADY) { o3_padyt = ar[++i]; o3_padyb = ar[++i]; continue; }
+                       if (ar[i] == FULLHTML) { o3_fullhtml = 1; continue; }
+                       if (ar[i] == BELOW || ar[i] == ABOVE) { o3_vpos = ar[i]; continue; }
+                       if (ar[i] == CAPICON) { o3_capicon = ar[++i]; continue; }
+                       if (ar[i] == TEXTFONT) { o3_textfont = ar[++i]; continue; }
+                       if (ar[i] == CAPTIONFONT) { o3_captionfont = ar[++i]; continue; }
+                       if (ar[i] == CLOSEFONT) { o3_closefont = ar[++i]; continue; }
+                       if (ar[i] == TEXTSIZE) { o3_textsize = ar[++i]; continue; }
+                       if (ar[i] == CAPTIONSIZE) { o3_captionsize = ar[++i]; continue; }
+                       if (ar[i] == CLOSESIZE) { o3_closesize = ar[++i]; continue; }
+                       if (ar[i] == FRAME) { opt_FRAME(ar[++i]); continue; }
+                       if (ar[i] == TIMEOUT) { o3_timeout = ar[++i]; continue; }
+                       if (ar[i] == FUNCTION) { udf = 0; if (typeof ar[i+1] != 'number') v = ar[++i]; opt_FUNCTION(v); continue; } 
+                       if (ar[i] == DELAY) { o3_delay = ar[++i]; continue; }
+                       if (ar[i] == HAUTO) { o3_hauto = (o3_hauto == 0) ? 1 : 0; continue; }
+                       if (ar[i] == VAUTO) { o3_vauto = (o3_vauto == 0) ? 1 : 0; continue; }
+                       if (ar[i] == CLOSECLICK) { o3_closeclick = (o3_closeclick == 0) ? 1 : 0; continue; }
+                       if (ar[i] == CSSOFF) { o3_css = ar[i]; continue; }
+                       if (ar[i] == CSSSTYLE) { o3_css = ar[i]; continue; }
+                       if (ar[i] == CSSCLASS) { o3_css = ar[i]; continue; }
+                       if (ar[i] == FGCLASS) { o3_fgclass = ar[++i]; continue; }
+                       if (ar[i] == BGCLASS) { o3_bgclass = ar[++i]; continue; }
+                       if (ar[i] == TEXTFONTCLASS) { o3_textfontclass = ar[++i]; continue; }
+                       if (ar[i] == CAPTIONFONTCLASS) { o3_captionfontclass = ar[++i]; continue; }
+                       if (ar[i] == CLOSEFONTCLASS) { o3_closefontclass = ar[++i]; continue; }
+                       if (ar[i] == PADUNIT) { o3_padunit = ar[++i]; continue; }
+                       if (ar[i] == HEIGHTUNIT) { o3_heightunit = ar[++i]; continue; }
+                       if (ar[i] == WIDTHUNIT) { o3_widthunit = ar[++i]; continue; }
+                       if (ar[i] == TEXTSIZEUNIT) { o3_textsizeunit = ar[++i]; continue; }
+                       if (ar[i] == TEXTDECORATION) { o3_textdecoration = ar[++i]; continue; }
+                       if (ar[i] == TEXTSTYLE) { o3_textstyle = ar[++i]; continue; }
+                       if (ar[i] == TEXTWEIGHT) { o3_textweight = ar[++i]; continue; }
+                       if (ar[i] == CAPTIONSIZEUNIT) { o3_captionsizeunit = ar[++i]; continue; }
+                       if (ar[i] == CAPTIONDECORATION) { o3_captiondecoration = ar[++i]; continue; }
+                       if (ar[i] == CAPTIONSTYLE) { o3_captionstyle = ar[++i]; continue; }
+                       if (ar[i] == CAPTIONWEIGHT) { o3_captionweight = ar[++i]; continue; }
+                       if (ar[i] == CLOSESIZEUNIT) { o3_closesizeunit = ar[++i]; continue; }
+                       if (ar[i] == CLOSEDECORATION) { o3_closedecoration = ar[++i]; continue; }
+                       if (ar[i] == CLOSESTYLE) { o3_closestyle = ar[++i]; continue; }
+                       if (ar[i] == CLOSEWEIGHT) { o3_closeweight = ar[++i]; continue; }
+               }
+       }
+       if (udf && o3_function) o3_text = o3_function();
+
+       if (o3_delay == 0) {
+               return overlib351();
+       } else {
+               o3_delayid = setTimeout("overlib351()", o3_delay);
+               return false;
+       }
+}
+
+
+
+// Clears popups if appropriate
+function nd() {
+       if ( o3_removecounter >= 1 ) { o3_showingsticky = 0 };
+       if ( (ns4) || (ie4) || (ns6) ) {
+               if ( o3_showingsticky == 0 ) {
+                       o3_allowmove = 0;
+                       if (over != null) hideObject(over);
+               } else {
+                       o3_removecounter++;
+               }
+       }
+       
+       return true;
+}
+
+
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// OVERLIB 3.51 FUNCTION
+////////////////////////////////////////////////////////////////////////////////////
+
+
+// This function decides what it is we want to display and how we want it done.
+function overlib351() {
+
+       // Make layer content
+       var layerhtml;
+
+       if (o3_background != "" || o3_fullhtml) {
+               // Use background instead of box.
+               layerhtml = ol_content_background(o3_text, o3_background, o3_fullhtml);
+       } else {
+               // They want a popup box.
+
+               // Prepare popup background
+               if (o3_fgbackground != "" && o3_css == CSSOFF) {
+                       o3_fgbackground = "BACKGROUND=\""+o3_fgbackground+"\"";
+               }
+               if (o3_bgbackground != "" && o3_css == CSSOFF) {
+                       o3_bgbackground = "BACKGROUND=\""+o3_bgbackground+"\"";
+               }
+
+               // Prepare popup colors
+               if (o3_fgcolor != "" && o3_css == CSSOFF) {
+                       o3_fgcolor = "BGCOLOR=\""+o3_fgcolor+"\"";
+               }
+               if (o3_bgcolor != "" && o3_css == CSSOFF) {
+                       o3_bgcolor = "BGCOLOR=\""+o3_bgcolor+"\"";
+               }
+
+               // Prepare popup height
+               if (o3_height > 0 && o3_css == CSSOFF) {
+                       o3_height = "HEIGHT=" + o3_height;
+               } else {
+                       o3_height = "";
+               }
+
+               // Decide which kinda box.
+               if (o3_cap == "") {
+                       // Plain
+                       layerhtml = ol_content_simple(o3_text);
+               } else {
+                       // With caption
+                       if (o3_sticky) {
+                               // Show close text
+                               layerhtml = ol_content_caption(o3_text, o3_cap, o3_close);
+                       } else {
+                               // No close text
+                               layerhtml = ol_content_caption(o3_text, o3_cap, "");
+                       }
+               }
+       }
+       
+       // We want it to stick!
+       if (o3_sticky) {
+               if (o3_timerid > 0) {
+                       clearTimeout(o3_timerid);
+                       o3_timerid = 0;
+               }
+               o3_showingsticky = 1;
+               o3_removecounter = 0;
+       }
+       
+       // Write layer
+       layerWrite(layerhtml);
+       
+       // Prepare status bar
+       if (o3_autostatus > 0) {
+               o3_status = o3_text;
+               if (o3_autostatus > 1) {
+                       o3_status = o3_cap;
+               }
+       }
+
+       // When placing the layer the first time, even stickies may be moved.
+       o3_allowmove = 0;
+
+       // Initiate a timer for timeout
+       if (o3_timeout > 0) {
+               if (o3_timerid > 0) clearTimeout(o3_timerid);
+               o3_timerid = setTimeout("cClick()", o3_timeout);
+       }
+
+       // Show layer
+       disp(o3_status);
+
+       // Stickies should stay where they are. 
+       if (o3_sticky) o3_allowmove = 0;
+
+       return (o3_status != '');
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// LAYER GENERATION FUNCTIONS
+////////////////////////////////////////////////////////////////////////////////////
+
+// Makes simple table without caption
+function ol_content_simple(text) {
+       if (o3_css == CSSCLASS) txt = "<TABLE WIDTH="+o3_width+" BORDER=0 CELLPADDING="+o3_border+" CELLSPACING=0 class=\""+o3_bgclass+"\"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 class=\""+o3_fgclass+"\"><TR><TD VALIGN=TOP><FONT class=\""+o3_textfontclass+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+       if (o3_css == CSSSTYLE) txt = "<TABLE WIDTH="+o3_width+" BORDER=0 CELLPADDING="+o3_border+" CELLSPACING=0 style=\"background-color: "+o3_bgcolor+"; height: "+o3_height+o3_heightunit+";\"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 style=\"color: "+o3_fgcolor+"; background-color: "+o3_fgcolor+"; height: "+o3_height+o3_heightunit+";\"><TR><TD VALIGN=TOP><FONT style=\"font-family: "+o3_textfont+"; color: "+o3_textcolor+"; font-size: "+o3_textsize+o3_textsizeunit+"; text-decoration: "+o3_textdecoration+"; font-weight: "+o3_textweight+"; font-style:"+o3_textstyle+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+       if (o3_css == CSSOFF) txt = "<TABLE WIDTH="+o3_width+" BORDER=0 CELLPADDING="+o3_border+" CELLSPACING=0 "+o3_bgcolor+" "+o3_height+"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 "+o3_fgcolor+" "+o3_fgbackground+" "+o3_height+"><TR><TD VALIGN=TOP><FONT FACE=\""+o3_textfont+"\" COLOR=\""+o3_textcolor+"\" SIZE=\""+o3_textsize+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+
+       set_background("");
+       return txt;
+}
+
+
+
+
+// Makes table with caption and optional close link
+function ol_content_caption(text, title, close) {
+       closing = "";
+       closeevent = "onMouseOver";
+
+       if (o3_closeclick == 1) closeevent = "onClick";
+       if (o3_capicon != "") o3_capicon = "<IMG SRC=\""+o3_capicon+"\"> ";
+
+       if (close != "") {
+               if (o3_css == CSSCLASS) closing = "<TD ALIGN=RIGHT><A HREF=\"javascript:return "+fnRef+"cClick();\" "+closeevent+"=\"return " + fnRef + "cClick();\" class=\""+o3_closefontclass+"\">"+close+"</A></TD>";
+               if (o3_css == CSSSTYLE) closing = "<TD ALIGN=RIGHT><A HREF=\"javascript:return "+fnRef+"cClick();\" "+closeevent+"=\"return " + fnRef + "cClick();\" style=\"color: "+o3_closecolor+"; font-family: "+o3_closefont+"; font-size: "+o3_closesize+o3_closesizeunit+"; text-decoration: "+o3_closedecoration+"; font-weight: "+o3_closeweight+"; font-style:"+o3_closestyle+";\">"+close+"</A></TD>";
+               if (o3_css == CSSOFF) closing = "<TD ALIGN=RIGHT><A HREF=\"javascript:return "+fnRef+"cClick();\" "+closeevent+"=\"return " + fnRef + "cClick();\"><FONT COLOR=\""+o3_closecolor+"\" FACE=\""+o3_closefont+"\" SIZE=\""+o3_closesize+"\">"+close+"</FONT></A></TD>";
+       }
+
+       if (o3_css == CSSCLASS) txt = "<TABLE WIDTH="+o3_width+" BORDER=0 CELLPADDING="+o3_border+" CELLSPACING=0 class=\""+o3_bgclass+"\"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=0 CELLSPACING=0><TR><TD><FONT class=\""+o3_captionfontclass+"\">"+o3_capicon+title+"</FONT></TD>"+closing+"</TR></TABLE><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 class=\""+o3_fgclass+"\"><TR><TD VALIGN=TOP><FONT class=\""+o3_textfontclass+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+       if (o3_css == CSSSTYLE) txt = "<TABLE WIDTH="+o3_width+" BORDER=0 CELLPADDING="+o3_border+" CELLSPACING=0 style=\"background-color: "+o3_bgcolor+"; background-image: url("+o3_bgbackground+"); height: "+o3_height+o3_heightunit+";\"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=0 CELLSPACING=0><TR><TD><FONT style=\"font-family: "+o3_captionfont+"; color: "+o3_capcolor+"; font-size: "+o3_captionsize+o3_captionsizeunit+"; font-weight: "+o3_captionweight+"; font-style: "+o3_captionstyle+"; text-decoration: " + o3_captiondecoration + ";\">"+o3_capicon+title+"</FONT></TD>"+closing+"</TR></TABLE><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 style=\"color: "+o3_fgcolor+"; background-color: "+o3_fgcolor+"; height: "+o3_height+o3_heightunit+";\"><TR><TD VALIGN=TOP><FONT style=\"font-family: "+o3_textfont+"; color: "+o3_textcolor+"; font-size: "+o3_textsize+o3_textsizeunit+"; text-decoration: "+o3_textdecoration+"; font-weight: "+o3_textweight+"; font-style:"+o3_textstyle+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+       if (o3_css == CSSOFF) txt = "<TABLE WIDTH="+o3_width+" BORDER=0 CELLPADDING="+o3_border+" CELLSPACING=0 "+o3_bgcolor+" "+o3_bgbackground+" "+o3_height+"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=0 CELLSPACING=0><TR><TD><B><FONT COLOR=\""+o3_capcolor+"\" FACE=\""+o3_captionfont+"\" SIZE=\""+o3_captionsize+"\">"+o3_capicon+title+"</FONT></B></TD>"+closing+"</TR></TABLE><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 "+o3_fgcolor+" "+o3_fgbackground+" "+o3_height+"><TR><TD VALIGN=TOP><FONT COLOR=\""+o3_textcolor+"\" FACE=\""+o3_textfont+"\" SIZE=\""+o3_textsize+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+
+       set_background("");
+       return txt;
+}
+
+// Sets the background picture, padding and lots more. :)
+function ol_content_background(text, picture, hasfullhtml) {
+       var txt;
+       if (hasfullhtml) {
+               txt = text;
+       } else {
+               var pU, hU, wU;
+               pU = (o3_padunit == '%' ? '%' : '');
+               hU = (o3_heightunit == '%' ? '%' : '');
+               wU = (o3_widthunit == '%' ? '%' : '');
+
+               if (o3_css == CSSCLASS) txt = "<TABLE WIDTH="+o3_width+" BORDER=0 CELLPADDING=0 CELLSPACING=0 HEIGHT="+o3_height+"><TR><TD COLSPAN=3 HEIGHT="+o3_padyt+"></TD></TR><TR><TD WIDTH="+o3_padxl+"></TD><TD VALIGN=TOP WIDTH="+(o3_width-o3_padxl-o3_padxr)+"><FONT class=\""+o3_textfontclass+"\">"+text+"</FONT></TD><TD WIDTH="+o3_padxr+"></TD></TR><TR><TD COLSPAN=3 HEIGHT="+o3_padyb+"></TD></TR></TABLE>";
+               if (o3_css == CSSSTYLE) txt = "<TABLE WIDTH="+o3_width+wU+" BORDER=0 CELLPADDING=0 CELLSPACING=0 HEIGHT="+o3_height+hU+"><TR><TD COLSPAN=3 HEIGHT="+o3_padyt+pU+"></TD></TR><TR><TD WIDTH="+o3_padxl+pU+"></TD><TD VALIGN=TOP WIDTH="+(o3_width-o3_padxl-o3_padxr)+pU+"><FONT style=\"font-family: "+o3_textfont+"; color: "+o3_textcolor+"; font-size: "+o3_textsize+o3_textsizeunit+";\">"+text+"</FONT></TD><TD WIDTH="+o3_padxr+pU+"></TD></TR><TR><TD COLSPAN=3 HEIGHT="+o3_padyb+pU+"></TD></TR></TABLE>";
+               if (o3_css == CSSOFF) txt = "<TABLE WIDTH="+o3_width+" BORDER=0 CELLPADDING=0 CELLSPACING=0 HEIGHT="+o3_height+"><TR><TD COLSPAN=3 HEIGHT="+o3_padyt+"></TD></TR><TR><TD WIDTH="+o3_padxl+"></TD><TD VALIGN=TOP WIDTH="+(o3_width-o3_padxl-o3_padxr)+"><FONT FACE=\""+o3_textfont+"\" COLOR=\""+o3_textcolor+"\" SIZE=\""+o3_textsize+"\">"+text+"</FONT></TD><TD WIDTH="+o3_padxr+"></TD></TR><TR><TD COLSPAN=3 HEIGHT="+o3_padyb+"></TD></TR></TABLE>";
+       }
+       set_background(picture);
+       return txt;
+}
+
+// Loads a picture into the div.
+function set_background(pic) {
+       if (pic == "") {
+               if (ns4) over.background.src = null;
+               if (ie4) over.backgroundImage = "none";
+               if (ns6) over.style.backgroundImage = "none";
+       } else {
+               if (ns4) {
+                       over.background.src = pic;
+               } else if (ie4) {
+                       over.backgroundImage = "url("+pic+")";
+               } else if (ns6) {
+                       over.style.backgroundImage = "url("+pic+")";
+               }
+       }
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// HANDLING FUNCTIONS
+////////////////////////////////////////////////////////////////////////////////////
+
+
+// Displays the popup
+function disp(statustext) {
+       if ( (ns4) || (ie4) || (ns6) ) {
+               if (o3_allowmove == 0)  {
+                       placeLayer();
+                       showObject(over);
+                       o3_allowmove = 1;
+               }
+       }
+
+       if (statustext != "") {
+               self.status = statustext;
+       }
+}
+
+// Decides where we want the popup.
+function placeLayer() {
+       var placeX, placeY;
+       
+       // HORIZONTAL PLACEMENT
+       if (o3_fixx > -1) {
+               // Fixed position
+               placeX = o3_fixx;
+       } else {
+               winoffset = (ie4) ? eval('o3_frame.'+docRoot+'.scrollLeft') : o3_frame.pageXOffset;
+               if (ie4) iwidth = eval('o3_frame.'+docRoot+'.clientWidth');
+               if (ns4 || ns6) iwidth = o3_frame.innerWidth;
+               
+               // If HAUTO, decide what to use.
+               if (o3_hauto == 1) {
+                       if ( (o3_x - winoffset) > ((eval(iwidth)) / 2)) {
+                               o3_hpos = LEFT;
+                       } else {
+                               o3_hpos = RIGHT;
+                       }
+               }
+               
+               // From mouse
+               if (o3_hpos == CENTER) { // Center
+                       placeX = o3_x+o3_offsetx-(o3_width/2);
+                       if (placeX < winoffset) placeX = winoffset;
+               }
+               if (o3_hpos == RIGHT) { // Right
+                       placeX = o3_x+o3_offsetx;
+                       if ( (eval(placeX) + eval(o3_width)) > (winoffset + iwidth) ) {
+                               placeX = iwidth + winoffset - o3_width;
+                               if (placeX < 0) placeX = 0;
+                       }
+               }
+               if (o3_hpos == LEFT) { // Left
+                       placeX = o3_x-o3_offsetx-o3_width;
+                       if (placeX < winoffset) placeX = winoffset;
+               }
+       
+               // Snapping!
+               if (o3_snapx > 1) {
+                       var snapping = placeX % o3_snapx;
+                       if (o3_hpos == LEFT) {
+                               placeX = placeX - (o3_snapx + snapping);
+                       } else {
+                               // CENTER and RIGHT
+                               placeX = placeX + (o3_snapx - snapping);
+                       }
+                       if (placeX < winoffset) placeX = winoffset;
+               }
+       }
+
+       
+       
+       // VERTICAL PLACEMENT
+       if (o3_fixy > -1) {
+               // Fixed position
+               placeY = o3_fixy;
+       } else {
+               scrolloffset = (ie4) ? eval('o3_frame.'+docRoot+'.scrollTop') : o3_frame.pageYOffset;
+
+               // If VAUTO, decide what to use.
+               if (o3_vauto == 1) {
+                       if (ie4) iheight = eval('o3_frame.'+docRoot+'.clientHeight');
+                       if (ns4 || ns6) iheight = o3_frame.innerHeight;
+
+                       iheight = (eval(iheight)) / 2;
+                       if ( (o3_y - scrolloffset) > iheight) {
+                               o3_vpos = ABOVE;
+                       } else {
+                               o3_vpos = BELOW;
+                       }
+               }
+
+
+               // From mouse
+               if (o3_vpos == ABOVE) {
+                       if (o3_aboveheight == 0) {
+                               var divref = (ie4) ? o3_frame.document.all['overDiv'] : over;
+                               o3_aboveheight = (ns4) ? divref.clip.height : divref.offsetHeight;
+                       }
+
+                       placeY = o3_y - (o3_aboveheight + o3_offsety);
+                       if (placeY < scrolloffset) placeY = scrolloffset;
+               } else {
+                       // BELOW
+                       placeY = o3_y + o3_offsety;
+               }
+
+               // Snapping!
+               if (o3_snapy > 1) {
+                       var snapping = placeY % o3_snapy;
+                       
+                       if (o3_aboveheight > 0 && o3_vpos == ABOVE) {
+                               placeY = placeY - (o3_snapy + snapping);
+                       } else {
+                               placeY = placeY + (o3_snapy - snapping);
+                       }
+                       
+                       if (placeY < scrolloffset) placeY = scrolloffset;
+               }
+       }
+
+
+       // Actually move the object.    
+       repositionTo(over, placeX, placeY);
+}
+
+
+// Moves the layer
+function mouseMove(e) {
+       if ( (ns4) || (ns6) ) {o3_x=e.pageX; o3_y=e.pageY;}
+       if (ie4) {o3_x=event.x; o3_y=event.y;}
+       if (ie5) {o3_x=eval('event.x+o3_frame.'+docRoot+'.scrollLeft'); o3_y=eval('event.y+o3_frame.'+docRoot+'.scrollTop');}
+       
+       if (o3_allowmove == 1) {
+               placeLayer();
+       }
+}
+
+// The Close onMouseOver function for stickies
+function cClick() {
+       hideObject(over);
+       o3_showingsticky = 0;
+       
+       return false;
+}
+
+
+// Makes sure target frame has overLIB
+function compatibleframe(frameid) {
+       if (ns4) {
+               if (typeof frameid.document.overDiv =='undefined') return false;
+       } else if (ie4) {
+               if (typeof frameid.document.all["overDiv"] =='undefined') return false;
+       } else if (ns6) {
+               if (frameid.document.getElementById('overDiv') == null) return false;
+       }
+
+       return true;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// LAYER FUNCTIONS
+////////////////////////////////////////////////////////////////////////////////////
+
+
+// Writes to a layer
+function layerWrite(txt) {
+       txt += "\n";
+       
+       if (ns4) {
+               var lyr = o3_frame.document.overDiv.document
+               lyr.write(txt)
+               lyr.close()
+       } else if (ie4) {
+               o3_frame.document.all["overDiv"].innerHTML = txt
+       } else if (ns6) {
+               range = o3_frame.document.createRange();
+               range.setStartBefore(over);
+               domfrag = range.createContextualFragment(txt);
+               while (over.hasChildNodes()) {
+                       over.removeChild(over.lastChild);
+               }
+               over.appendChild(domfrag);
+       }
+}
+
+// Make an object visible
+function showObject(obj) {
+       if (ns4) obj.visibility = "show";
+       else if (ie4) obj.visibility = "visible";
+       else if (ns6) obj.style.visibility = "visible";
+}
+
+// Hides an object
+function hideObject(obj) {
+       if (ns4) obj.visibility = "hide";
+       else if (ie4) obj.visibility = "hidden";
+       else if (ns6) obj.style.visibility = "hidden";
+
+       if (o3_timerid > 0) clearTimeout(o3_timerid);
+       if (o3_delayid > 0) clearTimeout(o3_delayid);
+       o3_timerid = 0;
+       o3_delayid = 0;
+       self.status = "";
+}
+
+// Move a layer
+function repositionTo(obj,xL,yL) {
+       if ( (ns4) || (ie4) ) {
+               obj.left = (ie4 ? xL + 'px' : xL);
+               obj.top = (ie4 ? yL + 'px' : yL);
+       } else if (ns6) {
+               obj.style.left = xL + "px";
+               obj.style.top = yL+ "px";
+       }
+}
+
+function getFrameRef(thisFrame, ofrm) {
+       var retVal = '';
+       for (var i=0; i<thisFrame.length; i++) {
+               if (thisFrame[i].length > 0) { 
+                       retVal = getFrameRef(thisFrame[i],ofrm);
+                       if (retVal == '') continue;
+               } else if (thisFrame[i] != ofrm) continue;
+               
+               retVal = '['+i+']' + retVal;
+               break;
+       }
+       
+       return retVal;
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// PARSER FUNCTIONS
+////////////////////////////////////////////////////////////////////////////////////
+
+
+// Defines which frame we should point to.
+function opt_FRAME(frm) {
+       o3_frame = compatibleframe(frm) ? frm : ol_frame;
+
+       if (o3_frame != ol_frame) {
+               var tFrm = getFrameRef(top.frames, o3_frame);
+               var sFrm = getFrameRef(top.frames, ol_frame);
+
+               if (sFrm.length == tFrm.length) { 
+                       l = tFrm.lastIndexOf('['); 
+                       if (l) {
+                               while(sFrm.substring(0,l) != tFrm.substring(0,l)) l = tFrm.lastIndexOf('[',l-1);
+                               tFrm = tFrm.substr(l);
+                               sFrm = sFrm.substr(l);
+                       }
+               }
+                       
+               var cnt = 0, p = '', str = tFrm;
+                       
+               while((k = str.lastIndexOf('[')) != -1) {
+                       cnt++;
+                       str = str.substring(0,k);
+               }
+
+               for (var i=0; i<cnt; i++) p = p + 'parent.';
+               fnRef = p + 'frames' + sFrm + '.';
+       }
+
+       if ( (ns4) || (ie4 || (ns6)) ) {
+               if (ns4) over = o3_frame.document.overDiv;
+               if (ie4) over = o3_frame.overDiv.style;
+               if (ns6) over = o3_frame.document.getElementById("overDiv");
+       }
+
+       return 0;
+}
+
+// Calls an external function
+function opt_FUNCTION(callme) {
+       o3_text = (callme ? callme() : (o3_function ? o3_function() : 'No Function'));
+       return 0;
+}
+
+
+
+
+//end (For internal purposes.)
+////////////////////////////////////////////////////////////////////////////////////
+// OVERLIB 2 COMPATABILITY FUNCTIONS
+// If you aren't upgrading you can remove the below section.
+////////////////////////////////////////////////////////////////////////////////////
+
+// Converts old 0=left, 1=right and 2=center into constants.
+function vpos_convert(d) {
+       if (d == 0) {
+               d = LEFT;
+       } else {
+               if (d == 1) {
+                       d = RIGHT;
+               } else {
+                       d = CENTER;
+               }
+       }
+       
+       return d;
+}
+
+// Simple popup
+function dts(d,text) {
+       o3_hpos = vpos_convert(d);
+       overlib(text, o3_hpos, CAPTION, "");
+}
+
+// Caption popup
+function dtc(d,text, title) {
+       o3_hpos = vpos_convert(d);
+       overlib(text, CAPTION, title, o3_hpos);
+}
+
+// Sticky
+function stc(d,text, title) {
+       o3_hpos = vpos_convert(d);
+       overlib(text, CAPTION, title, o3_hpos, STICKY);
+}
+
+// Simple popup right
+function drs(text) {
+       dts(1,text);
+}
+
+// Caption popup right
+function drc(text, title) {
+       dtc(1,text,title);
+}
+
+// Sticky caption right
+function src(text,title) {
+       stc(1,text,title);
+}
+
+// Simple popup left
+function dls(text) {
+       dts(0,text);
+}
+
+// Caption popup left
+function dlc(text, title) {
+       dtc(0,text,title);
+}
+
+// Sticky caption left
+function slc(text,title) {
+       stc(0,text,title);
+}
+
+// Simple popup center
+function dcs(text) {
+       dts(2,text);
+}
+
+// Caption popup center
+function dcc(text, title) {
+       dtc(2,text,title);
+}
+
+// Sticky caption center
+function scc(text,title) {
+       stc(2,text,title);
+}
diff --git a/overlib_mini.js b/overlib_mini.js
new file mode 100644 (file)
index 0000000..da81179
--- /dev/null
@@ -0,0 +1,709 @@
+//\//////////////////////////////////////////////////////////////////////////////////
+//\  overLIB 3.50  --  This notice must remain untouched at all times.
+//\  Copyright Erik Bosrup 1998-2001. All rights reserved.
+//\
+//\  By Erik Bosrup (erik@bosrup.com).  Last modified 2001-08-28.
+//\  Portions by Dan Steinman (dansteinman.com). Additions by other people are
+//\  listed on the overLIB homepage.
+//\
+//\  Get the latest version at http://www.bosrup.com/web/overlib/
+//\
+//\  This script is published under an open source license. Please read the license
+//\  agreement online at: http://www.bosrup.com/web/overlib/license.html
+//\  If you have questions regarding the license please contact erik@bosrup.com.
+//\
+//\  This script library was originally created for personal use. By request it has
+//\  later been made public. This is free software. Do not sell this as your own
+//\  work, or remove this copyright notice. For full details on copying or changing
+//\  this script please read the license agreement at the link above.
+//\
+//\  Please give credit on sites that use overLIB and submit changes of the script
+//\  so other people can use them as well. This script is free to use, don't abuse.
+//\//////////////////////////////////////////////////////////////////////////////////
+
+//\  THIS IS A VERY MODIFIED VERSION. DO NOT EDIT OR PUBLISH. GET THE ORIGINAL!
+
+var INARRAY=1;
+var CAPARRAY=2;
+var STICKY=3;
+var BACKGROUND=4;
+var NOCLOSE=5;
+var CAPTION=6;
+var LEFT=7;
+var RIGHT=8;
+var CENTER=9;
+var OFFSETX=10;
+var OFFSETY=11;
+var FGCOLOR=12;
+var BGCOLOR=13;
+var TEXTCOLOR=14;
+var CAPCOLOR=15;
+var CLOSECOLOR=16;
+var WIDTH=17;
+var BORDER=18;
+var STATUS=19;
+var AUTOSTATUS=20;
+var AUTOSTATUSCAP=21;
+var HEIGHT=22;
+var CLOSETEXT=23;
+var SNAPX=24;
+var SNAPY=25;
+var FIXX=26;
+var FIXY=27;
+var FGBACKGROUND=28;
+var BGBACKGROUND=29;
+var PADX=30;// PADX2 out
+var PADY=31;// PADY2 out
+var FULLHTML=34;
+var ABOVE=35;
+var BELOW=36;
+var CAPICON=37;
+var TEXTFONT=38;
+var CAPTIONFONT=39;
+var CLOSEFONT=40;
+var TEXTSIZE=41;
+var CAPTIONSIZE=42;
+var CLOSESIZE=43;
+var FRAME=44;
+var TIMEOUT=45;
+var FUNCTION=46;
+var DELAY=47;
+var HAUTO=48;
+var VAUTO=49;
+var CLOSECLICK=50;
+var CSSOFF=51;
+var CSSSTYLE=52;
+var CSSCLASS=53;
+var FGCLASS=54;
+var BGCLASS=55;
+var TEXTFONTCLASS=56;
+var CAPTIONFONTCLASS=57;
+var CLOSEFONTCLASS=58;
+var PADUNIT=59;
+var HEIGHTUNIT=60;
+var WIDTHUNIT=61;
+var TEXTSIZEUNIT=62;
+var TEXTDECORATION=63;
+var TEXTSTYLE=64;
+var TEXTWEIGHT=65;
+var CAPTIONSIZEUNIT=66;
+var CAPTIONDECORATION=67;
+var CAPTIONSTYLE=68;
+var CAPTIONWEIGHT=69;
+var CLOSESIZEUNIT=70;
+var CLOSEDECORATION=71;
+var CLOSESTYLE=72;
+var CLOSEWEIGHT=73;
+if(typeof ol_fgcolor=='undefined'){var ol_fgcolor="#CCCCFF";}
+if(typeof ol_bgcolor=='undefined'){var ol_bgcolor="#333399";}
+if(typeof ol_textcolor=='undefined'){var ol_textcolor="#000000";}
+if(typeof ol_capcolor=='undefined'){var ol_capcolor="#FFFFFF";}
+if(typeof ol_closecolor=='undefined'){var ol_closecolor="#9999FF";}
+if(typeof ol_textfont=='undefined'){var ol_textfont="Verdana,Arial,Helvetica";}
+if(typeof ol_captionfont=='undefined'){var ol_captionfont="Verdana,Arial,Helvetica";}
+if(typeof ol_closefont=='undefined'){var ol_closefont="Verdana,Arial,Helvetica";}
+if(typeof ol_textsize=='undefined'){var ol_textsize="1";}
+if(typeof ol_captionsize=='undefined'){var ol_captionsize="1";}
+if(typeof ol_closesize=='undefined'){var ol_closesize="1";}
+if(typeof ol_width=='undefined'){var ol_width="200";}
+if(typeof ol_border=='undefined'){var ol_border="1";}
+if(typeof ol_offsetx=='undefined'){var ol_offsetx=10;}
+if(typeof ol_offsety=='undefined'){var ol_offsety=10;}
+if(typeof ol_text=='undefined'){var ol_text="Default Text";}
+if(typeof ol_cap=='undefined'){var ol_cap="";}
+if(typeof ol_sticky=='undefined'){var ol_sticky=0;}
+if(typeof ol_background=='undefined'){var ol_background="";}
+if(typeof ol_close=='undefined'){var ol_close="Close";}
+if(typeof ol_hpos=='undefined'){var ol_hpos=8;}
+if(typeof ol_status=='undefined'){var ol_status="";}
+if(typeof ol_autostatus=='undefined'){var ol_autostatus=0;}
+if(typeof ol_height=='undefined'){var ol_height=-1;}
+if(typeof ol_snapx=='undefined'){var ol_snapx=0;}
+if(typeof ol_snapy=='undefined'){var ol_snapy=0;}
+if(typeof ol_fixx=='undefined'){var ol_fixx=-1;}
+if(typeof ol_fixy=='undefined'){var ol_fixy=-1;}
+if(typeof ol_fgbackground=='undefined'){var ol_fgbackground="";}
+if(typeof ol_bgbackground=='undefined'){var ol_bgbackground="";}
+if(typeof ol_padxl=='undefined'){var ol_padxl=1;}
+if(typeof ol_padxr=='undefined'){var ol_padxr=1;}
+if(typeof ol_padyt=='undefined'){var ol_padyt=1;}
+if(typeof ol_padyb=='undefined'){var ol_padyb=1;}
+if(typeof ol_fullhtml=='undefined'){var ol_fullhtml=0;}
+if(typeof ol_vpos=='undefined'){var ol_vpos=36;}
+if(typeof ol_aboveheight=='undefined'){var ol_aboveheight=0;}
+if(typeof ol_caption=='undefined'){var ol_capicon="";}
+if(typeof ol_frame=='undefined'){var ol_frame=self;}
+if(typeof ol_timeout=='undefined'){var ol_timeout=0;}
+if(typeof ol_function=='undefined'){var ol_function=Function();}
+if(typeof ol_delay=='undefined'){var ol_delay=0;}
+if(typeof ol_hauto=='undefined'){var ol_hauto=0;}
+if(typeof ol_vauto=='undefined'){var ol_vauto=0;}
+if(typeof ol_closeclick=='undefined'){var ol_closeclick=0;}
+if(typeof ol_css=='undefined'){var ol_css=51;}
+if(typeof ol_fgclass=='undefined'){var ol_fgclass="";}
+if(typeof ol_bgclass=='undefined'){var ol_bgclass="";}
+if(typeof ol_textfontclass=='undefined'){var ol_textfontclass="";}
+if(typeof ol_captionfontclass=='undefined'){var ol_captionfontclass="";}
+if(typeof ol_closefontclass=='undefined'){var ol_closefontclass="";}
+if(typeof ol_padunit=='undefined'){var ol_padunit="px";}
+if(typeof ol_heightunit=='undefined'){var ol_heightunit="px";}
+if(typeof ol_widthunit=='undefined'){var ol_widthunit="px";}
+if(typeof ol_textsizeunit=='undefined'){var ol_textsizeunit="px";}
+if(typeof ol_textdecoration=='undefined'){var ol_textdecoration="none";}
+if(typeof ol_textstyle=='undefined'){var ol_textstyle="normal";}
+if(typeof ol_textweight=='undefined'){var ol_textweight="normal";}
+if(typeof ol_captionsizeunit=='undefined'){var ol_captionsizeunit="px";}
+if(typeof ol_captiondecoration=='undefined'){var ol_captiondecoration="none";}
+if(typeof ol_captionstyle=='undefined'){var ol_captionstyle="normal";}
+if(typeof ol_captionweight=='undefined'){var ol_captionweight="bold";}
+if(typeof ol_closesizeunit=='undefined'){var ol_closesizeunit="px";}
+if(typeof ol_closedecoration=='undefined'){var ol_closedecoration="none";}
+if(typeof ol_closestyle=='undefined'){var ol_closestyle="normal";}
+if(typeof ol_closeweight=='undefined'){var ol_closeweight="normal";}
+if(typeof ol_texts=='undefined'){var ol_texts=new Array("Text 0", "Text 1");}
+if(typeof ol_caps=='undefined'){var ol_caps=new Array("Caption 0", "Caption 1");}
+var otext="";
+var ocap="";
+var osticky=0;
+var obackground="";
+var oclose="Close";
+var ohpos=8;
+var ooffsetx=2;
+var ooffsety=2;
+var ofgcolor="";
+var obgcolor="";
+var otextcolor="";
+var ocapcolor="";
+var oclosecolor="";
+var owidth=100;
+var oborder=1;
+var ostatus="";
+var oautostatus=0;
+var oheight=-1;
+var osnapx=0;
+var osnapy=0;
+var ofixx=-1;
+var ofixy=-1;
+var ofgbackground="";
+var obgbackground="";
+var opadxl=0;
+var opadxr=0;
+var opadyt=0;
+var opadyb=0;
+var ofullhtml=0;
+var ovpos=36;
+var oaboveheight=0;
+var ocapicon="";
+var otextfont="Verdana,Arial,Helvetica";
+var ocaptionfont="Verdana,Arial,Helvetica";
+var oclosefont="Verdana,Arial,Helvetica";
+var otextsize="1";
+var ocaptionsize="1";
+var oclosesize="1";
+var oframe=self;
+var otimeout=0;
+var otimerid=0;
+var oallowmove=0;
+var ofunction=Function();
+var odelay=0;
+var odelayid=0;
+var ohauto=0;
+var ovauto=0;
+var ocloseclick=0;
+var ocss=51;
+var ofgclass="";
+var obgclass="";
+var otextfontclass="";
+var ocaptionfontclass="";
+var oclosefontclass="";
+var opadunit="px";
+var oheightunit="px";
+var owidthunit="px";
+var otextsizeunit="px";
+var otextdecoration="";
+var otextstyle="";
+var otextweight="";
+var ocaptionsizeunit="px";
+var ocaptiondecoration="";
+var ocaptionstyle="";
+var ocaptionweight="";
+var oclosesizeunit="px";
+var oclosedecoration="";
+var oclosestyle="";
+var ocloseweight="";
+var ox=0;
+var oy=0;
+var oallow=0;
+var oshowingsticky=0;
+var oremovecounter=0;
+var over=null;
+var ns4=(document.layers)? true:false;
+var ns6=(document.getElementById)? true:false;
+var ie4=(document.all)? true:false;
+var ie5=false;
+if(ie4){
+if((navigator.userAgent.indexOf('MSIE 5')> 0)||(navigator.userAgent.indexOf('MSIE 6')> 0)){
+ie5=true;
+}
+if(ns6){
+ns6=false;
+}
+}
+if((ns4)||(ie4)||(ns6)){
+document.onmousemove=mouseMove
+if(ns4)document.captureEvents(Event.MOUSEMOVE)
+}else{
+overlib=no_overlib;
+nd=no_overlib;
+ver3fix=true;
+}
+function no_overlib(){
+return ver3fix;
+}
+function overlib(){
+otext=ol_text;
+ocap=ol_cap;
+osticky=ol_sticky;
+obackground=ol_background;
+oclose=ol_close;
+ohpos=ol_hpos;
+ooffsetx=ol_offsetx;
+ooffsety=ol_offsety;
+ofgcolor=ol_fgcolor;
+obgcolor=ol_bgcolor;
+otextcolor=ol_textcolor;
+ocapcolor=ol_capcolor;
+oclosecolor=ol_closecolor;
+owidth=ol_width;
+oborder=ol_border;
+ostatus=ol_status;
+oautostatus=ol_autostatus;
+oheight=ol_height;
+osnapx=ol_snapx;
+osnapy=ol_snapy;
+ofixx=ol_fixx;
+ofixy=ol_fixy;
+ofgbackground=ol_fgbackground;
+obgbackground=ol_bgbackground;
+opadxl=ol_padxl;
+opadxr=ol_padxr;
+opadyt=ol_padyt;
+opadyb=ol_padyb;
+ofullhtml=ol_fullhtml;
+ovpos=ol_vpos;
+oaboveheight=ol_aboveheight;
+ocapicon=ol_capicon;
+otextfont=ol_textfont;
+ocaptionfont=ol_captionfont;
+oclosefont=ol_closefont;
+otextsize=ol_textsize;
+ocaptionsize=ol_captionsize;
+oclosesize=ol_closesize;
+otimeout=ol_timeout;
+ofunction=ol_function;
+odelay=ol_delay;
+ohauto=ol_hauto;
+ovauto=ol_vauto;
+ocloseclick=ol_closeclick;
+ocss=ol_css;
+ofgclass=ol_fgclass;
+obgclass=ol_bgclass;
+otextfontclass=ol_textfontclass;
+ocaptionfontclass=ol_captionfontclass;
+oclosefontclass=ol_closefontclass;
+opadunit=ol_padunit;
+oheightunit=ol_heightunit;
+owidthunit=ol_widthunit;
+otextsizeunit=ol_textsizeunit;
+otextdecoration=ol_textdecoration;
+otextstyle=ol_textstyle;
+otextweight=ol_textweight;
+ocaptionsizeunit=ol_captionsizeunit;
+ocaptiondecoration=ol_captiondecoration;
+ocaptionstyle=ol_captionstyle;
+ocaptionweight=ol_captionweight;
+oclosesizeunit=ol_closesizeunit;
+oclosedecoration=ol_closedecoration;
+oclosestyle=ol_closestyle;
+ocloseweight=ol_closeweight;
+if((ns4)||(ie4)||(ns6)){
+oframe=ol_frame;
+if(ns4)over=oframe.document.overDiv
+if(ie4)over=oframe.overDiv.style
+if(ns6)over=oframe.document.getElementById("overDiv");
+}
+var c=-1;
+var ar=arguments;
+for(i=0;i < ar.length;i++){
+if(c < 0){
+if(ar[i]==1){
+otext=ol_texts[ar[++i]];
+}else{
+otext=ar[i];
+}
+c=0;
+}else{
+if(ar[i]==1){otext=ol_texts[ar[++i]];continue;}
+if(ar[i]==2){ocap=ol_caps[ar[++i]];continue;}
+if(ar[i]==3){osticky=1;continue;}
+if(ar[i]==4){obackground=ar[++i];continue;}
+if(ar[i]==NOCLOSE){oclose="";continue;}
+if(ar[i]==6){ocap=ar[++i];continue;}
+if(ar[i]==9 || ar[i]==7 || ar[i]==8){ohpos=ar[i];continue;}
+if(ar[i]==10){ooffsetx=ar[++i];continue;}
+if(ar[i]==11){ooffsety=ar[++i];continue;}
+if(ar[i]==12){ofgcolor=ar[++i];continue;}
+if(ar[i]==13){obgcolor=ar[++i];continue;}
+if(ar[i]==14){otextcolor=ar[++i];continue;}
+if(ar[i]==15){ocapcolor=ar[++i];continue;}
+if(ar[i]==16){oclosecolor=ar[++i];continue;}
+if(ar[i]==17){owidth=ar[++i];continue;}
+if(ar[i]==18){oborder=ar[++i];continue;}
+if(ar[i]==19){ostatus=ar[++i];continue;}
+if(ar[i]==20){oautostatus=1;continue;}
+if(ar[i]==21){oautostatus=2;continue;}
+if(ar[i]==22){oheight=ar[++i];oaboveheight=ar[i];continue;}// Same param again.
+if(ar[i]==23){oclose=ar[++i];continue;}
+if(ar[i]==24){osnapx=ar[++i];continue;}
+if(ar[i]==25){osnapy=ar[++i];continue;}
+if(ar[i]==26){ofixx=ar[++i];continue;}
+if(ar[i]==27){ofixy=ar[++i];continue;}
+if(ar[i]==28){ofgbackground=ar[++i];continue;}
+if(ar[i]==29){obgbackground=ar[++i];continue;}
+if(ar[i]==30){opadxl=ar[++i];opadxr=ar[++i];continue;}
+if(ar[i]==31){opadyt=ar[++i];opadyb=ar[++i];continue;}
+if(ar[i]==34){ofullhtml=1;continue;}
+if(ar[i]==36 || ar[i]==35){ovpos=ar[i];continue;}
+if(ar[i]==37){ocapicon=ar[++i];continue;}
+if(ar[i]==38){otextfont=ar[++i];continue;}
+if(ar[i]==39){ocaptionfont=ar[++i];continue;}
+if(ar[i]==40){oclosefont=ar[++i];continue;}
+if(ar[i]==41){otextsize=ar[++i];continue;}
+if(ar[i]==42){ocaptionsize=ar[++i];continue;}
+if(ar[i]==43){oclosesize=ar[++i];continue;}
+if(ar[i]==44){opt_FRAME(ar[++i]);continue;}
+if(ar[i]==45){otimeout=ar[++i];continue;}
+if(ar[i]==46){opt_FUNCTION(ar[++i]);continue;}
+if(ar[i]==47){odelay=ar[++i];continue;}
+if(ar[i]==48){ohauto=(ohauto==0)? 1 : 0;continue;}
+if(ar[i]==49){ovauto=(ovauto==0)? 1 : 0;continue;}
+if(ar[i]==50){ocloseclick=(ocloseclick==0)? 1 : 0;continue;}
+if(ar[i]==51){ocss=ar[i];continue;}
+if(ar[i]==52){ocss=ar[i];continue;}
+if(ar[i]==53){ocss=ar[i];continue;}
+if(ar[i]==54){ofgclass=ar[++i];continue;}
+if(ar[i]==55){obgclass=ar[++i];continue;}
+if(ar[i]==56){otextfontclass=ar[++i];continue;}
+if(ar[i]==57){ocaptionfontclass=ar[++i];continue;}
+if(ar[i]==58){oclosefontclass=ar[++i];continue;}
+if(ar[i]==59){opadunit=ar[++i];continue;}
+if(ar[i]==60){oheightunit=ar[++i];continue;}
+if(ar[i]==61){owidthunit=ar[++i];continue;}
+if(ar[i]==62){otextsizeunit=ar[++i];continue;}
+if(ar[i]==63){otextdecoration=ar[++i];continue;}
+if(ar[i]==64){otextstyle=ar[++i];continue;}
+if(ar[i]==65){otextweight=ar[++i];continue;}
+if(ar[i]==66){ocaptionsizeunit=ar[++i];continue;}
+if(ar[i]==67){ocaptiondecoration=ar[++i];continue;}
+if(ar[i]==68){ocaptionstyle=ar[++i];continue;}
+if(ar[i]==69){ocaptionweight=ar[++i];continue;}
+if(ar[i]==70){oclosesizeunit=ar[++i];continue;}
+if(ar[i]==71){oclosedecoration=ar[++i];continue;}
+if(ar[i]==72){oclosestyle=ar[++i];continue;}
+if(ar[i]==73){ocloseweight=ar[++i];continue;}
+}
+}
+if(odelay==0){
+return overlib350();
+}else{
+odelayid=setTimeout("overlib350()", odelay);
+if(osticky){
+return false;
+}else{
+return true;
+}
+}
+}
+function nd(){
+if(oremovecounter >=1){oshowingsticky=0};
+if((ns4)||(ie4)||(ns6)){
+if(oshowingsticky==0){
+oallowmove=0;
+if(over !=null)hideObject(over);
+}else{
+oremovecounter++;
+}
+}
+return true;
+}
+function overlib350(){
+var layerhtml;
+if(obackground !="" || ofullhtml){
+layerhtml=ol_content_background(otext, obackground, ofullhtml);
+}else{
+if(ofgbackground !="" && ocss==CSSOFF){
+ofgbackground="BACKGROUND=\""+ofgbackground+"\"";
+}
+if(obgbackground !="" && ocss==CSSOFF){
+obgbackground="BACKGROUND=\""+obgbackground+"\"";
+}
+if(ofgcolor !="" && ocss==CSSOFF){
+ofgcolor="BGCOLOR=\""+ofgcolor+"\"";
+}
+if(obgcolor !="" && ocss==CSSOFF){
+obgcolor="BGCOLOR=\""+obgcolor+"\"";
+}
+if(oheight > 0 && ocss==51){
+oheight="HEIGHT=" + oheight;
+}else{
+oheight="";
+}
+if(ocap==""){
+layerhtml=ol_content_simple(otext);
+}else{
+if(osticky){
+layerhtml=ol_content_caption(otext, ocap, oclose);
+}else{
+layerhtml=ol_content_caption(otext, ocap, "");
+}
+}
+}
+if(osticky){
+oshowingsticky=1;
+oremovecounter=0;
+}
+layerWrite(layerhtml);
+if(oautostatus > 0){
+ostatus=otext;
+if(oautostatus > 1){
+ostatus=ocap;
+}
+}
+oallowmove=0;
+if(otimeout > 0){
+if(otimerid > 0)clearTimeout(otimerid);
+otimerid=setTimeout("cClick()", otimeout);
+}
+disp(ostatus);
+if(osticky){
+oallowmove=0;
+return false;
+}else{
+return true;
+}
+}
+function ol_content_simple(text){
+if(ocss==CSSCLASS)txt="<TABLE WIDTH="+owidth+" BORDER=0 CELLPADDING="+oborder+" CELLSPACING=0 class=\""+obgclass+"\"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 class=\""+ofgclass+"\"><TR><TD VALIGN=TOP><FONT class=\""+otextfontclass+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+if(ocss==CSSSTYLE)txt="<TABLE WIDTH="+owidth+" BORDER=0 CELLPADDING="+oborder+" CELLSPACING=0 style=\"background-color: "+obgcolor+";height: "+oheight+oheightunit+";\"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 style=\"color: "+ofgcolor+";background-color: "+ofgcolor+";height: "+oheight+oheightunit+";\"><TR><TD VALIGN=TOP><FONT style=\"font-family: "+otextfont+";color: "+otextcolor+";font-size: "+otextsize+otextsizeunit+";text-decoration: "+otextdecoration+";font-weight: "+otextweight+";font-style:"+otextstyle+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+if(ocss==CSSOFF)txt="<TABLE WIDTH="+owidth+" BORDER=0 CELLPADDING="+oborder+" CELLSPACING=0 "+obgcolor+" "+oheight+"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 "+ofgcolor+" "+ofgbackground+" "+oheight+"><TR><TD VALIGN=TOP><FONT FACE=\""+otextfont+"\" COLOR=\""+otextcolor+"\" SIZE=\""+otextsize+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+set_background("");
+return txt;
+}
+function ol_content_caption(text, title, close){
+closing="";
+closeevent="onMouseOver";
+if(ocloseclick==1)closeevent="onClick";
+if(ocapicon !="")ocapicon="<IMG SRC=\""+ocapicon+"\"> ";
+if(close !=""){
+if(ocss==CSSCLASS)closing="<TD ALIGN=RIGHT><A HREF=\"/\" "+closeevent+"=\"return cClick();\" class=\""+oclosefontclass+"\">"+close+"</A></TD>";
+if(ocss==CSSSTYLE)closing="<TD ALIGN=RIGHT><A HREF=\"/\" "+closeevent+"=\"return cClick();\" style=\"color: "+oclosecolor+";font-family: "+oclosefont+";font-size: "+oclosesize+oclosesizeunit+";text-decoration: "+oclosedecoration+";font-weight: "+ocloseweight+";font-style:"+oclosestyle+";\">"+close+"</A></TD>";
+if(ocss==CSSOFF)closing="<TD ALIGN=RIGHT><A HREF=\"/\" "+closeevent+"=\"return cClick();\"><FONT COLOR=\""+oclosecolor+"\" FACE=\""+oclosefont+"\" SIZE=\""+oclosesize+"\">"+close+"</FONT></A></TD>";
+}
+if(ocss==CSSCLASS)txt="<TABLE WIDTH="+owidth+" BORDER=0 CELLPADDING="+oborder+" CELLSPACING=0 class=\""+obgclass+"\"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=0 CELLSPACING=0><TR><TD><FONT class=\""+ocaptionfontclass+"\">"+ocapicon+title+"</FONT></TD>"+closing+"</TR></TABLE><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 class=\""+ofgclass+"\"><TR><TD VALIGN=TOP><FONT class=\""+otextfontclass+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+if(ocss==CSSSTYLE)txt="<TABLE WIDTH="+owidth+" BORDER=0 CELLPADDING="+oborder+" CELLSPACING=0 style=\"background-color: "+obgcolor+";background-image: url("+obgbackground+");height: "+oheight+oheightunit+";\"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=0 CELLSPACING=0><TR><TD><FONT style=\"font-family: "+ocaptionfont+";color: "+ocapcolor+";font-size: "+ocaptionsize+ocaptionsizeunit+";font-weight: "+ocaptionweight+";font-style: "+ocaptionstyle+";\">"+ocapicon+title+"</FONT></TD>"+closing+"</TR></TABLE><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 style=\"color: "+ofgcolor+";background-color: "+ofgcolor+";height: "+oheight+oheightunit+";\"><TR><TD VALIGN=TOP><FONT style=\"font-family: "+otextfont+";color: "+otextcolor+";font-size: "+otextsize+otextsizeunit+";text-decoration: "+otextdecoration+";font-weight: "+otextweight+";font-style:"+otextstyle+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+if(ocss==CSSOFF)txt="<TABLE WIDTH="+owidth+" BORDER=0 CELLPADDING="+oborder+" CELLSPACING=0 "+obgcolor+" "+obgbackground+" "+oheight+"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=0 CELLSPACING=0><TR><TD><B><FONT COLOR=\""+ocapcolor+"\" FACE=\""+ocaptionfont+"\" SIZE=\""+ocaptionsize+"\">"+ocapicon+title+"</FONT></B></TD>"+closing+"</TR></TABLE><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 "+ofgcolor+" "+ofgbackground+" "+oheight+"><TR><TD VALIGN=TOP><FONT COLOR=\""+otextcolor+"\" FACE=\""+otextfont+"\" SIZE=\""+otextsize+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+set_background("");
+return txt;
+}
+function ol_content_background(text, picture, hasfullhtml){
+if(hasfullhtml){
+txt=text;
+}else{
+if(ocss==CSSCLASS)txt="<TABLE WIDTH="+owidth+owidthunit+" BORDER=0 CELLPADDING=0 CELLSPACING=0 HEIGHT="+oheight+oheightunit+"><TR><TD COLSPAN=3 HEIGHT="+opadyt+opadunit+"></TD></TR><TR><TD WIDTH="+opadxl+opadunit+"></TD><TD VALIGN=TOP WIDTH="+(owidth-opadxl-opadxr)+opadunit+"><FONT class=\""+otextfontclass+"\">"+text+"</FONT></TD><TD WIDTH="+opadxr+opadunit+"></TD></TR><TR><TD COLSPAN=3 HEIGHT="+opadyb+opadunit+"></TD></TR></TABLE>";
+if(ocss==CSSSTYLE)txt="<TABLE WIDTH="+owidth+owidthunit+" BORDER=0 CELLPADDING=0 CELLSPACING=0 HEIGHT="+oheight+oheightunit+"><TR><TD COLSPAN=3 HEIGHT="+opadyt+opadunit+"></TD></TR><TR><TD WIDTH="+opadxl+opadunit+"></TD><TD VALIGN=TOP WIDTH="+(owidth-opadxl-opadxr)+opadunit+"><FONT style=\"font-family: "+otextfont+";color: "+otextcolor+";font-size: "+otextsize+otextsizeunit+";\">"+text+"</FONT></TD><TD WIDTH="+opadxr+opadunit+"></TD></TR><TR><TD COLSPAN=3 HEIGHT="+opadyb+opadunit+"></TD></TR></TABLE>";
+if(ocss==CSSOFF)txt="<TABLE WIDTH="+owidth+" BORDER=0 CELLPADDING=0 CELLSPACING=0 HEIGHT="+oheight+"><TR><TD COLSPAN=3 HEIGHT="+opadyt+"></TD></TR><TR><TD WIDTH="+opadxl+"></TD><TD VALIGN=TOP WIDTH="+(owidth-opadxl-opadxr)+"><FONT FACE=\""+otextfont+"\" COLOR=\""+otextcolor+"\" SIZE=\""+otextsize+"\">"+text+"</FONT></TD><TD WIDTH="+opadxr+"></TD></TR><TR><TD COLSPAN=3 HEIGHT="+opadyb+"></TD></TR></TABLE>";
+}
+set_background(picture);
+return txt;
+}
+function set_background(pic){
+if(pic==""){
+if(ie4)over.backgroundImage="none";
+if(ns6)over.style.backgroundImage="none";
+}else{
+if(ns4){
+over.background.src=pic;
+}else if(ie4){
+over.backgroundImage="url("+pic+")";
+}else if(ns6){
+over.style.backgroundImage="url("+pic+")";
+}
+}
+}
+function disp(statustext){
+if((ns4)||(ie4)||(ns6)){
+if(oallowmove==0){
+placeLayer();
+showObject(over);
+oallowmove=1;
+}
+}
+if(statustext !=""){
+self.status=statustext;
+}
+}
+function placeLayer(){
+var placeX, placeY;
+if(ofixx > -1){
+placeX=ofixx;
+}else{
+winoffset=(ie4)? oframe.document.body.scrollLeft : oframe.pageXOffset;
+if(ie4)iwidth=oframe.document.body.clientWidth;
+if(ns4)iwidth=oframe.innerWidth;// was screwed in mozilla, fixed now?
+if(ns6)iwidth=oframe.outerWidth;
+if(ohauto==1){
+if((ox - winoffset)>((eval(iwidth))/ 2)){
+ohpos=7;
+}else{
+ohpos=8;
+}
+}
+if(ohpos==9){// Center
+placeX=ox+ooffsetx-(owidth/2);
+}
+if(ohpos==8){// Right
+placeX=ox+ooffsetx;
+if((eval(placeX)+ eval(owidth))>(winoffset + iwidth)){
+placeX=iwidth + winoffset - owidth;
+if(placeX < 0)placeX=0;
+}
+}
+if(ohpos==7){// Left
+placeX=ox-ooffsetx-owidth;
+if(placeX < winoffset)placeX=winoffset;
+}
+if(osnapx > 1){
+var snapping=placeX % osnapx;
+if(ohpos==7){
+placeX=placeX -(osnapx + snapping);
+}else{
+placeX=placeX +(osnapx - snapping);
+}
+if(placeX < winoffset)placeX=winoffset;
+}
+}
+if(ofixy > -1){
+placeY=ofixy;
+}else{
+scrolloffset=(ie4)? oframe.document.body.scrollTop : oframe.pageYOffset;
+if(ovauto==1){
+if(ie4)iheight=oframe.document.body.clientHeight;
+if(ns4)iheight=oframe.innerHeight;
+if(ns6)iheight=oframe.outerHeight;
+iheight=(eval(iheight))/ 2;
+if((oy - scrolloffset)> iheight){
+ovpos=35;
+}else{
+ovpos=36;
+}
+}
+if(ovpos==35){
+if(oaboveheight==0){
+var divref=(ie4)? oframe.document.all['overDiv'] : over;
+oaboveheight=(ns4)? divref.clip.height : divref.offsetHeight;
+}
+placeY=oy -(oaboveheight + ooffsety);
+if(placeY < scrolloffset)placeY=scrolloffset;
+}else{
+placeY=oy + ooffsety;
+}
+if(osnapy > 1){
+var snapping=placeY % osnapy;
+if(oaboveheight > 0 && ovpos==35){
+placeY=placeY -(osnapy + snapping);
+}else{
+placeY=placeY +(osnapy - snapping);
+}
+if(placeY < scrolloffset)placeY=scrolloffset;
+}
+}
+repositionTo(over, placeX, placeY);
+}
+function mouseMove(e){
+if((ns4)||(ns6)){ox=e.pageX;oy=e.pageY;}
+if(ie4){ox=event.x;oy=event.y;}
+if(ie5){ox=event.x+oframe.document.body.scrollLeft;oy=event.y+oframe.document.body.scrollTop;}
+if(oallowmove==1){
+placeLayer();
+}
+}
+function cClick(){
+hideObject(over);
+oshowingsticky=0;
+return false;
+}
+function compatibleframe(frameid){
+if(ns4){
+if(typeof frameid.document.overDiv=='undefined')return false;
+}else if(ie4){
+if(typeof frameid.document.all["overDiv"]=='undefined')return false;
+}else if(ns6){
+if(frameid.document.getElementById('overDiv')==null)return false;
+}
+return true;
+}
+function layerWrite(txt){
+txt +="\n";
+if(ns4){
+var lyr=oframe.document.overDiv.document
+lyr.write(txt)
+lyr.close()
+}else if(ie4){
+oframe.document.all["overDiv"].innerHTML=txt
+}else if(ns6){
+range=oframe.document.createRange();
+range.setStartBefore(over);
+domfrag=range.createContextualFragment(txt);
+while(over.hasChildNodes()){
+over.removeChild(over.lastChild);
+}
+over.appendChild(domfrag);
+}
+}
+function showObject(obj){
+if(ns4)obj.visibility="show";
+else if(ie4)obj.visibility="visible";
+else if(ns6)obj.style.visibility="visible";
+}
+function hideObject(obj){
+if(ns4)obj.visibility="hide";
+else if(ie4)obj.visibility="hidden";
+else if(ns6)obj.style.visibility="hidden";
+if(otimerid > 0)clearTimeout(otimerid);
+if(odelayid > 0)clearTimeout(odelayid);
+otimerid=0;
+odelayid=0;
+self.status="";
+}
+function repositionTo(obj,xL,yL){
+if((ns4)||(ie4)){
+obj.left=xL;
+obj.top=yL;
+}else if(ns6){
+obj.style.left=xL + "px";
+obj.style.top=yL+ "px";
+}
+}
+function opt_FRAME(frm){
+oframe=compatibleframe(frm)? frm : ol_frame;
+if((ns4)||(ie4 ||(ns6))){
+if(ns4)over=oframe.document.overDiv;
+if(ie4)over=oframe.overDiv.style;
+if(ns6)over=oframe.document.getElementById("overDiv");
+}
+return 0;
+}
+function opt_FUNCTION(callme){
+otext=callme()
+return 0;
+}
diff --git a/overlib_mini_help.js b/overlib_mini_help.js
new file mode 100644 (file)
index 0000000..f1ef1ae
--- /dev/null
@@ -0,0 +1,709 @@
+//\//////////////////////////////////////////////////////////////////////////////////
+//\  overLIB 3.50  --  This notice must remain untouched at all times.
+//\  Copyright Erik Bosrup 1998-2001. All rights reserved.
+//\
+//\  By Erik Bosrup (erik@bosrup.com).  Last modified 2001-08-28.
+//\  Portions by Dan Steinman (dansteinman.com). Additions by other people are
+//\  listed on the overLIB homepage.
+//\
+//\  Get the latest version at http://www.bosrup.com/web/overlib/
+//\
+//\  This script is published under an open source license. Please read the license
+//\  agreement online at: http://www.bosrup.com/web/overlib/license.html
+//\  If you have questions regarding the license please contact erik@bosrup.com.
+//\
+//\  This script library was originally created for personal use. By request it has
+//\  later been made public. This is free software. Do not sell this as your own
+//\  work, or remove this copyright notice. For full details on copying or changing
+//\  this script please read the license agreement at the link above.
+//\
+//\  Please give credit on sites that use overLIB and submit changes of the script
+//\  so other people can use them as well. This script is free to use, don't abuse.
+//\//////////////////////////////////////////////////////////////////////////////////
+
+//\  THIS IS A VERY MODIFIED VERSION. DO NOT EDIT OR PUBLISH. GET THE ORIGINAL!
+
+var INARRAY=1;
+var CAPARRAY=2;
+var STICKY=3;
+var BACKGROUND=4;
+var NOCLOSE=5;
+var CAPTION=6;
+var LEFT=7;
+var RIGHT=8;
+var CENTER=9;
+var OFFSETX=10;
+var OFFSETY=11;
+var FGCOLOR=12;
+var BGCOLOR=13;
+var TEXTCOLOR=14;
+var CAPCOLOR=15;
+var CLOSECOLOR=16;
+var WIDTH=17;
+var BORDER=18;
+var STATUS=19;
+var AUTOSTATUS=20;
+var AUTOSTATUSCAP=21;
+var HEIGHT=22;
+var CLOSETEXT=23;
+var SNAPX=24;
+var SNAPY=25;
+var FIXX=26;
+var FIXY=27;
+var FGBACKGROUND=28;
+var BGBACKGROUND=29;
+var PADX=30;// PADX2 out
+var PADY=31;// PADY2 out
+var FULLHTML=34;
+var ABOVE=35;
+var BELOW=36;
+var CAPICON=37;
+var TEXTFONT=38;
+var CAPTIONFONT=39;
+var CLOSEFONT=40;
+var TEXTSIZE=41;
+var CAPTIONSIZE=42;
+var CLOSESIZE=43;
+var FRAME=44;
+var TIMEOUT=45;
+var FUNCTION=46;
+var DELAY=47;
+var HAUTO=48;
+var VAUTO=49;
+var CLOSECLICK=50;
+var CSSOFF=51;
+var CSSSTYLE=52;
+var CSSCLASS=53;
+var FGCLASS=54;
+var BGCLASS=55;
+var TEXTFONTCLASS=56;
+var CAPTIONFONTCLASS=57;
+var CLOSEFONTCLASS=58;
+var PADUNIT=59;
+var HEIGHTUNIT=60;
+var WIDTHUNIT=61;
+var TEXTSIZEUNIT=62;
+var TEXTDECORATION=63;
+var TEXTSTYLE=64;
+var TEXTWEIGHT=65;
+var CAPTIONSIZEUNIT=66;
+var CAPTIONDECORATION=67;
+var CAPTIONSTYLE=68;
+var CAPTIONWEIGHT=69;
+var CLOSESIZEUNIT=70;
+var CLOSEDECORATION=71;
+var CLOSESTYLE=72;
+var CLOSEWEIGHT=73;
+if(typeof ol_fgcolor=='undefined'){var ol_fgcolor="#EEEEEE";}
+if(typeof ol_bgcolor=='undefined'){var ol_bgcolor="#006699";}
+if(typeof ol_textcolor=='undefined'){var ol_textcolor="#000000";}
+if(typeof ol_capcolor=='undefined'){var ol_capcolor="#FFFFFF";}
+if(typeof ol_closecolor=='undefined'){var ol_closecolor="#9999FF";}
+if(typeof ol_textfont=='undefined'){var ol_textfont="Verdana,Arial,Helvetica";}
+if(typeof ol_captionfont=='undefined'){var ol_captionfont="Verdana,Arial,Helvetica";}
+if(typeof ol_closefont=='undefined'){var ol_closefont="Verdana,Arial,Helvetica";}
+if(typeof ol_textsize=='undefined'){var ol_textsize="2";}
+if(typeof ol_captionsize=='undefined'){var ol_captionsize="1";}
+if(typeof ol_closesize=='undefined'){var ol_closesize="1";}
+if(typeof ol_width=='undefined'){var ol_width="200";}
+if(typeof ol_border=='undefined'){var ol_border="1";}
+if(typeof ol_offsetx=='undefined'){var ol_offsetx=10;}
+if(typeof ol_offsety=='undefined'){var ol_offsety=10;}
+if(typeof ol_text=='undefined'){var ol_text="Default Text";}
+if(typeof ol_cap=='undefined'){var ol_cap="";}
+if(typeof ol_sticky=='undefined'){var ol_sticky=0;}
+if(typeof ol_background=='undefined'){var ol_background="";}
+if(typeof ol_close=='undefined'){var ol_close="Close";}
+if(typeof ol_hpos=='undefined'){var ol_hpos=8;}
+if(typeof ol_status=='undefined'){var ol_status="";}
+if(typeof ol_autostatus=='undefined'){var ol_autostatus=0;}
+if(typeof ol_height=='undefined'){var ol_height=-1;}
+if(typeof ol_snapx=='undefined'){var ol_snapx=0;}
+if(typeof ol_snapy=='undefined'){var ol_snapy=0;}
+if(typeof ol_fixx=='undefined'){var ol_fixx=-1;}
+if(typeof ol_fixy=='undefined'){var ol_fixy=-1;}
+if(typeof ol_fgbackground=='undefined'){var ol_fgbackground="";}
+if(typeof ol_bgbackground=='undefined'){var ol_bgbackground="";}
+if(typeof ol_padxl=='undefined'){var ol_padxl=1;}
+if(typeof ol_padxr=='undefined'){var ol_padxr=1;}
+if(typeof ol_padyt=='undefined'){var ol_padyt=1;}
+if(typeof ol_padyb=='undefined'){var ol_padyb=1;}
+if(typeof ol_fullhtml=='undefined'){var ol_fullhtml=1;}
+if(typeof ol_vpos=='undefined'){var ol_vpos=36;}
+if(typeof ol_aboveheight=='undefined'){var ol_aboveheight=0;}
+if(typeof ol_caption=='undefined'){var ol_capicon="";}
+if(typeof ol_frame=='undefined'){var ol_frame=self;}
+if(typeof ol_timeout=='undefined'){var ol_timeout=0;}
+if(typeof ol_function=='undefined'){var ol_function=Function();}
+if(typeof ol_delay=='undefined'){var ol_delay=0;}
+if(typeof ol_hauto=='undefined'){var ol_hauto=0;}
+if(typeof ol_vauto=='undefined'){var ol_vauto=0;}
+if(typeof ol_closeclick=='undefined'){var ol_closeclick=0;}
+if(typeof ol_css=='undefined'){var ol_css=51;} /* 51 */
+if(typeof ol_fgclass=='undefined'){var ol_fgclass="";}
+if(typeof ol_bgclass=='undefined'){var ol_bgclass="";}
+if(typeof ol_textfontclass=='undefined'){var ol_textfontclass="";}
+if(typeof ol_captionfontclass=='undefined'){var ol_captionfontclass="";}
+if(typeof ol_closefontclass=='undefined'){var ol_closefontclass="";}
+if(typeof ol_padunit=='undefined'){var ol_padunit="px";}
+if(typeof ol_heightunit=='undefined'){var ol_heightunit="px";}
+if(typeof ol_widthunit=='undefined'){var ol_widthunit="px";}
+if(typeof ol_textsizeunit=='undefined'){var ol_textsizeunit="px";}
+if(typeof ol_textdecoration=='undefined'){var ol_textdecoration="none";}
+if(typeof ol_textstyle=='undefined'){var ol_textstyle="normal";}
+if(typeof ol_textweight=='undefined'){var ol_textweight="normal";}
+if(typeof ol_captionsizeunit=='undefined'){var ol_captionsizeunit="px";}
+if(typeof ol_captiondecoration=='undefined'){var ol_captiondecoration="none";}
+if(typeof ol_captionstyle=='undefined'){var ol_captionstyle="normal";}
+if(typeof ol_captionweight=='undefined'){var ol_captionweight="bold";}
+if(typeof ol_closesizeunit=='undefined'){var ol_closesizeunit="px";}
+if(typeof ol_closedecoration=='undefined'){var ol_closedecoration="none";}
+if(typeof ol_closestyle=='undefined'){var ol_closestyle="normal";}
+if(typeof ol_closeweight=='undefined'){var ol_closeweight="normal";}
+if(typeof ol_texts=='undefined'){var ol_texts=new Array("Text 0", "Text 1");}
+if(typeof ol_caps=='undefined'){var ol_caps=new Array("Caption 0", "Caption 1");}
+var otext="";
+var ocap="";
+var osticky=0;
+var obackground="";
+var oclose="Close";
+var ohpos=8;
+var ooffsetx=2;
+var ooffsety=2;
+var ofgcolor="";
+var obgcolor="";
+var otextcolor="";
+var ocapcolor="";
+var oclosecolor="";
+var owidth=100;
+var oborder=1;
+var ostatus="";
+var oautostatus=0;
+var oheight=-1;
+var osnapx=0;
+var osnapy=0;
+var ofixx=-1;
+var ofixy=-1;
+var ofgbackground="";
+var obgbackground="";
+var opadxl=0;
+var opadxr=0;
+var opadyt=0;
+var opadyb=0;
+var ofullhtml=0;
+var ovpos=36;
+var oaboveheight=0;
+var ocapicon="";
+var otextfont="Verdana,Arial,Helvetica";
+var ocaptionfont="Verdana,Arial,Helvetica";
+var oclosefont="Verdana,Arial,Helvetica";
+var otextsize="1";
+var ocaptionsize="1";
+var oclosesize="1";
+var oframe=self;
+var otimeout=0;
+var otimerid=0;
+var oallowmove=0;
+var ofunction=Function();
+var odelay=0;
+var odelayid=0;
+var ohauto=0;
+var ovauto=0;
+var ocloseclick=0;
+var ocss=51;
+var ofgclass="";
+var obgclass="";
+var otextfontclass="";
+var ocaptionfontclass="";
+var oclosefontclass="";
+var opadunit="px";
+var oheightunit="px";
+var owidthunit="px";
+var otextsizeunit="px";
+var otextdecoration="";
+var otextstyle="";
+var otextweight="";
+var ocaptionsizeunit="px";
+var ocaptiondecoration="";
+var ocaptionstyle="";
+var ocaptionweight="";
+var oclosesizeunit="px";
+var oclosedecoration="";
+var oclosestyle="";
+var ocloseweight="";
+var ox=0;
+var oy=0;
+var oallow=0;
+var oshowingsticky=0;
+var oremovecounter=0;
+var over=null;
+var ns4=(document.layers)? true:false;
+var ns6=(document.getElementById)? true:false;
+var ie4=(document.all)? true:false;
+var ie5=false;
+if(ie4){
+if((navigator.userAgent.indexOf('MSIE 5')> 0)||(navigator.userAgent.indexOf('MSIE 6')> 0)){
+ie5=true;
+}
+if(ns6){
+ns6=false;
+}
+}
+if((ns4)||(ie4)||(ns6)){
+document.onmousemove=mouseMove
+if(ns4)document.captureEvents(Event.MOUSEMOVE)
+}else{
+overlib=no_overlib;
+nd=no_overlib;
+ver3fix=true;
+}
+function no_overlib(){
+return ver3fix;
+}
+function overlib2(){
+otext=ol_text;
+ocap=ol_cap;
+osticky=ol_sticky;
+obackground=ol_background;
+oclose=ol_close;
+ohpos=ol_hpos;
+ooffsetx=ol_offsetx;
+ooffsety=ol_offsety;
+ofgcolor=ol_fgcolor;
+obgcolor=ol_bgcolor;
+otextcolor=ol_textcolor;
+ocapcolor=ol_capcolor;
+oclosecolor=ol_closecolor;
+owidth=ol_width;
+oborder=ol_border;
+ostatus=ol_status;
+oautostatus=ol_autostatus;
+oheight=ol_height;
+osnapx=ol_snapx;
+osnapy=ol_snapy;
+ofixx=ol_fixx;
+ofixy=ol_fixy;
+ofgbackground=ol_fgbackground;
+obgbackground=ol_bgbackground;
+opadxl=ol_padxl;
+opadxr=ol_padxr;
+opadyt=ol_padyt;
+opadyb=ol_padyb;
+ofullhtml=ol_fullhtml;
+ovpos=ol_vpos;
+oaboveheight=ol_aboveheight;
+ocapicon=ol_capicon;
+otextfont=ol_textfont;
+ocaptionfont=ol_captionfont;
+oclosefont=ol_closefont;
+otextsize=ol_textsize;
+ocaptionsize=ol_captionsize;
+oclosesize=ol_closesize;
+otimeout=ol_timeout;
+ofunction=ol_function;
+odelay=ol_delay;
+ohauto=ol_hauto;
+ovauto=ol_vauto;
+ocloseclick=ol_closeclick;
+ocss=ol_css;
+ofgclass=ol_fgclass;
+obgclass=ol_bgclass;
+otextfontclass=ol_textfontclass;
+ocaptionfontclass=ol_captionfontclass;
+oclosefontclass=ol_closefontclass;
+opadunit=ol_padunit;
+oheightunit=ol_heightunit;
+owidthunit=ol_widthunit;
+otextsizeunit=ol_textsizeunit;
+otextdecoration=ol_textdecoration;
+otextstyle=ol_textstyle;
+otextweight=ol_textweight;
+ocaptionsizeunit=ol_captionsizeunit;
+ocaptiondecoration=ol_captiondecoration;
+ocaptionstyle=ol_captionstyle;
+ocaptionweight=ol_captionweight;
+oclosesizeunit=ol_closesizeunit;
+oclosedecoration=ol_closedecoration;
+oclosestyle=ol_closestyle;
+ocloseweight=ol_closeweight;
+if((ns4)||(ie4)||(ns6)){
+oframe=ol_frame;
+if(ns4)over=oframe.document.overDiv2
+if(ie4)over=oframe.overDiv2.style
+if(ns6)over=oframe.document.getElementById("overDiv");
+}
+var c=-1;
+var ar=arguments;
+for(i=0;i < ar.length;i++){
+if(c < 0){
+if(ar[i]==1){
+otext=ol_texts[ar[++i]];
+}else{
+otext=ar[i];
+}
+c=0;
+}else{
+if(ar[i]==1){otext=ol_texts[ar[++i]];continue;}
+if(ar[i]==2){ocap=ol_caps[ar[++i]];continue;}
+if(ar[i]==3){osticky=1;continue;}
+if(ar[i]==4){obackground=ar[++i];continue;}
+if(ar[i]==NOCLOSE){oclose="";continue;}
+if(ar[i]==6){ocap=ar[++i];continue;}
+if(ar[i]==9 || ar[i]==7 || ar[i]==8){ohpos=ar[i];continue;}
+if(ar[i]==10){ooffsetx=ar[++i];continue;}
+if(ar[i]==11){ooffsety=ar[++i];continue;}
+if(ar[i]==12){ofgcolor=ar[++i];continue;}
+if(ar[i]==13){obgcolor=ar[++i];continue;}
+if(ar[i]==14){otextcolor=ar[++i];continue;}
+if(ar[i]==15){ocapcolor=ar[++i];continue;}
+if(ar[i]==16){oclosecolor=ar[++i];continue;}
+if(ar[i]==17){owidth=ar[++i];continue;}
+if(ar[i]==18){oborder=ar[++i];continue;}
+if(ar[i]==19){ostatus=ar[++i];continue;}
+if(ar[i]==20){oautostatus=1;continue;}
+if(ar[i]==21){oautostatus=2;continue;}
+if(ar[i]==22){oheight=ar[++i];oaboveheight=ar[i];continue;}// Same param again.
+if(ar[i]==23){oclose=ar[++i];continue;}
+if(ar[i]==24){osnapx=ar[++i];continue;}
+if(ar[i]==25){osnapy=ar[++i];continue;}
+if(ar[i]==26){ofixx=ar[++i];continue;}
+if(ar[i]==27){ofixy=ar[++i];continue;}
+if(ar[i]==28){ofgbackground=ar[++i];continue;}
+if(ar[i]==29){obgbackground=ar[++i];continue;}
+if(ar[i]==30){opadxl=ar[++i];opadxr=ar[++i];continue;}
+if(ar[i]==31){opadyt=ar[++i];opadyb=ar[++i];continue;}
+if(ar[i]==34){ofullhtml=1;continue;}
+if(ar[i]==36 || ar[i]==35){ovpos=ar[i];continue;}
+if(ar[i]==37){ocapicon=ar[++i];continue;}
+if(ar[i]==38){otextfont=ar[++i];continue;}
+if(ar[i]==39){ocaptionfont=ar[++i];continue;}
+if(ar[i]==40){oclosefont=ar[++i];continue;}
+if(ar[i]==41){otextsize=ar[++i];continue;}
+if(ar[i]==42){ocaptionsize=ar[++i];continue;}
+if(ar[i]==43){oclosesize=ar[++i];continue;}
+if(ar[i]==44){opt_FRAME(ar[++i]);continue;}
+if(ar[i]==45){otimeout=ar[++i];continue;}
+if(ar[i]==46){opt_FUNCTION(ar[++i]);continue;}
+if(ar[i]==47){odelay=ar[++i];continue;}
+if(ar[i]==48){ohauto=(ohauto==0)? 1 : 0;continue;}
+if(ar[i]==49){ovauto=(ovauto==0)? 1 : 0;continue;}
+if(ar[i]==50){ocloseclick=(ocloseclick==0)? 1 : 0;continue;}
+if(ar[i]==51){ocss=ar[i];continue;}
+if(ar[i]==52){ocss=ar[i];continue;}
+if(ar[i]==53){ocss=ar[i];continue;}
+if(ar[i]==54){ofgclass=ar[++i];continue;}
+if(ar[i]==55){obgclass=ar[++i];continue;}
+if(ar[i]==56){otextfontclass=ar[++i];continue;}
+if(ar[i]==57){ocaptionfontclass=ar[++i];continue;}
+if(ar[i]==58){oclosefontclass=ar[++i];continue;}
+if(ar[i]==59){opadunit=ar[++i];continue;}
+if(ar[i]==60){oheightunit=ar[++i];continue;}
+if(ar[i]==61){owidthunit=ar[++i];continue;}
+if(ar[i]==62){otextsizeunit=ar[++i];continue;}
+if(ar[i]==63){otextdecoration=ar[++i];continue;}
+if(ar[i]==64){otextstyle=ar[++i];continue;}
+if(ar[i]==65){otextweight=ar[++i];continue;}
+if(ar[i]==66){ocaptionsizeunit=ar[++i];continue;}
+if(ar[i]==67){ocaptiondecoration=ar[++i];continue;}
+if(ar[i]==68){ocaptionstyle=ar[++i];continue;}
+if(ar[i]==69){ocaptionweight=ar[++i];continue;}
+if(ar[i]==70){oclosesizeunit=ar[++i];continue;}
+if(ar[i]==71){oclosedecoration=ar[++i];continue;}
+if(ar[i]==72){oclosestyle=ar[++i];continue;}
+if(ar[i]==73){ocloseweight=ar[++i];continue;}
+}
+}
+if(odelay==0){
+return overlib350();
+}else{
+odelayid=setTimeout("overlib350()", odelay);
+if(osticky){
+return false;
+}else{
+return true;
+}
+}
+}
+function nd2(){
+if(oremovecounter >=1){oshowingsticky=0};
+if((ns4)||(ie4)||(ns6)){
+if(oshowingsticky==0){
+oallowmove=0;
+if(over !=null)hideObject(over);
+}else{
+oremovecounter++;
+}
+}
+return true;
+}
+function overlib350(){
+var layerhtml;
+if(obackground !="" || ofullhtml){
+layerhtml=ol_content_background(otext, obackground, ofullhtml);
+}else{
+if(ofgbackground !="" && ocss==CSSOFF){
+ofgbackground="BACKGROUND=\""+ofgbackground+"\"";
+}
+if(obgbackground !="" && ocss==CSSOFF){
+obgbackground="BACKGROUND=\""+obgbackground+"\"";
+}
+if(ofgcolor !="" && ocss==CSSOFF){
+ofgcolor="BGCOLOR=\""+ofgcolor+"\"";
+}
+if(obgcolor !="" && ocss==CSSOFF){
+obgcolor="BGCOLOR=\""+obgcolor+"\"";
+}
+if(oheight > 0 && ocss==51){
+oheight="HEIGHT=" + oheight;
+}else{
+oheight="";
+}
+if(ocap==""){
+layerhtml=ol_content_simple(otext);
+}else{
+if(osticky){
+layerhtml=ol_content_caption(otext, ocap, oclose);
+}else{
+layerhtml=ol_content_caption(otext, ocap, "");
+}
+}
+}
+if(osticky){
+oshowingsticky=1;
+oremovecounter=0;
+}
+layerWrite(layerhtml);
+if(oautostatus > 0){
+ostatus=otext;
+if(oautostatus > 1){
+ostatus=ocap;
+}
+}
+oallowmove=0;
+if(otimeout > 0){
+if(otimerid > 0)clearTimeout(otimerid);
+otimerid=setTimeout("cClick()", otimeout);
+}
+disp(ostatus);
+if(osticky){
+oallowmove=0;
+return false;
+}else{
+return true;
+}
+}
+function ol_content_simple(text){
+if(ocss==CSSCLASS)txt="<TABLE WIDTH="+owidth+" BORDER=0 CELLPADDING="+oborder+" CELLSPACING=0 class=\""+obgclass+"\"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 class=\""+ofgclass+"\"><TR><TD VALIGN=TOP><FONT class=\""+otextfontclass+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+if(ocss==CSSSTYLE)txt="<TABLE WIDTH="+owidth+" BORDER=0 CELLPADDING="+oborder+" CELLSPACING=0 style=\"background-color: "+obgcolor+";height: "+oheight+oheightunit+";\"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 style=\"color: "+ofgcolor+";background-color: "+ofgcolor+";height: "+oheight+oheightunit+";\"><TR><TD VALIGN=TOP><FONT style=\"font-family: "+otextfont+";color: "+otextcolor+";font-size: "+otextsize+otextsizeunit+";text-decoration: "+otextdecoration+";font-weight: "+otextweight+";font-style:"+otextstyle+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+if(ocss==CSSOFF)txt="<TABLE WIDTH="+owidth+" BORDER=0 CELLPADDING="+oborder+" CELLSPACING=0 "+obgcolor+" "+oheight+"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 "+ofgcolor+" "+ofgbackground+" "+oheight+"><TR><TD VALIGN=TOP><FONT FACE=\""+otextfont+"\" COLOR=\""+otextcolor+"\" SIZE=\""+otextsize+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+set_background("");
+return txt;
+}
+function ol_content_caption(text, title, close){
+closing="";
+closeevent="onMouseOver";
+if(ocloseclick==1)closeevent="onClick";
+if(ocapicon !="")ocapicon="<IMG SRC=\""+ocapicon+"\"> ";
+if(close !=""){
+if(ocss==CSSCLASS)closing="<TD ALIGN=RIGHT><A HREF=\"/\" "+closeevent+"=\"return cClick();\" class=\""+oclosefontclass+"\">"+close+"</A></TD>";
+if(ocss==CSSSTYLE)closing="<TD ALIGN=RIGHT><A HREF=\"/\" "+closeevent+"=\"return cClick();\" style=\"color: "+oclosecolor+";font-family: "+oclosefont+";font-size: "+oclosesize+oclosesizeunit+";text-decoration: "+oclosedecoration+";font-weight: "+ocloseweight+";font-style:"+oclosestyle+";\">"+close+"</A></TD>";
+if(ocss==CSSOFF)closing="<TD ALIGN=RIGHT><A HREF=\"/\" "+closeevent+"=\"return cClick();\"><FONT COLOR=\""+oclosecolor+"\" FACE=\""+oclosefont+"\" SIZE=\""+oclosesize+"\">"+close+"</FONT></A></TD>";
+}
+if(ocss==CSSCLASS)txt="<TABLE WIDTH="+owidth+" BORDER=0 CELLPADDING="+oborder+" CELLSPACING=0 class=\""+obgclass+"\"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=0 CELLSPACING=0><TR><TD><FONT class=\""+ocaptionfontclass+"\">"+ocapicon+title+"</FONT></TD>"+closing+"</TR></TABLE><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 class=\""+ofgclass+"\"><TR><TD VALIGN=TOP><FONT class=\""+otextfontclass+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+if(ocss==CSSSTYLE)txt="<TABLE WIDTH="+owidth+" BORDER=0 CELLPADDING="+oborder+" CELLSPACING=0 style=\"background-color: "+obgcolor+";background-image: url("+obgbackground+");height: "+oheight+oheightunit+";\"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=0 CELLSPACING=0><TR><TD><FONT style=\"font-family: "+ocaptionfont+";color: "+ocapcolor+";font-size: "+ocaptionsize+ocaptionsizeunit+";font-weight: "+ocaptionweight+";font-style: "+ocaptionstyle+";\">"+ocapicon+title+"</FONT></TD>"+closing+"</TR></TABLE><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 style=\"color: "+ofgcolor+";background-color: "+ofgcolor+";height: "+oheight+oheightunit+";\"><TR><TD VALIGN=TOP><FONT style=\"font-family: "+otextfont+";color: "+otextcolor+";font-size: "+otextsize+otextsizeunit+";text-decoration: "+otextdecoration+";font-weight: "+otextweight+";font-style:"+otextstyle+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+if(ocss==CSSOFF)txt="<TABLE WIDTH="+owidth+" BORDER=0 CELLPADDING="+oborder+" CELLSPACING=0 "+obgcolor+" "+obgbackground+" "+oheight+"><TR><TD><TABLE WIDTH=100% BORDER=0 CELLPADDING=0 CELLSPACING=0><TR><TD><B><FONT COLOR=\""+ocapcolor+"\" FACE=\""+ocaptionfont+"\" SIZE=\""+ocaptionsize+"\">"+ocapicon+title+"</FONT></B></TD>"+closing+"</TR></TABLE><TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 "+ofgcolor+" "+ofgbackground+" "+oheight+"><TR><TD VALIGN=TOP><FONT COLOR=\""+otextcolor+"\" FACE=\""+otextfont+"\" SIZE=\""+otextsize+"\">"+text+"</FONT></TD></TR></TABLE></TD></TR></TABLE>";
+set_background("");
+return txt;
+}
+function ol_content_background(text, picture, hasfullhtml){
+if(hasfullhtml){
+txt=text;
+}else{
+if(ocss==CSSCLASS)txt="<TABLE WIDTH="+owidth+owidthunit+" BORDER=0 CELLPADDING=0 CELLSPACING=0 HEIGHT="+oheight+oheightunit+"><TR><TD COLSPAN=3 HEIGHT="+opadyt+opadunit+"></TD></TR><TR><TD WIDTH="+opadxl+opadunit+"></TD><TD VALIGN=TOP WIDTH="+(owidth-opadxl-opadxr)+opadunit+"><FONT class=\""+otextfontclass+"\">"+text+"</FONT></TD><TD WIDTH="+opadxr+opadunit+"></TD></TR><TR><TD COLSPAN=3 HEIGHT="+opadyb+opadunit+"></TD></TR></TABLE>";
+if(ocss==CSSSTYLE)txt="<TABLE WIDTH="+owidth+owidthunit+" BORDER=0 CELLPADDING=0 CELLSPACING=0 HEIGHT="+oheight+oheightunit+"><TR><TD COLSPAN=3 HEIGHT="+opadyt+opadunit+"></TD></TR><TR><TD WIDTH="+opadxl+opadunit+"></TD><TD VALIGN=TOP WIDTH="+(owidth-opadxl-opadxr)+opadunit+"><FONT style=\"font-family: "+otextfont+";color: "+otextcolor+";font-size: "+otextsize+otextsizeunit+";\">"+text+"</FONT></TD><TD WIDTH="+opadxr+opadunit+"></TD></TR><TR><TD COLSPAN=3 HEIGHT="+opadyb+opadunit+"></TD></TR></TABLE>";
+if(ocss==CSSOFF)txt="<TABLE WIDTH="+owidth+" BORDER=0 CELLPADDING=0 CELLSPACING=0 HEIGHT="+oheight+"><TR><TD COLSPAN=3 HEIGHT="+opadyt+"></TD></TR><TR><TD WIDTH="+opadxl+"></TD><TD VALIGN=TOP WIDTH="+(owidth-opadxl-opadxr)+"><FONT FACE=\""+otextfont+"\" COLOR=\""+otextcolor+"\" SIZE=\""+otextsize+"\">"+text+"</FONT></TD><TD WIDTH="+opadxr+"></TD></TR><TR><TD COLSPAN=3 HEIGHT="+opadyb+"></TD></TR></TABLE>";
+}
+set_background(picture);
+return txt;
+}
+function set_background(pic){
+if(pic==""){
+if(ie4)over.backgroundImage="none";
+if(ns6)over.style.backgroundImage="none";
+}else{
+if(ns4){
+over.background.src=pic;
+}else if(ie4){
+over.backgroundImage="url("+pic+")";
+}else if(ns6){
+over.style.backgroundImage="url("+pic+")";
+}
+}
+}
+function disp(statustext){
+if((ns4)||(ie4)||(ns6)){
+if(oallowmove==0){
+placeLayer();
+showObject(over);
+oallowmove=1;
+}
+}
+if(statustext !=""){
+self.status=statustext;
+}
+}
+function placeLayer(){
+var placeX, placeY;
+if(ofixx > -1){
+placeX=ofixx;
+}else{
+winoffset=(ie4)? oframe.document.body.scrollLeft : oframe.pageXOffset;
+if(ie4)iwidth=oframe.document.body.clientWidth;
+if(ns4)iwidth=oframe.innerWidth;// was screwed in mozilla, fixed now?
+if(ns6)iwidth=oframe.outerWidth;
+if(ohauto==1){
+if((ox - winoffset)>((eval(iwidth))/ 2)){
+ohpos=7;
+}else{
+ohpos=8;
+}
+}
+if(ohpos==9){// Center
+placeX=ox+ooffsetx-(owidth/2);
+}
+if(ohpos==8){// Right
+placeX=ox+ooffsetx;
+if((eval(placeX)+ eval(owidth))>(winoffset + iwidth)){
+placeX=iwidth + winoffset - owidth;
+if(placeX < 0)placeX=0;
+}
+}
+if(ohpos==7){// Left
+placeX=ox-ooffsetx-owidth;
+if(placeX < winoffset)placeX=winoffset;
+}
+if(osnapx > 1){
+var snapping=placeX % osnapx;
+if(ohpos==7){
+placeX=placeX -(osnapx + snapping);
+}else{
+placeX=placeX +(osnapx - snapping);
+}
+if(placeX < winoffset)placeX=winoffset;
+}
+}
+if(ofixy > -1){
+placeY=ofixy;
+}else{
+scrolloffset=(ie4)? oframe.document.body.scrollTop : oframe.pageYOffset;
+if(ovauto==1){
+if(ie4)iheight=oframe.document.body.clientHeight;
+if(ns4)iheight=oframe.innerHeight;
+if(ns6)iheight=oframe.outerHeight;
+iheight=(eval(iheight))/ 2;
+if((oy - scrolloffset)> iheight){
+ovpos=35;
+}else{
+ovpos=36;
+}
+}
+if(ovpos==35){
+if(oaboveheight==0){
+var divref=(ie4)? oframe.document.all['overDiv2'] : over;
+oaboveheight=(ns4)? divref.clip.height : divref.offsetHeight;
+}
+placeY=oy -(oaboveheight + ooffsety);
+if(placeY < scrolloffset)placeY=scrolloffset;
+}else{
+placeY=oy + ooffsety;
+}
+if(osnapy > 1){
+var snapping=placeY % osnapy;
+if(oaboveheight > 0 && ovpos==35){
+placeY=placeY -(osnapy + snapping);
+}else{
+placeY=placeY +(osnapy - snapping);
+}
+if(placeY < scrolloffset)placeY=scrolloffset;
+}
+}
+repositionTo(over, placeX, placeY);
+}
+function mouseMove(e){
+if((ns4)||(ns6)){ox=e.pageX;oy=e.pageY;}
+if(ie4){ox=event.x;oy=event.y;}
+if(ie5){ox=event.x+oframe.document.body.scrollLeft;oy=event.y+oframe.document.body.scrollTop;}
+if(oallowmove==1){
+placeLayer();
+}
+}
+function cClick(){
+hideObject(over);
+oshowingsticky=0;
+return false;
+}
+function compatibleframe(frameid){
+if(ns4){
+if(typeof frameid.document.overDiv2=='undefined')return false;
+}else if(ie4){
+if(typeof frameid.document.all["overDiv2"]=='undefined')return false;
+}else if(ns6){
+if(frameid.document.getElementById('overDiv2')==null)return false;
+}
+return true;
+}
+function layerWrite(txt){
+txt +="\n";
+if(ns4){
+var lyr=oframe.document.overDiv2.document
+lyr.write(txt)
+lyr.close()
+}else if(ie4){
+oframe.document.all["overDiv2"].innerHTML=txt
+}else if(ns6){
+range=oframe.document.createRange();
+range.setStartBefore(over);
+domfrag=range.createContextualFragment(txt);
+while(over.hasChildNodes()){
+over.removeChild(over.lastChild);
+}
+over.appendChild(domfrag);
+}
+}
+function showObject(obj){
+if(ns4)obj.visibility="show";
+else if(ie4)obj.visibility="visible";
+else if(ns6)obj.style.visibility="visible";
+}
+function hideObject(obj){
+if(ns4)obj.visibility="hide";
+else if(ie4)obj.visibility="hidden";
+else if(ns6)obj.style.visibility="hidden";
+if(otimerid > 0)clearTimeout(otimerid);
+if(odelayid > 0)clearTimeout(odelayid);
+otimerid=0;
+odelayid=0;
+self.status="";
+}
+function repositionTo(obj,xL,yL){
+if((ns4)||(ie4)){
+obj.left=xL;
+obj.top=yL;
+}else if(ns6){
+obj.style.left=xL + "px";
+obj.style.top=yL+ "px";
+}
+}
+function opt_FRAME(frm){
+oframe=compatibleframe(frm)? frm : ol_frame;
+if((ns4)||(ie4 ||(ns6))){
+if(ns4)over=oframe.document.overDiv2;
+if(ie4)over=oframe.overDiv.style;
+if(ns6)over=oframe.document.getElementById("overDiv");
+}
+return 0;
+}
+function opt_FUNCTION(callme){
+otext=callme()
+return 0;
+}
diff --git a/packages/index.php b/packages/index.php
new file mode 100644 (file)
index 0000000..a12c8b7
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/*
+ * packages/index.php
+ *
+ * This file is part of ATutor, see http://www.atutor.ca
+ * 
+ * Copyright (C) 2005  Matthai Kurian 
+ * 
+ * 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+require(AT_INCLUDE_PATH.'../tools/packages/lib.inc.php');
+
+$pkgs = getPackagesLearnerLinkList();
+
+if (sizeOf ($pkgs) == 0) {
+       $msg->addInfo (NO_PACKAGES);
+       $msg->printAll();
+} else {
+       echo getScript();
+       echo '<ol>' . "\n";
+       foreach ($pkgs as $p) {
+               echo '<li>' . $p . '</li>' . "\n";
+       }
+       echo '</ol>' . "\n";
+}
+require (AT_INCLUDE_PATH.'footer.inc.php');
+?>
diff --git a/packages/preferences.php b/packages/preferences.php
new file mode 100644 (file)
index 0000000..47f29a0
--- /dev/null
@@ -0,0 +1,115 @@
+<?php
+/*
+ * packages/preferences.php
+ *
+ * This file is part of ATutor, see http://www.atutor.ca
+ * 
+ * Copyright (C) 2005  Matthai Kurian 
+ * 
+ * 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+
+
+$sql = "SELECT lvalue, rvalue
+       FROM   ".TABLE_PREFIX."cmi
+       WHERE   item_id = 0
+       AND     member_id = " . $_SESSION[member_id]
+       ;
+
+$result = mysql_query($sql, $db);
+while ($row = mysql_fetch_assoc($result)) {
+       $p[$row['lvalue']] = $row['rvalue'];
+}
+
+if (!isset ($p['auto_advance'])) {
+       $p['auto_advance']           = 0;
+       $sql = "INSERT INTO ".TABLE_PREFIX."cmi
+               VALUES (NULL, 0, $_SESSION[member_id], 'auto_advance', '0')";
+       $result = mysql_query($sql, $db);
+
+}
+if (!isset ($p['show_rte_communication'])) {
+       $p['show_rte_communication'] = 0;
+       $sql = "INSERT INTO ".TABLE_PREFIX."cmi
+               VALUES (NULL, 0, $_SESSION[member_id],
+                       'show_rte_communication', '0'
+               )";
+       $result = mysql_query($sql, $db);
+}
+
+if (isset ($_POST['upd'])) {
+       $p['auto_advance'] = $_POST['auto_advance'];
+       $sql = "UPDATE ".TABLE_PREFIX."cmi
+               SET     rvalue = '$p[auto_advance]'
+               WHERE   member_id = $_SESSION[member_id]
+               AND     item_id = 0
+               AND     lvalue = 'auto_advance'
+               ";
+       $result1 = mysql_query($sql, $db);
+
+
+       $p['show_rte_communication'] = $_POST['show_rte_communication'];
+       $sql = "UPDATE ".TABLE_PREFIX."cmi
+               SET     rvalue = '$p[show_rte_communication]'
+               WHERE   member_id = $_SESSION[member_id]
+               AND     item_id = 0
+               AND     lvalue = 'show_rte_communication'
+               ";
+       $result2 = mysql_query($sql, $db);
+
+       if ($result1 && $result2) {
+               $msg->addFeedback (SCORM_SETTINGS_SAVED);
+       } else {
+               $msg->addError (SCORM_SETTINGS_SAVE_FAILED);
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+
+<div class="input-form">
+<form name="form1" method="post"
+            enctype="multipart/form-data">
+           <input type="hidden" name="upd" value="1">
+
+<p> <?php echo _AT(packages_auto_advance_info);?> </p>
+<p>
+<input type="checkbox" id="auto_advance" name="auto_advance" value="1" 
+<?php echo ($p['auto_advance']?'checked':'');?> />
+<label for="auto_advance"><?php echo _AT('packages_auto_advance');?><label>
+</p>
+
+<p> <?php echo _AT(packages_show_rte_communication_info);?> </p>
+<p>
+<input type="checkbox" id="show_rte_communication" name="show_rte_communication"
+       value="1" 
+<?php echo ($p['show_rte_communication']?'checked':'');?> />
+<label for="show_rte_communication">
+       <?php echo _AT('packages_show_rte_communication');?>
+<label>
+</p>
+
+<div class="row buttons">
+<input type="submit" name="submit" value="<?php echo _AT('save');?> " />
+</div>
+
+</form>
+</div>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php');?>
diff --git a/password_reminder.php b/password_reminder.php
new file mode 100644 (file)
index 0000000..cab0929
--- /dev/null
@@ -0,0 +1,163 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+$_user_location        = 'public';
+define('AT_INCLUDE_PATH', 'include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: login.php');
+       exit;
+
+} else if (isset($_POST['form_password_reminder'])) {
+
+       //get database info to create & email change-password-link
+       $_POST['form_email'] = $addslashes($_POST['form_email']);
+       $sql    = "SELECT member_id, login, password, email FROM ".TABLE_PREFIX."members WHERE email='$_POST[form_email]'";
+       $result = mysql_query($sql,$db);
+       if ($row = mysql_fetch_assoc($result)) {
+               
+               //date link was generated (# days since epoch)
+               $gen = intval(((time()/60)/60)/24);
+
+               $hash = sha1($row['member_id'] + $gen + $row['password']);
+               $hash_bit = substr($hash, 5, 15);
+               
+               $change_link = $_base_href.'password_reminder.php?id='.$row['member_id'].'&g='.$gen.'&h='.$hash_bit;
+
+               $tmp_message  = _AT(array('password_request2',$row['login'], $_base_href, AT_PASSWORD_REMINDER_EXPIRY, $change_link));
+
+               //send email
+               require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+               $mail = new ATutorMailer;
+               $mail->From     = $_config['contact_email'];
+               $mail->AddAddress($row['email']);
+               $mail->Subject = $_config['site_name'] . ': ' . _AT('password_forgot');
+               $mail->Body    = $tmp_message;
+
+               if(!$mail->Send()) {
+                  $msg->addError('SENDING_ERROR');
+                  $savant->display('password_reminder_feedback.tmpl.php'); 
+                  exit;
+               }
+
+               $msg->addFeedback('CONFIRM_EMAIL2');
+               unset($mail);
+
+               $savant->display('password_reminder_feedback.tmpl.php'); 
+
+       } else {
+               $msg->addError('EMAIL_NOT_FOUND');
+               $savant->display('password_reminder.tmpl.php'); 
+       }
+
+} else if (isset($_REQUEST['id']) && isset($_REQUEST['g']) && isset($_REQUEST['h'])) {
+//coming from an email link
+
+       //check if expired
+       $current = intval(((time()/60)/60)/24);
+       $expiry_date =  $_REQUEST['g'] + AT_PASSWORD_REMINDER_EXPIRY; //2 days after creation
+
+       if ($current > $expiry_date) {
+               $msg->addError('INVALID_LINK'); 
+               $savant->display('password_reminder_feedback.tmpl.php'); 
+               exit;
+       }
+
+       /* check if already visited (possibley add a "last login" field to members table)... if password was changed, won't work anyway. do later. */
+
+       //check for valid hash
+       $sql    = "SELECT password, email FROM ".TABLE_PREFIX."members WHERE member_id=".intval($_REQUEST['id']);
+       $result = mysql_query($sql,$db);
+       if ($row = mysql_fetch_assoc($result)) {
+               $email = $row['email'];
+
+               $hash = sha1($_REQUEST['id'] + $_REQUEST['g'] + $row['password']);
+               $hash_bit = substr($hash, 5, 15);
+
+               if ($_REQUEST['h'] != $hash_bit) {
+                       $msg->addError('INVALID_LINK');
+                       $savant->display('password_reminder_feedback.tmpl.php'); 
+               } else if (($_REQUEST['h'] == $hash_bit) && !isset($_POST['form_change'])) {
+                       $savant->assign('id', $_REQUEST['id']);
+                       $savant->assign('g', $_REQUEST['g']);
+                       $savant->assign('h', $_REQUEST['h']);
+                       $savant->display('password_change.tmpl.php');
+               }
+       } else {
+               $msg->addError('INVALID_LINK');
+               $savant->display('password_reminder_feedback.tmpl.php'); 
+               exit;
+       }
+
+       //changing the password
+       if (isset($_POST['form_change'])) {
+
+               /* password check: password is verified front end by javascript. here is to handle the errors from javascript */
+               if ($_POST['password_error'] <> "")
+               {
+                       $pwd_errors = explode(",", $_POST['password_error']);
+       
+                       foreach ($pwd_errors as $pwd_error)
+                       {
+                               if ($pwd_error == "missing_password")
+                                       $missing_fields[] = _AT('password');
+                               else
+                                       $msg->addError($pwd_error);
+                       }
+               }
+
+               if (!$msg->containsErrors()) {
+                       //save data
+                       $password   = $addslashes($_POST['form_password_hidden']);
+
+                       $sql    = "UPDATE ".TABLE_PREFIX."members SET password='".$password."', last_login=last_login WHERE member_id=".intval($_REQUEST['id']);
+                       $result = mysql_query($sql,$db);
+
+                       //send confirmation email
+                       require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+
+                       $tmp_message  = _AT(array('password_change_confirm', $_config['site_name'], $_base_href))."\n\n";
+
+                       $mail = new ATutorMailer;
+                       $mail->From     = $_config['contact_email'];
+                       $mail->AddAddress($email);
+                       $mail->Subject = $_config['site_name'] . ': ' . _AT('password_forgot');
+                       $mail->Body    = $tmp_message;
+
+                       if(!$mail->Send()) {
+                          $msg->printErrors('SENDING_ERROR');
+                          exit;
+                       }
+
+                       $msg->addFeedback('PASSWORD_CHANGED');
+                       unset($mail);
+                       
+                       header('Location:index.php');
+
+               } else {
+                       $savant->assign('id', $_REQUEST['id']);
+                       $savant->assign('g', $_REQUEST['g']);
+                       $savant->assign('h', $_REQUEST['h']);
+                       $savant->display('password_change.tmpl.php');
+               } 
+       }
+
+} else {
+       $savant->display('password_reminder.tmpl.php');
+}
+
+
+?>
\ No newline at end of file
diff --git a/polls/index.php b/polls/index.php
new file mode 100644 (file)
index 0000000..f414b65
--- /dev/null
@@ -0,0 +1,93 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                  */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton    */\r
+/* Adaptive Technology Resource Centre / University of Toronto             */\r
+/* http://atutor.ca                                                        */\r
+/*                                                                         */\r
+/* This program is free software. You can redistribute it and/or           */\r
+/* modify it under the terms of the GNU General Public License             */\r
+/* as published by the Free Software Foundation.                           */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+\r
+       if (isset($_POST['poll_submit'], $_POST['choice'])) {\r
+               $poll_id = intval($_POST['poll_id']);\r
+\r
+               $sql = "INSERT INTO ".TABLE_PREFIX."polls_members VALUES($poll_id, $_SESSION[member_id])";\r
+               if ($result = mysql_query($sql, $db)) {\r
+                       $n = intval($_POST['choice']);\r
+\r
+                       $sql = "UPDATE ".TABLE_PREFIX."polls SET count$n=count$n+1, total=total+1 WHERE poll_id=$poll_id AND course_id=$_SESSION[course_id]";\r
+                       $result = mysql_query($sql, $db);\r
+               }\r
+       }\r
+\r
+       if (!isset($include_all, $include_one)) {\r
+               $include_one = ' checked="checked"';\r
+       }\r
+\r
+       $sql = "SELECT * FROM ".TABLE_PREFIX."polls WHERE course_id=$_SESSION[course_id] ORDER BY question";\r
+       $result = mysql_query($sql, $db);\r
+       if (mysql_num_rows($result) == 0) {\r
+               $msg->addInfo('NO_POLLS');\r
+               $msg->printAll();\r
+               require(AT_INCLUDE_PATH.'footer.inc.php'); \r
+               exit;\r
+       }\r
+\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               echo '<form method="post" action="'.htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES).'">';\r
+               echo '<table width="70%" border="0" cellspacing="0" cellpadding="0" summary="" class="dropdown" align="center">';\r
+               echo '<tr>';\r
+               echo '<td valign="top" class="dropdown-heading" nowrap="nowrap" align="left"><strong>' . AT_print($row['question'], 'polls.question') . '</strong>';\r
+               echo '<input type="hidden" name="poll_id" value="'.$row['poll_id'].'" /></td></tr>';\r
+\r
+\r
+               if (!authenticate(AT_PRIV_POLLS, AT_PRIV_RETURN)) {\r
+                       $sql = "SELECT * FROM ".TABLE_PREFIX."polls_members WHERE poll_id=$row[poll_id] AND member_id=$_SESSION[member_id]";\r
+                       $my_result = mysql_query($sql, $db);\r
+               }\r
+\r
+               if (authenticate(AT_PRIV_POLLS, AT_PRIV_RETURN) || ($my_row = mysql_fetch_assoc($my_result))) {\r
+                       for ($i=1; $i<= AT_NUM_POLL_CHOICES; $i++) {\r
+                               if ($row['choice' . $i]) {\r
+                                       if ($row['total']) {\r
+                                               $width = round($row['count' . $i] / $row['total'] * 110);\r
+                                       } else {\r
+                                               $width = 0;\r
+                                       }\r
+\r
+                                       echo '<tr>';\r
+                                       echo '<td valign="top" class="dropdown" nowrap="nowrap" align="left">';\r
+                                       echo '<small>' . AT_print($row['choice' . $i], 'polls.choice') . '</small><br />';\r
+                                       echo '<img src="'.$_base_path . 'images/blue.gif" height="5" width="'.$width.'" alt="" /> '.$row['count' . $i];\r
+                                       echo '</td></tr>';\r
+                               }\r
+                       }\r
+               } else {\r
+                       for ($i=1; $i<= AT_NUM_POLL_CHOICES; $i++) {\r
+                               if ($row['choice' . $i]) {\r
+                                       echo '<tr>';\r
+                                       echo '<td valign="top" class="dropdown" nowrap="nowrap" align="left">';\r
+                                       echo '<small><input type="radio" name="choice" value="'.$i.'" id="xc'.$i.$row['poll_id'].'" /><label for="xc'.$i.$row['poll_id'].'">' . AT_print($row['choice' . $i], 'polls.choice') . '</label></small></td></tr>';\r
+                               }\r
+                       }\r
+\r
+                       echo '<tr>';\r
+                       echo '<td valign="top" class="dropdown" nowrap="nowrap" align="center"><input type="submit" name="poll_submit" value="'._AT('submit').'" class="button" />';\r
+                       echo '<br /><small>'._AT('vote_to_see_results').'</small>';\r
+                       echo '</td></tr>';\r
+               }\r
+               \r
+               echo '</table></form><br />';\r
+       }\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php'); \r
+?>
\ No newline at end of file
diff --git a/popuphelp.php b/popuphelp.php
new file mode 100644 (file)
index 0000000..79d5cd1
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                             */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+define('AT_INCLUDE_PATH', 'include/');
+
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+require(AT_INCLUDE_PATH.'html/frameset/header.inc.php');       
+?>
+[<a href="javascript:window.close()"><?php echo _AT('close_help_window'); ?></a>]
+<?php
+
+       /**
+        * Modified Jacek Materna
+        * Using Message.class.php layer to print
+        */
+       if ($_GET['h']) {
+               $h = $_GET['h'];
+               
+               if (is_string($_GET['h'])) { // just a AT_HELP code with no prefix
+                       $msg->printHelps($h);
+               } else {
+                       /* it's probably an array */
+                       $h = unserialize(urldecode(stripslashes($_GET['h'])));
+                       $msg->printHelps($h);
+               }
+       }
+?>
+</body>
+</html>
\ No newline at end of file
diff --git a/profile.php b/profile.php
new file mode 100644 (file)
index 0000000..a94205a
--- /dev/null
@@ -0,0 +1,57 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id: edit.php 3111 2005-01-18 19:32:00Z joel $\r
+\r
+define('AT_INCLUDE_PATH', 'include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+if (!$_SESSION['valid_user']) {\r
+       require(AT_INCLUDE_PATH.'header.inc.php');\r
+       $info = array('INVALID_USER', $_SESSION['course_id']);\r
+       $msg->printInfos($info);\r
+       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+\r
+$_GET['id'] = intval($_GET['id']);\r
+\r
+$sql   = 'SELECT member_id, login, website, first_name, second_name, last_name, email, private_email, phone FROM '.TABLE_PREFIX.'members WHERE member_id='.$_GET['id'];\r
+$result = mysql_query($sql,$db);\r
+if ($profile_row = mysql_fetch_assoc($result)) {\r
+       \r
+       //get privs\r
+       $sql    = 'SELECT `privileges`, approved FROM '.TABLE_PREFIX.'course_enrollment WHERE member_id='.$_GET['id'];\r
+       $result = mysql_query($sql,$db);\r
+       $row_en = mysql_fetch_assoc($result);\r
+\r
+       if ($system_courses[$_SESSION['course_id']]['member_id'] == $_GET['id']) {\r
+               $status = _AT('instructor');\r
+       } else if ( ($row_en['approved'] == 'y') && $row_en['privileges'] ) {\r
+               $status = _AT('assistant');\r
+       } else if ($row_en['approved'] == 'y') {\r
+               $status = _AT('enrolled');\r
+       }\r
+\r
+       $_pages['profile.php']['title'] = _AT($display_name_formats[$_config['display_name_format']], $profile_row['login'], $profile_row['first_name'], $profile_row['second_name'], $profile_row['last_name']);\r
+\r
+       require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+       $savant->assign('row', $profile_row);\r
+       $savant->assign('status', $status);\r
+       $savant->display('profile.tmpl.php');\r
+} else {\r
+       $msg->printErrors('NO_SUCH_USER');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/reading_list/add_resource_av.php b/reading_list/add_resource_av.php
new file mode 100644 (file)
index 0000000..996d618
--- /dev/null
@@ -0,0 +1,165 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_READING_LIST);
+
+// initial values for form
+$id = intval($_REQUEST['id']);
+$title = "";
+$author = "";
+$publisher = ""; 
+$date = ""; 
+$comments = "";
+$page_return = $_GET['page_return'];
+
+// check if user has submitted form
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+
+       header('Location: index_instructor.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $missing_fields = array();
+
+       if (trim($_POST['title']) == '') {
+               $missing_fields[] = _AT('title');
+       }
+       if (trim($_POST['author']) == '') {
+               $missing_fields[] = _AT('author');
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+
+       if (!$msg->containsErrors()) {
+               $_POST['title'] = $addslashes(validate_length($_POST['title'], 255));
+               $_POST['author'] = $addslashes(validate_length($_POST['author'], 150));
+               $_POST['publisher'] = $addslashes(validate_length($_POST['publisher'], 150));
+               $_POST['date'] = $addslashes($_POST['date']);
+               $_POST['comments'] = $addslashes(validate_length($_POST['comments'], 255));
+               
+               if ($id == '0'){ // creating a new URL resource
+                       $sql = "INSERT INTO ".TABLE_PREFIX."external_resources VALUES (NULL, $_SESSION[course_id],
+                       ".RL_TYPE_AV.", 
+                       '$_POST[title]', 
+                       '$_POST[author]', 
+                       '$_POST[publisher]', 
+                       '$_POST[date]', 
+                       '$_POST[comments]',
+                       '',
+                       '')";
+                       $result = mysql_query($sql,$db);
+
+                       // index to new URL resource
+                       $id_new = mysql_insert_id($db);
+
+                       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               } else { // modifying an existing URL resource
+
+                       $sql = "UPDATE ".TABLE_PREFIX."external_resources SET title='$_POST[title]', author='$_POST[author]', publisher='$_POST[publisher]', date='$_POST[date]', comments='$_POST[comments]' WHERE resource_id='$id' AND course_id=$_SESSION[course_id]";
+
+                       $result = mysql_query($sql,$db);
+
+                       // index to URL resource
+                       $id_new = $id;
+
+                       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               }
+
+               if (trim($_POST['page_return']) != ''){
+                       header('Location: '. $_POST['page_return']. '?existingbook='. $id_new);
+               } else {
+                       header('Location: index_instructor.php');
+               }
+               exit;
+       } else { // submission contained an error, update form values for redisplay
+               $title       = $stripslashes($_POST['title']);
+               $author      = $stripslashes($_POST['author']);
+               $publisher   = $stripslashes($_POST['publisher']);
+               $date        = $stripslashes($_POST['date']);
+               $comments    = $stripslashes($_POST['comments']);
+               $page_return = $stripslashes($_POST['page_return']);
+       }
+}
+
+// is user modifying an existing AV resource?
+if ($id && !isset($_POST['submit'])){
+       // yes, get resource from database
+       $id = intval ($_GET['id']);
+
+       $sql = "SELECT * FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND resource_id=$id";
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)){
+               $title     = $row['title'];
+               $author    = $row['author'];
+               $publisher = $row['publisher']; 
+               $date      = $row['date']; 
+               $comments  = $row['comments'];
+       }
+       // change title of page to 'edit AV resource' (default is 'add AV resource')
+       $_pages['reading_list/add_resource_av.php'][title_var] = 'rl_edit_resource_av';
+} else if ($id) {
+       $_pages['reading_list/add_resource_av.php'][title_var] = 'rl_edit_resource_av';
+}
+
+$onload = 'document.form.name.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="id" value="<?php echo $id ?>" />
+<input type="hidden" name="page_return" value="<?php echo $page_return ?>" />
+
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('rl_add_resource_av'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php  echo _AT('title'); ?></label><br />
+               <input type="text" name="title" size="35" id="title" value="<?php echo htmlspecialchars($title); ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="author"><?php  echo _AT('author'); ?></label><br />
+               <input type="text" name="author" size="25" id="author" value="<?php echo htmlspecialchars($author); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="date"><?php  echo _AT('rl_year_written'); ?></label><br />
+               <input type="text" name="date" size="6" id="date" value="<?php echo htmlspecialchars($date); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="publisher"><?php  echo _AT('rl_publisher'); ?></label><br />
+               <input type="text" name="publisher" size="20" id="publisher" value="<?php echo htmlspecialchars($publisher); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="comments"><?php  echo _AT('comment'); ?></label><br />
+               <textarea name="comments" cols="30" rows="2" id="comments"><?php echo htmlspecialchars($comments); ?></textarea>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/add_resource_book.php b/reading_list/add_resource_book.php
new file mode 100644 (file)
index 0000000..6a3ef0c
--- /dev/null
@@ -0,0 +1,174 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_READING_LIST);
+
+// initial values for form
+$id = intval($_REQUEST['id']);
+$title = "";
+$author = "";
+$publisher = ""; 
+$date = ""; 
+$comments = "";
+$isbn = "";
+$page_return = $_GET['page_return'];
+
+// check if user has submitted form
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+
+       header('Location: index_instructor.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $missing_fields = array();
+
+       if (trim($_POST['title']) == '') {
+               $missing_fields[] = _AT('title');
+       }
+       if (trim($_POST['author']) == '') {
+               $missing_fields[] = _AT('author');
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+
+       if (!$msg->containsErrors()) {
+               $_POST['title'] = $addslashes(validate_length($_POST['title'], 255));
+               $_POST['author'] = $addslashes(validate_length($_POST['author'], 150));
+               $_POST['publisher'] = $addslashes(validate_length($_POST['publisher'], 150));
+               $_POST['date']      = $addslashes($_POST['date']);
+               $_POST['comments'] = $addslashes(validate_length($_POST['comments'], 255));
+               $_POST['isbn']      = $addslashes($_POST['isbn']);
+               
+               if ($id == 0){ // creating a new book resource
+                       $sql = "INSERT INTO ".TABLE_PREFIX."external_resources VALUES (NULL, $_SESSION[course_id],
+                               ".RL_TYPE_BOOK.", 
+                               '$_POST[title]', 
+                               '$_POST[author]', 
+                               '$_POST[publisher]', 
+                               '$_POST[date]', 
+                               '$_POST[comments]',
+                               '$_POST[isbn]',
+                               '')";
+                       $result = mysql_query($sql,$db);
+
+                       // index to new book resource
+                       $id_new = mysql_insert_id($db);
+
+                       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               } else { // modifying an existing book resource
+
+                       $sql = "UPDATE ".TABLE_PREFIX."external_resources SET title='$_POST[title]', author='$_POST[author]', publisher='$_POST[publisher]', date='$_POST[date]', comments='$_POST[comments]', id='$_POST[isbn]' WHERE resource_id='$id' AND course_id=$_SESSION[course_id]";
+
+                       $result = mysql_query($sql,$db);
+
+                       // index to book resource
+                       $id_new = $id;
+
+                       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               }
+
+               if (trim($_POST['page_return']) != ''){
+                       header('Location: '. $_POST['page_return']. '?existingbook='. $id_new);
+               }
+               else {
+                       header('Location: index_instructor.php');
+               }
+               exit;
+       } else { // submission contained an error, update form values for redisplay
+               $title       = $stripslashes($_POST['title']);
+               $author      = $stripslashes($_POST['author']);
+               $publisher   = $stripslashes($_POST['publisher']);
+               $date        = $stripslashes($_POST['date']);
+               $comments    = $stripslashes($_POST['comments']);
+               $isbn        = $stripslashes($_POST['isbn']);
+               $page_return = $stripslashes($_POST['page_return']);
+       }
+}
+
+// is user modifying an existing book resource?
+if ($id && !isset($_POST['submit'])){
+       // yes, get resource from database
+
+       $sql = "SELECT * FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND resource_id=$id";
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)){
+               $title     = $row['title'];
+               $author    = $row['author'];
+               $publisher = $row['publisher']; 
+               $date      = $row['date']; 
+               $comments  = $row['comments'];
+               $isbn      = $row['id'];
+       }
+       // change title of page to 'edit book resource' (default is 'add book resource')
+       $_pages['reading_list/add_resource_book.php']['title_var'] = 'rl_edit_resource_book';
+} else if ($id) {
+       $_pages['reading_list/add_resource_book.php']['title_var'] = 'rl_edit_resource_book';
+}
+
+$onload = 'document.form.name.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="id" value="<?php echo $id ?>" />
+<input type="hidden" name="page_return" value="<?php echo $page_return ?>" />
+
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('rl_add_resource_book'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php  echo _AT('title'); ?></label><br />
+               <input type="text" name="title" size="35" id="title" value="<?php echo htmlspecialchars($title); ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="author"><?php  echo _AT('author'); ?></label><br />
+               <input type="text" name="author" size="25" id="author" value="<?php echo htmlspecialchars($author); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="date"><?php  echo _AT('rl_year_written'); ?></label><br />
+               <input type="text" name="date" size="6" id="date" value="<?php echo htmlspecialchars($date); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="publisher"><?php  echo _AT('rl_publisher'); ?></label><br />
+               <input type="text" name="publisher" size="20" id="publisher" value="<?php echo htmlspecialchars($publisher); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="isbn"><?php  echo _AT('rl_isbn_number'); ?></label><br />
+               <input type="text" name="isbn" size="15" id="isbn" value="<?php echo htmlspecialchars($isbn); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="comments"><?php  echo _AT('comment'); ?></label><br />
+               <textarea name="comments" cols="30" rows="2" id="comments"><?php echo htmlspecialchars($comments); ?></textarea>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/add_resource_file.php b/reading_list/add_resource_file.php
new file mode 100644 (file)
index 0000000..754000d
--- /dev/null
@@ -0,0 +1,173 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_READING_LIST);
+
+// initial values for form
+$id = intval($_REQUEST['id']);
+$title = "";
+$author = "";
+$publisher = ""; 
+$date = ""; 
+$comments = "";
+$isbn = "";
+$page_return = $_GET['page_return'];
+
+// check if user has submitted form
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+
+       header('Location: index_instructor.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $missing_fields = array();
+
+       if (trim($_POST['title']) == '') {
+               $missing_fields[] = _AT('title');
+       }
+       if (trim($_POST['author']) == '') {
+               $missing_fields[] = _AT('author');
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['title'] = $addslashes(validate_length($_POST['title'], 255));
+               $_POST['author'] = $addslashes(validate_length($_POST['author'], 150));
+               $_POST['publisher'] = $addslashes(validate_length($_POST['publisher'], 150));
+               $_POST['date']      = $addslashes($_POST['date']);
+               $_POST['comments'] = $addslashes(validate_length($_POST['comments'], 255));
+               $_POST['isbn']      = $addslashes($_POST['isbn']);
+               
+               if ($id == '0'){ // creating a new file resource
+                       $sql = "INSERT INTO ".TABLE_PREFIX."external_resources VALUES (NULL, $_SESSION[course_id],
+                               ".RL_TYPE_FILE.", 
+                               '$_POST[title]', 
+                               '$_POST[author]', 
+                               '$_POST[publisher]', 
+                               '$_POST[date]', 
+                               '$_POST[comments]',
+                               '$_POST[isbn]',
+                               '')";
+                       $result = mysql_query($sql,$db);
+
+                       // index to new file resource
+                       $id_new = mysql_insert_id($db);
+
+                       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               } else { // modifying an existing file resource
+
+                       $sql = "UPDATE ".TABLE_PREFIX."external_resources SET title='$_POST[title]', author='$_POST[author]', publisher='$_POST[publisher]', date='$_POST[date]', comments='$_POST[comments]', id='$_POST[isbn]' WHERE resource_id='$id' AND course_id=$_SESSION[course_id]";
+
+                       $result = mysql_query($sql,$db);
+
+                       // index to file resource
+                       $id_new = $id;
+
+                       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               }
+
+               if (trim($_POST['page_return']) != ''){
+                       header('Location: '. $_POST['page_return']. '?existingbook='. $id_new);
+               } else {
+                       header('Location: index_instructor.php');
+               }
+               exit;
+       } else { // submission contained an error, update form values for redisplay
+               $title       = $stripslashes($_POST['title']);
+               $author      = $stripslashes($_POST['author']);
+               $publisher   = $stripslashes($_POST['publisher']); 
+               $date        = $stripslashes($_POST['date']);
+               $comments    = $stripslashes($_POST['comments']);
+               $isbn        = $stripslashes($_POST['id']);
+               $page_return = $stripslashes($_POST['page_return']);
+       }
+}
+
+// is user modifying an existing file resource?
+if ($id && !isset($_POST['submit'])){
+       // yes, get resource from database
+       $id = intval ($_GET['id']);
+
+       $sql = "SELECT * FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND resource_id=$id";
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)){
+               $title     = $row['title'];
+               $author    = $row['author'];
+               $publisher = $row['publisher']; 
+               $date      = $row['date']; 
+               $comments  = $row['comments'];
+               $isbn      = $row['id'];
+       }
+       // change title of page to 'edit file resource' (default is 'add file resource')
+       $_pages['reading_list/add_resource_file.php']['title_var'] = 'rl_edit_resource_file';
+} else if ($id) {
+       $_pages['reading_list/add_resource_file.php']['title_var'] = 'rl_edit_resource_file';
+}
+
+$onload = 'document.form.name.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="id" value="<?php echo $id ?>" />
+<input type="hidden" name="page_return" value="<?php echo $page_return ?>" />
+
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('rl_add_resource_file'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php  echo _AT('title'); ?></label><br />
+               <input type="text" name="title" size="35" id="title" value="<?php echo htmlspecialchars($title); ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="author"><?php  echo _AT('author'); ?></label><br />
+               <input type="text" name="author" size="25" id="author" value="<?php echo htmlspecialchars($author); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="date"><?php  echo _AT('rl_year_written'); ?></label><br />
+               <input type="text" name="date" size="6" id="date" value="<?php echo htmlspecialchars($date); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="publisher"><?php  echo _AT('rl_publisher'); ?></label><br />
+               <input type="text" name="publisher" size="20" id="publisher" value="<?php echo htmlspecialchars($publisher); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="isbn"><?php  echo _AT('rl_isbn_number'); ?></label><br />
+               <input type="text" name="isbn" size="15" id="isbn" value="<?php echo htmlspecialchars($isbn); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="comments"><?php  echo _AT('comment'); ?></label><br />
+               <textarea name="comments" cols="30" rows="2" id="comments"><?php echo htmlspecialchars($comments); ?></textarea>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
diff --git a/reading_list/add_resource_handout.php b/reading_list/add_resource_handout.php
new file mode 100644 (file)
index 0000000..292a268
--- /dev/null
@@ -0,0 +1,156 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_READING_LIST);
+
+// initial values for form
+$id = intval($_REQUEST['id']);
+$title = "";
+$author = "";
+$date = ""; 
+$comments = "";
+$page_return = $_GET['page_return'];
+
+// check if user has submitted form
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+
+       header('Location: index_instructor.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $missing_fields = array();
+
+       if (trim($_POST['title']) == '') {
+               $missing_fields[] = _AT('title');
+       }
+       if (trim($_POST['author']) == '') {
+               $missing_fields[] = _AT('author');
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+
+       if (!$msg->containsErrors()) {
+               $_POST['title'] = $addslashes(validate_length($_POST['title'], 255));
+               $_POST['author'] = $addslashes(validate_length($_POST['author'], 150));
+               $_POST['date']     = $addslashes($_POST['date']);
+               $_POST['comments'] = $addslashes(validate_length($_POST['comments'], 255));
+               
+               if ($id == '0'){ // creating a new handout resource
+                       $sql = "INSERT INTO ".TABLE_PREFIX."external_resources VALUES (NULL, $_SESSION[course_id],
+                       ".RL_TYPE_HANDOUT.", 
+                       '$_POST[title]', 
+                       '$_POST[author]', 
+                       '', 
+                       '$_POST[date]', 
+                       '$_POST[comments]',
+                       '',
+                       '')";
+                       $result = mysql_query($sql,$db);
+
+                       // index to new handout resource
+                       $id_new = mysql_insert_id($db);
+
+                       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               } else { // modifying an existing handout resource
+
+                       $sql = "UPDATE ".TABLE_PREFIX."external_resources SET title='$_POST[title]', author='$_POST[author]', date='$_POST[date]', comments='$_POST[comments]' WHERE resource_id='$id' AND course_id=$_SESSION[course_id]";
+
+                       $result = mysql_query($sql,$db);
+
+                       // index to handout resource
+                       $id_new = $id;
+
+                       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               }
+
+               if (trim($_POST['page_return']) != ''){
+                       header('Location: '. $_POST['page_return']. '?existingbook='. $id_new);
+               } else {
+                       header('Location: index_instructor.php');
+               }
+               exit;
+       } else { // submission contained an error, update form values for redisplay
+               $title       = $stripslashes($_POST['title']);
+               $author      = $stripslashes($_POST['author']);
+               $date        = $stripslashes($_POST['date']);
+               $comments    = $stripslashes($_POST['comments']);
+               $page_return = $stripslashes($_POST['page_return']);
+       }
+}
+
+// is user modifying an existing handout resource?
+if ($id && !isset($_POST['submit'])){
+       // yes, get resource from database
+       $id = intval($_GET['id']);
+
+       $sql = "SELECT * FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND resource_id=$id";
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)){
+               $title    = $row['title'];
+               $author   = $row['author'];
+               $date     = $row['date']; 
+               $comments = $row['comments'];
+       }
+       // change title of page to 'edit handout resource' (default is 'add handout resource')
+       $_pages['reading_list/add_resource_handout.php']['title_var'] = 'rl_edit_resource_handout';
+} else if ($id) {
+       $_pages['reading_list/add_resource_handout.php']['title_var'] = 'rl_edit_resource_handout';
+}
+
+$onload = 'document.form.name.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="id" value="<?php echo $id; ?>" />
+<input type="hidden" name="page_return" value="<?php echo $page_return; ?>" />
+
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('rl_add_resource_handout'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php  echo _AT('title'); ?></label><br />
+               <input type="text" name="title" size="35" id="title" value="<?php echo htmlspecialchars($title); ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="author"><?php  echo _AT('author'); ?></label><br />
+               <input type="text" name="author" size="25" id="author" value="<?php echo htmlspecialchars($author); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="date"><?php  echo _AT('rl_year_written'); ?></label><br />
+               <input type="text" name="date" size="6" id="date" value="<?php echo htmlspecialchars($date); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="comments"><?php  echo _AT('comment'); ?></label><br />
+               <textarea name="comments" cols="30" rows="2" id="comments"><?php echo htmlspecialchars($comments); ?></textarea>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/add_resource_url.php b/reading_list/add_resource_url.php
new file mode 100644 (file)
index 0000000..4d1b929
--- /dev/null
@@ -0,0 +1,157 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_READING_LIST);
+
+// initial values for form
+$id = intval($_REQUEST['id']);
+$title = "";
+$author = "";
+$comments = "";
+$url = "";
+$page_return = $_GET['page_return'];
+
+// check if user has submitted form
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+
+       header('Location: index_instructor.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $missing_fields = array();
+
+       if (trim($_POST['title']) == '') {
+               $missing_fields[] = _AT('title');
+       }
+       if (trim($_POST['url']) == '') {
+               $missing_fields[] = _AT('url');
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['title'] = $addslashes(validate_length($_POST['title'], 255));
+               $_POST['author'] = $addslashes(validate_length($_POST['author'], 150));
+               $_POST['url'] = $addslashes($_POST['url']);
+               $_POST['comments'] = $addslashes(validate_length($_POST['comments'], 255));
+               
+               if ($id == '0'){ // creating a new URL resource
+                       $sql = "INSERT INTO ".TABLE_PREFIX."external_resources VALUES (NULL, $_SESSION[course_id],
+                       ".RL_TYPE_URL.", 
+                       '$_POST[title]', 
+                       '$_POST[author]', 
+                       '', 
+                       '', 
+                       '$_POST[comments]',
+                       '',
+                       '$_POST[url]')";
+                       $result = mysql_query($sql,$db);
+
+                       // index to new URL resource
+                       $id_new = mysql_insert_id($db);
+
+                       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               } else { // modifying an existing URL resource
+
+                       $sql = "UPDATE ".TABLE_PREFIX."external_resources SET title='$_POST[title]', author='$_POST[author]', url='$_POST[url]', comments='$_POST[comments]', id='$_POST[isbn]' WHERE resource_id='$id' AND course_id=$_SESSION[course_id]";
+
+                       $result = mysql_query($sql,$db);
+
+                       // index to URL resource
+                       $id_new = $id;
+
+                       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               }
+
+               if (trim($_POST['page_return']) != ''){
+                       header('Location: '. $_POST['page_return']. '?existingbook='. $id_new);
+               } else {
+                       header('Location: index_instructor.php');
+               }
+               exit;
+       } else { // submission contained an error, update form values for redisplay
+               $title       = $stripslashes($_POST['title']);
+               $author      = $stripslashes($_POST['author']);
+               $url         = $stripslashes($_POST['url']); 
+               $date        = $stripslashes($_POST['date']);
+               $comments    = $stripslashes($_POST['comments']);
+               $isbn        = $stripslashes($_POST['id']);
+               $page_return = $stripslashes($_POST['page_return']);
+       }
+}
+
+// is user modifying an existing URL resource?
+if ($id && !isset($_POST['submit'])){
+       // yes, get resource from database
+       $id = intval ($_GET['id']);
+
+       $sql = "SELECT * FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND resource_id=$id";
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)){
+               $title    = $row['title'];
+               $author   = $row['author'];
+               $comments = $row['comments'];
+               $url      = $row['url'];
+       }
+       // change title of page to 'edit URL resource' (default is 'add URL resource')
+       $_pages['reading_list/add_resource_url.php']['title_var'] = 'rl_edit_resource_url';
+} else if ($id) {
+       $_pages['reading_list/add_resource_url.php']['title_var'] = 'rl_edit_resource_url';
+}
+
+$onload = 'document.form.name.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="id" value="<?php echo $id ?>" />
+<input type="hidden" name="page_return" value="<?php echo $page_return ?>" />
+
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('rl_add_resource_url'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php  echo _AT('title'); ?></label><br />
+               <input type="text" name="title" size="35" id="title" value="<?php echo htmlspecialchars($title); ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="url"><?php  echo _AT('url'); ?></label><br />
+               <input type="text" name="url" size="50" id="url" value="<?php echo htmlspecialchars($url); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="author"><?php  echo _AT('author'); ?></label><br />
+               <input type="text" name="author" size="25" id="author" value="<?php echo htmlspecialchars($author); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="comments"><?php  echo _AT('comment'); ?></label><br />
+               <textarea name="comments" cols="30" rows="2" id="comments"><?php echo htmlspecialchars($comments); ?></textarea>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/delete_reading.php b/reading_list/delete_reading.php
new file mode 100644 (file)
index 0000000..db2b541
--- /dev/null
@@ -0,0 +1,61 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008                                      */\r
+/* Written by Greg Gay & Joel Kronenberg & Chris Ridpath        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_READING_LIST);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       Header('Location: index_instructor.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       $_POST['id'] = intval($_POST['id']);\r
+       $reading_id = $_POST['id'];\r
+\r
+       // delete the reading from the list\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."reading_list WHERE course_id=$_SESSION[course_id] AND reading_id=$reading_id";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: index_instructor.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$_GET['id'] = intval($_GET['id']); \r
+$reading_id = $_GET['id'];\r
+\r
+// get the resource ID for this reading\r
+$sql = "SELECT resource_id FROM ".TABLE_PREFIX."reading_list WHERE course_id=$_SESSION[course_id] AND reading_id=$reading_id";\r
+$result = mysql_query($sql, $db);\r
+\r
+if ($row = mysql_fetch_assoc($result)){\r
+       // get the external resource using the resource ID from the reading\r
+       $resource_id = $row['resource_id'];\r
+       $sql = "SELECT title, date FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND resource_id=$resource_id";\r
+       $resource_result = mysql_query($sql, $db);\r
+       if ($resource_row = mysql_fetch_assoc($resource_result)){\r
+               $hidden_vars['id'] = $reading_id;\r
+               $confirm = array('RL_DELETE_READING', $resource_row['title']);\r
+               $msg->addConfirm($confirm, $hidden_vars);\r
+               $msg->printConfirm();\r
+       }\r
+} else {\r
+       $msg->printErrors('ITEM_NOT_FOUND');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/reading_list/delete_resource.php b/reading_list/delete_resource.php
new file mode 100644 (file)
index 0000000..2cd0ef5
--- /dev/null
@@ -0,0 +1,60 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008                                      */\r
+/* Written by Greg Gay & Joel Kronenberg & Chris Ridpath        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_READING_LIST);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       Header('Location: display_resources.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       $_POST['id'] = intval($_POST['id']);\r
+       $resource_id = $_POST['id'];\r
+\r
+       // delete the resource from the list\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND resource_id=$resource_id";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       // find any readings that use this resource and delete them too\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."reading_list WHERE course_id=$_SESSION[course_id] AND resource_id=$resource_id";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: display_resources.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$_GET['id'] = intval($_GET['id']); \r
+$resource_id = $_GET['id'];\r
+\r
+// get the resource ID for this reading\r
+$sql = "SELECT title FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND resource_id=$resource_id";\r
+$result = mysql_query($sql, $db);\r
+\r
+if ($row = mysql_fetch_assoc($result)){\r
+       $hidden_vars['id'] = $resource_id;\r
+       $confirm = array('RL_DELETE_RESOURCE', $row['title']);\r
+       $msg->addConfirm($confirm, $hidden_vars);\r
+       $msg->printConfirm();\r
+}\r
+else {\r
+       $msg->addError('ITEM_NOT_FOUND');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/reading_list/display_resource.php b/reading_list/display_resource.php
new file mode 100644 (file)
index 0000000..03512ac
--- /dev/null
@@ -0,0 +1,143 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+if (isset($_GET['submit'])) { // was the 'back' button pressed?
+       header('Location: '.url_rewrite('reading_list/index.php', AT_PRETTY_URL_IS_HEADER));
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$id = intval ($_GET['id']);
+
+$sql = "SELECT * FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND resource_id=$id";
+$result = mysql_query($sql, $db);
+if (!$row = mysql_fetch_assoc($result)) {
+       // can't get resource from database
+       $msg->addError('ITEM_NOT_FOUND');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+?>
+<form action="<?php echo $_SERVER['PHP_SELF'];?>" method="get" name="form">
+<div class="input-form">
+
+       <?php if ($row['type'] == RL_TYPE_BOOK): ?>
+               <div class="row">
+                       <?php  echo _AT('title'). ": <strong>". $row['title']. "</strong>"; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('rl_type_of_resource'). ": ". _AT($_rl_types[$row['type']]); ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('author'). ": ". $row['author']; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('rl_publisher'). ": ". $row['publisher']; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('date'). ": ". $row['date']; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('rl_isbn_number'). ": ". $row['id']; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('comment'). ": ". $row['comments']; ?> 
+               </div>
+
+       <?php elseif ($row['type'] == RL_TYPE_URL): ?>
+               <div class="row">
+                       <?php  echo _AT('title'). ": <strong>". $row['title']. "</strong>"; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('rl_type_of_resource'). ": ". _AT($_rl_types[$row['type']]); ?> 
+               </div>
+               <div class="row">
+                       <?php echo _AT('location'). ": " ?><a href="<?php echo $row['url']?>"><?php echo $row['url']; ?></a> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('author'). ": ". $row['author']; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('comment'). ": ". $row['comments']; ?> 
+               </div>
+
+       <?php elseif ($row['type'] == RL_TYPE_HANDOUT): ?>
+               <div class="row">
+                       <?php  echo _AT('title'). ": <strong>". $row['title']. "</strong>"; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('rl_type_of_resource'). ": ". _AT($_rl_types[$row['type']]); ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('author'). ": ". $row['author']; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('date'). ": ". $row['date']; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('comment'). ": ". $row['comments']; ?> 
+               </div>
+
+       <?php elseif ($row['type'] == RL_TYPE_AV): ?>
+               <div class="row">
+                       <?php  echo _AT('title'). ": <strong>". $row['title']. "</strong>" ; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('rl_type_of_resource'). ": ". _AT($_rl_types[$row['type']]); ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('author'). ": ". $row['author']; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('date'). ": ". $row['date']; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('comment'). ": ". $row['comments']; ?> 
+               </div>
+
+       <?php elseif ($row['type'] == RL_TYPE_FILE): ?>
+               <div class="row">
+                       <?php  echo _AT('title'). ": <strong>". $row['title']. "</strong>"; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('rl_type_of_resource'). ": ". _AT($_rl_types[$row['type']]); ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('author'). ": ". $row['author']; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('rl_publisher'). ": ". $row['publisher']; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('date'). ": ". $row['date']; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('rl_id'). ": ". $row['id']; ?> 
+               </div>
+               <div class="row">
+                       <?php  echo _AT('comment'). ": ". $row['comments']; ?> 
+               </div>
+       <?php endif; ?>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('back'); ?>" />
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/display_resources.php b/reading_list/display_resources.php
new file mode 100644 (file)
index 0000000..5c2d721
--- /dev/null
@@ -0,0 +1,110 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_READING_LIST);
+
+if (isset($_GET['edit'])) {
+       $_GET['resource_id'] = intval($_GET['resource_id']);
+
+       // what kind of resource is user going to edit?
+       $sql = "SELECT type FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND resource_id=$_GET[resource_id]";
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)){
+               header('Location: add_resource_'.substr($_rl_types[$row['type']], 3).'.php?id='. $_GET['resource_id']. SEP. 'page_return=display_resources.php');
+       }
+} else if (isset($_GET['delete'])) {
+       $_GET['resource_id'] = intval($_GET['resource_id']);
+       header('Location: delete_resource.php?id='. $_GET['resource_id']);
+       exit;
+} else if (isset($_GET['create'])){
+       $_GET['new_resource'] = intval($_GET['new_resource']);
+       if (isset($_rl_types[$_GET['new_resource']])){
+               // Note: the '3' substring is used here to strip out the 'rl_' from the name
+               header('Location: add_resource_'.substr($_rl_types[$_GET['new_resource']], 3).'.php'. '?page_return=display_resources.php');
+               exit;
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$sql = "SELECT title, resource_id FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND type=".RL_TYPE_BOOK." ORDER BY title";
+$result = mysql_query($sql, $db);
+$num_books = mysql_num_rows($result);
+?>
+
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<div class="input-form" style="width: 30%">
+       <div class="row">
+               <label for="question"><?php echo _AT('rl_type_of_resource'); ?></label><br />
+               <select name="new_resource" class="dropdown" id="type">
+
+               <?php foreach ($_rl_types as $key => $value): ?>
+                       <option value="<?php echo $key; ?>"><?php echo _AT($value); ?></option>
+               <?php endforeach; ?>
+
+               </select>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="create" value="<?php echo _AT('create'); ?>" />
+       </div>
+</div>
+</form>
+
+<?php
+$sql = "SELECT * FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] ORDER BY type";
+$result = mysql_query($sql, $db);
+?>
+
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">
+<table class="data" style="width: 90%;">
+<thead>
+<tr>
+       <th>&nbsp;</th>
+       <th><?php echo _AT('type'); ?></th>
+       <th><?php echo _AT('title'); ?></th>
+       <th><?php echo _AT('author'); ?></th>
+</tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="6"><input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> 
+                                   <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /></td>
+</tr>
+</tfoot>
+<?php if ($row = mysql_fetch_assoc($result)) : ?>
+<tbody>
+               <?php $first=true; // check the first radio button ?>
+               <?php do { ?>
+                       <tr onmousedown="document.form['t<?php echo $row['resource_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $row['resource_id']; ?>_0">
+                               
+                       <td><input type="radio" id="t<?php echo $row['resource_id'];?>" name="resource_id" value="<?php echo $row['resource_id']; ?>"
+                       <?php if ($first == true){ echo 'checked="checked"'; $first=false;} ?>/></td>
+                       <td><?php echo _AT($_rl_types[$row['type']]); ?></td>
+                       <td><label for="t<?php echo $row['resource_id'];?>"><strong><?php echo $row['title']; ?></strong></label></td>
+                       <td><?php echo $row['author']; ?></td>
+                       </tr>
+               <?php } while($row = mysql_fetch_assoc($result)); ?>
+</tbody>
+<?php else: ?>
+       <tr>
+               <td colspan="2"><em><?php echo _AT('none_found'); ?></em></td>
+       </tr>
+<?php endif; ?>
+</table>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/edit_reading_av.php b/reading_list/edit_reading_av.php
new file mode 100644 (file)
index 0000000..507574f
--- /dev/null
@@ -0,0 +1,180 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_READING_LIST);
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index_instructor.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $_POST['id']         = intval($_POST['id']);
+       $_POST['existing']   = intval($_POST['existing']);
+       $_POST['hasdate']    = $addslashes($_POST['hasdate']);
+       $_POST['readstatus'] = $addslashes($_POST['readstatus']);
+       $_POST['comment']    = $addslashes($_POST['comment']);
+       $_POST['startday']   = intval($_POST['startday']);
+       $_POST['startmonth'] = intval($_POST['startmonth']);
+       $_POST['startyear']  = intval($_POST['startyear']);
+       $_POST['endday']     = intval($_POST['endday']);
+       $_POST['endmonth']   = intval($_POST['endmonth']);
+       $_POST['endyear']    = intval($_POST['endyear']);
+
+       $date_start = '0000-00-00';
+       $date_end = '0000-00-00';
+       if ($_POST['hasdate'] == 'true'){
+               $date_start = $_POST['startyear']. '-' .str_pad ($_POST['startmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['startday'], 2, "0", STR_PAD_LEFT);
+               $date_end = $_POST['endyear']. '-' .str_pad ($_POST['endmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['endday'], 2, "0", STR_PAD_LEFT);
+       }
+
+       $sql = "UPDATE ".TABLE_PREFIX."reading_list SET resource_id='$_POST[existing]', required='$_POST[readstatus]', comment='$_POST[comment]', date_start='$date_start', date_end='$date_end' WHERE reading_id='$_POST[id]' AND course_id=$_SESSION[course_id]";
+
+       $result = mysql_query($sql,$db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: index_instructor.php');
+       exit;
+}
+
+$onload = 'document.form.name.focus();';
+
+$today = getdate();
+
+$_GET['id'] = intval($_GET['id']);
+$reading_id = $_GET['id'];
+$resource_id = 0;
+
+// get the resource ID using the reading ID
+$sql = "SELECT * FROM ".TABLE_PREFIX."reading_list WHERE course_id=$_SESSION[course_id] AND reading_id=$reading_id";
+$result = mysql_query($sql, $db);
+if ($rowreading = mysql_fetch_assoc($result)) {
+       $resource_id = $rowreading['resource_id'];
+}
+
+// fill the select control using all the AV resources
+$sql = "SELECT title, resource_id FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND type=".RL_TYPE_AV." ORDER BY title";
+$av_result = mysql_query($sql, $db);
+
+$num_avs = mysql_num_rows($av_result);
+
+if ($num_avs == 0) {
+       header('Location: add_resource_av.php');
+       exit;
+}
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="id" value="<?php echo $reading_id ?>" />
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('rl_av_material_to_view'); ?></legend>
+<h3><?php echo _AT('rl_av_material_to_view');?></h3>
+       <div class="row">
+               <label for="title"><?php  echo _AT('select_av'); ?>:</label>
+               <select name="existing" id="title">
+                       <?php while ($row = mysql_fetch_assoc($av_result)): ?>
+                               <option value="<?php echo $row['resource_id']; ?>"<?php if ($row['resource_id'] == $resource_id) { echo ' selected="selected"'; } ?>><?php echo htmlspecialchars($row['title']); ?></option>
+                       <?php endwhile; ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <input type="radio" name="readstatus" value="required" id="required" <?php
+               if ($rowreading['required'] == 'required'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="required"><?php  echo _AT('required'); ?></label>
+               <input type="radio" name="readstatus" value="optional" id="optional" <?php
+               if ($rowreading['required'] == 'optional'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="optional"><?php  echo _AT('optional'); ?></label>
+       </div>  
+       
+       <div class="row">
+       <label for="comment"><?php  echo _AT('comment'); ?>:</label><input type="text" id="comment" size="75" name="comment" value="<?php echo htmlspecialchars($rowreading['comment']);  ?>" />
+       </div>
+
+<h3><?php echo _AT('rl_read_by_date'); ?></h3>
+
+       <div class="row">
+               <input type="radio" id="nodate" name="hasdate" value="false" <?php
+               if ($rowreading['date_start'] == '0000-00-00'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="nodate"><?php  echo _AT('rl_no_read_by_date'); ?></label>
+       </div>
+
+       <div class="row">
+               <input type="radio" id="hasdate" name="hasdate" value="true" <?php
+               if ($rowreading['date_start'] != '0000-00-00'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="hasdate"><?php  echo _AT('rl_reading_date'); ?></label><br/>
+
+               <label for="startdate"><?php  echo _AT('start_date'); ?>:</label>
+               <?php  $array_date_start = explode ('-', $rowreading['date_start'], 3); ?>
+
+               <select name="startday" id="startdate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_start[2]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+               
+               <select name="startmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_start[1]) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+
+               <select name="startyear">
+               <?php for ($i = ($today['year'] - '1'); $i <= ($today['year'] + '4'); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_start[0]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+               <br/><label for="enddate"><?php  echo _AT('end_date'); ?>:</label>
+               <?php  $array_date_end = explode ('-', $rowreading['date_end'], 3); ?>
+
+               <select name="endday" id="enddate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_end[2]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_end[1]) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endyear">
+               <?php for ($i = ($today['year'] - '1'); $i <= ($today['year'] + '4'); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_end[0]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/edit_reading_book.php b/reading_list/edit_reading_book.php
new file mode 100644 (file)
index 0000000..51fd446
--- /dev/null
@@ -0,0 +1,185 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_READING_LIST);
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index_instructor.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+
+       $_POST['id'] = intval($_POST['id']);
+       $_POST['existingbook'] = intval($_POST['existingbook']);
+       $_POST['hasdate'] = $addslashes($_POST['hasdate']);
+       $_POST['readstatus'] = $addslashes($_POST['readstatus']);
+       $_POST['comment'] = $addslashes($_POST['comment']);
+       $_POST['startday'] = intval($_POST['startday']);
+       $_POST['startmonth'] = intval($_POST['startmonth']);
+       $_POST['startyear'] = intval($_POST['startyear']);
+       $_POST['endday'] = intval($_POST['endday']);
+       $_POST['endmonth'] = intval($_POST['endmonth']);
+       $_POST['endyear'] = intval($_POST['endyear']);
+
+       $date_start = '0000-00-00';
+       $date_end = '0000-00-00';
+       if ($_POST['hasdate'] == 'true'){
+               $date_start = $_POST['startyear']. '-' .str_pad ($_POST['startmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['startday'], 2, "0", STR_PAD_LEFT);
+               $date_end = $_POST['endyear']. '-' .str_pad ($_POST['endmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['endday'], 2, "0", STR_PAD_LEFT);
+       }
+
+       $sql = "UPDATE ".TABLE_PREFIX."reading_list SET resource_id='$_POST[existingbook]', required='$_POST[readstatus]', comment='$_POST[comment]', date_start='$date_start', date_end='$date_end' WHERE reading_id='$_POST[id]' AND course_id=$_SESSION[course_id]";
+
+       $result = mysql_query($sql,$db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: index_instructor.php');
+       exit;
+}
+
+$onload = 'document.form.name.focus();';
+
+$today = getdate();
+
+$_GET['id'] = intval($_GET['id']);
+$reading_id = $_GET['id'];
+$resource_id = 0;
+
+// get the resource ID using the reading ID
+$sql = "SELECT * FROM ".TABLE_PREFIX."reading_list WHERE course_id=$_SESSION[course_id] AND reading_id=$reading_id";
+$result = mysql_query($sql, $db);
+if ($rowreading = mysql_fetch_assoc($result)) {
+       $resource_id = $rowreading['resource_id'];
+}
+
+// fill the select control using all the book resources
+$sql = "SELECT title, resource_id FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND type=".RL_TYPE_BOOK." ORDER BY title";
+$book_result = mysql_query($sql, $db);
+
+$num_books = mysql_num_rows($book_result);
+
+if ($num_books == 0) {
+       header('Location: add_resource_book.php');
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="id" value="<?php echo $reading_id ?>" />
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('rl_book_to_read'); ?></legend>
+<h3><?php echo _AT('rl_book_to_read'); ?></h3>
+       <div class="row">
+               <label for="booktitle"><?php  echo _AT('rl_select_book'); ?>:</label>
+               <select name="existingbook" id="booktitle">
+
+                       <?php while ($rowbook = mysql_fetch_assoc($book_result)): ?>
+                               <option value="<?php echo $rowbook['resource_id']; ?>"<?php if ($rowbook['resource_id'] == $resource_id) { echo ' selected="selected"'; } ?>><?php echo htmlspecialchars($rowbook['title']); ?></option>
+                       <?php endwhile; ?>
+               
+               </select>
+       </div>
+
+       <div class="row">
+               <input type="radio" name="readstatus" value="required" id="required" <?php
+               if ($rowreading['required'] == 'required'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="required"><?php  echo _AT('required'); ?></label>
+               <input type="radio" name="readstatus" value="optional" id="optional" <?php
+               if ($rowreading['required'] == 'optional'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="optional"><?php  echo _AT('optional'); ?></label>
+       </div>  
+       
+       <div class="row">
+       <label for="comment"><?php  echo _AT('comment'); ?>:</label><input type="text" id="comment" size="75" name="comment" value="<?php echo htmlspecialchars($rowreading['comment']);  ?>" />
+       </div>
+
+<h3><?php echo _AT('rl_read_by_date'); ?></h3>
+
+       <div class="row">
+               <input type="radio" id="nodate" name="hasdate" value="false" <?php
+               if ($rowreading['date_start'] == '0000-00-00'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="nodate"><?php  echo _AT('rl_no_read_by_date'); ?></label>
+       </div>
+
+       <div class="row">
+               <input type="radio" id="hasdate" name="hasdate" value="true" <?php
+               if ($rowreading['date_start'] != '0000-00-00'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="hasdate"><?php  echo _AT('rl_reading_date'); ?></label><br/>
+
+               <label for="startdate"><?php  echo _AT('start_date'); ?>:</label>
+               <?php  $array_date_start = explode ('-', $rowreading['date_start'], 3); ?>
+
+               <select name="startday" id="startdate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_start[2]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+               
+               <select name="startmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_start[1]) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+
+               <select name="startyear">
+               <?php for ($i = ($today['year'] - '1'); $i <= ($today['year'] + '4'); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_start[0]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+               <br/><label for="enddate"><?php  echo _AT('end_date'); ?>:</label>
+               <?php  $array_date_end = explode ('-', $rowreading['date_end'], 3); ?>
+
+               <select name="endday" id="enddate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_end[2]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_end[1]) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endyear">
+               <?php for ($i = ($today['year'] - '1'); $i <= ($today['year'] + '4'); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_end[0]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/edit_reading_file.php b/reading_list/edit_reading_file.php
new file mode 100644 (file)
index 0000000..9fbf40d
--- /dev/null
@@ -0,0 +1,181 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_READING_LIST);
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index_instructor.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $_POST['id'] = intval($_POST['id']);
+       $_POST['existing'] = intval($_POST['existing']);
+       $_POST['hasdate'] = $addslashes($_POST['hasdate']);
+       $_POST['readstatus'] = $addslashes($_POST['readstatus']);
+       $_POST['comment'] = $addslashes($_POST['comment']);
+       $_POST['startday'] = intval($_POST['startday']);
+       $_POST['startmonth'] = intval($_POST['startmonth']);
+       $_POST['startyear'] = intval($_POST['startyear']);
+       $_POST['endday'] = intval($_POST['endday']);
+       $_POST['endmonth'] = intval($_POST['endmonth']);
+       $_POST['endyear'] = intval($_POST['endyear']);
+
+       $date_start = '0000-00-00';
+       $date_end = '0000-00-00';
+       if ($_POST['hasdate'] == 'true'){
+               $date_start = $_POST['startyear']. '-' .str_pad ($_POST['startmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['startday'], 2, "0", STR_PAD_LEFT);
+               $date_end = $_POST['endyear']. '-' .str_pad ($_POST['endmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['endday'], 2, "0", STR_PAD_LEFT);
+       }
+
+       $sql = "UPDATE ".TABLE_PREFIX."reading_list SET resource_id='$_POST[existing]', required='$_POST[readstatus]', comment='$_POST[comment]', date_start='$date_start', date_end='$date_end' WHERE reading_id='$_POST[id]' AND course_id=$_SESSION[course_id]";
+
+       $result = mysql_query($sql,$db);
+
+       $msg->addFeedback('FILE_EDITED');
+       header('Location: index_instructor.php');
+       exit;
+}
+
+$onload = 'document.form.name.focus();';
+
+$today = getdate();
+
+$_GET['id'] = intval($_GET['id']);
+$reading_id = $_GET['id'];
+$resource_id = 0;
+
+// get the resource ID using the reading ID
+$sql = "SELECT * FROM ".TABLE_PREFIX."reading_list WHERE course_id=$_SESSION[course_id] AND reading_id=$reading_id";
+$result = mysql_query($sql, $db);
+if ($rowreading = mysql_fetch_assoc($result)) {
+       $resource_id = $rowreading['resource_id'];
+}
+
+// fill the select control using all the file resources
+$sql = "SELECT title, resource_id FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND type=".RL_TYPE_FILE." ORDER BY title";
+$file_result = mysql_query($sql, $db);
+
+$num_files = mysql_num_rows($file_result);
+
+if ($num_files == 0) {
+       header('Location: add_resource_file.php');
+       exit;
+}
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="id" value="<?php echo $reading_id ?>" />
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('file_to_read'); ?></legend>
+       <div class="row">
+               <label for="title"><?php  echo _AT('rl_select_file'); ?>:</label>
+               <select name="existing" id="title">
+
+                       <?php while ($row = mysql_fetch_assoc($file_result)): ?>
+                               <option value="<?php echo $row['resource_id']; ?>"<?php if ($row['resource_id'] == $resource_id) { echo ' selected="selected"'; } ?>><?php echo htmlspecialchars($row['title']); ?></option>
+                       <?php endwhile; ?>
+               
+               </select>
+       </div>
+
+       <div class="row">
+               <input type="radio" name="readstatus" value="required" id="required" <?php
+               if ($rowreading['required'] == 'required'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="required"><?php  echo _AT('required'); ?></label>
+               <input type="radio" name="readstatus" value="optional" id="optional" <?php
+               if ($rowreading['required'] == 'optional'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="optional"><?php  echo _AT('optional'); ?></label>
+       </div>  
+       
+       <div class="row">
+       <label for="comment"><?php  echo _AT('comment'); ?>:</label><input type="text" id="comment" size="75" name="comment" value="<?php echo htmlspecialchars($rowreading['comment']);  ?>" />
+       </div>
+
+<h3><?php echo _AT('rl_read_by_date'); ?></h3>
+       <div class="row">
+               <input type="radio" id="nodate" name="hasdate" value="false" <?php
+               if ($rowreading['date_start'] == '0000-00-00'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="nodate"><?php  echo _AT('rl_no_read_by_date'); ?></label>
+       </div>
+
+       <div class="row">
+               <input type="radio" id="hasdate" name="hasdate" value="true" <?php
+               if ($rowreading['date_start'] != '0000-00-00'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="hasdate"><?php  echo _AT('rl_reading_date'); ?></label><br/>
+
+               <label for="startdate"><?php  echo _AT('start_date'); ?>:</label>
+               <?php  $array_date_start = explode ('-', $rowreading['date_start'], 3); ?>
+
+               <select name="startday" id="startdate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_start[2]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+               
+               <select name="startmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_start[1]) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+
+               <select name="startyear">
+               <?php for ($i = ($today['year'] - '1'); $i <= ($today['year'] + '4'); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_start[0]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+               <br/><label for="enddate"><?php  echo _AT('end_date'); ?>:</label>
+               <?php  $array_date_end = explode ('-', $rowreading['date_end'], 3); ?>
+
+               <select name="endday" id="enddate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_end[2]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_end[1]) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endyear">
+               <?php for ($i = ($today['year'] - '1'); $i <= ($today['year'] + '4'); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_end[0]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/edit_reading_handout.php b/reading_list/edit_reading_handout.php
new file mode 100644 (file)
index 0000000..e0f84e0
--- /dev/null
@@ -0,0 +1,180 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_READING_LIST);
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index_instructor.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $_POST['id']         = intval($_POST['id']);
+       $_POST['existing']   = intval($_POST['existing']);
+       $_POST['hasdate']    = $addslashes($_POST['hasdate']);
+       $_POST['readstatus'] = $addslashes($_POST['readstatus']);
+       $_POST['comment']    = $addslashes($_POST['comment']);
+       $_POST['startday']   = intval($_POST['startday']);
+       $_POST['startmonth'] = intval($_POST['startmonth']);
+       $_POST['startyear']  = intval($_POST['startyear']);
+       $_POST['endday']     = intval($_POST['endday']);
+       $_POST['endmonth']   = intval($_POST['endmonth']);
+       $_POST['endyear']    = intval($_POST['endyear']);
+
+       $date_start = '0000-00-00';
+       $date_end = '0000-00-00';
+       if ($_POST['hasdate'] == 'true'){
+               $date_start = $_POST['startyear']. '-' .str_pad ($_POST['startmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['startday'], 2, "0", STR_PAD_LEFT);
+               $date_end = $_POST['endyear']. '-' .str_pad ($_POST['endmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['endday'], 2, "0", STR_PAD_LEFT);
+       }
+
+       $sql = "UPDATE ".TABLE_PREFIX."reading_list SET resource_id='$_POST[existing]', required='$_POST[readstatus]', comment='$_POST[comment]', date_start='$date_start', date_end='$date_end' WHERE reading_id='$_POST[id]' AND course_id=$_SESSION[course_id]";
+
+       $result = mysql_query($sql,$db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: index_instructor.php');
+       exit;
+}
+
+$onload = 'document.form.name.focus();';
+
+
+$today = getdate();
+
+$_GET['id'] = intval($_GET['id']);
+$reading_id = $_GET['id'];
+$resource_id = 0;
+
+// get the resource ID using the reading ID
+$sql = "SELECT * FROM ".TABLE_PREFIX."reading_list WHERE course_id=$_SESSION[course_id] AND reading_id=$reading_id";
+$result = mysql_query($sql, $db);
+if ($rowreading = mysql_fetch_assoc($result)) {
+       $resource_id = $rowreading['resource_id'];
+}
+
+// fill the select control using all the handout resources
+$sql = "SELECT title, resource_id FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND type=".RL_TYPE_HANDOUT." ORDER BY title";
+$handout_result = mysql_query($sql, $db);
+
+$num_handouts = mysql_num_rows($handout_result);
+
+if ($num_handouts == 0) {
+       header('Location: add_resource_handout.php');
+       exit;
+}
+require(AT_INCLUDE_PATH.'header.inc.php');
+       
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="id" value="<?php echo $reading_id ?>" />
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('handout_to_read'); ?></legend>
+       <div class="row">
+               <label for="title"><?php  echo _AT('rl_select_handout'); ?>:</label>
+               <select name="existing" id="title">
+                       <?php while ($row = mysql_fetch_assoc($handout_result)): ?>
+                               <option value="<?php echo $row['resource_id']; ?>"<?php if ($row['resource_id'] == $resource_id) { echo ' selected="selected"'; } ?>><?php echo htmlspecialchars($row['title']); ?></option>
+                       <?php endwhile; ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <input type="radio" name="readstatus" value="required" id="required" <?php
+               if ($rowreading['required'] == 'required'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="required"><?php  echo _AT('required'); ?></label>
+               <input type="radio" name="readstatus" value="optional" id="optional" <?php
+               if ($rowreading['required'] == 'optional'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="optional"><?php  echo _AT('optional'); ?></label>
+       </div>  
+       
+       <div class="row">
+       <label for="comment"><?php  echo _AT('comment'); ?>:</label><input type="text" id="comment" size="75" name="comment" value="<?php echo htmlspecialchars($rowreading['comment']);  ?>" />
+       </div>
+
+<h3><?php echo _AT('rl_read_by_date'); ?></h3>
+       <div class="row">
+               <input type="radio" id="nodate" name="hasdate" value="false" <?php
+               if ($rowreading['date_start'] == '0000-00-00'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="nodate"><?php  echo _AT('rl_no_read_by_date'); ?></label>
+       </div>
+
+       <div class="row">
+               <input type="radio" id="hasdate" name="hasdate" value="true" <?php
+               if ($rowreading['date_start'] != '0000-00-00'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="hasdate"><?php  echo _AT('rl_reading_date'); ?></label><br/>
+
+               <label for="startdate"><?php  echo _AT('start_date'); ?>:</label>
+               <?php  $array_date_start = explode ('-', $rowreading['date_start'], 3); ?>
+
+               <select name="startday" id="startdate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_start[2]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+               
+               <select name="startmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_start[1]) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+
+               <select name="startyear">
+               <?php for ($i = ($today['year'] - '1'); $i <= ($today['year'] + '4'); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_start[0]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+               <br/><label for="enddate"><?php  echo _AT('end_date'); ?>:</label>
+               <?php  $array_date_end = explode ('-', $rowreading['date_end'], 3); ?>
+
+               <select name="endday" id="enddate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_end[2]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_end[1]) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endyear">
+               <?php for ($i = ($today['year'] - '1'); $i <= ($today['year'] + '4'); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_end[0]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/edit_reading_url.php b/reading_list/edit_reading_url.php
new file mode 100644 (file)
index 0000000..3a7239f
--- /dev/null
@@ -0,0 +1,180 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_READING_LIST);
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index_instructor.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $_POST['id']         = intval($_POST['id']);
+       $_POST['existing']   = intval($_POST['existing']);
+       $_POST['hasdate']    = $addslashes($_POST['hasdate']);
+       $_POST['readstatus'] = $addslashes($_POST['readstatus']);
+       $_POST['comment']    = $addslashes($_POST['comment']);
+       $_POST['startday']   = intval($_POST['startday']);
+       $_POST['startmonth'] = intval($_POST['startmonth']);
+       $_POST['startyear']  = intval($_POST['startyear']);
+       $_POST['endday']     = intval($_POST['endday']);
+       $_POST['endmonth']   = intval($_POST['endmonth']);
+       $_POST['endyear']    = intval($_POST['endyear']);
+
+       $date_start = '0000-00-00';
+       $date_end = '0000-00-00';
+       if ($_POST['hasdate'] == 'true'){
+               $date_start = $_POST['startyear']. '-' .str_pad ($_POST['startmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['startday'], 2, "0", STR_PAD_LEFT);
+               $date_end = $_POST['endyear']. '-' .str_pad ($_POST['endmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['endday'], 2, "0", STR_PAD_LEFT);
+       }
+
+       $sql = "UPDATE ".TABLE_PREFIX."reading_list SET resource_id='$_POST[existing]', required='$_POST[readstatus]', comment='$_POST[comment]', date_start='$date_start', date_end='$date_end' WHERE reading_id='$_POST[id]' AND course_id=$_SESSION[course_id]";
+
+       $result = mysql_query($sql,$db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: index_instructor.php');
+       exit;
+}
+
+$onload = 'document.form.name.focus();';
+
+$today = getdate();
+
+$_GET['id'] = intval($_GET['id']);
+$reading_id = $_GET['id'];
+$resource_id = 0;
+
+// get the resource ID using the reading ID
+$sql = "SELECT * FROM ".TABLE_PREFIX."reading_list WHERE course_id=$_SESSION[course_id] AND reading_id=$reading_id";
+$result = mysql_query($sql, $db);
+if ($rowreading = mysql_fetch_assoc($result)) {
+       $resource_id = $rowreading['resource_id'];
+}
+
+// fill the select control using all the URL resources
+$sql = "SELECT title, resource_id FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND type=".RL_TYPE_URL." ORDER BY title";
+$url_result = mysql_query($sql, $db);
+
+$num_urls = mysql_num_rows($url_result);
+
+if ($num_urls == 0) {
+       header('Location: add_resource_url.php');
+       exit;
+}
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="id" value="<?php echo $reading_id ?>" />
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('url_to_read'); ?></legend>
+
+       <div class="row">
+               <label for="title"><?php  echo _AT('rl_select_url'); ?>:</label>
+               <select name="existing" id="title">
+                       <?php while ($row = mysql_fetch_assoc($url_result)): ?>
+                               <option value="<?php echo $row['resource_id']; ?>"<?php if ($row['resource_id'] == $resource_id) { echo ' selected="selected"'; } ?>><?php echo htmlspecialchars($row['title']); ?></option>
+                       <?php endwhile; ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <input type="radio" name="readstatus" value="required" id="required" <?php
+               if ($rowreading['required'] == 'required'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="required"><?php  echo _AT('required'); ?></label>
+               <input type="radio" name="readstatus" value="optional" id="optional" <?php
+               if ($rowreading['required'] == 'optional'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="optional"><?php  echo _AT('optional'); ?></label>
+       </div>  
+       
+       <div class="row">
+       <label for="comment"><?php  echo _AT('comment'); ?>:</label><input type="text" id="comment" size="75" name="comment" value="<?php echo htmlspecialchars($rowreading['comment']);  ?>" />
+       </div>
+
+<h3><?php echo _AT('rl_read_by_date'); ?></h3>
+
+       <div class="row">
+               <input type="radio" id="nodate" name="hasdate" value="false" <?php
+               if ($rowreading['date_start'] == '0000-00-00'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="nodate"><?php  echo _AT('rl_no_read_by_date'); ?></label>
+       </div>
+
+       <div class="row">
+               <input type="radio" id="hasdate" name="hasdate" value="true" <?php
+               if ($rowreading['date_start'] != '0000-00-00'){
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="hasdate"><?php  echo _AT('rl_reading_date'); ?></label><br/>
+
+               <label for="startdate"><?php  echo _AT('start_date'); ?>:</label>
+               <?php  $array_date_start = explode ('-', $rowreading['date_start'], 3); ?>
+
+               <select name="startday" id="startdate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_start[2]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+               
+               <select name="startmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_start[1]) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+
+               <select name="startyear">
+               <?php for ($i = ($today['year'] - '1'); $i <= ($today['year'] + '4'); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_start[0]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+               <br/><label for="enddate"><?php  echo _AT('end_date'); ?>:</label>
+               <?php  $array_date_end = explode ('-', $rowreading['date_end'], 3); ?>
+
+               <select name="endday" id="enddate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_end[2]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_end[1]) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endyear">
+               <?php for ($i = ($today['year'] - '1'); $i <= ($today['year'] + '4'); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $array_date_end[0]) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/index.php b/reading_list/index.php
new file mode 100644 (file)
index 0000000..91b6a32
--- /dev/null
@@ -0,0 +1,77 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008                                      */\r
+/* Written by Greg Gay & Joel Kronenberg & Chris Ridpath        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+require (AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$sql = "SELECT * FROM ".TABLE_PREFIX."reading_list WHERE course_id=$_SESSION[course_id] ORDER BY date_start";\r
+$result = mysql_query($sql, $db);\r
+?>\r
+\r
+<table class="data" style="width: 90%;">\r
+<thead>\r
+<tr>\r
+       <th><?php echo _AT('rl_start');    ?></th>\r
+       <th><?php echo _AT('rl_end');      ?></th>\r
+       <th><?php echo _AT('title');       ?></th>\r
+       <th><?php echo _AT('required'); ?></th>\r
+       <th><?php echo _AT('comment');  ?></th>\r
+</tr>\r
+</thead>\r
+<tbody>\r
+<?php if ($row = mysql_fetch_assoc($result)): ?>\r
+\r
+       <?php do { ?>\r
+                       <?php // get the external resource using the resource ID from the reading\r
+                       $id = $row['resource_id'];\r
+                       $sql = "SELECT title, type, url FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND resource_id=$id";\r
+                       $resource_result = mysql_query($sql, $db);\r
+                       if ($resource_row = mysql_fetch_assoc($resource_result)){ \r
+                       ?>\r
+                       <tr onclick="document.location='reading_list/display_resource.php?id=<?php echo $id ?>'">\r
+                               <td>\r
+                               <?php  if ($row['date_start'] == '0000-00-00'){\r
+                                       echo _AT ('none');\r
+                               } else {\r
+                                       echo AT_Date(_AT('rl_date_format'), $row['date_start'], AT_DATE_MYSQL_DATETIME);\r
+                               }?>\r
+                               </td>\r
+\r
+                               <td>\r
+                               <?php  if ($row['date_end'] == '0000-00-00'){\r
+                                       echo _AT ('none');\r
+                               } else {\r
+                                       echo AT_Date(_AT('rl_date_format'), $row['date_end'], AT_DATE_MYSQL_DATETIME);\r
+                               }?>\r
+                               </td>\r
+\r
+                               <td><a href="<?php echo url_rewrite('reading_list/display_resource.php?id='.$id); ?>" title="<?php echo _AT('rl_view_resource_details')?>" ><?php echo $resource_row['title']; ?></a>           \r
+                               </td>\r
+                               <td><?php echo _AT ($row['required']); ?></td>\r
+                               <td><?php echo $row['comment']; ?></td>\r
+                               </tr>\r
+\r
+                       <?php } ?>\r
+       <?php } while($row = mysql_fetch_assoc($result)); ?>\r
+<?php else: ?>\r
+       <tr>\r
+               <td colspan="3"><em><?php echo _AT('none_found'); ?></em></td>\r
+       </tr>\r
+<?php endif; ?>\r
+</tbody>\r
+</table>\r
+\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/index_instructor.php b/reading_list/index_instructor.php
new file mode 100644 (file)
index 0000000..e75bcd8
--- /dev/null
@@ -0,0 +1,162 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008                                      */\r
+/* Written by Greg Gay & Joel Kronenberg & Chris Ridpath        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_READING_LIST);\r
+\r
+if (isset($_GET['edit'])) {\r
+       if (!isset($_GET['reading'])) {\r
+               $msg->addError('NO_ITEM_SELECTED');\r
+               header('Location: index_instructor.php');\r
+               exit;\r
+       }\r
+\r
+       // reading ID of item that will be edited\r
+       $_GET['reading'] = intval($_GET['reading']);\r
+\r
+       // get resource ID of reading\r
+       $sql = "SELECT resource_id FROM ".TABLE_PREFIX."reading_list WHERE course_id=$_SESSION[course_id] AND reading_id=$_GET[reading]";\r
+       $result = mysql_query($sql, $db);\r
+       if ($row = mysql_fetch_assoc($result)){\r
+               // what kind of resource is it? (book, URL, file etc.)\r
+               $sql = "SELECT type FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND resource_id=$row[resource_id]";\r
+               $result = mysql_query($sql, $db);\r
+               if ($row = mysql_fetch_assoc($result)){\r
+                       // display the correct page for editing the resource\r
+                       header('Location: edit_reading_'.substr($_rl_types[$row['type']], 3).'.php?id='. $_GET['reading']);\r
+                       exit;\r
+               }\r
+       }\r
+       $msg->addError('ITEM_NOT_FOUND');\r
+} else if (isset($_GET['delete'])) {\r
+       if (!isset($_GET['reading'])) {\r
+               $msg->addError('NO_ITEM_SELECTED');\r
+               header('Location: index_instructor.php');\r
+               exit;\r
+       }\r
+       $_GET['reading'] = intval($_GET['reading']);\r
+       header('Location: delete_reading.php?id='. $_GET['reading']);\r
+       exit;\r
+} else if (isset($_GET['create'])){\r
+       $_GET['new_reading'] = intval($_GET['new_reading']);\r
+\r
+       if (isset($_rl_types[$_GET['new_reading']])){\r
+               // Note: the '3' substring is used here to strip out the 'rl_' from the name\r
+               header('Location: new_reading_'.substr($_rl_types[$_GET['new_reading']], 3).'.php');\r
+               exit;\r
+       }\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+?>\r
+\r
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<div class="input-form" style="width: 50%">\r
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('create'); ?></legend>\r
+       <div class="row">\r
+               <label for="question"><?php echo _AT('rl_type_of_reading'); ?></label><br />\r
+               <select name="new_reading" class="dropdown" id="type">\r
+\r
+               <?php foreach ($_rl_types as $key => $value): ?>\r
+                       <option value="<?php echo $key; ?>"><?php echo _AT($value); ?></option>\r
+               <?php endforeach; ?>\r
+\r
+               </select>\r
+       </div>\r
+       <div class="row buttons">\r
+               <input type="submit" name="create" value="<?php echo _AT('create'); ?>" />\r
+       </div>\r
+       </fieldset>\r
+</div>\r
+</form>\r
+\r
+<?php\r
+$sql = "SELECT * FROM ".TABLE_PREFIX."reading_list WHERE course_id=$_SESSION[course_id] ORDER BY date_start";\r
+$result = mysql_query($sql, $db);\r
+?>\r
+\r
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">\r
+<table class="data" style="width: 90%;">\r
+<thead>\r
+<tr>\r
+       <th>&nbsp;</th>\r
+       <th><?php echo _AT('rl_start'); ?></th>\r
+       <th><?php echo _AT('rl_end'); ?></th>\r
+       <th><?php echo _AT('title'); ?></th>\r
+       <th><?php echo _AT('required'); ?></th>\r
+       <th><?php echo _AT('comment'); ?></th>\r
+</tr>\r
+</thead>\r
+<tfoot>\r
+<tr>\r
+       <td colspan="6">\r
+               <input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> \r
+               <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" />\r
+       </td>\r
+</tr>\r
+</tfoot>\r
+<?php if ($row = mysql_fetch_assoc($result)): ?>\r
+<tbody>\r
+               <?php do { ?>\r
+\r
+                       <?php // get the external resource using the resource ID from the reading\r
+                       $id = $row['resource_id'];\r
+                       $sql = "SELECT title FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND resource_id=$id";\r
+                       $resource_result = mysql_query($sql, $db);\r
+                       if ($resource_row = mysql_fetch_assoc($resource_result)){ \r
+                       ?>\r
+                               <tr onmousedown="document.form['t<?php echo $row['reading_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $row['reading_id']; ?>_0">\r
+                               \r
+                               <td><input type="radio" id="t<?php echo $row['reading_id']; ?>" name="reading" value="<?php echo $row['reading_id']; ?>" \r
+\r
+                               <?php // set first item as checked if nothing selected\r
+                               if (isset($_GET['reading'])){\r
+                                       if ($_GET['reading'] == $row['reading_id']){ \r
+                                               echo ' checked="checked"'; \r
+                                       } \r
+                               } else {\r
+                                       echo ' checked="checked"';\r
+                                       $_GET['reading'] = $row['reading_id'];\r
+                               }\r
+                               ?> /></td>\r
+                               <td><?php  if ($row['date_start'] == '0000-00-00'){\r
+                                       echo _AT ('none');\r
+                               }else {\r
+                                       echo AT_Date(_AT('rl_date_format'), $row['date_start'], AT_DATE_MYSQL_DATETIME);\r
+                               }?></td>\r
+\r
+                               <td><?php  if ($row['date_end'] == '0000-00-00'){\r
+                                       echo _AT ('none');\r
+                               }else {\r
+                                       echo AT_Date(_AT('rl_date_format'), $row['date_end'], AT_DATE_MYSQL_DATETIME);\r
+                               }?></td>\r
+                               <td><label for="t<?php echo $row['reading_id'];?>"><strong><?php echo $resource_row['title']; ?></strong></label></td>\r
+                               <td><?php echo _AT ($row['required']); ?></td>\r
+                               <td><?php echo $row['comment']; ?></td>\r
+                               </tr>\r
+\r
+                       <?php } ?>\r
+\r
+               <?php } while($row = mysql_fetch_assoc($result)); ?>\r
+</tbody>\r
+<?php else: ?>\r
+       <tr>\r
+               <td colspan="6"><em><?php echo _AT('none_found'); ?></em></td>\r
+       </tr>\r
+<?php endif; ?>\r
+</table>\r
+</form>\r
+\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/new_reading_av.php b/reading_list/new_reading_av.php
new file mode 100644 (file)
index 0000000..75c0966
--- /dev/null
@@ -0,0 +1,181 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_READING_LIST);
+
+$existing = -1;
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index_instructor.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+
+       $_POST['existing']   = intval($_POST['existing']);
+       $existing            = $_POST['existing'];
+       $_POST['hasdate']    = $addslashes($_POST['hasdate']);
+       $_POST['readstatus'] = $addslashes($_POST['readstatus']);
+       $_POST['comment']    = $addslashes($_POST['comment']);
+       $_POST['startday']   = intval($_POST['startday']);
+       $_POST['startmonth'] = intval($_POST['startmonth']);
+       $_POST['startyear']  = intval($_POST['startyear']);
+       $_POST['endday']     = intval($_POST['endday']);
+       $_POST['endmonth']   = intval($_POST['endmonth']);
+       $_POST['endyear']    = intval($_POST['endyear']);
+
+       $date_start = '0000-00-00';
+       $date_end = '0000-00-00';
+       if ($_POST['hasdate'] == 'true'){
+               $date_start = $_POST['startyear']. '-' .str_pad ($_POST['startmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['startday'], 2, "0", STR_PAD_LEFT);
+               $date_end = $_POST['endyear']. '-' .str_pad ($_POST['endmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['endday'], 2, "0", STR_PAD_LEFT);
+       }
+
+       $sql = "INSERT INTO ".TABLE_PREFIX."reading_list VALUES (NULL, $_SESSION[course_id],
+               '$_POST[existing]',
+               '$_POST[readstatus]',
+               '$date_start',
+               '$date_end',
+               '$_POST[comment]'
+               )";
+       $result = mysql_query($sql,$db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: index_instructor.php');
+       exit;
+}
+
+if (isset($_GET['existing'])){
+       $existing = intval ($_GET['existing']);
+}
+
+$today = getdate();
+
+$sql = "SELECT title, resource_id FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND type=".RL_TYPE_AV." ORDER BY title";
+$av_result = mysql_query($sql, $db);
+
+if (!mysql_num_rows($av_result)) {
+       header('Location: add_resource_av.php?page_return=new_reading_av.php');
+       exit;
+}
+
+$onload = 'document.form.name.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('rl_av_material_to_view'); ?></legend>
+
+       <div class="row">
+               <label for="title"><?php  echo _AT('select_av'); ?>:</label>
+               <select name="existing" id="title">
+
+                       <?php while ($row = mysql_fetch_assoc($av_result)): ?>
+                               <option value="<?php echo $row['resource_id']; ?>"<?php if ($row['resource_id'] == $existing) { echo ' selected="selected"'; } ?>><?php echo htmlspecialchars($row['title']); ?></option>
+                       <?php endwhile; ?>
+               
+               </select>
+
+               <?php  echo _AT('rl_or'); ?> <a href="reading_list/add_resource_av.php"><?php  echo _AT('rl_create_new_av'); ?></a>
+       </div>
+
+       <div class="row">
+               <input type="radio" name="readstatus" value="required" id="required" <?php
+               if (isset($_POST['readstatus'])){
+                       if ($_POST['readstatus'] == 'required'){
+                               echo 'checked="checked"';
+                       }
+               } else {
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="required"><?php  echo _AT('required'); ?></label>
+               <input type="radio" name="readstatus" value="optional" id="optional" <?php if (isset($_POST['readstatus']) && ($_POST['readstatus'] == 'optional')) { echo ' checked="checked"'; } ?>/>
+               <label for="optional"><?php  echo _AT('optional'); ?></label>
+       </div>  
+       
+       <div class="row">
+       <label for="comment"><?php  echo _AT('comment'); ?>:</label><input type="text" id="comment" size="75" name="comment" value="<?php if (isset($_POST['comment'])) echo $stripslashes($_POST['comment']);  ?>" />
+       </div>
+
+<h3><?php  echo _AT('rl_read_by_date'); ?></h3>
+
+       <div class="row">
+               <input type="radio" id="nodate" name="hasdate" value="false" <?php
+               if (isset($_POST['hasdate'])){
+                       if ($_POST['hasdate'] != 'true'){
+                               echo ' checked="checked"';
+                       }
+               } else {
+                       echo ' checked="checked"';
+               }?>/>
+               <label for="nodate"><?php  echo _AT('rl_no_read_by_date'); ?></label>
+       </div>
+
+       <div class="row">
+               <input type="radio" id="hasdate" name="hasdate" value="true" <?php if (isset($_POST['hasdate']) && ($_POST['hasdate'] == 'true')) { echo ' checked="checked"'; } ?>/>
+               <label for="hasdate"><?php  echo _AT('rl_reading_date'); ?></label><br/>
+
+               <label for="startdate"><?php  echo _AT('start_date'); ?>:</label>
+
+               <select name="startday" id="startdate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mday']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+               
+               <select name="startmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mon']) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+
+               <select name="startyear">
+               <?php for ($i = ($today['year'] - 1); $i <= ($today['year'] + 4); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['year']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+       
+               <br/><label for="enddate"><?php  echo _AT('end_date'); ?>:</label>
+
+               <select name="endday" id="enddate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mday']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mon']) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endyear">
+               <?php for ($i = ($today['year'] - 1); $i <= ($today['year'] + 4); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['year']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>       
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/new_reading_book.php b/reading_list/new_reading_book.php
new file mode 100644 (file)
index 0000000..9db3c2b
--- /dev/null
@@ -0,0 +1,178 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_READING_LIST);
+
+$existingbook = -1;
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index_instructor.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+
+       $_POST['existingbook'] = intval($_POST['existingbook']);
+       $existingbook          = $_POST['existingbook'];
+       $_POST['hasdate']      = $addslashes($_POST['hasdate']);
+       $_POST['readstatus']   = $addslashes($_POST['readstatus']);
+       $_POST['comment']      = $addslashes($_POST['comment']);
+       $_POST['startday']     = intval($_POST['startday']);
+       $_POST['startmonth']   = intval($_POST['startmonth']);
+       $_POST['startyear']    = intval($_POST['startyear']);
+       $_POST['endday']       = intval($_POST['endday']);
+       $_POST['endmonth']     = intval($_POST['endmonth']);
+       $_POST['endyear']      = intval($_POST['endyear']);
+
+       $date_start = '0000-00-00';
+       $date_end = '0000-00-00';
+       if ($_POST['hasdate'] == 'true'){
+               $date_start = $_POST['startyear']. '-' .str_pad ($_POST['startmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['startday'], 2, "0", STR_PAD_LEFT);
+               $date_end = $_POST['endyear']. '-' .str_pad ($_POST['endmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['endday'], 2, "0", STR_PAD_LEFT);
+       }
+
+       $sql = "INSERT INTO ".TABLE_PREFIX."reading_list VALUES (NULL, $_SESSION[course_id],
+               '$_POST[existingbook]',
+               '$_POST[readstatus]',
+               '$date_start',
+               '$date_end',
+               '$_POST[comment]'
+               )";
+       $result = mysql_query($sql,$db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: index_instructor.php');
+       exit;
+}
+
+if (isset($_GET['existingbook'])){
+       $existingbook = intval ($_GET['existingbook']);
+}
+
+$sql = "SELECT title, resource_id FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND type=".RL_TYPE_BOOK." ORDER BY title";
+$books_result = mysql_query($sql, $db);
+
+if (!mysql_num_rows($books_result)) {
+       header('Location: add_resource_book.php?page_return=new_reading_book.php');
+       exit;
+}
+
+$onload = 'document.form.name.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$today = getdate();
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('rl_book_to_read'); ?></legend>
+       <div class="row">
+               <label for="booktitle"><?php  echo _AT('rl_select_book'); ?>:</label>
+               <select name="existingbook" id="booktitle">
+                       <?php while ($row = mysql_fetch_assoc($books_result)): ?>
+                               <option value="<?php echo $row['resource_id']; ?>"<?php if ($row['resource_id'] == $existingbook) { echo ' selected="selected"'; } ?>><?php echo htmlspecialchars($row['title']); ?></option>
+                       <?php endwhile; ?>
+               </select>
+
+               <?php  echo _AT('rl_or'); ?> <a href="reading_list/add_resource_book.php?page_return=new_reading_book.php"><?php  echo _AT('rl_create_new_book'); ?></a>
+       </div>
+
+       <div class="row">
+               <input type="radio" name="readstatus" value="required" id="required" <?php
+               if (isset($_POST['readstatus'])){
+                       if ($_POST['readstatus'] == 'required'){
+                               echo 'checked="checked"';
+                       }
+               } else {
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="required"><?php  echo _AT('required'); ?></label>
+               <input type="radio" name="readstatus" value="optional" id="optional" <?php if (isset($_POST['readstatus']) && ($_POST['readstatus'] == 'optional')) { echo ' checked="checked"'; } ?>/>
+               <label for="optional"><?php  echo _AT('optional'); ?></label>
+       </div>  
+       
+       <div class="row">
+       <label for="comment"><?php  echo _AT('comment'); ?>:</label><input type="text" id="comment" size="75" name="comment" value="<?php if (isset($_POST['comment'])) echo $stripslashes($_POST['comment']);  ?>" />
+       </div>
+
+<h3><?php echo _AT('rl_read_by_date'); ?></h3>
+
+       <div class="row">
+               <input type="radio" id="nodate" name="hasdate" value="false" <?php
+               if (isset($_POST['hasdate'])){
+                       if ($_POST['hasdate'] != 'true'){
+                               echo ' checked="checked"';
+                       }
+               }
+               else {
+                       echo ' checked="checked"';
+               }?>/>
+               <label for="nodate"><?php  echo _AT('rl_no_read_by_date'); ?></label>
+       </div>
+
+       <div class="row">
+               <input type="radio" id="hasdate" name="hasdate" value="true" <?php if (isset($_POST['hasdate']) && ($_POST['hasdate'] == 'true')) { echo ' checked="checked"'; } ?>/>
+               <label for="hasdate"><?php  echo _AT('rl_reading_date'); ?></label><br/>
+
+               <label for="startdate"><?php  echo _AT('start_date'); ?>:</label>
+
+               <select name="startday" id="startdate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mday']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+               
+               <select name="startmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mon']) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+
+               <select name="startyear">
+               <?php for ($i = ($today['year'] - 1); $i <= ($today['year'] + 4); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['year']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+               <br/><label for="enddate"><?php  echo _AT('end_date'); ?>:</label>
+
+               <select name="endday" id="enddate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mday']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mon']) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endyear">
+               <?php for ($i = ($today['year'] - 1); $i <= ($today['year'] + 4); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['year']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>       
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/new_reading_file.php b/reading_list/new_reading_file.php
new file mode 100644 (file)
index 0000000..a333313
--- /dev/null
@@ -0,0 +1,183 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_READING_LIST);
+
+$existing = -1;
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index_instructor.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+
+       $_POST['existing'] = intval($_POST['existing']);
+       $existing = $_POST['existing'];
+       $_POST['hasdate'] = $addslashes($_POST['hasdate']);
+       $_POST['readstatus'] = $addslashes($_POST['readstatus']);
+       $_POST['comment'] = $addslashes($_POST['comment']);
+       $_POST['startday'] = intval($_POST['startday']);
+       $_POST['startmonth'] = intval($_POST['startmonth']);
+       $_POST['startyear'] = intval($_POST['startyear']);
+       $_POST['endday'] = intval($_POST['endday']);
+       $_POST['endmonth'] = intval($_POST['endmonth']);
+       $_POST['endyear'] = intval($_POST['endyear']);
+
+       $date_start = '0000-00-00';
+       $date_end = '0000-00-00';
+       if ($_POST['hasdate'] == 'true'){
+               $date_start = $_POST['startyear']. '-' .str_pad ($_POST['startmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['startday'], 2, "0", STR_PAD_LEFT);
+               $date_end = $_POST['endyear']. '-' .str_pad ($_POST['endmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['endday'], 2, "0", STR_PAD_LEFT);
+       }
+
+       $sql = "INSERT INTO ".TABLE_PREFIX."reading_list VALUES (NULL, $_SESSION[course_id],
+               '$_POST[existing]',
+               '$_POST[readstatus]',
+               '$date_start',
+               '$date_end',
+               '$_POST[comment]'
+               )";
+       $result = mysql_query($sql,$db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: index_instructor.php');
+       exit;
+}
+
+if (isset($_GET['existing'])){
+       $existing = intval ($_GET['existing']);
+}
+
+$today = getdate();
+
+$sql = "SELECT title, resource_id FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND type=".RL_TYPE_FILE." ORDER BY title";
+$files_result = mysql_query($sql, $db);
+
+if (!mysql_num_rows($files_result)) {
+       header('Location: add_resource_file.php?page_return=new_reading_file.php');
+       exit;
+}
+
+$onload = 'document.form.name.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('file_to_read'); ?></legend>
+
+       <div class="row">
+               <label for="title"><?php  echo _AT('rl_select_file'); ?>:</label>
+               <select name="existing" id="title">
+
+                       <?php while ($row = mysql_fetch_assoc($files_result)): ?>
+                               <option value="<?php echo $row['resource_id']; ?>"<?php if ($row['resource_id'] == $existing) { echo ' selected="selected"'; } ?>><?php echo htmlspecialchars($row['title']); ?></option>
+                       <?php endwhile; ?>
+               
+               </select>
+
+               <?php  echo _AT('rl_or'); ?> <a href="reading_list/add_resource_file.php"><?php  echo _AT('rl_create_new_file'); ?></a>
+       </div>
+
+       <div class="row">
+               <input type="radio" name="readstatus" value="required" id="required" <?php
+               if (isset($_POST['readstatus'])){
+                       if ($_POST['readstatus'] == 'required'){
+                               echo 'checked="checked"';
+                       }
+               }
+               else {
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="required"><?php  echo _AT('required'); ?></label>
+               <input type="radio" name="readstatus" value="optional" id="optional" <?php if (isset($_POST['readstatus']) && ($_POST['readstatus'] == 'optional')) { echo ' checked="checked"'; } ?>/>
+               <label for="optional"><?php  echo _AT('optional'); ?></label>
+       </div>  
+       
+       <div class="row">
+       <label for="comment"><?php  echo _AT('comment'); ?>:</label><input type="text" id="comment" size="75" name="comment" value="<?php if (isset($_POST['comment'])) echo $stripslashes($_POST['comment']);  ?>" />
+       </div>
+
+<h3><?php echo _AT('rl_read_by_date'); ?></h3>
+
+       <div class="row">
+               <input type="radio" id="nodate" name="hasdate" value="false" <?php
+               if (isset($_POST['hasdate'])){
+                       if ($_POST['hasdate'] != 'true'){
+                               echo ' checked="checked"';
+                       }
+               }
+               else {
+                       echo ' checked="checked"';
+               }?>/>
+               <label for="nodate"><?php  echo _AT('rl_no_read_by_date'); ?></label>
+       </div>
+
+       <div class="row">
+               <input type="radio" id="hasdate" name="hasdate" value="true" <?php if (isset($_POST['hasdate']) && ($_POST['hasdate'] == 'true')) { echo ' checked="checked"'; } ?>/>
+               <label for="hasdate"><?php  echo _AT('rl_reading_date'); ?></label><br/>
+
+               <label for="startdate"><?php  echo _AT('start_date'); ?>:</label>
+
+               <select name="startday" id="startdate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mday']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+               
+               <select name="startmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mon']) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+
+               <select name="startyear">
+               <?php for ($i = ($today['year'] - 1); $i <= ($today['year'] + 4); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['year']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+       
+               <br/><label for="enddate"><?php  echo _AT('end_date'); ?>:</label>
+
+               <select name="endday" id="enddate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mday']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mon']) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endyear">
+               <?php for ($i = ($today['year'] - 1); $i <= ($today['year'] + 4); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['year']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>       
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/new_reading_handout.php b/reading_list/new_reading_handout.php
new file mode 100644 (file)
index 0000000..67d46b5
--- /dev/null
@@ -0,0 +1,183 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_READING_LIST);
+
+$existing = -1;
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index_instructor.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+
+       $_POST['existing'] = intval($_POST['existing']);
+       $existinghandout = $_POST['existinghandout'];
+       $_POST['hasdate'] = $addslashes($_POST['hasdate']);
+       $_POST['readstatus'] = $addslashes($_POST['readstatus']);
+       $_POST['comment'] = $addslashes($_POST['comment']);
+       $_POST['startday'] = intval($_POST['startday']);
+       $_POST['startmonth'] = intval($_POST['startmonth']);
+       $_POST['startyear'] = intval($_POST['startyear']);
+       $_POST['endday'] = intval($_POST['endday']);
+       $_POST['endmonth'] = intval($_POST['endmonth']);
+       $_POST['endyear'] = intval($_POST['endyear']);
+
+       $date_start = '0000-00-00';
+       $date_end = '0000-00-00';
+       if ($_POST['hasdate'] == 'true'){
+               $date_start = $_POST['startyear']. '-' .str_pad ($_POST['startmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['startday'], 2, "0", STR_PAD_LEFT);
+               $date_end = $_POST['endyear']. '-' .str_pad ($_POST['endmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['endday'], 2, "0", STR_PAD_LEFT);
+       }
+
+       $sql = "INSERT INTO ".TABLE_PREFIX."reading_list VALUES (NULL, $_SESSION[course_id],
+               '$_POST[existing]',
+               '$_POST[readstatus]',
+               '$date_start',
+               '$date_end',
+               '$_POST[comment]'
+               )";
+       $result = mysql_query($sql,$db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: index_instructor.php');
+       exit;
+}
+
+if (isset($_GET['existing'])){
+       $existinghandout = intval ($_GET['existing']);
+}
+
+$today = getdate();
+
+$sql = "SELECT title, resource_id FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND type=".RL_TYPE_HANDOUT." ORDER BY title";
+$handout_result = mysql_query($sql, $db);
+
+if (!mysql_num_rows($handout_result)) {
+       header('Location: add_resource_handout.php?page_return=new_reading_handout.php');
+       exit;
+}
+
+$onload = 'document.form.name.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('handout_to_read'); ?></legend>
+       <div class="row">
+               <label for="title"><?php  echo _AT('rl_select_handout'); ?>:</label>
+               <select name="existing" id="title">
+
+                       <?php while ($row = mysql_fetch_assoc($handout_result)): ?>
+                               <option value="<?php echo $row['resource_id']; ?>"<?php if ($row['resource_id'] == $existing) { echo ' selected="selected"'; } ?>><?php echo htmlspecialchars($row['title']); ?></option>
+                       <?php endwhile; ?>
+               
+               </select>
+
+               <?php  echo _AT('rl_or'); ?> <a href="reading_list/add_resource_handout.php"><?php  echo _AT('rl_create_new_handout'); ?></a>
+       </div>
+
+       <div class="row">
+               <input type="radio" name="readstatus" value="required" id="required" <?php
+               if (isset($_POST['readstatus'])){
+                       if ($_POST['readstatus'] == 'required'){
+                               echo 'checked="checked"';
+                       }
+               }
+               else {
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="required"><?php  echo _AT('required'); ?></label>
+               <input type="radio" name="readstatus" value="optional" id="optional" <?php if (isset($_POST['readstatus']) && ($_POST['readstatus'] == 'optional')) { echo ' checked="checked"'; } ?>/>
+               <label for="optional"><?php  echo _AT('optional'); ?></label>
+       </div>  
+       
+       <div class="row">
+       <label for="comment"><?php  echo _AT('comment'); ?>:</label><input type="text" id="comment" size="75" name="comment" value="<?php if (isset($_POST['comment'])) echo $stripslashes($_POST['comment']);  ?>" />
+       </div>
+
+<h3><?php echo _AT('rl_read_by_date'); ?></h3>
+
+       <div class="row">
+               <input type="radio" id="nodate" name="hasdate" value="false" <?php
+               if (isset($_POST['hasdate'])){
+                       if ($_POST['hasdate'] != 'true'){
+                               echo ' checked="checked"';
+                       }
+               }
+               else {
+                       echo ' checked="checked"';
+               }?>/>
+               <label for="nodate"><?php  echo _AT('rl_no_read_by_date'); ?></label>
+       </div>
+
+       <div class="row">
+               <input type="radio" id="hasdate" name="hasdate" value="true" <?php if (isset($_POST['hasdate']) && ($_POST['hasdate'] == 'true')) { echo ' checked="checked"'; } ?>/>
+               <label for="hasdate"><?php  echo _AT('rl_reading_date'); ?></label><br/>
+
+               <label for="startdate"><?php  echo _AT('start_date'); ?>:</label>
+
+               <select name="startday" id="startdate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mday']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+               
+               <select name="startmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mon']) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+
+               <select name="startyear">
+               <?php for ($i = ($today['year'] - 1); $i <= ($today['year'] + 4); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['year']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+       
+               <br/><label for="enddate"><?php  echo _AT('end_date'); ?>:</label>
+
+               <select name="endday" id="enddate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mday']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mon']) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endyear">
+               <?php for ($i = ($today['year'] - 1); $i <= ($today['year'] + 4); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['year']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>       
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/new_reading_url.php b/reading_list/new_reading_url.php
new file mode 100644 (file)
index 0000000..440bfc7
--- /dev/null
@@ -0,0 +1,184 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_READING_LIST);
+
+$existing = -1;
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index_instructor.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+
+       $_POST['existing'] = intval($_POST['existing']);
+       $existingurl = $_POST['existing'];
+       $_POST['hasdate'] = $addslashes($_POST['hasdate']);
+       $_POST['readstatus'] = $addslashes($_POST['readstatus']);
+       $_POST['comment'] = $addslashes($_POST['comment']);
+       $_POST['startday'] = intval($_POST['startday']);
+       $_POST['startmonth'] = intval($_POST['startmonth']);
+       $_POST['startyear'] = intval($_POST['startyear']);
+       $_POST['endday'] = intval($_POST['endday']);
+       $_POST['endmonth'] = intval($_POST['endmonth']);
+       $_POST['endyear'] = intval($_POST['endyear']);
+
+       $date_start = '0000-00-00';
+       $date_end = '0000-00-00';
+       if ($_POST['hasdate'] == 'true'){
+               $date_start = $_POST['startyear']. '-' .str_pad ($_POST['startmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['startday'], 2, "0", STR_PAD_LEFT);
+               $date_end = $_POST['endyear']. '-' .str_pad ($_POST['endmonth'], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST['endday'], 2, "0", STR_PAD_LEFT);
+       }
+
+       $sql = "INSERT INTO ".TABLE_PREFIX."reading_list VALUES (NULL, $_SESSION[course_id],
+               '$_POST[existing]',
+               '$_POST[readstatus]',
+               '$date_start',
+               '$date_end',
+               '$_POST[comment]'
+               )";
+       $result = mysql_query($sql,$db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: index_instructor.php');
+       exit;
+}
+
+if (isset($_GET['existing'])){
+       $existing = intval ($_GET['existing']);
+}
+
+$today = getdate();
+
+$sql = "SELECT title, resource_id FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND type=".RL_TYPE_URL." ORDER BY title";
+$url_result = mysql_query($sql, $db);
+
+if (!mysql_num_rows($url_result)) {
+       header('Location: add_resource_url.php?page_return=new_reading_url.php');
+       exit;
+}
+
+$onload = 'document.form.name.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('url_to_read'); ?></legend>
+
+       <div class="row">
+               <label for="urltitle"><?php  echo _AT('rl_select_url'); ?>:</label>
+               <select name="existing" id="urltitle">
+
+                       <?php while ($row = mysql_fetch_assoc($url_result)): ?>
+                               <option value="<?php echo $row['resource_id']; ?>"<?php if ($row['resource_id'] == $existing) { echo ' selected="selected"'; } ?>><?php echo htmlspecialchars($row['title']); ?></option>
+                       <?php endwhile; ?>
+               
+               </select>
+
+               <?php  echo _AT('rl_or'); ?> <a href="reading_list/add_resource_url.php"><?php  echo _AT('rl_create_new_url'); ?></a>
+       </div>
+
+       <div class="row">
+               <input type="radio" name="readstatus" value="required" id="required" <?php
+               if (isset($_POST['readstatus'])){
+                       if ($_POST['readstatus'] == 'required'){
+                               echo 'checked="checked"';
+                       }
+               }
+               else {
+                       echo 'checked="checked"';
+               }?>/>
+               <label for="required"><?php  echo _AT('required'); ?></label>
+               <input type="radio" name="readstatus" value="optional" id="optional" <?php if (isset($_POST['readstatus']) && ($_POST['readstatus'] == 'optional')) { echo ' checked="checked"'; } ?>/>
+               <label for="optional"><?php  echo _AT('optional'); ?></label>
+       </div>  
+       
+       <div class="row">
+       <label for="comment"><?php  echo _AT('comment'); ?>:</label><input type="text" id="comment" size="75" name="comment" value="<?php if (isset($_POST['comment'])) echo $stripslashes($_POST['comment']);  ?>" />
+       </div>
+
+<h3><?php echo _AT('rl_read_by_date'); ?></h3>
+
+       <div class="row">
+               <input type="radio" id="nodate" name="hasdate" value="false" <?php
+               if (isset($_POST['hasdate'])){
+                       if ($_POST['hasdate'] != 'true'){
+                               echo ' checked="checked"';
+                       }
+               }
+               else {
+                       echo ' checked="checked"';
+               }?>/>
+               <label for="nodate"><?php  echo _AT('rl_no_read_by_date'); ?></label>
+       </div>
+
+       <div class="row">
+               <input type="radio" id="hasdate" name="hasdate" value="true" <?php if (isset($_POST['hasdate']) && ($_POST['hasdate'] == 'true')) { echo ' checked="checked"'; } ?>/>
+               <label for="hasdate"><?php  echo _AT('rl_reading_date'); ?></label><br/>
+
+               <label for="startdate"><?php  echo _AT('start_date'); ?>:</label>
+
+               <select name="startday" id="startdate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mday']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+               
+               <select name="startmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mon']) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+
+               <select name="startyear">
+               <?php for ($i = ($today['year'] - 1); $i <= ($today['year'] + 4); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['year']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+       
+               <br/><label for="enddate"><?php  echo _AT('end_date'); ?>:</label>
+
+               <select name="endday" id="enddate">
+               <?php for ($i = 1; $i <= 31; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mday']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endmonth">
+               <?php for ($i = 1; $i <= 12; $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['mon']) { echo ' selected="selected"'; } ?>><?php echo AT_Date('%M', $i, AT_DATE_INDEX_VALUE) ?></option>
+               <?php } ?>
+               </select>
+       
+               <select name="endyear">
+               <?php for ($i = ($today['year'] - 1); $i <= ($today['year'] + 4); $i++){ ?>
+                       <option value="<?php echo $i ?>" <?php if ($i == $today['year']) { echo ' selected="selected"'; } ?>><?php echo $i ?></option>
+               <?php } ?>
+               </select>       
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/reading_list/reading_details.php b/reading_list/reading_details.php
new file mode 100644 (file)
index 0000000..3b0777c
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008                                      */
+/* Written by Greg Gay, Joel Kronenberg & Chris Ridpath         */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$sql = "SELECT * FROM ".TABLE_PREFIX."reading_list WHERE course_id=$_SESSION[course_id] ORDER BY date_start";
+$resultReadings = mysql_query($sql, $db);
+?>
+
+<?php if (($resultReadings != 0) && ($rowReadings = mysql_fetch_assoc($resultReadings))) : ?>
+
+               <?php do { ?>
+                       <?php $id = $rowReadings['resource_id']; 
+
+
+$sql = "SELECT * FROM ".TABLE_PREFIX."external_resources WHERE course_id=$_SESSION[course_id] AND resource_id=$id";
+$result = mysql_query($sql, $db);
+if ($row = mysql_fetch_assoc($result)){ 
+       if ($row['type'] == RL_TYPE_BOOK): ?>
+       <div class="input-form">
+               <p><?php  echo _AT('title'). ": <strong>". $row['title']. "</strong>"; ?><br/>
+                       <?php  echo _AT('rl_type_of_resource'). ": ". _AT($_rl_types[$row['type']]); ?><br/>
+                       <?php  echo _AT('author'). ": ". $row['author']; ?><br/>
+                       <?php  echo _AT('rl_publisher'). ": ". $row['publisher']; ?><br/>
+                       <?php  echo _AT('date'). ": ". $row['date']; ?><br/>
+                       <?php  echo _AT('rl_isbn_number'). ": ". $row['id']; ?><br/>
+                       <?php  echo _AT('comment'). ": ". $row['comments']; ?>
+               </p>
+       </div>
+<?php elseif ($row['type'] == RL_TYPE_URL): ?>
+       <div class="input-form">        
+               <p><?php  echo _AT('title'). ": <strong>". $row['title']. "</strong>"; ?><br/>
+                       <?php  echo _AT('rl_type_of_resource'). ": ". _AT($_rl_types[$row['type']]); ?><br/>
+                       <?php echo _AT('location'). ": " ?><a href="<?php echo $row['url']?>"><?php echo $row['url']; ?></a><br/>
+                       <?php  echo _AT('author'). ": ". $row['author']; ?><br/>
+                       <?php  echo _AT('comment'). ": ". $row['comments']; ?>
+                       </p>
+       </div>
+<?php elseif ($row['type'] == RL_TYPE_HANDOUT): ?>
+       <div class="input-form">        
+               <p><?php  echo _AT('title'). ": <strong>". $row['title']. "</strong>"; ?><br/>
+                       <?php  echo _AT('rl_type_of_resource'). ": ". _AT($_rl_types[$row['type']]); ?><br/>
+                       <?php  echo _AT('author'). ": ". $row['author']; ?><br/>
+                       <?php  echo _AT('date'). ": ". $row['date']; ?><br/>
+                       <?php  echo _AT('comment'). ": ". $row['comments']; ?>
+               </p>
+       </div>
+<?php elseif ($row['type'] == RL_TYPE_AV): ?>
+       <div class="input-form">        
+               <p><?php  echo _AT('title'). ": <strong>". $row['title']. "</strong>" ; ?><br/>
+                       <?php  echo _AT('rl_type_of_resource'). ": ". _AT($_rl_types[$row['type']]); ?><br/>
+                       <?php  echo _AT('author'). ": ". $row['author']; ?><br />
+                       <?php  echo _AT('date'). ": ". $row['date']; ?><br/>
+                       <?php  echo _AT('comment'). ": ". $row['comments']; ?>
+               </p>
+       </div>
+<?php elseif ($row['type'] == RL_TYPE_FILE): ?>
+       <div class="input-form">        
+               <p><?php  echo _AT('title'). ": <strong>". $row['title']. "</strong>"; ?><br/>
+                       <?php  echo _AT('rl_type_of_resource'). ": ". _AT($_rl_types[$row['type']]); ?><br/>
+                       <?php  echo _AT('author'). ": ". $row['author']; ?><br/>
+                       <?php  echo _AT('rl_publisher'). ": ". $row['publisher']; ?><br/>
+                       <?php  echo _AT('date'). ": ". $row['date']; ?><br/>
+                       <?php  echo _AT('id'). ": ". $row['id']; ?><br/>
+                       <?php  echo _AT('comment'). ": ". $row['comments']; ?>
+               </p>
+       </div>
+<?php endif;
+}
+?>
+       <?php } while($rowReadings = mysql_fetch_assoc($resultReadings)); ?>
+<?php else: ?>
+               <em><?php echo _AT('none_found'); ?></em>
+<?php endif; ?>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/readme b/readme
new file mode 100644 (file)
index 0000000..f7afc8d
--- /dev/null
+++ b/readme
@@ -0,0 +1,17 @@
+ATutor readme:
+
+To install ATutor simply point your browser to your installation and follow the provided instructions.
+
+For additional installation details see:
+http://www.atutor.ca/atutor/docs/installation.php
+
+Or, the official ATutor Handbook:
+http://help.atutor.ca
+
+
+
+Enjoy!
+
+
+The ATutor Development Team
+http://www.atutor.ca
diff --git a/registration.php b/registration.php
new file mode 100644 (file)
index 0000000..705a2f7
--- /dev/null
@@ -0,0 +1,319 @@
+<?php
+/****************************************************************/
+/* ATutor                                                       */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                             */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+$_user_location        = 'public';
+
+define('AT_INCLUDE_PATH', 'include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+if (isset($_POST['cancel'])) {
+       header('Location: ./login.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $missing_fields = array();
+
+       /* email check */
+       $chk_email = $addslashes($_POST['email']);
+       $chk_login = $addslashes($_POST['login']);
+
+       $_POST['password'] = $_POST['form_password_hidden'];
+       $_POST['first_name'] = trim($_POST['first_name']);
+       $_POST['second_name'] = trim($_POST['second_name']);
+       $_POST['last_name'] = trim($_POST['last_name']);
+
+       $_POST['first_name'] = str_replace('<', '', $_POST['first_name']);
+       $_POST['second_name'] = str_replace('<', '', $_POST['second_name']);
+       $_POST['last_name'] = str_replace('<', '', $_POST['last_name']);
+
+       /* login name check */
+       if ($_POST['login'] == '') {
+               $missing_fields[] = _AT('login_name');
+       } else {
+               /* check for special characters */
+               if (!(eregi("^[a-zA-Z0-9_.-]([a-zA-Z0-9_.-])*$", $_POST['login']))) {
+                       $msg->addError('LOGIN_CHARS');
+               } else {
+                       $result = mysql_query("SELECT * FROM ".TABLE_PREFIX."members WHERE login='$chk_login'",$db);
+                       if (mysql_num_rows($result) != 0) {
+                               $msg->addError('LOGIN_EXISTS');
+                       } else {
+                               $result = mysql_query("SELECT * FROM ".TABLE_PREFIX."admins WHERE login='$chk_login'",$db);
+                               if (mysql_num_rows($result) != 0) {
+                                       $msg->addError('LOGIN_EXISTS');
+                               }
+                       }
+               }
+       }
+
+       /* password check: password is verified front end by javascript. here is to handle the errors from javascript */
+       if ($_POST['password_error'] <> "")
+       {
+               $pwd_errors = explode(",", $_POST['password_error']);
+
+               foreach ($pwd_errors as $pwd_error)
+               {
+                       if ($pwd_error == "missing_password")
+                               $missing_fields[] = _AT('password');
+                       else
+                               $msg->addError($pwd_error);
+               }
+       }
+
+       if ($_POST['email'] == '') {
+               $missing_fields[] = _AT('email');
+       } else if (!eregi("^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$", $_POST['email'])) {
+               $msg->addError('EMAIL_INVALID');
+       }
+       $result = mysql_query("SELECT * FROM ".TABLE_PREFIX."members WHERE email='$chk_email'",$db);
+       if (mysql_num_rows($result) != 0) {
+               $msg->addError('EMAIL_EXISTS');
+       }
+
+       if (!$_POST['first_name']) { 
+               $missing_fields[] = _AT('first_name');
+       }
+
+       if (!$_POST['last_name']) { 
+               $missing_fields[] = _AT('last_name');
+       }
+
+       // check if first+last is unique
+       if ($_POST['first_name'] && $_POST['last_name']) {
+               $first_name_sql  = $addslashes($_POST['first_name']);
+               $last_name_sql   = $addslashes($_POST['last_name']);
+               $second_name_sql = $addslashes($_POST['second_name']);
+
+               $sql = "SELECT member_id FROM ".TABLE_PREFIX."members WHERE first_name='$first_name_sql' AND second_name='$second_name_sql' AND last_name='$last_name_sql' LIMIT 1";
+               $result = mysql_query($sql, $db);
+               if (mysql_fetch_assoc($result)) {
+                       $msg->addError('FIRST_LAST_NAME_UNIQUE');
+               }
+       }
+
+       $_POST['login'] = strtolower($_POST['login']);
+
+       //check date of birth
+       $mo = $_POST['month'] = intval($_POST['month']);
+       $day = $_POST['day'] = intval($_POST['day']);
+       $yr = $_POST['year'] = intval($_POST['year']);
+
+       /* let's us take (one or) two digit years (ex. 78 = 1978, 3 = 2003) */
+       if ($yr <= date('y')) { 
+               $yr += 2000; 
+       } else if ($yr < 1900) { 
+               $yr += 1900; 
+       } 
+
+       $dob = $yr.'-'.$mo.'-'.$day;
+
+       if ($mo && $day && $yr && !checkdate($mo, $day, $yr)) { 
+               $msg->addError('DOB_INVALID');
+       } else if (!$mo || !$day || !$yr) {
+               $dob = '0000-00-00';
+               $yr = $mo = $day = 0;
+       }
+
+       unset($master_list_sql);
+       if (defined('AT_MASTER_LIST') && AT_MASTER_LIST) {
+               
+               $student_id  = $addslashes($_POST['student_id']);
+               $student_pin = md5($_POST['student_pin']);
+
+               $sql    = "SELECT member_id FROM ".TABLE_PREFIX."master_list WHERE public_field='$student_id' AND hash_field='$student_pin'";
+               $result = mysql_query($sql, $db);
+               if (!($row = mysql_fetch_assoc($result)) || $row['member_id']) {
+                       // the row wasn't found, or it was found but already used
+                       $msg->addError('REGISTER_MASTER_USED');
+               } else {
+                       $master_list_sql = "UPDATE ".TABLE_PREFIX."master_list SET member_id=LAST_INSERT_ID() WHERE public_field='$student_id' AND hash_field='$student_pin'";
+               }
+       }
+
+       if (($_POST['gender'] != 'm') && ($_POST['gender'] != 'f')) {
+               $_POST['gender'] = 'n'; // not specified
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       if (!$msg->containsErrors()) {
+               if (($_POST['website']) && (!ereg("://",$_POST['website']))) { 
+                       $_POST['website'] = "http://".$_POST['website']; 
+               }
+               if ($_POST['website'] == 'http://') { 
+                       $_POST['website'] = ''; 
+               }
+               if (isset($_POST['private_email'])) {
+                       $_POST['private_email'] = 1;
+               } else {
+                       $_POST['private_email'] = 0;
+               }
+               $_POST['postal'] = strtoupper(trim($_POST['postal']));
+
+               $_POST['email']      = $addslashes($_POST['email']);
+               $_POST['login']      = $addslashes($_POST['login']);
+               $_POST['password']   = $addslashes($_POST['password']);
+               $_POST['website']    = $addslashes($_POST['website']);
+               $_POST['first_name'] = $addslashes($_POST['first_name']);
+               $_POST['second_name']= $addslashes($_POST['second_name']);
+               $_POST['last_name']  = $addslashes($_POST['last_name']);
+               $_POST['address']    = $addslashes($_POST['address']);
+               $_POST['postal']     = $addslashes($_POST['postal']);
+               $_POST['city']       = $addslashes($_POST['city']);
+               $_POST['province']   = $addslashes($_POST['province']);
+               $_POST['country']    = $addslashes($_POST['country']);
+               $_POST['phone']      = $addslashes($_POST['phone']);
+
+               if (defined('AT_EMAIL_CONFIRMATION') && AT_EMAIL_CONFIRMATION) {
+                       $status = AT_STATUS_UNCONFIRMED;
+               } else if (defined('AUTO_APPROVE_INSTRUCTORS') && AUTO_APPROVE_INSTRUCTORS) {
+                       $status = AT_STATUS_INSTRUCTOR;
+               } else {
+                       $status = AT_STATUS_STUDENT;
+               }
+               $now = date('Y-m-d H:i:s'); // we use this later for the email confirmation.
+
+               /* insert into the db */
+               $sql = "INSERT INTO ".TABLE_PREFIX."members 
+                             (login,
+                              password,
+                              email,
+                              website,
+                              first_name,
+                              second_name,
+                              last_name,
+                              dob,
+                              gender,
+                              address,
+                              postal,
+                              city,
+                              province,
+                              country,
+                              phone,
+                              status,
+                              preferences,
+                              creation_date,
+                              language,
+                              inbox_notify,
+                              private_email,
+                              last_login)
+                      VALUES ('$_POST[login]',
+                              '$_POST[password]',
+                              '$_POST[email]',
+                              '$_POST[website]',
+                              '$_POST[first_name]',
+                              '$_POST[second_name]',
+                              '$_POST[last_name]', 
+                              '$dob', 
+                              '$_POST[gender]', 
+                              '$_POST[address]',
+                              '$_POST[postal]',
+                              '$_POST[city]',
+                              '$_POST[province]',
+                              '$_POST[country]', 
+                              '$_POST[phone]', 
+                              $status, 
+                              '$_config[pref_defaults]', 
+                              '$now',
+                              '$_SESSION[lang]', 
+                              $_config[pref_inbox_notify], 
+                              $_POST[private_email], 
+                              '0000-00-00 00:00:00')";
+
+               $result = mysql_query($sql, $db) or die(mysql_error());
+               $m_id   = mysql_insert_id($db);
+               if (!$result) {
+                       require(AT_INCLUDE_PATH.'header.inc.php');
+                       $msg->addError('DB_NOT_UPDATED');
+                       $msg->printAll();
+                       require(AT_INCLUDE_PATH.'footer.inc.php');
+                       exit;
+               }
+
+               if (isset($master_list_sql)) {
+                       mysql_query($master_list_sql, $db);
+               }
+
+               if (defined('AT_EMAIL_CONFIRMATION') && AT_EMAIL_CONFIRMATION) {
+                       $msg->addFeedback('REG_THANKS_CONFIRM');
+
+                       $code = substr(md5($_POST['email'] . $now . $m_id), 0, 10);
+                       
+                       if (isset($_REQUEST["en_id"]) && $_REQUEST["en_id"] <> "")
+                               $confirmation_link = $_base_href . 'confirm.php?id='.$m_id.SEP.'m='.$code.SEP.'en_id='.$_REQUEST["en_id"];
+                       else
+                               $confirmation_link = $_base_href . 'confirm.php?id='.$m_id.SEP.'m='.$code;
+
+                       /* send the email confirmation message: */
+                       require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+                       $mail = new ATutorMailer();
+
+                       $mail->From     = $_config['contact_email'];
+                       $mail->AddAddress($_POST['email']);
+                       $mail->Subject = SITE_NAME . ' - ' . _AT('email_confirmation_subject');
+                       $mail->Body    = _AT('email_confirmation_message', SITE_NAME, $confirmation_link);
+
+                       $mail->Send();
+
+               } 
+               else 
+               {
+                       // if en_id is set, automatically enroll into courses that links with en_id and go to "My Start Page"
+                       $member_id      = $m_id;
+
+                       require (AT_INCLUDE_PATH.'html/auto_enroll_courses.inc.php');
+                       
+                       // auto login
+                       $_SESSION['valid_user'] = true;
+                       $_SESSION['member_id']  = $m_id;
+                       $_SESSION['course_id']  = 0;
+                       $_SESSION['login']              = $_POST[login];
+                       assign_session_prefs(unserialize(stripslashes($_config[pref_defaults])));
+                       $_SESSION['is_guest']   = 0;
+                       $_SESSION['lang']               = $_SESSION[lang];
+                       session_write_close();
+
+                       header('Location: '.AT_BASE_HREF.'bounce.php?course='.$_POST['course']);
+               }
+
+               require(AT_INCLUDE_PATH.'header.inc.php');
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+} else {
+       $_POST = array();
+}
+
+unset($_SESSION['member_id']);
+unset($_SESSION['valid_user']);
+unset($_SESSION['login']);
+unset($_SESSION['is_admin']);
+unset($_SESSION['course_id']);
+unset($_SESSION['is_guest']);
+
+/*****************************/
+/* template starts down here */
+
+if (defined('AT_MASTER_LIST') && AT_MASTER_LIST) {
+       $onload = 'document.form.student_id.focus();';
+} else {
+       $onload = 'document.form.login.focus();';
+}
+
+$savant->assign('languageManager', $languageManager);
+
+$savant->display('registration.tmpl.php');
+
+?>
\ No newline at end of file
diff --git a/search.php b/search.php
new file mode 100644 (file)
index 0000000..b81a513
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                      */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg & Boon-Hau Teh */
+/* Adaptive Technology Resource Centre / University of Toronto          */
+/* http://atutor.ca                                                                                                    */
+/*                                                                      */
+/* 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.                                       */
+/************************************************************************/
+// $Id$
+
+$_user_location = 'public';
+
+define('AT_INCLUDE_PATH', 'include/');
+require(AT_INCLUDE_PATH . 'vitals.inc.php');
+require(AT_INCLUDE_PATH . 'lib/search.inc.php');
+$onload = 'document.form.keywords.focus();';
+require(AT_INCLUDE_PATH . 'header.inc.php');
+require(AT_INCLUDE_PATH . 'html/search.inc.php');
+require(AT_INCLUDE_PATH . 'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/sha-1factory.js b/sha-1factory.js
new file mode 100644 (file)
index 0000000..00e8c30
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
+ * in FIPS PUB 180-1
+ * Version 2.1 Copyright Paul Johnston 2000 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for details.
+ */
+
+var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
+var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
+var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
+function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
+function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
+function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
+function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
+function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function sha1_vm_test()
+{
+  return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
+}
+
+/*
+ * Calculate the SHA-1 of an array of big-endian words, and a bit length
+ */
+function core_sha1(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << (24 - len % 32);
+  x[((len + 64 >> 9) << 4) + 15] = len;
+
+  var w = Array(80);
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+  var e = -1009589776;
+
+  for(var i = 0; i < x.length; i += 16)
+  {
+    var olda = a;
+    var oldb = b;
+    var oldc = c;
+    var oldd = d;
+    var olde = e;
+
+    for(var j = 0; j < 80; j++)
+    {
+      if(j < 16) w[j] = x[i + j];
+      else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
+      var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), 
+                       safe_add(safe_add(e, w[j]), sha1_kt(j)));
+      e = d;
+      d = c;
+      c = rol(b, 30);
+      b = a;
+      a = t;
+    }
+
+    a = safe_add(a, olda);
+    b = safe_add(b, oldb);
+    c = safe_add(c, oldc);
+    d = safe_add(d, oldd);
+    e = safe_add(e, olde);
+  }
+  return Array(a, b, c, d, e);
+  
+}
+
+/*
+ * Perform the appropriate triplet combination function for the current
+ * iteration
+ */
+function sha1_ft(t, b, c, d)
+{
+  if(t < 20) return (b & c) | ((~b) & d);
+  if(t < 40) return b ^ c ^ d;
+  if(t < 60) return (b & c) | (b & d) | (c & d);
+  return b ^ c ^ d;
+}
+
+/*
+ * Determine the appropriate additive constant for the current iteration
+ */
+function sha1_kt(t)
+{
+  return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 :
+         (t < 60) ? -1894007588 : -899497514;
+}  
+
+/*
+ * Calculate the HMAC-SHA1 of a key and some data
+ */
+function core_hmac_sha1(key, data)
+{
+  var bkey = str2binb(key);
+  if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
+
+  var ipad = Array(16), opad = Array(16);
+  for(var i = 0; i < 16; i++) 
+  {
+    ipad[i] = bkey[i] ^ 0x36363636;
+    opad[i] = bkey[i] ^ 0x5C5C5C5C;
+  }
+
+  var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
+  return core_sha1(opad.concat(hash), 512 + 160);
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+  return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert an 8-bit or 16-bit string to an array of big-endian words
+ * In 8-bit function, characters >255 have their hi-byte silently ignored.
+ */
+function str2binb(str)
+{
+  var bin = Array();
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < str.length * chrsz; i += chrsz)
+    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);
+  return bin;
+}
+
+/*
+ * Convert an array of big-endian words to a string
+ */
+function binb2str(bin)
+{
+  var str = "";
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < bin.length * 32; i += chrsz)
+    str += String.fromCharCode((bin[i>>5] >>> (24 - i%32)) & mask);
+  return str;
+}
+
+/*
+ * Convert an array of big-endian words to a hex string.
+ */
+function binb2hex(binarray)
+{
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i++)
+  {
+    str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
+           hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);
+  }
+  return str;
+}
+
+/*
+ * Convert an array of big-endian words to a base-64 string
+ */
+function binb2b64(binarray)
+{
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i += 3)
+  {
+    var triplet = (((binarray[i   >> 2] >> 8 * (3 -  i   %4)) & 0xFF) << 16)
+                | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
+                |  ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
+    for(var j = 0; j < 4; j++)
+    {
+      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+    }
+  }
+  return str;
+}
+
+
+/* 
+ * Verify passwords and its confirm
+ * password1: password
+ * password2: confirm password
+ */
+function verify_password(password1, password2)
+{
+       
+       var err = new Array();
+
+       if (password1 == "" || password2 == "")
+       {
+               err[err.length] = "missing_password";
+       }
+       if (password1 != password2)
+       {
+               err[err.length] = "PASSWORD_MISMATCH";
+       }
+       if (password1.length < 8)
+       {
+               err[err.length] = "PASSWORD_LENGTH";
+       }
+       if (password1.search(/[a-zA-Z]+/) +  password1.search(/[0-9]+/) + password1.search(/[_\-\/+!@#%^$*&)(|.]+/) < 0)
+       {
+               err[err.length] = "PASSWORD_CHARS";
+       }
+
+       return err;
+}      
diff --git a/sitemap.php b/sitemap.php
new file mode 100644 (file)
index 0000000..77663a3
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+$page = 'sitemap';
+define('AT_INCLUDE_PATH', 'include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/forums.inc.php');
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+echo '<p><a href="index.php">'._AT('home').'</a>';
+
+$_current_modules = array_slice($_pages[AT_NAV_COURSE], 1);
+$_current_modules = array_merge((array) $_current_modules, array_diff($_pages[AT_NAV_HOME],$_pages[AT_NAV_COURSE]));
+
+foreach ($_current_modules as $module) {
+       echo '<br />';
+       echo '<img src="images/'.$rtl.'tree/tree_split.gif" alt="" class="img-size-tree" />  <a href="'.url_rewrite($module).'">' . _AT($_pages[$module]['title_var']) . '</a>';
+
+       if ($module == 'forum/list.php') {
+               $forums = get_forums($_SESSION['course_id']);
+               if (is_array($forums)) {
+                       foreach ($forums as $state=>$rows) {
+                               $count = 0;
+                               $num_forums = count($rows);
+                               foreach ($rows as $row) {
+                                       $count++;
+                                       echo '<br />';
+                                       echo '<img src="images/'.$rtl.'tree/tree_vertline.gif" alt="" class="img-size-tree" />';
+                                       if ($count < $num_forums) {
+                                               echo '<img src="images/'.$rtl.'tree/tree_split.gif" alt="" class="img-size-tree" />';
+                                       } else {
+                                               echo '<img src="images/'.$rtl.'tree/tree_end.gif" alt="" class="img-size-tree" />';
+                                       }
+                                       echo '<img src="images/'.$rtl.'tree/tree_horizontal.gif" alt="" class="img-size-tree" />';
+                                       echo ' <a href="'.url_rewrite('forum/index.php?fid='.$row['forum_id']).'">'.AT_print($row['title'], 'forums.title').'</a>';
+                               }
+                       } 
+               } else {
+                       echo '<br />';
+                       echo '<img src="images/'.$rtl.'tree/tree_vertline.gif" alt="" class="img-size-tree" />';
+                       echo '<img src="images/'.$rtl.'tree/tree_vertline.gif" alt="" class="img-size-tree" />';
+                       echo '<img src="images/'.$rtl.'tree/tree_end.gif" alt="" class="img-size-tree" />';
+                       echo _AT('no_forums');
+               }
+       }
+}
+
+echo '<br /><img src="images/'.$rtl.'tree/tree_split.gif" alt="" class="img-size-tree" /> <a href="'.url_rewrite('search.php').'">'._AT('search').'</a><br />';
+echo '<img src="images/'.$rtl.'tree/tree_split.gif" alt="" class="img-size-tree" /> <a href="help/">'._AT('help').'</a><br />';
+echo '<img src="images/'.$rtl.'tree/tree_end.gif" alt="" class="img-size-tree" /> '._AT('content').'<br />';
+
+$contentManager->printSiteMapMenu();
+
+echo '</p>';
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/svn.php b/svn.php
new file mode 100644 (file)
index 0000000..d8ab13b
--- /dev/null
+++ b/svn.php
@@ -0,0 +1,28 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg, Heidi Hazelton        */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+
+// $Id$
+
+/* created by the bundle script.                     */
+/* the resulting file will look something like this: */
+/* $svn_data = '
+------------------------------------------------------------------------
+r3125 | joel | 2005-01-21 16:27:14 -0500 (Fri, 21 Jan 2005)
+------------------------------------------------------------------------';
+*/
+
+
+$svn_data = '
+------------------------------------------------------------------------
+r3125 | joel | 2005-01-21 16:27:14 -0500 (Fri, 21 Jan 2005)
+------------------------------------------------------------------------';
+?>
\ No newline at end of file
diff --git a/themes/blumin/content.tmpl.php b/themes/blumin/content.tmpl.php
new file mode 100644 (file)
index 0000000..89d2412
--- /dev/null
@@ -0,0 +1,31 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+if (!defined('AT_INCLUDE_PATH')) { exit; } ?>\r
+\r
+<?php if ($this->shortcuts): ?>\r
+<fieldset id="shortcuts"><legend><?php echo _AT('shortcuts'); ?></legend>\r
+       <ul>\r
+               <?php foreach ($this->shortcuts as $link): ?>\r
+                       <li><a href="<?php echo $link['url']; ?>"><?php echo $link['title']; ?></a></li>\r
+               <?php endforeach; ?>\r
+       </ul>\r
+</fieldset>\r
+<?php endif; ?>\r
+\r
+<div id="content-text">\r
+       <?php echo $this->body; ?>\r
+</div>\r
+\r
+<div id="content-info">\r
+       <?php echo $this->content_info; ?>\r
+</div>
\ No newline at end of file
diff --git a/themes/blumin/forms.css b/themes/blumin/forms.css
new file mode 100644 (file)
index 0000000..cc1e3cd
--- /dev/null
@@ -0,0 +1,73 @@
+div.input-form {\r
+       width: 80%; \r
+       max-width: 600px;\r
+       margin-left:auto; \r
+       margin-right:auto;\r
+       border: 1px solid #f0f0f0;\r
+       margin-bottom: 20px;\r
+}\r
+\r
+div.input-form div.row h3 {\r
+       margin-left: 0px;\r
+}\r
+\r
+\r
+div.input-form div.row {\r
+       background-color: #fdfdfd;\r
+       padding:8px;\r
+}\r
+\r
+div.input-form .footer {\r
+       border-top: 1px solid #f0f0f0;\r
+}\r
+\r
+div.input-form p {\r
+       margin-left: 0px;\r
+}\r
+\r
+div.input-form input {\r
+       z-index: 2;\r
+}\r
+div.input-form textarea {\r
+       border: 1px solid #999;\r
+       width: 98%;\r
+       background-color: white;\r
+       padding: 2px;\r
+       margin-right: 2px;\r
+}\r
+\r
+div.input-form textarea:focus {\r
+       border:1px solid blue;\r
+       background-color: white;\r
+       padding: 2px;\r
+}\r
+\r
+div.input-form input[type=text], div.input-form input[type=password] {\r
+       border: 1px solid #999;\r
+       background-color: white;\r
+       padding: 2px;\r
+       max-width: 60%;\r
+}\r
+\r
+div.input-form input:focus {\r
+       border: 1px solid blue;\r
+       padding: 2px\r
+}\r
+\r
+div.input-form div.buttons {\r
+       text-align: right;\r
+       padding:8px;\r
+}\r
+div.input-form div.buttons input {\r
+       border: 1px solid #999;\r
+       background-color: white;\r
+       padding: 2px;\r
+       padding-left: 10px;\r
+       padding-right: 10px;\r
+       min-width: 100px;\r
+       margin-left: 5px;\r
+}\r
+div.input-form div.buttons input:hover {\r
+       background-color: #f5f5ff;\r
+       border: 1px solid blue;\r
+}
\ No newline at end of file
diff --git a/themes/blumin/ie_styles.css b/themes/blumin/ie_styles.css
new file mode 100644 (file)
index 0000000..9b19ba5
--- /dev/null
@@ -0,0 +1,23 @@
+/* IE specific styles */
+
+ul#topnavlist {
+       zoom:100%;
+       margin:0px;
+}
+
+ul#topnavlist li {
+       zoom:100%;
+       padding:0.3em;
+       padding-bottom:0.3em;
+       margin:0px;
+       margin-bottom:-3px;
+}
+
+label {
+       zoom:100%;
+       margin:0px;
+}
+
+table.data tfoot input {
+       min-width:0px;
+}
\ No newline at end of file
diff --git a/themes/blumin/images/arrow_ltr.gif b/themes/blumin/images/arrow_ltr.gif
new file mode 100644 (file)
index 0000000..90da978
Binary files /dev/null and b/themes/blumin/images/arrow_ltr.gif differ
diff --git a/themes/blumin/images/back.gif b/themes/blumin/images/back.gif
new file mode 100644 (file)
index 0000000..f290f43
Binary files /dev/null and b/themes/blumin/images/back.gif differ
diff --git a/themes/blumin/images/continue.gif b/themes/blumin/images/continue.gif
new file mode 100644 (file)
index 0000000..157d3f1
Binary files /dev/null and b/themes/blumin/images/continue.gif differ
diff --git a/themes/blumin/images/linkOpaque.gif b/themes/blumin/images/linkOpaque.gif
new file mode 100644 (file)
index 0000000..12e588f
Binary files /dev/null and b/themes/blumin/images/linkOpaque.gif differ
diff --git a/themes/blumin/images/linkTransparent.gif b/themes/blumin/images/linkTransparent.gif
new file mode 100644 (file)
index 0000000..c2dd10f
Binary files /dev/null and b/themes/blumin/images/linkTransparent.gif differ
diff --git a/themes/blumin/images/newsitem_icon.gif b/themes/blumin/images/newsitem_icon.gif
new file mode 100644 (file)
index 0000000..fd6e96f
Binary files /dev/null and b/themes/blumin/images/newsitem_icon.gif differ
diff --git a/themes/blumin/images/next.gif b/themes/blumin/images/next.gif
new file mode 100644 (file)
index 0000000..9477a7b
Binary files /dev/null and b/themes/blumin/images/next.gif differ
diff --git a/themes/blumin/images/previous.gif b/themes/blumin/images/previous.gif
new file mode 100644 (file)
index 0000000..69c43e7
Binary files /dev/null and b/themes/blumin/images/previous.gif differ
diff --git a/themes/blumin/images/resume.gif b/themes/blumin/images/resume.gif
new file mode 100644 (file)
index 0000000..b80d5eb
Binary files /dev/null and b/themes/blumin/images/resume.gif differ
diff --git a/themes/blumin/images/side_arrow.gif b/themes/blumin/images/side_arrow.gif
new file mode 100644 (file)
index 0000000..c72b458
Binary files /dev/null and b/themes/blumin/images/side_arrow.gif differ
diff --git a/themes/blumin/images/sort.gif b/themes/blumin/images/sort.gif
new file mode 100644 (file)
index 0000000..097d27e
Binary files /dev/null and b/themes/blumin/images/sort.gif differ
diff --git a/themes/blumin/images/user-star.gif b/themes/blumin/images/user-star.gif
new file mode 100644 (file)
index 0000000..e53b7d5
Binary files /dev/null and b/themes/blumin/images/user-star.gif differ
diff --git a/themes/blumin/images/user.gif b/themes/blumin/images/user.gif
new file mode 100644 (file)
index 0000000..74a3cf5
Binary files /dev/null and b/themes/blumin/images/user.gif differ
diff --git a/themes/blumin/include/box.tmpl.php b/themes/blumin/include/box.tmpl.php
new file mode 100644 (file)
index 0000000..fb049c4
--- /dev/null
@@ -0,0 +1,7 @@
+<?php if (!defined('AT_INCLUDE_PATH')) { exit; } ?>
+
+<br />
+<h4 class="box"><?php echo $this->title; ?></h4>
+<div class="box">
+               <?php echo $this->dropdown_contents; ?>
+</div>
\ No newline at end of file
diff --git a/themes/blumin/include/footer.tmpl.php b/themes/blumin/include/footer.tmpl.php
new file mode 100644 (file)
index 0000000..de71190
--- /dev/null
@@ -0,0 +1,25 @@
+<?php if (!defined('AT_INCLUDE_PATH')) { exit; } ?>
+
+       <?php if ($_SESSION['course_id'] > 0): ?>
+               
+               <div align="right" style="clear: left;" id="gototop">           
+                       <br />
+                       <span style="font-size:smaller;padding-right:3px;"><a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#content" title="<?php echo _AT('goto_content'); ?> Alt-c" ><?php echo _AT('goto_top'); ?></a>  </span>
+               </div>  
+
+       <?php endif; ?> 
+
+</div>
+</div>
+       <?php if (($_SESSION['course_id'] > 0) && $this->side_menu): ?>
+               <div id="rightcolumn">
+                       <?php require(AT_INCLUDE_PATH.'side_menu.inc.php'); ?>
+               </div>
+       <?php endif; ?>
+<div id="footer">
+       <br /><br />
+       <?php require(AT_INCLUDE_PATH.'html/languages.inc.php'); ?>
+       <?php require(AT_INCLUDE_PATH.'html/copyright.inc.php'); ?>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/themes/blumin/include/header.tmpl.php b/themes/blumin/include/header.tmpl.php
new file mode 100644 (file)
index 0000000..348fb50
--- /dev/null
@@ -0,0 +1,228 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: header.tmpl.php 3825 2005-03-11 15:35:51Z joel $
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+/* available header.tmpl.php variables:
+ * $this->lang_code                    the ISO language code
+ * SITE_NAME                           the site name from the config file
+ * $this->page_title           the name of this page to use in the <title>
+ * $this->lang_charset         the ISO language character set
+ * $this->content_base_href    the <base href> to use for this page
+ * $this->base_path                    the absolute path to this atutor installation
+ * $this->rtl_css                      if set, the path to the RTL style sheet
+ * $this->banner_style         -deprecated-
+ * $this->theme                                the directory name of the current theme
+ * $this->base_href                    the full url to this atutor installation
+ * $this->onload                       javascript onload() calls
+ * $this->img                          the absolute path to this theme's images/ directory
+ * $this->sequence_links       associative array of 'previous', 'next', and/or 'resume' links
+ * $this->path                         associative array of path to this page: aka bread crumbs
+ * $this->rel_url                      the relative url from the installation root to this page
+ * $this->nav_courses          associative array of this user's enrolled courses
+ * $this->section_title                the title of this section (course, public, admin, my start page)
+ * $this->top_level_pages      associative array of the top level navigation
+ * $this->current_top_level_page       the full path to the current top level page with file name
+ * $this->sub_level_pages                      associate array of sub level navigation
+ * $this->back_to_page                         if set, the path and file name to the part of this page (if parent is not a top level nav)
+ * $this->current_sub_level_page       the full path to the current sub level page with file name
+ * $this->guide                                the full path and file name to the guide page
+ * ======================================
+ * top_level_pages           array(array('url', 'title'))     the top level pages. ATutor default creates tabs.
+ * section_title             string                           the name of the current section. either name of the course, administration, my start page, etc.
+ * page_title                string                           the title of the current page.
+ * path                      array(array('url', 'title'))     the path to the current page.
+ * back_to_page              array('url', 'title')            the link back to the part of the current page, if needed.
+ * current_top_level_page    string                           full url to the current top level page in "top_leve_pages"
+ * current_sub_level_page    string                           full url to the current sub level page in the "sub_level_pages"
+ * sub_level_pages           array(array('url', 'title'))     the sub level pages.
+ */
+
+// will have to be moved to the header.inc.php
+global $system_courses, $_custom_css;
+
+?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html lang="<?php echo $this->lang_code; ?>">
+<head>
+       <title><?php echo SITE_NAME; ?> : <?php echo $this->page_title; ?></title>
+       <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $this->lang_charset; ?>" />
+       <meta name="Generator" content="ATutor - Copyright 2005 by http://atutor.ca" />
+       <base href="<?php echo $this->content_base_href; ?>" />
+       <link rel="shortcut icon" href="<?php echo $this->base_path; ?>favicon.ico" type="image/x-icon" />
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/print.css" type="text/css" media="print" />
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/styles.css" type="text/css" />
+       <!--[if IE]>
+         <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/ie_styles.css" type="text/css" />
+       <![endif]-->
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/forms.css" type="text/css" />
+       <?php echo $this->rtl_css; ?>
+       <?php if ($system_courses[$_SESSION['course_id']]['rss']): ?>
+       <link rel="alternate" type="application/rss+xml" title="<?php echo SITE_NAME; ?> - RSS 2.0" href="<?php echo $this->base_href; ?>get_rss.php?<?php echo $_SESSION['course_id']; ?>-2" />
+       <link rel="alternate" type="application/rss+xml" title="<?php echo SITE_NAME; ?> - RSS 1.0" href="<?php echo $this->base_href; ?>get_rss.php?<?php echo $_SESSION['course_id']; ?>-1" />
+       <?php endif; ?>
+       <?php echo $this->custom_css; ?>
+</head>
+<body onload="<?php echo $this->onload; ?>"><div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>
+<script language="JavaScript" src="<?php echo $this->base_path; ?>overlib.js" type="text/javascript"></script>
+<script language="javascript" type="text/javascript">
+//<!--
+var newwindow;
+function poptastic(url) {
+       newwindow=window.open(url,'popup','height=600,width=600,scrollbars=yes,resizable=yes');
+       if (window.focus) {newwindow.focus()}
+}
+//-->
+</script>
+<!-- section title -->
+<div><a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#content" accesskey="c"><img src="<?php echo $this->base_path; ?>images/clr.gif" height="1" width="1" border="0" alt="<?php echo _AT('goto_content'); ?> ALT+c" /></a>               <a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#menu"  accesskey="m"><img src="<?php echo $this->base_path; ?>images/clr.gif" height="1" width="1" border="0" alt="<?php echo _AT('goto_menu'); ?> ALT+m" /></a><h1 id="section-title"><?php echo $this->section_title; ?><?php if (($_SESSION['course_id'] > 0) && ($_SESSION['enroll'] == AT_ENROLL_NO)) : ?>
+               - <small><a href="<?php echo $this->base_path; ?>enroll.php?course=<?php echo $_SESSION['course_id']; ?>"><?php echo _AT('enroll_me'); ?></a></small>
+       <?php endif; ?></h1>
+</div>
+
+<!-- top help/search/login links -->
+<div align="right" id="top-links">
+<!-- back to start page -->
+       <?php if (isset($_SESSION['member_id']) && $_SESSION['member_id']): ?>
+               <!-- start the jump menu -->
+               <?php if (empty($_GET)): ?>
+                       <form method="post" action="<?php echo $this->base_path; ?>bounce.php?p=<?php echo urlencode($this->rel_url); ?>" target="_top">
+               <?php else: ?>
+                       <form method="post" action="<?php echo $this->base_path; ?>bounce.php" target="_top">
+               <?php endif; ?>
+               <label for="jumpmenu" accesskey="j"></label>
+                       <select name="course" id="jumpmenu" title="<?php echo _AT('jump'); ?>:  Alt-j">                                                 
+                               <option value="0"><?php echo _AT('my_start_page'); ?></option>
+                               <optgroup label="<?php echo _AT('courses_below'); ?>">
+                                       <?php foreach ($this->nav_courses as $this_course_id => $this_course_title): ?>
+                                               <option value="<?php echo $this_course_id; ?>"><?php echo $this_course_title; ?></option>
+                                       <?php endforeach; ?>
+                               </optgroup>
+                       </select> <input type="submit" name="jump" value="<?php echo _AT('jump'); ?>" id="jump-button" /> &nbsp; </form>
+               <!-- /end the jump menu -->
+               <?php if ($_SESSION['is_super_admin']): ?>
+                       <img src="<?php echo $this->img; ?>linkTransparent.gif" alt="" /> <a href="<?php echo $this->base_path; ?>bounce.php?admin"><?php echo _AT('return_to_admin_area'); ?></a> | 
+               <?php endif; ?>
+
+               <?php if ($_SESSION['course_id'] > -1): ?>
+                       <?php if (get_num_new_messages()): ?>
+                               <img src="<?php echo $this->img; ?>linkTransparent.gif" alt="" /> <a href="<?php echo $this->base_path; ?>inbox/index.php"><?php echo _AT('inbox'); ?> (<?php echo get_num_new_messages(); ?>)</a>
+                       <?php else: ?>
+                               <img src="<?php echo $this->img; ?>linkTransparent.gif" alt="" /> <a href="<?php echo $this->base_path; ?>inbox/index.php"><?php echo _AT('inbox'); ?></a>
+                       <?php endif; ?>
+               <?php endif; ?>
+       <?php endif; ?>
+
+       <img src="<?php echo $this->img; ?>linkTransparent.gif" alt="" /> <a href="<?php echo $this->base_path; ?>search.php"><?php echo _AT('search'); ?></a> <img src="<?php echo $this->img; ?>linkTransparent.gif" alt="" /> <a href="<?php echo $this->base_path; ?>help/index.php"><?php echo _AT('help'); ?></a>
+</div>
+<br />
+<div id="topnavlistcontainer">
+<!-- the main navigation. in our case, tabs -->
+       <ul id="topnavlist">
+               <?php foreach ($this->top_level_pages as $page): ?>
+                       <?php ++$accesscounter; $accesscounter = ($accesscounter == 10 ? 0 : $accesscounter); ?>
+                       <?php $accesskey_text = ($accesscounter < 10 ? 'accesskey="'.$accesscounter.'"' : ''); ?>
+                       <?php $accesskey_title = ($accesscounter < 10 ? ' Alt+'.$accesscounter : ''); ?>
+                       <?php if ($page['url'] == $this->current_top_level_page): ?>
+                               <li><a href="<?php echo $page['url']; ?>" <?php echo $accesskey_text; ?> title="<?php echo $page['title'] . $accesskey_title; ?>" class="active"><?php echo $page['title']; ?></a></li>
+                       <?php else: ?>
+                               <li><a href="<?php echo $page['url']; ?>" <?php echo $accesskey_text; ?> title="<?php echo $page['title'] . $accesskey_title; ?>"><?php echo $page['title']; ?></a></li>
+                       <?php endif; ?>
+                       <?php $accesscounter = ($accesscounter == 0 ? 11 : $accesscounter); ?>
+               <?php endforeach; ?>
+       </ul>
+</div>
+
+<!-- the sub navigation -->
+<div style="float: right; padding-top: 5px; padding-right: 5px; font-size:0.85em; text-transform: lowercase;" id="suv-nav-logout">
+       <?php if ($_SESSION['valid_user']): ?>                                  
+               <strong><?php echo get_display_name($_SESSION['member_id']); ?></strong> &nbsp; <img src="<?php echo $this->img; ?>/linkOpaque.gif" alt="" /> <a href="<?php echo $this->base_path; ?>logout.php"><?php echo _AT('logout'); ?></a>
+       <?php else: ?>
+                <img src="<?php echo $this->img; ?>/linkOpaque.gif" alt="" /> <a href="<?php echo $this->base_path; ?>login.php?course=<?php echo $_SESSION['course_id']; ?>"><?php echo _AT('login'); ?></a> &nbsp; <img src="<?php echo $this->img; ?>/linkOpaque.gif" alt="" /> <a href="<?php echo $this->base_path; ?>registration.php"><?php echo _AT('register'); ?></a>
+       <?php endif; ?>
+</div>
+
+<?php if ($this->sub_level_pages): ?>
+       <div id="sub-navigation">
+               <?php if (isset($this->back_to_page)): ?>
+                       <a href="<?php echo $this->back_to_page['url']; ?>" id="back-to"><?php echo _AT('back_to').' '.$this->back_to_page['title']; ?></a> | 
+               <?php endif; ?>
+
+               <?php $num_pages = count($this->sub_level_pages); ?>
+               <?php for ($i=0; $i<$num_pages; $i++): ?>
+                       <?php if ($this->sub_level_pages[$i]['url'] == $this->current_sub_level_page): ?>
+                               <strong><?php echo $this->sub_level_pages[$i]['title']; ?></strong>
+                       <?php else: ?>
+                               <a href="<?php echo $this->sub_level_pages[$i]['url']; ?>"><?php echo $this->sub_level_pages[$i]['title']; ?></a>
+                       <?php endif; ?>
+                       <?php if ($i < $num_pages-1): ?>
+                               |
+                       <?php endif; ?>
+               <?php endfor; ?>
+       </div>
+<?php else: ?>
+       <div id="sub-navigation">
+               &nbsp;
+       </div>
+<?php endif; ?>
+
+<!-- the bread crumbs -->
+<div id="breadcrumbs">
+       <?php foreach ($this->path as $page): ?>
+               <a href="<?php echo $page['url']; ?>"><?php echo $page['title']; ?></a> » 
+       <?php endforeach; ?> <?php echo htmlspecialchars($this->page_title, ENT_COMPAT, "UTF-8"); ?>
+</div>
+
+<div id="contentwrapper">
+<div id="contentcolumn"
+       <?php if (($_SESSION['course_id'] <= 0) && !$this->side_menu): ?>
+               style="margin-right:0px;width:99%;"
+       <?php endif; ?>
+       >
+
+<!-- the page title -->
+       <div style="text-align: right; padding-bottom: 10px; padding-right: 10px; float: right; margin-top: 10px; padding-right: 5px; font-size:0.95em;">
+               <?php if ($this->guide): ?>
+                       <a href="<?php echo $this->guide; ?>" id="guide" onclick="poptastic('<?php echo $this->guide; ?>'); return false;" target="_new"><em><?php echo $this->page_title; ?></em></a>
+               <?php endif; ?>
+               <?php if ($_SESSION['course_id'] > 0 && $system_courses[$_SESSION['course_id']]['side_menu']): ?>
+                       <script type="text/javascript" language="javascript">
+                       //<![CDATA[
+                       var state = getcookie("side-menu");
+                       if (state && (state == 'none')) {
+                               showTocToggle("side-menu", "<?php echo _AT('show'); ?>","<?php echo _AT('hide'); ?>", "", "show");
+                       } else {
+                               showTocToggle("side-menu", "<?php echo _AT('show'); ?>","<?php echo _AT('hide'); ?>", "", "hide");
+                       }
+                       //]]>
+                       </script>
+               <?php endif; ?>
+       </div>
+
+       <div style="float:right;padding-top:7px;" id="sequence-links">
+               <?php if ($this->sequence_links['resume']): ?>
+                               <a style="color:white;" href="<?php echo $this->sequence_links['resume']['url']; ?>" accesskey="."><img src="<?php echo $this->img; ?>resume.gif" border="0" title="<?php echo _AT('resume').': '.$this->sequence_links['resume']['title']; ?> Alt+." alt="<?php echo $this->sequence_links['resume']['title']; ?> Alt+." class="img-size-ascdesc" /></a>
+               <?php else:
+                       if ($this->sequence_links['previous']): ?>
+                               <a href="<?php echo $this->sequence_links['previous']['url']; ?>" title="<?php echo _AT('previous_topic').': '. $this->sequence_links['previous']['title']; ?> Alt+," accesskey=","><img src="<?php echo $this->img; ?>previous.gif" border="0" alt="<?php echo _AT('previous_topic').': '. $this->sequence_links['previous']['title']; ?> Alt+," class="img-size-ascdesc" /></a>
+                       <?php endif;
+                       if ($this->sequence_links['next']): ?>
+                               <a href="<?php echo $this->sequence_links['next']['url']; ?>" title="<?php echo _AT('next_topic').': '.$this->sequence_links['next']['title']; ?> Alt+." accesskey="."><img src="<?php echo $this->img; ?>next.gif" border="0" alt="<?php echo _AT('next_topic').': '.$this->sequence_links['next']['title']; ?> Alt+." class="img-size-ascdesc" /></a>
+                       <?php endif; ?>
+               <?php endif; ?>
+               &nbsp;
+       </div>
+
+<!-- the page title -->
+<h2 class="page-title"><?php echo htmlspecialchars($this->page_title, ENT_COMPAT, "UTF-8"); ?></h2>
+
+<a name="content"></a>
+<?php global $msg; $msg->printAll(); ?>
\ No newline at end of file
diff --git a/themes/blumin/include/side_menu.tmpl.php b/themes/blumin/include/side_menu.tmpl.php
new file mode 100644 (file)
index 0000000..48f1cf9
--- /dev/null
@@ -0,0 +1,8 @@
+<?php if (!defined('AT_INCLUDE_PATH')) { exit; } ?>
+
+<?php if (($_SESSION['course_id'] > 0) && $this->side_menu): ?>
+       <?php foreach ($this->side_menu as $dropdown_file): ?>
+               <?php if (file_exists($dropdown_file)) { require($dropdown_file); } ?>
+       <?php endforeach; ?>
+<div style="position:absolute; bottom:0px;">&nbsp;</div>
+<?php endif; ?>
diff --git a/themes/blumin/print.css b/themes/blumin/print.css
new file mode 100644 (file)
index 0000000..48b2bc1
--- /dev/null
@@ -0,0 +1,13 @@
+body {
+       background-color: White;
+       font-family: Helvetica, arial, sans serif;
+       margin: 0px;
+       margin-top: 0px;
+       color: black;
+       border: 0px;
+}
+
+div#side-menu, div#member-links, span#side-menushowlink, div#rightcolumn, div#suv-nav-logout, div#top-links, span#side-menuhidelink, div#sequence-links, select#jumpmenu, a#guide, div#gototop, input#jump-button, div#topnavlistcontainer, a#guide, div#breadcrumbs, div#jump-area, table.tabbed-table, div#sub-navigation, div#sequence-links, div#language, div#toc, fieldset#shortcuts {
+       display: none;
+}
+
diff --git a/themes/blumin/readme.txt b/themes/blumin/readme.txt
new file mode 100644 (file)
index 0000000..71cb1e0
--- /dev/null
@@ -0,0 +1,9 @@
+\r
+Theme:         Plone-like\r
+Date:          March 2005\r
+\r
+\r
+Installing:    See section "Installing a New Theme" in the themes_readme.txt file located in docs/themes/.\r
+\r
+Licence:       Falls under the GPL agreement.  See http://www.gnu.org/copyleft/gpl.html.\r
+       
\ No newline at end of file
diff --git a/themes/blumin/screenshot.gif b/themes/blumin/screenshot.gif
new file mode 100644 (file)
index 0000000..bc1161c
Binary files /dev/null and b/themes/blumin/screenshot.gif differ
diff --git a/themes/blumin/styles.css b/themes/blumin/styles.css
new file mode 100644 (file)
index 0000000..3671fe3
--- /dev/null
@@ -0,0 +1,1346 @@
+/* main body attributes */
+body {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       margin-top: 0px;
+       margin-left: auto;
+       margin-right: auto;
+       font-size: small;
+       background-color: white;
+}
+
+p {
+    margin: 0.5em 0em 1em 0em;
+    text-align: justify;
+    line-height: 150%;
+       font-size: 0.9em;
+}
+
+p a {
+    text-decoration: underline;
+}
+
+p a:visited {
+       color: Purple;
+    background-color: transparent;
+}
+
+p a:active {
+       color: Red;
+    background-color: transparent;
+}
+
+h1, h2, h3, h4, h5, h6 {
+    color: Black;
+    clear: left;
+    font: 100% Verdana, Helvetica, Arial, sans-serif;
+    margin: 0;
+    padding-top: 0.5em;
+    /*border-bottom: 1px solid #8CACBB;*/
+}
+
+h1 {
+    font-size: 160%;
+}
+
+h2 {
+    font-size: 150%;
+}
+
+h3 {
+    font-size: 130%;
+}
+
+h4 {
+    font-size: 120%;
+}
+
+h5 {
+    font-size: 100%;
+}
+
+textarea {
+    border: 1px solid #8cacbb;  
+    color: Black;
+    background-color: white;
+    width: 88%;
+    padding: 0.1em;
+}
+
+/*  Table of content attributes*/
+p.toc{
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #eeeeee;
+       padding: .6em;
+       margin-bottom: .6em;
+       margin-top: 0em;
+       margin-left: 1em;
+       margin-right: 3em;
+       border: 1px #98AAB1 solid;
+} 
+
+/* list attributes */
+ul {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+
+li {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+
+li.folders {
+       list-style: disc url(../../images/folder.gif) outside;
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+
+li.folders .disabled {
+       color: #AAAAAA;
+}
+
+/* link attributes */
+a:link {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: #384F89;
+       text-decoration: none;
+}
+a:visited {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: #384F89;
+       text-decoration: none;
+}
+a:hover {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: black;
+       text-decoration: none;
+}
+
+.formfieldR {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: black;
+       border-top:  #003399  solid 1px;
+       border-bottom: #003399 solid 1px;
+       border-right: #003399 solid 1px;
+       border-left: #003399 solid 1px;
+       text-align: right;
+       padding: 2px;
+}
+
+/* align text to the left */
+.left {
+       text-align: left;
+}
+
+a.dropdown-title {
+       color: white;
+       font-weight: normal;
+       text-decoration: none;
+}
+
+
+/* table border */
+.tableborder {
+       border: 1px #606060 solid;
+}
+
+/* main submit button */
+.button {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #EBEDF6;
+       font-weight: normal;
+       border-top:  #354A81  solid 1px;
+       border-bottom: #354A81 solid 1px;
+       border-right: #354A81 solid 1px;
+       border-left: #354A81 solid 1px; 
+}
+
+/* small submit button at top */
+.button2 {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #F8F8F8;
+       border-top:  #354A81  solid 1px;
+       border-bottom: #354A81  solid 1px;
+       border-right: #354A81  solid 1px;
+       border-left: #354A81  solid 1px;
+}
+
+/* date attributes */
+small.date {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: #8CACBB; 
+       margin-bottom: 0px; 
+       margin-top: 0px;
+       margin-left: 5px;
+       margin-right: 0px;
+       font-size:small;
+}
+
+/* page breakline */
+hr {
+       color: #98AAB1;
+       background-color: white;
+       height: 1px;
+}
+
+/* message box styles */
+
+/* Editor box small */
+.editorsmallbox {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #EEEEEE;
+       padding: 2px;
+       padding-right: 3px;
+       border: 1px #99CCCC solid;
+}
+
+/* Editor box large */
+.editorlargebox {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #EEEEEE;
+       margin-left:1em;
+       padding-left: .2em;
+       padding-right: .5em;
+       padding-top: .5em;
+       padding-bottom: .4em;
+       border: 1px #99CCCC solid;
+}
+
+
+select.dropdown {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+    background-color: #F1F3F1;
+}                                                               
+
+.highlight, a.highlight {
+       background-color: yellow;
+}
+
+a .highlight{
+       background-color: yellow;
+       text-decoration: underline;
+}
+
+.center {
+       text-align: center;
+}
+
+
+/* edit content tabs */
+.buttontab {
+       font-family: Helvetica, Arial, Helvetica, sans-serif;
+       background-color: #ffffff;
+       font-weight: bold;
+       border: 0px;
+       padding-left: 0px;
+       color: #8799A0;
+}
+
+.etab {
+       color: black;
+       background-color: #ffffff;
+       border-top: 1px #98AAB1 solid;
+       border-left: 1px #98AAB1 solid;
+       border-right: 1px #98AAB1 solid;
+       text-decoration: none;
+       text-align: center;
+       font-weight: bold;
+}
+
+.etab a:link, .etab a:visited {
+       color: black;
+       text-decoration: none;
+}
+.etab a:hover {
+       color: black;
+       text-decoration: underline;
+}
+.etabself {
+       background-color: #EFEFEF;
+       border-top: 1px #98AAB1 solid;
+       border-left: 1px  #98AAB1 solid;
+       border-right: 1px #98AAB1 solid;
+       text-align: center;
+       font-weight: bold;
+       padding: 2px;
+}
+.unsaved {
+       color: red;
+       background-color: #FFFDE0;
+       margin: 10px;
+       font-weight: bold;
+}
+.saved {
+       background-color: #FFFDE0;
+       margin: 10px;
+}
+
+
+
+/* the side menu */
+/* the side menu heading */
+td.dropdown-heading {
+       background-color: #D4E5FD;
+       color: #006699;
+       border-left: 1px solid #EAF2FE;
+       border-right: 1px solid #EAF2FE;
+       border-top: 1px solid #EAF2FE;
+       font-weight: bold;
+       padding: 2px;
+}
+
+td.dropdown-heading a, td.dropdown-heading a:hover, td.dropdown-heading a:visited {
+       text-decoration: none;
+}
+
+td.dropdown-heading.closed {
+       border-bottom: 1px solid #EAF2FE;
+}
+
+/* the side menu content */
+td.dropdown {
+       padding: 2px;
+       background-color: white;
+       color: black;
+       border-left: 1px solid #EAF2FE;
+       border-right: 1px solid #EAF2FE;
+       border-bottom: 1px solid #EAF2FE;
+       font-weight: normal;
+}
+td.dropdown a, td.dropdown a:visited  {
+       color: #006699;
+       text-decoration: none;
+}
+td.dropdown a:hover {
+       color: #006699;
+       text-decoration: underline;
+}
+td.dropdown.cell {
+       border-bottom: 0px;
+}
+td.dropdown strong {
+       color: #51286C;
+}
+
+/* added for 1.4.2: */
+.results {
+       padding-left: 20px;
+}
+
+h5.search-results {
+       background-color: #FFF5A4;
+       color: #006699;
+       padding: 1px;
+       margin-bottom: 5px;
+       margin-top: 10px;
+       margin-left: 5px;
+}
+
+small.search-info {
+       color: #006699;
+}
+
+p.search-description {
+       background-color: #FFFCE5;
+       color: #006699;
+}
+
+.test-box {
+       background-color: #FFF5A4;
+       color: #006699;
+       border-left: 1px solid #006699;
+       border-right: 1px solid #006699;
+       border-top: 1px solid #006699;
+       font-weight: bold;
+       padding: 2px;
+}
+
+/***************************************************************/
+/* NEW STUFF */
+
+table.tabbed-table {
+       width: 100%;
+}
+table.tabbed-table th#left-empty-tab {
+       background-color: transparent;
+       width: 15px;
+       border-bottom: 1px solid #9DAB9A;
+}
+table.tabbed-table th#right-empty-tab {
+       text-align: right;
+       background-color: transparent;
+       border-bottom: 1px solid #9DAB9A;
+       width: 400px;
+       padding-right: 5px;
+}
+table.tabbed-table th#right-empty-tab a {
+       text-decoration: underline;
+}
+table.tabbed-table th.tab-spacer {
+       background-color: transparent;
+       width: 5px;
+       border-bottom: 1px solid #9DAB9A;
+}
+
+table.tabbed-table th.tab {
+       padding-top: 2px;
+       padding-bottom: 2px;
+       width: 110px;
+       background-color: #C9CEA4;
+       border-bottom: 1px solid #9DAB9A;
+       border-left: 1px solid #9DAB9A;
+       border-top: 1px solid #9DAB9A;
+       border-right: 1px solid #9DAB9A;
+}
+table.tabbed-table th.tab:hover {
+       background-color: #DFE1C7;
+}
+
+table.tabbed-table th.tab a:focus {
+       color: white;
+}
+table.tabbed-table th.selected {
+       padding-top: 2px;
+       padding-bottom: 2px;
+       width: 110px;
+       background-color: #DFE1C7;
+       border-left: 1px solid #9DAB9A;
+       border-top: 1px solid #9DAB9A;
+       border-right: 1px solid #9DAB9A;
+}
+
+table.tabbed-table a, table.tabbed-table a:visited, table.tabbed-table a:hover {
+       color: black;
+       text-decoration: none;
+}
+
+a#my-start-page {
+       padding: 2px;
+       padding-left: 15px;
+       background-image: url(http://www.gris.uni-tuebingen.de/images/start.gif);
+       background-repeat: no-repeat;
+       background-position: 2px 5px;
+}
+
+a#back-to {
+       padding-left: 20px;
+       background-image: url(images/back.gif);
+       background-repeat: no-repeat;
+       background-position: 0px 0px;
+}
+
+div#breadcrumbs {
+    /* The path bar, including breadcrumbs and add to favorites */
+    border-bottom-color: #8CACBB;
+    border-bottom-style: solid;
+    border-bottom-width: 1px;
+    padding-left: 3px;
+    text-transform: lowercase;
+       font-size:0.85em;
+       padding-bottom: 1px;
+       padding-top: 1px;
+}
+h2.page-title {
+       margin-bottom: 10px;
+       margin-top: 10px;
+       margin-left: 5px;
+       border-bottom: 1px solid #f0f0f0;
+       clear: left;
+}
+
+h1 {
+       margin-bottom: 5px;
+}
+
+div#sub-navigation {
+       padding: 3px;
+       background-color: #DEE7EC;
+       border-bottom: 1px solid #9DAB9A;
+       color: #9DAB9A;
+    text-transform: lowercase;
+       font-size:0.85em;
+}
+
+div#sub-navigation strong {
+       color: black;
+}
+
+div#help {
+       border-left: 1px solid black;
+       border-right: 1px solid black;
+       border-bottom: 1px solid black;
+       padding-left: 5px;
+       padding-right: 5px;
+       padding-bottom: 5px;
+       background-color: #efefef;
+       margin-left: 5px;
+       margin-right: 5px;
+       font-size: small;
+}
+
+h3#help-title {
+       margin-left: 5px;
+       margin-right: 5px;
+       border-left: 1px solid black;
+       border-right: 1px solid black;
+       padding: 1px;
+       background-color: #efefef;
+}
+.line {
+       border-bottom: 1px solid black;
+}
+div#help p {
+       padding: 0px;
+       margin: 0px;
+}
+
+div#toctoggle {
+       float: left;
+       font-size: smaller;
+       padding-left: 10px;
+}
+
+h1#section-title {
+       float: left;
+       margin-left: 5px;
+}
+
+div#top-links {
+       position: relative;
+       padding-right: 5px;
+       line-height: 170%;
+       margin-top: 3px;
+       font-size:0.85em;;
+    text-transform: lowercase;
+}
+
+a#editor-link {
+       background-color: #EFEFEF;
+       padding-top: 1px;
+       padding-bottom: 1px;
+       padding-left: 15px;
+       padding-right: 8px;
+       border: 1px solid #cccccc;
+       font-weight: normal;
+       text-decoration: none;
+}
+
+a#editor-link:hover {
+       background-color: #fafafa;
+       border: 1px solid #aaaaaa;
+}
+
+a#editor-link.off {
+       background-image: url(images/pen.gif);
+       background-repeat: no-repeat;
+       background-position: 0px 2px;
+}
+a#editor-link.on {
+       background-image: url(images/pen2.gif);
+       background-repeat: no-repeat;
+       background-position: 0px 2px;
+}
+
+
+/* for data tables */
+table.data {
+       clear:right;
+       border: 1px solid #f0f0f0;
+       width: 80%; 
+       margin-left: auto; 
+       margin-right: auto;
+       border-spacing: 0px;
+       border-collapse: collapse;
+} 
+
+table.data th {
+       background-color: #f0f0f0;
+       padding: 3px;
+       white-space: nowrap;
+}
+
+table.data th a {
+       color: black;
+       padding-right: 15px;
+       margin-right: 15px;
+       background-image: url('../default/images/sort.gif');
+       background-repeat: no-repeat;
+       background-position: right;
+       text-decoration:none;
+}
+
+table.data tbody {
+       background-color: #fdfdfd;
+}
+
+table.data tbody th {
+       text-align: left;
+       background-color: #fdfdfd;
+       cursor: auto;
+}
+
+table.data td {
+       padding: 3px;
+}
+
+table.data tbody tr:hover {
+       background-color: #f5f5ff;
+       cursor: pointer;
+}
+
+table.data tbody tr.selected {
+       background-color: #f5f5ff;
+       cursor: auto;
+}
+
+table.data tfoot {
+       background-color: #fafafa;
+}
+
+table.data tfoot tr:first-child td {
+       padding: 5px;
+       background-image: url('images/arrow_ltr.gif');
+       background-repeat: no-repeat;
+       background-position: 4px 5px;
+       padding-left: 40px;
+}
+
+table.data.static tfoot td, table.data.static tfoot tr:first-child td {
+       padding: 5px;
+       background-image: none;
+       padding-left: 0px;
+}
+
+table.data tfoot input {
+       border: 1px solid #999;
+       background-color: white;
+       padding: 2px;
+       padding-left: 10px;
+       padding-right: 10px;
+       max-width: 60%;
+       min-width: 100px;
+       margin-left: 5px;
+}
+
+/* used for static tables with no form elements: */
+table.data.static tbody tr:hover {
+       background-color: transparent;
+       cursor: auto;
+}
+
+table.data tfoot input[type=submit]:hover {
+       background-color: #f5f5ff;
+}
+
+/* course browser: */
+
+div#browse {
+       margin-left: auto; 
+       margin-right: auto; 
+       width: 80%;
+}
+
+div.browse-selected {
+       background-image: url('images/side_arrow.gif'); 
+       background-repeat: no-repeat; 
+       padding-left: 9px; 
+       background-position: center left;
+}
+
+div.browse-unselected {
+       padding-left: 9px; 
+}
+
+ul.browse-list {
+       list-style: none;
+       padding:0px;
+}
+
+/* feedback /errors */
+div#error {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid red;
+       padding: 5px;
+       background-color: #fffcf3;
+       color: red;
+       background: #FBF4ED url(images/error-large.gif) no-repeat scroll 5px 5px;
+       padding-left: 25px;
+       font-weight: bold;
+}
+div#error h4 {
+       color: black;
+       margin-left: 0px;
+}
+
+div#error ul, div#feedback ul, div#help ul {
+       position: relative;
+       list-style: none;
+       margin-left: 0px;
+       padding-left: 0px;
+}
+
+div#feedback {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid green;
+       padding: 5px;
+       background-color: #c3fffc;
+       color: green;
+       font-weight: bold;
+}
+
+div#help {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid blue;
+       padding: 5px;
+       background-color: #c3ffff;
+       color: blue;
+}
+
+div#info {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #2905A1;
+       padding: 5px;
+       background-color: #E1D7E8;
+       color: #2905A1;
+       font-weight: bold;
+}
+
+div#warning {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #FF8400;
+       padding: 5px;
+       background-color: #FFF6ED;
+       color: #D95900;
+       font-weight: bold;
+}
+acronym {
+       cursor: help;
+}
+
+div.news p {
+       margin-left: 10px;
+}
+div.news span.date {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: #8CACBB; 
+       font-size:smaller;
+}
+
+/* home page links */
+div.home-link {
+       padding: 2px;
+       float: left;
+       text-align: center;
+       margin: 2px;
+       width: 120px;
+       height: 90px;
+}
+div.home-link:hover {
+       padding: 1px;
+       background-color: #efefef;
+       border: 1px solid #afafaf;
+       float: left;
+       text-align: center;
+       margin: 2px;
+}
+div.home-link a {
+       text-decoration: none;
+       font-weight: bold;
+}
+
+div.home-link img {
+       border: 0px;
+}
+
+/* sequence links */
+div#sequence-links {
+       float: right;
+       margin-top: 10px;
+       padding-right: 5px;
+       font-size: smaller;
+}
+div#sequence-links a {
+       text-decoration: none;
+}
+
+div.dropdown {
+       width: 200px;
+       padding: 2px;
+       background-color: white;
+       color: black;
+       border-left: 1px solid #EAF2FE;
+       border-right: 1px solid #EAF2FE;
+       border-bottom: 1px solid #EAF2FE;
+       font-weight: normal;
+}
+
+div.dropdown-heading {
+       background-color: #DFE1C7;
+       color: #006699;
+       border-left: 1px solid #EAF2FE;
+       border-right: 1px solid #EAF2FE;
+       border-top: 1px solid #EAF2FE;
+       font-weight: bold;
+       padding: 2px;
+}
+
+div.required {
+       font-weight: bold;
+       color: red;
+       font-size: large;
+       float: left;
+       position: relative;
+       margin-top: -5px;
+       height: 15px;
+       padding-right: 2px;
+}
+
+div#content_text {
+       margin-left: 5px;
+}
+
+form {
+       clear: none;
+       display:inline;
+}
+#jump-button {
+    padding-left: 9px;
+       padding-right: 2px;
+       background: White url('images/linkTransparent.gif') 3px 2px no-repeat;
+       border: 1px solid #8CACBB;
+       cursor: pointer;
+    text-transform: lowercase;
+       font-size:0.85em;
+}
+#jumpmenu {
+       font-size: smaller;
+}
+
+optgroup {
+       font-size: small;
+}
+
+/* packing */
+div.paging {
+   width: 100%;
+   text-align: center;
+   margin: 0.5em auto;
+}
+div.paging ul {
+   list-style: none;
+   display: inline;
+   padding: 0px;
+   border: 1px solid #000;
+}
+div.paging li { 
+       display: inline; 
+       padding-left: 2px; 
+       padding-right: 2px;
+       padding-top: 0px;
+       padding-bottom: 0px;
+}
+
+div.paging li a {
+       text-decoration: none;
+       padding-left: 4px;
+       padding-right: 4px;
+       border-left: 1px solid white;
+       border-right: 1px solid white;
+}
+
+div.paging li a:hover, div.paging li a.current {
+   background-color: #efefef;
+   border-left: 1px solid #000;
+   border-right: 1px solid #000;
+}
+
+/*plone*/
+
+div.top {
+    /* Top space */
+    background: transparent;
+    margin: 0;
+    padding: 0;
+       padding-top:9px;
+}
+div.tabs {
+    /* Navigational Plone Tabs(tm), implemented by customizing the a tag - they are surprisingly elegant. The power of CSS runs strong in these :) */
+    background: transparent;
+    border-collapse: collapse;
+    border-bottom: 1px solid #8CACBB;
+    padding: 0.5em 0em 0em 2em;
+    white-space: nowrap;
+       font-size:0.85em;
+}
+
+div.tabs a {
+    /* The normal, unselected tabs. They are all links */
+    background: transparent;
+    border-color: #8CACBB;
+    border-width: 1px; 
+    border-style: solid solid none solid;
+    color: #436976;
+    height: 1.2em;
+    margin-right: 0.5em;
+    padding: 0em 2em 0em;
+    text-transform: lowercase;
+}
+
+div.tabs a.selected {
+    /* The selected tab. There's only one of this */
+    background: #DEE7EC;
+    border-bottom: #DEE7EC 1px solid;
+    color: #436976;
+    font-weight: normal;
+}
+
+div.tabs a:hover, div.tabs a.active {
+    background: #DEE7EC;
+    border-bottom: 1px solid #DEE7EC;
+    color: #436976;
+}
+
+
+h4.box {
+       font-size: x-small;
+       background-color: #DEE7EC;
+       color: black;
+       border: 1px solid #8CACBB;
+       padding: 2px;
+    text-transform: lowercase;
+       font-size: 0.85em;
+}
+
+div.box {
+       padding: 2px;
+       background-color: white;
+       color: black;
+       border-left: 1px solid #8CACBB;
+       border-right: 1px solid #8CACBB;
+       border-bottom: 1px solid #8CACBB;
+       font-weight: normal;
+       font-size: 0.85em;
+}
+
+h5.box { 
+    background: #DEE7EC;
+    border: 1px solid #8CACBB;
+    border-style: solid solid none solid;
+    color: Black;
+    padding: 0em 1em 0em 1em;
+    text-transform: lowercase;
+    display: inline;
+       font-size: 0.85em;
+    height: 1em;
+}
+
+div.box a:link {
+       text-decoration: none;
+}
+
+div.box a:visited {
+       color: #51286C;
+       text-decoration: none;
+}
+
+div.box a:hover {
+       text-decoration: underline;
+}
+
+.boxDetails {
+    text-align: right;
+}
+
+div.box .content {
+    padding: 1em;
+       font-size: 0.85em;
+}
+
+div.box a.close {
+    float: right;
+    text-transform: none;
+    border-left: 1pt solid #8CACBB;
+    padding: 0em 0.2em;
+}
+
+div.box h1, 
+div.box h2, 
+div.box h3, 
+div.box h4 {
+    margin: 0;
+    padding: 0;
+}
+
+div.box .even {
+    background-color: #F7F9FA;
+}
+
+div.box .odd {
+    background-color: transparent;
+}
+
+div.box input {
+    font-size: 100%;
+}
+
+/* users/index.php */
+
+div.course {
+       position: relative;
+       width: 30em;
+       height: 10.5em;
+       border: rgb(204, 204, 204) 1px solid;
+       background-color: white;
+       float: left;
+       margin: 3px;
+       padding: 3px;
+       font-size:0.85em;
+}
+
+div.course.break {
+       clear: left;
+}
+
+div.course h2 {
+       border: 0px;
+       font-weight: normal;
+       font-size: large;
+
+}
+
+div.course:hover {
+       background-color:#D1E3ED;
+       border: #AAAAAA 1px solid;
+}
+
+div.course a {
+       text-decoration: none;
+}
+
+div.course:hover a {
+       color: #006699;
+}
+
+div.course a:hover {
+       color: #000000;
+}
+
+div.course p {
+       font-size: 0.95em;
+}
+
+div.course p a {
+       font-weight: bold;
+}
+
+div.course img.icon    {
+       float: left;
+       margin: 2px;
+       height:6.8em;
+       width:6.8em;
+}
+
+div.course div.shortcuts {
+       text-align: right;
+       clear: left;
+       vertical-align: middle;
+}
+
+fieldset#shortcuts {
+       float: right;
+       background-color: #FAFAFA;
+       border: 1pt solid #AAAAAA;
+       margin: -5pt 5pt 5pt 5pt;
+       padding-right: 10pt;
+       padding-bottom: 5pt;
+       padding-left: 10pt;
+}
+
+legend {
+       padding-right: 10pt;
+       padding-left: 10pt;
+}
+
+fieldset {
+       margin-bottom: 10pt;
+}
+#shortcuts legend {
+       color: orange;
+       background-color: white;
+}
+#shortcuts ul {
+       position: relative;
+       margin-top: 0pt;
+       margin-bottom: 0pt;
+       margin-left: 0pt;
+       list-style-type:  none;
+       padding-left: 0pt; 
+}
+
+a#guide {
+       background-image: url('../default/images/guide.gif'); background-repeat: no-repeat; background-position: 7pt 2pt;
+       background-color: #eee;
+       padding: 1pt 10pt 1pt 23pt;
+       border: 1pt solid #ccc;
+       font-size:0.85em;
+}
+
+div#content-text {
+       padding-right: 5pt;
+       line-height:150%;
+}
+
+div#content-text li {
+       margin-left: 15pt;
+}
+
+div#content-info {
+       margin: 5pt;
+       font-size: smaller;
+       color: #cacaca;
+       clear: both;
+}
+
+div#container {
+       text-align: left;
+       margin: 0px auto;
+       padding: 0px;
+       border:0;
+       width: 90%;
+}
+
+div.column {
+       border: 1px solid #e0e0e0;
+       float: left;
+       width: 30%;
+       margin: 5px;
+       padding: 0px;
+       min-width: 170px;
+}
+
+div.column h3 {
+       margin-left: 0px;
+}
+
+div.insidecol {
+   min-height: 170px;
+   height: 170px;
+   padding:5px;
+}
+div[class] .insidecol {
+   height: auto;
+}
+
+/* index page */
+ul#home-links {
+       list-style: none;
+}
+ul#home-links li {
+       font-size:0.95em;
+
+       display: inline;
+       float: left;
+       padding: 0.8em;
+       text-align: center;
+       margin: 0.1em;
+       width: 8.5em;
+       height: 7.0em;
+       padding-left:0px;
+
+}
+ul#home-links li a {
+       text-decoration: none;
+       border: 1px transparent;
+       font-weight: bold;
+}
+ul#home-links li a img {
+       border: 0px;
+       display: block;
+       padding-left:25px;
+
+}
+
+/* enrollment tabs */
+#navlist {
+       padding: 0px;
+       margin-left: 0;
+       margin-right: auto;
+       margin-left: auto;
+       margin-bottom: 4px;
+       margin-top:15px;
+       white-space: nowrap;
+}
+
+#navlist li {
+       list-style: none;
+       display: inline;
+       margin: 0px;
+}
+
+#navlist li a {
+       padding: 3px 9px;
+       border: 1px solid #e0e0e0;
+       border-bottom: none;
+       background: #fafafa;
+       text-decoration: none;
+       margin-left: 4px;
+       -moz-border-radius-topright: 4px;
+       -moz-border-radius-topleft: 4px;
+       white-space: nowrap;
+}
+
+#navlist li a:hover, #navlist li a.active {
+       color: #000;
+       background: #fff;
+}
+
+/* tree */
+.img-size-tree {
+       vertical-align: middle;
+       margin-top: 0px;
+       height:1.45em;
+       width:1.45em;
+}
+/* profile page */
+dl#public-profile {
+       width: 100%;
+}
+dl#public-profile dt {
+       float: left;
+       font-weight: bold;
+       width: 30%;
+       text-align: right;
+       clear: left;
+       border-right: 1px solid #f0f0f0;
+       padding: 5px 5px 5px 0px;
+       vertical-align: middle;
+       margin-right: 5px;
+}
+dl#public-profile dd {
+       margin-bottom: 5px;
+       clear: right;
+       padding: 5px 0px 5px 5px;
+}
+
+/* floating layout */
+#contentwrapper{
+       float: left;
+       width: 99%;
+}
+#contentcolumn {
+       margin-right: 210px;
+       padding-left: 5px;
+}
+#rightcolumn{
+       float: left;
+       width: 200px;
+       margin-left: -200px;
+       overflow: hidden;
+}
+#footer{
+       clear: left;
+       width: 100%;
+       text-align: center;
+       padding: 4px 0px;
+}
+
+/** forum stuff **/
+#forum-thread li { clear:left; border:1px solid #eee; border-bottom: 1px solid #f0f0f0; float:left; width: 98%; list-style: none; }
+#forum-thread li.even { background: #fdfdfd; border-top: none; }
+#forum-thread li.odd { background: #fff; }
+div.forum-post-author { float:left; width:150px; padding:8px 10px; }
+div.forum-post-author a.title {        font-size: 1.1em; line-height: 1.2em; font-weight: bold; text-decoration:none; }        
+div.forum-post-author img.profile-picture { border: 2px solid #f0f0f0; }
+div.forum-post-content { margin-left: 150px; padding: 5px 0px 18px 18px; }
+div.forum-post-content h3 { font-weight: 500; }
+div.forum-post-ctrl { float: right; padding-right: 5px; color: #a1a1a1; }
+div.forum-post-ctrl a { text-decoration: none; }
+div.forum-post-ctrl span { color: black; background-color: #fefdc2; padding: 3px; }
+div.forum-post-content p.date { color: #a1a1a1; border-bottom: 1px solid #f0f0f0; }
+div.forum-post-content div.body p { margin-bottom:20px; }
+
+/** inbox stuff - reuses some of the forum layout **/
+#inbox-msg li { clear:left; border:1px solid #eee; border-bottom: 1px solid #f0f0f0; width: 98%; list-style: none; }
+
+
+div#topnavlistcontainer {
+    /* Navigational Plone Tabs(tm), implemented by customizing the a tag - they are surprisingly elegant. The power of CSS runs strong in these :) */
+    background: transparent;
+    border-collapse: collapse;
+    border-bottom: 1px solid #8CACBB;
+    padding: 0.5em 0em 0em 2em;
+    white-space: nowrap;
+       font-size:0.85em;
+}
+ul#topnavlist {
+       padding: 0px;
+       margin-right: auto;
+       margin-left: auto;
+       margin-bottom: 3px;
+       white-space: nowrap;
+       margin-top: 0px;
+       margin-bottom:0px;
+}
+
+ul#topnavlist li {
+       list-style: none;
+       display: inline;
+       margin: 0px;
+}
+
+ul#topnavlist li:first-child a {
+       margin-left: 8px;
+}
+
+ul#topnavlist li a:hover, ul#topnavlist li a.active, ul#topnavlist li a:focus {
+    background: #DEE7EC;
+    border-bottom: 1px solid #DEE7EC;
+    color: #436976;
+}
+
+ul#topnavlist li a {
+    /* The normal, unselected tabs. They are all links */
+    background: transparent;
+    border-color: #8CACBB;
+    border-width: 1px; 
+    border-style: solid solid none solid;
+    color: #436976;
+    height: 1.2em;
+    margin-right: 0.5em;
+    padding: 0em 2em 0em;
+    text-transform: lowercase;
+}
+
+ul#topnavlist li a.selected {
+    /* The selected tab. There's only one of this */
+    background: #DEE7EC;
+    border-bottom: #DEE7EC 1px solid;
+    color: #436976;
+    font-weight: normal;
+}
\ No newline at end of file
diff --git a/themes/blumin/theme.cfg.php b/themes/blumin/theme.cfg.php
new file mode 100644 (file)
index 0000000..de0ad82
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+
+// $Id: theme.cfg.php 2813 2004-12-12 15:37:46Z greg $
+
+/* This is the default configuration file for the default theme. */
+
+/* The theme's name. */
+       $_theme['name'] = 'Blumin';
+
+/* The theme's version number. */
+       $_theme['version'] = '0.2';
+
+/* Which version of ATutor is this theme intended for. */
+       $_theme['atutor-version'] = '1.5.3';
+
+/* author information */
+       $_theme['author_name']  = 'ATutor';
+       $_theme['author_url']   = 'http://atutor.ca';
+       $_theme['author_email'] = '';
+
+/* theme default course banner styles: */
+       $_theme['banner']['font-family'] = 'Verdana, Arial, sans-serif';
+       $_theme['banner']['font-weight'] = 'bold';
+       $_theme['banner']['color']       = 'black';
+       $_theme['banner']['font-size']   = 'xx-large';
+       $_theme['banner']['text-align']  = 'center';
+
+       $_theme['banner']['background-color'] = 'white';
+       $_theme['banner']['background-image'] = '';
+       $_theme['banner']['vertical-align']   = 'middle';
+       $_theme['banner']['padding']          = '3px';
+
+?>
diff --git a/themes/blumin/theme_info.xml b/themes/blumin/theme_info.xml
new file mode 100644 (file)
index 0000000..1672b7d
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="EN"?>\r
+<!--This is an ATutor Theme Generator document-->\r
+<!--Created from the ATutor Themes Export Generator-->\r
+\r
+<theme>\r
+       <title>blumin</title>\r
+       <version>1.6</version>\r
+       <last_updated>2006-04-21</last_updated>\r
+       <extra_info>plone-like.</extra_info>\r
+</theme>\r
+\r
diff --git a/themes/default/confirmmessage.tmpl.php b/themes/default/confirmmessage.tmpl.php
new file mode 100644 (file)
index 0000000..17ffdcf
--- /dev/null
@@ -0,0 +1,32 @@
+<?php  
+/*
+ * @author Jacek Materna
+ *
+ *     One Savant variable: $item which is the processed ouput message content according to lang spec.
+ */
+ global $_base_href;
+// header
+?>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<?php if(isset($this->hidden_vars)): ?>
+       <?php echo $this->hidden_vars; ?>
+<?php endif; ?>
+
+<div class="input-form">
+       <div class="row">
+               <?php if (is_array($this->item)) : ?>
+                       <?php foreach($this->item as $e) : ?>
+                               <p><?php echo $e; ?></p>
+                       <?php endforeach; ?>
+               <?php endif; ?>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit_yes" value="<?php echo _AT('submit_yes'); ?>" /> 
+               <input type="submit" name="submit_no" value="<?php echo _AT('submit_no'); ?>" />
+       </div>
+</div>
+</form>
\ No newline at end of file
diff --git a/themes/default/content.tmpl.php b/themes/default/content.tmpl.php
new file mode 100644 (file)
index 0000000..89d2412
--- /dev/null
@@ -0,0 +1,31 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+if (!defined('AT_INCLUDE_PATH')) { exit; } ?>\r
+\r
+<?php if ($this->shortcuts): ?>\r
+<fieldset id="shortcuts"><legend><?php echo _AT('shortcuts'); ?></legend>\r
+       <ul>\r
+               <?php foreach ($this->shortcuts as $link): ?>\r
+                       <li><a href="<?php echo $link['url']; ?>"><?php echo $link['title']; ?></a></li>\r
+               <?php endforeach; ?>\r
+       </ul>\r
+</fieldset>\r
+<?php endif; ?>\r
+\r
+<div id="content-text">\r
+       <?php echo $this->body; ?>\r
+</div>\r
+\r
+<div id="content-info">\r
+       <?php echo $this->content_info; ?>\r
+</div>
\ No newline at end of file
diff --git a/themes/default/errormessage.tmpl.php b/themes/default/errormessage.tmpl.php
new file mode 100644 (file)
index 0000000..bea7c63
--- /dev/null
@@ -0,0 +1,21 @@
+<?php 
+/*
+ * @author Jacek Materna
+ *
+ *     One Savant variable: $item which is the processed ouput message content according to lang spec.
+ */
+ global $_base_href;
+// header
+?>
+<div id="error">
+       <h4><?php echo _AT('the_follow_errors_occurred'); ?></h4>
+       <?php if (is_array($this->item)) : ?>
+               <ul>
+               <?php foreach($this->item as $e) : ?>
+                       <li><?php echo $e; ?></li>
+               <?php endforeach; ?>
+               </ul>
+       <?php endif; ?>
+</div>
\ No newline at end of file
diff --git a/themes/default/feedbackmessage.tmpl.php b/themes/default/feedbackmessage.tmpl.php
new file mode 100644 (file)
index 0000000..a7214d0
--- /dev/null
@@ -0,0 +1,20 @@
+<?php 
+/*
+ * @author Jacek Materna
+ *
+ *     One Savant variable: $item which is the processed ouput message content according to lang spec.
+ */
+ global $_base_href;
+// header
+?>
+<div id="feedback">
+       <?php if (is_array($this->item)) : ?>
+               <ul>
+               <?php foreach($this->item as $e) : ?>
+                       <li><?php echo $e; ?></li>
+               <?php endforeach; ?>
+               </ul>
+       <?php endif; ?>
+</div>
\ No newline at end of file
diff --git a/themes/default/forms.css b/themes/default/forms.css
new file mode 100644 (file)
index 0000000..272fb48
--- /dev/null
@@ -0,0 +1,71 @@
+div.input-form {
+       width: 90%; 
+       margin-left:auto; 
+       margin-right:auto;
+       border: thin #CCCCCC solid;
+       margin-bottom: 20px;
+       line-height:150%;
+       background-color: #F8F8F8;
+
+}
+
+div.input-form div.row h3 {
+       margin-left: 0px;
+}
+
+div.input-form div.row {
+       background-color: #F8F8F8;
+       padding:8px;
+}
+
+div.input-form .footer {
+       border-top: 1px solid #F9F6F2;
+}
+
+div.input-form p {
+       margin-left: 0px;
+}
+
+div.input-form input {
+       z-index: 2;
+}
+div.input-form textarea {
+       border: 1px solid #595241;
+       width: 98%;
+       padding: 2px;
+       margin-right: 2px;
+}
+div.input-form input[type=text], div.input-form input[type=password] {
+       border: 1px solid #595241;
+       padding: 2px;
+       max-width: 60%;
+       background-color:white;
+}
+
+div.input-form textarea:focus, div.input-form  input[type=password]:focus, div.input-form  input[type=text]:focus{
+       border:1px solid #A50707;
+       background-color: #FFDAB9;
+       padding: 2px;
+}
+
+input[type=checkbox]{
+
+       background-color: #FFDAB9;
+}
+
+div.input-form div.buttons {
+       text-align: right;
+       padding:8px;
+}
+div.input-form div.buttons input {
+       background-color: #efefef;
+       font-weight: normal;
+       border:  #AAA  solid 1px;
+}
+.formfield:focus{
+       background-color: #FFDAB9;
+}
+
+#ot:focus{
+       background-color: #FFDAB9;
+}
diff --git a/themes/default/ie_styles.css b/themes/default/ie_styles.css
new file mode 100644 (file)
index 0000000..e284b40
--- /dev/null
@@ -0,0 +1,36 @@
+/* IE specific styles */
+
+ul#topnavlist {
+       zoom:100%;
+       margin:0px;
+}
+
+ul#topnavlist li {
+       zoom:100%;
+       padding:0.3em;
+       padding-bottom:0.3em;
+       margin:0px;
+       margin-bottom:-3px;
+}
+
+label {
+       zoom:100%;
+       margin:0px;
+}
+
+table.data tfoot input {
+       min-width:0px;
+}
+
+#topnavlistcontainer {
+       margin-bottom:-1px;
+}
+
+#header{
+       height: 7.2em;
+}
+
+div#top-links a:active{
+       color:black;
+       background-color:#F6EAD6;
+}
\ No newline at end of file
diff --git a/themes/default/images/Thumbs.db b/themes/default/images/Thumbs.db
new file mode 100644 (file)
index 0000000..2ffc443
Binary files /dev/null and b/themes/default/images/Thumbs.db differ
diff --git a/themes/default/images/arrow_ltr.gif b/themes/default/images/arrow_ltr.gif
new file mode 100644 (file)
index 0000000..651857e
Binary files /dev/null and b/themes/default/images/arrow_ltr.gif differ
diff --git a/themes/default/images/back.gif b/themes/default/images/back.gif
new file mode 100644 (file)
index 0000000..274d5c5
Binary files /dev/null and b/themes/default/images/back.gif differ
diff --git a/themes/default/images/continue.gif b/themes/default/images/continue.gif
new file mode 100644 (file)
index 0000000..3a3badb
Binary files /dev/null and b/themes/default/images/continue.gif differ
diff --git a/themes/default/images/guide.gif b/themes/default/images/guide.gif
new file mode 100644 (file)
index 0000000..124c24a
Binary files /dev/null and b/themes/default/images/guide.gif differ
diff --git a/themes/default/images/linkOpaque.gif b/themes/default/images/linkOpaque.gif
new file mode 100644 (file)
index 0000000..235b32a
Binary files /dev/null and b/themes/default/images/linkOpaque.gif differ
diff --git a/themes/default/images/linkTransparent.gif b/themes/default/images/linkTransparent.gif
new file mode 100644 (file)
index 0000000..ff0276d
Binary files /dev/null and b/themes/default/images/linkTransparent.gif differ
diff --git a/themes/default/images/newsitem_icon.gif b/themes/default/images/newsitem_icon.gif
new file mode 100644 (file)
index 0000000..8f4957b
Binary files /dev/null and b/themes/default/images/newsitem_icon.gif differ
diff --git a/themes/default/images/next.gif b/themes/default/images/next.gif
new file mode 100644 (file)
index 0000000..b756085
Binary files /dev/null and b/themes/default/images/next.gif differ
diff --git a/themes/default/images/pencil_bottom.gif b/themes/default/images/pencil_bottom.gif
new file mode 100644 (file)
index 0000000..e66c532
Binary files /dev/null and b/themes/default/images/pencil_bottom.gif differ
diff --git a/themes/default/images/pencil_top.gif b/themes/default/images/pencil_top.gif
new file mode 100644 (file)
index 0000000..780813f
Binary files /dev/null and b/themes/default/images/pencil_top.gif differ
diff --git a/themes/default/images/pencils.gif b/themes/default/images/pencils.gif
new file mode 100644 (file)
index 0000000..819a038
Binary files /dev/null and b/themes/default/images/pencils.gif differ
diff --git a/themes/default/images/previous.gif b/themes/default/images/previous.gif
new file mode 100644 (file)
index 0000000..7391bfd
Binary files /dev/null and b/themes/default/images/previous.gif differ
diff --git a/themes/default/images/resume.gif b/themes/default/images/resume.gif
new file mode 100644 (file)
index 0000000..1a16515
Binary files /dev/null and b/themes/default/images/resume.gif differ
diff --git a/themes/default/images/side_arrow.gif b/themes/default/images/side_arrow.gif
new file mode 100644 (file)
index 0000000..a089413
Binary files /dev/null and b/themes/default/images/side_arrow.gif differ
diff --git a/themes/default/images/sort.gif b/themes/default/images/sort.gif
new file mode 100644 (file)
index 0000000..39311ec
Binary files /dev/null and b/themes/default/images/sort.gif differ
diff --git a/themes/default/images/tl_corner.gif b/themes/default/images/tl_corner.gif
new file mode 100644 (file)
index 0000000..f387191
Binary files /dev/null and b/themes/default/images/tl_corner.gif differ
diff --git a/themes/default/images/top.gif b/themes/default/images/top.gif
new file mode 100644 (file)
index 0000000..5e61588
Binary files /dev/null and b/themes/default/images/top.gif differ
diff --git a/themes/default/images/user-star.gif b/themes/default/images/user-star.gif
new file mode 100644 (file)
index 0000000..eae5efa
Binary files /dev/null and b/themes/default/images/user-star.gif differ
diff --git a/themes/default/images/user.gif b/themes/default/images/user.gif
new file mode 100644 (file)
index 0000000..e95818f
Binary files /dev/null and b/themes/default/images/user.gif differ
diff --git a/themes/default/include/box.tmpl.php b/themes/default/include/box.tmpl.php
new file mode 100644 (file)
index 0000000..b9e34b5
--- /dev/null
@@ -0,0 +1,7 @@
+<?php if (!defined('AT_INCLUDE_PATH')) { exit; } ?>
+
+<br />
+<h2 class="sidebox"><?php echo $this->title; ?></h2>
+<div class="box">
+               <?php echo $this->dropdown_contents; ?>
+</div>
\ No newline at end of file
diff --git a/themes/default/include/fm_footer.tmpl.php b/themes/default/include/fm_footer.tmpl.php
new file mode 100644 (file)
index 0000000..d733a1f
--- /dev/null
@@ -0,0 +1,2 @@
+</body>\r
+</html>
\ No newline at end of file
diff --git a/themes/default/include/fm_header.tmpl.php b/themes/default/include/fm_header.tmpl.php
new file mode 100644 (file)
index 0000000..2ccd760
--- /dev/null
@@ -0,0 +1,41 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+/* available header.tmpl.php variables:\r
+ *\r
+ * ======================================\r
+ * top_level_pages           array(array('url', 'title'))     the top level pages. ATutor default creates tabs.\r
+ * section_title             string                           the name of the current section. either name of the course, administration, my start page, etc.\r
+ * page_title                string                           the title of the current page.\r
+ * path                      array(array('url', 'title'))     the path to the current page.\r
+ * back_to_page              array('url', 'title')            the link back to the part of the current page, if needed.\r
+ * current_top_level_page    string                           full url to the current top level page in "top_leve_pages"\r
+ * current_sub_level_page    string                           full url to the current sub level page in the "sub_level_pages"\r
+ * sub_level_pages           array(array('url', 'title'))     the sub level pages.\r
+ */\r
+\r
+// will have to be moved to the header.inc.php\r
+global $system_courses;\r
+\r
+?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r
+<html lang="<?php echo $this->lang_code; ?>">\r
+<head>\r
+       <title><?php echo SITE_NAME; ?> : <?php echo $this->page_title; ?></title>\r
+       <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $this->lang_charset; ?>" />\r
+       <meta name="Generator" content="ATutor - Copyright 2005 by http://atutor.ca" />\r
+       <base href="<?php echo $this->content_base_href; ?>" />\r
+       <link rel="shortcut icon" href="<?php echo $this->base_path; ?>favicon.ico" type="image/x-icon" />\r
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/print.css" type="text/css" media="print" />\r
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/styles.css" type="text/css" />\r
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/forms.css" type="text/css" />\r
+       <?php echo $this->rtl_css; ?>\r
+       <style type="text/css"><?php echo $this->banner_style; ?></style>\r
+       <?php if ($system_courses[$_SESSION['course_id']]['rss']): ?>\r
+       <link rel="alternate" type="application/rss+xml" title="<?php echo SITE_NAME; ?> - RSS 2.0" href="<?php echo $this->base_href; ?>get_rss.php?<?php echo $_SESSION['course_id']; ?>-2" />\r
+       <link rel="alternate" type="application/rss+xml" title="<?php echo SITE_NAME; ?> - RSS 1.0" href="<?php echo $this->base_href; ?>get_rss.php?<?php echo $_SESSION['course_id']; ?>-1" />\r
+       <?php endif; ?>\r
+</head>\r
+<body onload="<?php echo $this->onload; ?>"><div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>\r
+<br /><div align="right"><a href="javascript:window.close()"><?php echo _AT('close_file_manager'); ?></a></div>\r
+<a name="content"></a>\r
+<?php global $msg; $msg->printAll(); ?>
\ No newline at end of file
diff --git a/themes/default/include/footer.tmpl.php b/themes/default/include/footer.tmpl.php
new file mode 100644 (file)
index 0000000..d5c3995
--- /dev/null
@@ -0,0 +1,28 @@
+<?php if (!defined('AT_INCLUDE_PATH')) { exit; } ?>
+
+               <?php if ($_SESSION['course_id'] > 0): ?>
+                       <div style="clear: left; text-align:right;" id="gototop">               
+                               <br />
+                               <span style="font-size:smaller;padding-right:3px;"><a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#content" title="<?php echo _AT('goto_content'); ?> Alt-c" ><?php echo _AT('goto_top'); ?>
+                               <img src="<?php echo $this->base_path; ?>themes/default/images/top.gif" alt="<?php echo _AT('goto_top'); ?> Alt-c" border="0"/> 
+                               
+                               </a>    </span>
+                       </div>  
+               <?php endif; ?> 
+
+       </div>
+</div>
+
+<div id="footer">
+       <br /><br />
+       <?php require(AT_INCLUDE_PATH.'html/languages.inc.php'); ?>
+       <?php require(AT_INCLUDE_PATH.'html/copyright.inc.php'); ?>
+</div>
+
+
+<?php
+debug($_rel_url,"get");
+
+?>
+</body>
+</html>
\ No newline at end of file
diff --git a/themes/default/include/forms.css b/themes/default/include/forms.css
new file mode 100644 (file)
index 0000000..b3a57b4
--- /dev/null
@@ -0,0 +1,75 @@
+div.input-form {
+       width: 80%; 
+       max-width: 600px;
+       margin-left:auto; 
+       margin-right:auto;
+       border: 1px solid #F9F6F2;
+       margin-bottom: 20px;
+}
+
+div.input-form div.row h3 {
+       margin-left: 0px;
+}
+
+
+div.input-form div.row {
+       background-color: #F9F6F2;
+       padding:8px;
+}
+
+div.input-form .footer {
+       border-top: 1px solid #F9F6F2;
+}
+
+div.input-form p {
+       margin-left: 0px;
+}
+
+div.input-form input {
+       z-index: 2;
+}
+div.input-form textarea {
+       border: 1px solid #595241;
+       width: 98%;
+       background-color: #EFE7DA;
+       padding: 2px;
+       margin-right: 2px;
+}
+
+div.input-form textarea:focus {
+       border:1px solid #A50707;
+       background-color: white;
+       padding: 2px;
+}
+
+div.input-form input[type=text], div.input-form input[type=password] {
+       border: 1px solid #595241;
+       background-color: #EFE7DA;
+       padding: 2px;
+       max-width: 60%;
+}
+
+div.input-form input:focus {
+       border: 1px solid #A50707;
+       background-color: white;
+       padding: 2px
+}
+
+div.input-form div.buttons {
+       text-align: left;
+       padding:8px;
+}
+div.input-form div.buttons input {
+       border: 1px solid #5B8E88;
+       background-color: #E9F4F3;
+       padding: 2px;
+       padding-left: 10px;
+       padding-right: 10px;
+       min-width: 100px;
+       margin-left: 5px;
+}
+div.input-form div.buttons input:hover {
+       background-color: #5B8E88;
+       border: 1px solid #5B8E88;
+       color: white;
+}
\ No newline at end of file
diff --git a/themes/default/include/header.tmpl.php b/themes/default/include/header.tmpl.php
new file mode 100644 (file)
index 0000000..ba38147
--- /dev/null
@@ -0,0 +1,385 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: header.tmpl.php 3825 2005-03-11 15:35:51 joel $
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+/* available header.tmpl.php variables:
+ * $this->lang_code                    the ISO language code
+ * SITE_NAME                           the site name from the config file
+ * $this->page_title           the name of this page to use in the <title>
+ * $this->lang_charset         the ISO language character set
+ * $this->content_base_href    the <base href> to use for this page
+ * $this->base_path                    the absolute path to this atutor installation
+ * $this->rtl_css                      if set, the path to the RTL style sheet
+ * $this->icon                 the path to a course icon
+ * $this->banner_style         -deprecated-
+ * $this->theme                                the directory name of the current theme
+ * $this->base_href                    the full url to this atutor installation
+ * $this->onload                       javascript onload() calls
+ * $this->img                          the absolute path to this theme's images/ directory
+ * $this->sequence_links       associative array of 'previous', 'next', and/or 'resume' links
+ * $this->path                         associative array of path to this page: aka bread crumbs
+ * $this->rel_url                      the relative url from the installation root to this page
+ * $this->nav_courses          associative array of this user's enrolled courses
+ * $this->section_title                the title of this section (course, public, admin, my start page)
+ * $this->top_level_pages      associative array of the top level navigation
+ * $this->current_top_level_page       the full path to the current top level page with file name
+ * $this->sub_level_pages                      associate array of sub level navigation
+ * $this->back_to_page                         if set, the path and file name to the part of this page (if parent is not a top level nav)
+ * $this->current_sub_level_page       the full path to the current sub level page with file name
+ * $this->guide                                the full path and file name to the guide page
+ * ======================================
+ * top_level_pages           array(array('url', 'title'))     the top level pages. ATutor default creates tabs.
+ * section_title             string                           the name of the current section. either name of the course, administration, my start page, etc.
+ * page_title                string                           the title of the current page.
+ * path                      array(array('url', 'title'))     the path to the current page.
+ * back_to_page              array('url', 'title')            the link back to the part of the current page, if needed.
+ * current_top_level_page    string                           full url to the current top level page in "top_leve_pages"
+ * current_sub_level_page    string                           full url to the current sub level page in the "sub_level_pages"
+ * sub_level_pages           array(array('url', 'title'))     the sub level pages.
+ */
+
+// will have to be moved to the header.inc.php
+global $system_courses, $_custom_css,$db;
+
+?><!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="<?php echo $this->lang_code; ?>"> 
+
+<head>
+       <title><?php echo SITE_NAME; ?> : <?php echo $this->page_title; ?></title>
+       <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $this->lang_charset; ?>" />
+       <meta name="Generator" content="ATutor - Copyright 2005 by http://atutor.ca" />
+       <base href="<?php echo $this->content_base_href; ?>" />
+       <link rel="shortcut icon" href="<?php echo $this->base_path; ?>favicon.ico" type="image/x-icon" />
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/print.css" type="text/css" media="print" />
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/styles.css" type="text/css" />
+        <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/qstats_bar.css" type="text/css" />
+       <!--[if IE]>
+         <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/ie_styles.css" type="text/css" />
+       <![endif]-->
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/forms.css" type="text/css" />
+       <?php echo $this->rtl_css; ?>
+       <?php if ($system_courses[$_SESSION['course_id']]['rss']): ?>
+       <link rel="alternate" type="application/rss+xml" title="<?php echo SITE_NAME; ?> - RSS 2.0" href="<?php echo $this->base_href; ?>get_rss.php?<?php echo $_SESSION['course_id']; ?>-2" />
+       <link rel="alternate" type="application/rss+xml" title="<?php echo SITE_NAME; ?> - RSS 1.0" href="<?php echo $this->base_href; ?>get_rss.php?<?php echo $_SESSION['course_id']; ?>-1" />
+       <?php endif; ?>
+       <?php echo $this->custom_css; ?>
+
+</head>
+<body onload="<?php echo $this->onload; ?>"><div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>
+
+<script language="JavaScript" src="<?php echo $this->base_path; ?>overlib.js" type="text/javascript"></script>
+<script language="javascript" type="text/javascript">
+//<!--
+var newwindow;
+function poptastic(url) {
+       newwindow=window.open(url,'popup','height=600,width=600,scrollbars=yes,resizable=yes');
+       if (window.focus) {newwindow.focus()}
+}
+
+function getexpirydate(nodays){
+       var UTCstring;
+       Today = new Date();
+       nomilli=Date.parse(Today);
+       Today.setTime(nomilli+nodays*24*60*60*1000);
+       UTCstring = Today.toUTCString();
+       return UTCstring;
+}
+
+function setcookie(name,value,duration){
+       cookiestring=name+"="+escape(value)+";path=/;expires="+getexpirydate(duration);
+       document.cookie=cookiestring;
+       if(!getcookie(name)){
+               return false;
+       } else {
+               return true;
+       }
+}
+
+function getcookie(cookiename) {
+       var cookiestring=""+document.cookie;
+       var index1=cookiestring.indexOf(cookiename);
+       if (index1==-1 || cookiename=="") return ""; 
+       var index2=cookiestring.indexOf(';',index1);
+       if (index2==-1) index2=cookiestring.length; 
+       return unescape(cookiestring.substring(index1+cookiename.length+1,index2));
+}
+
+function setDisplay(objId) {
+       var toc = document.getElementById(objId);
+
+       var state = getcookie(objId);
+       if (document.getElementById(objId) && state && (state == 'none')) {
+               toggleToc(objId);
+       }
+}
+
+
+function setstates() {
+       return;
+       var objId = "side-menu";
+       var state = getcookie(objId);
+       if (document.getElementById(objId) && state && (state == 'none')) {
+               toggleToc(objId);
+       }
+
+       var objId = "toccontent";
+       var state = getcookie(objId);
+       if (document.getElementById(objId) && state && (state == 'none')) {
+               toggleToc(objId);
+       }
+
+}
+
+function showTocToggle(objId, show, hide, key, selected) {
+       if(document.getElementById) {
+               if (key) {
+                       var accesskey = " accesskey='" + key + "' title='"+ show + "/" + hide + " Alt - "+ key +"'";
+               } else {
+                       var accesskey = "";
+               }
+
+               if (selected == 'hide') {
+                       document.writeln('<a href="javascript:toggleToc(\'' + objId + '\')" ' + accesskey + '>' +
+                       '<span id="' + objId + 'showlink" style="display:none;">' + show + '</span>' +
+                       '<span id="' + objId + 'hidelink">' + hide + '</span>'  + '</a>');
+               } else {
+                       document.writeln('<a href="javascript:toggleToc(\'' + objId + '\')" ' + accesskey + '>' +
+                       '<span id="' + objId + 'showlink">' + show + '</span>' +
+                       '<span id="' + objId + 'hidelink" style="display:none;">' + hide + '</span>'    + '</a>');
+               }
+       }
+}
+
+function toggleToc(objId) {
+       var toc = document.getElementById(objId);
+       if (toc == null) {
+               return;
+       }
+       var showlink=document.getElementById(objId + 'showlink');
+       var hidelink=document.getElementById(objId + 'hidelink');
+       if (hidelink.style.display == 'none') {
+               document.getElementById('contentcolumn').id="contentcolumn_shiftright";
+               toc.style.display = '';
+               hidelink.style.display='';
+               showlink.style.display='none';
+       } else {
+               document.getElementById('contentcolumn_shiftright').id="contentcolumn";
+               toc.style.display = 'none';
+               hidelink.style.display='none';
+               showlink.style.display='';
+       }
+       setcookie(objId, toc.style.display, 1);
+}
+//-->
+</script>
+
+<div id="header">
+       <a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#content" accesskey="c">
+       <img src="<?php echo $this->base_path; ?>images/clr.gif" height="1" width="1" border="0" alt="<?php echo _AT('goto_content'); ?> ALT+c" /></a>          
+
+       <a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#menu"  accesskey="m"><img src="<?php echo $this->base_path; ?>images/clr.gif" height="1" width="1" border="0" alt="<?php echo _AT('goto_menu'); ?> ALT+m" /></a>
+       <div id="top-links"> <!-- top help/search/login links -->
+               <?php if (isset($_SESSION['member_id']) && $_SESSION['member_id']): ?>
+                       <!-- start the jump menu -->
+                       <?php if (empty($_GET)): ?>
+                               <form method="post" action="<?php echo $this->base_path; ?>bounce.php?p=<?php echo urlencode($this->rel_url); ?>" target="_top">
+                       <?php else: ?>
+                               <form method="post" action="<?php echo $this->base_path; ?>bounce.php" target="_top">
+                       <?php endif; ?>
+                       <label for="jumpmenu" accesskey="j"></label>
+                               <select name="course" id="jumpmenu" title="<?php echo _AT('jump'); ?>:  Alt-j">                                                 
+                                       <option value="0"><?php echo _AT('my_start_page'); ?></option>
+                                       <optgroup label="<?php echo _AT('courses_below'); ?>">
+                                               <?php foreach ($this->nav_courses as $this_course_id => $this_course_title): ?>
+                                                       <option value="<?php echo $this_course_id; ?>"><?php echo $this_course_title; ?></option>
+                                               <?php endforeach; ?>
+                                       </optgroup>
+                               </select> <input type="submit" name="jump" value="<?php echo _AT('jump'); ?>" class="button" /> </form>
+                       <!-- /end the jump menu -->
+                       <?php if ($_SESSION['is_super_admin']): ?>
+                               <a href="<?php echo $this->base_path; ?>bounce.php?admin"><?php echo _AT('return_to_admin_area'); ?></a> | 
+                       <?php endif; ?>
+
+                       <?php if ($_SESSION['course_id'] > -1): ?>
+                               <?php if (get_num_new_messages()): ?>
+                                       <a href="<?php echo $this->base_path; ?>inbox/index.php"><?php echo _AT('inbox'); ?> (<?php echo get_num_new_messages(); ?>)</a> 
+                               <?php else: ?>
+                                       <a href="<?php echo $this->base_path; ?>inbox/index.php"><?php echo _AT('inbox'); ?></a>
+                               <?php endif; ?>
+                       <?php endif; ?>
+               <?php endif; ?>
+               <a href="<?php echo $this->base_path; ?>search.php"><?php echo _AT('search'); ?></a> <a href="<?php echo $this->base_path; ?>help/index.php"><?php echo _AT('help'); ?></a>
+       </div>
+       <?php if (!empty($this->icon)) { // if a course icon is available, display it here.  ?>
+               <a href="<?php echo $this->base_path; ?>index.php"><img src="<?php echo $this->icon; ?>" class="headicon" alt="<?php echo  _AT('home'); ?>" /></a>      
+       <?php } ?>
+
+
+
+       <?php
+       // If there is a custom course banner in the file manager called banner.html, display it here
+       @readfile(AT_CONTENT_DIR . $_SESSION['course_id'].'/banner.txt'); 
+
+       /*
+       and example banner.html file might look like:
+       <div style="width: 760px; height: 42px; background: white;"><img src="http://[mysite]/atutor15rc3/banners/kart-camb.jpg"></div>
+       */
+
+       ?>
+       <!-- section title -->
+       <?php if ($_SESSION['valid_user']): 
+               echo '<div style="font-size:small;font-weight:bold;padding-left:1em;color:white;">'.stripslashes(SITE_NAME).'</div>'; 
+       else:
+               echo '<br />';  
+       endif; ?>
+       <h1 id="section-title"><?php echo $this->section_title; ?>
+               <?php if (($_SESSION['course_id'] > 0) && ($_SESSION['enroll'] == AT_ENROLL_NO)) : ?> 
+                       - <small><a href="<?php echo $this->base_path; ?>enroll.php?course=<?php echo $_SESSION['course_id']; ?>"><?php echo _AT('enroll_me'); ?></a></small>
+               <?php endif; ?>
+       </h1>
+
+
+</div>
+
+<div id="topnavlistcontainer">
+<!-- the main navigation. in our case, tabs -->
+       <ul id="topnavlist">
+               <?php foreach ($this->top_level_pages as $page): ?>
+                       <?php ++$accesscounter; $accesscounter = ($accesscounter == 10 ? 0 : $accesscounter); ?>
+                       <?php $accesskey_text = ($accesscounter < 10 ? 'accesskey="'.$accesscounter.'"' : ''); ?>
+                       <?php $accesskey_title = ($accesscounter < 10 ? ' Alt+'.$accesscounter : ''); ?>
+                       <?php if ($page['url'] == $this->current_top_level_page): ?>
+                               <li><a href="<?php echo $page['url']; ?>" <?php echo $accesskey_text; ?> title="<?php echo $page['title'] . $accesskey_title; ?>" class="active"><?php echo $page['title']; ?></a></li>
+                       <?php else: ?>
+                               <li><a href="<?php echo $page['url']; ?>" <?php echo $accesskey_text; ?> title="<?php echo $page['title'] . $accesskey_title; ?>"><?php echo $page['title']; ?></a></li>
+                       <?php endif; ?>
+                       <?php $accesscounter = ($accesscounter == 0 ? 11 : $accesscounter); ?>
+               <?php endforeach; ?>
+       </ul>
+</div>
+
+<div style="background-color:#E6E6E6; font-size:0.85em; padding-top: 5px; border-bottom:1px solid black; height:2em;">
+       <!-- the sub navigation -->
+       <div style="float: right; padding-right: 5px; text-transform: lowercase;">
+               <?php if ($_SESSION['valid_user']): ?>                                  
+                       <strong><?php echo get_display_name($_SESSION['member_id']); ?></strong> | <a href="<?php echo $this->base_path; ?>logout.php"><?php echo _AT('logout'); ?></a>
+               <?php else: ?>
+                        <a href="<?php echo $this->base_path; ?>login.php?course=<?php echo $_SESSION['course_id']; ?>"><?php echo _AT('login'); ?></a> | <a href="<?php echo $this->base_path; ?>registration.php"><?php echo _AT('register'); ?></a>
+               <?php endif; ?>
+       </div>
+
+       <?php if ($this->sub_level_pages): ?>
+               <div id="sub-navigation">
+                       <?php if (isset($this->back_to_page)): ?>
+                               <a href="<?php echo $this->back_to_page['url']; ?>" id="back-to"><?php echo _AT('back_to').' '.$this->back_to_page['title']; ?></a> | 
+                       <?php endif; ?>
+
+                       <?php $num_pages = count($this->sub_level_pages); ?>
+                       <?php for ($i=0; $i<$num_pages; $i++): ?>
+                               <?php if ($this->sub_level_pages[$i]['url'] == $this->current_sub_level_page): ?>
+                                       <strong><?php echo $this->sub_level_pages[$i]['title']; ?></strong>
+                               <?php else: ?>
+                                       <a href="<?php echo $this->sub_level_pages[$i]['url']; ?>"><?php echo $this->sub_level_pages[$i]['title']; ?></a>
+                               <?php endif; ?>
+                               <?php if ($i < $num_pages-1): ?>
+                                       |
+                               <?php endif; ?>
+                       <?php endfor; ?>
+               </div>
+       <?php else: ?>
+               <div id="sub-navigation">
+                       &nbsp;
+               </div>
+       <?php endif; ?>
+</div>
+
+<div style="padding:3px;">
+       <!-- the bread crumbs -->
+       <div id="breadcrumbs">
+               <?php foreach ($this->path as $page): ?>
+                       <a href="<?php echo $page['url']; ?>"><?php echo $page['title']; ?></a> > 
+               <?php endforeach; ?> <?php echo $this->page_title; ?>
+       </div>
+       <?php if ($this->guide): ?>
+               <a href="<?php echo $this->guide; ?>" id="guide" onclick="poptastic('<?php echo $this->guide; ?>'); return false;" target="_new"><em><?php echo $this->page_title; ?></em></a>
+       <?php endif; ?>
+</div>
+
+<div id="contentwrapper">
+       <?php if (($_SESSION['course_id'] > 0) && $system_courses[$_SESSION['course_id']]['side_menu']): ?>
+               <div id="leftcolumn">
+                       <script type="text/javascript">
+                       //<![CDATA[
+                       var state = getcookie("side-menu");
+                       if (state && (state == 'none')) {
+                               document.writeln('<a name="menu"></a><div style="display:none;" id="side-menu">');
+                       } else {
+                               document.writeln('<a name="menu"></a><div style="" id="side-menu">');
+                       }
+                       //]]>
+                       </script>
+
+                       <?php require(AT_INCLUDE_PATH.'side_menu.inc.php'); ?>
+
+                       <script type="text/javascript">
+                       //<![CDATA[
+                               document.writeln('</div>');
+                       //]]>
+                       </script>
+               </div>
+       <?php endif; ?>
+
+       <div id="contentcolumn"
+               <?php if (($_SESSION['course_id'] <= 0) && !$this->side_menu): ?>
+                       style="margin-left:0.5em;width:99%;"
+               <?php endif; ?>
+               >
+
+               <?php if ($_SESSION['course_id'] > 0): ?>
+               <div id="menutoggle">
+
+                       <?php if ($_SESSION['course_id'] > 0 && $system_courses[$_SESSION['course_id']]['side_menu']): ?>
+                               <script type="text/javascript" language="javascript">
+                               //<![CDATA[
+                               var state = getcookie("side-menu");
+                               if (state && (state == 'none')) {
+                                       showTocToggle("side-menu", "<?php echo _AT('show'); ?>","<?php echo _AT('hide'); ?>", "", "show");
+                               } else {
+                                       document.getElementById('contentcolumn').id="contentcolumn_shiftright";
+                                       showTocToggle("side-menu", "<?php echo _AT('show'); ?>","<?php echo _AT('hide'); ?>", "", "hide");
+                               }
+                               //]]>
+                               </script>
+                       <?php endif; ?>
+               </div>
+               <div id="sequence-links">
+                       <?php if ($this->sequence_links['resume']): ?>
+                                       <a style="color:white;" href="<?php echo $this->sequence_links['resume']['url']; ?>" accesskey="."><img src="<?php echo $this->img; ?>resume.gif" border="0" title="<?php echo _AT('resume').': '.$this->sequence_links['resume']['title']; ?> Alt+." alt="<?php echo $this->sequence_links['resume']['title']; ?> Alt+." class="img-size-ascdesc" /></a>
+                       <?php else:
+                               if ($this->sequence_links['previous']): ?>
+                                       <a href="<?php echo $this->sequence_links['previous']['url']; ?>" title="<?php echo _AT('previous_topic').': '. $this->sequence_links['previous']['title']; ?> Alt+," accesskey=","><img src="<?php echo $this->img; ?>previous.gif" border="0" alt="<?php echo _AT('previous_topic').': '. $this->sequence_links['previous']['title']; ?> Alt+," class="img-size-ascdesc" /></a>
+                               <?php endif;
+                               if ($this->sequence_links['next']): ?>
+                                       <a href="<?php echo $this->sequence_links['next']['url']; ?>" title="<?php echo _AT('next_topic').': '.$this->sequence_links['next']['title']; ?> Alt+." accesskey="."><img src="<?php echo $this->img; ?>next.gif" border="0" alt="<?php echo _AT('next_topic').': '.$this->sequence_links['next']['title']; ?> Alt+." class="img-size-ascdesc" /></a>
+                               <?php endif; ?>
+                       <?php endif; ?>
+                       &nbsp;
+               </div>
+               <?php endif; ?>
+
+       <!-- the page title -->
+       <h2 class="page-title"><?php echo $this->page_title; ?></h2>
+
+       <a name="content"></a>
+       <?php global $msg; $msg->printAll(); ?>
\ No newline at end of file
diff --git a/themes/default/include/side_menu.tmpl.php b/themes/default/include/side_menu.tmpl.php
new file mode 100644 (file)
index 0000000..48f1cf9
--- /dev/null
@@ -0,0 +1,8 @@
+<?php if (!defined('AT_INCLUDE_PATH')) { exit; } ?>
+
+<?php if (($_SESSION['course_id'] > 0) && $this->side_menu): ?>
+       <?php foreach ($this->side_menu as $dropdown_file): ?>
+               <?php if (file_exists($dropdown_file)) { require($dropdown_file); } ?>
+       <?php endforeach; ?>
+<div style="position:absolute; bottom:0px;">&nbsp;</div>
+<?php endif; ?>
diff --git a/themes/default/index.tmpl.php b/themes/default/index.tmpl.php
new file mode 100644 (file)
index 0000000..448277b
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+if (!defined('AT_INCLUDE_PATH')) { exit; } ?>
+
+<?php if ($this->banner): ?><?php echo $this->banner; ?><?php endif; ?>
+
+<div style="width: 100%; margin-top: -5px; float:left;">
+       <ul id="home-links">
+       <?php foreach ($this->home_links as $link): ?>
+               <li><a href="<?php echo $link['url']; ?>"><img src="<?php echo $link['img']; ?>" alt="" class="img-size-home" border="0" /><?php echo $link['title']; ?></a></li>
+       <?php endforeach; ?>
+       </ul>
+</div>
+
+<?php if ($this->announcements): ?>
+<h2 class="page-title"><?php echo _AT('announcements'); ?></h2>
+       <?php foreach ($this->announcements as $item): ?>
+               <div class="news">
+                       <h3><?php echo $item['title']; ?></h3>
+                       <p><span class="date"><?php echo $item['date'] . ' by ' . $item['author']; ?></span> &nbsp; <?php echo $item['body']; ?></p>
+               </div>
+       <?php endforeach; ?>
+
+       <?php if ($this->num_pages > 1): ?>
+               <?php echo _AT('page'); ?>: | 
+               <?php for ($i=1; $i<=$this->num_pages; $i++): ?>
+                       <?php if ($i == $this->current_page): ?>
+                               <strong><?php echo $i; ?></strong>
+                       <?php else: ?>
+                               <a href="<?php echo $_SERVER['PHP_SELF']; ?>?p=<?php echo $i; ?>"><?php echo $i; ?></a>
+                       <?php endif; ?>
+                        | 
+               <?php endfor; ?>
+       <?php endif; ?>
+<?php endif; ?>
diff --git a/themes/default/infomessage.tmpl.php b/themes/default/infomessage.tmpl.php
new file mode 100644 (file)
index 0000000..cea188b
--- /dev/null
@@ -0,0 +1,18 @@
+<?php  
+/*
+ * @author Jacek Materna
+ *
+ *     One Savant variable: $item which is the processed ouput message content according to lang spec.
+ */
+global $_base_href; ?>
+
+<div id="info">
+       <?php if (is_array($this->item)) : ?>
+               <ul>
+               <?php foreach($this->item as $i) : ?>
+                       <li><?php echo $i; ?></li>
+               <?php endforeach; ?>
+               </ul>
+       <?php endif; ?>
+</div>
\ No newline at end of file
diff --git a/themes/default/login.tmpl.php b/themes/default/login.tmpl.php
new file mode 100644 (file)
index 0000000..9b1c0a6
--- /dev/null
@@ -0,0 +1,66 @@
+<?php require(AT_INCLUDE_PATH.'header.inc.php'); ?>
+
+<script language="JavaScript" src="sha-1factory.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+/* 
+ * Encrypt login password with sha1
+ */
+function encrypt_password() {
+       document.form.form_password_hidden.value = hex_sha1(document.form.form_password.value);
+       document.form.form_password.value = "";
+       return true;
+}
+
+</script>
+<div class="container">
+
+       <div class="column">
+               <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+               <input type="hidden" name="form_login_action" value="true" />
+               <input type="hidden" name="form_course_id" value="<?php echo $this->course_id; ?>" />
+               <input type="hidden" name="form_password_hidden" value="" />
+
+
+               <div class="input-form" style="background-color:white;">
+                       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('login') ;?></legend>
+                       <p><?php echo _AT('login_text') ;?></p>
+                               <?php if ($_GET['course']): ?>
+                                       <div class="row">
+                                               <h3><?php echo _AT('login'). ' ' . $this->title; ?></h3>
+                                       </div>
+                               <?php endif;?>
+
+                               <label for="login"><?php echo _AT('login_name_or_email'); ?></label><br />
+                               <input type="text" name="form_login" size="50" style="max-width: 80%; width: 80%;" id="login" /><br />
+
+                               <label for="pass"><?php echo _AT('password'); ?></label><br />
+                               <input type="password" class="formfield" name="form_password" style="max-width: 80%; width: 80%;" id="pass" />
+                               <br /><br />
+                               <input type="submit" name="submit" value="<?php echo _AT('login'); ?>" class="button" onclick="return encrypt_password();" />
+                       </fieldset>                     
+               </div>
+               </form>
+       </div>
+
+
+       <div class="column">
+               <form action="registration.php" method="get">
+                       <div class="input-form" style="background-color:white;">
+                       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('new_user') ;?></legend>
+                       <p><?php echo _AT('registration_text'); ?></p>
+
+                       <?php if (defined('AT_EMAIL_CONFIRMATION') && AT_EMAIL_CONFIRMATION): ?>
+                               <p><?php echo _AT('confirm_account_text'); ?></p>
+                       <?php endif; ?>
+                       <div style="width: 20%;margin-left:auto; margin-right:auto;margin-bottom:.6em;padding:.5em;">
+                       <br /><br /><br />
+                       <input type="submit" name="register" value="<?php echo _AT('register'); ?>" class="button" />
+                       </div>
+                       </fieldset>
+                       </div>
+               </form>
+
+       </div>
+</div>
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/themes/default/password_change.tmpl.php b/themes/default/password_change.tmpl.php
new file mode 100644 (file)
index 0000000..f98d715
--- /dev/null
@@ -0,0 +1,62 @@
+<?php 
+global $onload;
+$onload = 'document.form.password.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+?>
+
+<script language="JavaScript" src="sha-1factory.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+function encrypt_password()
+{
+       document.form.password_error.value = "";
+
+       err = verify_password(document.form.password.value, document.form.password2.value);
+       
+       if (err.length > 0)
+       {
+               document.form.password_error.value = err;
+       }
+       else
+       {
+               document.form.form_password_hidden.value = hex_sha1(document.form.password.value);
+               document.form.password.value = "";
+               document.form.password2.value = "";
+       }
+}
+</script>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+       <input type="hidden" name="form_change" value="true" />
+       <input type="hidden" name="id" value="<?php echo $this->id; ?>" />
+       <input type="hidden" name="g" value="<?php echo $this->g; ?>" />
+       <input type="hidden" name="h" value="<?php echo $this->h; ?>" />
+       <input type="hidden" name="form_password_hidden" value="" />
+       <input type="hidden" name="password_error" value="" />
+
+       <div class="input-form" style="max-width: 400px;">
+               <div class="row">
+                       <?php echo _AT('password_new_blurb'); ?>
+               </div>
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="password"><?php echo _AT('password'); ?></label><br />
+                       <input id="password" name="password" type="password" size="15" maxlength="15" value="<?php echo stripslashes(htmlspecialchars($_POST['password'])); ?>" /><br />
+                       <small>&middot; <?php echo _AT('combination'); ?><br />
+                                  &middot; <?php echo _AT('15_max_chars'); ?></small>
+               </div>
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="password2"><?php echo _AT('password_again'); ?></label><br />
+                       <input id="password2" name="password2" type="password" size="15" maxlength="15" value="<?php echo stripslashes(htmlspecialchars($_POST['password2'])); ?>" />
+               </div>
+
+               <div class="row buttons">
+                       <input type="submit" name="submit" value="<?php echo _AT('submit'); ?>" onClick="encrypt_password()" />
+                       <input type="submit" name="cancel" value=" <?php echo _AT('cancel'); ?> " />
+               </div>
+       </div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/themes/default/password_reminder.tmpl.php b/themes/default/password_reminder.tmpl.php
new file mode 100644 (file)
index 0000000..f4affde
--- /dev/null
@@ -0,0 +1,28 @@
+<?php 
+global $onload;
+$onload = 'document.form.form_email.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+       <input type="hidden" name="form_password_reminder" value="true" />
+       <div class="input-form" style="max-width: 400px;">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('password_reminder'); ?></legend>
+               <div class="row">
+                       <?php echo _AT('password_blurb'); ?>
+               </div>
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="email"><?php echo _AT('email_address'); ?></label><br />
+                       <input type="text" name="form_email" id="email" size="50" />
+               </div>
+
+               <div class="row buttons">
+                       <input type="submit" name="submit" value="<?php echo _AT('submit'); ?>" /> <input type="submit" name="cancel" value=" <?php echo _AT('cancel'); ?> " />
+               </div>
+       </fieldset>
+       </div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/themes/default/password_reminder_feedback.tmpl.php b/themes/default/password_reminder_feedback.tmpl.php
new file mode 100644 (file)
index 0000000..39ead0e
--- /dev/null
@@ -0,0 +1,6 @@
+<?php 
+
+       require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+?>
\ No newline at end of file
diff --git a/themes/default/print.css b/themes/default/print.css
new file mode 100644 (file)
index 0000000..48b2bc1
--- /dev/null
@@ -0,0 +1,13 @@
+body {
+       background-color: White;
+       font-family: Helvetica, arial, sans serif;
+       margin: 0px;
+       margin-top: 0px;
+       color: black;
+       border: 0px;
+}
+
+div#side-menu, div#member-links, span#side-menushowlink, div#rightcolumn, div#suv-nav-logout, div#top-links, span#side-menuhidelink, div#sequence-links, select#jumpmenu, a#guide, div#gototop, input#jump-button, div#topnavlistcontainer, a#guide, div#breadcrumbs, div#jump-area, table.tabbed-table, div#sub-navigation, div#sequence-links, div#language, div#toc, fieldset#shortcuts {
+       display: none;
+}
+
diff --git a/themes/default/profile.tmpl.php b/themes/default/profile.tmpl.php
new file mode 100644 (file)
index 0000000..356621c
--- /dev/null
@@ -0,0 +1,65 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+global $display_name_formats, $moduleFactory;\r
+\r
+?>\r
+<div class="input-form">\r
+       <div class="row">\r
+               <p><a href="inbox/send_message.php?id=<?php echo $this->row['member_id']; ?>"><?php echo _AT('send_message'); ?></a></p>\r
+\r
+               <dl id="public-profile">\r
+                       <dt><?php echo _AT('email'); ?></dt>\r
+                       <dd>\r
+                               <?php if($this->row['private_email']): ?>\r
+                                       <?php echo _AT('private'); ?>\r
+                               <?php else: ?>\r
+                                       <a href="mailto:<?php echo $this->row['email']; ?>"><?php echo $this->row['email']; ?></a>\r
+                               <?php endif; ?>\r
+                       </dd>\r
+               \r
+                       <dt><?php echo _AT('web_site'); ?></dt>\r
+                       <dd>\r
+                               <?php if ($this->row['website']) { \r
+                                       echo '<a href="'.htmlspecialchars($this->row['website'], ENT_COMPAT, "UTF-8").'">'.AT_print($this->row['website'], 'members.website').'</a>'; \r
+                               } else {\r
+                                       echo '--';\r
+                               } ?>\r
+                       </dd>\r
+\r
+                       <dt><?php echo _AT('phone'); ?></dt>\r
+                       <dd>\r
+                               <?php if ($this->row['phone']) { \r
+                                       echo $this->row['phone'];\r
+                               } else {\r
+                                       echo '--';\r
+                               }\r
+                               ?>\r
+                       </dt>\r
+\r
+                       <dt><?php echo _AT('status'); ?></dt>\r
+                       <dd><?php echo $this->status; ?></dd>\r
+\r
+                       <?php $mod = $moduleFactory->getModule('_standard/profile_pictures'); \r
+                       if ($mod->isEnabled() === TRUE): ?>\r
+                               <dt><?php echo _AT('picture'); ?></dt>\r
+                               <dd><?php if (profile_image_exists($this->row['member_id'])): ?>\r
+                                       <a href="get_profile_img.php?id=<?php echo $this->row['member_id'].SEP.'size=o'; ?>"><?php print_profile_img($this->row['member_id']); ?></a>\r
+                                       <?php else: ?>\r
+                                               <?php echo _AT('none'); ?>\r
+                                       <?php endif; ?>\r
+                               </dd>\r
+                       <?php endif; ?>\r
+               </dl>\r
+               <div style="clear: both; size: 1em"></div>\r
+       </div>\r
+</div>\r
diff --git a/themes/default/readme.txt b/themes/default/readme.txt
new file mode 100644 (file)
index 0000000..13d183a
--- /dev/null
@@ -0,0 +1,9 @@
+\r
+Theme:         1.6 Default Theme\r
+Date:          December 2007\r
+\r
+\r
+Installing:     See section "Installing a New Theme" in the themes_readme.txt file located in the themes/ top directory.\r
+\r
+Licence:       Falls under the GPL agreement.  See http://www.gnu.org/copyleft/gpl.html.\r
+       
\ No newline at end of file
diff --git a/themes/default/registration.tmpl.php b/themes/default/registration.tmpl.php
new file mode 100644 (file)
index 0000000..9fe83ab
--- /dev/null
@@ -0,0 +1,216 @@
+<?php 
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+?>
+
+<script language="JavaScript" src="sha-1factory.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+function encrypt_password()
+{
+       document.form.password_error.value = "";
+
+       err = verify_password(document.form.form_password1.value, document.form.form_password2.value);
+       
+       if (err.length > 0)
+       {
+               document.form.password_error.value = err;
+       }
+       else
+       {
+               document.form.form_password_hidden.value = hex_sha1(document.form.form_password1.value);
+               document.form.form_password1.value = "";
+               document.form.form_password2.value = "";
+       }
+}
+</script>
+
+<form method="post" action="<?php if (isset($_REQUEST["en_id"]) && $_REQUEST["en_id"] <> "") $getvars = '?en_id='. $_REQUEST["en_id"]; echo $_SERVER['PHP_SELF'] . $getvars; ?>" name="form">
+<?php global $languageManager, $_config, $moduleFactory; ?>
+<input name="ml" type="hidden" value="<?php echo $this->ml; ?>" />
+<input name="password_error" type="hidden" />
+<input type="hidden" name="form_password_hidden" value="" />
+
+<div class="input-form">
+<fieldset class="group_form"><legend class="group_form"><?php echo _AT('required_information'); ?></legend>
+       <?php if (!$_POST['member_id'] && defined('AT_MASTER_LIST') && AT_MASTER_LIST && !admin_authenticate(AT_ADMIN_PRIV_USERS, TRUE)): ?>
+               <div class="row">
+                       <h3><?php echo _AT('account_authorization'); ?></h3>
+               </div>
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="student_id"><?php echo _AT('student_id'); ?></label><br />
+                       <input id="student_id" name="student_id" type="text" size="15" maxlength="15" value="<?php echo stripslashes(htmlspecialchars($_POST['student_id'])); ?>" /><br />
+               </div>
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="student_pin"><?php echo _AT('student_pin'); ?></label><br />
+                       <input id="student_pin" name="student_pin" type="password" size="15" maxlength="15" value="<?php echo stripslashes(htmlspecialchars($_POST['student_pin'])); ?>" /><br />
+               </div>
+       <?php endif; ?>
+
+       <?php 
+               $table_title="
+               <div class=\"row\">
+                       <h3>" . _AT('course_to_auto_enroll'). "</h3>
+                       <small>&middot; " ._AT('auto_enroll_msg')."</small>
+               </div>";
+               
+               require(AT_INCLUDE_PATH.'html/auto_enroll_list_courses.inc.php'); 
+       ?>
+       
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="login"><?php echo _AT('login_name'); ?></label><br />
+               <?php if ($_POST['member_id']) : ?>
+                               <span id="login"><?php echo stripslashes(htmlspecialchars($_POST['login'])); ?></span>
+                               <input name="member_id" type="hidden" value="<?php echo intval($_POST['member_id']); ?>" />
+                               <input name="login" type="hidden" value="<?php echo stripslashes(htmlspecialchars($_POST['login'])); ?>" />
+               <?php else: ?>
+                       <input id="login" name="login" type="text" maxlength="20" size="30" value="<?php echo stripslashes(htmlspecialchars($_POST['login'])); ?>" /><br />
+                       <small>&middot; <?php echo _AT('contain_only'); ?><br />
+                                  &middot; <?php echo _AT('20_max_chars'); ?></small>
+               <?php endif; ?>
+       </div>
+
+       <?php if (!admin_authenticate(AT_ADMIN_PRIV_USERS, TRUE) || !$_POST['member_id']): ?>
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="form_password1"><?php echo _AT('password'); ?></label><br />
+                       <input id="form_password1" name="form_password1" type="password" size="15" maxlength="15" /><br />
+                       <small>&middot; <?php echo _AT('combination'); ?><br />
+                                  &middot; <?php echo _AT('15_max_chars'); ?></small>
+               </div>
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="form_password2"><?php echo _AT('password_again'); ?></label><br />
+                       <input id="form_password2" name="form_password2" type="password" size="15" maxlength="15" />
+               </div>
+       <?php endif; ?>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="email"><?php echo _AT('email_address'); ?></label><br />
+               <input id="email" name="email" type="text" size="50" maxlength="50" value="<?php echo stripslashes(htmlspecialchars($_POST['email'])); ?>" />
+               <input type="checkbox" id="priv" name="private_email" value="1" <?php if ($_POST['private_email'] || !isset($_POST['submit'])) { echo 'checked="checked"'; } ?> /><label for="priv"><?php echo _AT('keep_email_private');?></label>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="first_name"><?php echo _AT('first_name'); ?></label><br />
+               <input id="first_name" name="first_name" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['first_name'])); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="second_name"><?php echo _AT('second_name'); ?></label><br />
+               <input id="second_name" name="second_name" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['second_name'])); ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="last_name"><?php echo _AT('last_name'); ?></label><br />
+               <input id="last_name" name="last_name" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['last_name'])); ?>" />
+       </div>
+       
+       <?php if (admin_authenticate(AT_ADMIN_PRIV_USERS, TRUE)): 
+                       if ($_POST['status'] == AT_STATUS_INSTRUCTOR) {
+                               $inst = ' checked="checked"';
+                       } else if ($_POST['status'] == AT_STATUS_STUDENT) {
+                               $stud = ' checked="checked"';
+                       }  else if ($_POST['status'] == AT_STATUS_DISABLED) {
+                               $disa = ' checked="checked"';
+                       } else {
+                               $uncon = ' checked="checked"';
+                       }?>
+                       <input type="hidden" name="id" value="<?php echo $_POST['member_id']; ?>" >
+                       <div class="row">
+                               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><?php echo _AT('account_status'); ?><br />
+
+                               <input type="radio" name="status" value="0" id="disa" <?php echo $disa; ?> /><label for="disa"><?php echo _AT('disabled'); ?></label>
+                               <?php if (defined('AT_EMAIL_CONFIRMATION') && AT_EMAIL_CONFIRMATION): ?>
+                                       <input type="radio" name="status" value="1" id="uncon" <?php echo $uncon; ?> /><label for="uncon"><?php echo _AT('unconfirmed'); ?></label>
+                               <?php endif; ?>
+
+                               <input type="radio" name="status" value="2" id="stud" <?php echo $stud; ?> /><label for="stud"><?php echo _AT('student'); ?></label>
+
+                               <input type="radio" name="status" value="3" id="inst" <?php echo $inst; ?> /><label for="inst"><?php echo _AT('instructor'); ?></label>
+
+                               <input type="hidden" name="old_status" value="<?php echo $_POST['old_status']; ?>" />
+                       </div>
+       <?php endif; ?>
+</fieldset>
+<fieldset class="group_form"><legend class="group_form"><?php echo _AT('personal_information').' ('._AT('optional').')'; ?></legend>
+       <?php 
+       $mod = $moduleFactory->getModule('_standard/profile_pictures');
+       if (admin_authenticate(AT_ADMIN_PRIV_USERS, TRUE) && $_POST['member_id'] && $mod->isEnabled() === TRUE): ?>
+               <div class="row">
+                       <?php echo _AT('picture'); ?><br/>
+                       <?php if (profile_image_exists($_POST['member_id'])): ?>
+                               <a href="get_profile_img.php?id=<?php echo $_POST['member_id'].SEP.'size=o'; ?>"><?php print_profile_img($_POST['member_id']); ?></a>
+                               <input type="checkbox" name="profile_pic_delete" value="1" id="profile_pic_delete" /><label for="profile_pic_delete"><?php echo _AT('delete'); ?></label>
+                       <?php else: ?>
+                               <?php echo _AT('none'); ?> <a href="admin/profile_picture.php?member_id=<?php echo $_POST['member_id']; ?>"><?php echo _AT('add'); ?></a>
+                       <?php endif; ?>
+               </div>
+       <?php endif; ?>
+
+       <?php if (admin_authenticate(AT_ADMIN_PRIV_USERS, TRUE) && defined('AT_MASTER_LIST') && AT_MASTER_LIST): ?>
+               <input type="hidden" name="old_student_id" value="<?php echo $_POST['old_student_id']; ?>" />
+               <div class="row">
+                       <label for="student_id"><?php echo _AT('student_id'); ?></label><br />
+                               <input type="text" name="student_id" value="<?php echo $_POST['student_id']; ?>" size="20" /><br />
+               </div>
+               <div class="row">
+                       <input type="checkbox" id="overwrite" name="overwrite" value="1" <?php if ($_POST['overwrite']) { echo 'checked="checked"'; } ?> /><label for="overwrite"><?php echo _AT('overwrite_master');?></label>
+               </div>
+
+       <?php endif; ?>
+
+       <div class="row">
+               <?php echo _AT('date_of_birth'); ?><br />
+               <label for="year"><?php echo _AT('year'); ?>: </label><input id="year" class="formfield" name="year" type="text" size="4" maxlength="4" value="<?php echo $_POST['year']; ?>" />  <label for="month"><?php echo _AT('month'); ?>: </label><input id="month" class="formfield" name="month" type="text" size="2" maxlength="2" value="<?php echo $_POST['month']; ?>" /> <label for="day"><?php echo _AT('day'); ?>: </label><input id="day" class="formfield" name="day" type="text" size="2" maxlength="2" value="<?php echo $_POST['day']; ?>" />
+       </div>
+
+       <div class="row">
+               <?php echo _AT('gender'); ?><br />
+               <input type="radio" name="gender" id="m" value="m" <?php if ($_POST['gender'] == 'm') { echo 'checked="checked"'; } ?> /><label for="m"><?php echo _AT('male'); ?></label> <input type="radio" value="f" name="gender" id="f" <?php if ($_POST['gender'] == 'f') { echo 'checked="checked"'; } ?> /><label for="f"><?php echo _AT('female'); ?></label>  <input type="radio" value="n" name="gender" id="ns" <?php if (($_POST['gender'] == 'n') || ($_POST['gender'] == '')) { echo 'checked="checked"'; } ?> /><label for="ns"><?php echo _AT('not_specified'); ?></label>
+       </div>
+
+       <div class="row">
+               <label for="address"><?php echo _AT('street_address'); ?></label><br />
+               <input id="address" name="address" size="40" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['address'])); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="postal"><?php echo _AT('postal_code'); ?></label><br />
+               <input id="postal" name="postal" size="7" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['postal'])); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="city"><?php echo _AT('city'); ?></label><br />
+               <input id="city" name="city" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['city'])); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="province"><?php echo _AT('province'); ?></label><br />
+               <input id="province" name="province" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['province'])); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="country"><?php echo _AT('country'); ?></label><br />
+               <input id="country" name="country" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['country'])); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="phone"><?php echo _AT('phone'); ?></label><br />
+               <input size="11" name="phone" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['phone'])); ?>" id="phone" />
+       </div>
+
+       <div class="row">
+               <label for="website"><?php echo _AT('web_site'); ?></label><br />
+               <input id="website" name="website" size="40" type="text" value="<?php if ($_POST['website'] == '') { echo 'http://'; } else { echo stripslashes(htmlspecialchars($_POST['website'])); } ?>" />
+       </div>
+</fieldset>
+       <div class="row buttons">
+               <input type="submit" name="submit" value=" <?php echo _AT('save'); ?> " accesskey="s" onClick="encrypt_password()" class="button"/>
+               <input type="submit" name="cancel" value=" <?php echo _AT('cancel'); ?> "  class="button" />
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/themes/default/rtl.css b/themes/default/rtl.css
new file mode 100644 (file)
index 0000000..4e06fdf
--- /dev/null
@@ -0,0 +1,16 @@
+/* for right to left languages */
+html, body {
+       direction: rtl;
+}
+
+.img-size-tree {
+       vertical-align: middle;
+       margin-top: 0px;
+       height:1.45em;
+       width:1.45em;
+       float: right;
+}
+
+div.box {
+       line-height:150%;
+}
\ No newline at end of file
diff --git a/themes/default/screenshot.gif b/themes/default/screenshot.gif
new file mode 100644 (file)
index 0000000..b065030
Binary files /dev/null and b/themes/default/screenshot.gif differ
diff --git a/themes/default/styles.css b/themes/default/styles.css
new file mode 100644 (file)
index 0000000..671a0db
--- /dev/null
@@ -0,0 +1,1529 @@
+html,body{
+       height:100%;
+}
+
+
+/* main body attributes */
+body {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       margin:0px;
+       margin-top: -10px;
+       font-size: small;
+       background-color: white;
+}
+
+p {
+    margin: 0.5em 0em 1em 0em;
+    text-align: justify;
+    line-height: 150%;
+       font-size: 1em;
+}
+
+p a {
+    text-decoration: underline;
+}
+
+p a:visited {
+       color: #3F2670;
+    background-color: transparent;
+}
+
+p a:active {
+       color: #A50707;
+    background-color: transparent;
+}
+
+h1, h2, h3, h4, h5, h6 {
+    color: #A50707;
+    clear: right;
+    font: 100% Verdana, Helvetica, Arial, sans-serif;
+       font-weight: bold;
+    margin: 0;
+    padding-top: 0.5em;
+    /*border-bottom: 1px solid #B8AE9C;*/
+}
+
+h1 {
+    font-size: 160%;
+       color: #FFF;
+}
+
+h2 {
+    font-size: 150%;
+}
+h2.sidebox{
+    font-size: 110%;
+}
+h3 {
+    font-size: 130%;
+}
+
+h4 {
+    font-size: 120%;
+}
+
+
+h5 {
+    font-size: 100%;
+}
+
+
+
+/*  Table of content attributes*/
+p.toc{
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #E9F4F3;
+       padding: .6em;
+       margin-bottom: .6em;
+       margin-top: 0em;
+       margin-left: 1em;
+       margin-right: 3em;
+       border: 1px #ACCFCC solid;
+} 
+
+/* list attributes */
+ul {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+
+li {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+
+li.folders {
+       list-style: disc url(../../images/folder.gif) outside;
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+
+li.folders .disabled {
+       color: #B8AE9C;
+}
+
+/* link attributes */
+a:link, a:visited  {
+       color: #1A4A72;
+}
+a:hover {
+       color: #932318;
+color:#ffffff;
+}
+a:active {
+       color: #932318;
+}
+/* align text to the left */
+.left {
+       text-align: left;
+}
+
+a.dropdown-title {
+       color: white;
+       font-weight: normal;
+       text-decoration: none;
+}
+
+
+/* table border */
+.tableborder {
+       border: 1px #595241 solid;
+}
+
+/* main submit button */
+.button {
+       background-color: #efefef;
+       font-weight: normal;
+       border:  #AAA  solid 1px;
+
+}
+.button:focus {
+       border:1px solid #A50707;
+       background-color:  #FFDAB9;     
+}
+/* small submit button at top */
+.button2 {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #E9F4F3;
+
+}
+.button2:focus {
+       background-color: #E9F4F3;
+       border:  #ACCFCC  solid 1px;
+}
+
+/* date attributes */
+small.date {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: #595241; 
+       margin-bottom: 0px; 
+       margin-top: 0px;
+       margin-left: 5px;
+       margin-right: 0px;
+       font-size:1em;
+}
+
+/* page breakline */
+hr {
+       color: #ACCFCC;
+       background-color: white;
+       height: 1px;
+}
+
+/* message box styles */
+
+/* Editor box small */
+.editorsmallbox {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #E9F4F3;
+       padding: 2px;
+       padding-right: 3px;
+       border: 1px #ACCFCC solid;
+}
+
+/* Editor box large */
+.editorlargebox {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #E9F4F3;
+       margin-left:1em;
+       padding-left: .2em;
+       padding-right: .5em;
+       padding-top: .5em;
+       padding-bottom: .4em;
+       border: 1px #ACCFCC solid;
+}
+
+
+select.dropdown {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+}
+
+.highlight, a.highlight {
+       background-color: #5B8E88;
+       color: white;
+}
+
+a .highlight{
+       background-color: #5B8E88;
+       color: white;
+}
+
+.center {
+       text-align: center;
+}
+
+
+/* edit content tabs */
+.buttontab {
+       background-color: #E6E6E6;
+       font-weight: 500;
+       border:0;
+       padding-left: 3px;
+       padding-right: 3px;
+       padding-top: 3px;
+
+}
+
+.tab {
+       color: black;
+       background-color: #E6E6E6;
+       border-top: 1px #B8AE9C solid;
+       border-left: 1px #B8AE9C solid;
+       border-right: 1px #B8AE9C solid;
+       text-decoration: none;
+       text-align: center;
+       font-weight: bold;
+       
+}
+.buttontab selected {
+       font-family: Helvetica, Arial, Helvetica, sans-serif;
+       background-color: #6F7172;
+       font-weight: 600;
+       border:0;
+       padding-left: 3px;
+       padding-right: 3px;
+       padding-top: 3px;
+
+}
+td.selected{
+       font-family: Helvetica, Arial, Helvetica, sans-serif;
+       font-weight: 600;
+       text-decoration: none;
+       text-align: center;
+       background-color: white;
+       border-top: 1px #B8AE9C solid;
+       border-left: 1px #B8AE9C solid;
+       border-right: 1px #B8AE9C solid;
+}
+.econtainer{
+       background-color: #fffaf0;
+       border:1px #6F7172 solid;
+       margin-left:.5em;
+}
+
+.tab a:link, .etab a:visited {
+       color: black;
+       background-color: white;
+}
+.tab a:hover {
+       color: black;
+       background-color: white;
+}
+
+.etabself {
+       background-color: #6F7172;
+
+       text-align: center;
+       font-weight: bold;
+       padding: 2px;
+}
+
+
+.unsaved {
+       color: red;
+       background-color: #FFFDE0;
+       font-weight: bold;
+}
+.saved {
+       background-color: #FFFDE0;
+       margin: 10px;
+}
+
+
+
+/* the side menu */
+/* the side menu heading */
+td.dropdown-heading {
+       background-color: #DBFDD4;
+       color: #595241;
+       border-left: 1px solid #ECFEEA;
+       border-right: 1px solid #ECFEEA;
+       border-top: 1px solid #ECFEEA;
+       font-weight: bold;
+       padding: 2px;
+}
+
+td.dropdown-heading a, td.dropdown-heading a:hover, td.dropdown-heading a:visited {
+       text-decoration: none;
+}
+
+td.dropdown-heading.closed {
+       border-bottom: 1px solid #ECFEEA;
+}
+
+/* the side menu content */
+td.dropdown {
+       padding: 2px;
+       background-color: white;
+       color: black;
+       border-left: 1px solid #ECFEEA;
+       border-right: 1px solid #ECFEEA;
+       border-bottom: 1px solid #ECFEEA;
+       font-weight: normal;
+}
+td.dropdown a, td.dropdown a:visited  {
+       color: #595241;
+       text-decoration: none;
+}
+td.dropdown a:hover {
+       color: #595241;
+       text-decoration: underline;
+}
+td.dropdown.cell {
+       border-bottom: 0px;
+}
+td.dropdown strong {
+       color: #2A6C28;
+}
+
+/* added for 1.4.2: */
+.results {
+       padding-left: 20px;
+}
+
+h5.search-results {
+       background-color: #F7F3ED;
+       color: #595241;
+       padding: 1px;
+       margin-bottom: 5px;
+       margin-top: 10px;
+       margin-left: 5px;
+}
+
+small.search-info {
+       color: #595241;
+}
+
+p.search-description {
+       background-color: #FFFCE5;
+       color: #595241;
+}
+
+.test-box {
+       background-color: #F7F3ED;
+       color: #595241;
+       border-left: 1px solid #595241;
+       border-right: 1px solid #595241;
+       border-top: 1px solid #595241;
+       font-weight: bold;
+       padding: 2px;
+}
+
+/***************************************************************/
+/* NEW STUFF */
+
+table.tabbed-table {
+       width: 100%;
+       border:thin black solid;
+}
+table.tabbed-table th#left-empty-tab {
+       background-color: transparent;
+       width: 15px;
+       border-bottom: 1px solid #B8AE9C;
+}
+table.tabbed-table th#right-empty-tab {
+       text-align: right;
+       background-color: transparent;
+       border-bottom: 1px solid #B8AE9C;
+       width: 400px;
+       padding-right: 5px;
+}
+table.tabbed-table th#right-empty-tab a {
+       text-decoration: underline;
+}
+table.tabbed-table th.tab-spacer {
+       background-color: transparent;
+       width: 5px;
+       border-bottom: 1px solid #B8AE9C;
+}
+
+table.tabbed-table th.tab {
+       padding-top: 2px;
+       padding-bottom: 2px;
+       width: 110px;
+       background-color: #E9F4F3;
+       border-bottom: 1px solid #B8AE9C;
+       border-left: 1px solid #B8AE9C;
+       border-top: 1px solid #B8AE9C;
+       border-right: 1px solid #B8AE9C;
+}
+table.tabbed-table th.tab:hover {
+       background-color: #ACCFCC;
+}
+
+table.tabbed-table th.tab a:focus {
+       color: white;
+}
+table.tabbed-table th.selected {
+       padding-top: 2px;
+       padding-bottom: 2px;
+       width: 110px;
+       background-color: #ACCFCC;
+       border-left: 1px solid #B8AE9C;
+       border-top: 1px solid #B8AE9C;
+       border-right: 1px solid #B8AE9C;
+}
+
+table.tabbed-table a, table.tabbed-table a:visited, table.tabbed-table a:hover {
+       color: black;
+       text-decoration: none;
+}
+
+a#my-start-page {
+       padding: 2px;
+       padding-left: 15px;
+       background-image: url(http://www.gris.uni-tuebingen.de/images/start.gif);
+       background-repeat: no-repeat;
+       background-position: 2px 5px;
+}
+
+a#back-to {
+       padding-left: 20px;
+       background-image: url(images/back.gif);
+       background-repeat: no-repeat;
+       background-position: 0px 0px;
+}
+
+div#breadcrumbs {
+    /* The path bar, including breadcrumbs and add to favorites */
+       clear:both;
+    font-size: 0.85em;
+       padding:3px;
+       float:left;
+}
+h2.page-title {
+       clear:right;
+       margin-bottom: 10px;
+       padding:0px;
+}
+
+h1 {
+       margin-bottom: 5px;
+}
+
+div#sub-navigation {
+       padding: 3px;
+       color: #555;
+       float:left;
+}
+
+div#sub-navigation strong {
+       color: black;
+}
+
+div#help {
+       border-left: 1px solid black;
+       border-right: 1px solid black;
+       border-bottom: 1px solid black;
+       padding-left: 5px;
+       padding-right: 5px;
+       padding-bottom: 5px;
+       background-color: #F7F3ED;
+       margin-left: 5px;
+       margin-right: 5px;
+       font-size: small;
+}
+
+h3#help-title {
+       margin-left: 5px;
+       margin-right: 5px;
+       border-left: 1px solid black;
+       border-right: 1px solid black;
+       padding: 1px;
+       background-color: #F7F3ED;
+}
+.line {
+       border-bottom: 1px solid black;
+}
+div#help p {
+       padding: 0px;
+       margin: 0px;
+}
+
+div#toctoggle {
+       float: left;
+       padding-left: 10px;
+}
+
+h1#section-title {
+       float: left;
+       white-space:nowrap;
+       margin-left:1em;
+       margin-bottom: -0.5em;
+}
+
+div#top-links {
+       float:right;
+       padding-right: 5px;
+       margin-right:205px;
+       margin-top:1em;
+       white-space:nowrap;
+}
+
+div#top-links a:link, div#top-links a:visited {
+       text-decoration:none;
+       margin-left:10px;
+}
+div#top-links a:focus{
+       color:black;
+       background-color:#F6EAD6;
+}
+
+#jumpmenu:focus{
+       background-color:#F6EAD6;
+}
+a#editor-link {
+       background-color: #F7F3ED;
+       padding-top: 1px;
+       padding-bottom: 1px;
+       padding-left: 15px;
+       padding-right: 8px;
+       border: 1px solid #cccccc;
+       font-weight: normal;
+       text-decoration: none;
+}
+
+a#editor-link:hover {
+       background-color: #F7F3ED;
+       border: 1px solid #B8AE9C;
+}
+
+a#editor-link.off {
+       background-image: url(images/pen.gif);
+       background-repeat: no-repeat;
+       background-position: 0px 2px;
+}
+a#editor-link.on {
+       background-image: url(images/pen2.gif);
+       background-repeat: no-repeat;
+       background-position: 0px 2px;
+}
+
+
+/* for data tables */
+table.data {
+       clear:right;
+       border: 1px solid #B8AE9C;
+       width: 90%; 
+       margin-left: auto; 
+       margin-right: auto;
+} 
+
+table.data th {
+       background-color: #F6EAD6;
+       padding: 3px;
+       white-space: nowrap;
+}
+
+table.data th a {
+       color: #595241;
+       padding-right: 15px;
+       margin-right: 15px;
+       background-image: url('../default/images/sort.gif');
+       background-repeat: no-repeat;
+       background-position: right;
+}
+
+table.data tbody {
+       border-top: 1px solid #B8AE9C;
+       border-bottom: 1px solid #B8AE9C;
+}
+
+table.data tbody th {
+       text-align: left;
+       background-color: #F7F3ED;
+       cursor: auto;
+}
+
+table.data td {
+       padding: 3px;
+}
+
+table.data tbody tr:hover {
+       background-color: #efefef;
+       cursor: pointer;
+}
+
+table.data tbody tr.selected {
+       background-color: #E9F4F3;
+       cursor: auto;
+}
+
+table.data tfoot {
+       background-color: #F7F3ED;
+       /*border-top: 1px solid #B8AE9C;*/
+}
+
+table.data tfoot tr:first-child td {
+       /*border-top: 1px solid #B8AE9C;*/
+       padding: 5px;
+       background-image: url('images/arrow_ltr.gif');
+       background-repeat: no-repeat;
+       background-position: 4px 5px;
+       padding-left: 40px;
+}
+
+table.data.static tfoot td, table.data.static tfoot tr:first-child td {
+       border-top: 1px solid #B8AE9C;
+       padding: 5px;
+       background-image: none;
+       padding-left: 0px;
+
+}
+
+/*buttons*/
+table.data tfoot input {
+       background-color: #efefef;
+       font-weight: normal;
+       border:  #AAA  solid 1px;
+}
+table.data tfoot input:focus {
+       background-color: #FFDAB9;
+       border:  #AAA  solid 1px;
+}
+
+
+/* used for static tables with no form elements: */
+table.data.static tbody tr:hover {
+       background-color: transparent;
+       cursor: auto;
+}
+
+
+
+/* course browser: */
+
+div#browse {
+       margin-left: auto; 
+       margin-right: auto; 
+       width: 80%;
+}
+
+div.browse-selected {
+       background-image: url('images/side_arrow.gif'); 
+       background-repeat: no-repeat; 
+       padding-left: 9px; 
+       background-position: center left;
+}
+
+div.browse-unselected {
+       padding-left: 9px; 
+}
+
+ul.browse-list {
+       list-style: none;
+       padding:0px;
+}
+
+/* feedback /errors */
+div#error {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #DD0000;
+       padding: 5px;
+       background-color: #F4DCDC;
+       color: #A50707;
+       background-color: #F4DCDC;
+       padding-left: 25px;
+       font-weight: bold;
+}
+div#error h4 {
+       color: black;
+       margin-left: 0px;
+}
+
+div#error ul, div#feedback ul, div#help ul {
+       position: relative;
+       list-style: none;
+       margin-left: 0px;
+       padding-left: 0px;
+}
+
+div#error ul li{
+       margin-top: 5px;
+}
+
+div#feedback {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #17B506;
+       padding: 5px;
+       background-color: #F2FCF0;
+       color: #595241;
+       font-weight: bold;
+}
+
+div#help {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #ACCFCC;
+       padding: 5px;
+       background-color: #E9F4F3;
+       color: #024C41;
+}
+
+div#info {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #B8AE9C;
+       padding: 5px;
+       background-color: #EFE6FF;
+       color: #595241;
+       font-weight: bold;
+}
+
+div#warning {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #FF8400;
+       padding: 5px;
+       background-color: #FFF6ED;
+       color: #D95900;
+       font-weight: bold;
+}
+acronym {
+       cursor: help;
+}
+
+div.news p {
+       margin-left: 10px;
+}
+div.news span.date {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: #B8AE9C; 
+}
+
+/* home page links */
+div.home-link {
+       padding: 2px;
+       float: left;
+       text-align: center;
+       margin: 2px;
+       width: 120px;
+       height: 90px;
+}
+div.home-link:hover {
+       padding: 1px;
+       background-color: #F7F3ED;
+       border: 1px solid #afafaf;
+       float: left;
+       text-align: center;
+       margin: 2px;
+}
+div.home-link a {
+       text-decoration: none;
+       font-weight: bold;
+}
+
+div.home-link img {
+       border: 0px;
+}
+
+/* sequence links */
+div#sequence-links {
+       float:right;
+       margin-top: 10px;
+       padding-right: 5px;
+       padding-top:7px;
+}
+div#sequence-links a {
+       text-decoration: none;
+}
+
+div.dropdown {
+       width: 200px;
+       padding: 2px;
+       background-color: white;
+       color: black;
+       border-left: 1px solid #ECFEEA;
+       border-right: 1px solid #ECFEEA;
+       border-bottom: 1px solid #ECFEEA;
+       font-weight: normal;
+}
+
+div.dropdown-heading {
+       background-color: #ACCFCC;
+       color: #595241;
+       border-left: 1px solid #ECFEEA;
+       border-right: 1px solid #ECFEEA;
+       border-top: 1px solid #ECFEEA;
+       font-weight: bold;
+       padding: 2px;
+}
+
+div.required {
+       font-weight: bold;
+       color: red;
+       font-size: large;
+       float: left;
+       position: relative;
+       margin-top: -5px;
+       height: 15px;
+       padding-right: 2px;
+}
+
+div#content_text {
+       margin-left: 5px;
+}
+
+form {
+       clear: none;
+       display:inline;
+}
+
+
+optgroup {
+       /*font-size: small;*/
+}
+
+/* packing */
+div.paging {
+   width: 100%;
+   text-align: center;
+   margin: 0.5em auto;
+}
+div.paging ul {
+   list-style: none;
+   display: inline;
+   padding: 0px;
+   border: 1px solid #000;
+}
+div.paging li { 
+       display: inline; 
+       padding-left: 2px; 
+       padding-right: 2px;
+       padding-top: 0px;
+       padding-bottom: 0px;
+}
+
+div.paging li a {
+       text-decoration: none;
+       padding-left: 4px;
+       padding-right: 4px;
+       border-left: 1px solid white;
+       border-right: 1px solid white;
+}
+
+div.paging li a:hover, div.paging li a.current {
+   background-color: #F7F3ED;
+   border-left: 1px solid #000;
+   border-right: 1px solid #000;
+}
+
+#header{
+       background-color: #1D2326;
+       background-image: url(images/pencil_top.gif);
+       background-position: right bottom;
+       background-repeat: no-repeat;
+       height : 6.85em;
+}
+
+#header a{
+       font-weight:600;
+       color: white;
+}
+
+
+#header a:hover {
+       color: #595241;
+       background-color: #F7F3ED;
+}
+#tl_corner{
+
+       background-image:url(images/tl_corner.gif);
+       background-position: top left;
+       background-repeat: no-repeat;
+padding:0;
+}
+div.top {
+    /* Top space */
+    background-color: #595241;
+       color: #FFF;
+    margin: 0;
+    padding: 0;
+       padding-top:9px;
+}
+div.tabs {
+       /* Navigational Plone Tabs(tm), implemented by customizing the a tag - they are surprisingly elegant. The power of CSS runs strong in these :) */
+    background-color: transparent;
+       border-collapse: collapse;
+       border-bottom: 1px solid #B8AE9C;
+       padding: 0.5em 0em 0em 2em;
+       white-space: nowrap;
+}
+
+div.tabs a {
+    /* The normal, unselected tabs. They are all links */
+    background-color: transparent;
+    border-color: #B8AE9C;
+    border-width: 1px; 
+    border-style: solid solid none solid;
+    color: #595241;
+    height: 1.2em;
+    margin-right: 0.5em;
+    padding: 0em 2em 0em;
+    
+}
+
+div.tabs a.selected {
+    /* The selected tab. There's only one of this */
+    background-color: white;
+    border-bottom: #B8AE9C 1px solid;
+    color: #595241;
+    font-weight: normal;
+}
+
+div.tabs a:hover, div.tabs a.active {
+    background-color: #B8AE9C;
+    border-bottom: 1px solid #B8AE9C;
+    color: white;
+}
+
+
+h4.box {
+       font-size:0.85em;
+       padding: 2px;
+}
+
+div.box {
+       padding: 5px;
+       background-color: #F5F5F5;
+       color: black;
+       border: 1px solid #B8AE9C;
+
+       font-size:0.85em;
+       font-weight: normal;
+       padding:2px;
+}
+
+h5.box { 
+    background-color: #6F7172;
+    border: 1px solid #B8AE9C;
+    border-style: solid solid none solid;
+    color: Black;
+    padding: 0em 1em 0em 1em;
+    
+    display: inline;
+       font-size:  1em;
+    height: 1em;
+}
+
+div.box a:link {
+       text-decoration: none;
+}
+
+div.box a:visited {
+       color: #2A6C28;
+       text-decoration: none;
+}
+
+div.box a:hover {
+       text-decoration: underline;
+}
+
+.boxDetails {
+    text-align: right;
+}
+
+div.box .content {
+    padding: 1em;
+       font-size:  1em;
+}
+
+div.box a.close {
+    float: right;
+    text-transform: none;
+    border-left: 1pt solid #B8AE9C;
+    padding: 0em 0.2em;
+}
+
+div.box h1, 
+div.box h2, 
+div.box h3, 
+div.box h4 {
+    margin: 0;
+    padding: 0;
+}
+
+div.box .even {
+    background-color: #F7F3ED;
+}
+
+div.box .odd {
+    background-color: transparent;
+}
+
+
+/* users/index.php */
+
+div.course {
+       position: relative;
+       width: 30em;
+       height: 10.5em;
+       border: rgb(204, 204, 204) 1px solid;
+       background-color: #F7F7F7;
+       float: left;
+       margin: 3px;
+       padding: 5px;
+}
+
+div.course.break {
+       clear: left;
+}
+
+div.course h2 {
+       border: 0px;
+       font-weight: normal;
+       font-size: large;
+
+}
+
+div.course:hover {
+       background-color:#FBF4E9;
+       border: #B8AE9C 1px solid;
+}
+
+div.course img.icon    {
+       float: left;
+       margin: 2px;
+       height:6.8em;
+       width:6.8em;
+       margin-right:5px;
+}
+img.headicon   {
+       float:  left;
+       margin-top:1.2em;
+       margin-right:.5em;
+       height:6.45em;
+       width:6.45em;
+       vertical-align:top;
+       border:1px solid white;
+}
+div.course div.shortcuts {
+       text-align: right;
+       clear: left;
+       vertical-align: middle;
+}
+
+fieldset#shortcuts {
+       float: right;
+       background-color: #FEFDEF;
+       border: 1pt solid #B8AE9C;
+       margin: -5pt 5pt 5pt 5pt;
+       padding-right: 10pt;
+       padding-bottom: 5pt;
+       padding-left: 10pt;
+}
+
+
+
+fieldset {
+       margin-bottom: 10pt;
+}
+#shortcuts legend {
+}
+#shortcuts ul {
+       position: relative;
+       margin-top: 0pt;
+       margin-bottom: 0pt;
+       margin-left: 0pt;
+       list-style-type:  none;
+       padding-left: 0pt; 
+}
+
+a#guide {
+       background-image: url('../default/images/guide.gif'); background-repeat: no-repeat; background-position: 7px 4px;
+       background-color: #eee;
+       padding: 2px 10px 2px 27px;
+       border: 1px solid #ccc;
+       float:right;
+       text-decoration:none;
+       font-size:0.85em;
+}
+
+div#content-text {
+       padding-right: 5pt;
+       line-height:150%;
+}
+
+div#content-text li {
+       margin-left: 15pt;
+}
+
+div#content-info {
+       margin: 5pt;
+       font-size: small;
+       color: #b8ae9c;
+       clear: both;
+}
+
+div#container {
+       text-align: left;
+       margin: 0px auto;
+       padding: 0px;
+       border:0;
+       width: 95%;
+}
+
+div#menutoggle{
+       text-align: right; 
+       padding-bottom: 10px; 
+       padding-right: 10px; 
+       float: left; 
+       margin-top: 10px; 
+       padding-right: 5px; 
+       font-size:0.95em;
+}
+
+
+/* login page */
+div.column {
+       /* border: 1px solid #6F7172; */
+       float: left;
+       width: 45%;
+       margin: 5px;
+       min-width: 170px;
+}
+
+div.column h3 {
+       background-color: #F6EAD6;
+       border-bottom: .05em solid #6F7172;
+       font-size: small;
+       display:block;
+       color:black;
+       font-weight:600;        
+       padding-left:0.5em;
+}
+
+div.insidecol {
+   min-height: 170px;
+   height: 170px;
+   padding:5px;
+}
+
+
+/* index page */
+ul#home-links {
+       list-style: none;
+}
+ul#home-links li {
+       
+       display: inline;
+       float: left;
+       padding: 0.8em;
+       text-align: center;
+       margin: 0.1em;
+       width: 8.5em;
+       height: 7.0em;
+       padding-left:0px;
+
+}
+ul#home-links li a {
+       text-decoration: none;
+       border: 1px transparent;
+       font-weight: bold;
+}
+ul#home-links li a img {
+       border: 0px;
+       display: block;
+       padding-left:25px;
+}
+
+/* enrollment tabs */
+#navlist {
+       padding: 0px;
+       margin-left: 0;
+       margin-right: auto;
+       margin-left: auto;
+       margin-bottom: 4px;
+       margin-top:15px;
+       white-space: nowrap;
+}
+
+#navlist li {
+       list-style: none;
+       display: inline;
+       margin: 0px;
+}
+
+#navlist li a {
+       padding: 3px 9px;
+       border: 1px solid #F7F3ED;
+       border-bottom: none;
+       background-color: #F7F3ED;
+       text-decoration: none;
+       margin-left: 4px;
+/*
+       -moz-border-radius-topright: 4px;
+       -moz-border-radius-topleft: 4px;
+*/
+       white-space: nowrap;
+}
+
+#navlist li a:hover, #navlist li a:active {
+       color: #000;
+       background-color: #fff;
+}
+
+/* tree */
+.img-size-tree {
+       vertical-align: middle;
+       margin-top: 0px;
+        padding:0;
+       height:1.45em;
+       width:1.5em;
+}
+/* profile page */
+dl#public-profile {
+       width: 100%;
+}
+dl#public-profile dt {
+       float: left;
+       font-weight: bold;
+       width: 30%;
+       text-align: right;
+       clear: left;
+       border-right: 1px solid #F7F3ED;
+       padding: 5px 5px 5px 0px;
+       vertical-align: middle;
+       margin-right: 5px;
+}
+dl#public-profile dd {
+       margin-bottom: 5px;
+       clear: right;
+       padding: 5px 0px 5px 5px;
+}
+
+/* floating layout */
+#contentwrapper{
+       float: left;
+       width: 99%;
+}
+#contentcolumn {
+       margin-left: 0.5em;
+       padding-right: 5px;
+}
+#contentcolumn_shiftright {
+       margin-left: 18em;
+}
+
+#leftcolumn{
+       float: left;
+       width: 17em;
+       margin-left: 5px;
+       margin-top:-10px;
+}
+
+#footer{
+       /*position:absolute;
+       bottom:0px;*/
+       clear: left;
+       width: 100%;
+       text-align: center;
+       padding: 4px 0px;
+}
+
+/** forum stuff **/
+#forum-thread li {border:1px solid #eee; border-bottom: 1px solid #F7F3ED; float:left; width: 98%; list-style: none; }
+#forum-thread li.even { background-color: #F7F3ED; border-top: none; }
+#forum-thread li.odd { background-color: #fff; }
+div.forum-post-author { float:left; width:150px; padding:8px 10px; }
+div.forum-post-author a.title {font-size: 1.1em; line-height: 1.2em; font-weight: bold; text-decoration:none; }        
+div.forum-post-author img.profile-picture { border: 2px solid #F7F3ED; text-align:right;}
+div.forum-post-content { margin-left: 150px; padding: 5px 0px 18px 18px;}
+div.forum-post-content h3 { font-weight: 500; float:left;clear:right; }
+div.forum-post-ctrl { float: right; padding-right: 5px; color: #a1a1a1;}
+div.forum-post-ctrl a { text-decoration: none; }
+div.forum-post-ctrl span { color: black; background-color: #fefdc2; padding: 3px; }
+div.forum-post-content p.date { color: #a1a1a1; border-bottom: 1px solid #F7F3ED; }
+div.forum-post-content div.body p { margin-bottom:1em; }
+div.forum-paginator{border:thin #cccccc solid; padding:.3em; width:95%;margin:auto;background-color:#F7F3ED;}
+span.forum-paginator-active{font-weight:700;text-decoration:underline; height:2em;}
+
+
+
+/** inbox stuff - reuses some of the forum layout **/
+#inbox-msg li {border:1px solid #eee; border-bottom: 1px solid #F7F3ED; width: 95%; list-style: none; min-height: 11em;}
+
+
+
+div#topnavlistcontainer {
+    background-color: #1D2326;
+       background-image: url(images/pencil_bottom.gif);
+       background-position:  top right;
+       background-repeat: no-repeat;
+}
+ul#topnavlist {
+       padding-top: 5px;
+       white-space: nowrap;
+       margin-top: 0px;
+       margin-left:5px;
+       margin-left:5px;
+}
+
+ul#topnavlist li {
+       list-style: none;
+       display: inline;
+       margin: 0px;
+}
+
+ul#topnavlist li a:hover, ul#topnavlist li a:focus, ul#topnavlist li a.active {
+    background-color: #E6E6E6;
+    color: black;
+       text-decoration:none;
+}
+
+ul#topnavlist li a {
+    /* The normal, unselected tabs. They are all links */
+    color: #555;
+       font-weight:bold;
+    height: 1.5em;
+    padding: 0em 2em 0em;
+       text-decoration:none;
+       background-color:white;
+}
+
+ul#topnavlist li a.selected {
+    /* The selected tab. There's only one of these */
+    color: #555;
+    font-weight: normal;
+}
+
+ol#tools>li:hover {
+       border: 1px solid #e0e0e0;
+       background-color: #efefef; 
+}
+
+/*  tool list on admin home and manage screens  */
+ li.top-tool { 
+       list-style: none;
+       padding: 2px 2px 2px 15px;
+       margin-bottom: 5px; 
+       line-height: 200%; 
+       background-color: #fdfdfd; 
+       border-bottom: 1px solid #efefef; 
+       /* -moz-border-radius: 4px;  */
+       border: 1px solid #eeeeff;}
+
+li.top-tool a {  font-weight: bold; } /* ol#tools>li>a */ 
+
+li.child-tool a { 
+       font-size: x-small;
+       font-weight: normal; 
+}
+
+/* ol#tools>li>ul, */ 
+ul.child-top-tool {
+       margin-top: -5px;
+       padding-left: 0px;
+       margin-left: 0px;
+       display: inline;
+}
+ul.child-top-tool:before {
+       content: " : ";
+}
+
+/* ol#tools>li>ul>li, */ 
+li.child-tool {
+       display: inline;
+       margin-right: 5px;
+       font-size: x-small;
+}
+
+/* to modify  tool icons on the course home page */
+/*
+#icon-color-filter{
+       width:3.9em;
+       height:3.85em;
+       background-color:#000000;
+       -moz-opacity:0.5;
+         filter:alpha(opacity=10);
+       opacity:.10;
+       margin-top:-3.85em;
+       margin-left:1.90em;
+
+}
+*/
+.img-size-home {
+       height:3.85em;
+       width:3.9em;
+}
+
+/* browse courses */
+dl.browse-course {
+       width: 100%;
+       padding-bottom: 25px;
+       background-color: #fffaf0;
+       border:1px #6F7172 solid;
+       width:75%;
+       margin:auto;
+       margin-left:15em;
+}
+dl.browse-course dt {
+       float: left;
+       font-weight: bold;
+       width: 25%;
+       text-align: right;
+       clear: left;
+       padding: 5px 10px 5px 0px;
+       vertical-align: middle;
+}
+dl.browse-course dd {
+       margin-bottom: 5px;
+       clear: right;
+       padding: 5px 0px 5px 10px;
+       margin-left: 26%;
+
+}
+
+
+/*  form fields grouping for WCAG 2.0 conformance*/
+
+fieldset.group_form{
+       margin:2em;
+       border:thin #6D7B8D solid;
+       min-height: 170px;
+       padding:.5em;
+}
+
+legend.group_form{
+       border:thin #6D7B8D solid;
+       background-color: #CCCCCC;
+       font-weight: 600;
+       color: black;
+       padding:.5em;
+}
+/* file storage */
+
+#fsfloat1{
+       float:right;
+}
+#fsfloat2{
+       float:right;
+       width:48%;
+}
+
+
+/* highlight active links for WCAG 2.0 conformance */
+a:active,a:hover,a:focus{
+       background-color:#F6EAD6;
+       color:#000000;
+}
+
+
+/* menu align right layout, uncomment to enable */
+
+/*
+h2.page-title {
+    clear:left
+}
+h2, h3, h4, h5, h6 {
+        clear: left;
+}
+#contentcolumn_shiftright {
+    margin-right: 17em;
+margin-left:1em;
+margin-top:1em;
+}
+#leftcolumn{
+    float: right;
+}
+#home-links{
+clear:left;
+}
+table.data {
+       clear:left;
+}
+div#menutoggle{
+       float: right; 
+}
+#fsfloat2{
+       float:left;
+       width:48%;
+}
+
+#fsfloat1{
+       float:left;
+}
+*/
\ No newline at end of file
diff --git a/themes/default/test_questions/footer.tmpl.php b/themes/default/test_questions/footer.tmpl.php
new file mode 100644 (file)
index 0000000..7f5eaa3
--- /dev/null
@@ -0,0 +1 @@
+</div>
\ No newline at end of file
diff --git a/themes/default/test_questions/header.tmpl.php b/themes/default/test_questions/header.tmpl.php
new file mode 100644 (file)
index 0000000..0f10638
--- /dev/null
@@ -0,0 +1,17 @@
+<div style="background-color: #f3f3f3; padding: 5px 10px; margin: 0px; border-top: 1px solid">
+       <?php if ($this->weight): ?>
+               <div style="float: right; width: 50%; text-align: right; font-weight: bold">
+                       <?php if ($this->score !== FALSE && $this->question_id): ?>
+                               <input type="text" name="scores[<?php echo $this->question_id; ?>]" value="<?php echo $this->score; ?>" size="5" style="font-weight: bold; text-align: right" maxlength="5"/> / 
+                       <?php elseif ($this->score !== FALSE): ?>
+                               <?php echo $this->score; ?> /
+                       <?php endif; ?>
+                       <?php echo $this->weight; ?> <?php echo _AT('points'); ?>
+               </div>
+       <?php endif; ?>
+
+       <h4 style="color: black"><?php echo _AT('question'); ?> <?php echo $this->number; ?>: <span style="padding-left: 10px"><?php echo $this->type; ?></span></h4>
+</span>
+       </strong>
+</div>
+<div class="row" style="padding-bottom: 20px">
\ No newline at end of file
diff --git a/themes/default/test_questions/likert.tmpl.php b/themes/default/test_questions/likert.tmpl.php
new file mode 100644 (file)
index 0000000..10d4bff
--- /dev/null
@@ -0,0 +1,12 @@
+<p><?php echo AT_print($this->row['question'], 'tests_questions.question'); ?></p>
+
+<ul style="padding: 0px; margin: 0px; list-style-type: none">
+       <?php for ($i=0; $i < $this->num_choices; $i++): ?>
+               <li style="padding: 4px; display: inline">
+                       <input type="radio" name="answers[<?php echo $this->row['question_id']; ?>]" value="<?php echo $i; ?>" id="choice_<?php echo $this->row['question_id'].'_'.$i; ?>" <?php if ($this->response == $i): ?>checked="checked"<?php endif; ?>/><label for="choice_<?php echo $this->row['question_id'].'_'.$i; ?>"><?php echo AT_print($this->row['choice_'.$i], 'tests_answers.answer'); ?></label>
+               </li>
+       <?php endfor; ?>
+       <li style="padding: 4px; display: inline">
+               <input type="radio" name="answers[<?php echo $this->row['question_id']; ?>]" value="-1" id="choice_<?php echo $this->row['question_id']; ?>_x" <?php if ($this->response == -1): ?>checked="checked"<?php endif; ?>/><label for="choice_<?php echo $this->row['question_id']; ?>_x"><em><?php echo _AT('leave_blank'); ?></em></label>
+       </li>
+</ul>
\ No newline at end of file
diff --git a/themes/default/test_questions/likert_qti_2p1.tmpl.php b/themes/default/test_questions/likert_qti_2p1.tmpl.php
new file mode 100644 (file)
index 0000000..16b3443
--- /dev/null
@@ -0,0 +1,24 @@
+<<?php echo '?'; ?>xml version="1.0" encoding="<?php echo $this->encoding; ?>"<?php echo '?'; ?>>
+<!-- likert question (aka multiple choice with no correct answer) -->
+<assessmentItem 
+       xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1" 
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+       xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p1 imsqti_v2p1.xsd" 
+       identifier="ATUTOR-<?php echo $this->row['question_id']; ?>" 
+       title="<?php echo $this->row['question']; ?>" 
+       adaptive="false" 
+       timeDependent="false"
+       toolname="ATutor - atutor.ca"
+       toolversion="<?php echo VERSION; ?>"
+>
+
+       <itemBody>
+               <choiceInteraction responseIdentifier="RESPONSE" shuffle="false" maxChoices="1">
+                       <prompt><?php echo $this->row['question']; ?></prompt>
+                       <?php for ($i=0; $i < $this->num_choices; $i++): ?>
+                               <simpleChoice identifier="Choice<?php echo $i; ?>" fixed="true"><?php echo $this->row['choice_'.$i]; ?></simpleChoice> 
+                       <?php endfor; ?>
+         </choiceInteraction>
+       </itemBody>
+
+</assessmentItem>
\ No newline at end of file
diff --git a/themes/default/test_questions/likert_result.tmpl.php b/themes/default/test_questions/likert_result.tmpl.php
new file mode 100644 (file)
index 0000000..b60a047
--- /dev/null
@@ -0,0 +1,16 @@
+<p><?php echo AT_print($this->row['question'], 'tests_questions.question'); ?></p>
+
+<ul style="padding: 0px; margin: 0px; list-style-type: none">
+       <?php for ($i=0; $i < 10; $i++): ?>
+               <?php if ($this->row['choice_'.$i] != ''): ?>
+                       <li style="padding: 4px; display: inline">
+                               <?php if ($this->answer == $i): ?>
+                                       <img src="<?php echo $this->base_path; ?>images/checkbox_check.gif" alt="<?php echo _AT('checked'); ?>" title="<?php echo _AT('checked'); ?>" height="13" width="13" style="vertical-align: middle" />
+                               <?php else: ?>
+                                       <img src="<?php echo $this->base_path; ?>images/checkbox_empty.gif" alt="<?php echo _AT('unchecked'); ?>" title="<?php echo _AT('unchecked'); ?>" height="13" width="13" style="vertical-align: middle" />
+                               <?php endif; ?>
+                               <?php echo AT_print($this->row['choice_'.$i], 'tests_answers.answer'); ?>
+                       </li>
+               <?php endif; ?>
+       <?php endfor; ?>
+</ul>
\ No newline at end of file
diff --git a/themes/default/test_questions/likert_stats.tmpl.php b/themes/default/test_questions/likert_stats.tmpl.php
new file mode 100644 (file)
index 0000000..33d9b19
--- /dev/null
@@ -0,0 +1,28 @@
+<br />
+<table class="data static" summary="" style="width: 95%" rules="cols">
+<thead>
+<tr>
+       <th scope="col" width="40%"><?php echo _AT('question'); ?></th>
+       <th scope="col"><?php echo _AT('left_blank'); ?></th>
+       <th scope="col"><?php echo _AT('average'); ?></th>
+       <?php for ($i=0; $i<$this->num_choices; $i++): ?>
+               <th scope="col" title="<?php echo $this->row['choice_'.$i]; ?>"><?php echo ($i+1); ?></th>
+       <?php endfor; ?>
+</tr>
+</thead>
+<tr>
+       <td valign="top" rowspan="2"><?php echo $this->row['question']; ?></td>
+       <td align="center" width="70" valign="top"><?php echo $this->num_blanks;?> / <?php echo $this->num_results; ?></td>
+       <td align="center" width="70" valign="top"><?php echo $this->average;?> / <?php echo $this->num_choices; ?></td>
+       <?php for ($j=0; $j<$this->num_choices; $j++): ?>
+               <td align="center" valign="top"><?php echo (int) $this->answers[$j]['count']; ?> / <?php echo $this->num_results; ?></td>
+       <?php endfor; ?>
+</tr>
+<tr>
+       <td align="center"><div class="qstat_bar-border"><div class="qstat_bar-bar"><div class="qstat_bar-fill" style="height:<?php echo 100-($this->num_results ? round($this->num_blanks/$this->num_results*100) : 0); ?>%;"></div></div></div><?php echo $this->num_results ? round($this->num_blanks/$this->num_results*100) : 0; ?>%</td>
+       <td align="center"><div class="qstat_bar-border"><div class="qstat_bar-bar"><div class="qstat_bar-fill" style="height:<?php echo 100-($this->num_results ? round($this->average/$this->num_choices*100) : 0); ?>%;"></div></div></div></td>
+       <?php for ($j=0; $j<$this->num_choices; $j++): ?>
+               <td align="center" valign="top"><div class="qstat_bar-border"><div class="qstat_bar-bar"><div class="qstat_bar-fill" style="height:<?php echo 100-($this->num_results ? round($this->answers[$j]['count']/$this->num_results*100) : 0); ?>%;"></div></div></div><?php echo $this->num_results ? round($this->answers[$j]['count']/$this->num_results*100) : 0; ?>%</td>
+       <?php endfor; ?>
+</tr>
+</table>
\ No newline at end of file
diff --git a/themes/default/test_questions/long.tmpl.php b/themes/default/test_questions/long.tmpl.php
new file mode 100644 (file)
index 0000000..bfc8ac0
--- /dev/null
@@ -0,0 +1,15 @@
+<p><?php echo AT_print($this->row['question'], 'tests_questions.question'); ?></p>
+
+<?php if ($this->row['properties'] == 1): /* one word */ ?>
+       <input type="text" name="answers[<?php echo $this->row['question_id']; ?>]" class="formfield" size="15" value="<?php echo htmlspecialchars($this->response); ?>" />
+
+<?php elseif ($this->row['properties'] == 2): /* sentence */ ?>
+       <input type="text" name="answers[<?php echo $this->row['question_id']; ?>]" class="formfield" size="45" value="<?php echo htmlspecialchars($this->response); ?>" />
+
+<?php elseif ($this->row['properties'] == 3): /* paragraph */ ?>
+       <textarea cols="55" rows="5" name="answers[<?php echo $this->row['question_id']; ?>]" class="formfield"><?php echo htmlspecialchars($this->response); ?></textarea>
+
+<?php elseif ($this->row['properties'] == 4): /* page */ ?>
+       <textarea cols="55" rows="25" name="answers[<?php echo $this->row['question_id']; ?>]" class="formfield"><?php echo htmlspecialchars($this->response); ?></textarea>
+
+<?php endif; ?>
\ No newline at end of file
diff --git a/themes/default/test_questions/long_qti_2p1.tmpl.php b/themes/default/test_questions/long_qti_2p1.tmpl.php
new file mode 100644 (file)
index 0000000..6b07f85
--- /dev/null
@@ -0,0 +1,31 @@
+<<?php echo '?'; ?>xml version="1.0" encoding="<?php echo $this->encoding; ?>"<?php echo '?'; ?>>
+<!-- open ended (free text) question -->
+<assessmentItem 
+       xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1" 
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+       xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p1 imsqti_v2p1.xsd" 
+       identifier="ATUTOR-<?php echo $this->row['question_id']; ?>" 
+       title="<?php echo $this->row['question']; ?>" 
+       adaptive="false" 
+       timeDependent="false"
+       toolname="ATutor - atutor.ca"
+       toolversion="<?php echo VERSION; ?>"
+>
+
+       <responseDeclaration identifier="RESPONSE" cardinality="single" baseType="string">
+         <?php if ($this->row['feedback']): ?>
+                 <outcomeDeclaration identifier="FEEDBACK" cardinality="single" baseType="identifier"/>
+         <?php endif; ?>
+       </responseDeclaration>
+
+
+       <itemBody>
+               <extendedTextInteraction responseIdentifier="RESPONSE">
+                       <prompt><?php echo $this->row['question']; ?></prompt>
+               </extendedTextInteraction>
+       </itemBody>
+
+       <?php if ($this->row['feedback']): ?>
+               <modalFeedback outcomeIdentifier="FEEDBACK" identifier="FEEDBACK" showHide="hide"><?php echo $this->row['feedback']; ?></modalFeedback> 
+       <?php endif; ?>
+</assessmentItem>
\ No newline at end of file
diff --git a/themes/default/test_questions/long_result.tmpl.php b/themes/default/test_questions/long_result.tmpl.php
new file mode 100644 (file)
index 0000000..0f94261
--- /dev/null
@@ -0,0 +1,3 @@
+<p><?php echo AT_print($this->row['question'], 'tests_questions.question'); ?></p>
+
+<p style="font-family: curior new; font-size: medium"><?php echo AT_print($this->answer, 'tests_answers.answer'); ?></p>
diff --git a/themes/default/test_questions/long_stats.tmpl.php b/themes/default/test_questions/long_stats.tmpl.php
new file mode 100644 (file)
index 0000000..6da523c
--- /dev/null
@@ -0,0 +1,21 @@
+<br/>
+<table class="data static" summary="" style="width: 95%" rules="cols">
+<thead>
+<tr>
+       <th scope="col"><?php echo _AT('question'); ?></th>
+       <th scope="col"><?php echo _AT('left_blank'); ?></th>
+       <th scope="col"><?php echo _AT('results'); ?></th>
+</tr>
+</thead>
+<tr>
+       <td><?php echo $this->row['question']; ?></td>
+       <td align="center" width="70" valign="top"><?php echo $this->num_blanks; ?> / <?php echo $this->num_results; ?></td>
+       <td align="center" valign="top">
+               <?php if ((count($this->answers)-$this->num_blanks) > 0): ?>
+                       <a href="tools/tests/results_quest_long.php?tid=<?php echo intval($_GET['tid']).SEP; ?>qid=<?php echo $this->row['question_id'].SEP.'q='.urlencode($this->row['question']); ?>"><?php echo _AT('view_responses'); ?> (<?php echo (count($this->answers)-$this->num_blanks); ?>)</a>
+               <?php else: ?>
+                       <?php echo _AT('none'); ?>              
+               <?php endif; ?>
+       </td>
+</tr>
+</table>
\ No newline at end of file
diff --git a/themes/default/test_questions/manifest_qti_2p1.tmpl.php b/themes/default/test_questions/manifest_qti_2p1.tmpl.php
new file mode 100644 (file)
index 0000000..4b196f4
--- /dev/null
@@ -0,0 +1,29 @@
+<<?php echo '?'; ?>xml version="1.0" encoding="<?php echo $this->encoding; ?>"<?php echo '?'; ?>>
+<manifest xmlns="http://www.imsglobal.org/xsd/imscp_v1p2" xmlns:imsmd="http://www.imsglobal.org/xsd/imsmd_v1p2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:imsqti="http://www.imsglobal.org/xsd/imsqti_v2p1" identifier="MANIFEST-<?php echo md5(time()); ?>" xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p2 http://www.imsglobal.org/xsd/imscp_v1p2.xsd http://www.imsglobal.org/xsd/imsmd_v1p2 http://www.imsglobal.org/xsd/imsmd_v1p2p2.xsd http://www.imsglobal.org/xsd/imsqti_v2p1 http://www.imsglobal.org/xsd/imsqti_v2p1.xsd">
+       <metadata>
+               <schema>IMS Content</schema>
+               <schemaversion>1.2</schemaversion>
+       </metadata>
+
+       <organizations/>
+
+       <resources>
+               <?php foreach ($this->resources as $resource): ?>
+                       <resource identifier="RES-<?php echo md5($resource['href']); ?>" type="imsqti_item_xmlv2p1" href="<?php echo $resource['href']; ?>">
+                               <metadata/>
+                               <file href="<?php echo $resource['href']; ?>"/>
+                               <?php foreach ($resource['dependencies'] as $dependency_href): ?>
+                                       <dependency identifierref="<?php echo md5($dependency_href); ?>"/>
+                               <?php endforeach; ?>
+                       </resource>
+               <?php endforeach; ?>
+
+               <!-- dependancies go here -->
+               <?php foreach ($this->dependencies as $dependency_href): ?>
+                       <resource identifier="<?php echo md5($dependency_href); ?>" type="webcontent">
+                               <metadata/>
+                               <file href="resources/<?php echo $dependency_href; ?>"/>
+                       </resource>
+               <?php endforeach; ?>
+       </resources>
+</manifest>
\ No newline at end of file
diff --git a/themes/default/test_questions/matching.tmpl.php b/themes/default/test_questions/matching.tmpl.php
new file mode 100644 (file)
index 0000000..6db85fe
--- /dev/null
@@ -0,0 +1,28 @@
+<p><?php echo AT_print($this->row['question'], 'tests_questions.question'); ?></p>
+
+<table style="width: 100%">
+<tr>
+       <td valign="top">
+               <ul style="padding: 0px; margin: 0px; list-style-type: none">
+                       <?php for ($i=0; $i < $this->num_choices; $i++): ?>
+                               <li style="padding: 4px">
+                               <select name="answers[<?php echo $this->row['question_id']; ?>][<?php echo $i; ?>]">
+                                       <option value="-1" <?php if ('' === $this->response[$i] || -1 == $this->response[$i]): ?>selected="selected"<?php endif; ?>>-</option>
+                                       <?php for ($j=0; $j < $this->num_options; $j++): ?>
+                                               <option value="<?php echo $j; ?>" <?php if (is_numeric($this->response[$i]) && $j == $this->response[$i]): ?>selected="selected"<?php endif; ?>><?php echo $this->letters[$j]; ?></option>
+                                       <?php endfor; ?>
+                               </select>
+                               <?php echo $this->row['choice_'. $i]; ?>
+                               </li>
+                       <?php endfor; ?>
+               </ul>
+       </td>
+       <td valign="top">
+               <ul style="list-style-type: none; margin: 0px; padding: 0px">
+                       <?php for ($i=0; $i < $this->num_options; $i++): ?>
+                               <li style="padding: 4px"><?php echo $this->letters[$i]; ?>. <?php echo $this->row['option_'. $i]; ?></li>
+                       <?php endfor; ?>
+               </ul>
+       </td>
+</tr>
+</table>
\ No newline at end of file
diff --git a/themes/default/test_questions/matching_qti_2p1.tmpl.php b/themes/default/test_questions/matching_qti_2p1.tmpl.php
new file mode 100644 (file)
index 0000000..cb4ce1c
--- /dev/null
@@ -0,0 +1,54 @@
+<<?php echo '?'; ?>xml version="1.0" encoding="<?php echo $this->encoding; ?>"<?php echo '?'; ?>>
+<!-- matching question with partial marks -->
+<assessmentItem 
+       xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1" 
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+       xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p1 imsqti_v2p1.xsd" 
+       identifier="ATUTOR-<?php echo $this->row['question_id']; ?>" 
+       title="<?php echo $this->row['question']; ?>" 
+       adaptive="false" 
+       timeDependent="false"
+       toolname="ATutor - atutor.ca"
+       toolversion="<?php echo VERSION; ?>"
+>
+       <responseDeclaration identifier="RESPONSE" cardinality="multiple" baseType="directedPair">
+               <correctResponse>
+                       <?php for ($i=0; $i < $this->num_choices; $i++): ?>
+                               <?php if ($this->row['answer_'.$i] > -1): ?>
+                                       <value>Choice<?php echo $i; ?> Option<?php echo $this->row['answer_'.$i]; ?></value>
+                               <?php endif; ?>
+                       <?php endfor; ?>
+               </correctResponse>
+               <mapping lowerBound="0" defaultValue="0">
+                       <?php for ($i=0; $i < $this->num_choices; $i++): ?>
+                               <?php if ($this->row['answer_'.$i] > -1): ?>
+                                       <mapEntry mapKey="Choice<?php echo $i; ?> Option<?php echo $this->row['answer_'.$i]; ?>" mappedValue="1"/>
+                               <?php endif; ?>
+                       <?php endfor; ?>
+               </mapping>
+         <?php if ($this->row['feedback']): ?>
+                 <outcomeDeclaration identifier="FEEDBACK" cardinality="multiple" baseType="identifier"/>
+         <?php endif; ?>
+       </responseDeclaration>
+
+       <itemBody>
+               <associateInteraction responseIdentifier="RESPONSE" shuffle="true" maxAssociations="<?php echo $this->num_choices; ?>">
+                       <prompt><?php echo $this->row['question']; ?></prompt>
+                       <simpleMatchSet>
+                               <?php for ($i=0; $i < $this->num_choices; $i++): ?>
+                                       <simpleAssociableChoice identifier="Choice<?php echo $i; ?>" matchMax="1"><?php echo $this->row['choice_'.$i]; ?></simpleAssociableChoice>
+                               <?php endfor; ?>
+                       </simpleMatchSet>
+
+                       <simpleMatchSet>
+                               <?php for ($i=0; $i < $this->num_options; $i++): ?>
+                                       <simpleAssociableChoice identifier="Option<?php echo $i; ?>" matchMax="<?php echo $this->num_choices; ?>"><?php echo $this->row['option_'.$i]; ?></simpleAssociableChoice>
+                               <?php endfor; ?>
+                       </simpleMatchSet>
+               </associateInteraction>
+       </itemBody>
+
+       <?php if ($this->row['feedback']): ?>
+               <modalFeedback outcomeIdentifier="FEEDBACK" identifier="FEEDBACK" showHide="hide"><?php echo $this->row['feedback']; ?></modalFeedback> 
+       <?php endif; ?>
+</assessmentItem>
\ No newline at end of file
diff --git a/themes/default/test_questions/matching_result.tmpl.php b/themes/default/test_questions/matching_result.tmpl.php
new file mode 100644 (file)
index 0000000..24a51e3
--- /dev/null
@@ -0,0 +1,37 @@
+<p><?php echo AT_print($this->row['question'], 'tests_questions.question'); ?></p>
+
+<table style="width: 100%">
+<tr>
+       <td valign="top">
+               <ul style="padding: 0px; margin: 0px; list-style-type: none">
+                       <?php for ($i=0; $i < 10; $i++): ?>
+                               <?php if ($this->row['choice_'. $i] != ''): ?>
+                                       <li style="padding: 4px">
+                                               <?php if ($this->row['answer_'.$i] == $this->answers[$i]): ?>
+                                                       <img src="<?php echo $this->base_path; ?>images/checkmark.gif" alt="<?php echo _AT('correct_answer'); ?>" title="<?php echo _AT('correct_answer'); ?>" height="16" width="16" style="vertical-align: middle" />
+                                               <?php else: ?>
+                                                       <img src="<?php echo $this->base_path; ?>images/x.gif" alt="<?php echo _AT('wrong_answer'); ?>" title="<?php echo _AT('wrong_answer'); ?>" height="16" width="16" style="vertical-align: middle" />
+                                                       <?php if ($this->row['answer_'.$i] >= 0): ?>
+                                                               (<?php echo $this->letters[$this->row['answer_'.$i]]; ?>)
+                                                       <?php endif; ?>
+                                               <?php endif; ?>
+                                               <?php if ($this->answers[$i] != '' && $this->answers[$i] >= 0): ?>
+                                                       <?php echo $this->letters[$this->answers[$i]]; ?>.
+                                               <?php else: ?>
+                                                       -.
+                                               <?php endif; ?>
+                                               <?php echo $this->row['choice_'. $i]; ?>
+                                       </li>
+                               <?php endif; ?>
+                       <?php endfor; ?>
+               </ul>
+       </td>
+       <td valign="top">
+               <ul style="list-style-type: none; margin: 0px; padding: 0px">
+                       <?php for ($i=0; $i < $this->num_options; $i++): ?>
+                               <li style="padding: 4px"><?php echo $this->letters[$i]; ?>. <?php echo $this->row['option_'. $i]; ?></li>
+                       <?php endfor; ?>
+               </ul>
+       </td>
+</tr>
+</table>
\ No newline at end of file
diff --git a/themes/default/test_questions/matching_stats.tmpl.php b/themes/default/test_questions/matching_stats.tmpl.php
new file mode 100644 (file)
index 0000000..36aeca1
--- /dev/null
@@ -0,0 +1,23 @@
+<br/>
+<table class="data static" summary="" style="width: 95%" rules="cols">
+<thead>
+<tr>
+       <th scope="col" width="40%"><?php echo _AT('question'); ?></th>
+       <?php for ($i=0; $i< $this->num_choices; $i++): ?>
+               <?php $this->row['choice_'.$i] = validate_length($this->row['choice_'.$i], 15, VALIDATE_LENGTH_FOR_DISPLAY); ?>
+               <th scope="col"><?php echo htmlspecialchars($this->row['choice_'.$i], ENT_COMPAT, "UTF-8"); ?></th>
+       <?php endfor; ?>
+</tr>
+</thead>
+<tr>
+       <td valign="top" rowspan="2"><?php echo $this->row['question']; ?></td>
+       <?php for ($j=0; $j<$this->num_choices; $j++): ?>
+               <td align="center" valign="top"><?php echo (int) $this->answers[$j]['count']; ?> / <?php echo $this->num_results; ?></td>
+       <?php endfor; ?>
+</tr>
+<tr>
+       <?php for ($j=0; $j<$this->num_choices; $j++): ?>
+               <td align="center" valign="top"><div class="qstat_bar-border"><div class="qstat_bar-bar"><div class="qstat_bar-fill" style="height:<?php echo 100-($this->num_results ? round($this->answers[$j]['count']/$this->num_results*100) : 0); ?>%;"></div></div></div><?php echo $this->num_results ? round($this->answers[$j]['count']/$this->num_results*100) : 0; ?>%</td>
+       <?php endfor; ?>
+</tr>
+</table>
\ No newline at end of file
diff --git a/themes/default/test_questions/matchingdd.tmpl.php b/themes/default/test_questions/matchingdd.tmpl.php
new file mode 100644 (file)
index 0000000..298eed1
--- /dev/null
@@ -0,0 +1,8 @@
+<p><?php echo AT_print($this->row['question'], 'tests_questions.question'); ?></p>
+
+<?php $tmp_response = implode('|', $this->response); ?>
+
+<?php for ($i=0; $i < $this->num_choices; $i++): ?>
+       <input type="hidden" name="answers[<?php echo $this->row['question_id']; ?>][<?php echo $i; ?>]" id="<?php echo $this->row['question_id']; ?>q<?php echo $i; ?>" value="<?php echo $this->response[$i]; ?>"/>
+<?php endfor; ?>
+<iframe id="qframe<?php echo $this->row['question_id']; ?>" src="<?php echo $this->base_href; ?>tools/tests/dd.php?qid=<?php echo $this->row['question_id'].SEP; ?>response=<?php echo $tmp_response; ?>" height="200" width="100%" frameborder="0"></iframe>
\ No newline at end of file
diff --git a/themes/default/test_questions/matchingdd_qti_2p1.tmpl.php b/themes/default/test_questions/matchingdd_qti_2p1.tmpl.php
new file mode 100644 (file)
index 0000000..dff8d9b
--- /dev/null
@@ -0,0 +1 @@
+<?php require('matching_qti_2p1.tmpl.php'); ?>
\ No newline at end of file
diff --git a/themes/default/test_questions/matchingdd_result.tmpl.php b/themes/default/test_questions/matchingdd_result.tmpl.php
new file mode 100644 (file)
index 0000000..0054a6d
--- /dev/null
@@ -0,0 +1 @@
+<?php require('matching_result.tmpl.php'); ?>
\ No newline at end of file
diff --git a/themes/default/test_questions/matchingdd_stats.tmpl.php b/themes/default/test_questions/matchingdd_stats.tmpl.php
new file mode 100644 (file)
index 0000000..2006efd
--- /dev/null
@@ -0,0 +1 @@
+<?php require('matching_stats.tmpl.php'); ?>
\ No newline at end of file
diff --git a/themes/default/test_questions/multianswer.tmpl.php b/themes/default/test_questions/multianswer.tmpl.php
new file mode 100644 (file)
index 0000000..01ce9af
--- /dev/null
@@ -0,0 +1,10 @@
+<p><?php echo AT_print($this->row['question'], 'tests_questions.question'); ?></p>
+
+<input type="hidden" name="answers[<?php echo $this->row['question_id']; ?>][]" value="-1" />
+
+<ul style="padding: 0px; margin: 0px; list-style-type: none">
+       <?php for ($i=0; $i < $this->num_choices; $i++): ?>
+               <li style="padding: 4px">
+                       <input type="checkbox" name="answers[<?php echo $this->row['question_id']; ?>][]" value="<?php echo $i; ?>" id="choice_<?php echo $this->row['question_id'].'_'.$i; ?>" <?php if (in_array($i, $this->response)): ?>checked="checked"<?php endif; ?>/><label for="choice_<?php echo $this->row['question_id'].'_'.$i; ?>"><?php echo AT_print($this->row['choice_'.$i], 'tests_questions.choice_'.$i); ?></label>
+       <?php endfor; ?>
+</ul>
\ No newline at end of file
diff --git a/themes/default/test_questions/multianswer_qti_2p1.tmpl.php b/themes/default/test_questions/multianswer_qti_2p1.tmpl.php
new file mode 100644 (file)
index 0000000..857e242
--- /dev/null
@@ -0,0 +1,46 @@
+<<?php echo '?'; ?>xml version="1.0" encoding="<?php echo $this->encoding; ?>"<?php echo '?'; ?>>
+<!-- multi answer multiple choice question with partial marks -->
+<assessmentItem 
+       xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1" 
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+       xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p1 imsqti_v2p1.xsd" 
+       identifier="ATUTOR-<?php echo $this->row['question_id']; ?>" 
+       title="<?php echo $this->row['question']; ?>" 
+       adaptive="false" 
+       timeDependent="false"
+       toolname="ATutor - atutor.ca"
+       toolversion="<?php echo VERSION; ?>"
+>
+       <responseDeclaration identifier="RESPONSE" cardinality="multiple" baseType="identifier">
+         <correctResponse>
+               <?php for ($i=0; $i < $this->num_choices; $i++): ?>
+                       <?php if ($this->row['answer_'.$i]): ?>
+                               <value>Choice<?php echo $i; ?></value>
+                       <?php endif; ?>
+               <?php endfor; ?>
+         </correctResponse>
+         <mapping lowerBound="0" upperBound="<?php echo $this->num_correct; ?>" defaultValue="0">
+               <?php for ($i=0; $i < $this->num_choices; $i++): ?>
+                       <?php if ($this->row['answer_'.$i]): ?>
+                               <mapEntry mapKey="Choice<?php echo $i; ?>" mappedValue="1"/>
+                       <?php endif; ?>
+               <?php endfor; ?>
+               </mapping>
+         <?php if ($this->row['feedback']): ?>
+                 <outcomeDeclaration identifier="FEEDBACK" cardinality="multiple" baseType="identifier"/>
+         <?php endif; ?>
+       </responseDeclaration>
+
+       <itemBody>
+               <choiceInteraction responseIdentifier="RESPONSE" shuffle="false" maxChoices="0">
+                       <prompt><?php echo $this->row['question']; ?></prompt>
+                       <?php for ($i=0; $i < $this->num_choices; $i++): ?>
+                               <simpleChoice identifier="Choice<?php echo $i; ?>" fixed="false"><?php echo $this->row['choice_'.$i]; ?></simpleChoice> 
+                       <?php endfor; ?>
+         </choiceInteraction>
+       </itemBody>
+
+       <?php if ($this->row['feedback']): ?>
+               <modalFeedback outcomeIdentifier="FEEDBACK" identifier="FEEDBACK" showHide="hide"><?php echo $this->row['feedback']; ?></modalFeedback> 
+       <?php endif; ?>
+</assessmentItem>
\ No newline at end of file
diff --git a/themes/default/test_questions/multianswer_result.tmpl.php b/themes/default/test_questions/multianswer_result.tmpl.php
new file mode 100644 (file)
index 0000000..d520321
--- /dev/null
@@ -0,0 +1 @@
+<?php require('multichoice_result.tmpl.php'); ?>
\ No newline at end of file
diff --git a/themes/default/test_questions/multianswer_stats.tmpl.php b/themes/default/test_questions/multianswer_stats.tmpl.php
new file mode 100644 (file)
index 0000000..140367f
--- /dev/null
@@ -0,0 +1 @@
+<?php require('multichoice_stats.tmpl.php'); ?>
\ No newline at end of file
diff --git a/themes/default/test_questions/multichoice.tmpl.php b/themes/default/test_questions/multichoice.tmpl.php
new file mode 100644 (file)
index 0000000..3ef3ebd
--- /dev/null
@@ -0,0 +1,13 @@
+<p><?php echo AT_print($this->row['question'], 'tests_questions.question'); ?></p>
+
+<ul style="padding: 0px; margin: 0px; list-style-type: none">
+       <?php for ($i=0; $i < $this->num_choices; $i++): ?>
+               <li style="padding: 4px">
+                       <input type="radio" name="answers[<?php echo $this->row['question_id']; ?>]" value="<?php echo $i; ?>" id="choice_<?php echo $this->row['question_id'].'_'.$i; ?>" <?php 
+                       //Multiple choice will always have just 1 choice, thus the response is always in the array of $this->response[0]
+                       if (is_numeric($this->response[0]) && $i == $this->response[0]): ?>checked="checked"<?php endif; ?>/><label for="choice_<?php echo $this->row['question_id'].'_'.$i; ?>"><?php echo AT_print($this->row['choice_'.$i], 'tests_questions.choice_'.$i); ?></label>
+       <?php endfor; ?>
+       <li style="padding: 4px">
+               <input type="radio" name="answers[<?php echo $this->row['question_id']; ?>]" value="-1" id="choice_<?php echo $this->row['question_id']; ?>'_x" <?php if (is_numeric($this->response[0]) && -1 == $this->response[0]): ?>checked="checked"<?php endif; ?> /><label for="choice_<?php echo $this->row['question_id']; ?>'_x"><em><?php echo _AT('leave_blank'); ?></em></label>
+       </li>
+</ul>
\ No newline at end of file
diff --git a/themes/default/test_questions/multichoice_qti_2p1.tmpl.php b/themes/default/test_questions/multichoice_qti_2p1.tmpl.php
new file mode 100644 (file)
index 0000000..624201c
--- /dev/null
@@ -0,0 +1,39 @@
+<<?php echo '?'; ?>xml version="1.0" encoding="<?php echo $this->encoding; ?>"<?php echo '?'; ?>>
+<!-- single answer multiple choice question -->
+<assessmentItem 
+       xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1" 
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+       xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p1 imsqti_v2p1.xsd" 
+       identifier="ATUTOR-<?php echo $this->row['question_id']; ?>" 
+       title="<?php echo $this->row['question']; ?>" 
+       adaptive="false" 
+       timeDependent="false"
+       toolname="ATutor - atutor.ca"
+       toolversion="<?php echo VERSION; ?>"
+>
+       <responseDeclaration identifier="RESPONSE" cardinality="single" baseType="identifier">
+         <correctResponse>
+               <?php for ($i=0; $i < $this->num_choices; $i++): ?>
+                       <?php if ($this->row['answer_'.$i]): ?>
+                               <value>Choice<?php echo $i; ?></value>
+                       <?php endif; ?>
+               <?php endfor; ?>
+         </correctResponse>
+         <?php if ($this->row['feedback']): ?>
+                 <outcomeDeclaration identifier="FEEDBACK" cardinality="single" baseType="identifier"/>
+         <?php endif; ?>
+       </responseDeclaration>
+
+       <itemBody>
+               <choiceInteraction responseIdentifier="RESPONSE" shuffle="false" maxChoices="1">
+                       <prompt><?php echo $this->row['question']; ?></prompt>
+                       <?php for ($i=0; $i < $this->num_choices; $i++): ?>
+                               <simpleChoice identifier="Choice<?php echo $i; ?>" fixed="false"><?php echo $this->row['choice_'.$i]; ?></simpleChoice> 
+                       <?php endfor; ?>
+         </choiceInteraction>
+       </itemBody>
+
+       <?php if ($this->row['feedback']): ?>
+               <modalFeedback outcomeIdentifier="FEEDBACK" identifier="FEEDBACK" showHide="hide"><?php echo $this->row['feedback']; ?></modalFeedback> 
+       <?php endif; ?>
+</assessmentItem>
\ No newline at end of file
diff --git a/themes/default/test_questions/multichoice_result.tmpl.php b/themes/default/test_questions/multichoice_result.tmpl.php
new file mode 100644 (file)
index 0000000..3c028fd
--- /dev/null
@@ -0,0 +1,23 @@
+<p><?php echo AT_print($this->row['question'], 'tests_questions.question'); ?></p>
+
+<ul style="padding: 0px; margin: 0px; list-style-type: none">
+       <?php for ($i=0; $i < 10; $i++): ?>
+               <?php if ($this->row['choice_'.$i] != ''): ?>
+                       <li style="padding: 4px">
+                               <?php if (($this->row['answer_'.$i] == 1) && in_array($i, $this->answers)): ?>
+                                       <img src="<?php echo $this->base_path; ?>images/checkmark.gif" alt="<?php echo _AT('correct_answer'); ?>" title="<?php echo _AT('correct_answer'); ?>" height="16" width="16" style="vertical-align: middle" />
+                               <?php elseif (($this->row['answer_'.$i] == 1) || in_array($i, $this->answers)): ?>
+                                       <img src="<?php echo $this->base_path; ?>images/x.gif" alt="<?php echo _AT('wrong_answer'); ?>" title="<?php echo _AT('wrong_answer'); ?>" height="16" width="16" style="vertical-align: middle" />
+                               <?php else: ?>
+                                       <img src="<?php echo $this->base_path; ?>images/clr.gif" alt="" title="" height="16" width="16" style="vertical-align: middle" />
+                               <?php endif; ?>
+
+                               <?php if (in_array($i, $this->answers)): ?>
+                                       <img src="<?php echo $this->base_path; ?>images/checkbox_check.gif" alt="<?php echo _AT('checked'); ?>" title="<?php echo _AT('checked'); ?>" height="13" width="13" style="vertical-align: middle" />
+                               <?php else: ?>
+                                       <img src="<?php echo $this->base_path; ?>images/checkbox_empty.gif" alt="<?php echo _AT('unchecked'); ?>" title="<?php echo _AT('unchecked'); ?>" height="13" width="13" style="vertical-align: middle" />
+                               <?php endif; ?>
+                               <?php echo AT_print($this->row['choice_'.$i], 'tests_questions.choice_'.$i); ?>
+               <?php endif; ?>
+       <?php endfor; ?>
+</ul>
\ No newline at end of file
diff --git a/themes/default/test_questions/multichoice_stats.tmpl.php b/themes/default/test_questions/multichoice_stats.tmpl.php
new file mode 100644 (file)
index 0000000..0504fa1
--- /dev/null
@@ -0,0 +1,30 @@
+<br />
+<table class="data static" summary="" style="width: 95%" rules="cols">
+<thead>
+<tr>
+       <th scope="col" width="40%"><?php echo _AT('question'); ?></th>
+       <th scope="col" nowrap="nowrap"><?php echo _AT('left_blank'); ?></th>
+       <?php for ($i=0; $i<$this->num_choices; $i++): ?>
+               <?php $this->row['choice_'.$i] = validate_length($this->row['choice_'.$i], 15, VALIDATE_LENGTH_FOR_DISPLAY); ?>
+               <?php if ($this->row['answer_'.$i]): ?>
+                       <th scope="col"><?php echo htmlspecialchars($this->row['choice_'.$i]); ?><img src="images/checkmark.gif" alt="" /></th>
+               <?php else: ?>
+                       <th scope="col"><?php echo htmlspecialchars($this->row['choice_'.$i], ENT_COMPAT, "UTF-8"); ?></th>
+               <?php endif; ?>
+       <?php endfor; ?>
+</tr>
+</thead>
+<tr>
+       <td valign="top" rowspan="2"><?php echo $this->row['question']; ?></td>
+       <td align="center" valign="top"><?php echo $this->num_blanks; ?> / <?php echo $this->num_results; ?></td>
+       <?php for ($j=0; $j< $this->num_choices; $j++): ?>
+               <td align="center" valign="top"><?php echo (int) $this->answers[$j]['count']; ?> / <?php echo $this->num_results; ?></td>
+       <?php endfor; ?>
+</tr>
+<tr>
+       <td align="center"><div class="qstat_bar-border"><div class="qstat_bar-bar"><div class="qstat_bar-fill" style="height:<?php echo 100-($this->num_results ? round($this->num_blanks/$this->num_results*100) : 0); ?>%;"></div></div></div><?php echo $this->num_results ? round($this->num_blanks/$this->num_results*100) : 0; ?>%</td>
+       <?php for ($j=0; $j< $this->num_choices; $j++): ?>
+               <td align="center" valign="top"><div class="qstat_bar-border"><div class="qstat_bar-bar"><div class="qstat_bar-fill" style="height:<?php echo 100-($this->num_results ? round($this->answers[$j]['count']/$this->num_results*100) : 0); ?>%;"></div></div></div><?php echo $this->num_results ? round($this->answers[$j]['count']/$this->num_results*100) : 0; ?>%</td>
+       <?php endfor; ?>
+</tr>
+</table>
\ No newline at end of file
diff --git a/themes/default/test_questions/ordering.tmpl.php b/themes/default/test_questions/ordering.tmpl.php
new file mode 100644 (file)
index 0000000..b7fdfcf
--- /dev/null
@@ -0,0 +1,14 @@
+<p><?php echo AT_print($this->row['question'], 'tests_questions.question'); ?></p>
+
+<ul style="padding: 0px; margin: 0px; list-style-type: none">
+       <?php for ($i=0; $i < $this->num_choices; $i++): ?>
+               <li style="padding: 4px">
+               <select name="answers[<?php echo $this->row['question_id']; ?>][<?php echo $i; ?>]" id="choice_<?php echo $this->row['question_id'].'_'.$i; ?>" />
+                       <option value="-1">-</option>
+                       <?php for ($j=0; $j < $this->num_choices; $j++): ?>
+                               <option value="<?php echo $j; ?>"<?php if (is_numeric($this->response[$i]) && $j == $this->response[$i]): ?>selected="selected"<?php endif; ?>><?php echo ($j+1); ?></option>
+                       <?php endfor; ?>
+               </select> <label for="choice_<?php echo $this->row['question_id'].'_'.$i; ?>"><?php echo AT_print($this->row['choice_'.$i], 'tests_questions.choice_'.$i); ?></label>
+               </li>
+       <?php endfor; ?>
+</ul>
\ No newline at end of file
diff --git a/themes/default/test_questions/ordering_qti_2p1.tmpl.php b/themes/default/test_questions/ordering_qti_2p1.tmpl.php
new file mode 100644 (file)
index 0000000..82a9614
--- /dev/null
@@ -0,0 +1,37 @@
+<<?php echo '?'; ?>xml version="1.0" encoding="<?php echo $this->encoding; ?>"<?php echo '?'; ?>>
+<!-- ordering question -->
+<assessmentItem 
+       xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1" 
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+       xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p1 imsqti_v2p1.xsd" 
+       identifier="ATUTOR-<?php echo $this->row['question_id']; ?>" 
+       title="<?php echo $this->row['question']; ?>" 
+       adaptive="false" 
+       timeDependent="false"
+       toolname="ATutor - atutor.ca"
+       toolversion="<?php echo VERSION; ?>"
+>
+
+       <responseDeclaration identifier="RESPONSE" cardinality="ordered" baseType="identifier">
+               <correctResponse>
+               <?php for ($i=0; $i < $this->num_choices; $i++): ?>
+                       <value>Choice<?php echo $i; ?></value>
+               <?php endfor; ?>
+               </correctResponse>
+         <?php if ($this->row['feedback']): ?>
+                 <outcomeDeclaration identifier="FEEDBACK" cardinality="multiple" baseType="identifier"/>
+         <?php endif; ?>
+       </responseDeclaration>
+
+       <itemBody>
+               <orderInteraction responseIdentifier="RESPONSE" shuffle="true">
+                       <prompt><?php echo $this->row['question']; ?></prompt>
+                       <?php for ($i=0; $i < $this->num_choices; $i++): ?>
+                               <simpleChoice identifier="Choice<?php echo $i; ?>" fixed="false"><?php echo $this->row['choice_'.$i]; ?></simpleChoice> 
+                       <?php endfor; ?>
+               </orderInteraction>
+       </itemBody>
+       <?php if ($this->row['feedback']): ?>
+               <modalFeedback outcomeIdentifier="FEEDBACK" identifier="FEEDBACK<?php echo $this->row['question_id'];?>" showHide="hide"><?php echo $this->row['feedback']; ?></modalFeedback> 
+       <?php endif; ?>
+</assessmentItem>
\ No newline at end of file
diff --git a/themes/default/test_questions/ordering_result.tmpl.php b/themes/default/test_questions/ordering_result.tmpl.php
new file mode 100644 (file)
index 0000000..91257c1
--- /dev/null
@@ -0,0 +1,14 @@
+<p><?php echo AT_print($this->row['question'], 'tests_questions.question'); ?></p>
+
+<ol style="margin: 0px; padding: 0px">
+       <?php for ($i=0; $i < $this->num_choices; $i++): ?>
+               <li style="padding: 4px; list-style: none">
+                       <?php if ($i == $this->answers[$i]): ?>
+                               <img src="<?php echo $this->base_path; ?>images/checkmark.gif" alt="<?php echo _AT('correct_answer'); ?>" title="<?php echo _AT('correct_answer'); ?>" height="16" width="16" style="vertical-align: middle" />
+                       <?php else: ?>
+                               <img src="<?php echo $this->base_path; ?>images/x.gif" alt="<?php echo _AT('wrong_answer'); ?>" title="<?php echo _AT('wrong_answer'); ?>" height="16" width="16" style="vertical-align: middle" />
+                       <?php endif; ?>
+                       <?php echo ($i+1); ?>. <?php echo AT_print($this->row['choice_'.$i], 'tests_questions.choice_'.$i); ?>
+               </li>
+       <?php endfor; ?>
+</ol>
\ No newline at end of file
diff --git a/themes/default/test_questions/ordering_stats.tmpl.php b/themes/default/test_questions/ordering_stats.tmpl.php
new file mode 100644 (file)
index 0000000..a3e3a26
--- /dev/null
@@ -0,0 +1,23 @@
+<br/>
+<table class="data static" summary="" style="width: 95%" rules="cols">
+<thead>
+<tr>
+       <th scope="col" width="40%"><?php echo _AT('question'); ?></th>
+       <?php for ($i=0; $i<$this->num_choices; $i++): ?>
+               <?php $this->row['choice_'.$i] = validate_length($this->row['choice_'.$i], 15, VALIDATE_LENGTH_FOR_DISPLAY); ?>
+               <th scope="col"><?php echo htmlspecialchars($this->row['choice_'.$i], ENT_COMPAT, "UTF-8"); ?></th>
+       <?php endfor; ?>
+</tr>
+</thead>
+<tr>
+       <td valign="top" rowspan="2"><?php echo $this->row['question']; ?></td>
+       <?php for ($j=0; $j<$this->num_choices; $j++): ?>
+               <td align="center" valign="top"><?php echo (int) $this->answers[$j]; ?> / <?php echo $this->num_results; ?></td>
+       <?php endfor; ?>
+</tr>
+<tr>
+       <?php for ($j=0; $j<$this->num_choices; $j++): ?>
+               <td align="center" valign="top"><div class="qstat_bar-border"><div class="qstat_bar-bar"><div class="qstat_bar-fill" style="height:<?php echo 100-($this->num_results ? round($this->answers[$j]/$this->num_results*100) : 0); ?>%;"></div></div></div><?php echo $this->num_results ? round($this->answers[$j]/$this->num_results*100) : 0; ?>%</td>
+       <?php endfor; ?>
+</tr>
+</table>
\ No newline at end of file
diff --git a/themes/default/test_questions/truefalse.tmpl.php b/themes/default/test_questions/truefalse.tmpl.php
new file mode 100644 (file)
index 0000000..62c7b73
--- /dev/null
@@ -0,0 +1,7 @@
+<p><?php echo AT_print($this->row['question'], 'tests_questions.question'); ?></p>
+
+<p><input type="radio" name="answers[<?php echo $this->row['question_id']; ?>]" value="1" id="choice_<?php echo $this->row['question_id']; ?>_0" <?php if ($this->response == 1):?>checked="checked"<?php endif; ?>/><label for="choice_<?php echo $this->row['question_id']; ?>_0"><?php echo _AT('true'); ?></label></p>
+
+<p><input type="radio" name="answers[<?php echo $this->row['question_id']; ?>]" value="2" id="choice_<?php echo $this->row['question_id']; ?>_1" <?php if ($this->response == 2):?>checked="checked"<?php endif; ?>/><label for="choice_<?php echo $this->row['question_id']; ?>_1"><?php echo _AT('false'); ?></label></p>
+
+<p><input type="radio" name="answers[<?php echo $this->row['question_id']; ?>]" value="-1" id="choice_<?php echo $this->row['question_id']; ?>_x" <?php if ($this->response < 1):?>checked="checked"<?php endif; ?>/><label for="choice_<?php echo $this->row['question_id']; ?>_x"><em><?php echo _AT('leave_blank'); ?></em></label></p>
\ No newline at end of file
diff --git a/themes/default/test_questions/truefalse_qti_2p1.tmpl.php b/themes/default/test_questions/truefalse_qti_2p1.tmpl.php
new file mode 100644 (file)
index 0000000..94d386c
--- /dev/null
@@ -0,0 +1,38 @@
+<<?php echo '?'; ?>xml version="1.0" encoding="<?php echo $this->encoding; ?>"<?php echo '?'; ?>>
+<!-- true or false question (aka multiple choice with two choices) -->
+<assessmentItem 
+       xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1" 
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+       xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p1 imsqti_v2p1.xsd" 
+       identifier="ATUTOR-<?php echo $this->row['question_id']; ?>" 
+       title="<?php echo $this->row['question']; ?>" 
+       adaptive="false" 
+       timeDependent="false"
+       toolname="ATutor - atutor.ca"
+       toolversion="<?php echo VERSION; ?>"
+>
+       <responseDeclaration identifier="RESPONSE" cardinality="single" baseType="identifier">
+         <correctResponse>
+               <?php if ($this->row['answer_0'] == 1): ?>
+                       <value>ChoiceT</value>
+               <?php else: ?>
+                       <value>ChoiceF</value>
+               <?php endif; ?>
+         </correctResponse>
+         <?php if ($this->row['feedback']): ?>
+                 <outcomeDeclaration identifier="FEEDBACK" cardinality="single" baseType="identifier"/>
+         <?php endif; ?>
+       </responseDeclaration>
+
+       <itemBody>
+               <choiceInteraction responseIdentifier="RESPONSE<?php echo $this->row['question_id']; ?>" shuffle="false" maxChoices="1">
+                       <prompt><?php echo $this->row['question']; ?></prompt>
+                       <simpleChoice identifier="ChoiceT" fixed="true"><?php echo _AT('true'); ?></simpleChoice> 
+                       <simpleChoice identifier="ChoiceF" fixed="true"><?php echo _AT('false'); ?></simpleChoice> 
+         </choiceInteraction>
+       </itemBody>
+
+       <?php if ($this->row['feedback']): ?>
+               <modalFeedback outcomeIdentifier="FEEDBACK" identifier="FEEDBACK" showHide="hide"><?php echo $this->row['feedback']; ?></modalFeedback> 
+       <?php endif; ?>
+</assessmentItem>
\ No newline at end of file
diff --git a/themes/default/test_questions/truefalse_result.tmpl.php b/themes/default/test_questions/truefalse_result.tmpl.php
new file mode 100644 (file)
index 0000000..b9213fe
--- /dev/null
@@ -0,0 +1,36 @@
+<p><?php echo AT_print($this->row['question'], 'tests_questions.question'); ?></p>
+
+<p>
+       <?php if (($this->row['answer_0'] == 1) && ($this->answers == 1)): ?>
+               <img src="<?php echo $this->base_path; ?>images/checkmark.gif" alt="<?php echo _AT('correct_answer'); ?>" title="<?php echo _AT('correct_answer'); ?>" height="16" width="16" style="vertical-align: middle" />
+       <?php elseif ($this->row['answer_0'] == 1): ?>
+               <img src="<?php echo $this->base_path; ?>images/x.gif" alt="<?php echo _AT('wrong_answer'); ?>" title="<?php echo _AT('wrong_answer'); ?>" height="16" width="16" style="vertical-align: middle" />
+       <?php else: ?>
+               <img src="<?php echo $this->base_path; ?>images/clr.gif" alt="" title="" height="16" width="16" style="vertical-align: middle" />
+       <?php endif; ?>
+
+       <?php if ($this->answers == 1): ?>
+               <img src="<?php echo $this->base_path; ?>images/checkbox_check.gif" alt="<?php echo _AT('checked'); ?>" title="<?php echo _AT('checked'); ?>" height="13" width="13" style="vertical-align: middle" />
+       <?php else: ?>
+               <img src="<?php echo $this->base_path; ?>images/checkbox_empty.gif" alt="<?php echo _AT('unchecked'); ?>" title="<?php echo _AT('unchecked'); ?>" height="13" width="13" style="vertical-align: middle" />
+       <?php endif; ?>
+
+       <?php echo _AT('true'); ?>
+</p>
+
+<p>
+       <?php if (($this->row['answer_0'] == 2) && ($this->answers == 2)): ?>
+               <img src="<?php echo $this->base_path; ?>images/checkmark.gif" alt="<?php echo _AT('correct_answer'); ?>" title="<?php echo _AT('correct_answer'); ?>" height="16" width="16" style="vertical-align: middle" />
+       <?php elseif ($this->row['answer_0'] == 2): ?>
+               <img src="<?php echo $this->base_path; ?>images/x.gif" alt="<?php echo _AT('wrong_answer'); ?>" title="<?php echo _AT('wrong_answer'); ?>" height="16" width="16" style="vertical-align: middle" />
+       <?php else: ?>
+               <img src="<?php echo $this->base_path; ?>images/clr.gif" alt="" title="" height="16" width="16" style="vertical-align: middle" />
+       <?php endif; ?>
+
+       <?php if ($this->answers == 2): ?>
+               <img src="<?php echo $this->base_path; ?>images/checkbox_check.gif" alt="<?php echo _AT('checked'); ?>" title="<?php echo _AT('checked'); ?>" height="13" width="13" style="vertical-align: middle" />
+       <?php else: ?>
+               <img src="<?php echo $this->base_path; ?>images/checkbox_empty.gif" alt="<?php echo _AT('unchecked'); ?>" title="<?php echo _AT('unchecked'); ?>" height="13" width="13" style="vertical-align: middle" />
+       <?php endif; ?>
+       <?php echo _AT('false'); ?>
+</p>
diff --git a/themes/default/test_questions/truefalse_stats.tmpl.php b/themes/default/test_questions/truefalse_stats.tmpl.php
new file mode 100644 (file)
index 0000000..7a58d5f
--- /dev/null
@@ -0,0 +1,31 @@
+<br />
+<table class="data static" summary="" style="width: 95%" rules="cols">
+<thead>
+<tr>
+       <th scope="col" width="40%"><?php echo _AT('question'); ?></th>
+       <th scope="col" nowrap="nowrap"><?php echo _AT('left_blank'); ?></th>
+<?php if ($this->row['answer_0'] == 1): ?>
+       <th scope="col"><?php echo _AT('true'); ?><img src="images/checkmark.gif" alt="Correct checkmark" /></th>
+       <th scope="col"><?php echo _AT('false'); ?></th>
+<?php elseif ($this->row['answer_0'] == 2): ?>
+       <th scope="col"><?php echo _AT('true'); ?></th>
+       <th scope="col"><?php echo _AT('false'); ?><img src="images/checkmark.gif" alt="Correct checkmark" /></th>
+<?php else: ?>
+       <th scope="col"><?php echo _AT('true'); ?></th>
+       <th scope="col"><?php echo _AT('false'); ?></th>
+<?php endif; ?>
+</tr>
+</thead>
+<tr>
+       <td valign="top" rowspan="2"><?php echo $this->row['question']; ?></td>
+       <td align="center" valign="top"><?php echo $this->num_blanks; ?> / <?php echo $this->num_results; ?></td>
+       <td align="center" valign="top"><?php echo $this->num_true; ?> / <?php echo $this->num_results; ?></td>
+       <td align="center" valign="top"><?php echo $this->num_false; ?> / <?php echo $this->num_results; ?></td>
+</tr>
+<tr>
+       <td align="center" valign="top"><div class="qstat_bar-border"><div class="qstat_bar-bar"><div class="qstat_bar-fill" style="height:<?php echo 100-($this->num_results ? round($this->num_blanks/$this->num_results*100) : 0); ?>%;"></div></div></div><?php echo $this->num_results ? round($this->num_blanks/$this->num_results*100) : 0; ?>%</td>
+       <td align="center" valign="top"><div class="qstat_bar-border"><div class="qstat_bar-bar"><div class="qstat_bar-fill" style="height:<?php echo 100-($this->num_results ? round($this->num_true/$this->num_results*100) : 0); ?>%;"></div></div></div><?php echo $this->num_results ? round($this->num_true/$this->num_results*100) : 0; ?>%</td>
+  <td align="center" valign="top"><div class="qstat_bar-border"><div class="qstat_bar-bar"><div class="qstat_bar-fill" style="height:<?php echo 100-($this->num_results ? round($this->num_false/$this->num_results*100) : 0); ?>%;"></div></div></div><?php echo $this->num_results ? round($this->num_false/$this->num_results*100) : 0; ?>%</td>
+</tr>
+</table>
+
diff --git a/themes/default/theme.cfg.php b/themes/default/theme.cfg.php
new file mode 100644 (file)
index 0000000..a812bee
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+
+// $Id: theme.cfg.php 2813 2004-12-12 15:37:46Z greg $
+
+/* This is the default configuration file for the default theme. */
+
+/* The theme's name. */
+       $_theme['name'] = 'Default 1.6';
+
+/* The theme's version number. */
+       $_theme['version'] = '0.1';
+
+/* Which version of ATutor is this theme intended for. */
+       $_theme['atutor-version'] = '1.6';
+
+/* author information */
+       $_theme['author_name']  = 'ATutor';
+       $_theme['author_url']   = 'http://atutor.ca';
+       $_theme['author_email'] = '';
+
+/* theme default course banner styles: */
+       $_theme['banner']['font-family'] = 'Verdana, Arial, sans-serif';
+       $_theme['banner']['font-weight'] = 'bold';
+       $_theme['banner']['color']       = 'black';
+       $_theme['banner']['font-size']   = 'xx-large';
+       $_theme['banner']['text-align']  = 'center';
+
+       $_theme['banner']['background-color'] = 'white';
+       $_theme['banner']['background-image'] = '';
+       $_theme['banner']['vertical-align']   = 'middle';
+       $_theme['banner']['padding']          = '3px';
+
+?>
diff --git a/themes/default/theme_info.xml b/themes/default/theme_info.xml
new file mode 100644 (file)
index 0000000..76da602
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="EN"?>\r
+<!--This is an ATutor Theme Generator document-->\r
+<!--Created from the ATutor Themes Export Generator-->\r
+\r
+<theme>\r
+       <title>Default</title>\r
+       <version>1.0</version>\r
+       <last_updated>2008-02-12</last_updated>\r
+       <extra_info>plone-like.</extra_info>\r
+</theme>\r
+\r
diff --git a/themes/default/users/browse.tmpl.php b/themes/default/users/browse.tmpl.php
new file mode 100644 (file)
index 0000000..76a7ebc
--- /dev/null
@@ -0,0 +1,87 @@
+<?php require(AT_INCLUDE_PATH.'header.inc.php'); ?>\r
+\r
+<div id="browse">\r
+       <div style="white-space:nowrap; padding-right:30px;">\r
+\r
+                       <!--h3><?php echo _AT('cats_categories'); ?></h3>\r
+\r
+                       <ul class="browse-list">\r
+                               <?php \r
+                               foreach ($this->cats as $cat_id => $cat_name): \r
+                                       echo '<li>';\r
+                                       if ($cat_id == $this->cat): ?>\r
+                                               <div class="browse-selected">\r
+                                       <?php else: ?>\r
+                                               <div class="browse-unselected">\r
+                                       <?php endif; ?>\r
+                                                       <a href="<?php echo $_SERVER['PHP_SELF'].'?cat='.$cat_id; ?>#courses"><?php echo $cat_name ?></a>    \r
+                                               </div>\r
+                                       </li>\r
+                               <?php endforeach; ?>            \r
+                       </ul>                   <br /-->\r
+       </div>\r
+       <a name="courses"></a>\r
+       <!--div style="float: left; white-space:nowrap; padding-right:30px;">\r
+                       <h3><?php echo _AT('courses').': '.$this->cats[$this->cat]; ?></h3>\r
+\r
+                       <?php if (isset($this->courses)):\r
+                               $cur_sub_cat = ''; ?>\r
+\r
+                               <ul class="browse-list">\r
+                                       <li>\r
+                                       <?php if ($this->show_course == 0): ?>\r
+                                               <div class="browse-selected">\r
+                                       <?php else: ?>\r
+                                               <div class="browse-unselected">\r
+                                       <?php endif; ?>\r
+                                               <a href="<?php echo $_SERVER['PHP_SELF']; ?>?cat=0<?php echo SEP;?>show_course=0#info"><?php echo _AT('all_courses'); ?></a>\r
+                                       </div>                  \r
+                                       </li>\r
+                                       \r
+                                       <?php foreach ($this->courses as $course_id=>$info):\r
+                                               if (isset($this->sub_cats) && array_key_exists($info['cat_id'], $this->sub_cats) && ($cur_sub_cat != $this->sub_cats[$info['cat_id']])):\r
+                                                       $cur_sub_cat = $this->sub_cats[$info['cat_id']];?>\r
+                                                       </ul><br /><h4><?php echo $cur_sub_cat; ?></h4><ul class="browse-list">\r
+                                               <?php endif; ?>\r
+                                               <li>\r
+                                               <?php if ($info['selected']): ?>\r
+                                                       <div class="browse-selected">\r
+                                               <?php else: ?>\r
+                                                       <div class="browse-unselected">\r
+                                               <?php endif; ?>\r
+                                                       <a href="<?php echo $info['url']; ?>"><?php echo $info['title']; ?></a>\r
+                                               </div>\r
+                                               </li>\r
+\r
+                                       <?php endforeach; ?>\r
+                               </ul>\r
+                       <?php else:\r
+                               echo _AT('no_courses');\r
+                       endif;?>\r
+                       <br />\r
+       </div-->\r
+\r
+       <ul style=" padding: 0px; margin: 0px">\r
+       <?php foreach ($this->course_row as $this->course_row): ?>\r
+               <li style="list-style: none; width: 80%">\r
+                       <dl id="public-profile">\r
+                               <dd><h3><a href="bounce.php?course=<?php echo $this->course_row['course_id']; ?>"><?php echo $this->course_row['title']; ?></a></h3></dd>\r
+                               \r
+                               <dt><?php echo _AT('description'); ?></dt>\r
+                               <dd><?php echo $this->course_row['description']; ?>&nbsp;</dd>\r
+\r
+                               <dt><?php echo _AT('category'); ?></dt>\r
+                               <dd><?php echo $this->cats[$this->course_row['cat_id']]; ?>&nbsp;</dd>\r
+                               \r
+                               <dt><?php echo _AT('instructor'); ?></dt>\r
+                               <dd><a href="<?php echo AT_BASE_HREF; ?>contact_instructor.php?id=<?php echo $this->course_row['course_id']; ?>"><?php echo get_display_name($this->course_row['member_id']); ?></a></dd>\r
+\r
+                               <dt><?php echo _AT('access'); ?></dt>\r
+                               <dd><?php echo _AT($this->course_row['access']); ?></dd>\r
+                       </dl>\r
+               </li>\r
+       <?php endforeach; ?>\r
+       </ul>\r
+</div>\r
+<br />\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/themes/default/users/email_change.tmpl.php b/themes/default/users/email_change.tmpl.php
new file mode 100644 (file)
index 0000000..b85510a
--- /dev/null
@@ -0,0 +1,39 @@
+<?php 
+global $onload;
+$onload = 'document.form.form_password.focus();';
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+?>
+
+<script language="JavaScript" type="text/javascript" src="sha-1factory.js"></script>
+
+<script type="text/javascript">
+function encrypt_password()
+{
+       document.form.form_password_hidden.value = hex_sha1(document.form.form_password.value);
+       document.form.form_password.value = "";
+}
+</script>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+       <input type="hidden" name="form_password_hidden" value="" />
+
+       <div class="input-form" style="max-width: 400px;">
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="form_password"><?php echo _AT('password'); ?></label><br />
+                       <input id="form_password" name="form_password" type="password" size="15" maxlength="15" value="" /><br />
+               </div>
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="email"><?php echo _AT('email_address'); ?></label><br />
+                       <input id="email" name="email" type="text" size="50" maxlength="50" value="<?php echo stripslashes(htmlspecialchars($_POST['email'])); ?>" />
+               </div>
+
+               <div class="row buttons">
+                       <input type="submit" name="submit" value="<?php echo _AT('submit'); ?>" onClick="encrypt_password()" />
+                       <input type="submit" name="cancel" value=" <?php echo _AT('cancel'); ?> " />
+               </div>
+       </div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/themes/default/users/index.tmpl.php b/themes/default/users/index.tmpl.php
new file mode 100644 (file)
index 0000000..c57f173
--- /dev/null
@@ -0,0 +1,92 @@
+<?php require(AT_INCLUDE_PATH.'header.inc.php'); ?>
+
+<?php if (!$this->courses && get_instructor_status()): ?>
+       <?php global $msg; $msg->printInfos('NO_COURSES_INST'); ?>
+<?php elseif (!$this->courses): ?>
+       <?php global $msg; $msg->printInfos('NO_COURSES'); ?>
+<?php endif; ?>
+
+<?php foreach ($this->courses as $row):?>      
+       <div class="course">
+               <div style="font-size:smaller;" align="right"><?php
+                       $link  = '<a href="'.url_rewrite('bounce.php?course=' . $row['course_id']) . '">';
+                       $link2 = '</a>';
+
+                       if ($_SESSION['member_id'] == $row['member_id']) {
+                               //if instructor
+                               echo _AT('instructor');
+                       } else if ($row['approved'] == 'a') {
+                               //if alumni
+                               echo _AT('alumni');
+                       } else if ($row['approved'] == 'n') {
+                               //if notenrolled
+                               echo _AT('pending_approval');
+                               $link  = $link2 = "";
+                       } else {
+                               //if no role and enrolled
+                               echo _AT('student1');
+                       } ?>
+               </div>
+                       <div class="body">
+                               <?php if ($row['icon'] == ''): ?>
+                                               <img src="images/clr.gif" class="icon" border="0" width="79" height="79" alt="" />
+                               <?php else: 
+                                               echo $link;  
+
+               $sql2="SELECT icon from ".TABLE_PREFIX."courses WHERE course_id='$row[course_id]'";
+                               $result2 = mysql_query($sql2, $db);
+                               
+                               while($row2=mysql_fetch_assoc($result2)){
+                                       $filename = $row2['icon'];
+                               }
+               
+                $path = AT_CONTENT_DIR .$row['course_id'].'/custom_icons/'.$filename;
+                
+                if (file_exists($path)) {
+                    if (defined('AT_FORCE_GET_FILE')) {
+                        $dir = 'get_course_icon.php?id='.$row['course_id'];
+                    } else {
+                        $dir = 'content/' . $_SESSION['course_id'] . '/'.$row['icon'];
+                    }
+                } else {
+                       $dir = "images/courses/".$row['icon'];
+                }
+                ?>
+                               <img src="<?php echo $dir; ?>" class="icon" border="0" alt="" />
+                                       <?php echo $link2; ?>
+                               <?php endif; ?>
+
+                               <strong><?php echo $link.$row['title'].$link2; ?></strong>
+
+                               <?php if ($row['member_id'] != $_SESSION['member_id']): ?>
+                                       - <a href="users/remove_course.php?course=<?php echo $row['course_id']; ?>"><?php echo _AT('unenroll_me'); ?></a>
+                               <?php endif; ?>
+
+                               <br />
+                               <p>
+                                       <small><?php echo _AT('instructor');?>: <?php echo get_display_name($row['member_id']); ?>
+                                       <?php echo ' - <a href="'. AT_BASE_HREF.'inbox/send_message.php?id='.$row['member_id'].'">'._AT('send_message').'</a>'; ?>
+                                       <br />
+                                       <?php echo _AT('category'); ?>: <?php echo get_category_name($row['cat_id']); ?><br />
+                                       
+                                       
+                                       <?php if ($row['tests']): ?>
+                                               <?php echo _AT('tests'); ?>: 
+                                               <?php foreach ($row['tests'] as $test): ?>
+                                                       <a href="bounce.php?course=<?php echo $row['course_id'].SEP.'p='.urlencode('tools/test_intro.php?tid='.$test['test_id']); ?>"><?php echo $test['title']; ?></a> 
+                                               <?php endforeach ;?>
+                                       <?php endif; ?>
+                               </small>
+                               </p>
+
+                               <?php if ($row['last_cid']): ?>
+                                       <div class="shortcuts">
+                                               <small><a href="bounce.php?course=<?php echo $row['course_id'].SEP.'p='.urlencode('content.php?cid='.$row['last_cid']); ?>"><?php echo _AT('resume'); ?></a></small>
+                                       </div>
+                               <?php endif; ?>
+                       </div>
+       </div>
+<?php endforeach; ?>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/themes/default/users/password_change.tmpl.php b/themes/default/users/password_change.tmpl.php
new file mode 100644 (file)
index 0000000..8c4a012
--- /dev/null
@@ -0,0 +1,66 @@
+<?php 
+global $onload;
+$onload = 'document.form.old_password.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+?>
+
+<script language="JavaScript" src="sha-1factory.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+function encrypt_password()
+{
+       document.form.password_error.value = "";
+
+       document.form.form_old_password_hidden.value = hex_sha1(document.form.old_password.value);
+       document.form.old_password.value = "";
+
+       // verify new password
+       err = verify_password(document.form.password.value, document.form.password2.value);
+       
+       if (err.length > 0)
+       {
+               document.form.password_error.value = err;
+       }
+       else
+       {
+               document.form.form_password_hidden.value = hex_sha1(document.form.password.value);
+               document.form.password.value = "";
+               document.form.password2.value = "";
+       }
+}
+</script>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+       <input type="hidden" name="form_change" value="true" />
+       <input name="password_error" type="hidden" />
+       <input type="hidden" name="form_old_password_hidden" value="" />
+       <input type="hidden" name="form_password_hidden" value="" />
+
+       <div class="input-form" style="max-width: 400px;">
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="old_password"><?php echo _AT('password_old'); ?></label><br />
+                       <input id="old_password" name="old_password" type="password" size="15" maxlength="15" /><br />
+               </div>
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="password"><?php echo _AT('password'); ?></label><br />
+                       <input id="password" name="password" type="password" size="15" maxlength="15" /><br />
+                       <small>&middot; <?php echo _AT('combination'); ?><br />
+                                  &middot; <?php echo _AT('15_max_chars'); ?></small>
+               </div>
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="password2"><?php echo _AT('password_again'); ?></label><br />
+                       <input id="password2" name="password2" type="password" size="15" maxlength="15" />
+               </div>
+
+               <div class="row buttons">
+                       <input type="submit" name="submit" value="<?php echo _AT('submit'); ?>" onClick="encrypt_password()" /> 
+                       <input type="submit" name="cancel" value=" <?php echo _AT('cancel'); ?> " />
+               </div>
+       </div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/themes/default/users/preferences.tmpl.php b/themes/default/users/preferences.tmpl.php
new file mode 100644 (file)
index 0000000..f42675a
--- /dev/null
@@ -0,0 +1,123 @@
+<?php require(AT_INCLUDE_PATH.'header.inc.php'); ?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get" name="prefs">
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('preferences'); ?></legend>
+       <div class="row">
+               <?php if (defined('AT_ENABLE_CATEGORY_THEMES') && AT_ENABLE_CATEGORY_THEMES): ?>
+                       <?php echo _AT('themes_disabled'); ?>
+               <?php else: ?>
+                       <label for="theme"><?php echo _AT('theme'); ?></label><br />
+                               <select name="theme" id="theme"><?php
+                                                       $_themes = get_enabled_themes();
+                                                       
+                                                       foreach ($_themes as $theme) {
+                                                               if (!$theme) {
+                                                                       continue;
+                                                               }
+
+                                                               $theme_fldr = get_folder($theme);
+
+                                                               if ($theme_fldr == $_SESSION['prefs']['PREF_THEME']) {
+                                                                       echo '<option value="'.$theme_fldr.'" selected="selected">'.$theme.'</option>';
+                                                               } else {
+                                                                       echo '<option value="'.$theme_fldr.'">'.$theme.'</option>';
+                                                               }
+                                                       }
+                                               ?>
+                               </select>
+               <?php endif; ?>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('inbox_notification'); ?><br />
+               <?php
+                       $yes = $no  = '';
+                       if ($this->notify == 1) {
+                               $yes = ' checked="checked"';
+                       } else {
+                               $no  = ' checked="checked"';
+                       }
+               ?>
+               <input type="radio" name="mnot" id="mnot_yes" value="1" <?php echo $yes; ?> /><label for="mnot_yes"><?php echo _AT('enable'); ?></label> 
+               <input type="radio" name="mnot" id="mnot_no" value="0" <?php echo $no; ?> /><label for="mnot_no"><?php echo _AT('disable'); ?></label>          
+       </div>
+
+       <div class="row">
+               <?php echo _AT('show_numbers');  ?><br />
+               <?php
+                       $num = $num2 = '';
+                       if ($_SESSION['prefs']['PREF_NUMBERING'] == 1) {
+                               $num = ' checked="checked"';
+                       } else {
+                               $num2 = ' checked="checked"';
+                       }
+                       ?><input type="radio" name ="numbering" id="num_en" value="1" <?php echo $num; ?> /><label for="num_en"><?php echo _AT('enable');  ?></label> 
+                       <input type="radio" name ="numbering" id="num_dis" value="0" <?php echo $num2; ?> /><label for="num_dis"><?php echo _AT('disable');  ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('jump_redirect'); ?><br />
+               <?php
+                       $num = $num2 = '';
+                       if ($_SESSION['prefs']['PREF_JUMP_REDIRECT'] == 1) {
+                               $num = ' checked="checked"';
+                       } else {
+                               $num2 = ' checked="checked"';
+                       }
+                       ?><input type="radio" name ="use_jump_redirect" id="jump_en" value="1" <?php echo $num; ?> /><label for="jump_en"><?php echo _AT('enable');  ?></label> 
+                       <input type="radio" name ="use_jump_redirect" id="jump_dis" value="0" <?php echo $num2; ?> /><label for="jump_dis"><?php echo _AT('disable');  ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('auto_login1');  ?><br /><?php
+                       $auto_en = $auto_dis = '';
+                       if ( !empty($_COOKIE['ATLogin']) && !empty($_COOKIE['ATPass']) ) {
+                               $auto_en = 'checked="checked"';
+                       } else {
+                               $auto_dis = 'checked="checked"';
+                       }
+               ?><input type="radio" name ="auto" id="auto_en" value="enable" <?php echo $auto_en; ?> /><label for="auto_en"><?php echo _AT('enable');  ?></label> 
+               <input type="radio" name ="auto" id="auto_dis" value="disable" <?php echo $auto_dis; ?> /><label for="auto_dis"><?php echo _AT('disable');  ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('form_focus');  ?><br />
+               <?php
+                       $num = $num2 = '';
+                       if ($_SESSION['prefs']['PREF_FORM_FOCUS'] == 1) {
+                               $num = ' checked="checked"';
+                       } else {
+                               $num2 = ' checked="checked"';
+                       }
+                       ?><input type="radio" name ="form_focus" id="focus_on" value="1" <?php echo $num; ?> /><label for="focus_on"><?php echo _AT('enable');  ?></label> 
+                       <input type="radio" name ="form_focus" id="focus_off" value="0" <?php echo $num2; ?> /><label for="focus_off"><?php echo _AT('disable');  ?></label>
+       </div>
+
+       <div class="row">
+               <?php
+                       $num0 = $num1 = $num2 = '';
+                       if ($_SESSION['prefs']['PREF_CONTENT_EDITOR'] == 1) {
+                               $num1 = ' checked="checked"';
+                       } else if ($_SESSION['prefs']['PREF_CONTENT_EDITOR'] == 2) {
+                               $num2 = ' checked="checked"';
+                       } else {
+                               $num0 = ' checked="checked"';
+                       }
+               ?>
+               <?php echo _AT('content_editor'); ?><br />
+               <input type="radio" name="content_editor" id="ce_0" value="0" <?php echo $num0; ?>/><label for="ce_0"><?php echo _AT('plain_text');?></label>
+               <input type="radio" name="content_editor" id="ce_1" value="1" <?php echo $num1; ?>/><label for="ce_1"><?php echo _AT('html'); ?></label>
+               <input type="radio" name="content_editor" id="ce_2" value="2" <?php echo $num2; ?>/><label for="ce_2"><?php echo _AT('html') . ' - '. _AT('visual_editor'); ?></label>
+       </div>
+</fieldset>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('apply'); ?>" accesskey="s" />
+               <input type="reset" name="reset" value="<?php echo _AT('reset'); ?>" />
+       </div>
+       
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/themes/default/users/profile.tmpl.php b/themes/default/users/profile.tmpl.php
new file mode 100644 (file)
index 0000000..109fd65
--- /dev/null
@@ -0,0 +1,132 @@
+<?php require(AT_INCLUDE_PATH.'header.inc.php'); ?>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">
+<?php global $languageManager, $_config; ?>
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('required_information'); ?></legend>
+       <div class="row">
+               <h3><?php echo _AT('required_information'); ?></h3>
+       </div>
+
+       <div class="row">
+               <label for="login"><?php echo _AT('login_name'); ?></label><br />
+                               <span id="login"><?php echo stripslashes(htmlspecialchars($_POST['login'])); ?></span>
+                               <input name="member_id" type="hidden" value="<?php echo intval($_POST['member_id']); ?>" />
+                               <input name="login" type="hidden" value="<?php echo stripslashes(htmlspecialchars($_POST['login'])); ?>" />
+       </div>
+       <div class="row">
+               <?php echo _AT('email_address'); ?><br />
+               <?php echo stripslashes(htmlspecialchars($_POST['email'])); ?>
+               <input type="checkbox" id="priv" name="private_email" value="1" <?php if ($_POST['private_email']) { echo 'checked="checked"'; } ?> /><label for="priv"><?php echo _AT('keep_email_private');?></label>
+       </div>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="first_name"><?php echo _AT('first_name'); ?></label><br />
+               <input id="first_name" name="first_name" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['first_name'])); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="second_name"><?php echo _AT('second_name'); ?></label><br />
+               <input id="second_name" name="second_name" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['second_name'])); ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="last_name"><?php echo _AT('last_name'); ?></label><br />
+               <input id="last_name" name="last_name" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['last_name'])); ?>" />
+       </div>
+       
+       <?php if (admin_authenticate(AT_ADMIN_PRIV_USERS, TRUE)): 
+                       if ($_POST['status'] == AT_STATUS_INSTRUCTOR) {
+                               $inst = ' checked="checked"';
+                       } else if ($_POST['status'] == AT_STATUS_STUDENT) {
+                               $stud = ' checked="checked"';
+                       }  else if ($_POST['status'] == AT_STATUS_DISABLED) {
+                               $disa = ' checked="checked"';
+                       } else {
+                               $uncon = ' checked="checked"';
+                       }?>
+                       <input type="hidden" name="id" value="<?php echo $_POST['member_id']; ?>" >
+                       <div class="row">
+                               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><?php echo _AT('account_status'); ?><br />
+
+                               <input type="radio" name="status" value="0" id="disa" <?php echo $disa; ?> /><label for="disa"><?php echo _AT('disabled'); ?></label>
+                               <?php if (defined('AT_EMAIL_CONFIRMATION') && AT_EMAIL_CONFIRMATION): ?>
+                                       <input type="radio" name="status" value="1" id="uncon" <?php echo $uncon; ?> /><label for="uncon"><?php echo _AT('unconfirmed'); ?></label>
+                               <?php endif; ?>
+
+                               <input type="radio" name="status" value="2" id="stud" <?php echo $stud; ?> /><label for="stud"><?php echo _AT('student'); ?></label>
+
+                               <input type="radio" name="status" value="3" id="inst" <?php echo $inst; ?> /><label for="inst"><?php echo _AT('instructor'); ?></label>
+
+                               <input type="hidden" name="old_status" value="<?php echo $_POST['old_status']; ?>" />
+                       </div>
+       <?php endif; ?>
+       </fieldset>
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('personal_information'); ?></legend>
+       <div class="row">
+               <h3><?php echo _AT('personal_information').' ('._AT('optional').')'; ?></h3>
+       </div>
+
+       <?php if (admin_authenticate(AT_ADMIN_PRIV_USERS, TRUE) && defined('AT_MASTER_LIST') && AT_MASTER_LIST): ?>
+               <div class="row">
+                       <label for="student_id"><?php echo _AT('student_id'); ?></label><br />
+                               <input type="text" name="student_id" value="<?php echo $_POST['student_id']; ?>" size="20" /><br />
+               </div>
+               <div class="row">
+                       <label for="student_pin"><?php echo _AT('student_pin'); ?></label><br />
+                       <input id="student_pin" name="student_pin" type="password" size="15" maxlength="15" value="<?php echo stripslashes(htmlspecialchars($_POST['student_pin'])); ?>" /><br />
+               </div>
+       <?php endif; ?>
+
+       <div class="row">
+               <?php echo _AT('date_of_birth'); ?><br />
+               <label for="year"><?php echo _AT('year'); ?>: </label><input id="year" class="formfield" name="year" type="text" size="4" maxlength="4" value="<?php echo $_POST['year']; ?>" />  <label for="month"><?php echo _AT('month'); ?>: </label><input id="month" class="formfield" name="month" type="text" size="2" maxlength="2" value="<?php echo $_POST['month']; ?>" /> <label for="day"><?php echo _AT('day'); ?>: </label><input id="day" class="formfield" name="day" type="text" size="2" maxlength="2" value="<?php echo $_POST['day']; ?>" />
+       </div>
+
+       <div class="row">
+               <?php echo _AT('gender'); ?><br />
+               <input type="radio" name="gender" id="m" value="m" <?php if ($_POST['gender'] == 'm') { echo 'checked="checked"'; } ?> /><label for="m"><?php echo _AT('male'); ?></label> <input type="radio" value="f" name="gender" id="f" <?php if ($_POST['gender'] == 'f') { echo 'checked="checked"'; } ?> /><label for="f"><?php echo _AT('female'); ?></label>  <input type="radio" value="n" name="gender" id="ns" <?php if (($_POST['gender'] == 'n') || ($_POST['gender'] == '')) { echo 'checked="checked"'; } ?> /><label for="ns"><?php echo _AT('not_specified'); ?></label>
+       </div>
+
+       <div class="row">
+               <label for="address"><?php echo _AT('street_address'); ?></label><br />
+               <input id="address" name="address" size="40" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['address'])); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="postal"><?php echo _AT('postal_code'); ?></label><br />
+               <input id="postal" name="postal" size="7" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['postal'])); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="city"><?php echo _AT('city'); ?></label><br />
+               <input id="city" name="city" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['city'])); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="province"><?php echo _AT('province'); ?></label><br />
+               <input id="province" name="province" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['province'])); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="country"><?php echo _AT('country'); ?></label><br />
+               <input id="country" name="country" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['country'])); ?>" />
+       </div>
+
+       <div class="row">
+               <label for="phone"><?php echo _AT('phone'); ?></label><br />
+               <input size="11" name="phone" type="text" value="<?php echo stripslashes(htmlspecialchars($_POST['phone'])); ?>" id="phone" />
+       </div>
+
+       <div class="row">
+               <label for="website"><?php echo _AT('web_site'); ?></label><br />
+               <input id="website" name="website" size="40" type="text" value="<?php if ($_POST['website'] == '') { echo 'http://'; } else { echo stripslashes(htmlspecialchars($_POST['website'])); } ?>" />
+       </div>
+       </fieldset>
+       <div class="row buttons">
+               <input type="submit" name="submit" value=" <?php echo _AT('save'); ?> " accesskey="s" />
+               <input type="submit" name="cancel" value=" <?php echo _AT('cancel'); ?> " />
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/themes/default/warningmessage.tmpl.php b/themes/default/warningmessage.tmpl.php
new file mode 100644 (file)
index 0000000..c8ed8da
--- /dev/null
@@ -0,0 +1,20 @@
+<?php  
+/*
+ * @author Jacek Materna
+ *
+ *     One Savant variable: $item which is the processed ouput message content according to lang spec.
+ */
+ global $_base_href;
+?>
+
+<div id="warning">
+       <?php if (is_array($this->item)) : ?>
+               <ul>
+               <?php foreach($this->item as $e) : ?>
+                       <li><?php echo $e; ?></li>
+               <?php endforeach; ?>
+               </ul>
+       <?php endif; ?>
+</div>
\ No newline at end of file
diff --git a/themes/default15/confirmmessage.tmpl.php b/themes/default15/confirmmessage.tmpl.php
new file mode 100644 (file)
index 0000000..17ffdcf
--- /dev/null
@@ -0,0 +1,32 @@
+<?php  
+/*
+ * @author Jacek Materna
+ *
+ *     One Savant variable: $item which is the processed ouput message content according to lang spec.
+ */
+ global $_base_href;
+// header
+?>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<?php if(isset($this->hidden_vars)): ?>
+       <?php echo $this->hidden_vars; ?>
+<?php endif; ?>
+
+<div class="input-form">
+       <div class="row">
+               <?php if (is_array($this->item)) : ?>
+                       <?php foreach($this->item as $e) : ?>
+                               <p><?php echo $e; ?></p>
+                       <?php endforeach; ?>
+               <?php endif; ?>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit_yes" value="<?php echo _AT('submit_yes'); ?>" /> 
+               <input type="submit" name="submit_no" value="<?php echo _AT('submit_no'); ?>" />
+       </div>
+</div>
+</form>
\ No newline at end of file
diff --git a/themes/default15/content.tmpl.php b/themes/default15/content.tmpl.php
new file mode 100644 (file)
index 0000000..5a0f6df
--- /dev/null
@@ -0,0 +1,32 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+if (!defined('AT_INCLUDE_PATH')) { exit; } ?>\r
+\r
+<?php if ($this->shortcuts): ?>\r
+<fieldset id="shortcuts"><legend><?php echo _AT('shortcuts'); ?></legend>\r
+       <ul>\r
+               <?php foreach ($this->shortcuts as $link): ?>\r
+                       <li><a href="<?php echo $link['url']; ?>"><?php echo $link['title']; ?></a></li>\r
+               <?php endforeach; ?>\r
+       </ul>\r
+</fieldset>\r
+<?php endif; ?>\r
+\r
+\r
+<div id="content-text">\r
+       <?php echo $this->body; ?>\r
+</div>\r
+\r
+<div id="content-info">\r
+       <?php echo $this->content_info; ?>\r
+</div>
\ No newline at end of file
diff --git a/themes/default15/errormessage.tmpl.php b/themes/default15/errormessage.tmpl.php
new file mode 100644 (file)
index 0000000..bea7c63
--- /dev/null
@@ -0,0 +1,21 @@
+<?php 
+/*
+ * @author Jacek Materna
+ *
+ *     One Savant variable: $item which is the processed ouput message content according to lang spec.
+ */
+ global $_base_href;
+// header
+?>
+<div id="error">
+       <h4><?php echo _AT('the_follow_errors_occurred'); ?></h4>
+       <?php if (is_array($this->item)) : ?>
+               <ul>
+               <?php foreach($this->item as $e) : ?>
+                       <li><?php echo $e; ?></li>
+               <?php endforeach; ?>
+               </ul>
+       <?php endif; ?>
+</div>
\ No newline at end of file
diff --git a/themes/default15/feedbackmessage.tmpl.php b/themes/default15/feedbackmessage.tmpl.php
new file mode 100644 (file)
index 0000000..a7214d0
--- /dev/null
@@ -0,0 +1,20 @@
+<?php 
+/*
+ * @author Jacek Materna
+ *
+ *     One Savant variable: $item which is the processed ouput message content according to lang spec.
+ */
+ global $_base_href;
+// header
+?>
+<div id="feedback">
+       <?php if (is_array($this->item)) : ?>
+               <ul>
+               <?php foreach($this->item as $e) : ?>
+                       <li><?php echo $e; ?></li>
+               <?php endforeach; ?>
+               </ul>
+       <?php endif; ?>
+</div>
\ No newline at end of file
diff --git a/themes/default15/forms.css b/themes/default15/forms.css
new file mode 100644 (file)
index 0000000..f7c921e
--- /dev/null
@@ -0,0 +1,124 @@
+div.input-form {\r
+       width: 80%; \r
+       margin-left:auto; \r
+       margin-right:auto;\r
+       border: 1px solid #f0f0f0;\r
+       margin-bottom: 20px;\r
+}\r
+\r
+div.input-form div.row h3 {\r
+       margin-left: 0px;\r
+}\r
+\r
+\r
+div.input-form div.row {\r
+       background-color: #fdfdfd;\r
+       padding:8px;\r
+}\r
+\r
+div.input-form .footer {\r
+       border-top: 1px solid #f0f0f0;\r
+}\r
+\r
+div.input-form p {\r
+       margin-left: 0px;\r
+}\r
+\r
+div.input-form input {\r
+       cursor: pointer;\r
+}\r
+div.input-form textarea {\r
+       border: 1px solid #999;\r
+       width: 98%;\r
+       background-color: white;\r
+       padding: 2px;\r
+       margin-right: 2px;\r
+}\r
+\r
+div.input-form textarea:focus {\r
+       border:1px solid blue;\r
+       background-color: white;\r
+       padding: 2px;\r
+}\r
+\r
+div.input-form input[type=text], div.input-form input[type=password] {\r
+       border: 1px solid #999;\r
+       background-color: white;\r
+       padding: 2px;\r
+       max-width: 60%;\r
+}\r
+\r
+div.input-form input:focus {\r
+       border: 1px solid blue;\r
+       padding: 2px\r
+}\r
+\r
+div.input-form div.buttons {\r
+       text-align: right;\r
+       padding:8px;\r
+}\r
+div.input-form div.buttons input {\r
+       border: 1px solid #999;\r
+       background-color: white;\r
+       padding: 2px;\r
+       padding-left: 10px;\r
+       padding-right: 10px;\r
+       min-width: 100px;\r
+       margin-left: 5px;\r
+}\r
+div.input-form div.buttons input:hover {\r
+       background-color: #f5f5ff;\r
+       border: 1px solid blue;\r
+}\r
+\r
+\r
+/* editor tabs */\r
+table.etabbed-table {\r
+       background-color: white;\r
+}\r
+table.etabbed-table td#left-empty-tab {\r
+       background-color: transparent;\r
+       width: 15px;\r
+       border-bottom: 1px solid #9DAB9A;\r
+}\r
+table.etabbed-table td#right-empty-tab {\r
+       text-align: right;\r
+       background-color: transparent;\r
+       border-bottom: 1px solid #9DAB9A;\r
+       padding-right: 5px;\r
+}\r
+\r
+table.etabbed-table td.tab-spacer {\r
+       background-color: transparent;\r
+       width: 5px;\r
+       border-bottom: 1px solid #9DAB9A;\r
+}\r
+\r
+table.etabbed-table td.tab {\r
+       padding-top: 2px;\r
+       padding-bottom: 2px;\r
+       width: 110px;\r
+       background-color: white;\r
+       border-bottom: 1px solid #9DAB9A;\r
+       border-left: 1px solid #9DAB9A;\r
+       border-top: 1px solid #9DAB9A;\r
+       border-right: 1px solid #9DAB9A;\r
+       font-weight:normal;\r
+       text-align:center;\r
+}\r
+\r
+table.etabbed-table td.selected {\r
+       padding-top: 2px;\r
+       padding-bottom: 2px;\r
+       width: 110px;\r
+       background-color: #fdfdfd;\r
+       border-left: 1px solid #9DAB9A;\r
+       border-top: 1px solid #9DAB9A;\r
+       border-right: 1px solid #9DAB9A;\r
+       font-weight:bold;\r
+       text-align:center;\r
+}\r
+\r
+table.etabbed-table td.tab:hover {\r
+       background-color: #fdfdfd;\r
+}
\ No newline at end of file
diff --git a/themes/default15/ie_styles.css b/themes/default15/ie_styles.css
new file mode 100644 (file)
index 0000000..5767555
--- /dev/null
@@ -0,0 +1,23 @@
+/* IE specific styles */
+
+ul#topnavlist {
+       zoom:100%;
+       margin:0px;
+}
+
+ul#topnavlist li {
+       zoom:100%;
+       padding:0.3em;
+       padding-bottom:0.3em;
+       margin:0px;
+       margin-bottom:-1px;
+}
+
+label {
+       zoom:100%;
+       margin:0px;
+}
+
+table.data tfoot input {
+       min-width:0px;
+}
\ No newline at end of file
diff --git a/themes/default15/images/arrow_ltr.gif b/themes/default15/images/arrow_ltr.gif
new file mode 100644 (file)
index 0000000..90da978
Binary files /dev/null and b/themes/default15/images/arrow_ltr.gif differ
diff --git a/themes/default15/images/back.gif b/themes/default15/images/back.gif
new file mode 100644 (file)
index 0000000..f290f43
Binary files /dev/null and b/themes/default15/images/back.gif differ
diff --git a/themes/default15/images/error-large.gif b/themes/default15/images/error-large.gif
new file mode 100644 (file)
index 0000000..d4ec6c1
Binary files /dev/null and b/themes/default15/images/error-large.gif differ
diff --git a/themes/default15/images/guide.gif b/themes/default15/images/guide.gif
new file mode 100644 (file)
index 0000000..124c24a
Binary files /dev/null and b/themes/default15/images/guide.gif differ
diff --git a/themes/default15/images/instructor.gif b/themes/default15/images/instructor.gif
new file mode 100644 (file)
index 0000000..e31d942
Binary files /dev/null and b/themes/default15/images/instructor.gif differ
diff --git a/themes/default15/images/next.gif b/themes/default15/images/next.gif
new file mode 100644 (file)
index 0000000..9477a7b
Binary files /dev/null and b/themes/default15/images/next.gif differ
diff --git a/themes/default15/images/pen.gif b/themes/default15/images/pen.gif
new file mode 100644 (file)
index 0000000..bff8964
Binary files /dev/null and b/themes/default15/images/pen.gif differ
diff --git a/themes/default15/images/pen2.gif b/themes/default15/images/pen2.gif
new file mode 100644 (file)
index 0000000..1a15c9b
Binary files /dev/null and b/themes/default15/images/pen2.gif differ
diff --git a/themes/default15/images/pencils.jpg b/themes/default15/images/pencils.jpg
new file mode 100644 (file)
index 0000000..aec65bd
Binary files /dev/null and b/themes/default15/images/pencils.jpg differ
diff --git a/themes/default15/images/previous.gif b/themes/default15/images/previous.gif
new file mode 100644 (file)
index 0000000..69c43e7
Binary files /dev/null and b/themes/default15/images/previous.gif differ
diff --git a/themes/default15/images/resume.gif b/themes/default15/images/resume.gif
new file mode 100644 (file)
index 0000000..b80d5eb
Binary files /dev/null and b/themes/default15/images/resume.gif differ
diff --git a/themes/default15/images/side_arrow.gif b/themes/default15/images/side_arrow.gif
new file mode 100644 (file)
index 0000000..c72b458
Binary files /dev/null and b/themes/default15/images/side_arrow.gif differ
diff --git a/themes/default15/images/sort.gif b/themes/default15/images/sort.gif
new file mode 100644 (file)
index 0000000..097d27e
Binary files /dev/null and b/themes/default15/images/sort.gif differ
diff --git a/themes/default15/images/user-star.gif b/themes/default15/images/user-star.gif
new file mode 100644 (file)
index 0000000..e53b7d5
Binary files /dev/null and b/themes/default15/images/user-star.gif differ
diff --git a/themes/default15/images/user.gif b/themes/default15/images/user.gif
new file mode 100644 (file)
index 0000000..2c11019
Binary files /dev/null and b/themes/default15/images/user.gif differ
diff --git a/themes/default15/include/box.tmpl.php b/themes/default15/include/box.tmpl.php
new file mode 100644 (file)
index 0000000..fb049c4
--- /dev/null
@@ -0,0 +1,7 @@
+<?php if (!defined('AT_INCLUDE_PATH')) { exit; } ?>
+
+<br />
+<h4 class="box"><?php echo $this->title; ?></h4>
+<div class="box">
+               <?php echo $this->dropdown_contents; ?>
+</div>
\ No newline at end of file
diff --git a/themes/default15/include/fm_footer.tmpl.php b/themes/default15/include/fm_footer.tmpl.php
new file mode 100644 (file)
index 0000000..d733a1f
--- /dev/null
@@ -0,0 +1,2 @@
+</body>\r
+</html>
\ No newline at end of file
diff --git a/themes/default15/include/fm_header.tmpl.php b/themes/default15/include/fm_header.tmpl.php
new file mode 100644 (file)
index 0000000..79cd999
--- /dev/null
@@ -0,0 +1,41 @@
+<?php\r
+if (!defined('AT_INCLUDE_PATH')) { exit; }\r
+\r
+/* available header.tmpl.php variables:\r
+ *\r
+ * ======================================\r
+ * top_level_pages           array(array('url', 'title'))     the top level pages. ATutor default creates tabs.\r
+ * section_title             string                           the name of the current section. either name of the course, administration, my start page, etc.\r
+ * page_title                string                           the title of the current page.\r
+ * path                      array(array('url', 'title'))     the path to the current page.\r
+ * back_to_page              array('url', 'title')            the link back to the part of the current page, if needed.\r
+ * current_top_level_page    string                           full url to the current top level page in "top_leve_pages"\r
+ * current_sub_level_page    string                           full url to the current sub level page in the "sub_level_pages"\r
+ * sub_level_pages           array(array('url', 'title'))     the sub level pages.\r
+ */\r
+\r
+// will have to be moved to the header.inc.php\r
+global $system_courses;\r
+\r
+?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r
+<html lang="<?php echo $this->lang_code; ?>">\r
+<head>\r
+       <title><?php echo SITE_NAME; ?> : <?php echo $this->page_title; ?></title>\r
+       <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $this->lang_charset; ?>" />\r
+       <meta name="Generator" content="ATutor - Copyright 2005 by http://atutor.ca" />\r
+       <base href="<?php echo $this->content_base_href; ?>" />\r
+       <link rel="shortcut icon" href="<?php echo $this->base_path; ?>favicon.ico" type="image/x-icon" />\r
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/print.css" type="text/css" media="print" />\r
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/styles.css" type="text/css" />\r
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/forms.css" type="text/css" />\r
+       <?php echo $this->rtl_css; ?>\r
+       <style type="text/css"><?php echo $this->banner_style; ?></style>\r
+       <?php if ($system_courses[$_SESSION['course_id']]['rss']): ?>\r
+       <link rel="alternate" type="application/rss+xml" title="<?php echo SITE_NAME; ?> - RSS 2.0" href="<?php echo $this->base_href; ?>get_rss.php?<?php echo $_SESSION['course_id']; ?>-2" />\r
+       <link rel="alternate" type="application/rss+xml" title="<?php echo SITE_NAME; ?> - RSS 1.0" href="<?php echo $this->base_href; ?>get_rss.php?<?php echo $_SESSION['course_id']; ?>-1" />\r
+       <?php endif; ?>\r
+</head>\r
+<body onload="<?php echo $this->onload; ?>"><div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>\r
+<br /><br /><div align="right"><a href="javascript:window.close()"><?php echo _AT('close_file_manager'); ?></a></div>\r
+<a name="content"></a>\r
+<?php global $msg; $msg->printAll(); ?>
\ No newline at end of file
diff --git a/themes/default15/include/footer.tmpl.php b/themes/default15/include/footer.tmpl.php
new file mode 100644 (file)
index 0000000..e8c99a0
--- /dev/null
@@ -0,0 +1,46 @@
+<?php if (!defined('AT_INCLUDE_PATH')) { exit; } ?>
+
+       <?php if ($_SESSION['course_id'] > 0): ?>
+               
+               <div align="right" style="clear: left;" id="gototop">
+                       <br />
+                       <span style="font-size:smaller;padding-right:3px;"><a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#content" title="<?php echo _AT('goto_content'); ?> Alt-c"><?php echo _AT('goto_top'); ?></a>   </span>
+               </div>  
+
+       <?php endif; ?> 
+
+       </td>
+       <?php if (($_SESSION['course_id'] > 0) && $this->side_menu): ?>
+               <td valign="top" style="width: 25%">
+               <script type="text/javascript">
+               //<![CDATA[
+               var state = getcookie("side-menu");
+               if (state && (state == 'none')) {
+                       document.writeln('<a name="menu"></a><div style="display:none;" id="side-menu">');
+               } else {
+                       document.writeln('<a name="menu"></a><div style="" id="side-menu">');
+               }
+               //]]>
+               </script>
+                       <?php foreach ($this->side_menu as $dropdown_file): ?>
+                               <?php if (file_exists($dropdown_file)) { require($dropdown_file); } ?>
+                       <?php endforeach; ?>
+               <script type="text/javascript">
+               //<![CDATA[
+                       document.writeln('</div>');
+               //]]>
+               </script>
+               </td>
+       <?php endif; ?>
+</tr>
+<tr>
+       <td colspan="2">
+               <br /><br />
+               <?php require(AT_INCLUDE_PATH.'html/languages.inc.php'); ?>
+               <?php require(AT_INCLUDE_PATH.'html/copyright.inc.php'); ?>
+               <br />
+       </td>
+</tr>
+</table>
+</body>
+</html>
\ No newline at end of file
diff --git a/themes/default15/include/header.tmpl.php b/themes/default15/include/header.tmpl.php
new file mode 100644 (file)
index 0000000..55ad428
--- /dev/null
@@ -0,0 +1,330 @@
+<?php
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+/* available header.tmpl.php variables:
+ * $this->lang_code                    the ISO language code
+ * SITE_NAME                           the site name from the config file
+ * $this->page_title           the name of this page to use in the <title>
+ * $this->lang_charset         the ISO language character set
+ * $this->content_base_href    the <base href> to use for this page
+ * $this->base_path                    the absolute path to this atutor installation
+ * $this->rtl_css                      if set, the path to the RTL style sheet
+ * $this->banner_style         -deprecated-
+ * $this->theme                                the directory name of the current theme
+ * $this->base_href                    the full url to this atutor installation
+ * $this->onload                       javascript onload() calls
+ * $this->img                          the absolute path to this theme's images/ directory
+ * $this->sequence_links       associative array of 'previous', 'next', and/or 'resume' links
+ * $this->path                         associative array of path to this page: aka bread crumbs
+ * $this->rel_url                      the relative url from the installation root to this page
+ * $this->nav_courses          associative array of this user's enrolled courses
+ * $this->section_title                the title of this section (course, public, admin, my start page)
+ * $this->top_level_pages      associative array of the top level navigation
+ * $this->current_top_level_page       the full path to the current top level page with file name
+ * $this->sub_level_pages                      associate array of sub level navigation
+ * $this->back_to_page                         if set, the path and file name to the part of this page (if parent is not a top level nav)
+ * $this->current_sub_level_page       the full path to the current sub level page with file name
+ * $this->guide                                the full path and file name to the guide page
+ * ======================================
+ * top_level_pages           array(array('url', 'title'))     the top level pages. ATutor default creates tabs.
+ * section_title             string                           the name of the current section. either name of the course, administration, my start page, etc.
+ * page_title                string                           the title of the current page.
+ * path                      array(array('url', 'title'))     the path to the current page.
+ * back_to_page              array('url', 'title')            the link back to the part of the current page, if needed.
+ * current_top_level_page    string                           full url to the current top level page in "top_leve_pages"
+ * current_sub_level_page    string                           full url to the current sub level page in the "sub_level_pages"
+ * sub_level_pages           array(array('url', 'title'))     the sub level pages.
+ */
+
+// will have to be moved to the header.inc.php
+global $system_courses, $_custom_css;
+
+?><!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="<?php echo $this->lang_code; ?>">
+<head>
+       <title><?php echo SITE_NAME; ?> : <?php echo $this->page_title; ?></title>
+       <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $this->lang_charset; ?>" />
+       <meta name="Generator" content="ATutor - Copyright 2007 by http://atutor.ca" />
+       <base href="<?php echo $this->content_base_href; ?>" />
+       <link rel="shortcut icon" href="<?php echo $this->base_path; ?>favicon.ico" type="image/x-icon" />
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/print.css" type="text/css" media="print" />
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/styles.css" type="text/css" />
+       <!--[if IE]>
+         <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/ie_styles.css" type="text/css" />
+       <![endif]-->
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/forms.css" type="text/css" />
+       <?php echo $this->rtl_css; ?>
+       <?php if ($system_courses[$_SESSION['course_id']]['rss']): ?>
+       <link rel="alternate" type="application/rss+xml" title="<?php echo SITE_NAME; ?> - RSS 2.0" href="<?php echo $this->base_path; ?>get_rss.php?<?php echo $_SESSION['course_id']; ?>-2" />
+       <link rel="alternate" type="application/rss+xml" title="<?php echo SITE_NAME; ?> - RSS 1.0" href="<?php echo $this->base_path; ?>get_rss.php?<?php echo $_SESSION['course_id']; ?>-1" />
+       <?php endif; ?>
+       <?php echo $this->custom_css; ?>
+</head>
+<body onload="setstates(); <?php echo $this->onload; ?>"><div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000; <?php if ($this->rtl_css): ?>direction:rtl;<?php endif; ?>"></div>
+<script language="JavaScript" src="<?php echo $this->base_path; ?>overlib.js" type="text/javascript"></script><script language="javascript" type="text/javascript">
+//<!--
+
+var newwindow;
+function poptastic(url) {
+       newwindow=window.open(url,'popup','height=700,width=700,scrollbars=yes,resizable=yes');
+       if (window.focus) {newwindow.focus()}
+}
+
+function getexpirydate(nodays){
+       var UTCstring;
+       Today = new Date();
+       nomilli=Date.parse(Today);
+       Today.setTime(nomilli+nodays*24*60*60*1000);
+       UTCstring = Today.toUTCString();
+       return UTCstring;
+}
+
+function setcookie(name,value,duration){
+       cookiestring=name+"="+escape(value)+";path=/;expires="+getexpirydate(duration);
+       document.cookie=cookiestring;
+       if(!getcookie(name)){
+               return false;
+       } else {
+               return true;
+       }
+}
+
+function getcookie(cookiename) {
+       var cookiestring=""+document.cookie;
+       var index1=cookiestring.indexOf(cookiename);
+       if (index1==-1 || cookiename=="") return ""; 
+       var index2=cookiestring.indexOf(';',index1);
+       if (index2==-1) index2=cookiestring.length; 
+       return unescape(cookiestring.substring(index1+cookiename.length+1,index2));
+}
+
+function setDisplay(objId) {
+       var toc = document.getElementById(objId);
+
+       var state = getcookie(objId);
+       if (document.getElementById(objId) && state && (state == 'none')) {
+               toggleToc(objId);
+       }
+}
+
+
+function setstates() {
+       return;
+       var objId = "side-menu";
+       var state = getcookie(objId);
+       if (document.getElementById(objId) && state && (state == 'none')) {
+               toggleToc(objId);
+       }
+
+       var objId = "toccontent";
+       var state = getcookie(objId);
+       if (document.getElementById(objId) && state && (state == 'none')) {
+               toggleToc(objId);
+       }
+       return true;
+}
+
+function showTocToggle(objId, show, hide, key, selected) {
+       if(document.getElementById) {
+               if (key) {
+                       var accesskey = " accesskey='" + key + "' title='"+ show + "/" + hide + " Alt+"+ key +"'";
+               } else {
+                       var accesskey = "";
+               }
+
+               if (selected == 'hide') {
+                       document.writeln('<a href="javascript:toggleToc(\'' + objId + '\')" ' + accesskey + '>' +
+                       '<span id="' + objId + 'showlink" style="display:none;">' + show + '</span>' +
+                       '<span id="' + objId + 'hidelink">' + hide + '</span>'  + '</a>');
+               } else {
+                       document.writeln('<a href="javascript:toggleToc(\'' + objId + '\')" ' + accesskey + '>' +
+                       '<span id="' + objId + 'showlink">' + show + '</span>' +
+                       '<span id="' + objId + 'hidelink" style="display:none;">' + hide + '</span>'    + '</a>');
+               }
+       }
+}
+
+function toggleToc(objId) {
+       var toc = document.getElementById(objId);
+       if (toc == null) {
+               return;
+       }
+       var showlink=document.getElementById(objId + 'showlink');
+       var hidelink=document.getElementById(objId + 'hidelink');
+       if (hidelink.style.display == 'none') {
+               toc.style.display = '';
+               hidelink.style.display='';
+               showlink.style.display='none';
+       } else {
+               toc.style.display = 'none';
+               hidelink.style.display='none';
+               showlink.style.display='';
+       }
+       setcookie(objId, toc.style.display, 1);
+}
+//-->
+</script>
+
+<div id="member-links" style="float: right;">
+       <!-- hidden direct link to content -->
+       <a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#content" style="border: 0px;" accesskey="c"><img src="<?php echo $this->base_path; ?>images/clr.gif" height="1" width="1" border="0" alt="<?php echo _AT('goto_content'); ?> ALT+c" /></a>
+       <a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#menu" style="border: 0px;" accesskey="m"><img src="<?php echo $this->base_path; ?>images/clr.gif" height="1" width="1" border="0" alt="<?php echo _AT('goto_menu'); ?> ALT+m" /></a>
+
+       <?php if ($_SESSION['is_super_admin']): ?>
+               <a href="<?php echo $this->base_path; ?>bounce.php?admin"><?php echo _AT('return_to_admin_area'); ?></a> | 
+       <?php endif; ?>
+
+       <?php if ($_SESSION['valid_user']): ?>
+               <img src="<?php echo $this->img;?>user-star.gif" style="vertical-align: middle;" class="img-size-star" alt="" /><strong><?php echo get_display_name($_SESSION['member_id']); ?></strong>  |
+               <?php if ($_SESSION['course_id'] > -1): ?>
+                       <?php if (get_num_new_messages()): ?>
+                               <strong><a href="<?php echo $this->base_path; ?>inbox/index.php"><?php echo _AT('inbox'); ?> - <?php echo get_num_new_messages(); ?></a></strong> | 
+                       <?php else: ?>
+                               <a href="<?php echo $this->base_path; ?>inbox/index.php"><?php echo _AT('inbox'); ?></a> | 
+                       <?php endif; ?>
+               <?php endif; ?>
+               <a href="<?php echo $this->base_path; ?>search.php"><?php echo _AT('search'); ?></a> |
+               <a href="<?php echo $this->base_path; ?>help/index.php"><?php echo _AT('help'); ?></a> |
+               <a href="<?php echo $this->base_path; ?>logout.php"><?php echo _AT('logout'); ?></a>
+       <?php elseif ($_SESSION['course_id'] == -1): ?>
+               <img src="<?php echo $this->img;?>user-star.gif" style="vertical-align: middle;" class="img-size-star" alt="" /><strong><?php echo get_display_name($_SESSION['member_id']); ?></strong>  |
+               <a href="<?php echo $this->base_path; ?>search.php"><?php echo _AT('search'); ?></a> |
+               <a href="<?php echo $this->base_path; ?>help/index.php"><?php echo _AT('help'); ?></a> |
+               <a href="<?php echo $this->base_path; ?>logout.php"><?php echo _AT('logout'); ?></a>
+       <?php else: ?>
+               <a href="<?php echo $this->base_path; ?>browse.php"><?php echo _AT('browse_courses'); ?></a> | 
+               <a href="<?php echo $this->base_path; ?>login.php?course=<?php echo $_SESSION['course_id']; ?>"><?php echo _AT('login'); ?></a> | 
+               <a href="<?php echo $this->base_path; ?>search.php"><?php echo _AT('search'); ?></a> | 
+               <a href="<?php echo $this->base_path; ?>help/index.php"><?php echo _AT('help'); ?></a>
+       <?php endif; ?>
+</div>
+
+<div style="float: right;">
+       <?php if (isset($_SESSION['member_id']) && $_SESSION['member_id']): ?>
+               <!-- start the jump menu -->
+               <?php if (empty($_GET)): ?>
+                       <form method="post" action="<?php echo $this->base_path; ?>bounce.php?p=<?php echo urlencode($this->rel_url); ?>" target="_top">
+               <?php else: ?>
+                       <form method="post" action="<?php echo $this->base_path; ?>bounce.php" target="_top">
+               <?php endif; ?>
+               <label for="jumpmenu" accesskey="j"></label>
+               <select name="course" id="jumpmenu" title="<?php echo _AT('jump'); ?>:  Alt-j">                                                 
+                       <option value="0" id="start-page"><?php echo _AT('my_start_page'); ?></option>
+                       <optgroup label="<?php echo _AT('courses_below'); ?>">
+                               <?php foreach ($this->nav_courses as $this_course_id => $this_course_title): ?>
+                                       <option value="<?php echo $this_course_id; ?>"><?php echo $this_course_title; ?></option>
+                               <?php endforeach; ?>
+                       </optgroup>
+               </select> <input type="submit" name="jump" value="<?php echo _AT('jump'); ?>" id="jump-button" /></form>
+               <!-- /end the jump menu -->
+       <?php endif; ?>
+</div>
+
+<div id="breadcrumbs">
+       <span style="white-space:nowrap;font-size:smaller;padding-top:150px;">
+       <?php foreach ($this->path as $page): ?>
+               <a href="<?php echo $page['url']; ?>" title="<?php echo _AT('back_to').' '.$page['title']; ?>"><?php echo $page['title']; ?></a> &raquo; 
+       <?php endforeach; ?> <?php echo htmlspecialchars($this->page_title, ENT_COMPAT, "UTF-8"); ?></span>
+</div>
+
+<div class="header">
+       <!-- section title -->  
+       <?php if ($_SESSION['valid_user']): 
+               echo '<span style="font-size:small;font-weight:bold;padding-left:5px;">'.stripslashes(SITE_NAME).'</span>'; 
+       else:
+               echo '<br />';  
+       endif; ?>
+       <h1><?php echo $this->section_title; ?>
+       <?php if (($_SESSION['course_id'] > 0) && ($_SESSION['enroll'] == AT_ENROLL_NO)) : ?>
+               - <small><a href="<?php echo $this->base_path; ?>enroll.php?course=<?php echo $_SESSION['course_id']; ?>"><?php echo _AT('enroll_me'); ?></a></small>
+       <?php endif; ?></h1>
+
+       <div id="topnavlistcontainer">
+               <!-- the main navigation. in our case, tabs -->
+               <ul id="topnavlist">
+                       <?php foreach ($this->top_level_pages as $page): ?>
+                               <?php ++$accesscounter; $accesscounter = ($accesscounter == 10 ? 0 : $accesscounter); ?>
+                               <?php $accesskey_text = ($accesscounter < 10 ? 'accesskey="'.$accesscounter.'"' : ''); ?>
+                               <?php $accesskey_title = ($accesscounter < 10 ? ' Alt+'.$accesscounter : ''); ?>
+                               <?php if ($page['url'] == $this->current_top_level_page): ?>
+                                       <li><a href="<?php echo $page['url']; ?>" <?php echo $accesskey_text; ?> title="<?php echo $page['title'] . $accesskey_title; ?>" class="active"><?php echo $page['title']; ?></a></li>
+                               <?php else: ?>
+                                       <li><a href="<?php echo $page['url']; ?>" <?php echo $accesskey_text; ?> title="<?php echo $page['title'] . $accesskey_title; ?>"><?php echo $page['title']; ?></a></li>
+                               <?php endif; ?>
+                               <?php $accesscounter = ($accesscounter == 0 ? 11 : $accesscounter); ?>
+                       <?php endforeach; ?>
+               </ul>
+       </div>
+</div>
+
+<!-- the sub navigation -->
+<div style="text-align: right; padding-top: 5px; padding-right: 5px;"><small><?php echo $this->current_date; ?></small></div>
+<?php if ($this->sub_level_pages && !(count($this->sub_level_pages) == 1 && $this->sub_level_pages[0]['url'] == $this->current_sub_level_page)): ?>
+       <div id="sub-navigation">
+               <?php if (isset($this->back_to_page)): ?>
+                       <a href="<?php echo $this->back_to_page['url']; ?>" id="back-to"><?php echo _AT('back_to'); ?> <?php echo $this->back_to_page['title']; ?></a> | 
+               <?php endif; ?>
+
+               <?php $num_pages = count($this->sub_level_pages); ?>
+               <?php for($i=0; $i<$num_pages; $i++): ?>
+                       <?php if ($this->sub_level_pages[$i]['url'] == $this->current_sub_level_page): ?>
+                               <strong><?php echo $this->sub_level_pages[$i]['title']; ?></strong>
+                       <?php else: ?>
+                               <a href="<?php echo $this->sub_level_pages[$i]['url']; ?>"><?php echo $this->sub_level_pages[$i]['title']; ?></a>
+                       <?php endif; ?>
+                       <?php if ($i < $num_pages-1): ?>
+                               | 
+                       <?php endif; ?>
+               <?php endfor; ?>
+       </div>
+<?php else: ?>
+       <div id="sub-navigation">
+               &nbsp;
+       </div>
+<?php endif; ?>
+
+<table align="center" border="0" cellpadding="0" cellspacing="0" width="99%">
+       <tr>
+               <?php if ($_SESSION['course_id'] > 0): ?>
+                       <td valign="top" width="100%">
+               <?php else: ?>
+                       <td valign="top" width="100%" colspan="2">
+               <?php endif; ?>
+
+<!-- the page title -->
+       <div style="text-align: right; padding-bottom: 10px; padding-right: 10px; float: right; margin-top: 10px; padding-right: 5px;">
+               <?php if ($this->guide): ?>
+                       <a href="<?php echo $this->guide; ?>" id="guide" onclick="poptastic('<?php echo $this->guide; ?>'); return false;" target="_new"><em><?php echo $this->page_title; ?></em></a>
+               <?php endif; ?>
+               <?php if ($_SESSION['course_id'] > 0 && $system_courses[$_SESSION['course_id']]['side_menu']): ?>
+                       <script type="text/javascript" language="javascript">
+                       //<![CDATA[
+                       var state = getcookie("side-menu");
+                       if (state && (state == 'none')) {
+                               showTocToggle("side-menu", "<?php echo _AT('show'); ?>","<?php echo _AT('hide'); ?>", "", "show");
+                       } else {
+                               showTocToggle("side-menu", "<?php echo _AT('show'); ?>","<?php echo _AT('hide'); ?>", "", "hide");
+                       }
+                       //]]>
+                       </script>
+               <?php endif; ?>
+       </div>
+
+       <div style="float:right;padding-top:7px;" id="sequence-links">
+               <?php if ($this->sequence_links['resume']): ?>
+                               <a style="color:white;" href="<?php echo $this->sequence_links['resume']['url']; ?>" accesskey="."><img src="<?php echo $this->img; ?>resume.gif" border="0" title="<?php echo _AT('resume').': '.$this->sequence_links['resume']['title']; ?> Alt+." alt="<?php echo $this->sequence_links['resume']['title']; ?> Alt+." class="img-size-ascdesc" /></a>
+               <?php else:
+                       if ($this->sequence_links['previous']): ?>
+                               <a href="<?php echo $this->sequence_links['previous']['url']; ?>" title="<?php echo _AT('previous_topic').': '. $this->sequence_links['previous']['title']; ?> Alt+," accesskey=","><img src="<?php echo $this->img; ?>previous.gif" border="0" alt="<?php echo _AT('previous_topic').': '. $this->sequence_links['previous']['title']; ?> Alt+," class="img-size-ascdesc" /></a>
+                       <?php endif;
+                       if ($this->sequence_links['next']): ?>
+                               <a href="<?php echo $this->sequence_links['next']['url']; ?>" title="<?php echo _AT('next_topic').': '.$this->sequence_links['next']['title']; ?> Alt+." accesskey="."><img src="<?php echo $this->img; ?>next.gif" border="0" alt="<?php echo _AT('next_topic').': '.$this->sequence_links['next']['title']; ?> Alt+." class="img-size-ascdesc" /></a>
+                       <?php endif; ?>
+               <?php endif; ?>
+               &nbsp;
+       </div>
+
+       <h2 class="page-title"><?php echo htmlspecialchars($this->page_title, ENT_COMPAT, "UTF-8"); ?></h2>
+
+<a name="content"></a>
+<?php global $msg; $msg->printAll(); ?>
diff --git a/themes/default15/index.tmpl.php b/themes/default15/index.tmpl.php
new file mode 100644 (file)
index 0000000..5192534
--- /dev/null
@@ -0,0 +1,45 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+if (!defined('AT_INCLUDE_PATH')) { exit; } ?>\r
+\r
+<?php if ($this->banner): ?><?php echo $this->banner; ?><?php endif; ?>\r
+\r
+<div style="width: 100%; margin-top: -5px;">\r
+       <ul id="home-links">\r
+       <?php foreach ($this->home_links as $link): ?>\r
+               <li><a href="<?php echo $link['url']; ?>"><img src="<?php echo $link['img']; ?>" alt="" class="img-size-home" border="0" /><?php echo $link['title']; ?></a></li>\r
+       <?php endforeach; ?>\r
+       </ul>\r
+</div>\r
+\r
+<?php if ($this->announcements): ?>\r
+<h2 class="page-title"><?php echo _AT('announcements'); ?></h2>\r
+       <?php foreach ($this->announcements as $item): ?>\r
+               <div class="news">\r
+                       <h3><?php echo $item['title']; ?></h3>\r
+                       <p><span class="date"><?php echo $item['date']; ?></span> &nbsp; <?php echo $item['body']; ?></p>\r
+               </div>\r
+       <?php endforeach; ?>\r
+\r
+       <?php if ($this->num_pages > 1): ?>\r
+               <?php echo _AT('page'); ?>: | \r
+               <?php for ($i=1; $i<=$this->num_pages; $i++): ?>\r
+                       <?php if ($i == $this->current_page): ?>\r
+                               <strong><?php echo $i; ?></strong>\r
+                       <?php else: ?>\r
+                               <a href="<?php echo $_SERVER['PHP_SELF']; ?>?p=<?php echo $i; ?>"><?php echo $i; ?></a>\r
+                       <?php endif; ?>\r
+                        | \r
+               <?php endfor; ?>\r
+       <?php endif; ?>\r
+<?php endif; ?>\r
diff --git a/themes/default15/infomessage.tmpl.php b/themes/default15/infomessage.tmpl.php
new file mode 100644 (file)
index 0000000..cea188b
--- /dev/null
@@ -0,0 +1,18 @@
+<?php  
+/*
+ * @author Jacek Materna
+ *
+ *     One Savant variable: $item which is the processed ouput message content according to lang spec.
+ */
+global $_base_href; ?>
+
+<div id="info">
+       <?php if (is_array($this->item)) : ?>
+               <ul>
+               <?php foreach($this->item as $i) : ?>
+                       <li><?php echo $i; ?></li>
+               <?php endforeach; ?>
+               </ul>
+       <?php endif; ?>
+</div>
\ No newline at end of file
diff --git a/themes/default15/password_change.tmpl.php b/themes/default15/password_change.tmpl.php
new file mode 100644 (file)
index 0000000..ca96846
--- /dev/null
@@ -0,0 +1,32 @@
+<?php require(AT_INCLUDE_PATH.'header.inc.php'); ?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+       <input type="hidden" name="form_change" value="true" />
+       <input type="hidden" name="id" value="<?php echo $this->id; ?>" />
+       <input type="hidden" name="g" value="<?php echo $this->g; ?>" />
+       <input type="hidden" name="h" value="<?php echo $this->h; ?>" />
+
+       <div class="input-form" style="max-width: 400px;">
+               <div class="row">
+                       <?php echo _AT('password_new_blurb'); ?>
+               </div>
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="password"><?php echo _AT('password'); ?></label><br />
+                       <input id="password" name="password" type="password" size="15" maxlength="15" value="<?php echo stripslashes(htmlspecialchars($_POST['password'])); ?>" /><br />
+                       <small>&middot; <?php echo _AT('combination'); ?><br />
+                                  &middot; <?php echo _AT('15_max_chars'); ?></small>
+               </div>
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="password2"><?php echo _AT('password_again'); ?></label><br />
+                       <input id="password2" name="password2" type="password" size="15" maxlength="15" value="<?php echo stripslashes(htmlspecialchars($_POST['password2'])); ?>" />
+               </div>
+
+               <div class="row buttons">
+                       <input type="submit" name="submit" value="<?php echo _AT('submit'); ?>" /> <input type="submit" name="cancel" value=" <?php echo _AT('cancel'); ?> " />
+               </div>
+       </div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/themes/default15/password_reminder_feedback.tmpl.php b/themes/default15/password_reminder_feedback.tmpl.php
new file mode 100644 (file)
index 0000000..39ead0e
--- /dev/null
@@ -0,0 +1,6 @@
+<?php 
+
+       require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+?>
\ No newline at end of file
diff --git a/themes/default15/print.css b/themes/default15/print.css
new file mode 100644 (file)
index 0000000..cbecd5c
--- /dev/null
@@ -0,0 +1,13 @@
+body {
+       background-color: White;
+       font-family: Helvetica, arial, sans serif;
+       margin: 0px;
+       margin-top: 0px;
+       color: black;
+       border: 0px;
+}
+
+div#side-menu, div#member-links, span#side-menushowlink, span#side-menuhidelink, div#sequence-links, select#jumpmenu, a#guide, div#gototop, input#jump-button, div#topnavlistcontainer, a#guide, div#breadcrumbs, div#jump-area, table.tabbed-table, div#sub-navigation, div#sequence-links, div#language, div#toc, fieldset#shortcuts {
+       display: none;
+}
+
diff --git a/themes/default15/profile.tmpl.php b/themes/default15/profile.tmpl.php
new file mode 100644 (file)
index 0000000..356621c
--- /dev/null
@@ -0,0 +1,65 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+global $display_name_formats, $moduleFactory;\r
+\r
+?>\r
+<div class="input-form">\r
+       <div class="row">\r
+               <p><a href="inbox/send_message.php?id=<?php echo $this->row['member_id']; ?>"><?php echo _AT('send_message'); ?></a></p>\r
+\r
+               <dl id="public-profile">\r
+                       <dt><?php echo _AT('email'); ?></dt>\r
+                       <dd>\r
+                               <?php if($this->row['private_email']): ?>\r
+                                       <?php echo _AT('private'); ?>\r
+                               <?php else: ?>\r
+                                       <a href="mailto:<?php echo $this->row['email']; ?>"><?php echo $this->row['email']; ?></a>\r
+                               <?php endif; ?>\r
+                       </dd>\r
+               \r
+                       <dt><?php echo _AT('web_site'); ?></dt>\r
+                       <dd>\r
+                               <?php if ($this->row['website']) { \r
+                                       echo '<a href="'.htmlspecialchars($this->row['website'], ENT_COMPAT, "UTF-8").'">'.AT_print($this->row['website'], 'members.website').'</a>'; \r
+                               } else {\r
+                                       echo '--';\r
+                               } ?>\r
+                       </dd>\r
+\r
+                       <dt><?php echo _AT('phone'); ?></dt>\r
+                       <dd>\r
+                               <?php if ($this->row['phone']) { \r
+                                       echo $this->row['phone'];\r
+                               } else {\r
+                                       echo '--';\r
+                               }\r
+                               ?>\r
+                       </dt>\r
+\r
+                       <dt><?php echo _AT('status'); ?></dt>\r
+                       <dd><?php echo $this->status; ?></dd>\r
+\r
+                       <?php $mod = $moduleFactory->getModule('_standard/profile_pictures'); \r
+                       if ($mod->isEnabled() === TRUE): ?>\r
+                               <dt><?php echo _AT('picture'); ?></dt>\r
+                               <dd><?php if (profile_image_exists($this->row['member_id'])): ?>\r
+                                       <a href="get_profile_img.php?id=<?php echo $this->row['member_id'].SEP.'size=o'; ?>"><?php print_profile_img($this->row['member_id']); ?></a>\r
+                                       <?php else: ?>\r
+                                               <?php echo _AT('none'); ?>\r
+                                       <?php endif; ?>\r
+                               </dd>\r
+                       <?php endif; ?>\r
+               </dl>\r
+               <div style="clear: both; size: 1em"></div>\r
+       </div>\r
+</div>\r
diff --git a/themes/default15/readme.txt b/themes/default15/readme.txt
new file mode 100644 (file)
index 0000000..88e88ef
--- /dev/null
@@ -0,0 +1,6 @@
+\r
+Theme:         ATutor Default\r
+Date:          May 2005\r
+\r
+Licence:       Falls under the GPL agreement.  See http://www.gnu.org/copyleft/gpl.html.\r
+       
\ No newline at end of file
diff --git a/themes/default15/rtl.css b/themes/default15/rtl.css
new file mode 100644 (file)
index 0000000..b95ecf0
--- /dev/null
@@ -0,0 +1,14 @@
+/* for right to left languages */
+html, body {
+       direction: rtl;
+}
+
+/* required for mozilla browsers*/
+.img-size-tree {
+       vertical-align: middle;
+       margin-top: 0px;
+       height:1.45em;
+       width:1.45em;
+       text-align: right.;
+       float: right;
+}
\ No newline at end of file
diff --git a/themes/default15/screenshot.gif b/themes/default15/screenshot.gif
new file mode 100644 (file)
index 0000000..8273db6
Binary files /dev/null and b/themes/default15/screenshot.gif differ
diff --git a/themes/default15/styles.css b/themes/default15/styles.css
new file mode 100644 (file)
index 0000000..9ab5930
--- /dev/null
@@ -0,0 +1,1315 @@
+/* main body attributes */
+body {
+       font-family: Helevetica, Arial, sans-serif;
+       margin-top: 0px;
+       margin-left: 0px;
+       margin-right: 0px;
+       /* max-width: 760px; */
+       margin-bottom: 0px;
+       font-size: small;
+       background-color: white;
+       /*border-right: 1px solid #788CB3;*/
+}
+
+html,body {
+       height: 100%;
+}
+
+/* heading attributes */
+h1, h2, h3, h4, h5, h6 {
+       font-family: trebuchet ms, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-left: 5px;
+       margin-right: 0px;
+       color: #384F89; /* #152065; #D15600; */
+}
+
+/* paragraph attributes */
+p {
+       font-family: Helevetica, Arial, sans-serif;
+       margin-bottom: 10px;
+       margin-top: 0px;
+       margin-left: 5px;
+       margin-right: 0px;
+} 
+
+
+/* for filemanager */
+li.folders {
+       list-style: disc url(../../images/folder.gif) outside;
+       font-family: Helevetica, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+
+/* link attributes */
+a:link {
+       font-family: Helevetica, Arial, sans-serif;
+       color: #384F89;
+       text-decoration: underline;
+}
+a:visited {
+       font-family: Helevetica, Arial, sans-serif;
+       color: #384F89;
+       text-decoration: underline;
+}
+a:hover {
+       font-family: Helevetica, Arial, sans-serif;
+       color: black;
+       text-decoration: underline;
+}
+
+/*  Table of content attributes*/
+div#toc{
+       font-family: Helevetica, Arial, sans-serif;
+       background-color: #eeeeee;
+       padding-right: 3px;
+       margin: 0px 5px 5px 5px;
+       border: 1px #98AAB1 solid;
+       float: left;
+       font-size: smaller;
+}
+
+/* table border */
+.tableborder {
+       border: 1px #606060 solid;
+}
+
+/* button */
+.button input {
+       border: 1px solid #999;
+       background-color: white;
+       padding: 2px;
+
+}
+
+.button input:hover {
+       background-color: #f5f5ff;
+       border: 1px solid blue;
+       cursor: pointer;
+}
+
+input.button {
+       border: 1px solid #999;
+       background-color: white;
+       padding: 2px;
+       padding-left: 10px;
+       padding-right: 10px;
+}
+input.button:hover {
+       background-color: #f5f5ff;
+       border: 1px solid blue;
+}
+
+/* page breakline */
+hr {
+       color: #98AAB1;
+       background-color: white;
+       height: 1px;
+}
+
+/* Editor boxes */
+.editorsmallbox {
+       font-family: Helevetica, Arial, sans-serif;
+       background-color: #EEEEEE;
+       padding: 2px;
+       padding-right: 3px;
+       border: 1px #99CCCC solid;
+}
+.editorlargebox {
+       font-family: Helevetica, Arial, sans-serif;
+       background-color: #EEEEEE;
+       margin-left:1em;
+       padding-left: .2em;
+       padding-right: .5em;
+       padding-top: .5em;
+       padding-bottom: .4em;
+       border: 1px #99CCCC solid;
+}                                                          
+
+/* feedback for translators and install */
+.feedback2  {
+  font-family : Arial, Helvetica, Arial Cyr, Arial Ua, sans-serif;
+  color : white;
+  background: green;
+  font-weight : bold;
+  padding: 4px;
+ }
+
+/* search results */
+.highlight, a.highlight {
+       background-color: yellow;
+}
+
+a .highlight{
+       background-color: yellow;
+       text-decoration: underline;
+}
+
+.results {
+       padding-left: 20px;
+}
+
+h5.search-results {
+       background-color: #FFF5A4;
+       color: #006699;
+       padding: 1px;
+       margin-bottom: 5px;
+       margin-top: 10px;
+       margin-left: 5px;
+}
+
+small.search-info {
+       color: #006699;
+}
+
+p.search-description {
+       background-color: #FFFCE5;
+       color: #006699;
+}
+
+/* date attributes */
+small.date {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: #8CACBB; 
+       margin-bottom: 0px; 
+       margin-top: 0px;
+       margin-left: 5px;
+       margin-right: 0px;
+       font-size:small;
+}
+
+/* content editor tabs */
+
+.etable {
+       border-left:1pt solid black;
+       border-right:1pt solid black;
+       border-bottom:1pt solid black;
+       width:90%;
+}
+
+/* button link on tab */
+.buttontab {
+       font-family: Helvetica, Arial, Helvetica, sans-serif;
+       background-color: #ffffff;
+       border: 0px;
+       color: black;
+       font-size:small;
+}
+
+/* button link for enrollment tabs */
+.buttontab2 {
+       font-family: Helvetica, Arial, Helvetica, sans-serif;
+       background-color: #EFEFEF;
+       border: 0px;
+       color: black;
+       font-size:small;
+}
+
+/* tab itself */
+.etab {
+       background-color: #ffffff;
+       border-top: 1px #98AAB1 solid;
+       border-left: 1px #98AAB1 solid;
+       border-right: 1px #98AAB1 solid;
+       text-align: center;
+}
+
+.etab-selected {
+       background-color: #EFEFEF;
+       border-top: 1px #98AAB1 solid;
+       border-left: 1px  #98AAB1 solid;
+       border-right: 1px #98AAB1 solid;
+       text-align: center;
+       padding: 2px;
+       font-weight:bold;
+}
+
+div.top {
+    /* Top section */
+    background: transparent;
+    margin: 0;
+    padding: 0;
+}
+div.etabs {
+    background: transparent;
+    border-collapse: collapse;
+    border-bottom-color: #8CACBB;
+    border-bottom-style: solid;
+    border-bottom-width: 1px;
+    padding: 0.5em 0em 0em 2em;
+    white-space: nowrap;
+       font-size:smaller;
+}
+
+div.etabs plain {
+    background: transparent;
+    border-color: #8CACBB;
+    border-width: 1px; 
+    border-style: solid solid none solid;
+    color: #436976;
+    font-weight: normal;
+    height: 1.2em;
+    margin-right: 0.5em;
+    padding: 0em 2em;
+    text-transform: lowercase;
+}
+
+div.etabs selected {
+    background: #DEE7EC;
+    border: 1px solid #8CACBB;
+    border-bottom: #DEE7EC 1px solid;
+    color: #436976;
+    font-weight: normal;
+}
+
+/* status bar */
+div.saved, div.unsaved {
+       text-align:right;
+       padding-right:20px;
+       padding-top:5px;
+       padding-bottom:10px;
+}
+
+div.saved input, div.unsaved input {
+       border: 1px solid black;
+       background-color: white;
+    font-weight: normal;
+}
+
+div.saved input:focus, div.unsaved input:focus {
+       border: 1px solid black;
+       background-color: white;
+    font-weight: normal;
+}
+
+#body_text {
+       width:75%;
+}
+
+/* side menu heading */
+td.dropdown-heading {
+       background-color: #D4E5FD;
+       color: #006699;
+       border-left: 1px solid #EAF2FE;
+       border-right: 1px solid #EAF2FE;
+       border-top: 1px solid #EAF2FE;
+       font-weight: bold;
+       padding: 2px;
+}
+
+/* side menu content */
+td.dropdown {
+       padding: 2px;
+       background-color: white;
+       color: black;
+       border-left: 1px solid #EAF2FE;
+       border-right: 1px solid #EAF2FE;
+       border-bottom: 1px solid #EAF2FE;
+       font-weight: normal;
+}
+
+
+td.dropdown strong {
+       color: #51286C;
+}
+
+/* test listing on home page */
+
+.test-box {
+       background-color: #FFF5A4;
+       color: #006699;
+       border-left: 1px solid #006699;
+       border-right: 1px solid #006699;
+       border-top: 1px solid #006699;
+       font-weight: bold;
+       padding: 2px;
+}
+
+/* message boxes */
+div#feedback {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid green;
+       padding: 5px;
+       background-color: #c3fffc;
+       color: green;
+       font-weight: bold;
+}
+
+div#help {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid blue;
+       padding: 5px;
+       background-color: #c3ffff;
+       color: blue;
+}
+
+div#info {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #2905A1;
+       padding: 5px;
+       background-color: #E1D7E8;
+       color: #2905A1;
+       font-weight: bold;
+}
+
+div#warning {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #FF8400;
+       padding: 5px;
+       background-color: #FFF6ED;
+       color: #D95900;
+       font-weight: bold;
+}
+
+/***************************************************************/
+/* NEW STUFF */
+
+/* main navigation tabs */
+a#back-to {
+       padding-left: 20px;
+       background-image: url(images/back.gif);
+       background-repeat: no-repeat;
+       background-position: 0px 0px;
+       height:1.45em;
+       width:1.45em;
+}
+
+div#breadcrumbs {
+       margin-bottom: 0px;
+       margin-top: 0px;
+       padding-left: 5px;
+       padding-right: 5px;
+       padding-bottom: 10px;
+       font-size: small;
+       background-color: #EBF4F9;
+       color: black;
+       border-bottom: dashed 1pt #A7D2F8;
+}
+div#breadcrumbs a:link, div#breadcrumbs a:visited, div#member-links a:link, div#member-links a:visited {
+       color: black;
+       text-decoration:none;
+}
+div#breadcrumbs a:hover, div#member-links a:hover {
+       text-decoration:underline;
+}
+
+div#breadcrumbs a:focus, div#member-links a:focus {
+       text-decoration:none;
+       color: #AFAFAF;
+}
+
+div#member-links {
+       margin-top:3px;
+       padding-right:5px;
+}
+
+h2.page-title {
+       margin-bottom: 10px;
+       margin-top: 4px;
+       margin-left: 5px;
+       border-bottom: 1px solid #f0f0f0;
+       clear: left;
+}
+
+h1 {
+       margin-bottom: 5px;
+}
+
+div#sub-navigation {
+       padding: 5px;
+       background-color: white; /*#FFFCE5;*/
+       /* border-bottom: 1px solid #9DAB9A;*/
+       color: #9DAB9A;
+       margin-bottom:0px;
+}
+
+div#sub-navigation strong {
+       color: black;
+}
+
+div#help {
+       border-left: 1px solid black;
+       border-right: 1px solid black;
+       border-bottom: 1px solid black;
+       padding-left: 5px;
+       padding-right: 5px;
+       padding-bottom: 5px;
+       background-color: #efefef;
+       margin-left: 5px;
+       margin-right: 5px;
+       font-size: small;
+}
+
+h3#help-title {
+       margin-left: 5px;
+       margin-right: 5px;
+       border-left: 1px solid black;
+       border-right: 1px solid black;
+       padding: 1px;
+       background-color: #efefef;
+}
+.line {
+       border-bottom: 1px solid black;
+}
+div#help p {
+       padding: 0px;
+       margin: 0px;
+}
+
+div#toctoggle {
+       float: left;
+       font-size: smaller;
+       padding-left: 10px;
+}
+
+div#top-links {
+       position: relative;
+       padding-right: 5px;
+       line-height: 170%;
+       margin-top: 3px;
+}
+
+a#editor-link {
+       background-color: #EFEFEF;
+       padding-top: 1px;
+       padding-bottom: 1px;
+       padding-left: 15px;
+       padding-right: 8px;
+       border: 1px solid #cccccc;
+       font-weight: normal;
+       text-decoration: none;
+}
+
+a#editor-link:hover {
+       background-color: #fafafa;
+       border: 1px solid #aaaaaa;
+}
+
+a#editor-link.off {
+       background-image: url(images/pen.gif);
+       background-repeat: no-repeat;
+       background-position: 0px 2px;
+}
+a#editor-link.on {
+       background-image: url(images/pen2.gif);
+       background-repeat: no-repeat;
+       background-position: 0px 2px;
+}
+
+
+/* for data tables */
+table.data {
+       clear:right;
+       border: 1px solid #e0e0e0;
+       width: 90%; 
+       margin-left: auto; 
+       margin-right: auto;
+       border-spacing: 0px;
+       border-collapse: collapse;
+}
+
+table.data th {
+       background-color: #fafafa;
+       border-bottom: 1px solid #e0e0e0;
+       padding: 2px;
+       white-space: nowrap;
+
+}
+
+table.data th a {
+       color: black;
+       padding-right: 15px;
+       margin-right: 15px;
+       background-image: url('images/sort.gif');
+       background-repeat: no-repeat;
+       background-position: right;
+       text-decoration:none;
+}
+
+table.data th a:hover {
+       text-decoration: underline;
+}
+
+table.data tbody th {
+       text-align: left;
+       background-color: #fdfdfd;
+       cursor: auto;
+       border-bottom: 0px;
+       border-top: 1px solid #e0e0e0;
+}
+
+table.data td {
+       padding: 3px;
+}
+table.data td.indent {
+       padding-left: 12px;
+}
+
+table.data col.sort {
+       background-color: #fafafa;
+}
+
+table.data tbody tr:hover, table.data tbody tr:hover th {
+       background-color: #f5f5ff;
+       cursor: pointer;
+}
+table.data.static tbody tr:hover th {
+       background-color: #fdfdfd;
+       cursor: auto;
+}
+
+
+table.data tbody tr.selected, table.data tbody tr.selected th {
+       background-color: #f5f5ff;
+}
+
+table.data tfoot {
+       background-color: #fafafa;
+       border-top: 1px solid #e0e0e0;
+}
+
+table.data tfoot tr:first-child td {
+       padding: 5px;
+       background-image: url('images/arrow_ltr.gif');
+       background-repeat: no-repeat;
+       background-position: 4px 5px;
+       padding-left: 40px;
+}
+table.data.static tfoot td, table.data.static tfoot tr:first-child td {
+       padding: 5px;
+       background-image: none;
+       padding-left: 0px;
+}
+
+table.data tfoot input {
+       border: 1px solid #999;
+       background-color: white;
+       padding: 2px;
+       padding-left: 10px;
+       padding-right: 10px;
+       max-width: 60%;
+       min-width: 100px;
+       margin-left: 5px;
+}
+
+/* used for static tables with no form elements */
+table.data.static tbody tr:hover {
+       background-color: transparent;
+       cursor: auto;
+}
+
+table.data tfoot input[type=submit]:hover {
+       background-color: #f5f5ff;
+       cursor: pointer;
+}
+
+/* course browser */
+
+/*div#browse {
+       margin-left: auto; 
+       margin-right: auto; 
+       width: 80%;
+}
+*/
+
+/*
+div.browse-selected {
+       background-image: url('images/side_arrow.gif'); 
+       background-repeat: no-repeat; 
+       padding-left: 9px; 
+       background-position: center left;
+}
+
+div.browse-unselected {
+       padding-left: 9px; 
+}
+
+ul.browse-list {
+       list-style: none;
+       padding:0px;
+}
+*/
+
+/* feedback/errors */
+div#error {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid red;
+       padding: 5px;
+       background-color: #fffcf3;
+       color: red;
+       background: #FBF4ED url(images/error-large.gif) no-repeat scroll 5px 5px;
+       padding-left: 25px;
+       font-weight: bold;
+}
+div#error h4 {
+       color: black;
+       margin-left: 0px;
+}
+
+div#error ul, div#feedback ul, div#help ul {
+       position: relative;
+       list-style: none;
+       margin: 0px;
+       padding-left: 0px;
+}
+div#error li + li, div#feedback li + li {
+       margin-top: 5px;
+}
+
+acronym {
+       cursor: help;
+}
+
+div.news p {
+       margin-left: 10px;
+}
+div.news span.date {
+       color: #ACACAC;
+}
+
+/* home page links */
+ul#home-links {
+       list-style: none;
+}
+ul#home-links li {
+       display: inline;
+       float: left;
+       padding: 0.5em;
+       text-align: center;
+       margin: 0.1em;
+       width: 8.5em;
+       height: 7.0em;
+}
+ul#home-links li a {
+       text-decoration: none;
+       border: 1px transparent;
+       font-weight: bold;
+}
+ul#home-links li a img {
+       border: 0px;
+       display: block;
+}
+
+a.sortable {
+       color: blue;
+       text-decoration: underline;
+       font-weight: bold;
+}
+
+div.dropdown {
+       width: 200px;
+       padding: 2px;
+       background-color: white;
+       color: black;
+       border-left: 1px solid #EAF2FE;
+       border-right: 1px solid #EAF2FE;
+       border-bottom: 1px solid #EAF2FE;
+       font-weight: normal;
+}
+
+div.dropdown-heading {
+       background-color: #DFE1C7;
+       color: #006699;
+       border-left: 1px solid #EAF2FE;
+       border-right: 1px solid #EAF2FE;
+       border-top: 1px solid #EAF2FE;
+       font-weight: bold;
+       padding: 2px;
+}
+
+div.required {
+       font-weight: bold;
+       color: red;
+       font-size: xx-large;
+       float: left;
+       position: relative;
+       margin-top: -5px;
+       height: 15px;
+       padding-right: 2px;
+}
+
+div#content-text {
+       margin-left: 10px;
+       padding-right: 5px;
+}
+
+div#content-text li {
+       margin-left: 15px;
+}
+
+div#content-info {
+       margin: 5px;
+       font-size: smaller;
+       color: #cacaca;
+       clear: both;
+}
+
+form {
+       clear: none;
+       display:inline;
+}
+
+/* images in jump select box */
+option#start-page {
+       color: black;
+       text-decoration: none;
+       padding-left: 15px;
+       border-bottom: 1px solid black;
+}
+
+#jump-button {
+       padding: 0px;
+       margin: 1px;
+       background-color: #A7D2F8;
+       color: black;
+       border: 1px solid gray;
+       cursor: pointer;
+}
+#jump-button:focus, #jump-button:hover {
+       padding: 0px;
+       border: 1px solid #cccccc;
+       cursor: pointer;
+}
+#jumpmenu, optgroup {
+       font-size: smaller;
+}
+
+/* paging */
+div.paging {
+   width: 98%;
+   text-align: center;
+       padding: 5px;
+       margin: 10px;
+}
+div.paging ul, div.paging ul li {
+       display: inline;
+       padding: 0px;
+       margin: 0px;
+}
+div.paging ul li a {
+       padding: 7px;
+       background-color: #fafaff;
+       text-decoration: none;
+}
+div.paging ul li a:hover, div.paging ul li a.current {
+       background-color: #aaf;
+       color: white;
+       font-weight: bold;
+}
+
+/* users/index.php */
+div.course {
+       position: relative;
+       width: 300px;
+       height: 10.5em;
+       border: rgb(204, 204, 204) 1px solid;
+       background-color: white;
+       float: left;
+       margin: 3px;
+       padding: 3px;
+}
+
+div.course.break {
+       clear: left;
+}
+
+div.course h2 {
+       border: 0px;
+       font-weight: normal;
+       font-size: large;
+
+}
+
+div.course:hover {
+       background-color:#D1E3ED;
+       border: #AAAAAA 1px solid;
+}
+
+div.course a {
+       text-decoration: none;
+}
+
+div.course:hover a {
+       color: #006699;
+}
+
+div.course a:hover {
+       color: #000000;
+}
+
+div.course p {
+       font-size: small;
+}
+
+div.course p a {
+       font-weight: bold;
+}
+
+div.course img.icon    {
+       float: left;
+       margin: 2px;
+       height:6.8em;
+       width:6.8em;
+}
+
+div.course div.shortcuts {
+       text-align: right;
+       clear: left;
+       vertical-align: middle;
+}
+
+fieldset#shortcuts {
+       float: right;
+       background-color: #FAFAFA;
+       border: 1px solid #AAAAAA;
+       margin: -5px 5px 5px 5px;
+       padding-right: 10px;
+       padding-bottom: 5px;
+       padding-left: 10px;
+}
+
+legend {
+       padding-right: 10px;
+       padding-left: 10px;
+       border: 1px solid #AAAAAA;
+}
+
+fieldset {
+       margin-bottom: 10px;
+}
+#shortcuts legend {
+       color: #FFA500;
+       background-color: white;
+}
+#shortcuts ul {
+       position: relative;
+       margin-top: 0px;
+       margin-bottom: 0px;
+       margin-left: 0px;
+       list-style-type:  none;
+       padding-left: 0px; 
+}
+
+
+/* side-menu */
+h4.box {
+       margin-top: 10px;
+       font-family: Helevetica, Arial, sans-serif;
+       background: #efefef;
+       border: 1px solid #afafaf;
+       color: black;
+       white-space:nowrap;
+       padding: 0em 1em 0em 1em;
+       display: inline;
+       font-weight:normal;
+       margin-left: 0px;
+}
+
+div.box {
+    background: transparent;
+    border-collapse: collapse;
+    border: 1px solid #afafaf;
+    padding: 1em;
+       font-size: 85%;
+}
+
+div.box a:link {
+       text-decoration: none;
+}
+
+div.box a:visited {
+       color: #51286C;
+       text-decoration: none;
+}
+
+div.box a:hover {
+       text-decoration: underline;
+}
+
+a#guide {
+       background-image: url('images/guide.gif'); background-repeat: no-repeat; background-position: 7px 5px;
+       background-color: #eee;
+       padding: 2px 10px 2px 28px;
+       border: 1px solid #ccc;
+}
+
+label {
+       cursor: pointer;
+}
+
+/* AChat Styles  */
+body.chat {
+       background-color: #EBF4F9;
+       border-right: #006699 solid 1px;
+}
+
+table.chat-display {
+       border: #006699 solid 1px;
+       line-height:150%;
+}
+
+/* image relative sizing */
+
+/* course home imgs */
+.img-size-home {
+       height:3.85em;
+       width:3.9em;
+       margin-left: auto;
+       margin-right: auto;
+}
+/* prev/next imgs */
+.img-size-prevnext {
+       height:1.45em;
+       width:1.45em;
+}
+
+/* star */
+.img-size-star {
+       height:1.15em;
+       width:1.2em;
+}
+
+/* tree */
+.img-size-tree {
+       vertical-align: middle;
+       margin-top: 0px;
+       height:1.45em;
+       width:1.45em;
+}
+
+/* filemanager */
+.img-size-fm1 {
+       vertical-align: middle;
+       margin-top: 0px;
+       height:1.35em;
+       width:1.5em;
+}
+.img-size-fm2 {
+       vertical-align: middle;
+       margin-top: 0px;
+       height:1.25em;
+       width:1.25em;
+}
+
+.img-size-fm3 {
+       vertical-align: middle;
+       margin-top: 0px;
+       height:1.2em;
+       width:.86em;
+}
+
+.img-size-fm4 {
+       vertical-align: middle;
+       margin-top: 0px;
+       height:1.15em;
+       width:1.4em;
+}
+
+/* asc/desc arrows */
+.img-size-ascdesc {
+       height: 1.95em;
+       width:  1.95em;
+}
+
+.scormfeedback  {
+       font-family : Arial, Helvetica, Arial Cyr, Arial Ua, sans-serif;
+       color: #152065; /* #D15600; */
+       background: white;
+       font-weight : normal;
+       padding: 10px;
+       border: 1px solid black;
+}
+
+.scormitem  {
+       font-family : Arial, Helvetica, Arial Cyr, Arial Ua, sans-serif;
+       color: #152065; /* #D15600; */
+       background: white;
+       font-weight : normal;
+       padding: 0px;
+       display: inline;
+}
+
+.scorminput {
+       padding: 2px;
+}
+
+.scorminput:hover {
+}
+
+#rte {
+       float: right;
+       padding: 0px;
+       width:   0px;
+       height:  0px;
+}
+
+.header {      
+       background-image:url('images/pencils.jpg');
+       background-repeat:no-repeat;
+       background-color: #EBF4F9 /*#F9F9F9*/;
+       background-position:top right;
+}
+
+/* enrollment tabs */
+#navlist {
+       padding: 0px;
+       margin-left: 0;
+       margin-right: auto;
+       margin-left: auto;
+       margin-bottom: 4px;
+       white-space: nowrap;
+}
+
+#navlist li {
+       list-style: none;
+       display: inline;
+       margin: 0px;
+}
+
+#navlist li a {
+       padding: 3px 9px;
+       border: 1px solid #e0e0e0;
+       border-bottom: none;
+       background: #fafafa;
+       text-decoration: none;
+       margin-left: 4px;
+       -moz-border-radius-topright: 4px;
+       -moz-border-radius-topleft: 4px;
+       white-space: nowrap;
+}
+
+#navlist li a:hover, #navlist li a.active {
+       color: #000;
+       background: #fff;
+}
+
+/* MAIN TABS */
+div#topnavlistcontainer {
+       border-bottom: 1px solid #70A1CA;
+}
+ul#topnavlist {
+       padding: 0px;
+       margin-right: auto;
+       margin-left: auto;
+       margin-bottom: 3px;
+       margin-top: 0px;
+       white-space: nowrap;
+}
+
+ul#topnavlist li {
+       list-style: none;
+       display: inline;
+       margin: 0px;
+}
+
+ul#topnavlist li a {
+       padding: 3px 9px;
+       border: 1px solid #70A1CA;
+       background: #F4F9FE;
+       text-decoration: none;
+       margin-left: 1px;
+       -moz-border-radius-topright: 4px;
+       -moz-border-radius-topleft: 4px;
+       white-space: nowrap;
+       font-weight: bold;
+}
+ul#topnavlist li:first-child a {
+       margin-left: 10px;
+}
+
+ul#topnavlist li a:hover, ul#topnavlist li a.active, ul#topnavlist li a:focus {
+       color: #000;
+       background: white;
+       border-bottom: 1px solid white;
+}
+
+div#container {
+       text-align: left;
+       margin: 0px auto;
+       padding: 0px;
+       border:0;
+       width: 90%;
+}
+
+div.column {
+       border: 1px solid #e0e0e0;
+       float: left;
+       width: 45%;
+       margin: 5px;
+       padding: 0px;
+       min-width: 170px;
+}
+
+div.column h3 {
+       margin-left: 0px;
+}
+
+div.insidecol {
+   min-height: 170px;
+   height: 170px;
+   padding:5px;
+}
+div[class] .insidecol {
+   height: auto;
+}
+
+ul.horizontal {
+       padding: 0px;
+       margin: 0px;
+}
+ul.horizontal li {
+       list-style: none;
+       display: inline;
+       margin: 0px;
+       padding-right: 10px;
+}
+
+ul.rss_feed {
+       padding-left:7px; 
+       margin-left:7px; 
+       padding-top: 0px; 
+       margin-top:0px; 
+       margin-bottom:0px;
+}
+
+/* the tools page */
+/* ol#tools>li */ li.top-tool { 
+list-style: none;
+padding: 2px 2px 2px 15px;
+margin-bottom: 5px; 
+line-height: 200%; 
+background-color: #fdfdfd; 
+border-bottom: 1px solid #efefef; 
+-moz-border-radius: 4px; 
+border: 1px solid #eeeeff;}
+
+ol#tools>li:hover {
+       border: 1px solid #e0e0e0;
+       background-color: #f5f5ff;
+}
+
+li.top-tool a {  font-weight: bold; } /* ol#tools>li>a */ 
+
+li.child-tool a { 
+       font-size: x-small;
+       font-weight: normal; 
+}
+
+/* ol#tools>li>ul, */ ul.child-top-tool {
+       margin-top: -5px;
+       padding-left: 0px;
+       margin-left: 0px;
+       display: inline;
+}
+ul.child-top-tool:before {
+       content: " : ";
+}
+
+/* ol#tools>li>ul>li, */ li.child-tool {
+       display: inline;
+       margin-right: 5px;
+       font-size: x-small;
+}
+
+a.user {
+       background: url('images/user.gif') no-repeat;
+       background-position: left center;
+       padding-left: 20px;
+       padding-top: 5px;
+       padding-bottom: 5px;
+}
+a.user.instructor {
+       background-image: url('images/instructor.gif');
+}
+
+p.fm-desc {
+       font-size: small;
+}
+/* profile page */
+dl#public-profile, dl.col-list {
+       width: 100%;
+       padding-bottom: 25px;
+}
+dl#public-profile dt, dl.col-list dt {
+       float: left;
+       font-weight: bold;
+       width: 25%;
+       text-align: right;
+       clear: left;
+       padding: 5px 10px 5px 0px;
+       vertical-align: middle;
+}
+dl#public-profile dd, dl.col-list dd {
+       margin-bottom: 5px;
+       clear: right;
+       padding: 5px 0px 5px 10px;
+       margin-left: 26%;
+       border-left: 1px solid #e0e0ff;
+}
+
+dl.col-list dt { width: 30% }
+dl.col-list dd { margin-left: 32% }
+
+/* browse courses */
+dl.browse-course {
+       width: 100%;
+       padding-bottom: 25px;
+}
+dl.browse-course dt {
+       float: left;
+       font-weight: bold;
+       width: 25%;
+       text-align: right;
+       clear: left;
+       padding: 5px 10px 5px 0px;
+       vertical-align: middle;
+}
+dl.browse-course dd {
+       margin-bottom: 5px;
+       clear: right;
+       padding: 5px 0px 5px 10px;
+       margin-left: 26%;
+       border-left: 1px solid #e0e0ff;
+}
+
+/** forum stuff **/
+#forum-thread li { clear:left; border:1px solid #eee; border-bottom: 1px solid #f0f0f0; float:left; width: 98%; list-style: none; }
+#forum-thread li.even { background: #fdfdfd; border-top: none; }
+#forum-thread li.odd { background: #fff; }
+div.forum-post-author { float:left; width:150px; padding:8px 10px; }
+div.forum-post-author a.title {        font-size: 1.1em; line-height: 1.2em; font-weight: bold; text-decoration:none; }        
+div.forum-post-author img.profile-picture { border: 2px solid #f0f0f0; }
+div.forum-post-content { margin-left: 150px; padding: 5px 0px 18px 18px; }
+div.forum-post-content h3 { font-weight: 500; }
+div.forum-post-ctrl { float: right; padding-right: 5px; color: #a1a1a1; }
+div.forum-post-ctrl a { text-decoration: none; }
+div.forum-post-ctrl span { color: black; background-color: #fefdc2; padding: 3px; }
+div.forum-post-content p.date { color: #a1a1a1; border-bottom: 1px solid #f0f0f0; }
+div.forum-post-content div.body p { margin-bottom:20px; }
+
+/** inbox stuff - reuses some of the forum layout **/
+#inbox-msg li { clear:left; border:1px solid #eee; border-bottom: 1px solid #f0f0f0; width: 98%; list-style: none; }
+
diff --git a/themes/default15/theme.cfg.php b/themes/default15/theme.cfg.php
new file mode 100644 (file)
index 0000000..c93c4e5
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: theme.cfg.php 6481 2006-07-06 15:03:02Z joel $
+
+/* This is the default configuration file for the default theme. */
+
+/* The theme's name. */
+       $_theme['name'] = 'ATutor';
+
+/* The theme's version number. */
+       $_theme['version'] = '0.2';
+
+/* Which version of ATutor is this theme intended for. */
+       $_theme['atutor-version'] = '1.5.3';
+
+/* author information */
+       $_theme['author_name']  = 'ATutor';
+       $_theme['author_url']   = 'http://atutor.ca';
+       $_theme['author_email'] = '';
+
+/* theme default course banner styles: */
+       $_theme['banner']['font-family'] = 'Verdana, Arial, sans-serif';
+       $_theme['banner']['font-weight'] = 'bold';
+       $_theme['banner']['color']       = 'black';
+       $_theme['banner']['font-size']   = 'xx-large';
+       $_theme['banner']['text-align']  = 'center';
+
+       $_theme['banner']['background-color'] = 'white';
+       $_theme['banner']['background-image'] = '';
+       $_theme['banner']['vertical-align']   = 'middle';
+       $_theme['banner']['padding']          = '3px';
+
+?>
\ No newline at end of file
diff --git a/themes/default15/warningmessage.tmpl.php b/themes/default15/warningmessage.tmpl.php
new file mode 100644 (file)
index 0000000..c8ed8da
--- /dev/null
@@ -0,0 +1,20 @@
+<?php  
+/*
+ * @author Jacek Materna
+ *
+ *     One Savant variable: $item which is the processed ouput message content according to lang spec.
+ */
+ global $_base_href;
+?>
+
+<div id="warning">
+       <?php if (is_array($this->item)) : ?>
+               <ul>
+               <?php foreach($this->item as $e) : ?>
+                       <li><?php echo $e; ?></li>
+               <?php endforeach; ?>
+               </ul>
+       <?php endif; ?>
+</div>
\ No newline at end of file
diff --git a/themes/default_classic/ie_styles.css b/themes/default_classic/ie_styles.css
new file mode 100644 (file)
index 0000000..5767555
--- /dev/null
@@ -0,0 +1,23 @@
+/* IE specific styles */
+
+ul#topnavlist {
+       zoom:100%;
+       margin:0px;
+}
+
+ul#topnavlist li {
+       zoom:100%;
+       padding:0.3em;
+       padding-bottom:0.3em;
+       margin:0px;
+       margin-bottom:-1px;
+}
+
+label {
+       zoom:100%;
+       margin:0px;
+}
+
+table.data tfoot input {
+       min-width:0px;
+}
\ No newline at end of file
diff --git a/themes/default_classic/images/guide.gif b/themes/default_classic/images/guide.gif
new file mode 100644 (file)
index 0000000..124c24a
Binary files /dev/null and b/themes/default_classic/images/guide.gif differ
diff --git a/themes/default_classic/images/user-star.gif b/themes/default_classic/images/user-star.gif
new file mode 100644 (file)
index 0000000..e53b7d5
Binary files /dev/null and b/themes/default_classic/images/user-star.gif differ
diff --git a/themes/default_classic/include/footer.tmpl.php b/themes/default_classic/include/footer.tmpl.php
new file mode 100644 (file)
index 0000000..eae6155
--- /dev/null
@@ -0,0 +1,41 @@
+<?php if (!defined('AT_INCLUDE_PATH')) { exit; } ?>
+
+       <?php if ($_SESSION['course_id'] > 0): ?>
+               <br /><div align="right" id="gototop" style="vertical-align:bottom;padding-right:3px;font-size:smaller;"><a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#content" style="border: 0px;" title="<?php echo _AT('goto_content'); ?>" ><?php echo _AT('goto_top'); ?></a></div>  
+       <?php endif; ?>
+
+       </td>
+       <?php if (($_SESSION['course_id'] > 0) && $this->side_menu): ?>
+               <td valign="top">
+               <script type="text/javascript">
+               //<![CDATA[
+               var state = getcookie("side-menu");
+               if (state && (state == 'none')) {
+                       document.writeln('<div style="display:none;" id="side-menu">');
+               } else {
+                       document.writeln('<div style="" id="side-menu">');
+               }
+               //]]>
+               </script>
+                       <?php foreach ($this->side_menu as $dropdown_file): ?>
+                               <?php if (file_exists($dropdown_file)) { require($dropdown_file); } ?>
+                       <?php endforeach; ?>
+               <script type="text/javascript">
+               //<![CDATA[
+                       document.writeln('</div>');
+               //]]>
+               </script>
+               </td>
+       <?php endif; ?>
+</tr>
+<tr>
+       <td colspan="2">
+               <br /><br />
+               <?php require(AT_INCLUDE_PATH.'html/languages.inc.php'); ?>
+               <?php require(AT_INCLUDE_PATH.'html/copyright.inc.php'); ?>
+               <br />
+       </td>
+</tr>
+</table>
+</body>
+</html>
\ No newline at end of file
diff --git a/themes/default_classic/include/header.tmpl.php b/themes/default_classic/include/header.tmpl.php
new file mode 100644 (file)
index 0000000..4a7c63e
--- /dev/null
@@ -0,0 +1,304 @@
+<?php
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+
+global $system_courses, $_custom_css;
+
+?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html lang="<?php echo $this->lang_code; ?>">
+<head>
+       <title><?php echo SITE_NAME; ?> : <?php echo $this->page_title; ?></title>
+       <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $this->lang_charset; ?>" />
+       <meta name="Generator" content="ATutor - Copyright 2005 by http://atutor.ca" />
+       <base href="<?php echo $this->content_base_href; ?>" />
+       <link rel="shortcut icon" href="<?php echo $this->base_path; ?>favicon.ico" type="image/x-icon" />
+       <link rel="stylesheet" href="<?php echo $this->base_path; ?>themes/default/print.css" type="text/css" media="print" />
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/styles.css" type="text/css" />
+       <link rel="stylesheet" href="<?php echo $this->base_path; ?>themes/default/forms.css" type="text/css" />
+
+       <!--[if IE]>
+         <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/ie_styles.css" type="text/css" />
+       <![endif]-->
+
+       <?php echo $this->rtl_css; ?>
+       <style type="text/css"><?php echo $this->banner_style; ?></style>
+       <?php if ($system_courses[$_SESSION['course_id']]['rss']): ?>
+       <link rel="alternate" type="application/rss+xml" title="<?php echo SITE_NAME; ?> - RSS 2.0" href="<?php echo $this->base_href; ?>get_rss.php?<?php echo $_SESSION['course_id']; ?>-2" />
+       <link rel="alternate" type="application/rss+xml" title="<?php echo SITE_NAME; ?> - RSS 1.0" href="<?php echo $this->base_href; ?>get_rss.php?<?php echo $_SESSION['course_id']; ?>-1" />
+       <?php endif; ?>
+       <?php echo $this->custom_css; ?>
+</head>
+<body onload="setstates(); <?php echo $this->onload; ?>"><div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>
+<script language="JavaScript" src="<?php echo $this->base_path; ?>overlib.js" type="text/javascript"></script><script language="javascript" type="text/javascript">
+//<!--
+
+var newwindow;
+function poptastic(url) {
+       newwindow=window.open(url,'popup','height=600,width=600,scrollbars=yes,resizable=yes');
+       if (window.focus) {newwindow.focus()}
+}
+
+function getexpirydate(nodays){
+       var UTCstring;
+       Today = new Date();
+       nomilli=Date.parse(Today);
+       Today.setTime(nomilli+nodays*24*60*60*1000);
+       UTCstring = Today.toUTCString();
+       return UTCstring;
+}
+
+function setcookie(name,value,duration){
+       cookiestring=name+"="+escape(value)+";path=/;expires="+getexpirydate(duration);
+       document.cookie=cookiestring;
+       if(!getcookie(name)){
+               return false;
+       } else {
+               return true;
+       }
+}
+
+function getcookie(cookiename) {
+       var cookiestring=""+document.cookie;
+       var index1=cookiestring.indexOf(cookiename);
+       if (index1==-1 || cookiename=="") return ""; 
+       var index2=cookiestring.indexOf(';',index1);
+       if (index2==-1) index2=cookiestring.length; 
+       return unescape(cookiestring.substring(index1+cookiename.length+1,index2));
+}
+
+function setDisplay(objId) {
+       var toc = document.getElementById(objId);
+
+       var state = getcookie(objId);
+       if (document.getElementById(objId) && state && (state == 'none')) {
+               toggleToc(objId);
+       }
+}
+
+
+function setstates() {
+       return;
+       var objId = "side-menu";
+       var state = getcookie(objId);
+       if (document.getElementById(objId) && state && (state == 'none')) {
+               toggleToc(objId);
+       }
+
+       var objId = "toccontent";
+       var state = getcookie(objId);
+       if (document.getElementById(objId) && state && (state == 'none')) {
+               toggleToc(objId);
+       }
+
+}
+
+function showTocToggle(objId, show, hide, key, selected) {
+       if(document.getElementById) {
+               if (key) {
+                       var accesskey = " accesskey='" + key + "' title='"+ show + "/" + hide + " Alt - "+ key +"'";
+               } else {
+                       var accesskey = "";
+               }
+
+               if (selected == 'hide') {
+                       document.writeln('<a href="javascript:toggleToc(\'' + objId + '\')" ' + accesskey + '>' +
+                       '<span id="' + objId + 'showlink" style="display:none;">' + show + '</span>' +
+                       '<span id="' + objId + 'hidelink">' + hide + '</span>'  + '</a>');
+               } else {
+                       document.writeln('<a href="javascript:toggleToc(\'' + objId + '\')" ' + accesskey + '>' +
+                       '<span id="' + objId + 'showlink">' + show + '</span>' +
+                       '<span id="' + objId + 'hidelink" style="display:none;">' + hide + '</span>'    + '</a>');
+               }
+       }
+}
+
+function toggleToc(objId) {
+       var toc = document.getElementById(objId);
+       if (toc == null) {
+               return;
+       }
+       var showlink=document.getElementById(objId + 'showlink');
+       var hidelink=document.getElementById(objId + 'hidelink');
+       if (hidelink.style.display == 'none') {
+               toc.style.display = '';
+               hidelink.style.display='';
+               showlink.style.display='none';
+       } else {
+               toc.style.display = 'none';
+               hidelink.style.display='none';
+               showlink.style.display='';
+       }
+       setcookie(objId, toc.style.display, 1);
+}
+//-->
+</script>
+
+<div id="member-links" style="float: right;">
+       <!-- hidden direct link to content -->
+       <a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#content" style="border: 0px;" accesskey="c"><img src="<?php echo $this->base_path; ?>images/clr.gif" height="1" width="1" border="0" alt="<?php echo _AT('goto_content'); ?> ALT+c" /></a>
+
+       <?php if ($_SESSION['is_super_admin']): ?>
+               <a href="<?php echo $this->base_path; ?>bounce.php?admin"><?php echo _AT('return_to_admin_area'); ?></a> | 
+       <?php endif; ?>
+
+       <?php if ($_SESSION['valid_user']): ?>
+               <img src="<?php echo $this->img;?>user-star.gif" style="vertical-align: middle;" class="img-size-star" alt="" />
+               
+               <span style="font-weight:bold; color: white;"><?php echo get_display_name($_SESSION['member_id']); ?></span>  | 
+
+               <?php if ($_SESSION['course_id'] > -1): ?>
+                       <?php if (get_num_new_messages()): ?>
+                               <a href="<?php echo $this->base_path; ?>inbox/index.php"><?php echo _AT('inbox'); ?> - <?php echo get_num_new_messages(); ?></a> | 
+                       <?php else: ?>
+                               <a href="<?php echo $this->base_path; ?>inbox/index.php"><?php echo _AT('inbox'); ?></a> | 
+                       <?php endif; ?>
+               <?php endif; ?>
+               <a href="<?php echo $this->base_path; ?>search.php"><?php echo _AT('search'); ?></a> | 
+               <a href="<?php echo $this->base_path; ?>help/index.php"><?php echo _AT('help'); ?></a> |
+               <a href="<?php echo $this->base_path; ?>logout.php"><?php echo _AT('logout'); ?></a>
+       <?php else: ?>
+               <a href="<?php echo $this->base_path; ?>login.php?course=<?php echo $_SESSION['course_id']; ?>"><?php echo _AT('login'); ?></a> | 
+               <a href="<?php echo $this->base_path; ?>search.php"><?php echo _AT('search'); ?></a> | 
+               <a href="<?php echo $this->base_path; ?>help/index.php"><?php echo _AT('help'); ?></a>
+       <?php endif; ?>
+</div>
+<div style="float: right;">
+       <?php if (isset($_SESSION['course_id']) && ($_SESSION['course_id'] >= 0)): ?>
+               <!-- start the jump menu -->
+               <?php if (empty($_GET)): ?>
+                       <form method="post" action="<?php echo $this->base_path; ?>bounce.php?p=<?php echo urlencode($this->rel_url); ?>" target="_top">
+               <?php else: ?>
+                       <form method="post" action="<?php echo $this->base_path; ?>bounce.php" target="_top">
+               <?php endif; ?>
+               <label for="jumpmenu" accesskey="j"></label>
+                       <select name="course" id="jumpmenu" title="<?php echo _AT('jump'); ?>:  Alt-j">                                                 
+                               <option value="0" id="start-page"><?php echo _AT('my_start_page'); ?></option>
+                               <optgroup label="<?php echo _AT('courses_below'); ?>">
+                                       <?php foreach ($this->nav_courses as $this_course_id => $this_course_title): ?>
+                                               <option value="<?php echo $this_course_id; ?>"><?php echo $this_course_title; ?></option>
+                                       <?php endforeach; ?>
+                               </optgroup>
+                       </select> <input type="submit" name="jump" value="<?php echo _AT('jump'); ?>" id="jump-button" /></form>
+               <!-- /end the jump menu -->
+       <?php endif; ?>
+</div>
+
+<!-- the bread crumbs -->
+<div id="breadcrumbs" style="border-bottom:1pt solid #152065;">
+       <span style="white-space:nowrap;font-size:smaller;padding-top:150px;">
+       <?php if ($this->sequence_links['resume']): ?>
+                       <a href="<?php echo $this->sequence_links['resume']['url']; ?>" accesskey="." title="<?php echo _AT('resume').': '.$this->sequence_links['resume']['title']; ?>"><?php echo $this->sequence_links['resume']['title']; ?></a> - 
+       <?php endif; ?>
+       <?php foreach ($this->path as $page): ?>
+               <a href="<?php echo $page['url']; ?>" title="<?php echo _AT('back_to').' '.$page['title']; ?>"><?php echo $page['title']; ?></a> &raquo; 
+       <?php endforeach; ?> <?php echo htmlspecialchars($this->page_title, ENT_COMPAT, "UTF-8"); ?></span>
+</div>
+
+<div>
+       <div style="float:right;text-align:right;padding-top:5px;">
+       <?php if ($_SESSION['valid_user']) : 
+               echo '<span style="font-size:small;font-weight:bold;padding-left:5px;">'.stripslashes(SITE_NAME).'</span>'; 
+       endif; ?>
+
+       <h1 class="section-title">
+               <?php if (defined('AT_HEADER_LOGO') && AT_HEADER_LOGO): ?>
+                       <img src="<?php echo AT_HEADER_LOGO; ?>" border="0" alt="<?php echo SITE_NAME; ?>" />
+               <?php endif; ?> 
+               <!-- section title -->
+               <?php echo $this->section_title; ?>
+               <?php if (($_SESSION['course_id'] > 0) && ($_SESSION['enroll'] == AT_ENROLL_NO)) : ?>
+                       - <a href="<?php echo $this->base_path; ?>enroll.php?course=<?php echo $_SESSION['course_id']; ?>"><?php echo _AT('enroll_me'); ?></a></small>
+               <?php endif; ?></h1>
+       </div>
+
+       <div style="background-image: url('<?php echo AT_HEADER_IMAGE; ?>'); background-repeat: no-repeat; background-position:left;height:60px; width:250px; vertical-align:top; text-align:right;">&nbsp;</div>
+
+       <div id="topnavlistcontainer">
+       <!-- the main navigation. in our case, tabs -->
+               <ul id="topnavlist">
+                       <?php foreach ($this->top_level_pages as $page): ?>
+                               <?php ++$accesscounter; $accesscounter = ($accesscounter == 10 ? 0 : $accesscounter); ?>
+                               <?php $accesskey_text = ($accesscounter < 10 ? 'accesskey="'.$accesscounter.'"' : ''); ?>
+                               <?php $accesskey_title = ($accesscounter < 10 ? ' Alt+'.$accesscounter : ''); ?>
+                               <?php if ($page['url'] == $this->current_top_level_page): ?>
+                                       <li><a href="<?php echo $page['url']; ?>" <?php echo $accesskey_text; ?> title="<?php echo $page['title'] . $accesskey_title; ?>" class="active"><?php echo $page['title']; ?></a></li>
+                               <?php else: ?>
+                                       <li><a href="<?php echo $page['url']; ?>" <?php echo $accesskey_text; ?> title="<?php echo $page['title'] . $accesskey_title; ?>"><?php echo $page['title']; ?></a></li>
+                               <?php endif; ?>
+                               <?php $accesscounter = ($accesscounter == 0 ? 11 : $accesscounter); ?>
+                       <?php endforeach; ?>
+               </ul>
+       </div>
+</div>
+
+<!-- the sub navigation -->
+<div style="text-align: right; padding-top: 5px; padding-right: 5px; float:right"><small><?php echo $this->current_date; ?></small></div>
+<?php if ($this->sub_level_pages): ?>
+       <div id="sub-navigation">
+               <?php if (isset($this->back_to_page)): ?>
+                       <a href="<?php echo $this->back_to_page['url']; ?>" id="back-to"><?php echo _AT('back_to'); ?> <?php echo $this->back_to_page['title']; ?></a> | 
+               <?php endif; ?>
+
+               <?php $num_pages = count($this->sub_level_pages); ?>
+               <?php for($i=0; $i<$num_pages; $i++): ?>
+                       <?php if ($this->sub_level_pages[$i]['url'] == $this->current_sub_level_page): ?>
+                               <strong><?php echo $this->sub_level_pages[$i]['title']; ?></strong>
+                       <?php else: ?>
+                               <a href="<?php echo $this->sub_level_pages[$i]['url']; ?>"><?php echo $this->sub_level_pages[$i]['title']; ?></a>
+                       <?php endif; ?>
+                       <?php if ($i < $num_pages-1): ?>
+                               |
+                       <?php endif; ?>
+               <?php endfor; ?>
+       </div>
+<?php else: ?>
+       <div id="sub-navigation">
+               &nbsp;
+       </div>
+<?php endif; ?>
+
+<table align="center" border="0" cellpadding="0" cellspacing="0" width="100%">
+       <tr>
+               <?php if ($_SESSION['course_id'] > 0): ?>
+                       <td valign="top" width="100%">
+               <?php else: ?>
+                       <td valign="top" width="100%" colspan="2">
+               <?php endif; ?>
+
+<!-- the page title -->
+       <div style="text-align: right; padding-bottom: 10px; padding-right: 10px; float: right; margin-top: 10px; padding-right: 5px;">
+               <?php if ($this->guide): ?>
+                       <a href="<?php echo $this->guide; ?>" id="guide" onclick="poptastic('<?php echo $this->guide; ?>'); return false;" target="_new"><em><?php echo $this->page_title; ?></em></a>
+               <?php endif; ?>
+
+               <?php if ($_SESSION['course_id'] > 0): ?>
+                       <script type="text/javascript" language="javascript">
+                       //<![CDATA[
+                       var state = getcookie("side-menu");
+                       if (state && (state == 'none')) {
+                               showTocToggle("side-menu", "<?php echo _AT('show'); ?>","<?php echo _AT('hide'); ?>", "n", "show");
+                       } else {
+                               showTocToggle("side-menu", "<?php echo _AT('show'); ?>","<?php echo _AT('hide'); ?>", "n", "hide");
+                       }
+                       //]]>
+                       </script>
+               <?php endif; ?>
+       </div>
+
+       <div style="float:right;padding-top:7px;" id="sequence-links">
+               <?php if ($this->sequence_links['resume']): ?>
+                               <a style="color:white;" href="<?php echo $this->sequence_links['resume']['url']; ?>" accesskey="."><img src="<?php echo $this->base_href; ?>themes/default/images/resume.gif" border="0" title="<?php echo _AT('resume').': '.$this->sequence_links['resume']['title']; ?> Alt+." alt="<?php echo $this->sequence_links['resume']['title']; ?> Alt+." class="img-size-ascdesc" /></a>
+               <?php else:
+                       if ($this->sequence_links['previous']): ?>
+                               <a href="<?php echo $this->sequence_links['previous']['url']; ?>" title="<?php echo _AT('previous_topic').': '. $this->sequence_links['previous']['title']; ?> Alt+," accesskey=","><img src="<?php echo $this->base_href; ?>themes/default/images/previous.gif" border="0" alt="<?php echo _AT('previous_topic').': '. $this->sequence_links['previous']['title']; ?> Alt+," class="img-size-ascdesc" /></a>
+                       <?php endif;
+                       if ($this->sequence_links['next']): ?>
+                               <a href="<?php echo $this->sequence_links['next']['url']; ?>" title="<?php echo _AT('next_topic').': '.$this->sequence_links['next']['title']; ?> Alt+." accesskey="."><img src="<?php echo $this->base_href; ?>themes/default/images/next.gif" border="0" alt="<?php echo _AT('next_topic').': '.$this->sequence_links['next']['title']; ?> Alt+." class="img-size-ascdesc" /></a>
+                       <?php endif; ?>
+               <?php endif; ?>
+               &nbsp;
+       </div>
+
+       <h2 class="page-title"><?php echo htmlspecialchars($this->page_title, ENT_COMPAT, "UTF-8"); ?></h2>
+
+<a name="content"></a>
+<?php global $msg; $msg->printAll(); ?>
\ No newline at end of file
diff --git a/themes/default_classic/print.css b/themes/default_classic/print.css
new file mode 100644 (file)
index 0000000..cbecd5c
--- /dev/null
@@ -0,0 +1,13 @@
+body {
+       background-color: White;
+       font-family: Helvetica, arial, sans serif;
+       margin: 0px;
+       margin-top: 0px;
+       color: black;
+       border: 0px;
+}
+
+div#side-menu, div#member-links, span#side-menushowlink, span#side-menuhidelink, div#sequence-links, select#jumpmenu, a#guide, div#gototop, input#jump-button, div#topnavlistcontainer, a#guide, div#breadcrumbs, div#jump-area, table.tabbed-table, div#sub-navigation, div#sequence-links, div#language, div#toc, fieldset#shortcuts {
+       display: none;
+}
+
diff --git a/themes/default_classic/rtl.css b/themes/default_classic/rtl.css
new file mode 100644 (file)
index 0000000..b95ecf0
--- /dev/null
@@ -0,0 +1,14 @@
+/* for right to left languages */
+html, body {
+       direction: rtl;
+}
+
+/* required for mozilla browsers*/
+.img-size-tree {
+       vertical-align: middle;
+       margin-top: 0px;
+       height:1.45em;
+       width:1.45em;
+       text-align: right.;
+       float: right;
+}
\ No newline at end of file
diff --git a/themes/default_classic/screenshot.gif b/themes/default_classic/screenshot.gif
new file mode 100644 (file)
index 0000000..3c5df00
Binary files /dev/null and b/themes/default_classic/screenshot.gif differ
diff --git a/themes/default_classic/styles.css b/themes/default_classic/styles.css
new file mode 100644 (file)
index 0000000..3b505d7
--- /dev/null
@@ -0,0 +1,1210 @@
+/* main body attributes */
+body {
+       font-family: Helevetica, Arial, sans-serif;
+       margin-top: 0px;
+       margin-left: 0px;
+       margin-right: 0px;
+       /* max-width: 760px; */
+       margin-bottom: 0px;
+       font-size: small;
+       background-color: white;
+       /*border-right: 1px solid #788CB3;*/
+       width:100%;
+}
+
+html,body {
+       height: 100%;
+}
+
+/* heading attributes */
+h1, h2, h3, h4, h5, h6 {
+       font-family: trebuchet ms, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-left: 5px;
+       margin-right: 0px;
+       color: #152065; /* #D15600; */
+}
+
+/* paragraph attributes */
+p {
+       font-family: Helevetica, Arial, sans-serif;
+       margin-bottom: 10px;
+       margin-top: 0px;
+       margin-left: 5px;
+       margin-right: 0px;
+} 
+
+/* list attributes */
+ul {
+       font-family: Helevetica, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+
+li {
+       font-family: Helevetica, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+
+/* for filemanager */
+li.folders {
+       list-style: disc url('../../images/folder.gif') outside;
+       font-family: Helevetica, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+
+/* link attributes */
+a:link {
+       font-family: Helevetica, Arial, sans-serif;
+       color: #384F89;
+       text-decoration: underline;
+}
+a:visited {
+       font-family: Helevetica, Arial, sans-serif;
+       color: #51286C;
+       text-decoration: underline;
+}
+a:hover {
+       font-family: Helevetica, Arial, sans-serif;
+       color: black;
+       text-decoration: underline;
+}
+
+/*  Table of content attributes*/
+div#toc{
+       font-family: Helevetica, Arial, sans-serif;
+       background-color: #eeeeee;
+       padding: 5px;
+       margin: 0px 5px 5px 5px;
+       border: 1px #98AAB1 solid;
+       float: left;
+       font-size: smaller;
+}
+
+/* table border */
+.tableborder {
+       border: 1px #606060 solid;
+}
+
+/* main submit button */
+.button {
+       font-family: Helevetica, Arial, sans-serif;
+       background-color: #EBEDF6;
+       font-weight: bold;
+       border:  #354A81  solid 1px;
+}
+
+input.button {
+       border: 1px solid #999;
+       background-color: white;
+       padding: 2px;
+       padding-left: 10px;
+       padding-right: 10px;
+       min-width: 100px;
+       margin-left: 5px;
+}
+input.button:hover {
+       background-color: #f5f5ff;
+       border: 1px solid blue;
+}
+
+/* page breakline */
+hr {
+       color: #98AAB1;
+       background-color: white;
+       height: 1px;
+}
+
+/* Editor boxes */
+.editorsmallbox {
+       font-family: Helevetica, Arial, sans-serif;
+       background-color: #EEEEEE;
+       padding: 2px;
+       padding-right: 3px;
+       border: 1px #99CCCC solid;
+}
+.editorlargebox {
+       font-family: Helevetica, Arial, sans-serif;
+       background-color: #EEEEEE;
+       margin-left:1em;
+       padding-left: .2em;
+       padding-right: .5em;
+       padding-top: .5em;
+       padding-bottom: .4em;
+       border: 1px #99CCCC solid;
+}                                                          
+
+/* feedback for translators and install */
+.feedback2  {
+  font-family : Arial, Helvetica, Arial Cyr, Arial Ua, sans-serif;
+  color : white;
+  background: green;
+  font-weight : bold;
+  padding: 4px;
+ }
+
+/* search results */
+.highlight, a.highlight {
+       background-color: yellow;
+}
+
+a .highlight{
+       background-color: yellow;
+       text-decoration: underline;
+}
+
+.results {
+       padding-left: 20px;
+}
+
+h5.search-results {
+       background-color: #FFF5A4;
+       color: #006699;
+       padding: 1px;
+       margin-bottom: 5px;
+       margin-top: 10px;
+       margin-left: 5px;
+}
+
+small.search-info {
+       color: #006699;
+}
+
+p.search-description {
+       background-color: #FFFCE5;
+       color: #006699;
+}
+
+/* date attributes */
+small.date {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: #8CACBB; 
+       margin-bottom: 0px; 
+       margin-top: 0px;
+       margin-left: 5px;
+       margin-right: 0px;
+       font-size:small;
+}
+
+/* content editor tabs */
+
+.etable {
+       border-left:1pt solid black;
+       border-right:1pt solid black;
+       border-bottom:1pt solid black;
+       width:90%;
+}
+
+/* button link on tab */
+.buttontab {
+       font-family: Helvetica, Arial, Helvetica, sans-serif;
+       background-color: #ffffff;
+       border: 0px;
+       color: black;
+       font-size:small;
+}
+
+/* button link for enrollment tabs */
+.buttontab2 {
+       font-family: Helvetica, Arial, Helvetica, sans-serif;
+       background-color: #EFEFEF;
+       border: 0px;
+       color: black;
+       font-size:small;
+}
+
+/* tab itself */
+.etab {
+       background-color: #ffffff;
+       border-top: 1px #98AAB1 solid;
+       border-left: 1px #98AAB1 solid;
+       border-right: 1px #98AAB1 solid;
+       text-align: center;
+}
+
+.etab-selected {
+       background-color: #EFEFEF;
+       border-top: 1px #98AAB1 solid;
+       border-left: 1px  #98AAB1 solid;
+       border-right: 1px #98AAB1 solid;
+       text-align: center;
+       padding: 2px;
+       font-weight:bold;
+}
+
+div.top {
+    /* Top section */
+    background: transparent;
+    margin: 0;
+    padding: 0;
+}
+div.etabs {
+    background: transparent;
+    border-collapse: collapse;
+    border-bottom-color: #8CACBB;
+    border-bottom-style: solid;
+    border-bottom-width: 1px;
+    padding: 0.5em 0em 0em 2em;
+    white-space: nowrap;
+       font-size:smaller;
+}
+
+div.etabs plain {
+    background: transparent;
+    border-color: #8CACBB;
+    border-width: 1px; 
+    border-style: solid solid none solid;
+    color: #436976;
+    font-weight: normal;
+    height: 1.2em;
+    margin-right: 0.5em;
+    padding: 0em 2em;
+    text-transform: lowercase;
+}
+
+div.etabs selected {
+    background: #DEE7EC;
+    border: 1px solid #8CACBB;
+    border-bottom: #DEE7EC 1px solid;
+    color: #436976;
+    font-weight: normal;
+}
+
+
+
+/* status bar */
+.unsaved, .saved {
+       text-align:right;
+       padding-right:20px;
+       padding-top:5px;
+       padding-bottom:10px;
+}
+
+.saved input, .unsaved input {
+       border: 1px solid black;
+       background-color: white;
+    font-weight: normal;
+}
+
+#body_text {
+       width:75%;
+}
+
+/* side menu heading */
+td.dropdown-heading {
+       background-color: #D4E5FD;
+       color: #006699;
+       border-left: 1px solid #EAF2FE;
+       border-right: 1px solid #EAF2FE;
+       border-top: 1px solid #EAF2FE;
+       font-weight: bold;
+       padding: 2px;
+}
+
+td.dropdown-heading a, td.dropdown-heading a:hover, td.dropdown-heading a:visited {
+       text-decoration: none;
+}
+
+td.dropdown-heading.closed {
+       border-bottom: 1px solid #EAF2FE;
+}
+
+/* side menu content */
+td.dropdown {
+       padding: 2px;
+       background-color: white;
+       color: black;
+       border-left: 1px solid #EAF2FE;
+       border-right: 1px solid #EAF2FE;
+       border-bottom: 1px solid #EAF2FE;
+       font-weight: normal;
+}
+td.dropdown a, td.dropdown a:visited  {
+       color: #006699;
+       text-decoration: none;
+}
+td.dropdown a:hover {
+       color: #006699;
+       text-decoration: underline;
+}
+
+td.dropdown strong {
+       color: #51286C;
+}
+
+/* test listing on home page */
+
+.test-box {
+       background-color: #FFF5A4;
+       color: #006699;
+       border-left: 1px solid #006699;
+       border-right: 1px solid #006699;
+       border-top: 1px solid #006699;
+       font-weight: bold;
+       padding: 2px;
+}
+
+/* message boxes */
+div#feedback {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid green;
+       padding: 5px;
+       background-color: #c3fffc;
+       color: green;
+       font-weight: bold;
+}
+
+div#help {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid blue;
+       padding: 5px;
+       background-color: #c3ffff;
+       color: blue;
+}
+
+div#info {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #2905A1;
+       padding: 5px;
+       background-color: #CDE3E8;
+       color: #2905A1;
+       font-weight: bold;
+}
+
+div#warning {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #FF8400;
+       padding: 5px;
+       background-color: #FFF6ED;
+       color: #D95900;
+       font-weight: bold;
+}
+
+/***************************************************************/
+/* NEW STUFF */
+
+a#back-to {
+       padding-left: 20px;
+       background-image: url('../default/images/back.gif');
+       background-repeat: no-repeat;
+       background-position: 0px 0px;
+       height:1.45em;
+       width:1.45em;
+}
+
+div#breadcrumbs {
+       margin-bottom: 0px;
+       margin-top: 0px;
+       padding-left: 5px;
+       padding-right: 5px;
+       padding-bottom: 10px;
+       font-size: small;
+       background-color: #788CB3;
+       color: white;
+}
+div#breadcrumbs a, div#member-links a {
+       color: white;
+}
+div#breadcrumbs a:hover, div#member-links a:hover{
+       text-decoration:none;
+}
+
+div#breadcrumbs a:focus, div#member-links a:focus {
+       text-decoration:none;
+       font-weight: bold;
+       color: #FFFF00;
+}
+
+div#member-links {
+       margin-top:3px;
+       padding-right:5px;
+}
+
+h2.page-title {
+       margin-bottom: 10px;
+       margin-top: 10px;
+       margin-left: 5px;
+       border-bottom: 1px solid #f0f0f0;
+       clear: left;
+}
+
+h1 {
+       margin-bottom: 5px;
+}
+
+div#sub-navigation {
+       padding: 5px;
+       background-color: #FFFCE5;
+       border-bottom: 1px solid #9DAB9A;
+       color: #9DAB9A;
+}
+
+div#sub-navigation strong {
+       color: black;
+}
+
+div#help {
+       border-left: 1px solid black;
+       border-right: 1px solid black;
+       border-bottom: 1px solid black;
+       padding-left: 5px;
+       padding-right: 5px;
+       padding-bottom: 5px;
+       background-color: #efefef;
+       margin-left: 5px;
+       margin-right: 5px;
+       font-size: small;
+}
+
+h3#help-title {
+       margin-left: 5px;
+       margin-right: 5px;
+       border-left: 1px solid black;
+       border-right: 1px solid black;
+       padding: 1px;
+       background-color: #efefef;
+}
+.line {
+       border-bottom: 1px solid black;
+}
+div#help p {
+       padding: 0px;
+       margin: 0px;
+}
+
+div#toctoggle {
+       float: left;
+       font-size: smaller;
+       padding-left: 10px;
+}
+
+h1#section-title {
+       margin-left: 5px;
+       clear: none;
+       display:inline;
+       background-color: white;
+}
+
+div#top-links {
+       position: relative;
+       padding-right: 5px;
+       line-height: 170%;
+       margin-top: 3px;
+}
+
+a#editor-link {
+       background-color: #EFEFEF;
+       padding-top: 1px;
+       padding-bottom: 1px;
+       padding-left: 15px;
+       padding-right: 8px;
+       border: 1px solid #cccccc;
+       font-weight: normal;
+       text-decoration: none;
+}
+
+a#editor-link:hover {
+       background-color: #fafafa;
+       border: 1px solid #aaaaaa;
+}
+
+a#editor-link.off {
+       background-image: url('../default/images/pen.gif');
+       background-repeat: no-repeat;
+       background-position: 0px 2px;
+}
+a#editor-link.on {
+       background-image: url('../default/images/pen2.gif');
+       background-repeat: no-repeat;
+       background-position: 0px 2px;
+}
+
+
+/* for data tables */
+table.data {
+       clear:right;
+       border: 1px solid #f0f0f0;
+       width: 90%; 
+       margin-left: auto; 
+       margin-right: auto;
+       border-spacing: 0px;
+       border-collapse: collapse;
+} 
+
+table.data th {
+       background-color: #fafafa;
+       padding: 3px;
+       white-space: nowrap;
+}
+
+table.data tbody {
+       background-color: #fdfdfd;
+}
+
+table.data tbody th {
+       text-align: left;
+       background-color: #fdfdfd;
+       cursor: auto;
+}
+
+table.data td {
+       padding: 3px;
+}
+
+table.data col.sort + td {
+       padding: 7px;
+       background-color: red;
+}
+
+table.data tbody tr:hover {
+       background-color: #f5f5ff;
+       cursor: pointer;
+}
+
+table.data tbody tr.selected {
+       background-color: #f5f5ff;
+       cursor: auto;
+}
+
+table.data tfoot {
+       background-color: #fafafa;
+}
+
+table.data tfoot tr:first-child td {
+       padding: 5px;
+       background-image: url('../default/images/arrow_ltr.gif');
+       background-repeat: no-repeat;
+       background-position: 4px 5px;
+       padding-left: 40px;
+}
+
+table.data.static tfoot td, table.data.static tfoot tr:first-child td {
+       padding: 5px;
+       background-image: none;
+       padding-left: 0px;
+}
+
+table.data tfoot input {
+       border: 1px solid #999;
+       background-color: white;
+       padding: 2px;
+       padding-left: 10px;
+       padding-right: 10px;
+       max-width: 60%;
+       min-width: 100px;
+       margin-left: 5px;
+}
+
+/* used for static tables with no form elements */
+table.data.static tbody tr:hover {
+       background-color: transparent;
+       cursor: auto;
+}
+
+table.data tfoot input[type=submit]:hover {
+       background-color: #f5f5ff;
+}
+
+/* course browser */
+
+div#browse {
+       margin-left: auto; 
+       margin-right: auto; 
+       width: 80%;
+}
+
+div.browse-selected {
+       background-image: url('../default/images/side_arrow.gif'); 
+       background-repeat: no-repeat; 
+       padding-left: 9px; 
+       background-position: center left;
+}
+
+div.browse-unselected {
+       padding-left: 9px; 
+}
+
+ul.browse-list {
+       list-style: none;
+       padding:0px;
+}
+
+/* feedback/errors */
+div#error {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid red;
+       padding: 5px;
+       background-color: #fffcf3;
+       color: red;
+       background: #FBF4ED url('../default/images/error-large.gif') no-repeat scroll 5px 5px;
+       padding-left: 25px;
+       font-weight: bold;
+}
+div#error h4 {
+       color: black;
+       margin-left: 0px;
+}
+
+div#error ul, div#feedback ul, div#help ul {
+       position: relative;
+       list-style: none;
+       margin-left: 0px;
+       padding-left: 0px;
+}
+div#error li + li, div#feedback li + li {
+       margin-top: 5px;
+}
+
+acronym {
+       cursor: help;
+}
+
+div.news p {
+       margin-left: 10px;
+}
+div.news span.date {
+       color: #ACACAC;
+}
+
+/* home page links */
+ul#home-links {
+       list-style: none;
+}
+ul#home-links li {
+       display: inline;
+       float: left;
+       padding: 0.5em;
+       text-align: center;
+       margin: 0.2em;
+       width: 7.9em;
+       height: 7.4em;
+}
+ul#home-links li a {
+       text-decoration: none;
+       border: 1px transparent;
+       font-weight: bold;
+}
+ul#home-links li a img {
+       border: 0px;
+       display: block;
+}
+
+a.sortable {
+       color: blue;
+       text-decoration: underline;
+       font-weight: bold;
+}
+
+/* sequence links */
+div#sequence-links {
+       float: right;
+       margin-top: 10px;
+       padding-right: 5px;
+}
+div#sequence-links a {
+       text-decoration: none;
+}
+
+div.dropdown {
+       width: 200px;
+       padding: 2px;
+       background-color: white;
+       color: black;
+       border-left: 1px solid #EAF2FE;
+       border-right: 1px solid #EAF2FE;
+       border-bottom: 1px solid #EAF2FE;
+       font-weight: normal;
+}
+
+div.dropdown-heading {
+       background-color: #DFE1C7;
+       color: #006699;
+       border-left: 1px solid #EAF2FE;
+       border-right: 1px solid #EAF2FE;
+       border-top: 1px solid #EAF2FE;
+       font-weight: bold;
+       padding: 2px;
+}
+
+div.required {
+       font-weight: bold;
+       color: red;
+       font-size: xx-large;
+       float: left;
+       position: relative;
+       margin-top: -5px;
+       height: 15px;
+       padding-right: 2px;
+}
+
+div#content-text {
+       margin-left: 5px;
+       padding-right: 5px;
+}
+
+div#content-info {
+       margin: 5px;
+       font-size: smaller;
+       color: #cacaca;
+       clear: both;
+}
+
+form {
+       clear: none;
+       display:inline;
+}
+
+/* images in jump select box */
+option#start-page {
+       color: black;
+       text-decoration: none;
+       padding-left: 15px;
+       border-bottom: 1px solid black;
+}
+
+#jump-button {
+       padding: 0px;
+       background-color: #5E6D89;
+       color: white;
+       border: 1px solid #cccccc;
+       cursor: pointer;
+}
+#jump-button:focus, #jump-button:hover {
+       padding: 0px;
+       background-color: #AE8DA9;
+       color: white;
+       border: 1px solid #cccccc;
+       cursor: pointer;
+}
+#jumpmenu, optgroup {
+       font-size: smaller;
+}
+
+/* paging */
+div.paging {
+   width: 100%;
+   text-align: center;
+   margin: 0.5em auto;
+}
+div.paging ul {
+   list-style: none;
+   display: inline;
+   padding: 0px;
+   border: 1px solid #000;
+}
+div.paging li { 
+       display: inline; 
+       padding-left: 2px; 
+       padding-right: 2px;
+       padding-top: 0px;
+       padding-bottom: 0px;
+}
+
+div.paging li a {
+       text-decoration: none;
+       padding-left: 4px;
+       padding-right: 4px;
+       border-left: 1px solid white;
+       border-right: 1px solid white;
+}
+
+div.paging li a:hover, div.paging li a.current {
+   background-color: #efefef;
+   border-left: 1px solid #000;
+   border-right: 1px solid #000;
+}
+
+
+/* users/index.php */
+
+div.course {
+       position: relative;
+       width: 300px;
+       border: rgb(204, 204, 204) 1px solid;
+       background-color: #FFFCE5;
+       float: left;
+       margin: 3px;
+       padding: 3px;
+       height: 10.5em;
+}
+
+div.course.break {
+       clear: left;
+}
+
+div.course h2 {
+       border: 0px;
+       font-weight: normal;
+       font-size: large;
+
+}
+
+div.course:hover {
+       background-color: #FFF8C8;
+       border: #AAAAAA 1px solid;
+}
+
+div.course a {
+       text-decoration: none;
+}
+
+div.course:hover a {
+       color: #006699;
+}
+
+div.course a:hover {
+       color: #000000;
+}
+
+div.course p {
+       font-size: small;
+}
+
+div.course p a {
+       font-weight: bold;
+}
+
+div.course img.icon    {
+       float: left;
+       margin: 2px;
+       height:6.1em;
+       width:6.1em;
+}
+
+div.course div.shortcuts {
+       text-align: right;
+       clear: left;
+       vertical-align: middle;
+}
+
+fieldset#shortcuts {
+       float: right;
+       background-color: #FAFAFA;
+       border: 1px solid #AAAAAA;
+       margin: -5px 5px 5px 5px;
+       padding-right: 10px;
+       padding-bottom: 5px;
+       padding-left: 10px;
+}
+
+legend {
+       padding-right: 10px;
+       padding-left: 10px;
+}
+
+fieldset {
+       margin-bottom: 10px;
+}
+#shortcuts legend {
+       color: orange;
+       background-color: white;
+}
+#shortcuts ul {
+       position: relative;
+       margin-top: 0px;
+       margin-bottom: 0px;
+       margin-left: 0px;
+       list-style-type:  none;
+       padding-left: 0px; 
+}
+
+
+/* side-menu */
+h4.box {
+       margin-top: 10px;
+       font-family: Helevetica, Arial, sans-serif;
+    background: #788CB3;
+    border: 1px solid #788CB3;
+    color: white;
+    padding: 0em 1em 0em 1em;
+    display: inline;
+       font-weight:normal;
+       margin-left: 0px;
+       margin-top: 1000px;
+       white-space:nowrap;
+}
+
+div.box {
+    background: transparent;
+    border-collapse: collapse;
+    border-left: 1px solid #788CB3;
+    border-top: 1px solid #788CB3;
+    border-bottom: 1px solid #788CB3;
+    border-right: 1px solid #788CB3;
+    padding: 1em;
+       font-size: 85%;
+}
+
+div.box a {
+       text-decoration: none;
+}
+
+div.box a:hover {
+       text-decoration: underline;
+}
+
+/* image relative sizing */
+
+/* course home imgs */
+.img-size-home {
+       height:3.85em;
+       width:3.9em;
+       margin-left: auto;
+       margin-right: auto;
+}
+/* prev/next imgs */
+.img-size-prevnext {
+       height:1.45em;
+       width:1.45em;
+}
+
+/* star */
+.img-size-star {
+       height:1.15em;
+       width:1.2em;
+}
+
+/* tree */
+.img-size-tree {
+       vertical-align: middle;
+       margin-top: 0px;
+       height:1.45em;
+       width:1.45em;
+}
+
+/* filemanager */
+.img-size-fm1 {
+       vertical-align: middle;
+       margin-top: 0px;
+       height:1.35em;
+       width:1.5em;
+}
+.img-size-fm2 {
+       vertical-align: middle;
+       margin-top: 0px;
+       height:1.25em;
+       width:1.25em;
+}
+
+.img-size-fm3 {
+       vertical-align: middle;
+       margin-top: 0px;
+       height:1.2em;
+       width:.86em;
+}
+
+.img-size-fm4 {
+       vertical-align: middle;
+       margin-top: 0px;
+       height:1.15em;
+       width:1.4em;
+}
+
+/* asc/desc arrows */
+.img-size-ascdesc {
+       height:1.95em;
+       width:1.95em;
+}
+
+a#guide {
+       background-image: url('images/guide.gif'); background-repeat: no-repeat; background-position: 7px 5px;
+       background-color: #eee;
+       padding: 2px 10px 2px 28px;
+       border: 1px solid #ccc;
+}
+
+/* enrollment tabs */
+#navlist {
+       padding: 0px;
+       margin-left: 0;
+       margin-right: auto;
+       margin-left: auto;
+       margin-bottom: 4px;
+       white-space: nowrap;
+}
+
+#navlist li {
+       list-style: none;
+       display: inline;
+       margin: 0px;
+}
+
+#navlist li a {
+       padding: 3px 9px;
+       border: 1px solid #e0e0e0;
+       border-bottom: none;
+       background: #fafafa;
+       text-decoration: none;
+       margin-left: 4px;
+       -moz-border-radius-topright: 4px;
+       -moz-border-radius-topleft: 4px;
+       white-space: nowrap;
+}
+
+#navlist li a:hover, #navlist li a.active {
+       color: #000;
+       background: #fff;
+}
+
+/* MAIN TABS */
+div#topnavlistcontainer {
+       border-bottom: 1px solid #9DAB9A;
+}
+ul#topnavlist {
+       padding: 0px;
+       margin-right: auto;
+       margin-left: auto;
+       margin-bottom: 3px;
+       white-space: nowrap;
+       margin-top: -20px;
+}
+
+ul#topnavlist li {
+       list-style: none;
+       display: inline;
+       margin: 0px;
+}
+
+ul#topnavlist li a {
+       padding: 3px 9px;
+       border: 1px solid #9DAB9A;
+       background: #FFF8C8;
+       text-decoration: none;
+       margin-left: 3px;
+       -moz-border-radius-topright: 4px;
+       -moz-border-radius-topleft: 4px;
+       white-space: nowrap;
+       font-weight: bold;
+}
+ul#topnavlist li:first-child a {
+       margin-left: 8px;
+}
+
+ul#topnavlist li a:hover, ul#topnavlist li a.active, ul#topnavlist li a:focus {
+       color: #000;
+       background: #FFFCE5;
+       border-bottom: 1px solid #FFFCE5;
+}
+
+div#container {
+       text-align: left;
+       margin: 0px auto;
+       padding: 0px;
+       border:0;
+       width: 90%;
+}
+
+div.column {
+       border: 1px solid #e0e0e0;
+       float: left;
+       width: 30%;
+       margin: 5px;
+       padding: 0px;
+       min-width: 170px;
+}
+
+div.column h3 {
+       margin-left: 0px;
+}
+
+div.insidecol {
+   min-height: 170px;
+   height: 170px;
+   padding:5px;
+}
+div[class] .insidecol {
+   height: auto;
+}
+ul.horizontal{
+       padding: 0px;
+       margin: 0px;
+}
+ul.horizontal li {
+       list-style: none;
+       display: inline;
+       margin: 0px;
+       padding-right: 10px;
+}
+
+ul.rss_feed {
+       padding-left:7px; 
+       margin-left:7px; 
+       padding-top: 0px; 
+       margin-top:0px; 
+       margin-bottom:0px;
+}
+
+/* the tools page */
+ol#tools { width: 90%; }
+/* ol#tools>li */ li.top-tool { padding: 2px 2px 2px 15px; margin-bottom: 5px; line-height: 200%; background-color: #fdfdfd; border-bottom: 1px solid #efefef; -moz-border-radius: 4px; list-style-position: inside;  border: 1px solid #eeeeff;}
+
+ol#tools>li:hover {
+       border: 1px solid #e0e0e0;
+       background-color: #f5f5ff;
+}
+
+/* ol#tools>li>a */ li.top-tool a {  font-weight: bold; }
+
+li.child-tool a { font-size: x-small; font-weight: normal; }
+
+/* ol#tools>li>ul, */ ul.child-top-tool {
+       margin-top: -5px;
+       padding-left: 0px;
+       margin-left: 0px;
+       display: inline;
+}
+ul.child-top-tool:before {
+       content: " : ";
+}
+
+/* ol#tools>li>ul>li, */ li.child-tool {
+       display: inline;
+       margin-right: 5px;
+       font-size: x-small;
+}
+/* profile page */
+dl#public-profile {
+       width: 100%;
+}
+dl#public-profile dt {
+       float: left;
+       font-weight: bold;
+       width: 30%;
+       text-align: right;
+       clear: left;
+       border-right: 1px solid #f0f0f0;
+       padding: 5px 5px 5px 0px;
+       vertical-align: middle;
+       margin-right: 5px;
+}
+dl#public-profile dd {
+       margin-bottom: 5px;
+       clear: right;
+       padding: 5px 0px 5px 5px;
+}
\ No newline at end of file
diff --git a/themes/default_classic/theme.cfg.php b/themes/default_classic/theme.cfg.php
new file mode 100644 (file)
index 0000000..32c5498
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+
+/* This is the default configuration file for the default theme. */
+
+/* The theme's name. */
+       $_theme['name'] = 'ATutor Classic';
+
+/* The theme's version number. */
+       $_theme['version'] = '0.2';
+
+/* Which version of ATutor is this theme intended for. */
+       $_theme['atutor-version'] = '1.5.3';
+
+/* author information */
+       $_theme['author_name']  = 'ATutor';
+       $_theme['author_url']   = 'http://atutor.ca';
+       $_theme['author_email'] = '';
+
+
+/* Top left header image  - approximately w:230 x h:90                                 */
+/* Default: images/pub_default.jpg                                                                             */      
+/* The path to the image must be an absolute path, or use $_base_href   */
+/* if it's in the ATutor installation directory.                        */
+define('AT_HEADER_IMAGE',                                      $_base_path. 'images/pub_default.jpg');
+
+/* Top right logo default: images/at-logo.gif */
+/* The path to the image must be an absolute path, or use $_base_href   */
+/* if it's in the ATutor installation directory.                        */
+define('AT_HEADER_LOGO',                                       $_base_path . 'images/at-logo.gif');
+
+?>
diff --git a/themes/fluid/at_fluid.css b/themes/fluid/at_fluid.css
new file mode 100644 (file)
index 0000000..e46eb57
--- /dev/null
@@ -0,0 +1,29 @@
+
+.orderable-default {
+       float:left;
+       margin:5px!important;
+}
+/*.orderable-hover {
+       float:left;
+       margin:5px!important;
+}*/
+
+.orderable-selected{
+       float:left;
+       margin:5px!important;
+}
+
+.orderable-dragging{
+       background-color:#eee;
+       float:left;
+       margin:5px!important;
+       opacity:.2;
+       /*filter:alpha(opacity=20);*/
+}
+
+div .orderable-drop-marker{
+       height:160px!important;
+       width:4px;
+       background-color:red;
+       float:left;
+}
\ No newline at end of file
diff --git a/themes/fluid/fluid.zip b/themes/fluid/fluid.zip
new file mode 100644 (file)
index 0000000..6ebd57b
Binary files /dev/null and b/themes/fluid/fluid.zip differ
diff --git a/themes/fluid/forms.css b/themes/fluid/forms.css
new file mode 100644 (file)
index 0000000..5dc9ccd
--- /dev/null
@@ -0,0 +1,66 @@
+div.input-form {
+       width: 90%; 
+
+       margin-left:auto; 
+       margin-right:auto;
+       border: 0px;
+       margin-bottom: 20px;
+       line-height:150%;
+       background-color: #F8F8F8;
+
+}
+
+div.input-form div.row h3 {
+       margin-left: 0px;
+}
+
+
+div.input-form div.row {
+       background-color: #F8F8F8;
+       padding:8px;
+}
+
+div.input-form .footer {
+       border-top: 1px solid #F9F6F2;
+}
+
+div.input-form p {
+       margin-left: 0px;
+}
+
+div.input-form input {
+       z-index: 2;
+}
+div.input-form textarea {
+       border: 1px solid #595241;
+       width: 98%;
+       padding: 2px;
+       margin-right: 2px;
+}
+
+div.input-form textarea:focus {
+       border:1px solid #A50707;
+       background-color: white;
+       padding: 2px;
+}
+
+div.input-form input[type=text], div.input-form input[type=password] {
+       border: 1px solid #595241;
+       padding: 2px;
+       max-width: 60%;
+}
+
+div.input-form input:focus {
+       border: 1px solid #A50707;
+       background-color: white;
+}
+
+div.input-form div.buttons {
+       text-align: right;
+       padding:8px;
+}
+div.input-form div.buttons input {
+       background-color: #efefef;
+       font-weight: normal;
+       border:  #AAA  solid 1px;
+}
diff --git a/themes/fluid/ie_styles.css b/themes/fluid/ie_styles.css
new file mode 100644 (file)
index 0000000..3c77016
--- /dev/null
@@ -0,0 +1,42 @@
+/* IE specific styles */
+
+ul#topnavlist {
+       zoom:100%;
+       margin:0px;
+}
+
+ul#topnavlist li {
+       zoom:100%;
+       padding:0.3em;
+       padding-bottom:0.3em;
+       margin:0px;
+       margin-bottom:-3px;
+}
+
+label {
+       zoom:100%;
+       margin:0px;
+}
+
+table.data tfoot input {
+       min-width:0px;
+}
+
+#topnavlistcontainer {
+       margin-bottom:-1px;
+}
+
+div#breadcrumbs {
+    /* The path bar, including breadcrumbs and add to favorites */
+    background-color:#efefef;
+}
+.side-menu {
+       background-color:#efefef;
+       padding:0px 5px 0px 5px;
+}
+#header{
+       background-color: #e1ecfe;
+}
+div#topnavlistcontainer {
+    background-color: #e1ecfe;
+}
\ No newline at end of file
diff --git a/themes/fluid/images/arrow_left.png b/themes/fluid/images/arrow_left.png
new file mode 100644 (file)
index 0000000..5dc6967
Binary files /dev/null and b/themes/fluid/images/arrow_left.png differ
diff --git a/themes/fluid/images/continue.gif b/themes/fluid/images/continue.gif
new file mode 100644 (file)
index 0000000..3a3badb
Binary files /dev/null and b/themes/fluid/images/continue.gif differ
diff --git a/themes/fluid/images/layers.png b/themes/fluid/images/layers.png
new file mode 100755 (executable)
index 0000000..00818f6
Binary files /dev/null and b/themes/fluid/images/layers.png differ
diff --git a/themes/fluid/images/next.gif b/themes/fluid/images/next.gif
new file mode 100644 (file)
index 0000000..b756085
Binary files /dev/null and b/themes/fluid/images/next.gif differ
diff --git a/themes/fluid/images/previous.gif b/themes/fluid/images/previous.gif
new file mode 100644 (file)
index 0000000..7391bfd
Binary files /dev/null and b/themes/fluid/images/previous.gif differ
diff --git a/themes/fluid/images/resume.gif b/themes/fluid/images/resume.gif
new file mode 100644 (file)
index 0000000..1a16515
Binary files /dev/null and b/themes/fluid/images/resume.gif differ
diff --git a/themes/fluid/images/top.gif b/themes/fluid/images/top.gif
new file mode 100644 (file)
index 0000000..5e61588
Binary files /dev/null and b/themes/fluid/images/top.gif differ
diff --git a/themes/fluid/include/box.tmpl.php b/themes/fluid/include/box.tmpl.php
new file mode 100644 (file)
index 0000000..973df83
--- /dev/null
@@ -0,0 +1,6 @@
+<?php if (!defined('AT_INCLUDE_PATH')) { exit; } ?>
+
+<h2><?php echo $this->title; ?></h2>
+<div class="box">
+       <?php echo $this->dropdown_contents; ?>
+</div>
\ No newline at end of file
diff --git a/themes/fluid/include/footer.tmpl.php b/themes/fluid/include/footer.tmpl.php
new file mode 100644 (file)
index 0000000..616c8ef
--- /dev/null
@@ -0,0 +1,36 @@
+<?php if (!defined('AT_INCLUDE_PATH')) { exit; } global $system_courses; ?>
+
+               <?php if ($_SESSION['course_id'] > 0): ?>
+                       <div id="gototop">              
+                               <a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#content" title="<?php echo _AT('goto_content'); ?> Alt-c" ><?php echo _AT('goto_top'); ?></a>
+                       </div>  
+               <?php endif; ?> 
+       </div>
+       <?php if ($_SESSION['course_id']>0 && $system_courses[$_SESSION['course_id']]['side_menu'] && $_SESSION['prefs']['PREF_MENU']=="right"): ?>
+               <div id="atutor.menu" class="side-menu">
+                       <div id="toolbar.menu" class="grabmenu grab"><img src="<?php echo $this->img; ?>layers.png" /></div>
+                       <?php require(AT_INCLUDE_PATH.'side_menu.inc.php'); ?>
+               </div>
+       <?php endif; ?>
+</div>
+
+<div id="footer">
+       <br /><br />
+       <?php require(AT_INCLUDE_PATH.'html/languages.inc.php'); ?>
+       <?php require(AT_INCLUDE_PATH.'html/copyright.inc.php'); ?>
+</div>
+
+
+<?php
+debug($_SESSION);
+
+
+if (($_SESSION['course_id'] > 0) && $system_courses[$_SESSION['course_id']]['side_menu']): 
+?>
+       <script type="text/javascript">
+         demo.initMyLayout('<?php echo $this->base_path ?>');
+       </script>
+<?php endif; ?>        
+
+</body>
+</html>
\ No newline at end of file
diff --git a/themes/fluid/include/forms.css b/themes/fluid/include/forms.css
new file mode 100644 (file)
index 0000000..b3a57b4
--- /dev/null
@@ -0,0 +1,75 @@
+div.input-form {
+       width: 80%; 
+       max-width: 600px;
+       margin-left:auto; 
+       margin-right:auto;
+       border: 1px solid #F9F6F2;
+       margin-bottom: 20px;
+}
+
+div.input-form div.row h3 {
+       margin-left: 0px;
+}
+
+
+div.input-form div.row {
+       background-color: #F9F6F2;
+       padding:8px;
+}
+
+div.input-form .footer {
+       border-top: 1px solid #F9F6F2;
+}
+
+div.input-form p {
+       margin-left: 0px;
+}
+
+div.input-form input {
+       z-index: 2;
+}
+div.input-form textarea {
+       border: 1px solid #595241;
+       width: 98%;
+       background-color: #EFE7DA;
+       padding: 2px;
+       margin-right: 2px;
+}
+
+div.input-form textarea:focus {
+       border:1px solid #A50707;
+       background-color: white;
+       padding: 2px;
+}
+
+div.input-form input[type=text], div.input-form input[type=password] {
+       border: 1px solid #595241;
+       background-color: #EFE7DA;
+       padding: 2px;
+       max-width: 60%;
+}
+
+div.input-form input:focus {
+       border: 1px solid #A50707;
+       background-color: white;
+       padding: 2px
+}
+
+div.input-form div.buttons {
+       text-align: left;
+       padding:8px;
+}
+div.input-form div.buttons input {
+       border: 1px solid #5B8E88;
+       background-color: #E9F4F3;
+       padding: 2px;
+       padding-left: 10px;
+       padding-right: 10px;
+       min-width: 100px;
+       margin-left: 5px;
+}
+div.input-form div.buttons input:hover {
+       background-color: #5B8E88;
+       border: 1px solid #5B8E88;
+       color: white;
+}
\ No newline at end of file
diff --git a/themes/fluid/include/header.tmpl.php b/themes/fluid/include/header.tmpl.php
new file mode 100644 (file)
index 0000000..9c70f8e
--- /dev/null
@@ -0,0 +1,373 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: header.tmpl.php 3825 2005-03-11 15:35:51 joel $
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+/* available header.tmpl.php variables:
+ * $this->lang_code                    the ISO language code
+ * SITE_NAME                           the site name from the config file
+ * $this->page_title           the name of this page to use in the <title>
+ * $this->lang_charset         the ISO language character set
+ * $this->content_base_href    the <base href> to use for this page
+ * $this->base_path                    the absolute path to this atutor installation
+ * $this->rtl_css                      if set, the path to the RTL style sheet
+ * $this->icon                 the path to a course icon
+ * $this->banner_style         -deprecated-
+ * $this->theme                                the directory name of the current theme
+ * $this->base_href                    the full url to this atutor installation
+ * $this->onload                       javascript onload() calls
+ * $this->img                          the absolute path to this theme's images/ directory
+ * $this->sequence_links       associative array of 'previous', 'next', and/or 'resume' links
+ * $this->path                         associative array of path to this page: aka bread crumbs
+ * $this->rel_url                      the relative url from the installation root to this page
+ * $this->nav_courses          associative array of this user's enrolled courses
+ * $this->section_title                the title of this section (course, public, admin, my start page)
+ * $this->top_level_pages      associative array of the top level navigation
+ * $this->current_top_level_page       the full path to the current top level page with file name
+ * $this->sub_level_pages                      associate array of sub level navigation
+ * $this->back_to_page                         if set, the path and file name to the part of this page (if parent is not a top level nav)
+ * $this->current_sub_level_page       the full path to the current sub level page with file name
+ * $this->guide                                the full path and file name to the guide page
+ * ======================================
+ * top_level_pages           array(array('url', 'title'))     the top level pages. ATutor default creates tabs.
+ * section_title             string                           the name of the current section. either name of the course, administration, my start page, etc.
+ * page_title                string                           the title of the current page.
+ * path                      array(array('url', 'title'))     the path to the current page.
+ * back_to_page              array('url', 'title')            the link back to the part of the current page, if needed.
+ * current_top_level_page    string                           full url to the current top level page in "top_leve_pages"
+ * current_sub_level_page    string                           full url to the current sub level page in the "sub_level_pages"
+ * sub_level_pages           array(array('url', 'title'))     the sub level pages.
+ */
+
+// will have to be moved to the header.inc.php
+global $system_courses, $_custom_css,$db;
+
+?><!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="<?php echo $this->lang_code; ?>"> 
+
+<head>
+       <title><?php echo SITE_NAME; ?> : <?php echo $this->page_title; ?></title>
+       <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $this->lang_charset; ?>" />
+       <meta name="Generator" content="ATutor - Copyright 2005 by http://atutor.ca" />
+       <base href="<?php echo $this->content_base_href; ?>" />
+       <link rel="shortcut icon" href="<?php echo $this->base_path; ?>favicon.ico" type="image/x-icon" />
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/print.css" type="text/css" media="print" />
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/styles.css" type="text/css" />
+       <!--[if IE]>
+         <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/ie_styles.css" type="text/css" />
+       <![endif]-->
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/forms.css" type="text/css" />
+       <?php echo $this->rtl_css; ?>
+       <?php if ($system_courses[$_SESSION['course_id']]['rss']): ?>
+       <link rel="alternate" type="application/rss+xml" title="<?php echo SITE_NAME; ?> - RSS 2.0" href="<?php echo $this->base_href; ?>get_rss.php?<?php echo $_SESSION['course_id']; ?>-2" />
+       <link rel="alternate" type="application/rss+xml" title="<?php echo SITE_NAME; ?> - RSS 1.0" href="<?php echo $this->base_href; ?>get_rss.php?<?php echo $_SESSION['course_id']; ?>-1" />
+       <?php endif; ?>
+       <?php echo $this->custom_css; ?>
+
+       <script type="text/javascript" src="<?php echo $this->base_path; ?>jscripts/jquery/jquery-1.2.3.js"></script>
+       <script type="text/javascript" src="<?php echo $this->base_path; ?>jscripts/jquery/jquery.tabindex.js"></script>
+       <script type="text/javascript" src="<?php echo $this->base_path; ?>jscripts/jquery/jquery.dimensions.js"></script>
+       <script type="text/javascript" src="<?php echo $this->base_path; ?>jscripts/jquery/ui.base.js"></script>
+       <script type="text/javascript" src="<?php echo $this->base_path; ?>jscripts/jquery/ui.draggable.js"></script>
+       <script type="text/javascript" src="<?php echo $this->base_path; ?>jscripts/jquery/ui.droppable.js"></script>
+       <script type="text/javascript" src="<?php echo $this->base_path; ?>jscripts/jquery/jARIA.js"></script>
+
+       <script language="JavaScript" src="<?php echo $this->base_path; ?>jscripts/fluid/Fluid.js" type="text/javascript"></script>
+       <script language="JavaScript" src="<?php echo $this->base_path; ?>jscripts/fluid/Reorderer.js" type="text/javascript"></script>
+
+       <script type="text/javascript">jQuery.noConflict();</script> 
+       
+       <script type="text/javascript" src="<?php echo $this->base_path; ?>jscripts/fluid-atutor.js"></script>
+       <script language="javascript" type="text/javascript">
+//<!--
+var newwindow;
+function poptastic(url) {
+       newwindow=window.open(url,'popup','height=600,width=600,scrollbars=yes,resizable=yes');
+       if (window.focus) {newwindow.focus()}
+}
+
+function getexpirydate(nodays){
+       var UTCstring;
+       Today = new Date();
+       nomilli=Date.parse(Today);
+       Today.setTime(nomilli+nodays*24*60*60*1000);
+       UTCstring = Today.toUTCString();
+       return UTCstring;
+}
+
+function setcookie(name,value,duration){
+       cookiestring=name+"="+escape(value)+";path=/;expires="+getexpirydate(duration);
+       document.cookie=cookiestring;
+       if(!getcookie(name)){
+               return false;
+       } else {
+               return true;
+       }
+}
+
+function getcookie(cookiename) {
+       var cookiestring=""+document.cookie;
+       var index1=cookiestring.indexOf(cookiename);
+       if (index1==-1 || cookiename=="") return ""; 
+       var index2=cookiestring.indexOf(';',index1);
+       if (index2==-1) index2=cookiestring.length; 
+       return unescape(cookiestring.substring(index1+cookiename.length+1,index2));
+}
+
+function setDisplay(objId) {
+       var toc = document.getElementById(objId);
+
+       var state = getcookie(objId);
+       if (document.getElementById(objId) && state && (state == 'none')) {
+               toggleToc(objId);
+       }
+}
+
+
+function setstates() {
+       return;
+       var objId = "side-menu";
+       var state = getcookie(objId);
+       if (document.getElementById(objId) && state && (state == 'none')) {
+               toggleToc(objId);
+       }
+
+       var objId = "toccontent";
+       var state = getcookie(objId);
+       if (document.getElementById(objId) && state && (state == 'none')) {
+               toggleToc(objId);
+       }
+
+}
+
+function showTocToggle(objId, show, hide, key, selected) {
+       if(document.getElementById) {
+               if (key) {
+                       var accesskey = " accesskey='" + key + "' title='"+ show + "/" + hide + " Alt - "+ key +"'";
+               } else {
+                       var accesskey = "";
+               }
+
+               if (selected == 'hide') {
+                       document.writeln('<a href="javascript:toggleToc(\'' + objId + '\')" ' + accesskey + '>' +
+                       '<span id="' + objId + 'showlink" style="display:none;">' + show + '</span>' +
+                       '<span id="' + objId + 'hidelink">' + hide + '</span>'  + '</a>');
+               } else {
+                       document.writeln('<a href="javascript:toggleToc(\'' + objId + '\')" ' + accesskey + '>' +
+                       '<span id="' + objId + 'showlink">' + show + '</span>' +
+                       '<span id="' + objId + 'hidelink" style="display:none;">' + hide + '</span>'    + '</a>');
+               }
+       }
+}
+
+function toggleToc(objId) {
+       var toc = document.getElementById(objId);
+       if (toc == null) {
+               return;
+       }
+       var showlink=document.getElementById(objId + 'showlink');
+       var hidelink=document.getElementById(objId + 'hidelink');
+       if (hidelink.style.display == 'none') {
+               document.getElementById('contentcolumn').id="contentcolumn_shiftright";
+               toc.style.display = '';
+               hidelink.style.display='';
+               showlink.style.display='none';
+       } else {
+               document.getElementById('contentcolumn_shiftright').id="contentcolumn";
+               toc.style.display = 'none';
+               hidelink.style.display='none';
+               showlink.style.display='';
+       }
+       setcookie(objId, toc.style.display, 1);
+}
+//-->
+</script>
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/at_fluid.css" type="text/css" />    
+</head>
+
+<body onload="<?php echo $this->onload; ?>"><div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>
+<script language="JavaScript" src="<?php echo $this->base_path; ?>overlib.js" type="text/javascript"></script>
+<script language="javascript" type="text/javascript">
+//<!--
+       function getcookie(cookiename) {
+               var cookiestring=""+document.cookie;
+               var index1=cookiestring.indexOf(cookiename);
+               if (index1==-1 || cookiename=="") return ""; 
+               var index2=cookiestring.indexOf(';',index1);
+               if (index2==-1) index2=cookiestring.length; 
+               return unescape(cookiestring.substring(index1+cookiename.length+1,index2));
+       }
+//-->
+</script>
+<div id="top-links"> <!-- top help/search/login links -->
+       <a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#content" accesskey="c">
+       <img src="<?php echo $this->base_path; ?>images/clr.gif" height="1" width="1" border="0" alt="<?php echo _AT('goto_content'); ?> ALT+c" /></a>          
+
+       <a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#menu"  accesskey="m"><img src="<?php echo $this->base_path; ?>images/clr.gif" height="1" width="1" border="0" alt="<?php echo _AT('goto_menu'); ?> ALT+m" /></a>
+               <?php if (isset($_SESSION['member_id']) && $_SESSION['member_id']): ?>
+                       <!-- start the jump menu -->
+                       <?php if (empty($_GET)): ?>
+                               <form method="post" action="<?php echo $this->base_path; ?>bounce.php?p=<?php echo urlencode($this->rel_url); ?>" target="_top">
+                       <?php else: ?>
+                               <form method="post" action="<?php echo $this->base_path; ?>bounce.php" target="_top">
+                       <?php endif; ?>
+                       <label for="jumpmenu" accesskey="j"></label>
+                               <select name="course" id="jumpmenu" title="<?php echo _AT('jump'); ?>:  Alt-j">                                                 
+                                       <option value="0"><?php echo _AT('my_start_page'); ?></option>
+                                       <optgroup label="<?php echo _AT('courses_below'); ?>">
+                                               <?php foreach ($this->nav_courses as $this_course_id => $this_course_title): ?>
+                                                       <option value="<?php echo $this_course_id; ?>"><?php echo $this_course_title; ?></option>
+                                               <?php endforeach; ?>
+                                       </optgroup>
+                               </select> <input type="submit" name="jump" value="<?php echo _AT('jump'); ?>" class="button" /> </form>
+                       <!-- /end the jump menu -->
+                       <?php if ($_SESSION['is_super_admin']): ?>
+                               <a href="<?php echo $this->base_path; ?>bounce.php?admin"><?php echo _AT('return_to_admin_area'); ?></a> | 
+                       <?php endif; ?>
+
+                       <?php if ($_SESSION['course_id'] > -1): ?>
+                               <?php if (get_num_new_messages()): ?>
+                                       <a href="<?php echo $this->base_path; ?>inbox/index.php"><?php echo _AT('inbox'); ?> (<?php echo get_num_new_messages(); ?>)</a> 
+                               <?php else: ?>
+                                       <a href="<?php echo $this->base_path; ?>inbox/index.php"><?php echo _AT('inbox'); ?></a>
+                               <?php endif; ?>
+                       <?php endif; ?>
+               <?php endif; ?>
+               <a href="<?php echo $this->base_path; ?>search.php"><?php echo _AT('search'); ?></a> <a href="<?php echo $this->base_path; ?>help/index.php"><?php echo _AT('help'); ?></a>
+       </div>
+<div id="header">
+
+
+       <?php
+       // If there is a custom course banner in the file manager called banner.html, display it here
+       @readfile(AT_CONTENT_DIR . $_SESSION['course_id'].'/banner.txt'); 
+
+       /*
+       and example banner.html file might look like:
+       <div style="width: 760px; height: 42px; background: white;"><img src="http://[mysite]/atutor15rc3/banners/kart-camb.jpg"></div>
+       */
+
+       ?>
+
+       <?php if (!empty($this->icon)) { // if a course icon is available, display it here.  ?>
+               <a href="<?php echo $this->base_path; ?>index.php"><img src="<?php echo $this->icon; ?>" class="headicon" alt="<?php echo  _AT('home'); ?>" /></a>      
+       <?php } ?>
+
+       <h1 id="section-title">
+               <?php if ($_SESSION['valid_user']): 
+                       echo '<span style="color:black;font-size:small;font-weight:bold;">'.stripslashes(SITE_NAME).'</span><br />';    
+               endif; ?>       
+               <?php echo $this->section_title; ?>
+               <?php if (($_SESSION['course_id'] > 0) && ($_SESSION['enroll'] == AT_ENROLL_NO)) : ?> 
+                       - <small><a href="<?php echo $this->base_path; ?>enroll.php?course=<?php echo $_SESSION['course_id']; ?>"><?php echo _AT('enroll_me'); ?></a></small>
+               <?php endif; ?>
+       </h1>
+       
+       
+</div>
+
+<div id="topnavlistcontainer">
+<!-- the main navigation. in our case, tabs -->
+       <ul id="topnavlist">
+               <?php foreach ($this->top_level_pages as $page): ?>
+                       <?php ++$accesscounter; $accesscounter = ($accesscounter == 10 ? 0 : $accesscounter); ?>
+                       <?php $accesskey_text = ($accesscounter < 10 ? 'accesskey="'.$accesscounter.'"' : ''); ?>
+                       <?php $accesskey_title = ($accesscounter < 10 ? ' Alt+'.$accesscounter : ''); ?>
+                       <?php if ($page['url'] == $this->current_top_level_page): ?>
+                               <li><a href="<?php echo $page['url']; ?>" <?php echo $accesskey_text; ?> title="<?php echo $page['title'] . $accesskey_title; ?>" class="active"><?php echo $page['title']; ?></a></li>
+                       <?php else: ?>
+                               <li><a href="<?php echo $page['url']; ?>" <?php echo $accesskey_text; ?> title="<?php echo $page['title'] . $accesskey_title; ?>"><?php echo $page['title']; ?></a></li>
+                       <?php endif; ?>
+                       <?php $accesscounter = ($accesscounter == 0 ? 11 : $accesscounter); ?>
+               <?php endforeach; ?>
+       </ul>
+</div>
+
+<div id="subnav">
+       <!-- the sub navigation -->
+       <div style="float: right; text-transform: lowercase;">
+               <?php if ($_SESSION['valid_user']): ?>                                  
+                       <strong><?php echo get_display_name($_SESSION['member_id']); ?></strong> | <a href="<?php echo $this->base_path; ?>logout.php"><?php echo _AT('logout'); ?></a>
+               <?php else: ?>
+                        <a href="<?php echo $this->base_path; ?>login.php?course=<?php echo $_SESSION['course_id']; ?>"><?php echo _AT('login'); ?></a> | <a href="<?php echo $this->base_path; ?>registration.php"><?php echo _AT('register'); ?></a>
+               <?php endif; ?>
+       </div>
+
+       <?php if ($this->sub_level_pages): ?>
+               <?php if (isset($this->back_to_page)): ?>
+                       <a href="<?php echo $this->back_to_page['url']; ?>" id="back-to"><?php echo _AT('back_to').' '.$this->back_to_page['title']; ?></a> | 
+               <?php endif; ?>
+
+               <?php $num_pages = count($this->sub_level_pages); ?>
+               <?php for ($i=0; $i<$num_pages; $i++): ?>
+                       <?php if ($this->sub_level_pages[$i]['url'] == $this->current_sub_level_page): ?>
+                               <strong><?php echo $this->sub_level_pages[$i]['title']; ?></strong>
+                       <?php else: ?>
+                               <a href="<?php echo $this->sub_level_pages[$i]['url']; ?>"><?php echo $this->sub_level_pages[$i]['title']; ?></a>
+                       <?php endif; ?>
+                       <?php if ($i < $num_pages-1): ?>
+                               |
+                       <?php endif; ?>
+               <?php endfor; ?>
+       <?php else: ?>
+               <div id="sub-navigation">
+                       &nbsp;
+               </div>
+       <?php endif; ?>
+</div>
+
+<div id="contentwrapper">
+       
+       <?php if (($_SESSION['course_id'] > 0) && $system_courses[$_SESSION['course_id']]['side_menu'] && ($_SESSION['prefs']['PREF_MENU']!="right")): ?>
+               <div id="atutor.menu" class="side-menu">
+                       <div id="toolbar.menu" class="grabmenu grab"><img src="<?php echo $this->img; ?>layers.png" alt="<?php echo _AT('drag'); ?>" /></div>
+                       <?php require(AT_INCLUDE_PATH.'side_menu.inc.php'); ?>
+               </div>
+       <?php endif; ?>
+
+       <div id="atutor.content" style="
+               <?php if (($_SESSION['course_id'] <= 0) && !$this->side_menu) { ?> width:99%; <?php } else { ?> width:76.5%; <?php } ?>
+       ">
+               <div id="breadcrumbs">
+               <div id="toolbar.content" class="grab"><img src="<?php echo $this->img; ?>layers.png" style="float:left;" alt="<?php echo _AT('drag'); ?>" /></div>
+                       &nbsp;
+                       <?php foreach ($this->path as $page): ?>
+                               <a href="<?php echo $page['url']; ?>"><?php echo $page['title']; ?></a> > 
+                       <?php endforeach; ?> <?php echo $this->page_title; ?>
+               </div>
+               <?php if ($this->guide): ?>
+                       <a href="<?php echo $this->guide; ?>" id="guide" onclick="poptastic('<?php echo $this->guide; ?>'); return false;" target="_new"><em><?php echo $this->page_title; ?></em></a>
+               <?php endif; ?>
+
+               <?php if ($_SESSION['course_id'] > 0): ?>
+               <a href=""></a>
+               <div id="sequence-links">
+                       <?php if ($this->sequence_links['resume']): ?>
+                                       <a style="color:white;" href="<?php echo $this->sequence_links['resume']['url']; ?>" accesskey="."><img src="<?php echo $this->img; ?>resume.gif" border="0" title="<?php echo _AT('resume').': '.$this->sequence_links['resume']['title']; ?> Alt+." alt="<?php echo $this->sequence_links['resume']['title']; ?> Alt+." class="img-size-ascdesc" /></a>
+                       <?php else:
+                               if ($this->sequence_links['previous']): ?>
+                                       <a href="<?php echo $this->sequence_links['previous']['url']; ?>" title="<?php echo _AT('previous_topic').': '. $this->sequence_links['previous']['title']; ?> Alt+," accesskey=","><img src="<?php echo $this->img; ?>previous.gif" border="0" alt="<?php echo _AT('previous_topic').': '. $this->sequence_links['previous']['title']; ?> Alt+," class="img-size-ascdesc" /></a>
+                               <?php endif;
+                               if ($this->sequence_links['next']): ?>
+                                       <a href="<?php echo $this->sequence_links['next']['url']; ?>" title="<?php echo _AT('next_topic').': '.$this->sequence_links['next']['title']; ?> Alt+." accesskey="."><img src="<?php echo $this->img; ?>next.gif" border="0" alt="<?php echo _AT('next_topic').': '.$this->sequence_links['next']['title']; ?> Alt+." class="img-size-ascdesc" /></a>
+                               <?php endif; ?>
+                       <?php endif; ?>
+                       &nbsp;
+               </div>
+               <?php endif; ?>
+
+       <!-- the page title -->
+       <h2 class="page-title"><?php echo $this->page_title; ?></h2>
+
+       <a name="content"></a>
+       <?php global $msg; $msg->printAll(); ?>
\ No newline at end of file
diff --git a/themes/fluid/include/side_menu.tmpl.php b/themes/fluid/include/side_menu.tmpl.php
new file mode 100644 (file)
index 0000000..48f1cf9
--- /dev/null
@@ -0,0 +1,8 @@
+<?php if (!defined('AT_INCLUDE_PATH')) { exit; } ?>
+
+<?php if (($_SESSION['course_id'] > 0) && $this->side_menu): ?>
+       <?php foreach ($this->side_menu as $dropdown_file): ?>
+               <?php if (file_exists($dropdown_file)) { require($dropdown_file); } ?>
+       <?php endforeach; ?>
+<div style="position:absolute; bottom:0px;">&nbsp;</div>
+<?php endif; ?>
diff --git a/themes/fluid/index.tmpl.php b/themes/fluid/index.tmpl.php
new file mode 100644 (file)
index 0000000..448277b
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+if (!defined('AT_INCLUDE_PATH')) { exit; } ?>
+
+<?php if ($this->banner): ?><?php echo $this->banner; ?><?php endif; ?>
+
+<div style="width: 100%; margin-top: -5px; float:left;">
+       <ul id="home-links">
+       <?php foreach ($this->home_links as $link): ?>
+               <li><a href="<?php echo $link['url']; ?>"><img src="<?php echo $link['img']; ?>" alt="" class="img-size-home" border="0" /><?php echo $link['title']; ?></a></li>
+       <?php endforeach; ?>
+       </ul>
+</div>
+
+<?php if ($this->announcements): ?>
+<h2 class="page-title"><?php echo _AT('announcements'); ?></h2>
+       <?php foreach ($this->announcements as $item): ?>
+               <div class="news">
+                       <h3><?php echo $item['title']; ?></h3>
+                       <p><span class="date"><?php echo $item['date'] . ' by ' . $item['author']; ?></span> &nbsp; <?php echo $item['body']; ?></p>
+               </div>
+       <?php endforeach; ?>
+
+       <?php if ($this->num_pages > 1): ?>
+               <?php echo _AT('page'); ?>: | 
+               <?php for ($i=1; $i<=$this->num_pages; $i++): ?>
+                       <?php if ($i == $this->current_page): ?>
+                               <strong><?php echo $i; ?></strong>
+                       <?php else: ?>
+                               <a href="<?php echo $_SERVER['PHP_SELF']; ?>?p=<?php echo $i; ?>"><?php echo $i; ?></a>
+                       <?php endif; ?>
+                        | 
+               <?php endfor; ?>
+       <?php endif; ?>
+<?php endif; ?>
diff --git a/themes/fluid/print.css b/themes/fluid/print.css
new file mode 100644 (file)
index 0000000..48b2bc1
--- /dev/null
@@ -0,0 +1,13 @@
+body {
+       background-color: White;
+       font-family: Helvetica, arial, sans serif;
+       margin: 0px;
+       margin-top: 0px;
+       color: black;
+       border: 0px;
+}
+
+div#side-menu, div#member-links, span#side-menushowlink, div#rightcolumn, div#suv-nav-logout, div#top-links, span#side-menuhidelink, div#sequence-links, select#jumpmenu, a#guide, div#gototop, input#jump-button, div#topnavlistcontainer, a#guide, div#breadcrumbs, div#jump-area, table.tabbed-table, div#sub-navigation, div#sequence-links, div#language, div#toc, fieldset#shortcuts {
+       display: none;
+}
+
diff --git a/themes/fluid/save_state.php b/themes/fluid/save_state.php
new file mode 100644 (file)
index 0000000..9bc4fc7
--- /dev/null
@@ -0,0 +1,14 @@
+<?php
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'/vitals.inc.php');
+
+if ($_POST['left'] == 'atutor.menu') {
+       $_SESSION['prefs']['PREF_MENU']='left';
+} else {
+       $_SESSION['prefs']['PREF_MENU']='right';
+}
+
+save_prefs();
+
+?>
\ No newline at end of file
diff --git a/themes/fluid/screenshot.gif b/themes/fluid/screenshot.gif
new file mode 100644 (file)
index 0000000..10b6e33
Binary files /dev/null and b/themes/fluid/screenshot.gif differ
diff --git a/themes/fluid/styles.css b/themes/fluid/styles.css
new file mode 100644 (file)
index 0000000..d595183
--- /dev/null
@@ -0,0 +1,1499 @@
+html,body{
+       height:100%;
+}
+
+
+/* main body attributes */
+body {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       margin:0px;
+       padding:0px;
+       font-size: .9em;
+       background-color: white;
+}
+
+p {
+    margin: 0.5em 0em 1em 0em;
+    text-align: justify;
+    line-height: 150%;
+       font-size: 1em;
+}
+
+p a {
+    text-decoration: underline;
+}
+
+p a:visited {
+       color: #3F2670;
+    background-color: transparent;
+}
+
+p a:active {
+       color: #A50707;
+    background-color: transparent;
+}
+
+h1, h2, h3, h4, h5, h6 {
+    color: #4b535f;
+    clear: right;
+    font: 100% Verdana, Helvetica, Arial, sans-serif;
+       font-weight: bold;
+    margin: 0;
+    padding-top: 0.5em;
+    /*border-bottom: 1px solid #B8AE9C;*/
+}
+
+h1 {
+    font-size: 160%;
+       color: #595241;
+}
+
+h2 {
+    font-size: 150%;
+}
+h3 {
+    font-size: 130%;
+}
+
+h4 {
+    font-size: 120%;
+}
+
+
+h5 {
+    font-size: 100%;
+}
+
+
+
+/*  Table of content attributes*/
+p.toc{
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #E9F4F3;
+       padding: .6em;
+       margin-bottom: .6em;
+       margin-top: 0em;
+       margin-left: 1em;
+       margin-right: 3em;
+       border: 1px #ACCFCC solid;
+} 
+
+/* list attributes */
+ul {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+
+li {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+
+li.folders {
+       list-style: disc url(../../images/folder.gif) outside;
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+
+li.folders .disabled {
+       color: #B8AE9C;
+}
+
+/* link attributes */
+a:link, a:visited  {
+       color: #1A4A72;
+}
+a:hover {
+       color: #932318;
+}
+
+/* align text to the left */
+.left {
+       text-align: left;
+}
+
+a.dropdown-title {
+       color: white;
+       font-weight: normal;
+       text-decoration: none;
+}
+
+
+/* table border */
+.tableborder {
+       border: 1px #595241 solid;
+}
+
+/* main submit button */
+.button {
+       background-color: #efefef;
+       font-weight: normal;
+       border:  #AAA  solid 1px;
+}
+
+/* small submit button at top */
+.button2 {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #E9F4F3;
+       border:  #ACCFCC  solid 1px;
+}
+
+/* date attributes */
+small.date {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: #595241; 
+       margin-bottom: 0px; 
+       margin-top: 0px;
+       margin-left: 5px;
+       margin-right: 0px;
+       font-size:1em;
+}
+
+/* page breakline */
+hr {
+       color: #ACCFCC;
+       background-color: white;
+       height: 1px;
+}
+
+/* message box styles */
+
+/* Editor box small */
+.editorsmallbox {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #E9F4F3;
+       padding: 2px;
+       padding-right: 3px;
+       border: 1px #ACCFCC solid;
+}
+
+/* Editor box large */
+.editorlargebox {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #E9F4F3;
+       margin-left:1em;
+       padding-left: .2em;
+       padding-right: .5em;
+       padding-top: .5em;
+       padding-bottom: .4em;
+       border: 1px #ACCFCC solid;
+}
+
+
+select.dropdown {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+}
+
+.highlight, a.highlight {
+       background-color: #5B8E88;
+       color: white;
+}
+
+a .highlight{
+       background-color: #5B8E88;
+       color: white;
+}
+
+.center {
+       text-align: center;
+}
+
+
+/* edit content tabs */
+.buttontab {
+       background-color: #E6E6E6;
+       font-weight: 500;
+       border:0;
+       padding-left: 3px;
+       padding-right: 3px;
+       padding-top: 3px;
+}
+
+.tab {
+       color: black;
+       background-color: #E6E6E6;
+       border-top: 1px #B8AE9C solid;
+       border-left: 1px #B8AE9C solid;
+       border-right: 1px #B8AE9C solid;
+       text-decoration: none;
+       text-align: center;
+       font-weight: bold;
+       
+}
+.buttontab selected {
+       font-family: Helvetica, Arial, Helvetica, sans-serif;
+       background-color: #6F7172;
+       font-weight: 600;
+       border:0;
+       padding-left: 3px;
+       padding-right: 3px;
+       padding-top: 3px;
+
+}
+td.selected{
+       font-family: Helvetica, Arial, Helvetica, sans-serif;
+       font-weight: 600;
+       text-decoration: none;
+       text-align: center;
+       background-color: white;
+       border-top: 1px #B8AE9C solid;
+       border-left: 1px #B8AE9C solid;
+       border-right: 1px #B8AE9C solid;
+}
+.econtainer{
+       background-color: #fffaf0;
+       border:1px #6F7172 solid;
+       margin-left:.5em;
+}
+
+.tab a:link, .etab a:visited {
+       color: black;
+       background-color: white;
+}
+.tab a:hover {
+       color: black;
+       background-color: white;
+}
+
+.etabself {
+       background-color: #6F7172;
+
+       text-align: center;
+       font-weight: bold;
+       padding: 2px;
+}
+
+
+.unsaved {
+       color: red;
+       background-color: #FFFDE0;
+       font-weight: bold;
+}
+.saved {
+       background-color: #FFFDE0;
+       margin: 10px;
+}
+
+
+/* the side menu 
+td.dropdown-heading {
+       background-color: #DBFDD4;
+       color: #595241;
+       border-left: 1px solid #ECFEEA;
+       border-right: 1px solid #ECFEEA;
+       border-top: 1px solid #ECFEEA;
+       font-weight: bold;
+       padding: 2px;
+}
+
+td.dropdown-heading a, td.dropdown-heading a:hover, td.dropdown-heading a:visited {
+       text-decoration: none;
+}
+
+td.dropdown-heading.closed {
+       border-bottom: 1px solid #ECFEEA;
+}
+
+td.dropdown {
+       padding: 2px;
+       background-color: white;
+       color: black;
+       border-left: 1px solid #ECFEEA;
+       border-right: 1px solid #ECFEEA;
+       border-bottom: 1px solid #ECFEEA;
+       font-weight: normal;
+}
+td.dropdown a, td.dropdown a:visited  {
+       color: #595241;
+       text-decoration: none;
+}
+td.dropdown a:hover {
+       color: #595241;
+       text-decoration: underline;
+}
+td.dropdown.cell {
+       border-bottom: 0px;
+}
+td.dropdown strong {
+       color: #2A6C28;
+} */
+
+/* added for 1.4.2: */
+.results {
+       padding-left: 20px;
+}
+
+h5.search-results {
+       background-color: #F7F3ED;
+       color: #595241;
+       padding: 1px;
+       margin-bottom: 5px;
+       margin-top: 10px;
+       margin-left: 5px;
+}
+
+small.search-info {
+       color: #595241;
+}
+
+p.search-description {
+       background-color: #FFFCE5;
+       color: #595241;
+}
+
+.test-box {
+       background-color: #F7F3ED;
+       color: #595241;
+       border-left: 1px solid #595241;
+       border-right: 1px solid #595241;
+       border-top: 1px solid #595241;
+       font-weight: bold;
+       padding: 2px;
+}
+
+/***************************************************************/
+/* NEW STUFF */
+
+table.tabbed-table {
+       width: 100%;
+       border:thin black solid;
+}
+table.tabbed-table th#left-empty-tab {
+       background-color: transparent;
+       width: 15px;
+       border-bottom: 1px solid #B8AE9C;
+}
+table.tabbed-table th#right-empty-tab {
+       text-align: right;
+       background-color: transparent;
+       border-bottom: 1px solid #B8AE9C;
+       width: 400px;
+       padding-right: 5px;
+}
+table.tabbed-table th#right-empty-tab a {
+       text-decoration: underline;
+}
+table.tabbed-table th.tab-spacer {
+       background-color: transparent;
+       width: 5px;
+       border-bottom: 1px solid #B8AE9C;
+}
+
+table.tabbed-table th.tab {
+       padding-top: 2px;
+       padding-bottom: 2px;
+       width: 110px;
+       background-color: #E9F4F3;
+       border-bottom: 1px solid #B8AE9C;
+       border-left: 1px solid #B8AE9C;
+       border-top: 1px solid #B8AE9C;
+       border-right: 1px solid #B8AE9C;
+}
+table.tabbed-table th.tab:hover {
+       background-color: #ACCFCC;
+}
+
+table.tabbed-table th.tab a:focus {
+       color: white;
+}
+table.tabbed-table th.selected {
+       padding-top: 2px;
+       padding-bottom: 2px;
+       width: 110px;
+       background-color: #ACCFCC;
+       border-left: 1px solid #B8AE9C;
+       border-top: 1px solid #B8AE9C;
+       border-right: 1px solid #B8AE9C;
+}
+
+table.tabbed-table a, table.tabbed-table a:visited, table.tabbed-table a:hover {
+       color: black;
+       text-decoration: none;
+}
+
+a#my-start-page {
+       padding: 2px;
+       padding-left: 15px;
+       background-image: url(http://www.gris.uni-tuebingen.de/images/start.gif);
+       background-repeat: no-repeat;
+       background-position: 2px 5px;
+}
+
+a#back-to {
+       padding-left: 20px;
+       background-image: url(images/arrow_left.png);
+       background-repeat: no-repeat;
+       background-position: 0px -1px;
+}
+
+div#breadcrumbs {
+    /* The path bar, including breadcrumbs and add to favorites */
+    background-color:#efefef;
+    border: 1px solid #8b8b8b;
+    display:block;
+    width:100%;
+       clear:both;
+    font-size: 0.85em;
+       padding:3px 0px 3px 0px;
+       float:left;
+}
+h2.page-title {
+       margin-bottom: 10px;
+       padding:0px;
+}
+
+h1 {
+       margin-bottom: 5px;
+}
+
+div#help {
+       border-left: 1px solid black;
+       border-right: 1px solid black;
+       border-bottom: 1px solid black;
+       padding-left: 5px;
+       padding-right: 5px;
+       padding-bottom: 5px;
+       background-color: #F7F3ED;
+       margin-left: 5px;
+       margin-right: 5px;
+       font-size: small;
+}
+
+h3#help-title {
+       margin-left: 5px;
+       margin-right: 5px;
+       border-left: 1px solid black;
+       border-right: 1px solid black;
+       padding: 1px;
+       background-color: #F7F3ED;
+}
+.line {
+       border-bottom: 1px solid black;
+}
+div#help p {
+       padding: 0px;
+       margin: 0px;
+}
+
+div#toctoggle {
+       float: left;
+       padding-left: 10px;
+}
+
+h1#section-title {
+       float: left;
+       white-space:nowrap;
+       margin-left:1em;
+       margin-top:-5px;
+}
+
+div#top-links {
+       float:right;
+       padding-right:10px;
+       white-space:nowrap;
+}
+
+div#top-links a:link, div#top-links a:visited {
+       text-decoration:none;
+       margin-left:7px;
+}
+
+
+a#editor-link {
+       background-color: #F7F3ED;
+       padding-top: 1px;
+       padding-bottom: 1px;
+       padding-left: 15px;
+       padding-right: 8px;
+       border: 1px solid #cccccc;
+       font-weight: normal;
+       text-decoration: none;
+}
+
+a#editor-link:hover {
+       background-color: #F7F3ED;
+       border: 1px solid #B8AE9C;
+}
+
+a#editor-link.off {
+       background-image: url(images/pen.gif);
+       background-repeat: no-repeat;
+       background-position: 0px 2px;
+}
+a#editor-link.on {
+       background-image: url(images/pen2.gif);
+       background-repeat: no-repeat;
+       background-position: 0px 2px;
+}
+
+
+/* for data tables */
+table.data {
+       clear:right;
+       border: 1px solid #B8AE9C;
+       width: 90%; 
+       margin-left: auto; 
+       margin-right: auto;
+} 
+
+table.data th {
+       background-color: #F6EAD6;
+       padding: 3px;
+       white-space: nowrap;
+}
+
+table.data th a {
+       color: #595241;
+       padding-right: 15px;
+       margin-right: 15px;
+       background-image: url('../default/images/sort.gif');
+       background-repeat: no-repeat;
+       background-position: right;
+}
+
+table.data tbody {
+       border-top: 1px solid #B8AE9C;
+       border-bottom: 1px solid #B8AE9C;
+}
+
+table.data tbody th {
+       text-align: left;
+       background-color: #F7F3ED;
+       cursor: auto;
+}
+
+table.data td {
+       padding: 3px;
+}
+
+table.data tbody tr:hover {
+       background-color: #efefef;
+       cursor: pointer;
+}
+
+table.data tbody tr.selected {
+       background-color: #E9F4F3;
+       cursor: auto;
+}
+
+table.data tfoot {
+       background-color: #F7F3ED;
+       /*border-top: 1px solid #B8AE9C;*/
+}
+
+table.data tfoot tr:first-child td {
+       /*border-top: 1px solid #B8AE9C;*/
+       padding: 5px;
+       background-image: url('images/arrow_ltr.gif');
+       background-repeat: no-repeat;
+       background-position: 4px 5px;
+       padding-left: 40px;
+}
+
+table.data.static tfoot td, table.data.static tfoot tr:first-child td {
+       border-top: 1px solid #B8AE9C;
+       padding: 5px;
+       background-image: none;
+       padding-left: 0px;
+
+}
+
+/*buttons*/
+table.data tfoot input {
+       background-color: #efefef;
+       font-weight: normal;
+       border:  #AAA  solid 1px;
+}
+
+
+
+/* used for static tables with no form elements: */
+table.data.static tbody tr:hover {
+       background-color: transparent;
+       cursor: auto;
+}
+
+
+
+/* course browser: */
+
+div#browse {
+       margin-left: auto; 
+       margin-right: auto; 
+       width: 80%;
+}
+
+div.browse-selected {
+       background-image: url('images/side_arrow.gif'); 
+       background-repeat: no-repeat; 
+       padding-left: 9px; 
+       background-position: center left;
+}
+
+div.browse-unselected {
+       padding-left: 9px; 
+}
+
+ul.browse-list {
+       list-style: none;
+       padding:0px;
+}
+
+/* feedback /errors */
+div#error {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #DD0000;
+       padding: 5px;
+       background-color: #F4DCDC;
+       color: #A50707;
+       background-color: #F4DCDC;
+       padding-left: 25px;
+       font-weight: bold;
+}
+div#error h4 {
+       color: black;
+       margin-left: 0px;
+}
+
+div#error ul, div#feedback ul, div#help ul {
+       position: relative;
+       list-style: none;
+       margin-left: 0px;
+       padding-left: 0px;
+}
+
+div#error ul li{
+       margin-top: 5px;
+}
+
+div#feedback {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #17B506;
+       padding: 5px;
+       background-color: #F2FCF0;
+       color: #595241;
+       font-weight: bold;
+}
+
+div#help {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #ACCFCC;
+       padding: 5px;
+       background-color: #E9F4F3;
+       color: #024C41;
+}
+
+div#info {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #B8AE9C;
+       padding: 5px;
+       background-color: #EFE6FF;
+       color: #595241;
+       font-weight: bold;
+}
+
+div#warning {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #FF8400;
+       padding: 5px;
+       background-color: #FFF6ED;
+       color: #D95900;
+       font-weight: bold;
+}
+acronym {
+       cursor: help;
+}
+
+div.news p {
+       margin-left: 10px;
+}
+div.news span.date {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: #B8AE9C; 
+}
+
+/* home page links */
+div.home-link {
+       padding: 2px;
+       float: left;
+       text-align: center;
+       margin: 2px;
+       width: 120px;
+       height: 90px;
+}
+div.home-link:hover {
+       padding: 1px;
+       background-color: #F7F3ED;
+       border: 1px solid #afafaf;
+       float: left;
+       text-align: center;
+       margin: 2px;
+}
+div.home-link a {
+       text-decoration: none;
+       font-weight: bold;
+}
+
+div.home-link img {
+       border: 0px;
+}
+
+/* sequence links */
+div#sequence-links {
+       float:right;
+       margin-top: 10px;
+       padding-right: 5px;
+       padding-top:7px;
+}
+div#sequence-links a {
+       text-decoration: none;
+}
+
+div.dropdown {
+       width: 200px;
+       padding: 2px;
+       background-color: white;
+       color: black;
+       border-left: 1px solid #ECFEEA;
+       border-right: 1px solid #ECFEEA;
+       border-bottom: 1px solid #ECFEEA;
+       font-weight: normal;
+}
+
+div.dropdown-heading {
+       background-color: #ACCFCC;
+       color: #595241;
+       border-left: 1px solid #ECFEEA;
+       border-right: 1px solid #ECFEEA;
+       border-top: 1px solid #ECFEEA;
+       font-weight: bold;
+       padding: 2px;
+}
+
+div.required {
+       font-weight: bold;
+       color: red;
+       font-size: large;
+       float: left;
+       position: relative;
+       margin-top: -5px;
+       height: 15px;
+       padding-right: 2px;
+}
+
+div#content_text {
+       margin-left: 5px;
+}
+
+form {
+       clear: none;
+       display:inline;
+}
+
+
+optgroup {
+       /*font-size: small;*/
+}
+
+/* packing */
+div.paging {
+   width: 100%;
+   text-align: center;
+   margin: 0.5em auto;
+}
+div.paging ul {
+   list-style: none;
+   display: inline;
+   padding: 0px;
+   border: 1px solid #000;
+}
+div.paging li { 
+       display: inline; 
+       padding-left: 2px; 
+       padding-right: 2px;
+       padding-top: 0px;
+       padding-bottom: 0px;
+}
+
+div.paging li a {
+       text-decoration: none;
+       padding-left: 4px;
+       padding-right: 4px;
+       border-left: 1px solid white;
+       border-right: 1px solid white;
+}
+
+div.paging li a:hover, div.paging li a.current {
+   background-color: #F7F3ED;
+   border-left: 1px solid #000;
+   border-right: 1px solid #000;
+}
+
+#header{
+       background-color: white;
+       /*background-image: url(images/pencil_top.gif);
+       background-position: right bottom;
+       background-repeat: no-repeat;*/
+       height : 5.7em;
+}
+
+#header a{
+       font-weight:600;
+       color: black;
+}
+
+
+#header a:hover {
+       color: #595241;
+       background-color: #F7F3ED;
+}
+#tl_corner{
+
+       background-image:url(images/tl_corner.gif);
+       background-position: top left;
+       background-repeat: no-repeat;
+padding:0;
+}
+div.top {
+    /* Top space */
+    background-color: #595241;
+       color: #FFF;
+    margin: 0;
+    padding: 0;
+       padding-top:9px;
+}
+div.tabs {
+       /* Navigational Plone Tabs(tm), implemented by customizing the a tag - they are surprisingly elegant. The power of CSS runs strong in these :) */
+    background-color: transparent;
+       border-collapse: collapse;
+       border-bottom: 1px solid #B8AE9C;
+       padding: 0.5em 0em 0em 2em;
+       white-space: nowrap;
+}
+
+div.tabs a {
+    /* The normal, unselected tabs. They are all links */
+    background-color: transparent;
+    border-color: #B8AE9C;
+    border-width: 1px; 
+    border-style: solid solid none solid;
+    color: #595241;
+    height: 1.2em;
+    margin-right: 0.5em;
+    padding: 0em 2em 0em;
+    
+}
+
+div.tabs a.selected {
+    /* The selected tab. There's only one of this */
+    background-color: white;
+    border-bottom: #B8AE9C 1px solid;
+    color: #595241;
+    font-weight: normal;
+}
+
+div.tabs a:hover, div.tabs a:active {
+    background-color: #B8AE9C;
+    border-bottom: 1px solid #B8AE9C;
+    color: white;
+}
+
+
+h4.box {
+       font-size:0.85em;
+       padding: 2px;
+}
+
+div.box {
+       color: black;
+
+       font-size:0.85em;
+       font-weight: normal;
+       padding:5px;
+       margin-bottom:5px;
+}
+
+h5.box { 
+    background-color: #6F7172;
+    border: 1px solid #B8AE9C;
+    border-style: solid solid none solid;
+    color: Black;
+    padding: 0em 1em 0em 1em;
+    
+    display: inline;
+       font-size:  1em;
+    height: 1em;
+}
+
+div.box a:link {
+       text-decoration: none;
+}
+
+div.box a:visited {
+       color: #2A6C28;
+       text-decoration: none;
+}
+
+div.box a:hover {
+       text-decoration: underline;
+}
+
+.boxDetails {
+    text-align: right;
+}
+
+div.box .content {
+    padding: 1em;
+       font-size:  1em;
+}
+
+div.box a.close {
+    float: right;
+    text-transform: none;
+    border-left: 1pt solid #B8AE9C;
+    padding: 0em 0.2em;
+}
+
+div.box h1, 
+div.box h2, 
+div.box h3, 
+div.box h4 {
+    margin: 0;
+    padding: 0;
+}
+
+div.box .even {
+    background-color: #F7F3ED;
+}
+
+div.box .odd {
+    background-color: transparent;
+}
+
+
+/* users/index.php */
+
+div.course {
+       position: relative;
+       width: 30em;
+       height: 10.5em;
+       border: rgb(204, 204, 204) 1px solid;
+       background-color: #F7F7F7;
+       float: left;
+       margin: 3px;
+       padding: 5px;
+}
+
+div.course.break {
+       clear: left;
+}
+
+div.course h2 {
+       border: 0px;
+       font-weight: normal;
+       font-size: large;
+
+}
+
+div.course:hover {
+       background-color:#FBF4E9;
+       border: #B8AE9C 1px solid;
+}
+
+div.course img.icon    {
+       float: left;
+       margin: 2px;
+       height:6.8em;
+       width:6.8em;
+       margin-right:5px;
+}
+img.headicon   {
+       float: left;
+       margin:-10px -10px 0px 5px;
+       height:5em;
+       width:5em;
+       vertical-align:top;
+       border:0px;
+}
+div.course div.shortcuts {
+       text-align: right;
+       clear: left;
+       vertical-align: middle;
+}
+
+fieldset#shortcuts {
+       float: right;
+       background-color: #FEFDEF;
+       border: 1px solid #B8AE9C;
+       margin: -5pt 5pt 5pt 5pt;
+       padding-right: 10pt;
+       padding-bottom: 5pt;
+       padding-left: 10pt;
+}
+
+
+
+fieldset {
+       margin-bottom: 10pt;
+}
+#shortcuts legend {
+}
+#shortcuts ul {
+       position: relative;
+       margin-top: 0pt;
+       margin-bottom: 0pt;
+       margin-left: 0pt;
+       list-style-type:  none;
+       padding-left: 0pt; 
+}
+
+a#guide {
+       background-image: url('../default/images/guide.gif'); background-repeat: no-repeat; background-position: 7px 4px;
+       background-color: #eee;
+       padding: 2px 10px 2px 27px;
+       border: 1px solid #ccc;
+       float:right;
+       text-decoration:none;
+       font-size:0.85em;
+       margin-top:5px;
+}
+
+div#content-text {
+       padding-right: 5pt;
+       line-height:150%;
+}
+
+div#content-text li {
+       margin-left: 15pt;
+}
+
+div#content-info {
+       margin: 5pt;
+       font-size: small;
+       color: #b8ae9c;
+       clear: both;
+}
+
+div#container {
+       text-align: left;
+       margin: 0px auto;
+       padding: 0px;
+       border:0;
+       width: 95%;
+}
+
+/* login page */
+div.column {
+       float: left;
+       width: 49%;
+       min-width: 170px;
+}
+
+div.column h3 {
+       background-color: #F6EAD6;
+       border-bottom: .05em solid #6F7172;
+       font-size: small;
+       display:block;
+       color:black;
+       font-weight:600;        
+       padding-left:0.5em;
+}
+
+div.column fieldset {
+       margin-right:-30px;     
+       height:17em;
+}
+
+div.insidecol {
+   min-height: 170px;
+   height: 170px;
+   padding:5px;
+}
+
+
+/* index page */
+ul#home-links {
+       list-style: none;
+}
+ul#home-links li {
+       
+       display: inline;
+       float: left;
+       padding: 0.8em;
+       text-align: center;
+       margin: 0.1em;
+       width: 8.5em;
+       height: 7.0em;
+       padding-left:0px;
+
+}
+ul#home-links li a {
+       text-decoration: none;
+       border: 1px transparent;
+       font-weight: bold;
+}
+ul#home-links li a img {
+       border: 0px;
+       display: block;
+       padding-left:25px;
+}
+
+/* enrollment tabs */
+#navlist {
+       padding: 0px;
+       margin-left: 0;
+       margin-right: auto;
+       margin-left: auto;
+       margin-bottom: 4px;
+       margin-top:15px;
+       white-space: nowrap;
+}
+
+#navlist li {
+       list-style: none;
+       display: inline;
+       margin: 0px;
+}
+
+#navlist li a {
+       padding: 3px 9px;
+       border: 1px solid #F7F3ED;
+       border-bottom: none;
+       background-color: #F7F3ED;
+       text-decoration: none;
+       margin-left: 4px;
+/*
+       -moz-border-radius-topright: 4px;
+       -moz-border-radius-topleft: 4px;
+*/
+       white-space: nowrap;
+}
+
+#navlist li a:hover, #navlist li a:active {
+       color: #000;
+       background-color: #fff;
+}
+
+/* tree */
+.img-size-tree {
+       vertical-align: middle;
+       margin-top: 0px;
+       padding:0;
+       height:1.45em;
+       width:1.45em;
+       margin:-4px;
+}
+/* profile page */
+dl#public-profile {
+       width: 100%;
+}
+dl#public-profile dt {
+       float: left;
+       font-weight: bold;
+       width: 30%;
+       text-align: right;
+       clear: left;
+       border-right: 1px solid #F7F3ED;
+       padding: 5px 5px 5px 0px;
+       vertical-align: middle;
+       margin-right: 5px;
+}
+dl#public-profile dd {
+       margin-bottom: 5px;
+       clear: right;
+       padding: 5px 0px 5px 5px;
+}
+
+/* floating layout */
+#contentwrapper{
+       float: left;
+       width: 99%;
+       min-width:53em;
+       padding:0px;
+       margin-left:5px;
+       margin-right:5px;
+}
+
+/*#contentcolumn {
+       margin-left: 0.5em;
+       padding-right: 5px;
+}
+#contentcolumn_shiftright {
+       margin-left: 17em;
+}
+
+#leftcolumn{
+       float: left;
+       width: 16em;
+       margin-left: 5px;
+       margin-top:-10px;
+}*/
+
+.sidebox fieldset {
+       border:0px;
+}
+
+#footer{
+       /*position:absolute;
+       bottom:0px;*/
+       clear: left;
+       width: 100%;
+       text-align: center;
+       padding: 4px 0px;
+}
+
+/** forum stuff **/
+#forum-thread li {border:1px solid #eee; border-bottom: 1px solid #F7F3ED; float:left; width: 98%; list-style: none; }
+#forum-thread li.even { background-color: #F7F3ED; border-top: none; }
+#forum-thread li.odd { background-color: #fff; }
+div.forum-post-author { float:left; width:150px; padding:8px 10px; }
+div.forum-post-author a.title {font-size: 1.1em; line-height: 1.2em; font-weight: bold; text-decoration:none; }        
+div.forum-post-author img.profile-picture { border: 2px solid #F7F3ED; text-align:right;}
+div.forum-post-content { margin-left: 150px; padding: 5px 0px 18px 18px;}
+div.forum-post-content h3 { font-weight: 500; float:left;clear:right; }
+div.forum-post-ctrl { float: right; padding-right: 5px; color: #a1a1a1;}
+div.forum-post-ctrl a { text-decoration: none; }
+div.forum-post-ctrl span { color: black; background-color: #fefdc2; padding: 3px; }
+div.forum-post-content p.date { color: #a1a1a1; border-bottom: 1px solid #F7F3ED; }
+div.forum-post-content div.body p { margin-bottom:1em; }
+div.forum-paginator{border:thin #cccccc solid; padding:.3em; width:95%;margin:auto;background-color:#F7F3ED;}
+span.forum-paginator-active{font-weight:700;text-decoration:underline; height:2em;}
+
+
+
+/** inbox stuff - reuses some of the forum layout **/
+#inbox-msg li {border:1px solid #eee; border-bottom: 1px solid #F7F3ED; width: 95%; list-style: none; min-height: 11em;}
+
+
+
+div#topnavlistcontainer {
+    background-color: white;
+       /*background-image: url(images/pencil_bottom.gif);
+       background-position:  top right;
+       background-repeat: no-repeat;*/
+}
+ul#topnavlist {
+       padding-top: 5px;
+       white-space: nowrap;
+       margin-top: 0px;
+       margin-left:5px;
+}
+
+ul#topnavlist li {
+       list-style: none;
+       display: inline;
+       margin: 0px;
+}
+
+ul#topnavlist li a:hover, ul#topnavlist li a:focus, ul#topnavlist li a.active {
+    background-color: #a1c4f8;
+    color: black;
+       text-decoration:none;
+}
+
+ul#topnavlist li a {
+    /* The normal, unselected tabs. They are all links */
+    color: #4b535f;
+       font-weight:bold;
+    height: 1.5em;
+    padding: 0.2em 2em 0em;
+       text-decoration:none;
+       background-color:#f2f7fe;
+
+       border-left:1px solid #a1c4f8;
+       border-right:1px solid #a1c4f8;
+       border-top:1px solid #a1c4f8;   
+/*
+       border-left:1px solid #ccc;
+       border-right:1px solid #ccc;
+       border-top:1px solid #ccc;      
+*/
+}
+
+ul#topnavlist li a.selected {
+    /* The selected tab. There's only one of these */
+    color: #4b535f;
+    font-weight: normal;
+}
+
+#subnav {
+       background-color:#a1c4f8; 
+       font-size:0.85em; 
+       padding: 5px 10px 0px 5px; 
+       border-bottom:1px solid #4b535f; 
+       height:1.8em;
+       margin-bottom:5px;
+}
+
+#subnav a {
+       text-decoration:none;
+}
+
+ol#tools>li:hover {
+       border: 1px solid #e0e0e0;
+       background-color: #efefef; 
+}
+
+/*  tool list on admin home and manage screens  */
+ li.top-tool { 
+       list-style: none;
+       padding: 2px 2px 2px 15px;
+       margin-bottom: 5px; 
+       line-height: 200%; 
+       background-color: #fdfdfd; 
+       border-bottom: 1px solid #efefef; 
+       /* -moz-border-radius: 4px;  */
+       border: 1px solid #eeeeff;}
+
+li.top-tool a {  font-weight: bold; } /* ol#tools>li>a */ 
+
+li.child-tool a { 
+       font-size: x-small;
+       font-weight: normal; 
+}
+
+/* ol#tools>li>ul, */ 
+ul.child-top-tool {
+       margin-top: -5px;
+       padding-left: 0px;
+       margin-left: 0px;
+       display: inline;
+}
+ul.child-top-tool:before {
+       content: " : ";
+}
+
+/* ol#tools>li>ul>li, */ 
+li.child-tool {
+       display: inline;
+       margin-right: 5px;
+       font-size: x-small;
+}
+
+/* to modify  tool icons on the course home page */
+/*
+#icon-color-filter{
+       width:3.9em;
+       height:3.85em;
+       background-color:#000000;
+       -moz-opacity:0.5;
+         filter:alpha(opacity=10);
+       opacity:.10;
+       margin-top:-3.85em;
+       margin-left:1.90em;
+
+}
+*/
+.img-size-home {
+       height:3.85em;
+       width:3.9em;
+}
+
+/* browse courses */
+dl.browse-course {
+       width: 100%;
+       padding-bottom: 25px;
+       background-color: #fffaf0;
+       border:1px #6F7172 solid;
+       width:75%;
+       margin:auto;
+       margin-left:15em;
+}
+dl.browse-course dt {
+       float: left;
+       font-weight: bold;
+       width: 25%;
+       text-align: right;
+       clear: left;
+       padding: 5px 10px 5px 0px;
+       vertical-align: middle;
+}
+dl.browse-course dd {
+       margin-bottom: 5px;
+       clear: right;
+       padding: 5px 0px 5px 10px;
+       margin-left: 26%;
+
+}
+
+.side-menu {
+
+width: 19%;
+/*     min-width:15em;*/
+/*     max-width:18em;*/
+       background-color:#efefef;
+       border:1px solid #8b8b8b;
+       padding:0px 5px 0px 5px;
+}
+
+.side-menu h3 {
+       color:black; 
+       font-size:smaller; 
+       padding:3px;
+       margin-left:-5px;
+       margin-right:-5px;      
+
+}
+
+.side-menu h2 {
+       font-size:95%;
+       border-bottom:1px solid #838383;        
+       
+}
+
+#gototop {
+       clear: left; 
+       font-size:smaller;
+       text-align:right;
+       margin-top:80px;
+}
+#gototop a:link, #gototop a:visited{
+       text-decoration:none;
+}
+
+.box fieldset {
+       border:0px;
+}
+
+.box .button {
+       float:right;
+       margin-top:-15px;
+}
+
+.grab {
+       cursor:move;
+       padding: 0px 5px 0px 5px;
+}
+
+.grabmenu {
+       float:right; 
+       margin-bottom:-10px; 
+       margin-top:3px; 
+       margin-right:-5px;
+}
\ No newline at end of file
diff --git a/themes/fluid/theme.cfg.php b/themes/fluid/theme.cfg.php
new file mode 100644 (file)
index 0000000..144b030
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+
+// $Id: theme.cfg.php 2813 2004-12-12 15:37:46Z greg $
+
+/* This is the default configuration file for the default theme. */
+
+/* The theme's name. */
+       $_theme['name'] = 'Fluid';
+
+/* The theme's version number. */
+       $_theme['version'] = '0.1';
+
+/* Which version of ATutor is this theme intended for. */
+       $_theme['atutor-version'] = '1.6';
+
+/* author information */
+       $_theme['author_name']  = 'ATutor';
+       $_theme['author_url']   = 'http://atutor.ca';
+       $_theme['author_email'] = '';
+
+/* theme default course banner styles: */
+       $_theme['banner']['font-family'] = 'Verdana, Arial, sans-serif';
+       $_theme['banner']['font-weight'] = 'bold';
+       $_theme['banner']['color']       = 'black';
+       $_theme['banner']['font-size']   = 'xx-large';
+       $_theme['banner']['text-align']  = 'center';
+
+       $_theme['banner']['background-color'] = 'white';
+       $_theme['banner']['background-image'] = '';
+       $_theme['banner']['vertical-align']   = 'middle';
+       $_theme['banner']['padding']          = '3px';
+
+?>
diff --git a/themes/fluid/theme_info.xml b/themes/fluid/theme_info.xml
new file mode 100644 (file)
index 0000000..c79f188
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="EN"?>\r
+\r
+<theme>\r
+       <title>Fluid</title>\r
+       <version>1.0</version>\r
+       <last_updated>2008-05-12</last_updated>\r
+       <extra_info>An ATutor theme that implements fluid elements. See http://fluidproject.org for more information.</extra_info>\r
+</theme>\r
+\r
diff --git a/themes/greenmin/content.tmpl.php b/themes/greenmin/content.tmpl.php
new file mode 100644 (file)
index 0000000..89d2412
--- /dev/null
@@ -0,0 +1,31 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+if (!defined('AT_INCLUDE_PATH')) { exit; } ?>\r
+\r
+<?php if ($this->shortcuts): ?>\r
+<fieldset id="shortcuts"><legend><?php echo _AT('shortcuts'); ?></legend>\r
+       <ul>\r
+               <?php foreach ($this->shortcuts as $link): ?>\r
+                       <li><a href="<?php echo $link['url']; ?>"><?php echo $link['title']; ?></a></li>\r
+               <?php endforeach; ?>\r
+       </ul>\r
+</fieldset>\r
+<?php endif; ?>\r
+\r
+<div id="content-text">\r
+       <?php echo $this->body; ?>\r
+</div>\r
+\r
+<div id="content-info">\r
+       <?php echo $this->content_info; ?>\r
+</div>
\ No newline at end of file
diff --git a/themes/greenmin/forms.css b/themes/greenmin/forms.css
new file mode 100644 (file)
index 0000000..36460cf
--- /dev/null
@@ -0,0 +1,73 @@
+div.input-form {\r
+       width: 90%; \r
+       max-width: 600px;\r
+       margin-left:auto; \r
+       margin-right:auto;\r
+       border: 1px solid #f0f0f0;\r
+       margin-bottom: 20px;\r
+}\r
+\r
+div.input-form div.row h3 {\r
+       margin-left: 0px;\r
+}\r
+\r
+\r
+div.input-form div.row {\r
+       background-color: #fdfdfd;\r
+       padding:8px;\r
+}\r
+\r
+div.input-form .footer {\r
+       border-top: 1px solid #f0f0f0;\r
+}\r
+\r
+div.input-form p {\r
+       margin-left: 0px;\r
+}\r
+\r
+div.input-form input {\r
+       z-index: 2;\r
+}\r
+div.input-form textarea {\r
+       border: 1px solid #999;\r
+       width: 98%;\r
+       background-color: white;\r
+       padding: 2px;\r
+       margin-right: 2px;\r
+}\r
+\r
+div.input-form textarea:focus {\r
+       border:1px solid blue;\r
+       background-color: white;\r
+       padding: 2px;\r
+}\r
+\r
+div.input-form input[type=text], div.input-form input[type=password] {\r
+       border: 1px solid #999;\r
+       background-color: white;\r
+       padding: 2px;\r
+       max-width: 60%;\r
+}\r
+\r
+div.input-form input:focus {\r
+       border: 1px solid blue;\r
+       padding: 2px\r
+}\r
+\r
+div.input-form div.buttons {\r
+       text-align: right;\r
+       padding:8px;\r
+}\r
+div.input-form div.buttons input {\r
+       border: 1px solid #999;\r
+       background-color: white;\r
+       padding: 2px;\r
+       padding-left: 10px;\r
+       padding-right: 10px;\r
+       min-width: 100px;\r
+       margin-left: 5px;\r
+}\r
+div.input-form div.buttons input:hover {\r
+       background-color: #f5f5ff;\r
+       border: 1px solid blue;\r
+}
\ No newline at end of file
diff --git a/themes/greenmin/ie_styles.css b/themes/greenmin/ie_styles.css
new file mode 100644 (file)
index 0000000..76ad01e
--- /dev/null
@@ -0,0 +1,25 @@
+/* IE specific styles */
+
+ul#topnavlist {
+       zoom:100%;
+       margin:0px;
+}
+
+ul#topnavlist li {
+       zoom:100%;
+       padding:0.3em;
+       padding-bottom:0.3em;
+       margin:0px;
+       margin-bottom:-3px;
+}
+
+label {
+       zoom:100%;
+       margin:0px;
+}
+
+table.data tfoot input {
+       min-width:0px;
+}
+
+
diff --git a/themes/greenmin/images/Thumbs.db b/themes/greenmin/images/Thumbs.db
new file mode 100644 (file)
index 0000000..2ffc443
Binary files /dev/null and b/themes/greenmin/images/Thumbs.db differ
diff --git a/themes/greenmin/images/arrow_ltr.gif b/themes/greenmin/images/arrow_ltr.gif
new file mode 100644 (file)
index 0000000..90da978
Binary files /dev/null and b/themes/greenmin/images/arrow_ltr.gif differ
diff --git a/themes/greenmin/images/back.gif b/themes/greenmin/images/back.gif
new file mode 100644 (file)
index 0000000..f290f43
Binary files /dev/null and b/themes/greenmin/images/back.gif differ
diff --git a/themes/greenmin/images/continue.gif b/themes/greenmin/images/continue.gif
new file mode 100644 (file)
index 0000000..157d3f1
Binary files /dev/null and b/themes/greenmin/images/continue.gif differ
diff --git a/themes/greenmin/images/linkOpaque.gif b/themes/greenmin/images/linkOpaque.gif
new file mode 100644 (file)
index 0000000..12e588f
Binary files /dev/null and b/themes/greenmin/images/linkOpaque.gif differ
diff --git a/themes/greenmin/images/linkTransparent.gif b/themes/greenmin/images/linkTransparent.gif
new file mode 100644 (file)
index 0000000..c2dd10f
Binary files /dev/null and b/themes/greenmin/images/linkTransparent.gif differ
diff --git a/themes/greenmin/images/newsitem_icon.gif b/themes/greenmin/images/newsitem_icon.gif
new file mode 100644 (file)
index 0000000..fd6e96f
Binary files /dev/null and b/themes/greenmin/images/newsitem_icon.gif differ
diff --git a/themes/greenmin/images/next.gif b/themes/greenmin/images/next.gif
new file mode 100644 (file)
index 0000000..9477a7b
Binary files /dev/null and b/themes/greenmin/images/next.gif differ
diff --git a/themes/greenmin/images/previous.gif b/themes/greenmin/images/previous.gif
new file mode 100644 (file)
index 0000000..69c43e7
Binary files /dev/null and b/themes/greenmin/images/previous.gif differ
diff --git a/themes/greenmin/images/resume.gif b/themes/greenmin/images/resume.gif
new file mode 100644 (file)
index 0000000..b80d5eb
Binary files /dev/null and b/themes/greenmin/images/resume.gif differ
diff --git a/themes/greenmin/images/side_arrow.gif b/themes/greenmin/images/side_arrow.gif
new file mode 100644 (file)
index 0000000..c72b458
Binary files /dev/null and b/themes/greenmin/images/side_arrow.gif differ
diff --git a/themes/greenmin/images/sort.gif b/themes/greenmin/images/sort.gif
new file mode 100644 (file)
index 0000000..097d27e
Binary files /dev/null and b/themes/greenmin/images/sort.gif differ
diff --git a/themes/greenmin/images/user-star.gif b/themes/greenmin/images/user-star.gif
new file mode 100644 (file)
index 0000000..e53b7d5
Binary files /dev/null and b/themes/greenmin/images/user-star.gif differ
diff --git a/themes/greenmin/images/user.gif b/themes/greenmin/images/user.gif
new file mode 100644 (file)
index 0000000..74a3cf5
Binary files /dev/null and b/themes/greenmin/images/user.gif differ
diff --git a/themes/greenmin/include/box.tmpl.php b/themes/greenmin/include/box.tmpl.php
new file mode 100644 (file)
index 0000000..fb049c4
--- /dev/null
@@ -0,0 +1,7 @@
+<?php if (!defined('AT_INCLUDE_PATH')) { exit; } ?>
+
+<br />
+<h4 class="box"><?php echo $this->title; ?></h4>
+<div class="box">
+               <?php echo $this->dropdown_contents; ?>
+</div>
\ No newline at end of file
diff --git a/themes/greenmin/include/footer.tmpl.php b/themes/greenmin/include/footer.tmpl.php
new file mode 100644 (file)
index 0000000..4ac8828
--- /dev/null
@@ -0,0 +1,44 @@
+<?php if (!defined('AT_INCLUDE_PATH')) { exit; } ?>
+
+       <?php if ($_SESSION['course_id'] > 0): ?>
+               
+               <div align="right" style="clear: left;" id="gototop">           
+                       <br />
+                       <span style="font-size:smaller;padding-right:3px;"><a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#content" title="<?php echo _AT('goto_content'); ?> Alt-c" ><?php echo _AT('goto_top'); ?></a>  </span>
+               </div>  
+
+       <?php endif; ?> 
+
+</div>
+</div>
+       <?php if (($_SESSION['course_id'] > 0) && $this->side_menu): ?>
+               <div id="leftcolumn">
+                       <script type="text/javascript">
+                       //<![CDATA[
+                       var state = getcookie("side-menu");
+                       if (state && (state == 'none')) {
+                               document.writeln('<a name="menu"></a><div style="display:none;" id="side-menu">');
+                       } else {
+                               document.writeln('<a name="menu"></a><div style="" id="side-menu">');
+                       }
+                       //]]>
+                       </script>
+
+                       <?php require(AT_INCLUDE_PATH.'side_menu.inc.php'); ?>
+
+                       <script type="text/javascript">
+                       //<![CDATA[
+                               document.writeln('</div>');
+                       //]]>
+                       </script>
+               </div>
+       <?php endif; ?>
+</div>
+
+<div id="footer">
+       <br /><br />
+       <?php require(AT_INCLUDE_PATH.'html/languages.inc.php'); ?>
+       <?php require(AT_INCLUDE_PATH.'html/copyright.inc.php'); ?>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/themes/greenmin/include/header.tmpl.php b/themes/greenmin/include/header.tmpl.php
new file mode 100644 (file)
index 0000000..b9130a1
--- /dev/null
@@ -0,0 +1,331 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: header.tmpl.php 3825 2005-03-11 15:35:51Z joel $
+if (!defined('AT_INCLUDE_PATH')) { exit; }
+/* available header.tmpl.php variables:
+ * $this->lang_code                    the ISO language code
+ * SITE_NAME                           the site name from the config file
+ * $this->page_title           the name of this page to use in the <title>
+ * $this->lang_charset         the ISO language character set
+ * $this->content_base_href    the <base href> to use for this page
+ * $this->base_path                    the absolute path to this atutor installation
+ * $this->rtl_css                      if set, the path to the RTL style sheet
+ * $this->banner_style         -deprecated-
+ * $this->theme                                the directory name of the current theme
+ * $this->base_href                    the full url to this atutor installation
+ * $this->onload                       javascript onload() calls
+ * $this->img                          the absolute path to this theme's images/ directory
+ * $this->sequence_links       associative array of 'previous', 'next', and/or 'resume' links
+ * $this->path                         associative array of path to this page: aka bread crumbs
+ * $this->rel_url                      the relative url from the installation root to this page
+ * $this->nav_courses          associative array of this user's enrolled courses
+ * $this->section_title                the title of this section (course, public, admin, my start page)
+ * $this->top_level_pages      associative array of the top level navigation
+ * $this->current_top_level_page       the full path to the current top level page with file name
+ * $this->sub_level_pages                      associate array of sub level navigation
+ * $this->back_to_page                         if set, the path and file name to the part of this page (if parent is not a top level nav)
+ * $this->current_sub_level_page       the full path to the current sub level page with file name
+ * $this->guide                                the full path and file name to the guide page
+ * ======================================
+ * top_level_pages           array(array('url', 'title'))     the top level pages. ATutor default creates tabs.
+ * section_title             string                           the name of the current section. either name of the course, administration, my start page, etc.
+ * page_title                string                           the title of the current page.
+ * path                      array(array('url', 'title'))     the path to the current page.
+ * back_to_page              array('url', 'title')            the link back to the part of the current page, if needed.
+ * current_top_level_page    string                           full url to the current top level page in "top_leve_pages"
+ * current_sub_level_page    string                           full url to the current sub level page in the "sub_level_pages"
+ * sub_level_pages           array(array('url', 'title'))     the sub level pages.
+ */
+
+// will have to be moved to the header.inc.php
+global $system_courses, $_custom_css;
+
+?><!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="<?php echo $this->lang_code; ?>"> 
+
+<head>
+       <title><?php echo SITE_NAME; ?> : <?php echo $this->page_title; ?></title>
+       <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $this->lang_charset; ?>" />
+       <meta name="Generator" content="ATutor - Copyright 2005 by http://atutor.ca" />
+       <base href="<?php echo $this->content_base_href; ?>" />
+       <link rel="shortcut icon" href="<?php echo $this->base_path; ?>favicon.ico" type="image/x-icon" />
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/print.css" type="text/css" media="print" />
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/styles.css" type="text/css" />
+       <!--[if IE]>
+         <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/ie_styles.css" type="text/css" />
+       <![endif]-->
+       <link rel="stylesheet" href="<?php echo $this->base_path.'themes/'.$this->theme; ?>/forms.css" type="text/css" />
+       <?php echo $this->rtl_css; ?>
+       <?php if ($system_courses[$_SESSION['course_id']]['rss']): ?>
+       <link rel="alternate" type="application/rss+xml" title="<?php echo SITE_NAME; ?> - RSS 2.0" href="<?php echo $this->base_href; ?>get_rss.php?<?php echo $_SESSION['course_id']; ?>-2" />
+       <link rel="alternate" type="application/rss+xml" title="<?php echo SITE_NAME; ?> - RSS 1.0" href="<?php echo $this->base_href; ?>get_rss.php?<?php echo $_SESSION['course_id']; ?>-1" />
+       <?php endif; ?>
+       <?php echo $this->custom_css; ?>
+</head>
+<body onload="<?php echo $this->onload; ?>"><div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>
+<script language="JavaScript" src="<?php echo $this->base_path; ?>overlib.js" type="text/javascript"></script>
+<script language="javascript" type="text/javascript">
+//<!--
+var newwindow;
+function poptastic(url) {
+       newwindow=window.open(url,'popup','height=600,width=600,scrollbars=yes,resizable=yes');
+       if (window.focus) {newwindow.focus()}
+}
+
+function getexpirydate(nodays){
+       var UTCstring;
+       Today = new Date();
+       nomilli=Date.parse(Today);
+       Today.setTime(nomilli+nodays*24*60*60*1000);
+       UTCstring = Today.toUTCString();
+       return UTCstring;
+}
+
+function setcookie(name,value,duration){
+       cookiestring=name+"="+escape(value)+";path=/;expires="+getexpirydate(duration);
+       document.cookie=cookiestring;
+       if(!getcookie(name)){
+               return false;
+       } else {
+               return true;
+       }
+}
+
+function getcookie(cookiename) {
+       var cookiestring=""+document.cookie;
+       var index1=cookiestring.indexOf(cookiename);
+       if (index1==-1 || cookiename=="") return ""; 
+       var index2=cookiestring.indexOf(';',index1);
+       if (index2==-1) index2=cookiestring.length; 
+       return unescape(cookiestring.substring(index1+cookiename.length+1,index2));
+}
+
+function setDisplay(objId) {
+       var toc = document.getElementById(objId);
+
+       var state = getcookie(objId);
+       if (document.getElementById(objId) && state && (state == 'none')) {
+               toggleToc(objId);
+       }
+}
+
+
+function setstates() {
+       return;
+       var objId = "side-menu";
+       var state = getcookie(objId);
+       if (document.getElementById(objId) && state && (state == 'none')) {
+               toggleToc(objId);
+       }
+
+       var objId = "toccontent";
+       var state = getcookie(objId);
+       if (document.getElementById(objId) && state && (state == 'none')) {
+               toggleToc(objId);
+       }
+
+}
+
+function showTocToggle(objId, show, hide, key, selected) {
+       if(document.getElementById) {
+               if (key) {
+                       var accesskey = " accesskey='" + key + "' title='"+ show + "/" + hide + " Alt - "+ key +"'";
+               } else {
+                       var accesskey = "";
+               }
+
+               if (selected == 'hide') {
+                       document.writeln('<a href="javascript:toggleToc(\'' + objId + '\')" ' + accesskey + '>' +
+                       '<span id="' + objId + 'showlink" style="display:none;">' + show + '</span>' +
+                       '<span id="' + objId + 'hidelink">' + hide + '</span>'  + '</a>');
+               } else {
+                       document.writeln('<a href="javascript:toggleToc(\'' + objId + '\')" ' + accesskey + '>' +
+                       '<span id="' + objId + 'showlink">' + show + '</span>' +
+                       '<span id="' + objId + 'hidelink" style="display:none;">' + hide + '</span>'    + '</a>');
+               }
+       }
+}
+
+function toggleToc(objId) {
+       var toc = document.getElementById(objId);
+       if (toc == null) {
+               return;
+       }
+       var showlink=document.getElementById(objId + 'showlink');
+       var hidelink=document.getElementById(objId + 'hidelink');
+       if (hidelink.style.display == 'none') {
+               document.getElementById('contentcolumn').id="contentcolumn_shiftright";
+               toc.style.display = '';
+               hidelink.style.display='';
+               showlink.style.display='none';
+       } else {
+               document.getElementById('contentcolumn_shiftright').id="contentcolumn";
+               toc.style.display = 'none';
+               hidelink.style.display='none';
+               showlink.style.display='';
+       }
+       setcookie(objId, toc.style.display, 1);
+}
+//-->
+</script>
+<!-- section title -->
+<div><a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#content" accesskey="c"><img src="<?php echo $this->base_path; ?>images/clr.gif" height="1" width="1" border="0" alt="<?php echo _AT('goto_content'); ?> ALT+c" /></a>               <a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); ?>#menu"  accesskey="m"><img src="<?php echo $this->base_path; ?>images/clr.gif" height="1" width="1" border="0" alt="<?php echo _AT('goto_menu'); ?> ALT+m" /></a><h1 id="section-title"><?php echo $this->section_title; ?><?php if (($_SESSION['course_id'] > 0) && ($_SESSION['enroll'] == AT_ENROLL_NO)) : ?>
+               - <small><a href="<?php echo $this->base_path; ?>enroll.php?course=<?php echo $_SESSION['course_id']; ?>"><?php echo _AT('enroll_me'); ?></a></small>
+       <?php endif; ?></h1>
+</div>
+
+<!-- top help/search/login links -->
+<div style="float:right;" id="top-links">
+<!-- back to start page -->
+       <?php if (isset($_SESSION['member_id']) && $_SESSION['member_id']): ?>
+               <!-- start the jump menu -->
+               <?php if (empty($_GET)): ?>
+                       <form method="post" action="<?php echo $this->base_path; ?>bounce.php?p=<?php echo urlencode($this->rel_url); ?>" target="_top">
+               <?php else: ?>
+                       <form method="post" action="<?php echo $this->base_path; ?>bounce.php" target="_top">
+               <?php endif; ?>
+               <label for="jumpmenu" accesskey="j"></label>
+                       <select name="course" id="jumpmenu" title="<?php echo _AT('jump'); ?>:  Alt-j">                                                 
+                               <option value="0"><?php echo _AT('my_start_page'); ?></option>
+                               <optgroup label="<?php echo _AT('courses_below'); ?>">
+                                       <?php foreach ($this->nav_courses as $this_course_id => $this_course_title): ?>
+                                               <option value="<?php echo $this_course_id; ?>"><?php echo $this_course_title; ?></option>
+                                       <?php endforeach; ?>
+                               </optgroup>
+                       </select> <input type="submit" name="jump" value="<?php echo _AT('jump'); ?>" id="jump-button" /> &nbsp; </form>
+               <!-- /end the jump menu -->
+               <?php if ($_SESSION['is_super_admin']): ?>
+                       <img src="<?php echo $this->img; ?>linkTransparent.gif" alt="" /> <a href="<?php echo $this->base_path; ?>bounce.php?admin"><?php echo _AT('return_to_admin_area'); ?></a> | 
+               <?php endif; ?>
+
+               <?php if ($_SESSION['course_id'] > -1): ?>
+                       <?php if (get_num_new_messages()): ?>
+                               <img src="<?php echo $this->img; ?>linkTransparent.gif" alt="" /> <a href="<?php echo $this->base_path; ?>inbox/index.php"><?php echo _AT('inbox'); ?> (<?php echo get_num_new_messages(); ?>)</a>
+                       <?php else: ?>
+                               <img src="<?php echo $this->img; ?>linkTransparent.gif" alt="" /> <a href="<?php echo $this->base_path; ?>inbox/index.php"><?php echo _AT('inbox'); ?></a>
+                       <?php endif; ?>
+               <?php endif; ?>
+       <?php endif; ?>
+
+       <img src="<?php echo $this->img; ?>linkTransparent.gif" alt="" /> <a href="<?php echo $this->base_path; ?>search.php"><?php echo _AT('search'); ?></a> <img src="<?php echo $this->img; ?>linkTransparent.gif" alt="" /> <a href="<?php echo $this->base_path; ?>help/index.php"><?php echo _AT('help'); ?></a>
+</div>
+<br />
+<div id="topnavlistcontainer">
+<!-- the main navigation. in our case, tabs -->
+       <ul id="topnavlist">
+               <?php foreach ($this->top_level_pages as $page): ?>
+                       <?php ++$accesscounter; $accesscounter = ($accesscounter == 10 ? 0 : $accesscounter); ?>
+                       <?php $accesskey_text = ($accesscounter < 10 ? 'accesskey="'.$accesscounter.'"' : ''); ?>
+                       <?php $accesskey_title = ($accesscounter < 10 ? ' Alt+'.$accesscounter : ''); ?>
+                       <?php if ($page['url'] == $this->current_top_level_page): ?>
+                               <li><a href="<?php echo $page['url']; ?>" <?php echo $accesskey_text; ?> title="<?php echo $page['title'] . $accesskey_title; ?>" class="active"><?php echo $page['title']; ?></a></li>
+                       <?php else: ?>
+                               <li><a href="<?php echo $page['url']; ?>" <?php echo $accesskey_text; ?> title="<?php echo $page['title'] . $accesskey_title; ?>"><?php echo $page['title']; ?></a></li>
+                       <?php endif; ?>
+                       <?php $accesscounter = ($accesscounter == 0 ? 11 : $accesscounter); ?>
+               <?php endforeach; ?>
+       </ul>
+</div>
+<!-- the sub navigation -->
+<div style="float: right; padding-top: 5px; padding-right: 5px; font-size:0.85em; text-transform: lowercase;" id="suv-nav-logout">
+       <?php if ($_SESSION['valid_user']): ?>                                  
+               <strong><?php echo get_display_name($_SESSION['member_id']); ?></strong> &nbsp; <img src="<?php echo $this->img; ?>/linkOpaque.gif" alt="" /> <a href="<?php echo $this->base_path; ?>logout.php"><?php echo _AT('logout'); ?></a>
+       <?php else: ?>
+                <img src="<?php echo $this->img; ?>/linkOpaque.gif" alt="" /> <a href="<?php echo $this->base_path; ?>login.php?course=<?php echo $_SESSION['course_id']; ?>"><?php echo _AT('login'); ?></a> &nbsp; <img src="<?php echo $this->img; ?>/linkOpaque.gif" alt="" /> <a href="<?php echo $this->base_path; ?>registration.php"><?php echo _AT('register'); ?></a>
+       <?php endif; ?>
+</div>
+
+<?php if ($this->sub_level_pages): ?>
+       <div id="sub-navigation">
+               <?php if (isset($this->back_to_page)): ?>
+                       <a href="<?php echo $this->back_to_page['url']; ?>" id="back-to"><?php echo _AT('back_to').' '.$this->back_to_page['title']; ?></a> | 
+               <?php endif; ?>
+
+               <?php $num_pages = count($this->sub_level_pages); ?>
+               <?php for ($i=0; $i<$num_pages; $i++): ?>
+                       <?php if ($this->sub_level_pages[$i]['url'] == $this->current_sub_level_page): ?>
+                               <strong><?php echo $this->sub_level_pages[$i]['title']; ?></strong>
+                       <?php else: ?>
+                               <a href="<?php echo $this->sub_level_pages[$i]['url']; ?>"><?php echo $this->sub_level_pages[$i]['title']; ?></a>
+                       <?php endif; ?>
+                       <?php if ($i < $num_pages-1): ?>
+                               |
+                       <?php endif; ?>
+               <?php endfor; ?>
+       </div>
+<?php else: ?>
+       <div id="sub-navigation">
+               &nbsp;
+       </div>
+<?php endif; ?>
+<!-- the bread crumbs -->
+<div id="breadcrumbs">
+       <?php foreach ($this->path as $page): ?>
+               <a href="<?php echo $page['url']; ?>"><?php echo $page['title']; ?></a> » 
+       <?php endforeach; ?> <?php echo $this->page_title; ?>
+</div>
+
+<!-- Extra div tag for IE fix in dealing with position:absolute (used by side menu)-->
+<div>
+
+<div id="contentwrapper">
+<div id="contentcolumn"
+       <?php if (($_SESSION['course_id'] <= 0) && !$this->side_menu): ?>
+               style="margin-right:0px;width:99%;"
+       <?php endif; ?>
+       >
+
+<!-- the page title -->
+
+               <?php if ($this->guide): ?>
+       <div style="text-align: right; padding-bottom: 10px; padding-right: 10px; float:right ; margin-top: 10px; padding-right: 5px; font-size:0.95em;">
+                       <a href="<?php echo $this->guide; ?>" id="guide" onclick="poptastic('<?php echo $this->guide; ?>'); return false;" target="_new"><em><?php echo $this->page_title; ?></em></a>
+       </div>
+               <?php endif; ?>
+       <div style="text-align: right; padding-bottom: 10px; padding-right: 10px; float:left ; margin-top: 10px; padding-right: 5px; font-size:0.95em;">
+
+               <?php if ($_SESSION['course_id'] > 0 && $system_courses[$_SESSION['course_id']]['side_menu']): ?>
+                       <script type="text/javascript" language="javascript">
+                       //<![CDATA[
+                       var state = getcookie("side-menu");
+                       if (state && (state == 'none')) {
+                               showTocToggle("side-menu", "<?php echo _AT('show'); ?>","<?php echo _AT('hide'); ?>", "", "show");
+                       } else {
+                               document.getElementById('contentcolumn').id="contentcolumn_shiftright";
+                               showTocToggle("side-menu", "<?php echo _AT('show'); ?>","<?php echo _AT('hide'); ?>", "", "hide");
+                       }
+                       //]]>
+                       </script>
+               <?php endif; ?>
+       </div>
+
+       <div  id="sequence-links">
+               <?php if ($this->sequence_links['resume']): ?>
+                               <a style="color:white;" href="<?php echo $this->sequence_links['resume']['url']; ?>" accesskey="."><img src="<?php echo $this->img; ?>resume.gif" border="0" title="<?php echo _AT('resume').': '.$this->sequence_links['resume']['title']; ?> Alt+." alt="<?php echo $this->sequence_links['resume']['title']; ?> Alt+." class="img-size-ascdesc" /></a>
+               <?php else:
+                       if ($this->sequence_links['previous']): ?>
+                               <a href="<?php echo $this->sequence_links['previous']['url']; ?>" title="<?php echo _AT('previous_topic').': '. $this->sequence_links['previous']['title']; ?> Alt+," accesskey=","><img src="<?php echo $this->img; ?>previous.gif" border="0" alt="<?php echo _AT('previous_topic').': '. $this->sequence_links['previous']['title']; ?> Alt+," class="img-size-ascdesc" /></a>
+                       <?php endif;
+                       if ($this->sequence_links['next']): ?>
+                               <a href="<?php echo $this->sequence_links['next']['url']; ?>" title="<?php echo _AT('next_topic').': '.$this->sequence_links['next']['title']; ?> Alt+." accesskey="."><img src="<?php echo $this->img; ?>next.gif" border="0" alt="<?php echo _AT('next_topic').': '.$this->sequence_links['next']['title']; ?> Alt+." class="img-size-ascdesc" /></a>
+                       <?php endif; ?>
+               <?php endif; ?>
+               &nbsp;
+       </div>
+
+       <!-- the page title -->
+       <h2 class="page-title"><?php echo $this->page_title; ?></h2>
+
+<a name="content"></a>
+<?php global $msg; $msg->printAll(); ?>
\ No newline at end of file
diff --git a/themes/greenmin/include/side_menu.tmpl.php b/themes/greenmin/include/side_menu.tmpl.php
new file mode 100644 (file)
index 0000000..48f1cf9
--- /dev/null
@@ -0,0 +1,8 @@
+<?php if (!defined('AT_INCLUDE_PATH')) { exit; } ?>
+
+<?php if (($_SESSION['course_id'] > 0) && $this->side_menu): ?>
+       <?php foreach ($this->side_menu as $dropdown_file): ?>
+               <?php if (file_exists($dropdown_file)) { require($dropdown_file); } ?>
+       <?php endforeach; ?>
+<div style="position:absolute; bottom:0px;">&nbsp;</div>
+<?php endif; ?>
diff --git a/themes/greenmin/print.css b/themes/greenmin/print.css
new file mode 100644 (file)
index 0000000..48b2bc1
--- /dev/null
@@ -0,0 +1,13 @@
+body {
+       background-color: White;
+       font-family: Helvetica, arial, sans serif;
+       margin: 0px;
+       margin-top: 0px;
+       color: black;
+       border: 0px;
+}
+
+div#side-menu, div#member-links, span#side-menushowlink, div#rightcolumn, div#suv-nav-logout, div#top-links, span#side-menuhidelink, div#sequence-links, select#jumpmenu, a#guide, div#gototop, input#jump-button, div#topnavlistcontainer, a#guide, div#breadcrumbs, div#jump-area, table.tabbed-table, div#sub-navigation, div#sequence-links, div#language, div#toc, fieldset#shortcuts {
+       display: none;
+}
+
diff --git a/themes/greenmin/readme.txt b/themes/greenmin/readme.txt
new file mode 100644 (file)
index 0000000..71cb1e0
--- /dev/null
@@ -0,0 +1,9 @@
+\r
+Theme:         Plone-like\r
+Date:          March 2005\r
+\r
+\r
+Installing:    See section "Installing a New Theme" in the themes_readme.txt file located in docs/themes/.\r
+\r
+Licence:       Falls under the GPL agreement.  See http://www.gnu.org/copyleft/gpl.html.\r
+       
\ No newline at end of file
diff --git a/themes/greenmin/screenshot.gif b/themes/greenmin/screenshot.gif
new file mode 100644 (file)
index 0000000..3a0f788
Binary files /dev/null and b/themes/greenmin/screenshot.gif differ
diff --git a/themes/greenmin/styles.css b/themes/greenmin/styles.css
new file mode 100644 (file)
index 0000000..a4a6369
--- /dev/null
@@ -0,0 +1,1366 @@
+/* main body attributes */
+body {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       margin-top: 0px;
+       margin-left: auto;
+       margin-right: auto;
+       font-size: small;
+       background-color: white;
+}
+
+p {
+    margin: 0.5em 0em 1em 0em;
+    text-align: justify;
+    line-height: 150%;
+       font-size: 0.9em;
+}
+
+p a {
+    text-decoration: underline;
+}
+
+p a:visited {
+       color: Purple;
+    background-color: transparent;
+}
+
+p a:active {
+       color: Red;
+    background-color: transparent;
+}
+
+h1, h2, h3, h4, h5, h6 {
+    color: Black;
+    clear: left;
+    font: 100% Verdana, Helvetica, Arial, sans-serif;
+    margin: 0;
+    padding-top: 0.5em;
+    /*border-bottom: 1px solid #57945A;*/
+}
+
+h1 {
+    font-size: 160%;
+}
+
+h2 {
+    font-size: 150%;
+}
+
+h3 {
+    font-size: 130%;
+}
+
+h4 {
+    font-size: 120%;
+}
+
+h5 {
+    font-size: 100%;
+}
+
+textarea {
+    border: 1px solid #57945A;  
+    color: Black;
+    background-color: white;
+    width: 88%;
+    padding: 0.1em;
+}
+
+/*  Table of content attributes*/
+p.toc{
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #eeeeee;
+       padding: .6em;
+       margin-bottom: .6em;
+       margin-top: 0em;
+       margin-left: 1em;
+       margin-right: 3em;
+       border: 1px #88A283 solid;
+} 
+
+/* list attributes */
+ul {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+
+li {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+
+li.folders {
+       list-style: disc url(../../images/folder.gif) outside;
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       margin-bottom: 0px;
+       margin-top: 0px;
+       margin-right: 0px;
+}
+
+li.folders .disabled {
+       color: #AAAAAA;
+}
+
+/* link attributes */
+a:link {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: #296542;
+       text-decoration: none;
+}
+a:visited {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: #296542;
+       text-decoration: none;
+}
+a:hover {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: black;
+       text-decoration: none;
+}
+
+.formfieldR {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: black;
+       border-top:  #003399  solid 1px;
+       border-bottom: #003399 solid 1px;
+       border-right: #003399 solid 1px;
+       border-left: #003399 solid 1px;
+       text-align: right;
+       padding: 2px;
+}
+
+/* align text to the left */
+.left {
+       text-align: left;
+}
+
+a.dropdown-title {
+       color: white;
+       font-weight: normal;
+       text-decoration: none;
+}
+
+
+/* table border */
+.tableborder {
+       border: 1px #606060 solid;
+}
+
+/* main submit button */
+.button {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #EBF6F3;
+       font-weight: normal;
+       border-top:  #348265  solid 1px;
+       border-bottom: #348265 solid 1px;
+       border-right: #348265 solid 1px;
+       border-left: #348265 solid 1px; 
+}
+
+/* small submit button at top */
+.button2 {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #F8F8F8;
+       border-top:  #348265  solid 1px;
+       border-bottom: #348265  solid 1px;
+       border-right: #348265  solid 1px;
+       border-left: #348265  solid 1px;
+}
+
+/* date attributes */
+small.date {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: #57945A; 
+       margin-bottom: 0px; 
+       margin-top: 0px;
+       margin-left: 5px;
+       margin-right: 0px;
+       font-size:small;
+}
+
+/* page breakline */
+hr {
+       color: #88A283;
+       background-color: white;
+       height: 1px;
+}
+
+/* message box styles */
+
+/* Editor box small */
+.editorsmallbox {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #EEEEEE;
+       padding: 2px;
+       padding-right: 3px;
+       border: 1px #ABC180 solid;
+}
+
+/* Editor box large */
+.editorlargebox {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       background-color: #EEEEEE;
+       margin-left:1em;
+       padding-left: .2em;
+       padding-right: .5em;
+       padding-top: .5em;
+       padding-bottom: .4em;
+       border: 1px #ABC180 solid;
+}
+
+
+select.dropdown {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+    background-color: #F1F3F1;
+}                                                               
+
+.highlight, a.highlight {
+       background-color: yellow;
+}
+
+a .highlight{
+       background-color: yellow;
+       text-decoration: underline;
+}
+
+.center {
+       text-align: center;
+}
+
+
+/* edit content tabs */
+.buttontab {
+       font-family: Helvetica, Arial, Helvetica, sans-serif;
+       background-color: #ffffff;
+       font-weight: bold;
+       border: 0px;
+       padding-left: 0px;
+       color: #779172;
+}
+
+.etab {
+       color: black;
+       background-color: #ffffff;
+       border-top: 1px #88A283 solid;
+       border-left: 1px #88A283 solid;
+       border-right: 1px #88A283 solid;
+       text-decoration: none;
+       text-align: center;
+       font-weight: bold;
+}
+
+.etab a:link, .etab a:visited {
+       color: black;
+       text-decoration: none;
+}
+.etab a:hover {
+       color: black;
+       text-decoration: underline;
+}
+.etabself {
+       background-color: #EFEFEF;
+       border-top: 1px #88A283 solid;
+       border-left: 1px  #88A283 solid;
+       border-right: 1px #88A283 solid;
+       text-align: center;
+       font-weight: bold;
+       padding: 2px;
+}
+.unsaved {
+       color: red;
+       background-color: #FFFDE0;
+       margin: 10px;
+       font-weight: bold;
+}
+.saved {
+       background-color: #FFFDE0;
+       margin: 10px;
+}
+
+
+
+/* the side menu */
+/* the side menu heading */
+td.dropdown-heading {
+       background-color: #DBFDD4;
+       color: #099015;
+       border-left: 1px solid #ECFEEA;
+       border-right: 1px solid #ECFEEA;
+       border-top: 1px solid #ECFEEA;
+       font-weight: bold;
+       padding: 2px;
+}
+
+td.dropdown-heading a, td.dropdown-heading a:hover, td.dropdown-heading a:visited {
+       text-decoration: none;
+}
+
+td.dropdown-heading.closed {
+       border-bottom: 1px solid #ECFEEA;
+}
+
+/* the side menu content */
+td.dropdown {
+       padding: 2px;
+       background-color: white;
+       color: black;
+       border-left: 1px solid #ECFEEA;
+       border-right: 1px solid #ECFEEA;
+       border-bottom: 1px solid #ECFEEA;
+       font-weight: normal;
+}
+td.dropdown a, td.dropdown a:visited  {
+       color: #099015;
+       text-decoration: none;
+}
+td.dropdown a:hover {
+       color: #099015;
+       text-decoration: underline;
+}
+td.dropdown.cell {
+       border-bottom: 0px;
+}
+td.dropdown strong {
+       color: #2A6C28;
+}
+
+/* added for 1.4.2: */
+.results {
+       padding-left: 20px;
+}
+
+h5.search-results {
+       background-color: #FFF5A4;
+       color: #099015;
+       padding: 1px;
+       margin-bottom: 5px;
+       margin-top: 10px;
+       margin-left: 5px;
+}
+
+small.search-info {
+       color: #099015;
+}
+
+p.search-description {
+       background-color: #FFFCE5;
+       color: #099015;
+}
+
+.test-box {
+       background-color: #FFF5A4;
+       color: #099015;
+       border-left: 1px solid #099015;
+       border-right: 1px solid #099015;
+       border-top: 1px solid #099015;
+       font-weight: bold;
+       padding: 2px;
+}
+
+/***************************************************************/
+/* NEW STUFF */
+
+table.tabbed-table {
+       width: 100%;
+}
+table.tabbed-table th#left-empty-tab {
+       background-color: transparent;
+       width: 15px;
+       border-bottom: 1px solid #9DAB9A;
+}
+table.tabbed-table th#right-empty-tab {
+       text-align: right;
+       background-color: transparent;
+       border-bottom: 1px solid #9DAB9A;
+       width: 400px;
+       padding-right: 5px;
+}
+table.tabbed-table th#right-empty-tab a {
+       text-decoration: underline;
+}
+table.tabbed-table th.tab-spacer {
+       background-color: transparent;
+       width: 5px;
+       border-bottom: 1px solid #9DAB9A;
+}
+
+table.tabbed-table th.tab {
+       padding-top: 2px;
+       padding-bottom: 2px;
+       width: 110px;
+       background-color: #C9CEA4;
+       border-bottom: 1px solid #9DAB9A;
+       border-left: 1px solid #9DAB9A;
+       border-top: 1px solid #9DAB9A;
+       border-right: 1px solid #9DAB9A;
+}
+table.tabbed-table th.tab:hover {
+       background-color: #DFE1C7;
+}
+
+table.tabbed-table th.tab a:focus {
+       color: white;
+}
+table.tabbed-table th.selected {
+       padding-top: 2px;
+       padding-bottom: 2px;
+       width: 110px;
+       background-color: #DFE1C7;
+       border-left: 1px solid #9DAB9A;
+       border-top: 1px solid #9DAB9A;
+       border-right: 1px solid #9DAB9A;
+}
+
+table.tabbed-table a, table.tabbed-table a:visited, table.tabbed-table a:hover {
+       color: black;
+       text-decoration: none;
+}
+
+a#my-start-page {
+       padding: 2px;
+       padding-left: 15px;
+       background-image: url(http://www.gris.uni-tuebingen.de/images/start.gif);
+       background-repeat: no-repeat;
+       background-position: 2px 5px;
+}
+
+a#back-to {
+       padding-left: 20px;
+       background-image: url(images/back.gif);
+       background-repeat: no-repeat;
+       background-position: 0px 0px;
+}
+
+div#breadcrumbs {
+    /* The path bar, including breadcrumbs and add to favorites */
+    border-bottom-color: #57945A;
+    border-bottom-style: solid;
+    border-bottom-width: 1px;
+    padding-left: 3px;
+    text-transform: lowercase;
+       font-size:0.85em;
+       padding-bottom: 1px;
+       padding-top: 1px;
+}
+h2.page-title {
+       margin-bottom: 10px;
+       margin-top: 10px;
+       margin-left: 5px;
+       border-bottom: 1px solid #f0f0f0;
+       clear: left;
+}
+
+h1 {
+       margin-bottom: 5px;
+}
+
+div#sub-navigation {
+       padding: 3px;
+       background-color: #DEECE2;
+       border-bottom: 1px solid #9DAB9A;
+       color: #9DAB9A;
+    text-transform: lowercase;
+       font-size:0.85em;
+}
+
+div#sub-navigation strong {
+       color: black;
+}
+
+div#help {
+       border-left: 1px solid black;
+       border-right: 1px solid black;
+       border-bottom: 1px solid black;
+       padding-left: 5px;
+       padding-right: 5px;
+       padding-bottom: 5px;
+       background-color: #efefef;
+       margin-left: 5px;
+       margin-right: 5px;
+       font-size: small;
+}
+
+h3#help-title {
+       margin-left: 5px;
+       margin-right: 5px;
+       border-left: 1px solid black;
+       border-right: 1px solid black;
+       padding: 1px;
+       background-color: #efefef;
+}
+.line {
+       border-bottom: 1px solid black;
+}
+div#help p {
+       padding: 0px;
+       margin: 0px;
+}
+
+div#toctoggle {
+       float: left;
+       font-size: smaller;
+       padding-left: 10px;
+}
+
+h1#section-title {
+       float: left;
+       margin-left: 5px;
+}
+
+div#top-links {
+       position: relative;
+       padding-right: 5px;
+       line-height: 170%;
+       margin-top: 3px;
+       font-size:0.85em;;
+    text-transform: lowercase;
+}
+
+a#editor-link {
+       background-color: #EFEFEF;
+       padding-top: 1px;
+       padding-bottom: 1px;
+       padding-left: 15px;
+       padding-right: 8px;
+       border: 1px solid #cccccc;
+       font-weight: normal;
+       text-decoration: none;
+}
+
+a#editor-link:hover {
+       background-color: #fafafa;
+       border: 1px solid #aaaaaa;
+}
+
+a#editor-link.off {
+       background-image: url(images/pen.gif);
+       background-repeat: no-repeat;
+       background-position: 0px 2px;
+}
+a#editor-link.on {
+       background-image: url(images/pen2.gif);
+       background-repeat: no-repeat;
+       background-position: 0px 2px;
+}
+
+
+/* for data tables */
+table.data {
+       clear:right;
+       border: 1px solid #f0f0f0;
+       width: 80%; 
+       margin-left: auto; 
+       margin-right: auto;
+       border-spacing: 0px;
+       border-collapse: collapse;
+} 
+
+table.data th {
+       background-color: #f0f0f0;
+       padding: 3px;
+       white-space: nowrap;
+}
+
+table.data th a {
+       color: black;
+       padding-right: 15px;
+       margin-right: 15px;
+       background-image: url('../default/images/sort.gif');
+       background-repeat: no-repeat;
+       background-position: right;
+       text-decoration:none;
+}
+
+table.data tbody {
+       background-color: #fdfdfd;
+}
+
+table.data tbody th {
+       text-align: left;
+       background-color: #fdfdfd;
+       cursor: auto;
+}
+
+table.data td {
+       padding: 3px;
+}
+
+table.data tbody tr:hover {
+       background-color: #F5FDFF;
+       cursor: pointer;
+}
+
+table.data tbody tr.selected {
+       background-color: #F5FDFF;
+       cursor: auto;
+}
+
+table.data tfoot {
+       background-color: #fafafa;
+}
+
+table.data tfoot tr:first-child td {
+       padding: 5px;
+       background-image: url('images/arrow_ltr.gif');
+       background-repeat: no-repeat;
+       background-position: 4px 5px;
+       padding-left: 40px;
+}
+
+table.data.static tfoot td, table.data.static tfoot tr:first-child td {
+       padding: 5px;
+       background-image: none;
+       padding-left: 0px;
+}
+
+table.data tfoot input {
+       border: 1px solid #999;
+       background-color: white;
+       padding: 2px;
+       padding-left: 10px;
+       padding-right: 10px;
+       max-width: 60%;
+       min-width: 100px;
+       margin-left: 5px;
+}
+
+/* used for static tables with no form elements: */
+table.data.static tbody tr:hover {
+       background-color: transparent;
+       cursor: auto;
+}
+
+table.data tfoot input[type=submit]:hover {
+       background-color: #F5FDFF;
+}
+
+/* course browser: */
+
+div#browse {
+       margin-left: auto; 
+       margin-right: auto; 
+       width: 80%;
+}
+
+div.browse-selected {
+       background-image: url('images/side_arrow.gif'); 
+       background-repeat: no-repeat; 
+       padding-left: 9px; 
+       background-position: center left;
+}
+
+div.browse-unselected {
+       padding-left: 9px; 
+}
+
+ul.browse-list {
+       list-style: none;
+       padding:0px;
+}
+
+/* feedback /errors */
+div#error {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid red;
+       padding: 5px;
+       background-color: #fffcf3;
+       color: red;
+       background: #FBF4ED url(images/error-large.gif) no-repeat scroll 5px 5px;
+       padding-left: 25px;
+       font-weight: bold;
+}
+div#error h4 {
+       color: black;
+       margin-left: 0px;
+}
+
+div#error ul, div#feedback ul, div#help ul {
+       position: relative;
+       list-style: none;
+       margin-left: 0px;
+       padding-left: 0px;
+}
+
+div#feedback {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid green;
+       padding: 5px;
+       background-color: #EAFFC3;
+       color: green;
+       font-weight: bold;
+}
+
+div#help {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid blue;
+       padding: 5px;
+       background-color: #EBFFC3;
+       color: blue;
+}
+
+div#info {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #099D3F;
+       padding: 5px;
+       background-color: #DAE8D7;
+       color: #099D3F;
+       font-weight: bold;
+}
+
+div#warning {
+       width: 50%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 15px;
+       margin-bottom: 15px;
+       border: 1px solid #FF8400;
+       padding: 5px;
+       background-color: #FFF6ED;
+       color: #D95900;
+       font-weight: bold;
+}
+acronym {
+       cursor: help;
+}
+
+div.news p {
+       margin-left: 10px;
+}
+div.news span.date {
+       font-family: Verdana, Helevetica, Arial, sans-serif;
+       color: #57945A; 
+       font-size:smaller;
+}
+
+/* home page links */
+div.home-link {
+       padding: 2px;
+       float: left;
+       text-align: center;
+       margin: 2px;
+       width: 120px;
+       height: 90px;
+}
+div.home-link:hover {
+       padding: 1px;
+       background-color: #efefef;
+       border: 1px solid #afafaf;
+       float: left;
+       text-align: center;
+       margin: 2px;
+}
+div.home-link a {
+       text-decoration: none;
+       font-weight: bold;
+}
+
+div.home-link img {
+       border: 0px;
+}
+
+/* sequence links */
+div#sequence-links {
+       float: right;
+       margin-top: 10px;
+       padding-right: 5px;
+       font-size: smaller;
+}
+div#sequence-links a {
+       text-decoration: none;
+}
+
+div.dropdown {
+       width: 200px;
+       padding: 2px;
+       background-color: white;
+       color: black;
+       border-left: 1px solid #ECFEEA;
+       border-right: 1px solid #ECFEEA;
+       border-bottom: 1px solid #ECFEEA;
+       font-weight: normal;
+}
+
+div.dropdown-heading {
+       background-color: #DFE1C7;
+       color: #099015;
+       border-left: 1px solid #ECFEEA;
+       border-right: 1px solid #ECFEEA;
+       border-top: 1px solid #ECFEEA;
+       font-weight: bold;
+       padding: 2px;
+}
+
+div.required {
+       font-weight: bold;
+       color: red;
+       font-size: large;
+       float: left;
+       position: relative;
+       margin-top: -5px;
+       height: 15px;
+       padding-right: 2px;
+}
+
+div#content_text {
+       margin-left: 5px;
+}
+
+form {
+       clear: none;
+       display:inline;
+}
+#jump-button {
+    padding-left: 9px;
+       padding-right: 2px;
+       background: White url('images/linkTransparent.gif') 3px 2px no-repeat;
+       border: 1px solid #57945A;
+       cursor: pointer;
+    text-transform: lowercase;
+       font-size:0.85em;
+}
+#jumpmenu {
+       font-size: smaller;
+}
+
+optgroup {
+       font-size: small;
+}
+
+/* packing */
+div.paging {
+   width: 100%;
+   text-align: center;
+   margin: 0.5em auto;
+}
+div.paging ul {
+   list-style: none;
+   display: inline;
+   padding: 0px;
+   border: 1px solid #000;
+}
+div.paging li { 
+       display: inline; 
+       padding-left: 2px; 
+       padding-right: 2px;
+       padding-top: 0px;
+       padding-bottom: 0px;
+}
+
+div.paging li a {
+       text-decoration: none;
+       padding-left: 4px;
+       padding-right: 4px;
+       border-left: 1px solid white;
+       border-right: 1px solid white;
+}
+
+div.paging li a:hover, div.paging li a.current {
+   background-color: #efefef;
+   border-left: 1px solid #000;
+   border-right: 1px solid #000;
+}
+
+/*plone*/
+
+div.top {
+    /* Top space */
+    background: transparent;
+    margin: 0;
+    padding: 0;
+       padding-top:9px;
+}
+div.tabs {
+    /* Navigational Plone Tabs(tm), implemented by customizing the a tag - they are surprisingly elegant. The power of CSS runs strong in these :) */
+    background: transparent;
+    border-collapse: collapse;
+    border-bottom: 1px solid #57945A;
+    padding: 0.5em 0em 0em 2em;
+    white-space: nowrap;
+       font-size:0.85em;
+}
+
+div.tabs a {
+    /* The normal, unselected tabs. They are all links */
+    background: transparent;
+    border-color: #57945A;
+    border-width: 1px; 
+    border-style: solid solid none solid;
+    color: #4F7643;
+    height: 1.2em;
+    margin-right: 0.5em;
+    padding: 0em 2em 0em;
+    text-transform: lowercase;
+}
+
+div.tabs a.selected {
+    /* The selected tab. There's only one of this */
+    background: #DEECE2;
+    border-bottom: #DEECE2 1px solid;
+    color: #4F7643;
+    font-weight: normal;
+}
+
+div.tabs a:hover, div.tabs a.active {
+    background: #DEECE2;
+    border-bottom: 1px solid #DEECE2;
+    color: #4F7643;
+}
+
+
+h4.box {
+       font-size: x-small;
+       background-color: #DEECE2;
+       color: black;
+       border: 1px solid #57945A;
+       padding: 2px;
+    text-transform: lowercase;
+       font-size: 0.85em;
+}
+
+div.box {
+       padding: 2px;
+       background-color: white;
+       color: black;
+       border-left: 1px solid #57945A;
+       border-right: 1px solid #57945A;
+       border-bottom: 1px solid #57945A;
+       font-weight: normal;
+       font-size: 0.85em;
+}
+
+h5.box { 
+    background: #DEECE2;
+    border: 1px solid #57945A;
+    border-style: solid solid none solid;
+    color: Black;
+    padding: 0em 1em 0em 1em;
+    text-transform: lowercase;
+    display: inline;
+       font-size: 0.85em;
+    height: 1em;
+}
+
+div.box a:link {
+       text-decoration: none;
+}
+
+div.box a:visited {
+       color: #2A6C28;
+       text-decoration: none;
+}
+
+div.box a:hover {
+       text-decoration: underline;
+}
+
+.boxDetails {
+    text-align: right;
+}
+
+div.box .content {
+    padding: 1em;
+       font-size: 0.85em;
+}
+
+div.box a.close {
+    float: right;
+    text-transform: none;
+    border-left: 1pt solid #57945A;
+    padding: 0em 0.2em;
+}
+
+div.box h1, 
+div.box h2, 
+div.box h3, 
+div.box h4 {
+    margin: 0;
+    padding: 0;
+}
+
+div.box .even {
+    background-color: #F7FAF7;
+}
+
+div.box .odd {
+    background-color: transparent;
+}
+
+div.box input {
+    font-size: 100%;
+}
+
+/* users/index.php */
+
+div.course {
+       position: relative;
+       width: 30em;
+       height: 10.5em;
+       border: rgb(204, 204, 204) 1px solid;
+       background-color: white;
+       float: left;
+       margin: 3px;
+       padding: 3px;
+       font-size:0.85em;
+}
+
+div.course.break {
+       clear: left;
+}
+
+div.course h2 {
+       border: 0px;
+       font-weight: normal;
+       font-size: large;
+
+}
+
+div.course:hover {
+       background-color:#D1EDD9;
+       border: #AAAAAA 1px solid;
+}
+
+div.course a {
+       text-decoration: none;
+}
+
+div.course:hover a {
+       color: #099015;
+}
+
+div.course a:hover {
+       color: #000000;
+}
+
+div.course p {
+       font-size: 0.95em;
+}
+
+div.course p a {
+       font-weight: bold;
+}
+
+div.course img.icon    {
+       float: left;
+       margin: 2px;
+       height:6.8em;
+       width:6.8em;
+}
+
+div.course div.shortcuts {
+       text-align: right;
+       clear: left;
+       vertical-align: middle;
+}
+
+fieldset#shortcuts {
+       float: right;
+       background-color: #FAFAFA;
+       border: 1pt solid #AAAAAA;
+       margin: -5pt 5pt 5pt 5pt;
+       padding-right: 10pt;
+       padding-bottom: 5pt;
+       padding-left: 10pt;
+}
+
+legend {
+       padding-right: 10pt;
+       padding-left: 10pt;
+}
+
+fieldset {
+       margin-bottom: 10pt;
+}
+#shortcuts legend {
+       color: orange;
+       background-color: white;
+}
+#shortcuts ul {
+       position: relative;
+       margin-top: 0pt;
+       margin-bottom: 0pt;
+       margin-left: 0pt;
+       list-style-type:  none;
+       padding-left: 0pt; 
+}
+
+a#guide {
+       background-image: url('../default/images/guide.gif'); background-repeat: no-repeat; background-position: 7pt 2pt;
+       background-color: #eee;
+       padding: 1pt 10pt 1pt 23pt;
+       border: 1pt solid #ccc;
+       font-size:0.85em;
+}
+
+div#content-text {
+       padding-right: 5pt;
+       line-height:150%;
+}
+
+div#content-text li {
+       margin-left: 15pt;
+}
+
+div#content-info {
+       margin: 5pt;
+       font-size: smaller;
+       color: #cacaca;
+       clear: both;
+}
+
+div#container {
+       text-align: left;
+       margin: 0px auto;
+       padding: 0px;
+       border:0;
+       width: 90%;
+}
+
+div.column {
+       border: 1px solid #e0e0e0;
+       float: left;
+       width: 30%;
+       margin: 5px;
+       padding: 0px;
+       min-width: 170px;
+}
+
+div.column h3 {
+       margin-left: 0px;
+}
+
+div.insidecol {
+   min-height: 170px;
+   height: 170px;
+   padding:5px;
+}
+div[class] .insidecol {
+   height: auto;
+}
+
+/* index page */
+ul#home-links {
+       list-style: none;
+}
+ul#home-links li {
+       font-size:0.95em;
+
+       display: inline;
+       float: left;
+       padding: 0.8em;
+       text-align: center;
+       margin: 0.1em;
+       width: 8.5em;
+       height: 7.0em;
+       padding-left:0px;
+
+}
+ul#home-links li a {
+       text-decoration: none;
+       border: 1px transparent;
+       font-weight: bold;
+}
+ul#home-links li a img {
+       border: 0px;
+       display: block;
+       padding-left:25px;
+}
+
+/* enrollment tabs */
+#navlist {
+       padding: 0px;
+       margin-left: 0;
+       margin-right: auto;
+       margin-left: auto;
+       margin-bottom: 4px;
+       margin-top:15px;
+       white-space: nowrap;
+}
+
+#navlist li {
+       list-style: none;
+       display: inline;
+       margin: 0px;
+}
+
+#navlist li a {
+       padding: 3px 9px;
+       border: 1px solid #e0e0e0;
+       border-bottom: none;
+       background: #fafafa;
+       text-decoration: none;
+       margin-left: 4px;
+       -moz-border-radius-topright: 4px;
+       -moz-border-radius-topleft: 4px;
+       white-space: nowrap;
+}
+
+#navlist li a:hover, #navlist li a.active {
+       color: #000;
+       background: #fff;
+}
+
+/* tree */
+.img-size-tree {
+       vertical-align: middle;
+       margin-top: 0px;
+       height:1.45em;
+       width:1.45em;
+}
+/* profile page */
+dl#public-profile {
+       width: 100%;
+}
+dl#public-profile dt {
+       float: left;
+       font-weight: bold;
+       width: 30%;
+       text-align: right;
+       clear: left;
+       border-right: 1px solid #f0f0f0;
+       padding: 5px 5px 5px 0px;
+       vertical-align: middle;
+       margin-right: 5px;
+}
+dl#public-profile dd {
+       margin-bottom: 5px;
+       clear: right;
+       padding: 5px 0px 5px 5px;
+}
+
+/* floating layout */
+#contentwrapper{
+       float: left;
+       width: 99%;
+}
+#contentcolumn {
+       margin-left: 5px;
+       padding-right: 5px;
+}
+#contentcolumn_shiftright {
+       margin-left: 210px;
+       padding-right: 5px;
+}
+#rightcolumn{
+       float: left;
+       width: 17em;
+       margin-left: -200px;
+       overflow: hidden;
+}
+#leftcolumn{
+       position: absolute;
+       left: 0;
+       float: left;
+       width: 200px;
+       margin-left: 5px;
+       overflow: hidden;
+}
+#footer{
+       clear: left;
+       width: 100%;
+       text-align: center;
+       padding: 4px 0px;
+}
+
+/** forum stuff **/
+#forum-thread li { clear:left; border:1px solid #eee; border-bottom: 1px solid #f0f0f0; float:left; width: 98%; list-style: none; }
+#forum-thread li.even { background: #fdfdfd; border-top: none; }
+#forum-thread li.odd { background: #fff; }
+div.forum-post-author { float:left; width:150px; padding:8px 10px; }
+div.forum-post-author a.title {        font-size: 1.1em; line-height: 1.2em; font-weight: bold; text-decoration:none; }        
+div.forum-post-author img.profile-picture { border: 2px solid #f0f0f0; }
+div.forum-post-content { margin-left: 150px; padding: 5px 0px 18px 18px; }
+div.forum-post-content h3 { font-weight: 500; }
+div.forum-post-ctrl { float: right; padding-right: 5px; color: #a1a1a1; }
+div.forum-post-ctrl a { text-decoration: none; }
+div.forum-post-ctrl span { color: black; background-color: #fefdc2; padding: 3px; }
+div.forum-post-content p.date { color: #a1a1a1; border-bottom: 1px solid #f0f0f0; }
+div.forum-post-content div.body p { margin-bottom:20px; }
+
+/** inbox stuff - reuses some of the forum layout **/
+#inbox-msg li { clear:left; border:1px solid #eee; border-bottom: 1px solid #f0f0f0; width: 98%; list-style: none; }
+
+
+div#topnavlistcontainer {
+    /* Navigational Plone Tabs(tm), implemented by customizing the a tag - they are surprisingly elegant. The power of CSS runs strong in these :) */
+    background: transparent;
+    border-collapse: collapse;
+    border-bottom: 1px solid #57945A;
+    padding: 0.5em 0em 0em 2em;
+    white-space: nowrap;
+       font-size:0.85em;
+}
+ul#topnavlist {
+       padding: 0px;
+       margin-right: auto;
+       margin-left: auto;
+       margin-bottom: 3px;
+       white-space: nowrap;
+       margin-top: 0px;
+       margin-bottom:0px;
+}
+
+ul#topnavlist li {
+       list-style: none;
+       display: inline;
+       margin: 0px;
+}
+
+ul#topnavlist li:first-child a {
+       margin-left: 8px;
+}
+
+ul#topnavlist li a:hover, ul#topnavlist li a.active, ul#topnavlist li a:focus {
+    background: #DEECE2;
+    border-bottom: 1px solid #DEECE2;
+    color: #4F7643;
+}
+
+ul#topnavlist li a {
+    /* The normal, unselected tabs. They are all links */
+    background: transparent;
+    border-color: #57945A;
+    border-width: 1px; 
+    border-style: solid solid none solid;
+    color: #4F7643;
+    height: 1.2em;
+    margin-right: 0.5em;
+    padding: 0em 2em 0em;
+    text-transform: lowercase;
+}
+
+ul#topnavlist li a.selected {    /* The selected tab. There's only one of this */
+    background: #DEECE2;
+    border-bottom: #DEECE2 1px solid;
+    color: #4F7643;
+    font-weight: normal;
+}
+
+
+#fsfloat1{
+       float:left;
+}
+#fsfloat2{
+       float:right;
+       width:48%;
+}
+
diff --git a/themes/greenmin/theme.cfg.php b/themes/greenmin/theme.cfg.php
new file mode 100644 (file)
index 0000000..de0ad82
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+
+// $Id: theme.cfg.php 2813 2004-12-12 15:37:46Z greg $
+
+/* This is the default configuration file for the default theme. */
+
+/* The theme's name. */
+       $_theme['name'] = 'Blumin';
+
+/* The theme's version number. */
+       $_theme['version'] = '0.2';
+
+/* Which version of ATutor is this theme intended for. */
+       $_theme['atutor-version'] = '1.5.3';
+
+/* author information */
+       $_theme['author_name']  = 'ATutor';
+       $_theme['author_url']   = 'http://atutor.ca';
+       $_theme['author_email'] = '';
+
+/* theme default course banner styles: */
+       $_theme['banner']['font-family'] = 'Verdana, Arial, sans-serif';
+       $_theme['banner']['font-weight'] = 'bold';
+       $_theme['banner']['color']       = 'black';
+       $_theme['banner']['font-size']   = 'xx-large';
+       $_theme['banner']['text-align']  = 'center';
+
+       $_theme['banner']['background-color'] = 'white';
+       $_theme['banner']['background-image'] = '';
+       $_theme['banner']['vertical-align']   = 'middle';
+       $_theme['banner']['padding']          = '3px';
+
+?>
diff --git a/themes/greenmin/theme_info.xml b/themes/greenmin/theme_info.xml
new file mode 100644 (file)
index 0000000..4838f13
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="EN"?>\r
+<!--This is an ATutor Theme Generator document-->\r
+<!--Created from the ATutor Themes Export Generator-->\r
+\r
+<theme>\r
+       <title>Greenmin</title>\r
+       <version>1.0</version>\r
+       <last_updated>2007-08-31</last_updated>\r
+       <extra_info>plone-like.</extra_info>\r
+</theme>\r
+\r
diff --git a/themes/themes_readme.txt b/themes/themes_readme.txt
new file mode 100644 (file)
index 0000000..b50c959
--- /dev/null
@@ -0,0 +1,87 @@
+===========================================\r
+      ATutor Themes Documentation\r
+===========================================\r
+\r
+In this file:\r
+       - Introduction\r
+       - Installing a New Theme\r
+       - File & Directory Structure\r
+       - Theme Configuration File\r
+       - Creating a Theme\r
+\r
+                  **************\r
+\r
+Introduction\r
+------------\r
+An ATutor theme is a set of template files with images and a stylesheet that \r
+change the overall look and feel of an ATutor installation. An installation \r
+may have one or more themes installed at one time; a user is given the ability \r
+of selecting a single theme to be used while they are logged-in.\r
+\r
+This document briefly explains the structure of an individual theme directory.\r
+\r
+                  **************\r
+\r
+Installing a New Theme\r
+----------------------\r
+\r
+Access the Themes area of the Administration section.\r
+\r
+                  **************\r
+\r
+File & Directory Sturcture\r
+--------------------------\r
+\r
+All themes go in /themes/.\r
+\r
+All theme specific files are in /themes/[theme_name]/, where \r
+`[theme_name]` is the directory name of the theme. The `theme_name` need not be\r
+the exact name of the theme (ie. a theme named `Blueberry Cheesecake` may exist\r
+in a directory called `bb_cc`). The actual name of the theme is specified\r
+in that theme's configuration file.\r
+\r
+The theme may be renamed however, if another theme by the same name already exists.\r
+\r
+The files below are in the theme directory:\r
+\r
+  - theme_info.xml             - The configuration file (see "Theme Configuration File" below)\r
+  - screenshot.jpg             - 200x125 pixel screenshot of the theme\r
+\r
+Any additional files or images may be placed in sub-directories. \r
+Example: /[theme_name]/images/ may be used for theme specific images.\r
+\r
+                  **************\r
+\r
+Theme Configuration File - theme_info.xml\r
+----------------------------------------\r
+\r
+Each theme has a configuration file that must exist and must be named 'theme_info.xml' .\r
+If the theme_info.xml file cannot be found in the theme's directory then the theme will\r
+not be made available to use. The fields in the theme_info.xml file are documented in the \r
+file; they describe such things as the name of the theme, its author, and the default\r
+course banner style.\r
+\r
+                  **************\r
+\r
+Creating a Theme\r
+----------------\r
+\r
+The best way to start your own theme is by exporting one of the themes displayed on the Theme Manager.\r
+The theme is exported onto your desktop as a '.zip' file.\r
+You must extract the contents of this file in order to change them.\r
+You should then edit the theme_info.xml file to give it a name.\r
+Once those changes are made you should zip the files and import them using the import theme function.\r
+The name of the zip file should be the name you want to give your theme, sunstituting '_' for spaces.\r
+\r
+The theme files described above are basically PHP files. You do not need to know a lot \r
+about PHP to create a theme; most of the syntax if straight forward and uses mostly\r
+if-statements and foreach-loops. For additional information on PHP check out: php.net .\r
+\r
+The theme files contain variables which look like $this->[something]. Those variables get\r
+set by ATutor and may contain simple text or in some cases arrays (or vectors) of text.\r
+\r
+The first theme files that should be created are the header.tmpl.php, footer.tmpl.php and\r
+styles.css . Editing those three files alone will let you dramatically change the look\r
+and feel of an ATutor installation. Once those files are complete you can move on to the \r
+in-course files; those are files that only get used when viewing a course. The in-course\r
+files format the dropdowns and the overall look of the course.
\ No newline at end of file
diff --git a/tile.php b/tile.php
new file mode 100644 (file)
index 0000000..1bd5fdd
--- /dev/null
+++ b/tile.php
@@ -0,0 +1,158 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', 'include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+$path = array();
+
+/* called at the start of en element */
+/* builds the $path array which is the path from the root to the current element */
+function startElement($parser, $name, $attrs) {
+       global $path;
+       array_push($path, $name);
+}
+
+/* called when an element ends */
+/* removed the current element from the $path */
+function endElement($parser, $name) {
+       global $my_data, $path, $tile_title, $tile_description, $tile_identifier;
+
+       if ($path == array('lom', 'general', 'title', 'langstring')) {
+               $tile_title = $my_data;
+       } else if ($path == array('lom', 'general', 'description', 'langstring')) {
+               $tile_description = $my_data;
+       } else if ($path == array('lom', 'general', 'identifier')) {
+               $tile_identifier = $my_data;
+       }
+
+       $my_data = '';
+       array_pop($path);
+}
+
+/* called when there is character data within elements */
+/* constructs the $items array using the last entry in $path as the parent element */
+function characterData($parser, $data){
+       global $my_data;
+       $my_data .= $data;
+}
+
+require (AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>#search_results" method="get" name="form">
+
+<div class="input-form" style="width: 40%">
+       <div class="row">
+               <label for="words2"><?php echo _AT('search_words'); ?></label><br />
+               <input type="text" name="query" size="40" id="words2" value="<?php echo stripslashes(htmlspecialchars($_GET['query'])); ?>" />
+       </div>
+
+       <div class="row">
+               <?php echo _AT('search_in'); ?><br />
+
+               <input type="radio" name="field" value="anyField" id="taf" <?php if (!isset($_GET['field']) || ($_GET['field'] == 'anyField')) { echo 'checked="checked"'; } ?> /><label for="taf"><?php echo _AT('tile_any_field'); ?></label><br />
+               <input type="radio" name="field" value="title" id="tt" <?php if ($_GET['field'] == 'title') { echo 'checked="checked"'; } ?> /><label for="tt"><?php echo _AT('title'); ?></label><br />
+               <input type="radio" name="field" value="author" id="ta" <?php if ($_GET['field'] == 'author') { echo 'checked="checked"'; } ?> /><label for="ta"><?php echo _AT('tile_author'); ?></label><br />
+               <input type="radio" name="field" value="subject" id="tk" <?php if ($_GET['field'] == 'subject') { echo 'checked="checked"'; } ?> /><label for="tk"><?php echo _AT('tile_keyword'); ?></label><br />
+               <input type="radio" name="field" value="description" id="td" <?php if ($_GET['field'] == 'description') { echo 'checked="checked"'; } ?> /><label for="td"><?php echo _AT('description'); ?></label><br />
+               <input type="radio" name="field" value="technicalFormat" id="tf" <?php if ($_GET['field'] == 'technicalFormat') { echo 'checked="checked"'; } ?> /><label for="tf"><?php echo _AT('tile_technical_format'); ?></label>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('search'); ?>" />
+       </div>
+</div>
+</form>
+<br />
+<?php
+
+if (isset($_GET['query'])) {
+
+       if (!extension_loaded('soap')) {
+               require(AT_INCLUDE_PATH . 'classes/nusoap.php');
+               // Create the client instance
+               $client = new nusoapclient(AT_TILE_WSDL, true);
+
+               // Check for an error
+               $error = $client->getError();
+               if ($error) {
+                       // Display the error
+
+                       $msg->addError('TILE_UNAVAILABLE');
+                       $msg->printAll();
+
+                       require(AT_INCLUDE_PATH.'footer.inc.php');
+                       exit;
+               }
+
+               // Create the proxy
+               $proxy = $client->getProxy();
+       } else {
+               // Create the client instance
+               $proxy = new soapclient(AT_TILE_WSDL);
+       }
+
+       $search_input = array('query' => $_GET['query'], 'field' => $_GET['field'], 'content' => 'contentPackage');
+
+       $results = $proxy->doSearch($search_input);
+
+
+       if ($results) {
+               $num_results = count($results);
+       } else {
+               $num_results = 0;
+       }
+       echo '<h3>'. _AT('results_found', $num_results).'</h3>';
+       if ($num_results) {
+               echo '<ol>';
+               foreach ($results as $result) {
+
+                       $xml_parser = xml_parser_create();
+
+                       xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false); /* conform to W3C specs */
+                       xml_set_element_handler($xml_parser, 'startElement', 'endElement');
+                       xml_set_character_data_handler($xml_parser, 'characterData');
+
+                       if (!xml_parse($xml_parser, $result, true)) {
+                               die(sprintf("XML error: %s at line %d",
+                                                       xml_error_string(xml_get_error_code($xml_parser)),
+                                                       xml_get_current_line_number($xml_parser)));
+                       }
+
+                       xml_parser_free($xml_parser);
+
+                       $tile_title = str_replace('<', '&lt;', $tile_title);
+
+                       echo '<li><strong>' . $tile_title . '</strong> - ';
+                       echo '<a href="'.AT_TILE_PREVIEW .'cp='.$tile_identifier.'&item='.$tile_identifier.'" target="_new">'._AT('preview').'</a>';
+                       echo ' | <a href="'.AT_TILE_EXPORT.'?cp='.$tile_identifier.'">'._AT('download').'</a>';
+                       echo '<br />';
+                       if (strlen($tile_description) > 200) {
+                               echo '<small>' . $tile_description  . '</small>';
+                       } else {
+                               echo $tile_description;
+                       }
+
+                       echo '<br /></li>';
+
+                       unset($tile_title);
+                       unset($tile_description);
+                       unset($tile_identifier);
+               }
+               echo '</ol>';
+       }
+}
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/tools/access.php b/tools/access.php
new file mode 100644 (file)
index 0000000..045bf3b
--- /dev/null
@@ -0,0 +1,161 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_ADMIN);
+
+if (isset($_POST['regenerate'])) {
+       $password = strtoupper(substr(md5(rand()), 3, 8));
+
+       $sql = "UPDATE ".TABLE_PREFIX."course_access SET `password`='$password' WHERE course_id=".$_SESSION['course_id'];
+       $result = mysql_query($sql, $db);
+       if (!mysql_affected_rows($db)) {
+               // conflict. try again
+               $password = strtoupper(substr(md5(rand()), 2, 7));
+               $sql = "UPDATE ".TABLE_PREFIX."course_access SET `password`='$password' WHERE course_id=".$_SESSION['course_id'];
+               $result = mysql_query($sql, $db);
+       }
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: '.$_SERVER['PHP_SELF']);
+       exit;
+} else if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.$_SERVER['PHP_SELF']);
+       exit;
+} else if (isset($_POST['submit'])) {
+       $auth = intval($_POST['auth']);
+
+       //expiry date
+       if (intval($_POST['expiry_date'])) {
+               $day_expire             = intval($_POST['day_expire']);
+               $month_expire   = intval($_POST['month_expire']);
+               $year_expire    = intval($_POST['year_expire']);
+               $hour_expire    = intval($_POST['hour_expire']);
+               $min_expire             = intval($_POST['min_expire']);
+
+               if (strlen($month_expire) == 1){
+                       $month_expire = "0$month_expire";
+               }
+               if (strlen($day_expire) == 1){
+                       $day_expire = "0$day_expire";
+               }
+               if (strlen($hour_expire) == 1){
+                       $hour_expire = "0$hour_expire";
+               }
+               if (strlen($min_expire) == 1){
+                       $min_expire = "0$min_expire";
+               }
+               $expiry_date = "$year_expire-$month_expire-$day_expire $hour_expire:$min_expire:00";
+       } else {
+               $expiry_date = 0;
+       }
+
+       $sql = "UPDATE ".TABLE_PREFIX."course_access SET `expiry_date`='$expiry_date', enabled=$auth WHERE course_id=".$_SESSION['course_id'];
+       $result = mysql_query($sql, $db);
+       
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: '.$_SERVER['PHP_SELF']);
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+if ($system_courses[$_SESSION['course_id']]['access'] == 'public') { 
+       // if this course is public, then we can't use this feature
+       $msg->printInfos('ACCESS_PUBLIC');
+       require(AT_INCLUDE_PATH.'footer.inc.php'); 
+       exit;
+}
+
+$sql = "SELECT password, expiry_date+0 AS expiry_date, enabled FROM ".TABLE_PREFIX."course_access WHERE course_id=".$_SESSION['course_id'];
+$result = mysql_query($sql, $db);
+
+if ($row = mysql_fetch_assoc($result)) {               
+       $enabled = $row['enabled'];
+       $password = $row['password'];
+       $expiry = $row['expiry_date'];
+} else {
+       $enabled = 0;
+       $password = strtoupper(substr(md5(rand()), 3, 8));
+       $expiry = 0;
+       $sql = "INSERT INTO ".TABLE_PREFIX."course_access VALUES ('$password', {$_SESSION['course_id']},'0000-00-00 00:00:00', 0)";
+       $result = mysql_query($sql, $db);
+}
+$url = AT_BASE_HREF.'acl.php?'.$password;
+
+?>
+       <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+               <div class="input-form">
+               <fieldset class="group_form"><legend class="group_form"><?php echo _AT('regenerate'); ?></legend>
+                       <div class="row">                               
+                               <?php echo _AT('auth_access_text'); ?>
+                       </div>
+                       <div class="row">
+                               <?php echo _AT('url'); ?><br />
+                               <kbd><?php echo $url; ?></kbd>
+                       </div>
+                       <div class="row buttons">
+                               <input type="submit" name="regenerate" value="<?php echo _AT('regenerate'); ?>"  />
+                       </div>
+               </fieldset>
+               </div>
+
+               <div class="input-form">
+               <fieldset class="group_form"><legend class="group_form"><?php echo _AT('authenticated_access'); ?></legend>
+                       <div class="row">
+                               <?php echo _AT('authenticated_access'); ?><br />
+                               <input type="radio" name="auth" id="enable" value="1" <?php if($enabled) { echo 'checked="checked"'; } ?> /> <label for="enable"><?php echo _AT('enable'); ?></label> <input type="radio" name="auth" id="disable" value="0" <?php if(!$enabled) { echo 'checked="checked"'; } ?> /> <label for="disable"><?php echo _AT('disable'); ?></label> 
+                       </div>
+
+                       <div class="row">
+                               <?php echo _AT('expiry_date'); ?><br />
+                               <?php
+                                       $exp_no = $exp_yes = '';
+
+                                       if (intval($expiry)) {
+                                               $exp_yes = ' checked="checked"';
+
+                                               $today_day   = substr($expiry, 6, 2);
+                                               $today_mon   = substr($expiry, 4, 2);
+                                               $today_year  = substr($expiry, 0, 4);
+                                               $today_hour  = substr($expiry, 8, 2);
+                                               $today_min   = substr($expiry, 10, 2);
+
+                                       } else {
+                                               $exp_no = ' checked="checked"'; 
+                                               $today_day       = date('d');
+                                               $today_mon       = date('m');
+                                               $today_year  = date('Y');
+                                       }
+                               ?>
+
+                               <input type="radio" name="expiry_date" value="0" id="expire_never" <?php echo $exp_no; ?> /> <label for="expire_never"><?php echo _AT('expire_never'); ?></label><br />
+
+                               <input type="radio" name="expiry_date" value="1" id="expire_on" <?php echo $exp_yes; ?> /> <label for="expire_on"><?php echo _AT('expire_on'); ?></label> 
+                               <?php
+                                       $name = '_expire';
+                                       require(AT_INCLUDE_PATH.'html/release_date.inc.php');
+                               ?>
+                       </div>
+
+                       <div class="row buttons">
+                               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" /> 
+                               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+                       </div>
+                       </fieldset>
+               </div>
+       </form>
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/backup/create.php b/tools/backup/create.php
new file mode 100644 (file)
index 0000000..ce1fb4f
--- /dev/null
@@ -0,0 +1,64 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_ADMIN);
+
+$course = $_SESSION['course_id'];
+require(AT_INCLUDE_PATH.'classes/Backup/Backup.class.php');
+$Backup =& new Backup($db, $_SESSION['course_id']);
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       //make backup of current course
+       $Backup->create($_POST['description']);
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: index.php');
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('create_backup'); ?></legend>
+       <div class="row">
+               <?php echo _AT('create_backup_about', AT_COURSE_BACKUPS); ?>
+       </div>
+
+       <?php if ($Backup->getNumAvailable() >= AT_COURSE_BACKUPS): ?>
+               <div class="row">
+                       <p><strong><?php echo _AT('max_backups_reached'); ?></strong></p>
+               </div>
+       <?php else: ?>
+               <div class="row">
+                       <label for="desc"><?php echo _AT('optional_description'); ?></label>
+                       <textarea cols="35" rows="2" id="desc" name="description"></textarea>
+               </div>
+
+               <div class="row buttons">
+                       <input type="submit" name="submit" value="<?php echo _AT('create'); ?>" accesskey="s" /> 
+                       <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+               </div>
+       <?php endif; ?>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php');  ?>
\ No newline at end of file
diff --git a/tools/backup/delete.php b/tools/backup/delete.php
new file mode 100644 (file)
index 0000000..eb44584
--- /dev/null
@@ -0,0 +1,58 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+authenticate(AT_PRIV_ADMIN); \r
+\r
+$_section[0][0] = _AT('tools');\r
+$_section[0][1] = 'tools/';\r
+$_section[1][0] = _AT('backup_manager');\r
+$_section[1][1] = 'tools/backup/index.php';\r
+$_section[2][0] = _AT('delete');\r
+\r
+\r
+if (isset($_POST['submit_yes'])) {\r
+       require(AT_INCLUDE_PATH.'classes/Backup/Backup.class.php');\r
+       $Backup =& new Backup($db, $_SESSION['course_id']);\r
+       $Backup->delete($_POST['backup_id']);\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+else if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+       $delete_backup = intval($_REQUEST['backup_id']);\r
+       $sql = "SELECT * from ".TABLE_PREFIX."backups WHERE backup_id = '$delete_backup'";\r
+       $result = mysql_query($sql, $db);\r
+\r
+\r
+while ($row = mysql_fetch_assoc($result)){\r
+       $title = $row['file_name'];\r
+}\r
+       $index['backup_id'] = $_GET['backup_id'];\r
+       $msg->addConfirm(array('DELETE', $title ), $index);\r
+       $msg->printConfirm();\r
+\r
+require (AT_INCLUDE_PATH.'footer.inc.php');\r
+\r
+?>
\ No newline at end of file
diff --git a/tools/backup/edit.php b/tools/backup/edit.php
new file mode 100644 (file)
index 0000000..570eb56
--- /dev/null
@@ -0,0 +1,59 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_ADMIN); \r
+\r
+require(AT_INCLUDE_PATH.'classes/Backup/Backup.class.php');\r
+\r
+if (isset($_POST['cancel']) || !isset($_REQUEST['backup_id'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+$Backup =& new Backup($db, $_SESSION['course_id']);\r
+\r
+if (isset($_POST['edit'])) {\r
+       $Backup->edit($_POST['backup_id'], $_POST['new_description']);\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: index.php');\r
+       exit;\r
+} \r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$row = $Backup->getRow($_REQUEST['backup_id']);\r
+//check for errors\r
+\r
+\r
+?>\r
+<form name="form1" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<input type="hidden" name="backup_id" value="<?php echo $_GET['backup_id']; ?>" />\r
+<div class="input-form">\r
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('edit'); ?></legend>\r
+       <div class="row">\r
+               <label for="description"><?php echo _AT('optional_description'); ?></label>\r
+               <textarea cols="30" rows="2" id="description" name="new_description"><?php echo $row['description']; ?></textarea>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="edit" value="<?php echo _AT('save'); ?>" accesskey="s" /> \r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+       </div>\r
+       </fieldset>\r
+</div>\r
+</form>\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php');  ?>
\ No newline at end of file
diff --git a/tools/backup/index.php b/tools/backup/index.php
new file mode 100644 (file)
index 0000000..153a0a1
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+$_section[0][0] = _AT('tools');
+$_section[0][1] = 'tools/';
+$_section[1][0] = _AT('backup_manager');
+$_section[1][1] = 'tools/';
+
+authenticate(AT_PRIV_ADMIN);
+
+require(AT_INCLUDE_PATH.'classes/Backup/Backup.class.php');
+require(AT_INCLUDE_PATH.'lib/filemanager.inc.php');
+
+if (isset($_POST['restore'], $_POST['backup_id'])) {
+       header('Location: restore.php?backup_id=' . $_POST['backup_id']);
+       exit;
+} else if (isset($_POST['download'], $_POST['backup_id'])) {
+       $Backup =& new Backup($db, $_SESSION['course_id']);
+       $Backup->download($_POST['backup_id']);
+       exit; // never reached
+} else if (isset($_POST['delete'], $_POST['backup_id'])) {
+       header('Location: delete.php?backup_id=' . $_POST['backup_id']);
+       exit;
+} else if (isset($_POST['edit'], $_POST['backup_id'])) {
+       header('Location: edit.php?backup_id=' . $_POST['backup_id']);
+       exit;
+} else if (!empty($_POST)) {
+       $msg->addError('NO_ITEM_SELECTED');
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$Backup =& new Backup($db, $_SESSION['course_id']);
+$list = $Backup->getAvailableList();
+
+?>
+
+<form name="form" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+
+<table class="data" summary="" rules="cols">
+<thead>
+<tr>
+       <th><?php echo _AT('file_name');    ?></th>
+       <th><?php echo _AT('date_created'); ?></th>
+       <th><?php echo _AT('file_size');    ?></th>
+       <th><?php echo _AT('description');  ?></th>
+</tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="6"><input type="submit" name="restore" value="<?php echo _AT('restore'); ?>" /> 
+                                 <input type="submit" name="download" value="<?php echo _AT('download'); ?>" /> 
+                                 <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /> 
+                                 <input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /></td>
+</tr>
+</tfoot>
+<tbody>
+<?php
+
+       if (!$list) {
+               ?>
+       <tr>
+               <td colspan="4"><?php echo _AT('none_found'); ?></td>
+       </tr>
+       <?php
+       } else {
+               foreach ($list as $row) {
+                       echo '<tr onmousedown="document.form[\'b'.$row['backup_id'].'\'].checked = true; rowselect(this);" id="r_'.$row['backup_id'].'">';
+                       echo '<td class="row1"><label><input type="radio" value="'.$row['backup_id'].'" name="backup_id" id="b'.$row['backup_id'].'" />';
+                       echo $row['file_name'].'</label></td>';
+                       echo '<td>'.AT_date(_AT('filemanager_date_format'), $row['date_timestamp'], AT_DATE_UNIX_TIMESTAMP).'</td>';
+                       echo '<td align="right">'.get_human_size($row['file_size']).'</td>';
+                       echo '<td>'.AT_Print($row['description'], 'backups.description').'</td>';
+                       echo '</tr>';
+               }
+?>
+       <?php } ?>
+</tbody>
+</table>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php');  ?>
diff --git a/tools/backup/restore.php b/tools/backup/restore.php
new file mode 100644 (file)
index 0000000..03d05e7
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_ADMIN); 
+require(AT_INCLUDE_PATH.'classes/Backup/Backup.class.php');
+require(AT_INCLUDE_PATH.'lib/filemanager.inc.php');
+
+$Backup =& new Backup($db, $_SESSION['course_id']);
+
+if (!isset($_REQUEST['backup_id'])) {
+       header('Location: index.php');
+       exit;
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       if (!$_POST['material']) {
+               $msg->addError(array('EMPTY_FIELDS', _AT('material')));
+       } else {
+               $Backup->restore($_POST['material'], $_POST['action'], $_POST['backup_id']);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: index.php');
+               exit;
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$row = $Backup->getRow($_REQUEST['backup_id']);
+
+?>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">
+<input type="hidden" name="backup_id" value="<?php echo $_REQUEST['backup_id']; ?>" />
+
+<div class="input-form">
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><?php echo _AT('material'); ?><br />
+
+               <input type="checkbox" value="1" name="all" id="all" onclick="javascript:selectAll();" /><label for="all"><?php echo _AT('material_select_all'); ?></label><br /><br />
+
+               <input type="checkbox" value="1" name='material[properties]' id='m0' /><label for='m0'><?php echo _AT('banner'); ?></label><br />
+               <?php
+               $i=0;
+               $modules = $moduleFactory->getModules(AT_MODULE_STATUS_ENABLED, 0, TRUE);
+               $keys = array_keys($modules);
+               ?>
+               <?php foreach($keys as $module_name): ?>
+                       <?php $module =& $modules[$module_name]; ?>
+                       <?php if ($module->isBackupable()): ?>
+                               <input type="checkbox" value="1" name="material[<?php echo $module_name; ?>]" id="m<?php echo ++$i; ?>" /><label for="m<?php echo $i; ?>"><?php echo $module->getName(); ?></label><br />
+                       <?php endif; ?>
+               <?php endforeach; ?>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('action'); ?><br />
+               <input type="radio" checked="checked" name="action" value="append" id="append" /><label for="append"><?php echo _AT('append_content'); ?></label><br />
+               
+               <input type="radio" name="action" value="overwrite" id="overwrite" /><label for="overwrite"><?php echo _AT('overwite_content'); ?></label><br />
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('restore'); ?>" /> 
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+</div>
+</form>
+<?php $i=0; ?>
+<script language="javascript" type="text/javascript">
+       
+       function selectAll() {
+               if (document.form.all.checked == true) {
+                       document.form.m0.checked = true;
+                       <?php foreach($keys as $module_name): $module =& $modules[$module_name]; if ($module->isBackupable()): ?>
+                               document.form.m<?php echo ++$i; ?>.checked = true;
+                       <?php endif; endforeach; ?>
+               } else {
+                       document.form.m0.checked = false;
+                       <?php $i=0;?>
+                       <?php foreach($keys as $module_name): $module =& $modules[$module_name]; if ($module->isBackupable()): ?>
+                               document.form.m<?php echo ++$i; ?>.checked = false;
+                       <?php endif; endforeach; ?>
+
+               }
+       }
+</script>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php');  ?>
\ No newline at end of file
diff --git a/tools/backup/upload.php b/tools/backup/upload.php
new file mode 100644 (file)
index 0000000..fbac26d
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_ADMIN); 
+
+$_SESSION['done'] = 0;
+
+require(AT_INCLUDE_PATH.'classes/Backup/Backup.class.php');
+$Backup =& new Backup($db, $_SESSION['course_id']);
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php');
+       exit;
+} else if (isset($_POST['upload']) && ($Backup->getNumAvailable() < AT_COURSE_BACKUPS)) {
+       $Backup->upload($_FILES, $_POST['description']);
+
+       $_SESSION['done'] = 1;
+
+       if($msg->containsErrors()) {
+               header('Location: upload.php');
+               exit;
+       } else {
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: index.php');
+               exit;
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+
+<form name="form1" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" enctype="multipart/form-data" >
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('upload'); ?></legend>
+       <div class="row">
+               <p><?php echo _AT('restore_upload'); ?></p>
+       </div>
+
+       <?php if ($Backup->getNumAvailable() >= AT_COURSE_BACKUPS): ?>
+               <div class="row">
+                       <p><strong><?php echo _AT('max_backups_reached'); ?></strong></p>
+               </div>
+       <?php else: ?>
+               <div class="row">
+                       <label for="descrip"><?php echo _AT('optional_description'); ?></label><br />
+                       <textarea id="descrip" cols="30" rows="2" name="description"></textarea>
+               </div>
+               
+               <div class="row">
+                       <label for="file"><div class="required" title="<?php echo _AT('required_field'); ?>">*</div><?php echo _AT('file'); ?></label><br />
+                       <input type="file" name="file" id="file" />
+               </div>
+
+               <div class="row buttons">
+               <input type="submit" name="upload" value="<?php echo _AT('upload_backup'); ?>" onclick="openWindow('<?php echo AT_BASE_HREF; ?>tools/prog.php');" /> 
+                       <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+               </div>
+       <?php endif; ?>
+       </fieldset>
+</div>
+</form>
+
+<script language="javascript" type="text/javascript">
+function openWindow(page) {
+       newWindow = window.open(page, "progWin", "width=400,height=200,toolbar=no,location=no");
+       newWindow.focus();
+}
+</script>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php');  ?>
\ No newline at end of file
diff --git a/tools/chat/delete_transcript.php b/tools/chat/delete_transcript.php
new file mode 100644 (file)
index 0000000..097e606
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+
+if ($_POST['m']) {
+       $m =str_replace('.', '', $_POST['m']);
+} else if ($_GET['m']) {
+       $m =str_replace('.', '', $_GET['m']);
+}
+
+if ($_POST['submit_no']) {
+       $msg->addFeedback('CANCELLED');
+       Header('Location: index.php');
+       exit;
+}
+
+if ($_POST['submit_yes']) {
+       unlink(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/tran/'.$m.'.html');
+
+       //if its the current tran, unset it
+       if (str_replace('.html', '', $admin['tranFile']) == $m) {
+               $admin['produceTran'] = 0;
+               writeAdminSettings($admin);
+       }
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       Header('Location: index.php');
+       exit;
+}
+
+if (!file_exists(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/tran/'.$m.'.html')) {
+       $msg->addError('FILE_NOT_FOUND');
+
+       header('Location: index.php');
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$hidden_vars['m'] = $m;
+
+$msg->addConfirm(array('DELETE_TRANSCRIPT', $m), $hidden_vars);
+$msg->printConfirm();
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
diff --git a/tools/chat/index.php b/tools/chat/index.php
new file mode 100644 (file)
index 0000000..3654707
--- /dev/null
@@ -0,0 +1,152 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+
+$CACHE_DEBUG=0;
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/chat.inc.php');
+
+if (isset($_GET['view'], $_GET['file'])) {
+       header("Location:view_transcript.php?t=".$_GET['file']);
+       exit;
+} else if ((isset($_GET['view']) || isset($_GET['delete'])) && !isset($_GET['file'])) {
+       $msg->addError('NO_ITEM_SELECTED');
+}
+
+$admin = getAdminSettings();
+
+if (isset($_GET['delete'], $_GET['file'])) {
+
+       if (($_GET['file'].'.html' == $admin['tranFile']) && ($admin['produceTran'])) {
+               $msg->addError('TRANSCRIPT_ACTIVE');
+       } else {
+               header("Location:delete_transcript.php?m=".$_GET['file']);
+               exit;
+       }
+}
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$orders = array('asc' => 'desc', 'desc' => 'asc');
+$cols   = array('name' => 1, 'date' => 1);
+
+if (isset($_GET['asc'])) {
+       $order = 'asc';
+       $col   = isset($cols[$_GET['asc']]) ? $_GET['asc'] : 'date';
+} else if (isset($_GET['desc'])) {
+       $order = 'desc';
+       $col   = isset($cols[$_GET['desc']]) ? $_GET['desc'] : 'date';
+} else {
+       // no order set
+       $order = 'desc';
+       $col   = 'date';
+}
+
+$tran_files = array();
+if (!@opendir(AT_CONTENT_DIR . 'chat/')){
+       mkdir(AT_CONTENT_DIR . 'chat/', 0777);
+}
+
+if(!file_exists(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings')){
+       @mkdir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'], 0777);
+       @mkdir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/tran/', 0776);
+       @mkdir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/msgs/', 0776);
+       @mkdir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/users/', 0776);
+       @copy('admin.settings.default', AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings');
+       @chmod (AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings', 0777);
+
+}
+       
+if ($dir = @opendir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/tran/')) {
+       while (($file = readdir($dir)) !== false) {
+               if (substr($file, -strlen('.html')) == '.html') {
+                       $la     = stat(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/tran/'.$file);
+
+                       $file = str_replace('.html', '', $file);
+                       $tran_files[$file] = $la['ctime'];
+               }
+       }
+}
+
+if (count($tran_files) == 0) {
+       echo '<p>'._AT('chat_none_found').'</p>';
+} else {?>
+       
+<form name="form" method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+
+       <table class="data" rules="cols" summary="">
+       <colgroup>
+               <?php if ($col == 'name'): ?>
+                       <col />
+                       <col class="sort" />
+                       <col span="2" />
+               <?php elseif($col == 'date'): ?>
+                       <col span="3" />
+                       <col class="sort" />
+               <?php endif; ?>
+       </colgroup>
+       <thead>
+       <tr>
+               <th scope="col">&nbsp;</th>
+               <th scope="col"><a href="tools/chat/index.php?<?php echo $orders[$order]; ?>=name"><?php echo _AT('chat_transcript');?></a></th>
+               <th scope="col"><?php echo _AT('status'); ?></th>
+               <th scope="col"><a href="tools/chat/index.php?<?php echo $orders[$order]; ?>=date"><?php echo _AT('date'); ?></a></th> 
+               </th> 
+       </tr>
+       </thead>
+       <?php
+
+       if (($col == 'date') && ($order == 'asc')) {
+               asort($tran_files);
+       } else if (($col == 'date') && ($order == 'desc')) {
+               arsort($tran_files);
+       } else if (($col == 'name') && ($order == 'asc')) {
+               ksort($tran_files);
+       } else if (($col == 'name') && ($order == 'desc')) {
+               krsort($tran_files);
+       }
+       reset ($tran_files);
+       ?>
+
+       <tbody>
+       <?php foreach ($tran_files as $file => $date) { ?>
+               <tr onmousedown="document.form['<?php echo $file; ?>'].checked = true; rowselect(this);" id="r_<?php echo $file; ?>">
+                       <td><input type="radio" name="file" value="<?php echo $file; ?>" id="<?php echo $file; ?>" /></td>
+
+                       <td><label for="<?php echo $file; ?>"><?php echo $file; ?></label></td>
+                       <td>
+                               <?php if (($file.'.html' == $admin['tranFile']) && ($admin['produceTran'])) { 
+                                       echo _AT('chat_currently_active');
+                               } else {
+                                       echo _AT('chat_inactive');
+                               }?>
+                       </td>
+       
+                       <td><?php echo date('Y-m-d h:i:s', $date); ?></td>
+               </tr>
+       <?php } ?>
+       </tbody>
+
+       <tfoot>
+       <tr>
+               <td colspan="4"><input type="submit" name="view" value="<?php echo _AT('view'); ?>" /> <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /></td>
+       </tr>
+       </tfoot>
+
+       </table>
+</form>
+<?php
+}
+
+require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/chat/start_transcript.php b/tools/chat/start_transcript.php
new file mode 100644 (file)
index 0000000..6565c74
--- /dev/null
@@ -0,0 +1,235 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+
+/* @See ./admin.php */
+function writeAdminSettings(&$admin) {
+       if (file_exists(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings')) {
+               chmod(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings', 0755);
+       }
+
+       $fp = @fopen(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings', 'w+');
+       if (!$fp) {
+               // error
+               return 0;
+       }
+
+       $settings = '';
+       foreach ($admin as $prefKey => $prefValue) {
+               $settings .= $prefKey.'='.$prefValue."\n";
+       }
+
+       flock($fp, LOCK_EX);
+       if (!@fwrite($fp, $settings)) {
+               return 0;
+       }
+       flock($fp, LOCK_UN);
+       chmod(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings', 0600);
+
+       return 1;
+}
+
+function getAdminSettings() {
+       if (!file_exists(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings')) {
+               return 0;
+       }
+
+       $admin = array();
+
+       $file_prefs = file(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/admin.settings');
+       foreach ($file_prefs as $pref) {
+               $pref = explode('=', $pref, 2);
+               $admin[$pref[0]] = trim($pref[1]);
+       }
+
+    if ($admin['returnT'] && $admin['returnL']) {
+        $admin['returnLink'] = '<a href="'.$admin['returnL'].'" onFocus="this.className=\'highlight\'" onBlur="this.className=\'\'">'.$admin['returnT'].'</a>';
+    } else {
+        $admin['returnLink'] = '';
+    }
+
+       return $admin;
+}
+
+function defaultAdminSettings() {
+       $admin = array();
+
+    //$admin['cgiURL'] = 'http://dev.atutor.ca/chat/';
+    //$admin['htmlDir'] = '/usr/webserver/content/snow/chat/';
+    //$admin['htmlURL'] = 'http://dev.atutor.ca/discussions/achat/';
+    $admin['msgLifeSpan']              = 1800;         /* 30 min  */
+    $admin['chatIDLifeSpan']   = 2678400;      /* 1 month */
+    $admin['chatSessionLifeSpan'] = 3600;      /* 1 hour  */
+    //$admin['chatName'] = 'Accessible Chat';
+    //$admin['chatIDListFlag'] = 0;
+   // $admin['returnL'] = 'http://dev.atutor.ca';
+    //$admin['returnT'] = 'Return to the ATRC';
+    //$admin['adminPass'] = 'temppass';
+
+       return $admin;
+}
+
+$admin = getAdminSettings();
+if ($admin === 0) {
+       $admin = defaultAdminSettings();
+}
+
+if (isset($_POST['submit'])) {
+       $admin['adminPass']                             = $_POST['newAdminPass'];
+       $adminPass                                              = $_POST['newAdminPass'];
+       $admin['chatName']                              = $_POST['chatName'];
+       $admin['returnL']                               = $_POST['returnL'];
+       $admin['returnT']                               = $_POST['returnT'];
+       $admin['msgLifeSpan']                   = $_POST['msgLifeSpan'];
+       $admin['chatSessionLifeSpan']   = $_POST['chatSessionLifeSpan'];
+       $admin['chatIDLifeSpan']                = $_POST['chatIDLifeSpan'];
+       writeAdminSettings($admin);
+
+} else if (isset($_POST['submit2'])) {
+       @mkdir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'] . '/tran');
+       if(file_exists(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/tran/'.$_POST['tranFile'].'.html')){
+               $warnings = array('CHAT_TRAN_EXISTS', $_POST['tranFile']); //'file already exists';
+               $msg->addWarning($warnings);
+       } else if ($_POST['function'] == 'startTran') {
+               if (!(eregi("^[a-zA-Z0-9_]([a-zA-Z0-9_])*$", $_POST['tranFile']))){
+                       $msg->addError('CHAT_TRAN_REJECTED');
+               } else {
+                       $admin['produceTran'] = 1;
+                       $admin['tranFile'] = $_POST['tranFile'] . '.html';
+                       writeAdminSettings($admin);
+                       $tran = '<p>'._AT('chat_transcript_start').' '.date('Y-M-d H:i').'</p>';
+                       $tran .= '<table border="0" cellpadding="3" summary="" class="chat-transcript">';
+                               
+                       $fp = fopen(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/tran/'.$admin['tranFile'], 'w+');
+
+                       flock($fp, LOCK_EX);
+                       if (!fwrite($fp, $tran)) {
+                               return 0;
+                       }
+                       flock($fp, LOCK_UN);
+
+                       header('Location: index.php');
+                       exit;
+               }
+       } else if ($_POST['function'] == 'stopTran') {
+               $admin['produceTran'] = 0;
+               writeAdminSettings($admin);
+                       
+               $tran = '<p>'._AT('chat_transcript_end').' '.date('Y-M-d H:i').'</p>';
+               $fp = @fopen(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/tran/'.$admin['tranFile'], 'a');
+
+               @flock($fp, LOCK_EX); 
+               if (!@fwrite($fp, $tran)) {
+                       return 0;
+               }
+               flock($fp, LOCK_UN);
+
+               header('Location: index.php');
+               exit;
+       }
+} else if ($_GET['function'] == 'clearOldChatIDs') {
+       $return = clearOutOldChatPrefs();
+} else if ($_POST['submit3']) {
+       deleteUser($_POST['delName']);
+} else if ($_POST['submit4']) {
+       if ($dir = @opendir(AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/users/')) {
+               while (($file = readdir($dir)) !== false) {
+                       if (substr($file, -strlen('.prefs')) == '.prefs') {
+                               $chatName = substr($file, 0, -strlen('.prefs'));
+                               deleteUser($chatName);
+                       }
+               }
+       }
+}
+
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+       if ($return != '') {
+               echo '<code>'.$return.'</code>';
+       }
+       
+       if ($admin['msgLifeSpan'] < 650) {
+        $m10 = ' selected ';
+    } else if ($admin['msgLifeSpan'] < 950) {
+        $m30 = ' selected ';
+    } else if ($admin['msgLifeSpan'] < 1850) {
+        $m60 = ' selected ';
+    } else if ($admin['msgLifeSpan'] < 10850) {
+        $m180 = ' selected ';
+    } else {
+        $m1D = ' selected ';
+    }
+
+    if ($admin['chatSessionLifeSpan'] < 650) {
+        $s10 = ' selected ';
+    } else if ($admin['chatSessionLifeSpan'] < 950) {
+        $s30 = ' selected ';
+    } else if ($admin['chatSessionLifeSpan'] < 1850) {
+        $s60 = ' selected ';
+    } else if ($admin['chatSessionLifeSpan'] < 10850) {
+        $s180 = ' selected ';
+    } else {
+        $s1D = ' selected ';
+    }
+    if ($admin['chatIDLifeSpan'] < 86450) {
+        $i1D = ' selected ';
+    } else if ($admin['chatIDLifeSpan'] < 1728050) {
+        $i20D = ' selected ';
+    } else if ($admin['chatIDLifeSpan'] < 2592050) {
+        $i1M = ' selected ';
+    } else {
+        $i1Y = ' selected ';
+    } 
+?>
+
+<form name="f1" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<div class="input-form">
+       <div class="row">
+               <?php echo _AT('chat_keep_tran'); ?>
+       </div>
+
+<?php
+       echo '<input type="hidden" name="adminPass" value="'.$adminPass.'" />';
+
+       if ($admin['produceTran'] > 0) {
+               echo '<input type="hidden" name="function" value="stopTran" />';
+               echo '<div class="row">';
+                       echo _AT('chat_current_tran').' <a href="tools/chat/view_transcript.php?t='.str_replace('.html', '', $admin['tranFile']).'" >'.str_replace('.html', '', $admin['tranFile']).'</a>.</p>';
+               echo '</div>';
+
+               echo '<div class="row buttons">';
+               echo '<input type="submit" value="'._AT('chat_stop_tran').'" name="submit2" />';
+               echo '</div>';
+
+    } else {
+        echo '<input type="hidden" name="function" value="startTran" />';
+
+               echo '<div class="row">';
+                       echo _AT('chat_tran_file_name').' ';
+                       echo '<input type="text" name="tranFile" class="formfield" />';
+               echo '</div>';          
+
+               echo '<div class="row buttons">';
+               echo '<input type="submit" value="'._AT('chat_start_tran').'" name="submit2" />';
+               echo '</div>';
+    }
+       echo '</div>';
+       echo '</form>';
+       
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/tools/chat/view_transcript.php b/tools/chat/view_transcript.php
new file mode 100644 (file)
index 0000000..7709523
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+
+$file = AT_CONTENT_DIR . 'chat/'.$_SESSION['course_id'].'/tran/'.$_GET['t'].'.html';
+if (!file_exists($file)) {
+       $msg->addError('FILE_NOT_FOUND');
+       header('Location: index.php');
+       exit;
+}
+require(AT_INCLUDE_PATH.'header.inc.php');
+@readfile($file);
+echo '</table>';
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/tools/content/index.php b/tools/content/index.php
new file mode 100644 (file)
index 0000000..f22f32e
--- /dev/null
@@ -0,0 +1,143 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_CONTENT);\r
+\r
+if (isset($_GET['edit'], $_GET['ctid'])) {\r
+       header('Location: '.AT_BASE_HREF.'editor/edit_content.php?cid='.intval($_GET['ctid']));\r
+       exit;\r
+} else if (isset($_GET['delete'], $_GET['ctid'])) {\r
+       header('Location: '.AT_BASE_HREF.'editor/delete_content.php?cid='.intval($_GET['ctid']));\r
+       exit;\r
+} else if (isset($_GET['view'], $_GET['ctid'])) {\r
+       header('Location: '.AT_BASE_HREF.'content.php?cid='.intval($_GET['ctid']));\r
+       exit;\r
+} else if (isset($_GET['usage'], $_GET['ctid'])) {\r
+       header('Location: '.AT_BASE_HREF.'tools/tracker/page_student_stats.php?content_id='.intval($_GET['ctid']));\r
+       exit;\r
+} else if (!isset($_GET['ctid']) && !isset($_GET['sub_content']) && (isset($_GET['usage']) || isset($_GET['view']) || isset($_GET['delete']) || isset($_GET['edit']))) {\r
+       $msg->addError('NO_ITEM_SELECTED');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+if ($_GET['col']) {\r
+       $col = addslashes($_GET['col']);\r
+} else {\r
+       $col = 'content_parent_id, ordering';\r
+}\r
+\r
+if ($_GET['order']) {\r
+       $order = addslashes($_GET['order']);\r
+} else {\r
+       $order = 'asc';\r
+}\r
+\r
+if (!isset($_GET['sub_content'])) {\r
+       $parent_id = 0; \r
+} else {\r
+       $parent_id = intval($_GET['ctid']);\r
+}\r
+\r
+\r
+$all_content = $contentManager->getContent();\r
+\r
+$content = $all_content[$parent_id];\r
+\r
+function print_select($pid, $depth) {\r
+       global $all_content;\r
+\r
+       if (!isset($all_content[$pid])) {\r
+               return;\r
+       }\r
+\r
+       foreach ($all_content[$pid] as $row) {\r
+               if (isset($all_content[$row['content_id']])) {\r
+                       echo '<option value="'.$row['content_id'].'"';\r
+                       if ($_GET['ctid'] == $row['content_id']) {\r
+                               echo ' selected="selected"';\r
+                       }\r
+                       echo '>';\r
+                       echo str_repeat('&nbsp;', $depth * 5);\r
+                       echo $row['title'].'</option>';\r
+\r
+                       print_select($row['content_id'], $depth+1);\r
+               }\r
+       }\r
+}\r
+\r
+?>\r
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<div class="input-form">\r
+       <div class="row">\r
+               <h3><label for="ctid"><?php echo _AT('select_parent_topic'); ?></label></h3>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <select name="ctid" id="ctid">\r
+                       <option value="0"><?php echo _AT('top_level'); ?></option>\r
+                       <?php\r
+                               print_select(0, 1);\r
+                       ?>\r
+               </select>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="sub_content" value="<?php echo _AT('view_sub_topics'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<form name="form" method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+\r
+<table class="data" summary="" rules="cols" style="width: 90%;">\r
+<thead>\r
+<tr>\r
+       <th scope="col">&nbsp;</th>\r
+       <th scope="col">#</th>\r
+       <th scope="col"><?php echo _AT('title'); ?></th>\r
+       <th scope="col"><?php echo _AT('num_pages'); ?></th>\r
+</tr>\r
+</thead>\r
+<tfoot>\r
+<tr>\r
+       <td colspan="5">\r
+               <input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> \r
+               <input type="submit" name="view" value="<?php echo _AT('view'); ?>" />\r
+               <input type="submit" name="usage" value="<?php echo _AT('usage'); ?>" />\r
+               <input type="submit" name="sub_content" value="<?php echo _AT('sub_topics'); ?>" />\r
+               <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" />\r
+       </td>\r
+</tr>\r
+</tfoot>\r
+<tbody>\r
+       <?php if (!empty($content)): ?>\r
+               <?php foreach ($content as $row): ?>\r
+                       <tr onmousedown="document.form['c<?php echo $row['content_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $row['content_id']; ?>">\r
+                               <td><input type="radio" name="ctid" value="<?php echo $row['content_id']; ?>" id="c<?php echo $row['content_id']; ?>" /></td>\r
+                               <td><?php echo $row['ordering']; ?></td>\r
+                               <td><label for="c<?php echo $row['content_id']; ?>"><?php echo AT_print($row['title'], 'content.title'); ?></label></td>\r
+                               <td><?php echo count($all_content[$row['content_id']]); ?></td>\r
+                       </tr>\r
+               <?php endforeach; ?>\r
+       <?php else: ?>\r
+               <tr>\r
+                       <td colspan="5"><?php echo _AT('none_found'); ?></td>\r
+               </tr>\r
+       <?php endif; ?>\r
+</tbody>\r
+</table>\r
+</form>\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/course_email.php b/tools/course_email.php
new file mode 100644 (file)
index 0000000..60a483a
--- /dev/null
@@ -0,0 +1,232 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_COURSE_EMAIL);
+
+$course = intval($_GET['course']);
+
+if ($course == 0) {
+       $course = $_SESSION['course_id'];
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $missing_fields = array();
+
+       $_POST['to_enrolled']   = trim($_POST['to_enrolled']);
+       $_POST['to_unenrolled'] = trim($_POST['to_unenrolled']);
+       $_POST['to_alumni']     = trim($_POST['to_alumni']);
+       $_POST['to_assistants'] = trim($_POST['to_assistants']);
+
+       $_POST['subject'] = trim($_POST['subject']);
+       $_POST['body'] = trim($_POST['body']);
+
+       if ( ($_POST['to_enrolled']   == '') &&
+                ($_POST['to_unenrolled'] == '') &&
+                ($_POST['to_alumni']     == '') &&
+                ($_POST['to_assistants'] == '') &&
+                ($_POST['groups']        == '')
+               ) {
+                       $missing_fields[] = _AT('to');
+       }
+
+       if ($_POST['subject'] == '') {
+               $missing_fields[] = _AT('subject');
+       }
+
+       if ($_POST['body'] == '') {
+               $missing_fields[] = _AT('body');
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       if (!$msg->containsErrors()) {
+               $email_sql      = "SELECT email, first_name, last_name, login, password  FROM ".TABLE_PREFIX."course_enrollment C INNER JOIN ".TABLE_PREFIX."members M USING (member_id) WHERE C.course_id=$course AND (";
+               
+               if ($_POST['to_unenrolled']) {
+                       // choose all unenrolled
+                       $email_sql .= "C.approved='n' OR ";
+               }
+               
+               if ($_POST['to_alumni']) {
+                       // choose all alumni
+                       $email_sql      .= "C.approved='a' OR ";
+               }
+
+               if ($_POST['to_assistants']){
+                       // choose all assistants
+                       $email_sql      .= "C.privileges<>0 OR ";
+               }
+
+               if ($_POST['groups']) {
+                       // specific groups
+                       $groups = implode(',', $_POST['groups']);
+
+                       $group_members = array();
+                       $sql = "SELECT member_id FROM ".TABLE_PREFIX."groups_members WHERE group_id IN ($groups)";
+                       $result = mysql_query($sql, $db);
+                       while ($row = mysql_fetch_assoc($result)) {
+                               $group_members[] = $row['member_id'];
+                       }
+                       $group_members = implode(',', $group_members);
+
+                       $email_sql .= "M.member_id IN ($group_members) OR ";
+               } else if ($_POST['to_enrolled']) {
+                       // includes instructor
+                       $email_sql      .= "(C.approved='y' AND c.privileges=0) OR ";
+               }
+
+               $email_sql = substr_replace($email_sql, '', -4). ')'; // strip off the last ' OR '
+               $result = mysql_query($email_sql,$db);
+
+               require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+
+               // generate email recipients
+               $mail_list = array();
+               while ($row = mysql_fetch_assoc($result)) {
+                       $mail_list[]=$row['email'];
+                       $fname_list[$row['email']] = $row['first_name'];
+                       $lname_list[$row['email']] = $row['last_name'];
+                       $login_list[$row['email']] = $row['login'];
+               }
+
+               // Get instructor ID.
+               $result = mysql_query("SELECT member_id FROM ".TABLE_PREFIX."courses WHERE course_id=$course",$db);
+               $row = mysql_fetch_assoc($result);
+               $instructor_id = $row['member_id'];
+
+               // Add instructor to email list if he is not the one sending email.
+               if ($instructor_id != $_SESSION['member_id']) {
+                       //$sql = "SELECT email FROM ".TABLE_PREFIX."members WHERE member_id=$instructor_id";
+                       $sql = "SELECT email FROM ".TABLE_PREFIX."members WHERE member_id=$instructor_id";
+                       $result = mysql_query($sql, $db);
+                       $row = mysql_fetch_assoc($result);
+                       $mail_list[]= $row['email'];
+               }
+
+               // Get the sender.              
+               $result = mysql_query("SELECT email, first_name, last_name,login,password FROM ".TABLE_PREFIX."members WHERE member_id=$_SESSION[member_id]", $db);
+               $row    = mysql_fetch_assoc($result);
+               $mail_list[] = $row['email'];
+       // Prep the mailer.
+               // set some user specific variables for the body (
+               // Added by Thomas Taennier (ipool)
+               foreach ($mail_list as $recip) {
+                       $subject = $_POST['subject'];
+                       $body = $_POST['body'];
+                       $mail = new ATutorMailer;
+                       $mail->From     = $row['email'];
+                       $mail->FromName = $row['first_name'] . ' ' . $row['last_name'];
+                       $subject = str_replace('{AT_FNAME}', $fname_list[$recip],$subject);
+                       $subject = str_replace('{AT_LNAME}', $lname_list[$recip],$subject);
+                       $body = str_replace('{AT_FNAME}', $fname_list[$recip],$body);
+                       $body = str_replace('{AT_LNAME}', $lname_list[$recip],$body);
+                       $body = str_replace('{AT_EMAIL}', $recip,$body);
+                       $body = str_replace('{AT_USER}', $login_list[$recip],$body);
+
+                       $mail->Subject = $subject;
+                       $mail->AddAddress($recip);
+                       $mail->Body    = $body;
+                       if(!$mail->Send()) {
+                               $msg->printErrors('SENDING_ERROR');
+                                exit;
+                       }
+                       unset($mail);
+               }
+
+               
+
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: index.php');
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$sql   = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."course_enrollment C, ".TABLE_PREFIX."members M WHERE C.course_id=$course AND C.member_id=M.member_id AND M.member_id<>$_SESSION[member_id] ORDER BY C.approved, M.login";
+$result = mysql_query($sql,$db);
+$row   = mysql_fetch_array($result);
+if ($row['cnt'] == 0) {
+       $msg->printInfos('NO_STUDENTS');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+?>
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<input type="hidden" name="course" value="<?php echo $course; ?>" />
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('course_email'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div>
+               <?php echo  _AT('to'); ?><br />
+               <input type="checkbox" name="to_assistants" value="1" id="assistants" <?php if ($_POST['to_assistants']=='1') { echo 'checked="checked"'; } ?> /><label for="assistants"><?php echo  _AT('assistants'); ?></label>
+               <input type="checkbox" name="to_enrolled" value="1" id="enrolled" <?php if ($_POST['to_enrolled']=='1') { echo 'checked="checked"'; } else { echo 'checked="checked"'; } ?> /><label for="enrolled"><?php echo  _AT('enrolled'); ?></label>
+               <input type="checkbox" name="to_unenrolled" value="1" id="unenrolled" <?php if ($_POST['to_unenrolled']=='1') { echo 'checked="checked"'; } ?> /><label for="unenrolled"><?php echo  _AT('unenrolled'); ?></label>
+               <input type="checkbox" name="to_alumni" value="1" id="alumni" <?php if ($_POST['to_alumni']=='1') { echo 'checked="checked"'; } ?> /><label for="alumni"><?php echo  _AT('alumni'); ?></label>
+
+               <?php
+               $sql = "SELECT type_id, title FROM ".TABLE_PREFIX."groups_types WHERE course_id=$_SESSION[course_id] ORDER BY title";
+               $result = mysql_query($sql, $db);
+               ?>
+               <?php if ($row = mysql_fetch_assoc($result)): ?>
+                       <br /><br />
+                       <?php echo _AT('or_groups'); ?>:<br />
+                       <select name="groups[]" multiple="multiple" size="10" style="padding-right: 5px">
+                               <?php do { ?>
+                                       <optgroup label="<?php echo $row['title']; ?>">
+                                               <?php 
+                                                       $sql = "SELECT group_id, title FROM ".TABLE_PREFIX."groups WHERE type_id=$row[type_id] ORDER BY title";
+                                                       $group_result = mysql_query($sql, $db);
+                                               ?>
+                                               <?php while ($group_row = mysql_fetch_assoc($group_result)): ?>
+                                                       <option value="<?php echo $group_row['group_id']; ?>"><?php echo $group_row['title']; ?></option>
+                                               <?php endwhile; ?>
+                                       </optgroup>
+                               <?php } while ($row = mysql_fetch_assoc($result)); ?>
+                       </select>
+               <?php endif; ?>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="subject"><?php echo _AT('subject'); ?></label><br />
+               <input type="text" name="subject" size="60" id="subject" value="<?php echo $_POST['subject']; ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="body"><?php echo _AT('body'); ?></label><br />
+               <textarea cols="55" rows="18" name="body" id="body"><?php echo $_POST['body']; ?></textarea>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('send'); ?>" accesskey="s" /> 
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/course_properties.php b/tools/course_properties.php
new file mode 100644 (file)
index 0000000..5778288
--- /dev/null
@@ -0,0 +1,70 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2003 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/tinymce.inc.php');
+require(AT_INCLUDE_PATH.'classes/Backup/Backup.class.php');
+require(AT_INCLUDE_PATH.'lib/file_storage.inc.php');
+
+authenticate(AT_PRIV_ADMIN);
+
+$course = $_SESSION['course_id'];
+$isadmin   = FALSE;
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php');
+       exit;
+
+
+}else if($_POST['submit']){
+       require(AT_INCLUDE_PATH.'lib/course.inc.php');
+       $_POST['instructor'] = $_SESSION['member_id'];
+
+       $errors = add_update_course($_POST);
+
+       if (is_numeric($errors)) {
+               $msg->addFeedback('COURSE_PROPERTIES');
+               header('Location: '.AT_BASE_HREF.'tools/index.php');    
+               exit;
+       }
+               
+//}else if(($_POST['setvisual'] && !$_POST['settext']) || $_GET['setvisual'])){
+} else if (($_POST['setvisual'] || $_POST['settext'])){
+               //header('Location: '.$_SESSION['PHP_SELF'].'');        
+               //exit;
+} else if (isset($_POST['course'])) {
+       require(AT_INCLUDE_PATH.'lib/course.inc.php');
+       $_POST['instructor'] = $_SESSION['member_id'];
+
+       $errors = add_update_course($_POST);
+
+       if (is_numeric($errors)) {
+               $msg->addFeedback('COURSE_PROPERTIES');
+               header('Location: '.AT_BASE_HREF.'tools/index.php');    
+               exit;
+       }
+}
+
+$onload = 'document.course_form.title.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+require(AT_INCLUDE_PATH.'html/course_properties.inc.php');
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+
+
+?>
\ No newline at end of file
diff --git a/tools/course_stats.php b/tools/course_stats.php
new file mode 100644 (file)
index 0000000..15fd1bf
--- /dev/null
@@ -0,0 +1,204 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_ADMIN, AT_PRIV_RETURN);
+
+$year  = intval($_GET['year']);
+$month = intval($_GET['month']);
+
+       if ($month == 0) {
+               $month = date('m');
+               $year  = date('Y');
+       }
+
+       $days   = array();
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."course_stats WHERE course_id=$_SESSION[course_id] AND MONTH(login_date)=$month AND YEAR(login_date)=$year ORDER BY login_date ASC";
+       $result = mysql_query($sql, $db);
+       //$today  = 1; /* we start on the 1st of the month */
+       $max_total_logins = 0;
+       $min_total_logins = (int) 99999999;
+       $total_logins = 0;
+
+       $empty = true;
+       while ($row = mysql_fetch_array($result)) {
+               $empty = false;
+               $row_day = substr($row['login_date'], 8, 2);
+
+               if (substr($row_day, 0,1) == '0') {
+                       $row_day = substr($row_day, 1, 1);
+               }
+               
+               while ($today < $row_day-1) {
+                       $today++;
+                       $days[$today] = array(0, 0);
+                       $min_total_logins = 0;
+               }
+
+               $today = $row_day; /* skip this day in the fill-in-the-blanks-loop */
+                               
+               $days[$row_day] = array($row['guests'], $row['members']);
+
+               if ($max_total_logins < $row['guests']+$row['members']) {
+                       $max_total_logins = $row['guests']+$row['members'];
+               }
+
+               if ($min_total_logins > $row['guests']+$row['members']) {
+                       $min_total_logins = $row['guests']+$row['members'];
+               }
+
+               $total_logins += $row['guests']+$row['members'];
+       }
+
+       /* add zeros to the end of the month, only if it isn't the current month */
+       $now_month = date('m');
+       $now_year  = date('Y');
+       if ( (($month < $now_month) && ($now_year == $year)) || ($now_year < $year) ) {
+               $today++;
+               while (checkdate($month, $today,$year)) {
+                       $days[$today] = array(0, 0);
+                       $today++;
+               }
+       }
+       $num_days = count($days);
+
+       if ($total_logins > 0) {
+               $avg_total_logins = $total_logins/$num_days;
+       } else {
+               $avg_total_logins = 0;
+       }
+
+       $block_height           = 10;
+       $multiplyer_height  = 5; /* should be multiples of 5 */
+
+       if ($month == 12) {
+               $next_month = 1;
+               $next_year  = $year + 1;
+       } else {
+               $next_month = $month + 1;
+               $next_year  = $year;
+       }
+
+       if ($month == 1) {
+               $last_month = 12;
+               $last_year  = $year - 1;
+       } else {
+               $last_month = $month - 1;
+               $last_year  = $year;
+       }
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+       <table cellspacing="1" cellpadding="1" border="0" class="bodyline" summary="" align="center">
+       <tr>
+               <th colspan="2" class="cyan"><small class="bigspacer"><?php
+                       echo '<a href="'.$_SERVER['PHP_SELF'].'?month='.($last_month).SEP.'year='.$last_year.'">';
+                       echo ' '.AT_date('%F', $last_month, AT_DATE_INDEX_VALUE ); ?></a> |</small>
+                       <?php echo AT_date('%F', $month, AT_DATE_INDEX_VALUE ); ?> <small class="bigspacer">| <?php
+                       echo '<a href="'.$_SERVER['PHP_SELF'].'?month='.$next_month.SEP.'year='.$next_year.'">';
+                       echo AT_date('%F', $next_month, AT_DATE_INDEX_VALUE); ?> </a></small></th>
+       </tr>
+<?php
+               if (($num_days == 0) || ($empty)) {
+                       echo '<tr>';
+                       echo '<td class="row1" colspan="2">'._AT('no_month_data').'</td>';
+                       echo '</tr>';
+                       echo '</table>';
+                       require(AT_INCLUDE_PATH.'footer.inc.php');
+                       exit;
+               }
+?>
+       <tr>
+               <td class="row1" valign="top" align="right"><strong><?php echo _AT('total'); ?>:</strong></td>
+               <td class="row1"><?php echo $total_logins; ?></td>
+       </tr>
+       <tr><td height="1" class="row2" colspan="2"></td></tr>
+       <tr>
+               <td class="row1" valign="top" align="right"><strong><?php echo _AT('maximum'); ?>:</strong></td>
+               <td class="row1"><?php echo $max_total_logins; ?></td>
+       </tr>
+       <tr><td height="1" class="row2" colspan="2"></td></tr>
+
+       <tr>
+               <td class="row1" valign="top" align="right"><strong><?php echo _AT('minimum'); ?>:</strong></td>
+               <td class="row1"><?php
+               if ($min_total_logins < 99999999) {
+                       echo $min_total_logins; 
+               } else {
+                       echo '0';
+               } ?></td>
+       </tr>
+       <tr><td height="1" class="row2" colspan="2"></td></tr>
+       <tr>
+               <td class="row1" valign="top" align="right"><strong><?php   echo _AT('average'); ?>:</strong></td>
+               <td class="row1"><?php echo number_format($avg_total_logins, 1); ?> <?php   echo _AT('per_day'); ?></td>
+       </tr>
+       <tr><td height="1" class="row2" colspan="2"></td></tr>
+
+       <tr>
+               <td class="row1" valign="top" align="right"><strong><?php   echo _AT('graph'); ?>:</strong></td>
+               <td class="row1">
+                       <table border="0" cellspacing="0" cellpadding="0">
+                       <tr>
+                               <td valign="top" class="graph1"><small><?php echo $max_total_logins; ?></small></td>
+
+<?php
+                       foreach ($days as $day => $logins) {
+                       $dd++;
+                               echo '<td valign="bottom" class="graph"><img src="images/clr.gif" height="'.(($max_total_logins*$multiplyer_height) % $block_height + $block_height).'" width="10" alt="" /><br /><img src="images/blue.gif" height="'.($logins[0]*$multiplyer_height).'" width="9" alt="'.$logins[0].' '._AT('guests').' ('.($logins[0]+$logins[1]).' '._AT('total').')" /><br /><img src="images/red.gif" height="'.($logins[1]*$multiplyer_height).'" width="9" alt="'.$logins[1].' '._AT('members').' ('.($logins[1]+$logins[0]).' '._AT('total').')" /><br /><small>'.$dd.'&nbsp;</small></td>';
+
+                       } while ($row = mysql_fetch_array($result));
+?>
+
+                       </tr>
+                       <tr>
+                               <td valign="top"><small>0</small></td>
+                       </tr>
+                       </table>
+
+                       <small><?php  echo _AT('legend'); ?>: <img src="images/red.gif" height="10" width="10" alt="<?php echo _AT('red_members'); ?>" /> <?php   echo _AT('members'); ?>,
+                               <img src="images/blue.gif" height="10" width="10" alt="<?php echo _AT('blue_guests'); ?>" /> <?php echo _AT('guests'); ?>.</small>
+               </td>
+       </tr>
+       <tr><td height="1" class="row2" colspan="2"></td></tr>
+       <tr>
+               <td class="row1" valign="top" align="right"><strong><?php echo _AT('raw_data'); ?>:</strong></td>
+               <td class="row1" align="center">
+       
+               <table class="data static" summary="" rules="cols">
+               <thead>
+               <tr>
+                       <th scope="col"><?php echo _AT('date');    ?></th>
+                       <th scope="col"><?php echo _AT('guests');  ?></th>
+                       <th scope="col"><?php echo _AT('members'); ?></th>
+               </tr>
+               </thead>
+               <tbody>
+               <?php $short_name = $month_name_con['en'][$month-1]; ?>
+               <?php foreach ($days as $day => $logins):?>
+                       <tr>
+                               <td><?php echo $short_name.' '.$day; ?></td>
+                               <td><?php echo $logins[0]; ?></td>
+                               <td><?php echo $logins[1]; ?></td>
+                       </tr>
+               <?php endforeach; ?>
+               <tbody>
+               </table>
+
+               </td>
+       </tr>
+       </table>
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/course_tracker.php b/tools/course_tracker.php
new file mode 100644 (file)
index 0000000..e257ffc
--- /dev/null
@@ -0,0 +1,315 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+exit('this file is no longer used');
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+$_section[0][0] = _AT('tools');
+
+//get the login name or real name for member_id translation
+$sql14 = "select member_id, login, first_name, last_name from ".TABLE_PREFIX."members";
+$result14=mysql_query($sql14, $db);
+while($row=mysql_fetch_array($result14)){
+       if($row['first_name'] && $row['last_name']){
+               $this_user[$row['member_id']]= $row['first_name'].' '. $row['last_name'];
+       }else{
+               $this_user[$row['member_id']]= $row['login'];
+       }
+}
+
+///////////
+// Create a CSV dump of the tracking data for this course
+if($_GET['csv']=='1'){
+       $sql5 = "select * from ".TABLE_PREFIX."g_refs";
+       $result = mysql_query($sql5,$db);
+       $refs = array();
+       while ($row= mysql_fetch_array($result)) {
+               $refs[$row['g_id']] = $row['reference'];
+       }
+       //get the g translation for non content pages
+       $sql8= "select
+               G.g,
+               R.reference,
+               R.g_id
+       from
+               ".TABLE_PREFIX."g_click_data G,
+               ".TABLE_PREFIX."g_refs R
+       where
+               G.g = R.g_id
+               AND
+               course_id='$_SESSION[course_id]'";
+
+       if(!$result8 = mysql_query($sql8,$db)){
+               echo "query failed";
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }else{
+
+               $title_refs = array();
+               while ($row= mysql_fetch_array($result8)) {
+                       $title_refs2[$row['g']] = $row['reference'];
+
+               }
+       }
+       //get the translations for the content id numbers
+       $sql7 = "select
+                       C.title,
+                       C.content_id
+
+               from
+                       ".TABLE_PREFIX."content C
+
+               where
+                       course_id='$_SESSION[course_id]'";
+       if(!$result7 = mysql_query($sql7,$db)){
+               echo "query failed";
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+       $title_refs = array();
+       while ($row= mysql_fetch_array($result7)) {
+               $title_refs[$row['content_id']] = $row['title'];
+
+       }
+
+       $name=ereg_replace(" ", "_", $_SESSION['course_title']);
+       $name=ereg_replace("'", "", $name);
+       header('Content-Type: text/csv');
+       header('Content-Disposition: inline; filename="'.$name.'_tracking.csv"');
+       header('Expires: 0');
+       header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+       header('Pragma: public');
+
+       $sqlall="select * from ".TABLE_PREFIX."g_click_data where course_id='$_SESSION[course_id]'";
+
+       $result_all=mysql_query($sqlall, $db);
+       $num_fields = mysql_num_fields($result_all);
+       for($i=0; $i<$num_fields; $i++){
+               if($i==($num_fields-1)){
+                       $this_row .= mysql_field_name($result_all,$i);
+               }else{
+                       $this_row .= mysql_field_name($result_all,$i).',';
+               }
+
+       }
+       $this_row .= "\n";
+       while($row=mysql_fetch_array($result_all)){
+               $this_row .= quote_csv($this_user[$row['member_id']]).",";
+               $this_row .= quote_csv($row['course_id']).",";
+               if($row['from_cid']=='' || $row['from_cid'] == '0'){
+                       $this_row .= '"0",';
+               }else if ($title_refs[$row['from_cid']] == ''){
+                       $this_row .= quote_csv(_AT('deleted')).',';
+               }else if ($title_refs[$row['from_cid']] != ''){
+                       $this_row .= quote_csv($title_refs[$row['from_cid']]).",";
+               }else{
+                       $this_row .= '"0",';
+               }
+               if($row['to_cid']=='' || $row['to_cid'] == '0'){
+                       $this_row .= '"0",';
+               }else if($title_refs[$row['to_cid']] == ''){
+                       $this_row .= quote_csv(_AT('deleted')).',';
+               }else if($title_refs[$row['to_cid']] != ''){
+                       $this_row .= quote_csv($title_refs[$row['to_cid']]).",";
+               }else{
+                       $this_row .= '"0",';
+               }
+
+               $this_row .= quote_csv(_AT($title_refs2[$row['g']])).",";
+               $this_row.= AT_date(_AT('forum_date_format'),$row['timestamp'], AT_DATE_UNIX_TIMESTAMP).",";
+               $this_row.= quote_csv($row['duration'])."\n";
+
+       }
+       if (!@opendir(AT_CONTENT_DIR . 'export/')){
+               mkdir(AT_CONTENT_DIR . 'export/', 0777);
+       }
+
+       $fp = @fopen(AT_CONTENT_DIR . 'export/'.$name.'_tracking.csv', 'w');
+       if (!$fp) {
+               $errors=array('CSV_FAILED', $name);
+               $msg->printErrors($errors);
+               exit;
+       }
+       @fputs($fp, $this_row); @fclose($fp);
+       @readfile(AT_CONTENT_DIR . 'export/'.escapeshellcmd($name).'_tracking.csv');
+       @unlink(AT_CONTENT_DIR . 'export/'.escapeshellcmd($name).'_tracking.csv');
+       exit;
+
+
+}
+
+///////
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+// Give the user two chances when deleting tracking data
+if ($_GET['reset']==1){
+       echo '<a name="warning"></a>';
+       $warnings=array('DELETE_TRACKING', $_SERVER['PHP_SELF']);
+       $msg->printWarnings($warnings);
+       
+       /* Since we do not know which choice will be taken, assume it No/Cancel, addFeedback('CENCELLED)
+        * If sent to results.php then OK, else if sent back here & if $_GET['reset']=2 then assumed choice was not taken
+        * ensure that addFeeback('CANCELLED') is properly cleaned up, see below
+        */
+       $msg->addFeedback('CANCELLED');
+       echo '<center><a href="'.$_SERVER['PHP_SELF'].'?reset=2">'._AT('yes_delete').'</a> | <a href="'.$_SERVER['PHP_SELF'].'">'._AT('no').'</a></center>';
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+} else if($_GET['reset']==2) {
+       /* We must ensure that any previous feedback is flushed, 
+        * since AT_FEEDBACK_CANCELLED might be present
+        * if Yes/Delete was chosen above when reset was = 1
+        */
+       $msg->deleteFeedback('CANCELLED'); // makes sure its not there 
+               
+       $sql_delete= "delete from ".TABLE_PREFIX."g_click_data where course_id='$_SESSION[course_id]'";
+       if ($result_delete_track=mysql_query($sql_delete, $db)){
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       } else {
+               $msg->addError('TRACKING_NOT_DELETED');
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+}
+/////////////////////////////
+// Top of the page
+$msg->printAll();
+
+//This page is only for instructor/owners
+if(!authenticate(AT_PRIV_ADMIN, AT_PRIV_RETURN)){
+       $msg->printInfos('NO_PERMISSION');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+//}
+//see if tracking is turned on
+$sql="SELECT tracking from ".TABLE_PREFIX."courses where course_id=$_SESSION[course_id]";
+$result=mysql_query($sql, $db);
+while($row= mysql_fetch_array($result)){
+       if($row['tracking'] == "off"){
+               if(authenticate(AT_PRIV_ADMIN, AT_PRIV_RETURN)){
+                       $msg->addInfo('TRACKING_OFFIN');
+               }else{
+                       $msg->addInfo('TRACKING_OFFST');
+               }
+       $msg->printInfos();
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+       }
+}
+
+$msg->printWarnings();
+
+?>
+       <ul>
+       <li><a href="<?php echo $_SERVER['PHP_SELF']; ?>?stats=summary#show_pages"><?php echo _AT('g_show_page_stats'); ?></a>
+       <br /><?php echo _AT('g_show_page_stats_desc'); ?>
+       </li>
+       <li><a href="<?php echo $_SERVER['PHP_SELF']; ?>?stats=student#show_members"><?php echo _AT('g_show_member_stats'); ?></a>
+       <br /><?php echo _AT('g_show_member_stats_desc'); ?>
+       </li>
+       <li><a href="<?php echo $_SERVER['PHP_SELF']; ?>?csv=1"><?php echo _AT('g_download_tracking_csv'); ?></a>
+       <br /><?php echo _AT('g_download_tracking_csv_desc'); ?>
+       </li>
+       <li><a href="<?php echo $_SERVER['PHP_SELF']; ?>?reset=1#warning"><?php echo _AT('g_reset_tracking'); ?></a>
+       <br /><?php echo _AT('g_reset_tracking_desc'); ?>
+       </li>
+       </ul>
+
+<hr />
+<?php
+
+// present the id picker
+if($_GET['stats']=='student' || $_GET['member_id']){
+
+       $sql = "select DISTINCT member_id from ".TABLE_PREFIX."g_click_data where course_id='$_SESSION[course_id]' order by member_id DESC";
+       $result = mysql_query($sql, $db);
+
+       //get the course enrollment
+       $sql2="select * from ".TABLE_PREFIX."course_enrollment where course_id='$_SESSION[course_id]' AND approved='y'";
+       $result2 = mysql_query($sql2, $db);
+       while($row2 = mysql_fetch_array($result2)){
+               $enrolled[$row2['member_id']] = $row2['member_id'];
+       }
+       ?>
+       <a name="show_members"></a>
+       <table class="data static" rules="cols" summary="">
+       <thead>
+       <tr>
+               <th><?php echo _AT('select_member'); ?></th>
+       </tr>
+       </thead>
+
+       <tbody>
+       <tr>
+               <td><?php
+                       if($_GET['summary2'] == "summary") {
+                               $select_summary = ' checked="checked"';
+                       } else if($_GET['summary2'] == "raw") {
+                               $select_raw = ' checked="checked"';
+                       }
+               ?>
+       <form action="<?php echo $_SERVER['PHP_SELF']; ?>#show_members" method="GET">
+       <input type="radio" name="summary2" id="summary2" value="summary" <?php echo $select_summary;  ?>><label for="summary2"><?php echo _AT('summary');  ?> </label>
+       <input type="radio" id="summary" name="summary2" value="raw" <?php echo $select_raw;  ?>><label for="summary"><?php echo _AT('raw');  ?> </label>
+       <select name="member_id">
+       <?php
+       while($row = mysql_fetch_array($result)){
+               if($row['member_id'] == $enrolled[$row['member_id']]){
+
+                       echo '<option  value="'.$row['member_id'].'" ';
+                       if($_GET['member_id']==$row['member_id']){
+                               echo ' selected="selected"';
+                       }
+                       echo '>'.$this_user[$row['member_id']].'</option>'."\n";
+               }
+       }
+       ?>
+       </select>
+       <input type="submit" value="<?php echo _AT('view_tracking');  ?>" class="button" />
+       </form>
+       </td>
+       </tr>
+       </tbody>
+       </table>
+<?php
+}
+
+if($_GET['stats'] =="details" || $_GET['stats'] == "summary" || $_GET['g_id'] || $_GET['csv']== 1) {
+       require(AT_INCLUDE_PATH.'lib/tracker_stats.inc.php');
+}
+
+else if ($_GET['summary2'] == "summary") {
+       require(AT_INCLUDE_PATH.'lib/tracker_stats2.inc.php');
+} 
+
+else {
+       require(AT_INCLUDE_PATH.'lib/tracker.inc.php');
+}
+
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+
+       
+function quote_csv($line) {
+       $line = str_replace('"', '""', $line);
+
+       $line = str_replace("\n", '\n', $line);
+       $line = str_replace("\r", '\r', $line);
+       $line = str_replace("\x00", '\0', $line);
+
+       return '"'.$line.'"';
+}
+?>
\ No newline at end of file
diff --git a/tools/delete_course.php b/tools/delete_course.php
new file mode 100644 (file)
index 0000000..52a6d5c
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg GayJoel Kronenberg & Heidi Hazelton */
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_ADMIN);
+
+$course = isset($_REQUEST['course']) ? intval($_REQUEST['course']) : 0;
+
+if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'tools/course_properties.php');
+       exit;
+} else if (isset($_POST['step']) && ($_POST['step'] == 2) && isset($_POST['submit_yes'])) {
+       require(AT_INCLUDE_PATH.'lib/filemanager.inc.php');
+       require(AT_INCLUDE_PATH.'lib/delete_course.inc.php');
+
+       delete_course($_SESSION['course_id'], $entire_course = true); // delete the course
+       cache_purge('system_courses','system_courses'); // purge the system_courses cache (if successful)
+       
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: '.AT_BASE_HREF.'bounce.php?course=0');
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+if (!isset($_POST['step'])) {
+       $hidden_vars['step']   = 1;
+       $msg->addConfirm(array('DELETE_COURSE_1', $system_courses[$_SESSION['course_id']]['title']), $hidden_vars);
+       $msg->printConfirm();
+} else if ($_POST['step'] == 1) {
+       $hidden_vars['step']   = 2;
+       $msg->addConfirm(array('DELETE_COURSE_2', $system_courses[$_SESSION['course_id']]['title']), $hidden_vars);
+       $msg->printConfirm();
+}
+
+require(AT_INCLUDE_PATH.'footer.inc.php'); 
+?>
\ No newline at end of file
diff --git a/tools/edit_styles.php b/tools/edit_styles.php
new file mode 100644 (file)
index 0000000..242fdc2
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+$_section[0][0] =  _AT('tools');
+$_section[0][1] = 'tools/';
+$_section[1][0] =  _AT('style_editor');
+
+$filename = AT_CONTENT_DIR . $_SESSION['course_id'].'/stylesheet.css';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+echo '<h2>';
+       if ($_SESSION['prefs'][PREF_CONTENT_ICONS] != 2) {
+               echo '<a href="tools/" class="hide"><img src="images/icons/default/square-large-tools.gif"  class="menuimageh2" border="0" vspace="2" width="42" height="40" alt="" /></a>';
+       }
+       if ($_SESSION['prefs'][PREF_CONTENT_ICONS] != 1) {
+               echo ' <a href="tools/" class="hide">'._AT('tools').'</a>';
+       }
+echo '</h2>';
+
+echo '<h3>';
+       if ($_SESSION['prefs'][PREF_CONTENT_ICONS] != 2) {
+               echo '&nbsp;<img src="images/icons/default/css-editor-large.gif"  class="menuimageh3" width="42" height="38" alt="" /> ';
+       }
+       if ($_SESSION['prefs'][PREF_CONTENT_ICONS] != 1) {
+               echo _AT('style_editor');
+       }
+echo '</h3>';
+
+$msg->addInfo('CSS_DEPRECATED');
+if (file_exists('../' . $filename)) {
+       $info = array('CSS_DEPRECATED_DL', AT_BASE_HREF . $filename);
+       $msg->addInfo($info);
+}
+
+$msg->printInfos();
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/tools/enrollment/create_course_list.php b/tools/enrollment/create_course_list.php
new file mode 100644 (file)
index 0000000..d6b57ce
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_ENROLLMENT);
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+$msg->printAll();
+?>
+               <fieldset class="group_form"><legend class="group_form"><?php echo _AT('list_create_course_list'); ?></legend>
+<form action="tools/enrollment/verify_list.php" method="post">
+<input type="hidden" name="from" value="create" />
+<div class="input-form">
+
+       <div class="row">
+               <?php echo _AT('import_sep_txt'); ?><br />
+               <input type="radio" name="sep_choice" id="und" value="_" checked="checked" />
+               <label for="und"><?php echo _AT('underscore'); ?></label>
+               <input type="radio" name="sep_choice" id="per" value="." />
+               <label for="per"><?php echo _AT('period'); ?></label>
+       </div>
+</div>
+               
+<table class="data static" summary="" rules="cols">
+<thead>
+<tr>
+       <th>&nbsp;</th>
+       <th><?php echo _AT('first_name'); ?></th>
+       <th><?php echo _AT('last_name'); ?></th>
+       <th><?php echo _AT('email'); ?></th>
+</tr>
+</thead>
+
+<tfoot>
+<tr>
+       <td colspan="4">
+               <input type="submit" name="submit" value="<?php echo _AT('list_add_course_list');  ?>" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </td>
+</tr>
+</tfoot>
+
+<tbody>
+<?php for ($i=1; $i <= 5; $i++): ?>
+       <tr>
+               <td><?php echo $i; ?></td>
+               <td><input type="text" name="first_name<?php echo $i; ?>" /></td>
+               <td><input type="text" name="last_name<?php echo $i; ?>" /></td>
+               <td><input type="text" name="email<?php echo $i; ?>" /></td>
+       </tr>
+<?php endfor; ?>
+</tbody>
+
+</table>
+</form>
+</fieldset>
+<?php  require(AT_INCLUDE_PATH.'footer.inc.php');      ?>
\ No newline at end of file
diff --git a/tools/enrollment/enroll_edit.php b/tools/enrollment/enroll_edit.php
new file mode 100644 (file)
index 0000000..3b2ae61
--- /dev/null
@@ -0,0 +1,23 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_ENROLLMENT);\r
+\r
+$course_id = $_SESSION['course_id'];\r
+\r
+require(AT_INCLUDE_PATH.'html/enroll_edit.inc.php');\r
+exit;\r
+?>
\ No newline at end of file
diff --git a/tools/enrollment/export_course_list.php b/tools/enrollment/export_course_list.php
new file mode 100644 (file)
index 0000000..688a30c
--- /dev/null
@@ -0,0 +1,125 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_ENROLLMENT);
+
+$completed = 0;
+
+/*EXPORT LIST OF STUDENTS*/
+if(isset($_POST['export'])) {
+       //if not list was selected
+       if (!$_POST['enrolled'] && !$_POST['pending_enrollment'] && !$_POST['alumni']) {
+               $msg->addError('NO_STUDENT_SELECTED');
+       }
+       //retrieve info from database based on selection (make sure that instructor is not exported!)
+       else {
+               if ($_POST['enrolled'] && $_POST['pending_enrollment'] && $_POST['alumni']) {
+                       $condition = "";
+               } else if ($_POST['enrolled'] && $_POST['pending_enrollment']) {
+                       $condition = "AND approved <> 'a'";
+               } else if ($_POST['enrolled'] && $_POST['alumni']) {
+                       $condition = "AND approved <> 'n'";
+               } else if ($_POST['pending_enrollment'] && $_POST['alumni']) {
+                       $condition = "AND approved <> 'y'";
+               } else if ($_POST['pending_enrollment']) {
+                       $condition = "AND approved = 'n'";                              
+               } else if ($_POST['enrolled']) {
+                       $condition = "AND approved = 'y'";
+               } else if ($_POST['alumni']) {
+                       $condition = "AND approved = 'a'";
+               } 
+
+               $sql = "SELECT m.first_name, m.last_name, m.email 
+                               FROM ".TABLE_PREFIX."course_enrollment cm JOIN ".TABLE_PREFIX."members m ON cm.member_id = m.member_id JOIN ".TABLE_PREFIX."courses c ON (cm.course_id = c.course_id AND cm.member_id <> c.member_id)   WHERE cm.course_id = $_SESSION[course_id] " . $condition . "ORDER BY m.last_name";
+
+               $result =  mysql_query($sql,$db);
+               while ($row = mysql_fetch_assoc($result)){
+                       $this_row .= quote_csv($row['first_name']).",";
+                       $this_row .= quote_csv($row['last_name']).",";
+                       $this_row .= quote_csv($row['email'])."\n";
+               }
+
+               if ($this_row) {
+                       header('Content-Type: text/csv');
+                       header('Content-transfer-encoding: binary');
+                       header('Content-Disposition: attachment; filename="course_list_'.$_SESSION['course_id'].'.csv"');
+                       header('Expires: 0');
+                       header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+                       header('Pragma: public');
+
+                       echo $this_row;
+               } else {
+                       // nothing to send. empty file
+                       $msg->addError('ENROLLMENT_NONE_FOUND');
+                       header('Location: export_course_list.php');
+               }
+               exit;
+       }
+}
+if(isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php');
+       exit;
+}
+
+if(isset($_POST['done'])) {
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: index.php');
+       exit;
+}
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+
+?>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="selectform">
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('export'); ?></legend>
+       <div class="row">
+               <label><input type="checkbox" name="enrolled" value="1" id="enrolled" /><?php echo _AT('enrolled_list_includes_assistants'); ?></label><br />
+               <label><input type="checkbox" name="pending_enrollment" value="1" id="pending_enrollment" /><?php echo _AT('pending_enrollment'); ?></label><br />
+               <label><input type="checkbox" name="alumni" value="1" id="alumni" /><?php echo _AT('alumni'); ?></label>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="export" value="<?php echo _AT('export'); ?>" /> 
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php 
+
+/**
+* Creates csv file to be exported
+* @access  private
+* @param   string $line                The line ot be converted to csv
+* @return  string                      The line after conversion to csv
+* @author  Shozub Qureshi
+*/
+function quote_csv($line) {
+       $line = str_replace('"', '""', $line);
+
+       $line = str_replace("\n", '\n', $line);
+       $line = str_replace("\r", '\r', $line);
+       $line = str_replace("\x00", '\0', $line);
+
+       return '"'.$line.'"';
+}
+
+require(AT_INCLUDE_PATH.'footer.inc.php'); 
+?>
\ No newline at end of file
diff --git a/tools/enrollment/import_course_list.php b/tools/enrollment/import_course_list.php
new file mode 100644 (file)
index 0000000..a311336
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_ENROLLMENT);
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+<form enctype="multipart/form-data" action="tools/enrollment/verify_list.php" method="post">
+<input type="hidden" name="from" value="import" />
+<input type="hidden" name="MAX_FILE_SIZE" value="100000" />
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('import'); ?></legend>
+       <div class="row">
+               <p><?php echo _AT('list_import_howto'); ?></p>
+       </div>
+
+       <div class="row">
+               <label for="sep_choice"><?php echo _AT('import_sep_txt'); ?></label><br />
+               <input type="radio" name="sep_choice" id="und" value="_" checked="checked" />
+               <label for="und"><?php echo _AT('underscore'); ?></label>
+               <input type="radio" name="sep_choice" id="per" value="." />
+               <label for="per"><?php echo _AT('period'); ?></label>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="course_list"><?php echo _AT('list_import_course_list'); ?></label><br />
+               <input type="file" name="file" id="course_list" />
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('list_import_course_list');  ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/enrollment/index.php b/tools/enrollment/index.php
new file mode 100644 (file)
index 0000000..0599288
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+if (!authenticate(AT_PRIV_ENROLLMENT, AT_PRIV_RETURN)) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->printErrors('NOT_OWNER');
+       require (AT_INCLUDE_PATH.'footer.inc.php'); 
+       exit;
+}
+
+$course_id = $_SESSION['course_id'];
+
+require(AT_INCLUDE_PATH.'html/enrollment.inc.php');
+exit;
+?>
\ No newline at end of file
diff --git a/tools/enrollment/privileges.php b/tools/enrollment/privileges.php
new file mode 100644 (file)
index 0000000..0f4ad6e
--- /dev/null
@@ -0,0 +1,27 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+if (!authenticate(AT_PRIV_ADMIN, true)) {\r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+$course_id = $_SESSION['course_id'];\r
+\r
+require(AT_INCLUDE_PATH.'html/privileges.inc.php');\r
+exit;\r
+?>
\ No newline at end of file
diff --git a/tools/enrollment/verify_list.php b/tools/enrollment/verify_list.php
new file mode 100644 (file)
index 0000000..1277efd
--- /dev/null
@@ -0,0 +1,218 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_ENROLLMENT);\r
+require(AT_INCLUDE_PATH.'lib/enroll.inc.php');\r
+\r
+/************  GETTING INFO FROM CREATE/IMPORT CALLS  **********/\r
+if (isset($_POST['addmore'])) {\r
+       //$msg->addFeedback('ADDMORE');\r
+       header('Location: create_course_list.php');\r
+       exit;\r
+} else if (isset($_POST['return'])) {\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: index.php');\r
+       exit;\r
+} else if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');  \r
+       exit;\r
+} else if (isset($_POST['submit']) && !$_POST['verify']) {\r
+       //CREATE COURSE LIST!!!!!!\r
+       if ($_POST['from'] == 'create') {\r
+               if (empty($_POST['first_name1']) && empty($_POST['last_name1']) && empty($_POST['email1'])) {\r
+                       $msg->addError('INCOMPLETE');\r
+                       header('Location: ./create_course_list.php');\r
+                       exit;\r
+               } else {\r
+                       $j=1;\r
+                       while ($_POST['first_name'.$j] || $_POST['last_name'.$j] || $_POST['email'.$j]) {\r
+                               $students[] = checkUserInfo(array('fname' => $_POST['first_name'.$j], 'lname' => $_POST['last_name'.$j], 'email' => $_POST['email'.$j]));\r
+                               $j++;\r
+                       }\r
+               }\r
+       } \r
+       //IMPORT COURSE LIST!!!!!!\r
+       else if ($_POST['from'] == 'import') {\r
+               if ($_FILES['file']['size'] < 1) {\r
+                       $msg->addError('FILE_EMPTY');\r
+                       header('Location: ./import_course_list.php');\r
+                       exit;\r
+               } else {\r
+                       $fp = fopen($_FILES['file']['tmp_name'],'r');\r
+                       $line_number=0;\r
+                       while ($data = fgetcsv($fp, 100000, ',')) {\r
+                               $line_number++;\r
+                               $num_fields = count($data);\r
+                               if ($num_fields == 3) {\r
+                                       $students[] = checkUserInfo(array('fname' => $data[0], 'lname' => $data[1], 'email' => $data[2]));\r
+                               } else if ($num_fields != 1) {\r
+                                       $errors = array('INCORRECT_FILE_FORMAT', $line_number);\r
+                                       $msg->addError($errors);\r
+                                       header('Location: ./import_course_list.php');\r
+                                       exit;\r
+                               } else if (($num_fields == 1) && (trim($data[0]) != '')) {\r
+                                       $errors = array('INCORRECT_FILE_FORMAT', $line_number);\r
+                                       $msg->addError($errors);\r
+                                       header('Location: ./import_course_list.php');\r
+                                       exit;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+}\r
+/*************  INFO GATHERED  **************/\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+\r
+if ($_POST['verify']) {\r
+       for ($i=0; $i<$_POST['count']; $i++) {\r
+               $info = array('fname' => $_POST['fname'.$i], 'lname' => $_POST['lname'.$i], 'email' => $_POST['email'.$i], 'uname' => $_POST['uname'.$i], 'remove' => $_POST['remove'.$i]);\r
+               $students[] = checkUserInfo($info);\r
+\r
+               if (!empty($students[$i]['err_email']) || !empty($students[$i]['err_uname'])) {\r
+                       $still_errors = TRUE;\r
+               }\r
+       }\r
+\r
+       /**************************************************************************/\r
+       // !!!!!!STEP 3 - INSERT INTO DB !!!!!!!\r
+       if (!$still_errors && (isset($_POST['submit_unenr']) || isset($_POST['submit_enr']))) {                 \r
+\r
+               $enroll = 'y';\r
+               if (isset($_POST['submit_unenr'])) {\r
+                       $enroll = 'n';\r
+               }\r
+\r
+               add_users($students, $enroll, $_SESSION['course_id']);\r
+\r
+               $msg->printFeedbacks(); ?>\r
+\r
+               <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="finalform" />\r
+               <div class="input-form">\r
+                       <div class="row buttons">\r
+                               <input type="submit" name="addmore" value="<?php echo _AT('add_more'); ?>" />\r
+                               <input type="submit" name="return"  value="<?php echo _AT('done'); ?>" />\r
+                       </div>\r
+               </div>\r
+               </form><?php                            \r
+       }\r
+\r
+}\r
+\r
+// STEP 2 - INTERNAL VERIFICATION\r
+if ($still_errors || !isset($_POST['verify']) || isset($_POST['resubmit'])) { ?>\r
+\r
+       <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">\r
+       <input type="hidden" name="verify" value="1" />\r
+       <input type="hidden" name="count" value="<?php echo count($students); ?>" />\r
+               \r
+       <table class="data static" summary="" rules="cols">\r
+       <thead>\r
+       <tr>\r
+               <th scope="col"><?php echo _AT('status');     ?></th>\r
+               <th scope="col"><?php echo _AT('first_name'); ?></th>\r
+               <th scope="col"><?php echo _AT('last_name');  ?></th>\r
+               <th scope="col"><?php echo _AT('email');      ?></th>\r
+               <th scope="col"><?php echo _AT('login_name'); ?></th>\r
+               <th scope="col"><?php echo _AT('remove');     ?></th>\r
+       </tr>\r
+       </thead><?php\r
+\r
+       $err_count = 0;\r
+       $i=0;\r
+       if (is_array($students)) {\r
+               echo '<tbody>';\r
+               foreach ($students as $student) {\r
+                       echo '<tr><small>';\r
+                       echo '<td><span style="color: red;">';\r
+\r
+                       //give status\r
+                       if(!empty($student['err_email'])) {\r
+                               echo $student['err_email'];\r
+                       }\r
+\r
+                       if(!empty($student['err_uname'])) {\r
+                               if(!empty($student['err_email'])) {\r
+                                       echo '<br />';\r
+                               }\r
+                               echo $student['err_uname'];\r
+                       }               \r
+                       if (empty($student['err_uname']) && empty($student['err_email'])) {\r
+                                \r
+                               if ($student['remove']) {\r
+                                       echo '</span><span style="color: purple;">'._AT('removed');\r
+                               } else if ($student['err_disabled']) {\r
+                                       echo '</span><span style="color: purple;">'._AT('disabled');                                                            \r
+                               } else if (!empty($student['exists'])) {\r
+                                       echo '</span><span style="color: green;">'._AT('ok').' - '.$student['exists'];\r
+                               } else {\r
+                                       echo '</span><span style="color: green;">'._AT('ok');                                                           \r
+                               }\r
+                       } else {\r
+                               $err_count++;\r
+                       }\r
+                       echo '</span></td>';\r
+\r
+                       if (empty($student['exists'])) {\r
+                               echo '<td><input type="text" name="fname'.$i.'" value="'.$student['fname'].'" /></td>';\r
+                               echo '<td><input type="text" name="lname'.$i.'" value="'.$student['lname'].'" /></td>';\r
+                               echo '<td><input type="text" name="email'.$i.'" value="'.$student['email'].'" /></td>';         \r
+                               echo '<td><input type="text" name="uname'.$i.'" value="'.$student['uname'].'" />';      \r
+                               echo '<td><input type="checkbox" ';                                     \r
+                               echo ($student['remove'] ? 'checked="checked" value="on"' : '');                                          \r
+                               echo 'name="remove'.$i.'" />';\r
+                       } else {\r
+                               echo '<input type="hidden" name="fname'.$i.'" value="'.$student['fname'].'" />';                \r
+                               echo '<input type="hidden" name="lname'.$i.'" value="'.$student['lname'].'" />';                \r
+                               echo '<input type="hidden" name="email'.$i.'" value="'.$student['email'].'" />';                \r
+                               echo '<input type="hidden" name="uname'.$i.'" value="'.$student['uname'].'" />';                \r
+\r
+                               echo '<td>'.AT_print($student['fname'], 'members.first_name').'</td>';\r
+                               echo '<td>'.AT_print($student['lname'], 'members.last_name').'</td>';\r
+                               echo '<td>'.AT_print($student['email'], 'members.email').'</td>';\r
+                               echo '<td>'.AT_print($student['uname'], 'members.login').'</td>';\r
+                               echo '<td><input type="checkbox" ';                                     \r
+                               echo ($student['remove'] ? 'checked="checked" value="on"' : '');                                          \r
+                               echo 'name="remove'.$i.'" />';\r
+                       }\r
+                       $i++;\r
+                       echo '</tr>';\r
+               }\r
+               echo '</tbody>';\r
+       }\r
+\r
+       $dsbld = '';\r
+       if ($still_errors || $err_count>0) {\r
+               $dsbld = 'disabled="disabled"';\r
+       } ?>\r
+\r
+       <tfoot>\r
+       <tr>\r
+               <td colspan="6">\r
+                       <input type="submit" name="resubmit" value="<?php echo _AT('resubmit'); ?>" />\r
+                       <input type="submit" name="submit_enr" value="<?php echo _AT('list_add_enrolled_list'); ?>" <?php echo $dsbld; ?> />\r
+               </td>\r
+       </tr>\r
+       </tfoot>\r
+\r
+       </table>\r
+       </form><?php\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/tools/filemanager/delete.php b/tools/filemanager/delete.php
new file mode 100644 (file)
index 0000000..3826b93
--- /dev/null
@@ -0,0 +1,140 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/filemanager.inc.php');
+
+if (!authenticate(AT_PRIV_FILES,AT_PRIV_RETURN)) {
+       authenticate(AT_PRIV_CONTENT);
+}
+
+$current_path = AT_CONTENT_DIR.$_SESSION['course_id'].'/';
+
+$popup = $_REQUEST['popup'];
+$framed = $_REQUEST['framed'];
+
+if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup']);
+       exit;
+}
+
+if (isset($_POST['submit_yes'])) {
+       /* delete files and directories */
+       /* delete the file  */
+       $pathext = $_POST['pathext'];
+       if (isset($_POST['listoffiles']))  {
+               $checkbox = explode(',',$_POST['listoffiles']);
+               $count = count($checkbox);
+               $result=true;
+               for ($i=0; $i<$count; $i++) {
+                       $filename=$checkbox[$i];
+
+                       if (course_realpath($current_path . $pathext . $filename) == FALSE) {
+                               $msg->addError('FILE_NOT_DELETED');
+                               $result=false;
+                               break;
+                       } else if (!(@unlink($current_path.$pathext.$filename))) {
+                               $msg->addError('FILE_NOT_DELETED');
+                               $result=false;
+                               break;
+                       }                       
+               }
+               if ($result) 
+                       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       }
+       /* delete directory */
+       if (isset($_POST['listofdirs'])) {
+                               
+               $checkbox = explode(',',$_POST['listofdirs']);
+               $count = count($checkbox);
+               $result=true;
+               for ($i=0; $i<$count; $i++) {
+                       $filename=$checkbox[$i];
+                               
+                       if (strpos($filename, '..') !== false) {
+                               $msg->addError('UNKNOWN');
+                               $result=false;
+                               header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup']);
+                               exit;
+                       } else if (!is_dir($current_path.$pathext.$filename)) {
+                               $msg->addError(array('DIR_NOT_DELETED',$filename));
+                               $result=false;
+                               header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup']);
+                               exit;
+                       } else if (!($result = clr_dir($current_path.$pathext.$filename))) { 
+                               $msg->addError('DIR_NO_PERMISSION');
+                               $result=false;
+                               header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup']);
+                               exit;
+                       } 
+               }
+               if ($result)
+                       $msg->addFeedback('DIR_DELETED');
+       }
+       
+       header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup']);
+       exit;
+}
+
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       // find the files and directories to be deleted 
+       $total_list = explode(',', $_GET['list']);
+       $pathext = $_GET['pathext']; 
+       $popup   = $_GET['popup'];
+       $framed  = $_GET['framed'];
+
+       $count = count($total_list);
+       $countd = 0;
+       $countf = 0;
+       
+       foreach ($total_list as $list_item) {
+               if (is_dir($current_path.$pathext.$list_item)) {
+                       $_dirs[$countd]  = $list_item;
+                       $countd++;
+               } else {
+                       $_files[$countf] = $list_item;
+                       $countf++;
+               }
+       }
+                               
+       $hidden_vars['pathext'] = $pathext;
+       $hidden_vars['popup']   = $popup;
+       $hidden_vars['framed']  = $framed;
+
+       if (isset($_files)) {
+               $list_of_files = implode(',', $_files);
+               $hidden_vars['listoffiles'] = $list_of_files;
+
+               foreach ($_files as $file) {
+                       $file_list_to_print .= '<li>'.$file.'</li>';
+               }
+               $msg->addConfirm(array('FILE_DELETE', $file_list_to_print), $hidden_vars);
+       }
+               
+       if (isset($_dirs)) {
+               $list_of_dirs = implode(',', $_dirs);
+               $hidden_vars['listofdirs'] = $list_of_dirs;
+
+               foreach ($_dirs as $dir) {
+                       $dir_list_to_print .= '<li>'.$dir.'</li>';
+               }
+
+               $msg->addConfirm(array('DIR_DELETE',$dir_list_to_print), $hidden_vars);
+       }
+
+       $msg->printConfirm();
+       
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/tools/filemanager/edit.php b/tools/filemanager/edit.php
new file mode 100644 (file)
index 0000000..61c433f
--- /dev/null
@@ -0,0 +1,146 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'lib/filemanager.inc.php');\r
+\r
+\r
+if (!authenticate(AT_PRIV_FILES,AT_PRIV_RETURN)) {\r
+       authenticate(AT_PRIV_CONTENT);\r
+}\r
+\r
+$current_path = AT_CONTENT_DIR.$_SESSION['course_id'].'/';\r
+\r
+$popup  = $_REQUEST['popup'];\r
+$framed = $_REQUEST['framed'];\r
+$file    = $_REQUEST['file'];\r
+$pathext = $_REQUEST['pathext']; \r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup']);\r
+       exit;\r
+}\r
+\r
+if (isset($_POST['save'])) {\r
+       $content = str_replace("\r\n", "\n", $stripslashes($_POST['body_text']));\r
+       $file = $_POST['file'];\r
+\r
+       if (course_realpath($current_path . $pathext . $file) == FALSE) {\r
+               $msg->addError('FILE_NOT_SAVED');\r
+       } else {\r
+               if (($f = @fopen($current_path.$pathext.$file, 'w')) && (@fwrite($f, $content) !== false) && @fclose($f)) {\r
+                       $msg->addFeedback(array('FILE_SAVED', $file));\r
+                       header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup']);\r
+                       exit;\r
+               } else {\r
+                       $msg->addError('FILE_NOT_SAVED');\r
+               }\r
+       }\r
+       header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup']);\r
+       exit;\r
+}\r
+\r
+\r
+$path_parts = pathinfo($current_path.$pathext.$file);\r
+$ext = strtolower($path_parts['extension']);\r
+\r
+// open file to edit\r
+$real = realpath($current_path . $pathext . $file);\r
+\r
+if (course_realpath($current_path . $pathext . $file) == FALSE) {\r
+       // error: File does not exist\r
+       $msg->addError('FILE_NOT_EXIST');\r
+       header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup);\r
+       exit;\r
+} else if (is_dir($current_path.$pathext.$file)) {\r
+       // error: cannot edit folder\r
+       $msg->addError('BAD_FILE_TYPE');\r
+       header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup);\r
+       exit;\r
+} else if (!is_readable($current_path.$pathext.$file)) {\r
+       // error: File cannot open file\r
+       $msg->addError(array('CANNOT_OPEN_FILE', $file));\r
+       header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup);\r
+       exit;\r
+} else if (in_array($ext, $editable_file_types)) {\r
+       $_POST['body_text'] = file_get_contents($current_path.$pathext.$file);\r
+} else {\r
+       //error: bad file type\r
+       $msg->addError('BAD_FILE_TYPE');\r
+       header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup);\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+require(AT_INCLUDE_PATH.'lib/tinymce.inc.php');\r
+\r
+if (!isset($_REQUEST['setvisual']) && !isset($_REQUEST['settext'])) {\r
+       if ($_SESSION['prefs']['PREF_CONTENT_EDITOR'] == 1) {\r
+               $_POST['formatting'] = 1;\r
+               $_REQUEST['settext'] = 0;\r
+               $_REQUEST['setvisual'] = 0;\r
+\r
+       } else if ($_SESSION['prefs']['PREF_CONTENT_EDITOR'] == 2) {\r
+               $_POST['formatting'] = 1;\r
+               $_POST['settext'] = 0;\r
+               $_POST['setvisual'] = 1;\r
+\r
+       } else { // else if == 0\r
+               $_POST['formatting'] = 0;\r
+               $_REQUEST['settext'] = 0;\r
+               $_REQUEST['setvisual'] = 0;\r
+       }\r
+}\r
+if (($_POST['setvisual'] && !$_POST['settext']) || $_GET['setvisual']) {\r
+       load_editor('body_text');\r
+}\r
+\r
+\r
+?>\r
+\r
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">\r
+<input type="hidden" name="pathext" value="<?php echo $pathext; ?>" />\r
+<input type="hidden" name="framed"  value="<?php echo $framed; ?>" />\r
+<input type="hidden" name="popup"   value="<?php echo $popup; ?>" />\r
+<input type="hidden" name="file"    value="<?php echo $file; ?>" />\r
+\r
+<div class="input-form">\r
+       <div class="row">\r
+               <h3><?php echo $file; ?></h3>\r
+       </div>\r
+               <div class="row">\r
+               <?php\r
+                       if (($_POST['setvisual'] && !$_POST['settext']) || $_GET['setvisual']){\r
+                               echo '<input type="hidden" name="setvisual" value="'.$_POST['setvisual'].'" />';\r
+                               echo '<input type="submit" name="settext" value="'._AT('switch_text').'" />';\r
+                       } else {\r
+                               echo '<input type="submit" name="setvisual" value="'._AT('switch_visual').'" />';\r
+                       }\r
+               ?>\r
+       </div>\r
+       <div class="row">\r
+               <label for="body_text"><?php echo _AT('body'); ?></label><br />\r
+               <textarea  name="body_text" id="body_text" rows="25"><?php echo htmlspecialchars($_POST['body_text']); ?></textarea>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="save" value="<?php echo _AT('save'); ?>" accesskey="s" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/filemanager/index.php b/tools/filemanager/index.php
new file mode 100644 (file)
index 0000000..c4b65b7
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+
+if ((isset($_REQUEST['popup']) && $_REQUEST['popup']) && 
+       (!isset($_REQUEST['framed']) || !$_REQUEST['framed'])) {
+       $popup = TRUE;
+       $framed = FALSE;
+} else if (isset($_REQUEST['framed']) && $_REQUEST['framed'] && isset($_REQUEST['popup']) && $_REQUEST['popup']) {
+       $popup = TRUE;
+       $framed = TRUE;
+} else {
+       $popup = FALSE;
+       $framed = FALSE;
+}
+
+require('top.php');
+$_SESSION['done'] = 1;
+
+require(AT_INCLUDE_PATH.'html/filemanager_display.inc.php');
+
+closedir($dir);
+
+?>
+<script type="text/javascript">
+//<!--
+function Checkall(form){ 
+  for (var i = 0; i < form.elements.length; i++){    
+    eval("form.elements[" + i + "].checked = form.checkall.checked");  
+  } 
+}
+function openWindow(page) {
+       newWindow = window.open(page, "progWin", "width=400,height=200,toolbar=no,location=no");
+       newWindow.focus();
+}
+//-->
+</script>
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/filemanager/move.php b/tools/filemanager/move.php
new file mode 100644 (file)
index 0000000..9e9e88e
--- /dev/null
@@ -0,0 +1,196 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/filemanager.inc.php');
+
+if (!authenticate(AT_PRIV_FILES,AT_PRIV_RETURN)) {
+       authenticate(AT_PRIV_CONTENT);
+}
+
+
+$current_path = AT_CONTENT_DIR.$_SESSION['course_id'].'/';
+
+$popup = $_REQUEST['popup'];
+$framed = $_REQUEST['framed'];
+
+if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup']);
+       exit;
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_REQUEST['framed'].SEP.'popup='.$_REQUEST['popup']);
+       exit;
+}
+
+if (isset($_POST['submit_yes'])) {
+       $dest = $_POST['dest'] .'/';
+       $pathext = $_POST['pathext'];
+
+       if (isset($_POST['listofdirs'])) {
+
+               $_dirs = explode(',',$_POST['listofdirs']);
+               $count = count($_dirs);
+               
+               for ($i = 0; $i < $count; $i++) {
+                       $source = $_dirs[$i];
+                       
+                       if (course_realpath($current_path . $pathext . $source) == FALSE) {
+                               // error: File does not exist
+                               $msg->addError('DIR_NOT_EXIST');
+                               header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup);
+                               exit;
+                       }
+                       else if (course_realpath($current_path . $dest) == FALSE) {
+                               // error: File does not exist
+                               $msg->addError('UNKNOWN');
+                               header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup);
+                               exit;
+                       }
+                       else if (strpos($source, '..') !== false) {
+                               $msg->addError('UNKNOWN');
+                               header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup);
+                               exit;
+                       }       
+                       else {
+                               @rename($current_path.$pathext.$source, $current_path.$dest.$source);
+                       }
+               }
+               $msg->addFeedback('DIRS_MOVED');
+       }
+       if (isset($_POST['listoffiles'])) {
+
+               $_files = explode(',',$_POST['listoffiles']);
+               $count = count($_files);
+
+               for ($i = 0; $i < $count; $i++) {
+                       $source = $_files[$i];
+                       
+                       if (course_realpath($current_path . $pathext . $source) == FALSE) {
+                               // error: File does not exist
+                               $msg->addError('FILE_NOT_EXIST');
+                               header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup);
+                               exit;
+                       }
+                       else if (course_realpath($current_path . $dest) == FALSE) {
+                               // error: File does not exist
+                               $msg->addError('UNKNOWN');
+                               header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup);
+                               exit;
+                       }
+                       else if (strpos($source, '..') !== false) {
+                               $msg->addError('UNKNOWN');
+                               header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup);
+                               exit;
+                       }       
+                       else {
+                               @rename($current_path.$pathext.$source, $current_path.$dest.$source);
+                       }
+               }
+               $msg->addFeedback('MOVED_FILES');
+       }
+       header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup']);
+       exit;
+}
+
+if (isset($_POST['dir_chosen'])) {
+       $hidden_vars['framed']  = $_POST['framed'];
+       $hidden_vars['popup']   = $_POST['popup'];
+       $hidden_vars['pathext'] = $_POST['pathext'];
+       $hidden_vars['dest']    = $_POST['dir_name'];
+
+       if (isset($_POST['files'])) {
+               $list_of_files = implode(',', $_POST['files']);
+               $hidden_vars['listoffiles'] = $list_of_files;
+               $msg->addConfirm(array('FILE_MOVE', $list_of_files, $_POST['dir_name']), $hidden_vars);
+       }
+       if (isset($_POST['dirs'])) {
+               $list_of_dirs = implode(',', $_POST['dirs']);
+               $hidden_vars['listoffiles'] = $list_of_dirs;
+               $msg->addConfirm(array('DIR_MOVE', $list_of_dirs, $_POST['dir_name']), $hidden_vars);
+       }
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->printConfirm();
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+} 
+else {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       
+       $tree = AT_CONTENT_DIR.$_SESSION['course_id'].'/';
+       $file    = $_GET['file'];
+       $pathext = $_GET['pathext']; 
+       $popup   = $_GET['popup'];
+       $framed  = $_GET['framed'];
+
+       /* find the files and directories to be copied */
+       $total_list = explode(',', $_GET['list']);
+
+       $count = count($total_list);
+       $countd = 0;
+       $countf = 0;
+       for ($i=0; $i<$count; $i++) {
+               if (is_dir($current_path.$pathext.$total_list[$i])) {
+                       $_dirs[$countd] = $total_list[$i];
+                       $hidden_dirs  .= '<input type="hidden" name="dirs['.$countd.']"   value="'.$_dirs[$countd].'" />';
+                       $countd++;
+               } else {
+                       $_files[$countf] = $total_list[$i];
+                       $hidden_files .= '<input type="hidden" name="files['.$countf.']" value="'.$_files[$countf].'" />';
+                       $countf++;
+               }
+       }
+?>
+
+<form name="move_form" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<div class="input-form">
+       <div class="row">
+               <p><?php echo _AT('select_directory'); ?></p>
+       </div>
+       
+       <div class="row">
+               <ul>
+                       <li class="folders"><label><input type="radio" name="dir_name" value=""<?php
+                               if ($pathext == '') {
+                                       echo ' checked="checked"';
+                                       $here = ' ' . _AT('current_location');
+                               } 
+                               echo '/>Home ' .$here.'</label>';
+                       
+                               echo display_tree($current_path, '', $pathext);
+                       ?></li>
+               </ul>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="dir_chosen" value="<?php echo _AT('move'); ?>" accesskey="s" /> 
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+</div>
+
+<input type="hidden" name="pathext" value="<?php echo $pathext; ?>" />
+<input type="hidden" name="framed" value="<?php echo $framed; ?>" />
+<input type="hidden" name="popup" value="<?php echo $popup; ?>" />
+<?php
+       echo $hidden_dirs;
+       echo $hidden_files;
+?>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php');
+}
+?>
\ No newline at end of file
diff --git a/tools/filemanager/new.php b/tools/filemanager/new.php
new file mode 100644 (file)
index 0000000..cb0242c
--- /dev/null
@@ -0,0 +1,249 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/filemanager.inc.php');
+
+if (!authenticate(AT_PRIV_FILES,AT_PRIV_RETURN)) {
+       authenticate(AT_PRIV_CONTENT);
+}
+
+
+$current_path = AT_CONTENT_DIR.$_SESSION['course_id'].'/';
+
+$popup  = $_REQUEST['popup'];
+$framed = $_REQUEST['framed'];
+
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup']);
+       exit;
+}
+
+if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup']);
+       exit;
+}
+
+if (isset($_POST['submit_yes'])) {
+       $filename = preg_replace("{[^a-zA-Z0-9_]}","_", trim($_POST['filename']));
+       $pathext  = $_POST['pathext'];
+
+       /* only html or txt extensions allowed */
+       if ($_POST['extension'] == 'html') {
+               $extension = 'html';
+       } else {
+               $extension = 'txt';
+       }
+       
+       if (course_realpath($current_path . $pathext . $filename.'.'.$extension) == FALSE) {
+               $msg->addError('FILE_NOT_SAVED');
+               /* take user to home page to avoid unspecified error warning */
+               header('Location: index.php?pathext='.SEP.'framed='.$framed.SEP.'popup='.$popup);
+               exit;
+       }
+
+       if (($f = @fopen($current_path.$pathext.$filename.'.'.$extension,'w')) && @fwrite($f, stripslashes($_POST['body_text'])) !== FALSE && @fclose($f)){
+               $msg->addFeedback('FILE_OVERWRITE');
+       } else {
+               $msg->addError('CANNOT_OVERWRITE_FILE');
+       }
+       unset($_POST['newfile']);
+       header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup);
+       exit;
+}
+
+if (isset($_POST['savenewfile'])) {
+
+       if (isset($_POST['filename']) && ($_POST['filename'] != "")) {
+               $filename     = preg_replace("{[^a-zA-Z0-9_]}","_", trim($_POST['filename']));
+               $pathext      = $_POST['pathext'];
+               $current_path = AT_CONTENT_DIR.$_SESSION['course_id'].'/';
+
+               /* only html or txt extensions allowed */
+               if ($_POST['extension'] == 'html') {
+                       $extension = 'html';
+                       $head_html = "<html>\n<head>\n<title>".$_POST['filename']."</title>\n<head>\n<body>";
+                       $foot_html ="\n</body>\n</html>";
+               } else {
+                       $extension = 'txt';
+               }
+
+               if (!@file_exists($current_path.$pathext.$filename.'.'.$extension)) {
+                       $content = str_replace("\r\n", "\n", $head_html.$_POST['body_text'].$foot_html);
+                       
+                       if (course_realpath($current_path . $pathext . $filename.'.'.$extension) == FALSE) {
+                               $msg->addError('FILE_NOT_SAVED');
+                               /* take user to home page to avoid unspecified error warning */
+                               header('Location: index.php?pathext='.SEP.'framed='.$framed.SEP.'popup='.$popup);
+                               exit;
+                       }
+
+                       if (($f = fopen($current_path.$pathext.$filename.'.'.$extension, 'w')) && (@fwrite($f, stripslashes($content)) !== false)  && (@fclose($f))) {
+                               $msg->addFeedback(array('FILE_SAVED', $filename.'.'.$extension));
+                               header('Location: index.php?pathext='.urlencode($_POST['pathext']).SEP.'popup='.$_POST['popup']);
+                               exit;
+                       } else {
+                               $msg->addError('FILE_NOT_SAVED');
+                               header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup);
+                               exit;
+                       }
+               }
+               else {
+                       require(AT_INCLUDE_PATH.'header.inc.php');
+                       $pathext = $_POST['pathext']; 
+                       $popup   = $_POST['popup'];
+
+                       $_POST['newfile'] = "new";
+
+                       $hidden_vars['pathext']   = $pathext;
+                       $hidden_vars['filename']  = $filename;
+                       $hidden_vars['extension'] = $extension;
+                       $hidden_vars['body_text'] = $_POST['body_text'];
+
+                       $hidden_vars['popup']  = $popup;
+                       $hidden_vars['framed'] = $framed;
+
+                       $msg->addConfirm(array('FILE_EXISTS', $filename.'.'.$extension), $hidden_vars);
+                       $msg->printConfirm();
+
+                       require(AT_INCLUDE_PATH.'footer.inc.php');
+                       exit;
+               }
+       } else {
+               $msg->addError(array('EMPTY_FIELDS', _AT('file_name')));
+       }
+}
+
+$onload="on_load()";
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+require(AT_INCLUDE_PATH.'lib/tinymce.inc.php');
+
+if (!isset($_REQUEST['setvisual']) && !isset($_REQUEST['settext'])) {
+       if ($_SESSION['prefs']['PREF_CONTENT_EDITOR'] == 1) {
+               $_POST['formatting'] = 1;
+               $_REQUEST['settext'] = 0;
+               $_REQUEST['setvisual'] = 0;
+
+       } else if ($_SESSION['prefs']['PREF_CONTENT_EDITOR'] == 2) {
+               $_POST['formatting'] = 1;
+               $_POST['settext'] = 0;
+               $_POST['setvisual'] = 1;
+
+       } else { // else if == 0
+               $_POST['formatting'] = 0;
+               $_REQUEST['settext'] = 0;
+               $_REQUEST['setvisual'] = 0;
+       }
+}
+
+// load tinymce library
+load_editor(false, "none");
+
+$pathext = $_GET['pathext']; 
+$popup   = $_GET['popup'];
+
+$msg->printAll();
+if (!$_POST['extension']) {
+       $_POST['extension'] = 'txt';
+       $_POST['formatting'] = 0;
+}else if($_POST['extension'] == "html"){
+       $_POST['formatting'] = 1;
+}
+
+?>
+       <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+       <input type="hidden" name="pathext" value="<?php echo $_REQUEST['pathext'] ?>" />
+       <input type="hidden" name="popup" value="<?php echo $popup; ?>" />
+
+       <div class="input-form">        
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('create_new_file'); ?></legend>
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="ctitle"><?php echo _AT('file_name');  ?></label><br />
+                       <input type="text" name="filename" id="ctitle" size="40" <?php if (isset($_POST['filename'])) echo 'value="'.$_POST['filename'].'"'?> />
+               </div>
+
+               <div class="row">
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><?php echo _AT('type'); ?><br />
+                       <input type="radio" name="extension" value="txt" id="text" <?php if ($_POST['formatting'] == 0) { echo 'checked="checked"'; } ?> onclick="javascript: document.form.setvisual.disabled=true;" <?php if ($_POST['setvisual'] && !$_POST['settext']) { echo 'disabled="disabled"'; } ?> />
+                       <label for="text"><?php echo _AT('plain_text'); ?></label>
+       
+                       , <input type="radio" name="extension" value="html" id="html" <?php if ($_POST['formatting'] ==1 || $_POST['setvisual']) { echo 'checked="checked"'; } ?> onclick="javascript: document.form.setvisual.disabled=false;"/>
+                       <label for="html"><?php echo _AT('html'); ?></label>
+       
+                       <input type="hidden" name="setvisual" value="<?php echo $_POST['setvisual']; ?>" />
+                       <input type="hidden" name="settext" value="<?php echo $_POST['settext']; ?>" />
+                       <input type="button" name="setvisualbutton" value="<?php echo _AT('switch_visual'); ?>" onClick="switch_body_editor()" />
+               </div>
+       
+               <div class="row">
+                       <label for="body_text"><?php echo _AT('body');  ?></label><br />
+                       <textarea name="body_text" id="body_text" rows="25"><?php echo ContentManager::cleanOutput($_POST['body_text']); ?></textarea>
+               </div>
+       
+               <div class="row buttons">
+                       <input type="submit" name="savenewfile" value="<?php echo _AT('save'); ?>" accesskey="s" />
+                       <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>"  />             
+               </div>
+       </fieldset>
+       </div>
+       </form>
+
+       <script type="text/javascript" language="javascript">
+       //<!--
+       function on_load()
+       {
+               if (document.getElementById("text").checked)
+                       document.form.setvisualbutton.disabled = true;
+                       
+               if (document.form.setvisual.value==1)
+               {
+                       tinyMCE.execCommand('mceAddControl', false, 'body_text');
+                       document.form.extension[0].disabled = "disabled";
+                       document.form.setvisualbutton.value = "<?php echo _AT('switch_text'); ?>";
+               }
+               else
+               {
+                       document.form.setvisualbutton.value = "<?php echo _AT('switch_visual'); ?>";
+               }
+       }
+       
+       // switch between text, visual editor for "body text"
+       function switch_body_editor()
+       {
+               if (document.form.setvisualbutton.value=="<?php echo _AT('switch_visual'); ?>")
+               {
+                       tinyMCE.execCommand('mceAddControl', false, 'body_text');
+                       document.form.setvisual.value=1;
+                       document.form.settext.value=0;
+                       document.form.extension[0].disabled = "disabled";
+                       document.form.setvisualbutton.value = "<?php echo _AT('switch_text'); ?>";
+               }
+               else
+               {
+                       tinyMCE.execCommand('mceRemoveControl', false, 'body_text');
+                       document.form.setvisual.value=0;
+                       document.form.settext.value=1;
+                       document.form.extension[0].disabled = "";
+                       document.form.setvisualbutton.value = "<?php echo _AT('switch_visual'); ?>";
+               }
+       }
+       //-->
+       </script>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/filemanager/preview.php b/tools/filemanager/preview.php
new file mode 100644 (file)
index 0000000..6aea81a
--- /dev/null
@@ -0,0 +1,46 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {\r
+       $get_file = $_base_path . 'get.php/';\r
+       $file = 'b64:'.base64_encode($_GET['file']);\r
+} else {\r
+       $get_file = $_base_path . 'content/' . $_SESSION['course_id'] . '/';\r
+       $file = $_GET['file'];\r
+}\r
+\r
+?>\r
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN" "http://www.w3.org/TR/REC-html40/frameset.dtd" />\r
+<html lang="<?php echo $myLang->getCode(); ?>">\r
+<head>\r
+       <title><?php echo _AT('file_manager_frame'); ?></title>\r
+       <meta http-equiv="Content-Type" content="text/html; <?php echo $myLang->getCharacterSet(); ?>" />\r
+</head>\r
+\r
+<frameset rows="50,*">\r
+\r
+<frame src="preview_top.php?file=<?php echo $file.SEP.'pathext='. $_GET['pathext'] . SEP . 'popup=' . $_GET['popup']; ?>" scrolling="no" marginwidth="0" marginheight="0" />\r
+<frame src="<?php echo $get_file; ?><?php echo $file; ?>" />\r
+\r
+<noframes>\r
+  <p><?php echo _AT('frame_contains'); ?><br />\r
+  * <a href="tools/file_manager.php"><?php echo _AT('file_manager'); ?></a>\r
+  </p>\r
+</noframes>\r
+\r
+</frameset>\r
+</html>
\ No newline at end of file
diff --git a/tools/filemanager/preview_top.php b/tools/filemanager/preview_top.php
new file mode 100644 (file)
index 0000000..5d44ff9
--- /dev/null
@@ -0,0 +1,44 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {\r
+       $get_file = AT_BASE_HREF.'get.php/';\r
+} else {\r
+       $get_file = AT_BASE_HREF.'content/' . $_SESSION['course_id'] . '/';\r
+}\r
+\r
+?>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" />\r
+<html lang="<?php echo $myLang->getCode(); ?>">\r
+<head>\r
+       <title><?php echo _AT('file_manager_frame'); ?></title>\r
+       <meta http-equiv="Content-Type" content="text/html; <?php echo $myLang->getCharacterSet(); ?>" />\r
+</head>\r
+\r
+<body>\r
+<p align="bottom">\r
+\r
+<a href="index.php?framed=<?php echo SEP; ?>popup=<?php echo SEP; ?>pathext=<?php echo $_GET['pathext'].SEP . 'popup=' . $_GET['popup'] . SEP . 'framed=' . $_GET['framed']; ?>" target="_top"><?php echo _AT('return_file_manager'); ?></a> \r
+<?php if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE): ?>\r
+        | \r
+       <a href="<?php echo $get_file; ?>@/<?php echo $_GET['file']; ?>" target="_top"><?php echo _AT('download_file'); ?></a>\r
+<?php endif; ?> |\r
+<a href="<?php echo $get_file; ?><?php echo $_GET['file']; ?>" target="_top"><?php echo _AT('remove_frame'); ?></a>\r
+</p>\r
+\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/tools/filemanager/rename.php b/tools/filemanager/rename.php
new file mode 100644 (file)
index 0000000..9705a84
--- /dev/null
@@ -0,0 +1,100 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/filemanager.inc.php');
+
+if (!authenticate(AT_PRIV_FILES,AT_PRIV_RETURN)) {
+       authenticate(AT_PRIV_CONTENT);
+}
+
+$current_path = AT_CONTENT_DIR.$_SESSION['course_id'].'/';
+
+$popup = $_REQUEST['popup'];
+$framed = $_REQUEST['framed'];
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup']);
+       exit;
+}
+
+if (isset($_POST['rename_action'])) {
+
+       $_POST['new_name'] = trim($_POST['new_name']);
+       $_POST['new_name'] = str_replace(' ', '_', $_POST['new_name']);
+       $_POST['new_name'] = str_replace(array(' ', '/', '\\', ':', '*', '?', '"', '<', '>', '|', '\''), '', $_POST['new_name']);
+
+       $_POST['oldname'] = trim($_POST['oldname']);
+       $_POST['oldname'] = str_replace(' ', '_', $_POST['oldname']);
+       $_POST['oldname'] = str_replace(array(' ', '/', '\\', ':', '*', '?', '"', '<', '>', '|', '\''), '', $_POST['oldname']);
+
+       $path_parts_new = pathinfo($_POST['new_name']);
+       $ext_new = $path_parts_new['extension'];
+       $pathext = $_POST['pathext'];
+
+       /* check if this file extension is allowed: */
+       /* $IllegalExtentions is defined in ./include/config.inc.php */
+       if (in_array($ext_new, $IllegalExtentions)) {
+               $errors = array('FILE_ILLEGAL', $ext_new);
+               $msg->addError($errors);
+       }
+       else if ($current_path.$pathext.$_POST['new_name'] == $current_path.$pathext.$_POST['oldname']) {
+               //do nothing
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: index.php?pathext='.urlencode($_POST['pathext']).SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup']);
+               exit;
+       }
+
+       //make sure new file is inside content directory
+       else if (course_realpath($current_path . $pathext . $_POST['new_name']) == FALSE) {
+               $msg->addError('CANNOT_RENAME');
+       }       
+       else if (course_realpath($current_path . $pathext . $_POST['oldname']) == FALSE) {
+               $msg->addError('CANNOT_RENAME');
+       }
+       else if (file_exists($current_path . $pathext . $_POST['new_name'])) {
+               $msg->addError('CANNOT_RENAME');
+       }
+       else {
+               @rename($current_path.$pathext.$_POST['oldname'], $current_path.$pathext.$_POST['new_name']);
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: index.php?pathext='.urlencode($_POST['pathext']).SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup']);
+               exit;
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+<form name="rename" action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
+<input type="hidden" name="pathext" value="<?php echo $_REQUEST['pathext']; ?>" />
+<input type="hidden" name="oldname" value="<?php echo $_REQUEST['oldname']; ?>" />
+<input type="hidden" name="framed" value="<?php echo $_REQUEST['framed']; ?>" />
+<input type="hidden" name="popup" value="<?php echo $_REQUEST['popup']; ?>" />
+
+<div class="input-form">
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div>
+               <label for="new"><?php echo _AT('new_name'); ?></label><br />
+               <?php echo $_GET['pathext']; ?><input type="text" name="new_name" id="new" value="<?php echo $_REQUEST['oldname']; ?>" size="30" />
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="rename_action" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/filemanager/top.php b/tools/filemanager/top.php
new file mode 100644 (file)
index 0000000..73b518b
--- /dev/null
@@ -0,0 +1,194 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/filemanager.inc.php');
+
+if (!$_GET['f']) {
+       $_SESSION['done'] = 0;
+}
+if (!authenticate(AT_PRIV_FILES,AT_PRIV_RETURN)) {
+       authenticate(AT_PRIV_CONTENT);
+}
+
+
+$current_path = AT_CONTENT_DIR.$_SESSION['course_id'].'/';
+
+if (isset($_POST['rename'])) {
+       if (!is_array($_POST['check'])) {
+               // error: you must select a file/dir to rename
+               $msg->addError('NO_FILE_SELECT');
+       } else if (count($_POST['check']) != 1) {
+               // error: you must select one file/dir to rename
+               $msg->addError('NO_ITEM_SELECTED');
+       } else {
+               header('Location: rename.php?pathext='.urlencode($_POST['pathext']).SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'oldname='.urlencode($_POST['check'][0]));
+               exit;
+       }
+} else if (isset($_POST['edit'])) {
+       if (!isset($_POST['check'][0])) {
+               // error: you must select a file/dir 
+               $msg->addError('NO_FILE_SELECT');
+       } else if (count($_POST['check']) != 1) {
+               // error: you must select one file/dir to rename
+               $msg->addError('NO_ITEM_SELECTED');
+       } else {
+               $file = $_POST['check'][0];
+               header('Location: edit.php?pathext='.urlencode($_POST['pathext']).SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'file=' . $file);
+               exit;
+       }
+} else if (isset($_POST['delete'])) {
+       
+       if (!is_array($_POST['check'])) {
+               $msg->addError('NO_FILE_SELECT');
+       } else {
+
+               $list = implode(',', $_POST['check']);
+               header('Location: delete.php?pathext=' . urlencode($_POST['pathext']) . SEP . 'framed=' . $framed . SEP . 'popup=' . $popup . SEP . 'list=' . urlencode($list));
+               exit;
+       }
+} else if (isset($_POST['move'])) {
+
+       if (!is_array($_POST['check'])) {
+               $msg->addError('NO_FILE_SELECT');
+       } else {
+
+               $list = implode(',', $_POST['check']);          
+               header('Location: move.php?pathext='.urlencode($_POST['pathext']).SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'list='.urlencode($list));
+               exit;
+       }
+}
+
+$MakeDirOn = true;
+
+/* get this courses MaxQuota and MaxFileSize: */
+$sql   = "SELECT max_quota, max_file_size FROM ".TABLE_PREFIX."courses WHERE course_id=$_SESSION[course_id]";
+$result = mysql_query($sql, $db);
+$row   = mysql_fetch_array($result);
+$my_MaxCourseSize      = $row['max_quota'];
+$my_MaxFileSize                = $row['max_file_size'];
+
+if ($my_MaxCourseSize == AT_COURSESIZE_DEFAULT) {
+       $my_MaxCourseSize = $MaxCourseSize;
+}
+if ($my_MaxFileSize == AT_FILESIZE_DEFAULT) {
+       $my_MaxFileSize = $MaxFileSize;
+} else if ($my_MaxFileSize == AT_FILESIZE_SYSTEM_MAX) {
+       $my_MaxFileSize = megabytes_to_bytes(substr(ini_get('upload_max_filesize'), 0, -1));
+}
+
+$MaxSubDirs  = 5;
+$MaxDirDepth = 10;
+
+if ($_GET['pathext'] != '') {
+       $pathext = urldecode($_GET['pathext']);
+} else if ($_POST['pathext'] != '') {
+       $pathext = $_POST['pathext'];
+}
+
+if (strpos($pathext, '..') !== false) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->printErrors('UNKNOWN');   
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+if($_GET['back'] == 1) {
+       $pathext  = substr($pathext, 0, -1);
+       $slashpos = strrpos($pathext, '/');
+       if($slashpos == 0) {
+               $pathext = '';
+       } else {
+               $pathext = substr($pathext, 0, ($slashpos+1));
+       }
+
+}
+
+$start_at = 2;
+/* remove the forward or backwards slash from the path */
+$newpath = $current_path;
+$depth = substr_count($pathext, '/');
+
+if ($pathext != '') {
+       $bits = explode('/', $pathext);
+       foreach ($bits as $bit) {
+               if ($bit != '') {
+                       $bit_path .= $bit;
+
+                       $_section[$start_at][0] = $bit;
+                       $_section[$start_at][1] = 'tools/filemanager/index.php?pathext=' . urlencode($bit_path) . SEP . 'popup=' . $popup . SEP . 'framed=' . $framed;
+
+                       $start_at++;
+               }
+       }
+       $bit_path = "";
+       $bit = "";
+}
+
+/* if upload successful, close the window */
+if ($f) {
+       $onload = 'closeWindow(\'progWin\');';
+}
+
+/* make new directory */
+if ($_POST['mkdir_value'] && ($depth < $MaxDirDepth) ) {
+       $_POST['dirname'] = trim($_POST['dirname']);
+
+       /* anything else should be okay, since we're on *nix..hopefully */
+       $_POST['dirname'] = ereg_replace('[^a-zA-Z0-9._]', '', $_POST['dirname']);
+
+       if ($_POST['dirname'] == '') {
+               $msg->addError(array('FOLDER_NOT_CREATED', $_POST['dirname'] ));
+       } 
+       else if (strpos($_POST['dirname'], '..') !== false) {
+               $msg->addError('BAD_FOLDER_NAME');
+       }       
+       else {
+               $result = @mkdir($current_path.$pathext.$_POST['dirname'], 0700);
+               if($result == 0) {
+                       $msg->addError(array('FOLDER_NOT_CREATED', $_POST['dirname'] ));
+               }
+               else {
+                       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               }
+       }
+}
+
+$newpath = substr($current_path.$pathext, 0, -1);
+
+/* open the directory */
+if (!($dir = @opendir($newpath))) {
+       if (isset($_GET['create']) && ($newpath.'/' == $current_path)) {
+               @mkdir($newpath);
+               if (!($dir = @opendir($newpath))) {
+                       require(AT_INCLUDE_PATH.'header.inc.php');
+                       $msg->printErrors('CANNOT_CREATE_DIR');                 
+                       require(AT_INCLUDE_PATH.'footer.inc.php');
+                       exit;
+               } else {
+                       $msg->addFeedback('CONTENT_DIR_CREATED');
+               }
+       } else {
+               require(AT_INCLUDE_PATH.'header.inc.php');
+
+               $msg->printErrors('CANNOT_OPEN_DIR');
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
\ No newline at end of file
diff --git a/tools/filemanager/upload.php b/tools/filemanager/upload.php
new file mode 100644 (file)
index 0000000..423af53
--- /dev/null
@@ -0,0 +1,146 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/filemanager.inc.php');
+
+if (!authenticate(AT_PRIV_FILES,AT_PRIV_RETURN)) {
+       authenticate(AT_PRIV_CONTENT);
+}
+
+$_SESSION['done'] = 1;
+$popup = $_REQUEST['popup'];
+$framed = $_REQUEST['framed'];
+
+/* get this courses MaxQuota and MaxFileSize: */
+$sql   = "SELECT max_quota, max_file_size FROM ".TABLE_PREFIX."courses WHERE course_id=$_SESSION[course_id]";
+$result = mysql_query($sql, $db);
+$row   = mysql_fetch_array($result);
+$my_MaxCourseSize      = $row['max_quota'];
+$my_MaxFileSize        = $row['max_file_size'];
+
+       if ($my_MaxCourseSize == AT_COURSESIZE_DEFAULT) {
+               $my_MaxCourseSize = $MaxCourseSize;
+       }
+       if ($my_MaxFileSize == AT_FILESIZE_DEFAULT) {
+               $my_MaxFileSize = $MaxFileSize;
+       } else if ($my_MaxFileSize == AT_FILESIZE_SYSTEM_MAX) {
+               $my_MaxFileSize = megabytes_to_bytes(substr(ini_get('upload_max_filesize'), 0, -1));
+       }
+
+$path = AT_CONTENT_DIR . $_SESSION['course_id'].'/'.$_POST['pathext'];
+
+if (isset($_POST['submit'])) {
+
+       if($_FILES['uploadedfile']['name'])     {
+
+               $_FILES['uploadedfile']['name'] = trim($_FILES['uploadedfile']['name']);
+               $_FILES['uploadedfile']['name'] = str_replace(' ', '_', $_FILES['uploadedfile']['name']);
+
+               $path_parts = pathinfo($_FILES['uploadedfile']['name']);
+               $ext = $path_parts['extension'];
+
+               /* check if this file extension is allowed: */
+               /* $IllegalExtentions is defined in ./include/config.inc.php */
+               if (in_array($ext, $IllegalExtentions)) {
+                       $errors = array('FILE_ILLEGAL', $ext);
+                       $msg->addError($errors);
+                       header('Location: index.php?pathext='.$_POST['pathext']);
+                       exit;
+               }
+
+               /* also have to handle the 'application/x-zip-compressed'  case */
+               if (   ($_FILES['uploadedfile']['type'] == 'application/x-zip-compressed')
+                       || ($_FILES['uploadedfile']['type'] == 'application/zip')
+                       || ($_FILES['uploadedfile']['type'] == 'application/x-zip')){
+                       $is_zip = true;                                         
+               }
+
+       
+               /* anything else should be okay, since we're on *nix.. hopefully */
+               $_FILES['uploadedfile']['name'] = str_replace(array(' ', '/', '\\', ':', '*', '?', '"', '<', '>', '|', '\''), '', $_FILES['uploadedfile']['name']);
+
+
+               /* if the file size is within allowed limits */
+               if( ($_FILES['uploadedfile']['size'] > 0) && ($_FILES['uploadedfile']['size'] <= $my_MaxFileSize) ) {
+
+                       /* if adding the file will not exceed the maximum allowed total */
+                       $course_total = dirsize($path);
+
+                       if ((($course_total + $_FILES['uploadedfile']['size']) <= ($my_MaxCourseSize + $MaxCourseFloat)) || ($my_MaxCourseSize == AT_COURSESIZE_UNLIMITED)) {
+
+                               /* check if this file exists first */
+                               if (file_exists($path.$_FILES['uploadedfile']['name'])) {
+                                       /* this file already exists, so we want to prompt for override */
+
+                                       /* save it somewhere else, temporarily first                    */
+                                       /* file_name.time ? */
+                                       $_FILES['uploadedfile']['name'] = substr(time(), -4).'.'.$_FILES['uploadedfile']['name'];
+
+                                       $f = array('FILE_EXISTS',
+                                                                       substr($_FILES['uploadedfile']['name'], 5), 
+                                                                       $_FILES['uploadedfile']['name'],
+                                                                       $_POST['pathext'],
+                                                                       $_GET['popup'],
+                                                                       SEP);
+                                       $msg->addFeedback($f);
+                               }
+
+                               /* copy the file in the directory */
+                               $result = move_uploaded_file( $_FILES['uploadedfile']['tmp_name'], $path.$_FILES['uploadedfile']['name'] );
+
+                               if (!$result) {
+                                       require(AT_INCLUDE_PATH.'header.inc.php');
+                                       $msg->printErrors('FILE_NOT_SAVED');
+                                       echo '<a href="tools/filemanager/index.php?pathext=' . $_POST['pathext'] . SEP . 'popup=' . $_GET['popup'] . '">' . _AT('back') . '</a>';
+                                       require(AT_INCLUDE_PATH.'footer.inc.php');
+                                       exit;
+                               } else {
+                                       if ($is_zip) {
+                                               $f = array('FILE_UPLOADED_ZIP',
+                                                                               urlencode($_POST['pathext']), 
+                                                                               urlencode($_FILES['uploadedfile']['name']), 
+                                                                               $_GET['popup'],
+                                                                               SEP);
+                                               $msg->addFeedback($f);
+                                               
+                                               header('Location: index.php?pathext=' . $_POST['pathext'] . SEP . 'popup=' . $_GET['popup']);
+                                               exit;
+                                       } /* else */
+
+                                       $msg->addFeedback('FILE_UPLOADED');
+
+                                       header('Location: index.php?pathext='.$_POST['pathext'].SEP.'popup='.$_GET['popup']);
+                                       exit;
+                               }
+                       } else {
+                               $msg->addError(array('MAX_STORAGE_EXCEEDED', get_human_size($my_MaxCourseSize)));
+                               header('Location: index.php?pathext='.$_POST['pathext'].SEP.'popup='.$_GET['popup']);
+                               exit;
+                       }
+               } else {
+                       $msg->addError(array('FILE_TOO_BIG', get_human_size($my_MaxFileSize)));
+                       header('Location: index.php?pathext='.$_POST['pathext'].SEP.'popup='.$_GET['popup']);
+                       exit;
+               }
+       } else {
+               $msg->addError('FILE_NOT_SELECTED');
+               header('Location: index.php?pathext='.$_POST['pathext'].SEP.'popup='.$_GET['popup']);
+               exit;
+       }
+}
+
+
+?>
\ No newline at end of file
diff --git a/tools/filemanager/zip.php b/tools/filemanager/zip.php
new file mode 100644 (file)
index 0000000..6280766
--- /dev/null
@@ -0,0 +1,291 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+$page = 'file_manager';
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'classes/pclzip.lib.php');
+require(AT_INCLUDE_PATH.'lib/filemanager.inc.php');
+
+if (!authenticate(AT_PRIV_FILES,AT_PRIV_RETURN)) {
+       authenticate(AT_PRIV_CONTENT);
+}
+
+
+$popup = $_REQUEST['popup'];
+$framed = $_REQUEST['framed'];
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php?pathext='.$_POST['pathext'].SEP.'popup='.$_POST['popup'].SEP.'framed='.$_POST['framed']);
+       exit;
+}
+
+       $path = AT_CONTENT_DIR . $_SESSION['course_id'].'/';
+
+       if ($_REQUEST['pathext'] != '') {
+               $pathext = $_REQUEST['pathext'];
+       }
+       if ($_REQUEST['file'] != '') {
+               $file = $_REQUEST['file'];
+       }
+
+       if (strpos($file, '..') !== false) {
+               require(AT_INCLUDE_PATH.'header.inc.php');
+               $msg->printErrors('UNKNOWN');
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+
+       $path_parts = pathinfo($pathext.$file);
+
+       $temp_name = substr($file, 0, -strlen('.'.$path_parts['extension']));
+
+       $zip = new PclZip($path.$pathext.$file);
+
+       if (($list = $zip->listContent()) == 0) {
+               die("Error : ".$zip->errorInfo(true));
+       }
+
+/*****************************************************************/
+       $totalBytes = 0;
+       $translated_file_names = array();
+
+       for ($i=0; $i<sizeof($list); $i++) {
+               $path_parts = pathinfo($list[$i]['stored_filename']);
+               if ($path_parts['dirname'] == '.') {
+                       $path_parts['dirname'] = '';
+               } else {
+                       $path_parts['dirname'] .= '/';
+               }
+               $ext = $path_parts['extension'];
+
+               $is_dir = false;
+               if($list[$i]['folder']) {
+
+                       $filename = $list[$i]['stored_filename'];
+                       $fileicon = '<img src="images/folder.gif" alt="'._AT('folder').'" />';
+
+                       $is_dir = true;
+
+               } else if ($ext == 'zip') {
+
+                       $totalBytes += $list[$i]['size'];
+                       $filename = $list[$i]['stored_filename'];
+                       $fileicon = '<img src="images/icon-zip.gif" alt="'._AT('zip_archive').'" height="16" width="16" border="0" />';
+
+               } else {
+                       $totalBytes += $list[$i]['size'];
+                       $filename = $list[$i]['stored_filename'];
+                       $fileicon = '<img src="images/icon_minipost.gif" alt="'._AT('file').'" height="11" width="16" />';
+               }
+               
+               if ($is_dir) {
+                       $dirs[strtolower($filename)] .= '<tr>
+                               <td>'.$filename.'</td>';
+
+                               $dirs[strtolower($filename)] .= '<td class="row1" align="right">'.get_human_size($list[$i]['size']).' </td>';
+                               $dirs[strtolower($filename)] .= '<td class="row1">&nbsp;';
+                               
+                               $dirs[strtolower($filename)] .= AT_date(_AT('filemanager_date_format'), $filedata[10], AT_DATE_UNIX_TIMESTAMP);
+                                       
+                               $dirs[strtolower($filename)] .= '&nbsp;</td>';
+
+                               $dirs[strtolower($filename)] .= '</tr>';
+               } else {
+
+                       $files[strtolower($filename)] .= '<tr>
+                               <td>';
+
+                               if (in_array($ext, $IllegalExtentions)) {
+                                       $files[strtolower($filename)] .=  '<span style="text-decoration: line-through;" title="'._AT('illegal_file').'">'.$filename.'</span>';
+                               } else {
+                                       $files[strtolower($filename)] .= $filename;
+                                       
+                                       $trans_name = str_replace(' ', '_', $path_parts['basename']);
+                                       $trans_name = preg_replace("/[^A-Za-z0-9._\-]/", '', $trans_name);
+
+                                       if (in_array($path_parts['dirname'].$trans_name, $translated_file_names)) {
+                                               $trans_count = 2;
+                                               while (in_array($trans_name, $translated_file_names)) {
+                                                       $part = substr($trans_name, 0, -strlen($ext)- 1 - (2*($trans_count-2)));
+                                                       $trans_name = $part.'_'.$trans_count.'.'.$ext;
+                                                       $trans_count++;
+                                                       if ($trans_count>15){
+                                                               exit; // INF loop safety thing..
+                                                       }
+                                               }
+                                       }
+                                       
+                                       $translated_file_names[$list[$i]['index']] = $path_parts['dirname'].$trans_name;
+
+                                       if ($path_parts['dirname'].$trans_name != $filename) {
+                                               $files[strtolower($filename)] .= ' => '.$trans_name;
+                                       }
+                                       
+                               }
+                                       
+                               $files[strtolower($filename)] .= '</td>';
+
+                               $files[strtolower($filename)] .= '<td align="right">'.get_human_size($list[$i]['size']).' </td>';
+                               $files[strtolower($filename)] .= '<td>&nbsp;';
+                               
+                               $files[strtolower($filename)] .= AT_date(_AT('filemanager_date_format'), $list[$i]['mtime'], AT_DATE_UNIX_TIMESTAMP);
+                                       
+                               $files[strtolower($filename)] .= '</td>';
+               
+                               $files[strtolower($filename)] .= '</tr>';
+               }
+       }
+
+       $sql    = "SELECT max_quota, max_file_size FROM ".TABLE_PREFIX."courses WHERE course_id=$_SESSION[course_id]";
+       $result = mysql_query($sql, $db);
+       $row    = mysql_fetch_assoc($result);
+       $my_MaxCourseSize       = $row['max_quota'];
+       $my_MaxFileSize     = $row['max_file_size'];
+
+       $course_total = dirsize($path);
+       if ($my_MaxCourseSize == AT_COURSESIZE_UNLIMITED) {
+               $total_after = 1;
+       } else if ($my_MaxCourseSize == AT_COURSESIZE_DEFAULT) {
+               $my_MaxCourseSize = $MaxCourseSize;
+               $total_after = get_human_size($my_MaxCourseSize-$course_total-$totalBytes);
+       }else{
+               $total_after = get_human_size($my_MaxCourseSize - $course_total - $totalBytes);
+       }
+
+       // if $total_after < 0: redirect with error msg
+
+       if (isset($_POST['submit']) && ($total_after > 0)) {
+               $_POST['custom_path'] = trim($_POST['custom_path']);
+               $_POST['custom_path'] = str_replace(' ', '_', $_POST['custom_path']);
+
+               /* anything else should be okay, since we're on *nix.. hopefully */
+               $_POST['custom_path'] = ereg_replace('[^a-zA-Z0-9._/]', '', $_POST['custom_path']);
+
+               if (strpos($_POST['pathext'].$_POST['custom_path'], '..') !== false) {
+                       $msg->addError('UNKNOWN');
+                       header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup']);
+                       exit;
+               } else if ($zip->extract(       PCLZIP_OPT_PATH,                $path. $_POST['pathext'] . $_POST['custom_path'],  
+                                                       PCLZIP_CB_PRE_EXTRACT,  'preExtractCallBack')                   == 0) {
+
+                       echo ("Error : ".$zip->errorInfo(true));
+               } else {
+                       $msg->addFeedback('ARCHIVE_EXTRACTED');
+                       header('Location: index.php?pathext='.$_POST['pathext'].SEP.'popup='.$_POST['popup'].SEP.'framed='.$_POST['framed']);
+                       exit;
+               }
+
+               header('Location: index.php');
+               exit;
+       }
+
+       require(AT_INCLUDE_PATH.'header.inc.php');
+
+       if (($my_MaxCourseSize != AT_COURSESIZE_UNLIMITED) && ($total_after  + $MaxCourseFloat <= 0)) {
+               $msg->printErrors('NO_SPACE_LEFT');
+       } else {
+?>
+               <form method="post" action="tools/filemanager/zip.php">
+               <input type="hidden" name="pathext" value="<?php echo $_GET['pathext']; ?>" />
+               <input type="hidden" name="file"    value="<?php echo $_GET['file']; ?>" />
+               <input type="hidden" name="popup"   value="<?php echo $_GET['popup']; ?>" />
+               <input type="hidden" name="framed"   value="<?php echo $_GET['framed']; ?>" />
+               <div class="input-form">
+                       <div class="row">
+                               <p><?php echo _AT('zip_illegal_contents'); ?></p>
+                               <p><?php echo _AT('extract_tip'); ?></p>
+                       </div>
+
+                       <div class="row">
+                               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><?php echo _AT('directory_name'); ?><br />
+                               <input type="text" name="custom_path" value="<?php echo $temp_name; ?>" />
+                       </div>
+
+                       <div class="row buttons">
+                               <input type="submit" name="submit" value="<?php echo _AT('extract'); ?>" /> 
+                               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+                       </div>
+               </div>
+               </form>
+<?php
+       } // end if
+?>
+
+<table class="data static" summary="" rules="groups">
+<thead>
+<tr>
+       <th><?php echo _AT('name'); ?></th>
+       <th><?php echo _AT('size'); ?></th>
+       <th><?php echo _AT('date'); ?></th>
+</tr>
+</thead>
+<tbody>
+       <?php
+       if (is_array($dirs)) {
+               foreach($dirs as $x => $y) {
+                       echo $y;
+               }
+       }
+
+       if (is_array($files)) {
+               foreach($files as $x => $y) {
+                       echo $y;
+               }
+       }
+?>
+</tbody>
+<tfoot>
+<tr>
+       <td align="right"><?php echo _AT('archive_total'); ?>:</td>
+       <td align="right"><?php echo get_human_size($totalBytes); ?></td>
+       <td>&nbsp;</td>
+</tr>
+<tr>
+       <td align="right"><?php echo _AT('course_total_zip'); ?>:</td>
+       <td align="right"><?php echo get_human_size($course_total); ?></td>
+       <td>&nbsp;</td>
+</tr>
+<tr>
+       <td align="right"><?php echo _AT('course_available_zip1'); ?>:</td>
+       <td align="right"><?php
+                       if ($my_MaxCourseSize == AT_COURSESIZE_UNLIMITED) {
+                               echo _AT('unlimited');
+                       } else {
+                               echo get_human_size($my_MaxCourseSize-$course_total);
+                       } ?></td>
+       <td>&nbsp;</td>
+</tr>
+<tr>
+       <td align="right"><?php echo _AT('course_available_zip2'); ?>:</td>
+       <td align="right"><?php
+                       if ($my_MaxCourseSize == AT_COURSESIZE_UNLIMITED) {
+                               echo _AT('unlimited');
+                       } else {
+                               if ($total_after <= 0) {
+                                       echo '<span style="color: red;">';
+                                       echo $total_after;
+                                       echo '</span>';
+                               } else {
+                                       echo $total_after;
+                               }
+                       } ?></td>
+       <td>&nbsp;</td>
+</tr>
+</tfoot>
+</table>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/forums/index.php b/tools/forums/index.php
new file mode 100644 (file)
index 0000000..30b81f1
--- /dev/null
@@ -0,0 +1,78 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+$page = 'tools';\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_FORUMS);\r
+\r
+if (isset($_GET['edit'], $_GET['id'])) {\r
+       header('Location: '.AT_BASE_HREF.'editor/edit_forum.php?fid='.intval($_GET['id']));\r
+       exit;\r
+} else if (isset($_GET['delete'], $_GET['id'])) {\r
+       header('Location: '.AT_BASE_HREF.'editor/delete_forum.php?fid='.intval($_GET['id']));\r
+       exit;\r
+} else if (isset($_GET['edit']) || isset($_GET['delete'])) {\r
+       $msg->addError('NO_ITEM_SELECTED');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'lib/forums.inc.php');\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+\r
+$all_forums = get_forums($_SESSION['course_id']);\r
+?>\r
+<form name="form" method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+\r
+<table class="data" summary="" rules="cols">\r
+<thead>\r
+<tr>\r
+       <th scope="col">&nbsp;</th>\r
+       <th scope="col"><?php echo _AT('title'); ?></th>\r
+       <th scope="col"><?php echo _AT('description'); ?></th>\r
+       <th scope="col"><?php echo _AT('allow_editing'); ?></th>\r
+</tr>\r
+</thead>\r
+<tfoot>\r
+<tr>\r
+       <td colspan="4"><input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /></td>\r
+</tr>\r
+</tfoot>\r
+<tbody>\r
+<?php if ($all_forums['nonshared']): ?>\r
+       <?php foreach($all_forums['nonshared'] as $row): ?>\r
+               <tr onmousedown="document.form['f<?php echo $row['forum_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $row['forum_id']; ?>">\r
+                       <td width="10"><input type="radio" name="id" value="<?php echo $row['forum_id']; ?>" id="f<?php echo $row['forum_id']; ?>" /></td>\r
+                       <td><label for="f<?php echo $row['forum_id']; ?>"><?php echo AT_print($row['title'], 'forums.title'); ?></label></td>\r
+                       <td><?php echo AT_print($row['description'], 'forums.description'); ?></td>\r
+                       <td>\r
+                               <?php if (!$row['mins_to_edit']): ?>\r
+                                       <?php echo _AT('no'); ?>\r
+                               <?php else: ?>\r
+                                       <?php echo  _AT('minutes', $row['mins_to_edit']); ?>\r
+                               <?php endif; ?>\r
+                       </td>\r
+               </tr>\r
+       <?php endforeach; ?>\r
+<?php else: ?>\r
+       <tr>\r
+               <td colspan="4"><?php echo _AT('none_found'); ?></td>\r
+       </tr>\r
+<?php endif; ?>\r
+</tbody>\r
+</table>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/glossary/add.php b/tools/glossary/add.php
new file mode 100644 (file)
index 0000000..9798424
--- /dev/null
@@ -0,0 +1,158 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_GLOSSARY);
+
+if ($_POST['cancel']) {        
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php');
+       exit;
+}
+
+if (isset($_POST['submit'])) {
+       $num_terms = intval($_POST['num_terms']);
+       $missing_fields = array();
+
+       for ($i=0; $i<$num_terms; $i++) {
+
+               if ($_POST['ignore'][$i] == '') {
+                       $_POST['word'][$i] = trim($_POST['word'][$i]);
+                       $_POST['definition'][$i] = trim($_POST['definition'][$i]);
+
+                       if ($_POST['word'][$i] == '') {
+                               $missing_fields[] = _AT('glossary_term');
+                       } else{
+                               //60 is defined by the sql
+                               $_POST['word'][$i] = validate_length($_POST['word'][$i], 60);
+                       }
+                       
+
+                       if ($_POST['definition'][$i] == '') {
+                               $missing_fields[] = _AT('glossary_definition');
+                       }
+
+                       if ($terms_sql != '') {
+                               $terms_sql .= ', ';
+                       }
+
+                       $_POST['related_term'][$i] = intval($_POST['related_term'][$i]);
+
+                       /* for each item check if it exists: */
+
+                       if ($glossary[urlencode($_POST['word'][$i])] != '' ) {
+                               $errors = array('TERM_EXISTS', $_POST['word'][$i]);
+                               $msg->addError($errors);
+                       } else {
+                               $_POST['word'][$i]         = $addslashes($_POST['word'][$i]);
+                               $_POST['definition'][$i]   = $addslashes($_POST['definition'][$i]);
+                               $_POST['related_term'][$i] = $addslashes($_POST['related_term'][$i]);
+
+                               $terms_sql .= "(NULL, $_SESSION[course_id], '{$_POST[word][$i]}', '{$_POST[definition][$i]}', {$_POST[related_term][$i]})";
+                       }
+               }
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       if (!$msg->containsErrors()) {
+               $sql = "INSERT INTO ".TABLE_PREFIX."glossary VALUES $terms_sql";
+               $result = mysql_query($sql, $db);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: index.php');
+               exit;
+       }
+       $_GET['pcid'] = $_POST['pcid'];
+}
+
+$onload = 'document.form.title0.focus();';
+
+unset($word);
+
+$num_terms = 1;
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="num_terms" value="<?php echo $num_terms; ?>" />
+<?php
+for ($i=0;$i<$num_terms;$i++) {
+       if ($glossary[$word[$i]] != '') {
+               echo '<input type="hidden" name="ignore['.$i.']" value="1" />';
+               continue;
+       }
+       
+       for ($j=0;$j<$i;$j++) {
+               if ($word[$j] == $word[$i]) {
+                       echo '<input type="hidden" name="ignore['.$i.']" value="1" />';
+                       continue 2;
+               }
+       }
+
+       if ($word[$i] == '') {
+               $word[$i] = ContentManager::cleanOutput($_POST['word'][$i]);
+       }
+?>
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('add_glossary'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title<?php echo $i; ?>"><?php echo _AT('glossary_term');  ?></label><br />
+               <input type="text" name="word[<?php echo $i; ?>]" size="30" value="<?php echo trim($word[$i]); ?>" id="title<?php echo $i; ?>" /><?php                  
+               if ($_GET['pcid'] != '') { 
+                       echo '<input type="checkbox" name="ignore['.$i.']" value="1" id="ig'.$i.'" /><label for="ig'.$i.'">Ignore this term</label>.';  
+               }
+               ?>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="body<?php echo $i; ?>"><?php echo _AT('glossary_definition');  ?></label><br />
+               <textarea name="definition[<?php echo $i; ?>]" class="formfield" cols="55" rows="7" id="body<?php echo $i; ?>" style="width:90%;"><?php echo ContentManager::cleanOutput($_POST['definition'][$i]); ?></textarea>
+       </div>
+
+       <div class="row">
+       <?php echo _AT('glossary_related');  ?><br />
+       <?php
+                       $sql = "SELECT * FROM ".TABLE_PREFIX."glossary WHERE course_id=$_SESSION[course_id] ORDER BY word";
+                       $result = mysql_query($sql, $db);
+                       if ($row_g = mysql_fetch_assoc($result)) {
+                               echo '<select name="related_term['.$i.']">';
+                               echo '<option value="0"></option>';
+                               do {
+                                       echo '<option value="'.$row_g['word_id'].'">'.$row_g['word'].'</option>';
+                               } while ($row_g = mysql_fetch_assoc($result));
+                               echo '</select>';
+                       } else {
+                               echo _AT('none_available');
+                       }
+               } // endfor
+       ?>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/glossary/delete.php b/tools/glossary/delete.php
new file mode 100644 (file)
index 0000000..356ee18
--- /dev/null
@@ -0,0 +1,70 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+authenticate(AT_PRIV_GLOSSARY);\r
+\r
+if ($_POST['submit_no']) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+if ($_POST['submit_yes']) {\r
+\r
+       $_POST['gid'] = intval($_POST['gid']);\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."glossary WHERE word_id=$_POST[gid] AND course_id=$_SESSION[course_id]";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $sql = "UPDATE ".TABLE_PREFIX."glossary SET related_word_id=0 WHERE related_word_id=$_POST[gid] AND course_id=$_SESSION[course_id]";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: index.php');\r
+       exit;\r
+} else if ($_POST['submit_no']) {\r
+\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$_GET['gid'] = intval($_GET['gid']);\r
+\r
+if ($_GET['gid'] == 0) {\r
+       $msg->printErrors('ITEM_NOT_FOUND');\r
+       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+\r
+$hidden_vars['word'] = $_GET['t'];\r
+$hidden_vars['gid']  = $_GET['gid'];\r
+\r
+$sql = "SELECT * from ".TABLE_PREFIX."glossary WHERE word_id = '$hidden_vars[gid]'";\r
+$result = mysql_query($sql, $db);\r
+while ($row = mysql_fetch_assoc($result)){\r
+       $title = $row['word'];\r
+}\r
+               \r
+$msg->addConfirm(array('DELETE', $title),  $hidden_vars);\r
+$msg->addConfirm('GLOSSARY_REMAINS', $hidden_vars);\r
+       \r
+$msg->printConfirm();\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/tools/glossary/edit.php b/tools/glossary/edit.php
new file mode 100644 (file)
index 0000000..f2c8aa5
--- /dev/null
@@ -0,0 +1,150 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+authenticate(AT_PRIV_GLOSSARY);\r
+\r
+if ($_POST['cancel']) {\r
+       $msg->addFeedback('CANCELLED');\r
+       Header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+if ($_POST['submit']) {\r
+       $missing_fields = array();\r
+\r
+       $_POST['word'] = trim($_POST['word']);\r
+       $_POST['definition'] = trim($_POST['definition']);\r
+\r
+       if ($_POST['word'] == '') {\r
+               $missing_fields[] = _AT('glossary_term');\r
+       } else{\r
+               //60 is defined by the sql\r
+               $_POST['word'] = validate_length($_POST['word'], 60);\r
+       }\r
+\r
+       if ($_POST['definition'] == '') {\r
+               $missing_fields[] = _AT('glossary_definition');\r
+       }\r
+\r
+       if ($missing_fields) {\r
+               $missing_fields = implode(', ', $missing_fields);\r
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));\r
+       }\r
+\r
+       $_POST['related_term'] = intval($_POST['related_term']);\r
+\r
+\r
+       if (!$msg->containsErrors()) {\r
+               $_POST['word']  = $addslashes($_POST['word']);\r
+               $_POST['definition']  = $addslashes($_POST['definition']);\r
+\r
+               $sql = "UPDATE ".TABLE_PREFIX."glossary SET word='$_POST[word]', definition='$_POST[definition]', related_word_id=$_POST[related_term] WHERE word_id=$_POST[gid] AND course_id=$_SESSION[course_id]";\r
+               \r
+               $result = mysql_query($sql, $db);\r
+\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+               Header('Location: index.php');\r
+               exit;\r
+       }\r
+}\r
+\r
+$onload = 'document.form.title.focus();';\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+if ($_POST['submit']) {\r
+       $gid = intval($_POST['gid']);\r
+} else {\r
+       $gid = intval($_GET['gid']);\r
+}\r
+\r
+if ($gid == 0) {\r
+       $msg->printErrors('ITEM_NOT_FOUND');\r
+       require (AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+\r
+$msg->printErrors();\r
+\r
+$result = mysql_query("SELECT * FROM ".TABLE_PREFIX."glossary WHERE word_id=$gid", $db);\r
+\r
+if (!( $row = @mysql_fetch_array($result)) ) {\r
+       $msg->printErrors('ITEM_NOT_FOUND');\r
+       require (AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+\r
+if ($_POST['submit']) {\r
+       $row['word']            = $_POST['word'];\r
+       $row['definition']  = $_POST['definition'];\r
+}\r
+\r
+?>\r
+\r
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">\r
+<input type="hidden" name="gid" value="<?php echo $gid; ?>" />\r
+\r
+<div class="input-form">\r
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('edit_glossary'); ?></legend>\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php echo _AT('glossary_term');  ?></label><br/ >\r
+               <input type="text" name="word" size="40" id="title" value="<?php echo htmlspecialchars($stripslashes($row['word'])); ?>" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="body"><?php echo _AT('glossary_definition'); ?></label><br />\r
+               <textarea name="definition" cols="55" rows="7" id="body"><?php echo $row['definition']; ?></textarea>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <?php echo _AT('glossary_related');  ?><br />\r
+       <?php\r
+               $sql = "SELECT * FROM ".TABLE_PREFIX."glossary WHERE course_id=$_SESSION[course_id] AND word_id<>$gid ORDER BY word";\r
+\r
+               $result = mysql_query($sql, $db);\r
+               if ($row_g = mysql_fetch_array($result)) {\r
+                       echo '<select name="related_term">';\r
+                       echo '<option value="0"></option>';\r
+                       do {\r
+                               if ($row_g['word_id'] == $row['word_id']) {\r
+                                       continue;\r
+                               }\r
+               \r
+                               echo '<option value="'.$row_g['word_id'].'"';\r
+                       \r
+                               if ($row_g['word_id'] == $row['related_word_id']) {\r
+                                       echo ' selected="selected" ';\r
+                               }\r
+                       \r
+                               echo '>'.$row_g['word'].'</option>';\r
+                       } while ($row_g = mysql_fetch_array($result));\r
+                       \r
+                       echo '</select>';\r
+               \r
+               } else {\r
+                       echo  _AT('no_glossary_items');\r
+               }\r
+       ?>\r
+       </div>\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel');  ?>" />\r
+       </div>\r
+       </fieldset>\r
+</div>\r
+</form>\r
+\r
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/glossary/index.php b/tools/glossary/index.php
new file mode 100644 (file)
index 0000000..4019d7c
--- /dev/null
@@ -0,0 +1,120 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+authenticate(AT_PRIV_GLOSSARY);\r
+\r
+require (AT_INCLUDE_PATH.'lib/links.inc.php');\r
+\r
+if (isset($_POST['edit'], $_POST['word_id'])) {\r
+       header('Location: edit.php?gid='.$_POST['word_id']);\r
+       exit;\r
+} else if (isset($_POST['delete'], $_POST['word_id'])) {\r
+       header('Location: delete.php?gid='.$_POST['word_id']);\r
+       exit;\r
+} else if (!empty($_POST)) {\r
+       $msg->addError('NO_ITEM_SELECTED');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+//get terms\r
+$sql   = "SELECT * FROM ".TABLE_PREFIX."glossary WHERE course_id=$_SESSION[course_id] ORDER BY word";                  \r
+$result= mysql_query($sql, $db);\r
+\r
+$gloss_results = array();\r
+while ($row = mysql_fetch_assoc($result)) {\r
+       $gloss_results[] = $row;\r
+}\r
+$num_results = count($gloss_results);\r
+$results_per_page = 25;\r
+$num_pages = ceil($num_results / $results_per_page);\r
+$page = intval($_GET['p']);\r
+if (!$page) {\r
+       $page = 1;\r
+}\r
+       \r
+$count = (($page-1) * $results_per_page) + 1;\r
+$gloss_results = array_slice($gloss_results, ($page-1)*$results_per_page, $results_per_page);\r
+       \r
+if($num_pages > 1) {\r
+       echo _AT('page').': ';\r
+       for ($i=1; $i<=$num_pages; $i++) {\r
+               if ($i == $page) {\r
+                       echo '<strong>'.$i.'</strong>';\r
+               } else {\r
+                       echo ' | <a href="'.$_SERVER['PHP_SELF'].'?p='.$i.'#list">'.$i.'</a>';\r
+               }\r
+       }\r
+}\r
+?>\r
+\r
+<form name="form" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+\r
+<table class="data" summary="" rules="cols" style="width: 90%;">\r
+<thead>\r
+<tr>\r
+       <th scope="col">&nbsp;</th>\r
+       <th scope="col"><?php echo _AT('glossary_term'); ?></th>\r
+       <th scope="col"><?php echo _AT('glossary_definition'); ?></th>\r
+       <th scope="col"><?php echo _AT('glossary_related'); ?></th>\r
+</tr>\r
+</thead>\r
+<tfoot>\r
+<tr>\r
+       <td colspan="4"><input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /></td>\r
+</tr>\r
+</tfoot>\r
+<tbody>\r
+<?php\r
+if(!empty($gloss_results)) {\r
+       foreach ($gloss_results as $row) {      \r
+               //get related term name\r
+               $related_word = '';\r
+               if ($row['related_word_id']) {\r
+                       $sql    = "SELECT word FROM ".TABLE_PREFIX."glossary WHERE word_id=".$row['related_word_id']." AND course_id=".$_SESSION['course_id'];\r
+                       $result = mysql_query($sql, $db);\r
+                       if ($row_related = mysql_fetch_array($result)) {\r
+                               $related_word = $row_related['word'];                   \r
+                       }\r
+               }\r
+\r
+               $def_trunc = $substr($row['definition'], 0, 70);\r
+               if ($strlen($def_trunc) < $strlen($row['definition'])) {\r
+                       $def_trunc .= ' &#8230;';\r
+               }\r
+       ?>\r
+                       <tr onmousedown="document.form['m<?php echo $row['word_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $row['word_id']; ?>">\r
+                               <td valign="top" width="10"><input type="radio" name="word_id" value="<?php echo $row['word_id']; ?>" id="m<?php echo $row['word_id']; ?>" /></td>\r
+                               <td valign="top"><label for="m<?php echo $row['word_id']; ?>"><?php echo AT_print($row['word'], 'glossary.word'); ?></label></td>\r
+                               <td style="whitespace:nowrap;"><?php echo AT_print($def_trunc,          'glossary.definition'); ?></td>\r
+                               <td valign="top"><?php echo AT_print($related_word,     'glossary.word'); ?></td>\r
+                       </tr>\r
+<?php \r
+       }                               \r
+} else {\r
+?>\r
+       <tr>\r
+               <td colspan="5"><?php echo _AT('none_found'); ?></td>\r
+       </tr>\r
+<?php\r
+}                                      \r
+?>\r
+\r
+</tbody>\r
+</table>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/groups/create.php b/tools/groups/create.php
new file mode 100644 (file)
index 0000000..befd18e
--- /dev/null
@@ -0,0 +1,46 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_GROUPS);\r
+\r
+if (isset($_GET['submit'], $_GET['create']) && ($_GET['create'] == 'automatic')) {\r
+       header('Location: create_automatic.php');\r
+       exit;\r
+} else if (isset($_GET['submit'], $_GET['create']) && ($_GET['create'] == 'manual')) {\r
+       header('Location: create_manual.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+?>\r
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<div class="input-form">\r
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('create_groups'); ?></legend>\r
+       <div class="row">\r
+               <input type="radio" name="create" value="automatic" id="automatic" checked="checked" /><label for="automatic"><?php echo _AT('groups_create_automatic'); ?></label>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <input type="radio" name="create" value="manual" id="manual" /><label for="manual"><?php echo _AT('groups_create_manual'); ?></label>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('continue'); ?>" />\r
+       </div>\r
+       </fieldset>\r
+</div>\r
+</form>\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/groups/create_automatic.php b/tools/groups/create_automatic.php
new file mode 100644 (file)
index 0000000..1b36437
--- /dev/null
@@ -0,0 +1,230 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_GROUPS);\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       $modules = '';\r
+       if (isset($_POST['modules'])) {\r
+               $modules = implode('|', $_POST['modules']);\r
+       }\r
+\r
+       $_POST['type_title']   = trim($_POST['type_title']);\r
+       $_POST['num_students'] = abs($_POST['num_students']);\r
+       $_POST['num_groups']   = abs($_POST['num_groups']);\r
+       $_POST['num_g']        = intval($_POST['num_g']);\r
+\r
+       $missing_fields = array();\r
+\r
+       if (!$_POST['type_title']) {\r
+               $missing_fields[] = _AT('groups_type');\r
+       }\r
+\r
+       if (!$_POST['prefix']) {\r
+               $missing_fields[] = _AT('group_prefix');\r
+       }\r
+\r
+       $course_owner = $system_courses[$_SESSION['course_id']]['member_id'];\r
+       if (isset($_POST['fill'])) {\r
+               $sql = "SELECT member_id FROM ".TABLE_PREFIX."course_enrollment WHERE course_id=$_SESSION[course_id] AND approved='y' AND `privileges`&".AT_PRIV_GROUPS."=0 AND member_id<>$course_owner";\r
+               $result = mysql_query($sql, $db);\r
+               $total_students = mysql_num_rows($result);\r
+               $students = array();\r
+               while ($row = mysql_fetch_assoc($result)) {\r
+                       $students[] = $row['member_id'];\r
+               }\r
+               shuffle($students);\r
+       } else {\r
+               $sql = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."course_enrollment WHERE course_id=$_SESSION[course_id] AND approved='y' AND `privileges`&".AT_PRIV_GROUPS."=0 AND member_id<>$course_owner";\r
+               $result = mysql_query($sql, $db);\r
+               $row = mysql_fetch_assoc($result);\r
+\r
+               $total_students = $row['cnt']; // 4 students in the course\r
+       }\r
+\r
+       if ($_POST['num_g'] == 1) { // number of students per group\r
+               $num_students_per_group = $_POST['num_students'];\r
+\r
+               if ($num_students_per_group == 0) {\r
+                       $missing_fields[] = _AT('number_of_students_per_group');\r
+               } else {\r
+                       if ($total_students == 0) {\r
+                               $msg->addError('GROUP_NO_STUDENTS');\r
+                       } else {\r
+                               $num_groups = ceil($total_students / $num_students_per_group);\r
+                       }\r
+               }\r
+       } else { // number of groups\r
+               $num_groups = $_POST['num_groups'];\r
+\r
+               if ($num_groups == 0) {\r
+                       $missing_fields[] = _AT('number_of_groups');\r
+               } else {\r
+                       if ($total_students > 0) {\r
+                               // to uniformly distribute all the groups we place the remaining students\r
+                               // into the first n groups, where n is the number of remaining students.\r
+                               $remainder = $total_students % $num_groups;\r
+                               if ($remainder) {\r
+                                       $num_students_per_group = floor($total_students / $num_groups);\r
+                               } else {\r
+                                       $num_students_per_group = $total_students / $num_groups;\r
+                               }\r
+                       } else {\r
+                               $num_students_per_group = 0;\r
+                       }\r
+               }\r
+       }\r
+\r
+       if ($missing_fields) {\r
+               $missing_fields = implode(', ', $missing_fields);\r
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               $_POST['type_title']  = $addslashes($_POST['type_title']);\r
+               $_POST['prefix']      = $addslashes($_POST['prefix']);\r
+               $_POST['description'] = $addslashes($_POST['description']);\r
+\r
+               $sql = "INSERT INTO ".TABLE_PREFIX."groups_types VALUES (NULL, $_SESSION[course_id], '$_POST[type_title]')";\r
+               $result = mysql_query($sql, $db);\r
+               $group_type_id = mysql_insert_id($db);\r
+\r
+               $start_index = 0;\r
+\r
+               for($i=0; $i<$num_groups; $i++) {\r
+                       $group_title = $_POST['prefix'] . ' ' . ($i + 1);\r
+                       $sql = "INSERT INTO ".TABLE_PREFIX."groups VALUES (NULL, $group_type_id, '$group_title', '$_POST[description]', '$modules')";\r
+                       $result = mysql_query($sql, $db);\r
+\r
+                       $group_id = mysql_insert_id($db);\r
+                       $_SESSION['groups'][$group_id] = $group_id;\r
+\r
+                       // call module init scripts:\r
+                       if (isset($_POST['modules'])) {\r
+                               foreach ($_POST['modules'] as $mod) {\r
+                                       $module =& $moduleFactory->getModule($mod);\r
+                                       $module->createGroup($group_id);\r
+                               }\r
+                       }\r
+\r
+                       if (isset($_POST['fill'])) {\r
+                               // put students in this group\r
+                               for ($j = $start_index; $j < min(($start_index + $num_students_per_group), $total_students); $j++) {\r
+                                       $sql = "INSERT INTO ".TABLE_PREFIX."groups_members VALUES ($group_id, $students[$j])";\r
+                                       mysql_query($sql, $db);\r
+                               }\r
+\r
+                               $start_index = $j;\r
+                               if ($remainder) {\r
+                                       $sql = "INSERT INTO ".TABLE_PREFIX."groups_members VALUES ($group_id, $students[$start_index])";\r
+                                       mysql_query($sql, $db);\r
+                                       $start_index++;\r
+                                       $remainder--;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+\r
+               header('Location: index.php');\r
+               exit;\r
+       } else {\r
+               $_POST['type_title']  = $stripslashes($_POST['type_title']);\r
+               $_POST['prefix']      = $stripslashes($_POST['prefix']);\r
+               $_POST['description'] = $stripslashes($_POST['description']);\r
+       }\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+?>\r
+\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">\r
+       <div class="input-form">\r
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('groups_create_automatic'); ?></legend>\r
+               <div class="row">\r
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="type"><?php echo _AT('groups_type'); ?></label><br />\r
+                       <input type="text" name="type_title" id="type" value="<?php echo htmlspecialchars($_POST['type_title']); ?>" size="30" maxlength="60" />\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="prefix"><?php echo _AT('group_prefix'); ?></label><br />\r
+                       <input type="text" name="prefix" id="prefix" value="<?php echo htmlspecialchars($_POST['prefix']); ?>" size="20" maxlength="40" />\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <label for="description"><?php echo _AT('default_description'); ?></label><br />\r
+                       <textarea name="description" id="description" cols="10" rows="2"><?php echo htmlspecialchars($_POST['description']); ?></textarea>\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><?php echo _AT('number_of_groups'); ?><br />\r
+                       <?php\r
+                               $sql = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."course_enrollment WHERE course_id=$_SESSION[course_id] AND approved='y' AND `privileges`&".AT_PRIV_GROUPS."=0";\r
+                               $result = mysql_query($sql, $db);\r
+                               $row = mysql_fetch_assoc($result);\r
+                       ?>\r
+                       <p><?php echo _AT('num_students_currently_enrolled', $row['cnt']-1); ?></p>\r
+\r
+                       <input type="radio" name="num_g" value="1" id="num1" checked="checked" onclick="javascript:changer('num_groups', 'num_students');" /><label for="num1"><?php echo _AT('number_of_students_per_group'); ?></label> <input type="text" name="num_students" size="3" style="text-align: right" maxlength="4" />\r
+                       <br />\r
+                       <input type="radio" name="num_g" value="2" id="num2" onclick="javascript:changer('num_students', 'num_groups');" /><label for="num2"><?php echo _AT('number_of_groups'); ?></label> <input type="text" name="num_groups" size="3" style="text-align: right" maxlength="4" value="-" />\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <?php echo _AT('fill_groups'); ?><br />\r
+                       <input type="checkbox" name="fill" value="1" id="fill_r" checked="checked" /><label for="fill_r"><?php echo _AT('fill_groups_randomly'); ?></label>\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <?php echo _AT('tools'); ?><br />\r
+                               <?php\r
+                               $modules = $moduleFactory->getModules(AT_MODULE_STATUS_ENABLED, 0, TRUE);\r
+                               $keys = array_keys($modules);\r
+                               $i=0;\r
+                               ?>\r
+                               <?php foreach($keys as $module_name): ?>\r
+                                       <?php $module =& $modules[$module_name]; ?>\r
+                                       <?php if ($module->getGroupTool() && (in_array($module->getGroupTool(),$_pages[AT_NAV_HOME]) || in_array($module->getGroupTool(),$_pages[AT_NAV_COURSE])) ): ?>\r
+                                               <input type="checkbox" value="<?php echo $module_name; ?>" name="modules[]" id="m<?php echo ++$i; ?>" /><label for="m<?php echo $i; ?>"><?php echo $module->getName(); ?></label><br />\r
+                                       <?php endif; ?>\r
+                               <?php endforeach; ?>\r
+               </div>\r
+\r
+               <div class="row buttons">\r
+                       <input type="submit" name="submit" value="<?php echo _AT('create'); ?>" accesskey="s" />\r
+                       <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+               </div>\r
+               </fieldset>\r
+       </div>\r
+</form>\r
+<script type="text/javascript">\r
+// <!--\r
+document.form.num_groups.disabled = true;\r
+function changer(name1, name2) {\r
+       document.form[name1].value= '-';\r
+       document.form[name1].disabled = true;\r
+       document.form[name2].disabled = false;\r
+\r
+       document.form[name2].value= '';\r
+       document.form[name2].focus();\r
+}\r
+// -->\r
+</script>\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/groups/create_manual.php b/tools/groups/create_manual.php
new file mode 100644 (file)
index 0000000..f667bd7
--- /dev/null
@@ -0,0 +1,151 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_GROUPS);\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       $modules = '';\r
+       if (isset($_POST['modules'])) {\r
+               $modules = implode('|', $_POST['modules']);\r
+       }\r
+\r
+       $_POST['type']   = abs($_POST['type']);\r
+       $_POST['prefix'] = trim($_POST['prefix']);\r
+       $_POST['new_type'] = trim($_POST['new_type']);\r
+\r
+       $missing_fields = array();\r
+\r
+       if (!$_POST['type'] && !$_POST['new_type']) {\r
+               $missing_fields[] = _AT('groups_type');\r
+       }\r
+       if (!$_POST['prefix']) {\r
+               $missing_fields[] = _AT('title');\r
+       }\r
+       if ($missing_fields) {\r
+               $missing_fields = implode(', ', $missing_fields);\r
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               $_POST['new_type'] = $addslashes($_POST['new_type']);\r
+               $_POST['prefix']      = $addslashes($_POST['prefix']);\r
+               $_POST['description'] = $addslashes($_POST['description']);\r
+\r
+               if ($_POST['new_type']) {\r
+                       $sql = "INSERT INTO ".TABLE_PREFIX."groups_types VALUES (NULL, $_SESSION[course_id], '$_POST[new_type]')";\r
+                       $result = mysql_query($sql, $db);\r
+                       $type_id = mysql_insert_id($db);\r
+               } else {\r
+                       $sql = "SELECT type_id FROM ".TABLE_PREFIX."groups_types WHERE course_id=$_SESSION[course_id] AND type_id=$_POST[type]";\r
+                       $result = mysql_query($sql, $db);\r
+                       if ($row = mysql_fetch_assoc($result)) {\r
+                               $type_id = $row['type_id'];\r
+                       } else {\r
+                               $type_id = FALSE;\r
+                       }\r
+               }\r
+               if ($type_id) {\r
+                       $sql = "INSERT INTO ".TABLE_PREFIX."groups VALUES (NULL, $type_id, '$_POST[prefix]', '$_POST[description]', '$modules')";\r
+                       $result = mysql_query($sql, $db);\r
+\r
+                       $group_id = mysql_insert_id($db);\r
+\r
+                       $_SESSION['groups'][$group_id] = $group_id;\r
+                       // call module init scripts:\r
+                       if (isset($_POST['modules'])) {\r
+                               foreach ($_POST['modules'] as $mod) {\r
+                                       $module =& $moduleFactory->getModule($mod);\r
+                                       $module->createGroup($group_id);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+\r
+               header('Location: index.php');\r
+               exit;\r
+       } else {\r
+               $_POST['new_type']    = $stripslashes($_POST['new_type']);\r
+               $_POST['prefix']      = $stripslashes($_POST['prefix']);\r
+               $_POST['description'] = $stripslashes($_POST['description']);\r
+       }\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$types = array();\r
+$sql = "SELECT type_id, title FROM ".TABLE_PREFIX."groups_types WHERE course_id=$_SESSION[course_id] ORDER BY title";\r
+$result = mysql_query($sql, $db);\r
+while ($row = mysql_fetch_assoc($result)) {\r
+       $types[$row['type_id']] = $row['title'];\r
+}\r
+\r
+?>\r
+\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">\r
+       <div class="input-form">\r
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('groups_create_manual'); ?></legend>\r
+               <div class="row">\r
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="type"><?php echo _AT('groups_type'); ?></label><br />\r
+                       <?php if ($types): ?>\r
+                               <?php echo _AT('existing_type'); ?>\r
+                               <select name="type" id="type">\r
+                               <?php foreach ($types as $type_id => $type_title): ?>\r
+                                       <option value="<?php echo $type_id; ?>"><?php echo $type_title; ?></option>\r
+                               <?php endforeach; ?>\r
+                               </select>\r
+                               <em><?php echo _AT('or'); ?></em>\r
+                       <?php endif; ?>\r
+                       <label for="new"><?php echo _AT('new_type'); ?></label> <input type="text" name="new_type" value="<?php echo htmlspecialchars($_POST['new_type']); ?>" id="new" size="30" maxlength="40" />\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="prefix"><?php echo _AT('title'); ?></label><br />\r
+                       <input type="text" name="prefix" id="prefix" value="<?php echo htmlspecialchars($_POST['prefix']); ?>" size="20" maxlength="40" />\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <label for="description"><?php echo _AT('description'); ?></label><br />\r
+                       <textarea name="description" id="description" cols="10" rows="2"><?php echo htmlspecialchars($_POST['description']); ?></textarea>\r
+               </div>\r
+\r
+               <div class="row">\r
+                       <?php echo _AT('tools'); ?><br />\r
+                               <?php\r
+                               $modules = $moduleFactory->getModules(AT_MODULE_STATUS_ENABLED, 0, TRUE);\r
+                               $keys = array_keys($modules);\r
+                               $i=0;\r
+                               ?>\r
+                               <?php foreach($keys as $module_name): ?>\r
+                                       <?php $module =& $modules[$module_name]; ?>\r
+                                       <?php if ($module->getGroupTool() && (in_array($module->getGroupTool(),$_pages[AT_NAV_HOME]) || in_array($module->getGroupTool(),$_pages[AT_NAV_COURSE])) ): ?>\r
+                                               <input type="checkbox" value="<?php echo $module_name; ?>" name="modules[]" id="m<?php echo ++$i; ?>" /><label for="m<?php echo $i; ?>"><?php echo $module->getName(); ?></label><br />\r
+                                       <?php endif; ?>\r
+                               <?php endforeach; ?>\r
+               </div>\r
+\r
+               <div class="row buttons">\r
+                       <input type="submit" name="submit" value="<?php echo _AT('create'); ?>" accesskey="s" />\r
+                       <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+               </div>\r
+               </fieldset>\r
+       </div>\r
+</form>\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/groups/delete_group.php b/tools/groups/delete_group.php
new file mode 100644 (file)
index 0000000..14309d5
--- /dev/null
@@ -0,0 +1,90 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+$page = 'tests';\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+authenticate(AT_PRIV_GROUPS);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       $_POST['id'] = intval($_POST['id']);\r
+       $_POST['type_id'] = intval($_POST['type_id']);\r
+\r
+       $id = intval($_POST['id']);\r
+       $type_id = intval($_POST['type_id']);\r
+\r
+       $sql = "SELECT type_id FROM ".TABLE_PREFIX."groups_types WHERE type_id=$type_id AND course_id=$_SESSION[course_id]";\r
+       $result = mysql_query($sql, $db);\r
+       if ($row = mysql_fetch_assoc($result)) {\r
+               $module_list = $moduleFactory->getModules(AT_MODULE_STATUS_ENABLED | AT_MODULE_STATUS_DISABLED);\r
+               $keys = array_keys($module_list);\r
+               foreach ($keys as $module_name) {       \r
+                       $module =& $module_list[$module_name];\r
+                       $module->deleteGroup($id);\r
+               }\r
+\r
+               $sql = "DELETE FROM ".TABLE_PREFIX."groups WHERE group_id=$id AND type_id=$type_id";\r
+               $result = mysql_query($sql, $db);\r
+\r
+               if (mysql_affected_rows($db)) {\r
+                       //remove all listings in groups_members table\r
+                       $sql = "DELETE FROM ".TABLE_PREFIX."groups_members WHERE group_id=$id";\r
+                       $result = mysql_query($sql, $db);\r
+\r
+                       // should be handled by each module:\r
+                       //remove all listings in tests_groups table\r
+                       $sql = "DELETE FROM ".TABLE_PREFIX."tests_groups WHERE group_id=$id";\r
+                       $result = mysql_query($sql, $db);\r
+               }\r
+       }\r
+\r
+       $msg->addFeedback('GROUP_DELETED');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$_GET['id'] = intval($_GET['id']);\r
+\r
+$sql = "SELECT * FROM ".TABLE_PREFIX."groups WHERE group_id=$_GET[id]";\r
+$result = mysql_query($sql,$db);\r
+if (!($row = mysql_fetch_assoc($result))) {\r
+       $msg->printErrors('GROUP_NOT_FOUND');\r
+       require (AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+\r
+$sql = "SELECT title FROM ".TABLE_PREFIX."groups_types WHERE type_id=$row[type_id] AND course_id=$_SESSION[course_id]";\r
+$result = mysql_query($sql,$db);\r
+if (!($type_row = mysql_fetch_assoc($result))) {\r
+       $msg->printErrors('GROUP_NOT_FOUND');\r
+       require (AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+\r
+unset($hidden_vars);\r
+$hidden_vars['id'] = $_GET['id'];\r
+$hidden_vars['type_id'] = $row['type_id'];\r
+\r
+$msg->addConfirm(array('DELETE_GROUP',$row['title']), $hidden_vars);\r
+$msg->printConfirm();\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/tools/groups/delete_type.php b/tools/groups/delete_type.php
new file mode 100644 (file)
index 0000000..cc94a89
--- /dev/null
@@ -0,0 +1,71 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+$page = 'tests';\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+authenticate(AT_PRIV_GROUPS);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+} \r
+else if (isset($_POST['submit_yes'])) {\r
+       $type_id = abs($_POST['id']);\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."groups_types WHERE type_id=$type_id AND course_id=$_SESSION[course_id]";\r
+       mysql_query($sql, $db);\r
+       if (mysql_affected_rows($db) == 1) {\r
+               $sql = "SELECT group_id FROM ".TABLE_PREFIX."groups WHERE type_id=$type_id";\r
+               $result = mysql_query($sql, $db);\r
+               while ($row = mysql_fetch_assoc($result)) {\r
+                       $sql = "DELETE FROM ".TABLE_PREFIX."groups_members WHERE group_id=$row[group_id]";\r
+                       mysql_query($sql, $db);\r
+\r
+                       // should be handled by each module:\r
+                       //remove all listings in tests_groups table\r
+                       $sql = "DELETE FROM ".TABLE_PREFIX."tests_groups WHERE group_id=$row[group_id]";\r
+                       mysql_query($sql, $db);\r
+               }\r
+               $sql = "DELETE FROM ".TABLE_PREFIX."groups WHERE type_id=$type_id";\r
+               $result = mysql_query($sql, $db);\r
+       }\r
+\r
+       $msg->addFeedback('GROUP_TYPE_DELETED');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$_GET['id'] = intval($_GET['id']);\r
+\r
+$sql = "SELECT * FROM ".TABLE_PREFIX."groups_types WHERE type_id=$_GET[id] AND course_id=$_SESSION[course_id]";\r
+$result = mysql_query($sql,$db);\r
+if (!($row = mysql_fetch_assoc($result))) {\r
+       $msg->printErrors('GROUP_TYPE_NOT_FOUND');\r
+       require (AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+\r
+unset($hidden_vars);\r
+$hidden_vars['id'] = $_GET['id'];\r
+\r
+$msg->addConfirm(array('DELETE_GROUP_TYPE',$row['title']), $hidden_vars);\r
+$msg->printConfirm();\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/tools/groups/edit_group.php b/tools/groups/edit_group.php
new file mode 100644 (file)
index 0000000..b56f6c5
--- /dev/null
@@ -0,0 +1,141 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_GROUPS);\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       $modules = '';\r
+       if (isset($_POST['modules'])) {\r
+               $modules = implode('|', $_POST['modules']);\r
+       }\r
+\r
+       $_POST['title']   = trim($_POST['title']);\r
+\r
+       if (!$_POST['title']) {\r
+               $msg->addError(array('EMPTY_FIELDS', _AT('title')));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               $_POST['title']       = $addslashes($_POST['title']);\r
+               $_POST['description'] = $addslashes($_POST['description']);\r
+\r
+               $id = intval($_POST['id']);\r
+               $type_id = intval($_POST['type_id']);\r
+\r
+               $sql = "SELECT type_id FROM ".TABLE_PREFIX."groups_types WHERE type_id=$type_id AND course_id=$_SESSION[course_id]";\r
+               $result = mysql_query($sql, $db);\r
+               if ($row = mysql_fetch_assoc($result)) {\r
+                       $sql = "UPDATE ".TABLE_PREFIX."groups SET title='$_POST[title]', description='$_POST[description]', modules='$modules' WHERE group_id=$id AND type_id=$type_id";\r
+                       $result = mysql_query($sql, $db);\r
+\r
+                       // delete the modules that were un-checked\r
+                       $old_modules = explode('|', $_POST['old_modules']);\r
+                       $modules = explode('|', $modules);\r
+\r
+                       foreach ($old_modules as $mod) {\r
+                               if (!in_array($mod, $modules)) {\r
+                                       $module =& $moduleFactory->getModule($mod);\r
+                                       $module->deleteGroup($id);\r
+                               }\r
+                       }\r
+                       foreach ($modules as $mod) {\r
+                               if (!in_array($mod, $old_modules)) {\r
+                                       $module =& $moduleFactory->getModule($mod);\r
+                                       $module->createGroup($id);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               $msg->addFeedback('GROUP_EDITED_SUCCESSFULLY');\r
+\r
+               header('Location: index.php');\r
+               exit;\r
+       }\r
+       $_GET['id'] = abs($_POST['id']);\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+       $_GET['id'] = intval($_GET['id']);\r
+\r
+       $sql = "SELECT * FROM ".TABLE_PREFIX."groups WHERE group_id=$_GET[id]";\r
+       $result = mysql_query($sql,$db);\r
+       if (!($row = mysql_fetch_assoc($result))) {\r
+               $msg->printErrors('GROUP_NOT_FOUND');\r
+               require (AT_INCLUDE_PATH.'footer.inc.php');\r
+               exit;\r
+       }\r
+       $sql = "SELECT title FROM ".TABLE_PREFIX."groups_types WHERE type_id=$row[type_id] AND course_id=$_SESSION[course_id]";\r
+       $result = mysql_query($sql,$db);\r
+       if (!($type_row = mysql_fetch_assoc($result))) {\r
+               $msg->printErrors('GROUP_NOT_FOUND');\r
+               require (AT_INCLUDE_PATH.'footer.inc.php');\r
+               exit;\r
+       }\r
+$old_modules = $row['modules'];\r
+$row['modules'] = explode('|', $row['modules']);\r
+?>\r
+\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">\r
+<input type="hidden" name="id" value="<?php echo $row['group_id']; ?>" />\r
+<input type="hidden" name="type_id" value="<?php echo $row['type_id']; ?>" />\r
+<input type="hidden" name="old_modules" value="<?php echo $old_modules; ?>" />\r
+<div class="input-form">\r
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('edit'); ?></legend>\r
+       <div class="row">\r
+               <h3><?php echo $type_row['title']; ?></h3>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php echo _AT('title'); ?></label><br />\r
+               <input type="text" name="title" id="title" value="<?php echo htmlspecialchars($row['title']); ?>" size="20" maxlength="40" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <label for="description"><?php echo _AT('description'); ?>:</label><br />\r
+               <textarea name="description" id="description" cols="10" rows="2"><?php echo htmlspecialchars($row['description']); ?></textarea>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <?php echo _AT('tools'); ?><br />\r
+                       <?php\r
+                       $modules = $moduleFactory->getModules(AT_MODULE_STATUS_ENABLED, 0, TRUE);\r
+                       $keys = array_keys($modules);\r
+                       $i=0;\r
+                       ?>\r
+                       <?php foreach($keys as $module_name): ?>\r
+                               <?php $module =& $modules[$module_name]; ?>\r
+                               <?php if ($module->getGroupTool() && (in_array($module->getGroupTool(),$_pages[AT_NAV_HOME]) || in_array($module->getGroupTool(),$_pages[AT_NAV_COURSE])) ): ?>\r
+                                       <input type="checkbox" value="<?php echo $module_name; ?>" name="modules[]" id="m<?php echo ++$i; ?>" <?php \r
+                                               if (in_array($module_name, $row['modules'])) { echo 'checked="checked"'; } \r
+                                       ?> /><label for="m<?php echo $i; ?>"><?php echo $module->getName(); ?></label><br />\r
+                               <?php endif; ?>\r
+                       <?php endforeach; ?>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+       </div>\r
+       </fieldset>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/groups/edit_type.php b/tools/groups/edit_type.php
new file mode 100644 (file)
index 0000000..33ad75f
--- /dev/null
@@ -0,0 +1,76 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_GROUPS);\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       $_POST['title']   = trim($_POST['title']);\r
+\r
+       if (!$_POST['title']) {\r
+               $msg->addError(array('EMPTY_FIELDS', _AT('title')));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               $_POST['title']       = $addslashes($_POST['title']);\r
+\r
+               $type_id = intval($_POST['type_id']);\r
+\r
+               $sql = "UPDATE ".TABLE_PREFIX."groups_types SET title='$_POST[title]' WHERE course_id=$_SESSION[course_id] AND type_id=$type_id";\r
+               $result = mysql_query($sql, $db);\r
+\r
+               $msg->addFeedback('GROUP_TYPE_EDITED_SUCCESSFULLY');\r
+\r
+               header('Location: index.php');\r
+               exit;\r
+       }\r
+       $_GET['id'] = abs($_POST['type_id']);\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+       $_GET['id'] = intval($_GET['id']);\r
+\r
+       $sql = "SELECT * FROM ".TABLE_PREFIX."groups_types WHERE type_id=$_GET[id] AND course_id=$_SESSION[course_id]";\r
+       $result = mysql_query($sql,$db);\r
+       if (!($row = mysql_fetch_assoc($result))) {\r
+               $msg->printErrors('GROUP_TYPE_NOT_FOUND');\r
+               require (AT_INCLUDE_PATH.'footer.inc.php');\r
+               exit;\r
+       }\r
+?>\r
+\r
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form">\r
+<input type="hidden" name="type_id" value="<?php echo $row['type_id']; ?>" />\r
+<div class="input-form">\r
+               <fieldset class="group_form"><legend class="group_form"><?php echo _AT('edit'); ?></legend>\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php echo _AT('title'); ?></label><br />\r
+               <input type="text" name="title" id="title" value="<?php echo $row['title']; ?>" size="30" maxlength="40" />\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+       </div>\r
+       </fieldset>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/groups/index.php b/tools/groups/index.php
new file mode 100644 (file)
index 0000000..78b012c
--- /dev/null
@@ -0,0 +1,113 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_GROUPS);\r
+\r
+if (isset($_GET['edit'], $_GET['id'])) {\r
+       $parts = explode('_', $_GET['id'], 2);\r
+       if (isset($parts[1]) && $parts[1]) {\r
+               header('Location: edit_group.php?id='.$parts[1]);\r
+               exit;\r
+       } else if ($parts[0]) {\r
+               header('Location: edit_type.php?id='.$parts[0]);\r
+               exit;\r
+       }\r
+} else if (isset($_GET['delete'], $_GET['id'])) {\r
+       $parts = explode('_', $_GET['id'], 2);\r
+       if (isset($parts[1]) && $parts[1]) {\r
+               header('Location: delete_group.php?id='.$parts[1]);\r
+               exit;\r
+       } else if ($parts[0]) {\r
+               header('Location: delete_type.php?id='.$parts[0]);\r
+               exit;\r
+       }\r
+} else if (isset($_GET['members'])) {\r
+       $parts = explode('_', $_GET['id'], 2);\r
+       if (isset($parts[1]) && $parts[1]) {\r
+               header('Location: members.php?id='.$parts[0].SEP.'gid='.$parts[1]);\r
+               exit;\r
+       } else if ($parts[0]) {\r
+               header('Location: members.php?id='.$parts[0]);\r
+               exit;\r
+       } else {\r
+               $msg->addError('NO_ITEM_SELECTED');\r
+       }\r
+} else if (isset($_GET['members']) || isset($_GET['delete']) || isset($_GET['edit'])) {\r
+       $msg->addError('NO_ITEM_SELECTED');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$sql = "SELECT type_id, title FROM ".TABLE_PREFIX."groups_types WHERE course_id=$_SESSION[course_id] ORDER BY title";\r
+$result = mysql_query($sql, $db);\r
+?>\r
+\r
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get" name="form">\r
+<fieldset class="group_form" style="width: 60%; margin:auto;"><legend class="group_form"><?php echo _AT('groups'); ?></legend>\r
+<table class="data" summary="" rules="cols" style="width: 80%">\r
+<tfoot>\r
+<tr>\r
+       <td>\r
+               <input type="submit" name="edit"    value="<?php echo _AT('edit'); ?>" />\r
+               <input type="submit" name="members" value="<?php echo _AT('members'); ?>" />\r
+               <input type="submit" name="delete"  value="<?php echo _AT('delete'); ?>" />\r
+       </td>\r
+</tr>\r
+</tfoot>\r
+<tbody>\r
+<?php if ($row = mysql_fetch_assoc($result)): ?>\r
+       <?php do { ?>\r
+\r
+               <?php \r
+                       $sql = "SELECT group_id, title FROM ".TABLE_PREFIX."groups WHERE type_id=$row[type_id] ORDER BY title";\r
+                       $group_result = mysql_query($sql, $db);\r
+                       $num_groups = mysql_num_rows($group_result);\r
+               ?>\r
+               <tr onmousedown="document.form['g<?php echo $row['type_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $row['type_id']; ?>">\r
+                       <th>\r
+                               <input type="radio" id="g<?php echo $row['type_id']; ?>" name="id" value="<?php echo $row['type_id']; ?>" />\r
+                               <label for="g<?php echo $row['type_id']; ?>"><?php echo $row['title']; ?></label> (<?php echo $num_groups.' '._AT('groups'); ?>)</td>\r
+                       </th>\r
+               </tr>\r
+               <?php if ($num_groups) : ?>\r
+                       <?php while ($group_row = mysql_fetch_assoc($group_result)): ?>\r
+                               <?php\r
+                                       $sql = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."groups_members WHERE group_id=$group_row[group_id]";\r
+                                       $group_cnt_result = mysql_query($sql, $db);\r
+                                       $group_cnt = mysql_fetch_assoc($group_cnt_result);\r
+                               ?>\r
+                               <tr onmousedown="document.form['g<?php echo $row['type_id'].'_'.$group_row['group_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $row['type_id'].'_'.$group_row['group_id']; ?>">\r
+                                       <td class="indent"><input type="radio" id="g<?php echo $row['type_id'].'_'.$group_row['group_id']; ?>" name="id" value="<?php echo $row['type_id'].'_'.$group_row['group_id']; ?>" /> <label for="g<?php echo $row['type_id'].'_'.$group_row['group_id']; ?>"><?php echo $group_row['title']; ?></label> (<?php echo $group_cnt['cnt'].' '._AT('members'); ?>)</td>\r
+                               </tr>\r
+                       <?php endwhile; ?>\r
+               <?php else: ?>\r
+                       <tr>\r
+                               <td class="indent"><em><?php echo _AT('none_found'); ?></em></td>\r
+                       </tr>\r
+               <?php endif; ?>\r
+\r
+       <?php } while ($row = mysql_fetch_assoc($result)); ?>\r
+<?php else: ?>\r
+       <tr>\r
+               <td><em><?php echo _AT('none_found'); ?></em></td>\r
+       </tr>\r
+<?php endif; ?>\r
+</tbody>\r
+</table>\r
+</fieldset>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/groups/members.php b/tools/groups/members.php
new file mode 100644 (file)
index 0000000..05acac1
--- /dev/null
@@ -0,0 +1,222 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg,                               */\r
+/* Heidi Hazelton, and Jonathan Hung                                                                   */\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_GROUPS);\r
+\r
+/* Get type ID */\r
+$id = intval($_REQUEST['id']);\r
+\r
+$sql = "SELECT * FROM ".TABLE_PREFIX."groups_types WHERE type_id=$id AND course_id=$_SESSION[course_id]";\r
+$result = mysql_query($sql,$db);\r
+if (!($type_row = mysql_fetch_assoc($result))) {\r
+       require (AT_INCLUDE_PATH.'header.inc.php');\r
+       $msg->printErrors('GROUP_TYPE_NOT_FOUND');\r
+       require (AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+}\r
+\r
+$tmp_groups = array();\r
+$sql = "SELECT group_id, title FROM ".TABLE_PREFIX."groups WHERE type_id=$id ORDER BY title";\r
+$result = mysql_query($sql, $db);\r
+while ($row = mysql_fetch_assoc($result)) {\r
+       $tmp_groups[$row['group_id']] = $row['title'];\r
+}\r
+$groups_keys = array_keys($tmp_groups);\r
+$groups_keys = implode($groups_keys, ',');\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: index.php');\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."groups_members WHERE group_id IN ($groups_keys)";\r
+       mysql_query($sql, $db);\r
+\r
+       $sql = '';\r
+       foreach ($_POST['groups'] as $mid => $gid) {\r
+               $mid = abs($mid);\r
+               $gid = abs($gid);\r
+               if ($gid) {\r
+                       $sql .= "($gid, $mid),";\r
+               }\r
+       }\r
+       if ($sql) {\r
+               $sql = substr($sql, 0, -1);\r
+               $sql = "INSERT INTO ".TABLE_PREFIX."groups_members VALUES $sql";\r
+               mysql_query($sql, $db);\r
+       }\r
+\r
+       $msg->addFeedback('GROUP_MEMBERS_SAVED');\r
+\r
+       header('Location: index.php');\r
+       exit;\r
+} else if (isset($_POST['assign'])) {\r
+\r
+       $groups_counts = array();\r
+       $sql = "SELECT group_id, COUNT(*) AS cnt FROM ".TABLE_PREFIX."groups_members WHERE group_id IN ($groups_keys) GROUP BY group_id ORDER BY cnt ASC";\r
+       $result = mysql_query($sql, $db);\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               $groups_counts[$row['group_id']] = $row['cnt'];\r
+       }\r
+       $total_assigned = array_sum($groups_counts);\r
+\r
+       if (is_array($_POST['groups'])) {\r
+               foreach ($_POST['groups'] as $mid => $gid) {\r
+                       if ($gid) {\r
+                               unset($_POST['groups'][$mid]);\r
+                       }\r
+               }\r
+               $students = array_keys($_POST['groups']);\r
+\r
+               $total_unassigned = count($students);\r
+\r
+               shuffle($students);\r
+               reset($students);\r
+       }\r
+\r
+       $total_students = $total_unassigned + $total_assigned;\r
+\r
+       $num_groups = count($tmp_groups);\r
+\r
+       if ($total_students > 0) {\r
+               // to uniformly distribute all the groups we place the remaining students\r
+               // into the first n groups, where n is the number of remaining students.\r
+               $remainder = $total_students % $num_groups;\r
+               if ($remainder) {\r
+                       $num_students_per_group = floor($total_students / $num_groups);\r
+               } else {\r
+                       $num_students_per_group = $total_students / $num_groups;\r
+               }\r
+\r
+               $sql = '';\r
+               foreach($tmp_groups as $group_id => $garbage) {\r
+\r
+                       if (!isset($groups_counts[$group_id])) {\r
+                               $groups_counts[$group_id] = 0;\r
+                       }\r
+                       while (($groups_counts[$group_id] < $num_students_per_group) && ($mid = current($students))) {\r
+                               $sql .= "($group_id, $mid),";\r
+                               $groups_counts[$group_id]++;\r
+                               next($students);\r
+                       }\r
+\r
+                       if ($remainder) {\r
+                               $mid = current($students);\r
+                               if ($mid) {\r
+                                       $sql .= "($group_id, $mid),";\r
+                                       $remainder--;\r
+                                       next($students);\r
+                                       $groups_counts[$group_id]++;\r
+                               }\r
+                       }\r
+               }\r
+               if ($sql) {\r
+                       $sql = substr($sql, 0, -1);\r
+                       $sql = "INSERT INTO ".TABLE_PREFIX."groups_members VALUES " . $sql;\r
+                       mysql_query($sql, $db);\r
+               }\r
+       }\r
+\r
+       $msg->addFeedback('GROUP_MEMBERS_SAVED');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+\r
+echo '<h2>'.$type_row['title'].'</h2>';\r
+\r
+\r
+if (isset($_GET['gid'])) {\r
+       $_GET['gid'] = abs($_GET['gid']);\r
+} else {\r
+       $_GET['gid'] = 0;\r
+}\r
+\r
+$groups_members = array();\r
+$sql = "SELECT member_id, group_id FROM ".TABLE_PREFIX."groups_members WHERE group_id IN ($groups_keys) ORDER BY member_id";\r
+$result = mysql_query($sql, $db);\r
+while ($row = mysql_fetch_assoc($result)) {\r
+       $groups_members[$row['member_id']] = $row['group_id'];\r
+}\r
+$groups_members_keys = array_keys($groups_members);\r
+$groups_members_keys = implode($groups_members_keys, ',');\r
+\r
+$owner = $system_courses[$_SESSION['course_id']]['member_id'];\r
+\r
+$sql = "SELECT M.member_id, M.login, M.first_name, M.last_name FROM ".TABLE_PREFIX."members M INNER JOIN ".TABLE_PREFIX."course_enrollment E USING (member_id) WHERE E.course_id=$_SESSION[course_id] AND E.privileges&".AT_PRIV_GROUPS."=0 AND E.approved='y' AND E.member_id<>$owner ORDER BY M.login";\r
+$result = mysql_query($sql, $db);\r
+\r
+$count = 0;\r
+?>\r
+<form name="form" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<input type="hidden" name="id" value="<?php echo $id; ?>" />\r
+<table class="data static" style="width: 60%" rules="rows">\r
+<thead>\r
+       <tr>\r
+               <th><?php echo _AT('login');      ?></th>\r
+               <th><?php echo _AT('first_name'); ?></th>\r
+               <th><?php echo _AT('last_name');  ?></th>\r
+               <th><?php echo _AT('groups');     ?></th>\r
+       </tr>\r
+</thead>\r
+<tfoot>\r
+       <tr>\r
+               <td colspan="4">\r
+                       <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" />\r
+                       <input type="submit" name="assign" value="<?php echo _AT('assign_unassigned'); ?>" />\r
+                       <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />\r
+               </td>\r
+       </tr>\r
+</tfoot>\r
+<tbody>\r
+       <?php while ($row = mysql_fetch_assoc($result)): ?>\r
+               <tr <?php if ($_GET['gid'] && $_GET['gid'] == $groups_members[$row['member_id']]) { echo 'style="background-color: #dfd; font-weight: bold;"';} ?> id="r<?php echo ++$count; ?>">\r
+                       <td><label for="m<?php echo $row['member_id']; ?>"><?php echo $row['login']; ?></label></td>\r
+                       <td><label for="m<?php echo $row['member_id']; ?>"><?php echo $row['first_name']; ?></label></td>\r
+                       <td><label for="m<?php echo $row['member_id']; ?>"><?php echo $row['last_name']; ?></label></td>\r
+                       <td>\r
+                               <select name="groups[<?php echo $row['member_id']; ?>]" id="m<?php echo $row['member_id']; ?>" onchange="javascript:hirow(this, <?php echo $count; ?>);">\r
+                                       <option value="0"></option>\r
+                                       <?php foreach ($tmp_groups as $group => $title): ?>\r
+                                               <option value="<?php echo $group; ?>" <?php if ($groups_members[$row['member_id']] == $group) { echo 'selected="selected"'; } ?>><?php echo htmlspecialchars($title); ?></option>\r
+                                       <?php endforeach; ?>\r
+                               </select>\r
+                       </td>\r
+               </tr>\r
+       <?php endwhile; ?>\r
+</tbody>\r
+</table>\r
+</form>\r
+\r
+<script type="text/javascript" language="javascript">\r
+// <!--\r
+function hirow(obj, row) {\r
+       if (obj.value && obj.value == <?php echo $_GET['gid']; ?>) {\r
+               e = document.getElementById("r" + row);\r
+               e.style.backgroundColor = "#dfd";\r
+               e.style.fontWeight = "bold";\r
+       } else {\r
+               e = document.getElementById("r" + row);\r
+               e.style.backgroundColor = "";\r
+               e.style.fontWeight = "";\r
+       }\r
+}\r
+// -->\r
+</script>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/ims/ims_export.php b/tools/ims/ims_export.php
new file mode 100644 (file)
index 0000000..9d0127f
--- /dev/null
@@ -0,0 +1,312 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+
+/* content id of an optional chapter */
+$cid = isset($_REQUEST['cid']) ? intval($_REQUEST['cid']) : 0;
+$c   = isset($_REQUEST['c'])   ? intval($_REQUEST['c'])   : 0;
+
+if (isset($_REQUEST['to_tile']) && !isset($_POST['cancel'])) {
+       /* for TILE */
+
+       /* redirect to TILE import servlet */
+
+       require(AT_INCLUDE_PATH.'vitals.inc.php');
+       if (!authenticate(AT_PRIV_ADMIN, AT_PRIV_RETURN)) {
+               /* user can't be authenticated */
+               header('HTTP/1.1 404 Not Found');
+               echo 'Document not found.';
+               exit;
+       }
+
+       $m = md5(DB_PASSWORD . 'x' . ADMIN_PASSWORD . 'x' . $_SERVER['SERVER_ADDR'] . 'x' . $cid . 'x' . $_SESSION['course_id'] . 'x' . date('Ymd'));
+
+       header('Location: '.AT_TILE_IMPORT. '?cp='.urlencode(AT_BASE_HREF. 'tools/ims/ims_export.php?cid='.$cid.'&c='.$_SESSION['course_id'].'&m='.$m));
+       exit;
+} else if (isset($_GET['m'])) {
+       /* for TILE */
+
+       /* request (hopefully) coming from a TILE server, send the content package */
+
+       $_user_location = 'public';
+       require(AT_INCLUDE_PATH.'vitals.inc.php');
+       $m = md5(DB_PASSWORD . 'x' . ADMIN_PASSWORD . 'x' . $_SERVER['SERVER_ADDR'] . 'x' . $cid . 'x' . $c . 'x' . date('Ymd'));
+       if (($m != $_GET['m']) || !$c) {
+               header('HTTP/1.1 404 Not Found');
+               echo 'Document not found.';
+               exit;
+       }
+       
+       $course_id = $c;
+
+} else {
+       require(AT_INCLUDE_PATH.'vitals.inc.php');
+       $course_id = $_SESSION['course_id'];
+}
+
+$instructor_id   = $system_courses[$course_id]['member_id'];
+$course_desc     = $system_courses[$course_id]['description'];
+$course_title    = $system_courses[$course_id]['title'];
+$course_language = $system_courses[$course_id]['primary_language'];
+
+$courseLanguage =& $languageManager->getLanguage($course_language);
+
+$course_language_charset = $courseLanguage->getCharacterSet();
+$course_language_code = $courseLanguage->getCode();
+
+require(AT_INCLUDE_PATH.'classes/zipfile.class.php');                          /* for zipfile */
+require(AT_INCLUDE_PATH.'classes/vcard.php');                                          /* for vcard */
+require(AT_INCLUDE_PATH.'classes/XML/XML_HTMLSax/XML_HTMLSax.php');    /* for XML_HTMLSax */
+require(AT_INCLUDE_PATH.'ims/ims_template.inc.php');                           /* for ims templates + print_organizations() */
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('EXPORT_CANCELLED');
+       header('Location: ../index.php');
+       exit;
+}
+
+
+$zipfile = new zipfile(); 
+$zipfile->create_dir('resources/');
+
+/*
+       the following resources are to be identified:
+       even if some of these can't be images, they can still be files in the content dir.
+       theoretically the only urls we wouldn't deal with would be for a <!DOCTYPE and <form>
+
+       img             => src
+       a               => href                         // ignore if href doesn't exist (ie. <a name>)
+       object  => data | classid       // probably only want data
+       applet  => classid | archive                    // whatever these two are should double check to see if it's a valid file (not a dir)
+       link    => href
+       script  => src
+       form    => action
+       input   => src
+       iframe  => src
+
+*/
+class MyHandler {
+    function MyHandler(){}
+    function openHandler(& $parser,$name,$attrs) {
+               global $my_files;
+
+               $name = strtolower($name);
+               $attrs = array_change_key_case($attrs, CASE_LOWER);
+
+               $elements = array(      'img'           => 'src',
+                                                       'a'                     => 'href',                              
+                                                       'object'        => array('data', 'classid'),
+                                                       'applet'        => array('classid', 'archive'),
+                                                       'link'          => 'href',
+                                                       'script'        => 'src',
+                                                       'form'          => 'action',
+                                                       'input'         => 'src',
+                                                       'iframe'        => 'src',
+                                                       'embed'         => 'src',
+                                                       'param'         => 'value');
+       
+               /* check if this attribute specifies the files in different ways: (ie. java) */
+               if (is_array($elements[$name])) {
+                       $items = $elements[$name];
+
+                       foreach ($items as $item) {
+                               if ($attrs[$item] != '') {
+
+                                       /* some attributes allow a listing of files to include seperated by commas (ie. applet->archive). */
+                                       if (strpos($attrs[$item], ',') !== false) {
+                                               $files = explode(',', $attrs[$item]);
+                                               foreach ($files as $file) {
+                                                       $my_files[] = trim($file);
+                                               }
+                                       } else {
+                                               $my_files[] = $attrs[$item];
+                                       }
+                               }
+                       }
+               } else if (isset($elements[$name]) && ($attrs[$elements[$name]] != '')) {
+                       /* we know exactly which attribute contains the reference to the file. */
+                       $my_files[] = $attrs[$elements[$name]];
+               }
+    }
+    function closeHandler(& $parser,$name) { }
+}
+
+/* get all the content */
+$content = array();
+$paths  = array();
+$top_content_parent_id = 0;
+
+$handler=new MyHandler();
+$parser =& new XML_HTMLSax();
+$parser->set_object($handler);
+$parser->set_element_handler('openHandler','closeHandler');
+
+if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
+       $sql = "SELECT *, UNIX_TIMESTAMP(last_modified) AS u_ts FROM ".TABLE_PREFIX."content WHERE course_id=$course_id ORDER BY content_parent_id, ordering";
+} else {
+       $sql = "SELECT *, UNIX_TIMESTAMP(last_modified) AS u_ts FROM ".TABLE_PREFIX."content WHERE course_id=$course_id ORDER BY content_parent_id, ordering";
+}
+$result = mysql_query($sql, $db);
+while ($row = mysql_fetch_assoc($result)) {
+       if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) || $contentManager->isReleased($row['content_id']) === TRUE) {
+               $content[$row['content_parent_id']][] = $row;
+               if ($cid == $row['content_id']) {
+                       $top_content = $row;
+                       $top_content_parent_id = $row['content_parent_id'];
+               }
+       }
+}
+
+
+if ($cid) {
+       /* filter out the top level sections that we don't want */
+       $top_level = $content[$top_content_parent_id];
+       foreach($top_level as $page) {
+               if ($page['content_id'] == $cid) {
+                       $content[$top_content_parent_id] = array($page);
+               } else {
+                       /* this is a page we don't want, so might as well remove it's children too */
+                       unset($content[$page['content_id']]);
+               }
+       }
+       $ims_course_title = $course_title . ' - ' . $content[$top_content_parent_id][0]['title'];
+} else {
+       $ims_course_title = $course_title;
+}
+
+
+/* generate the imsmanifest.xml header attributes */
+$imsmanifest_xml = str_replace(array('{COURSE_TITLE}', '{COURSE_DESCRIPTION}', '{COURSE_PRIMARY_LANGUAGE_CHARSET}', '{COURSE_PRIMARY_LANGUAGE_CODE}'), 
+                                                         array($ims_course_title, $course_desc, $course_language_charset, $course_language_code),
+                                                         $ims_template_xml['header']);
+//debug($imsmanifest_xml);
+//exit;
+
+/* get the first content page to default the body frame to */
+$first = $content[$top_content_parent_id][0];
+
+/* generate the resources and save the HTML files */
+
+$used_glossary_terms = array();
+ob_start();
+print_organizations($top_content_parent_id, $content, 0, '', array(), $toc_html);
+$organizations_str = ob_get_contents();
+ob_end_clean();
+
+
+if (count($used_glossary_terms)) {
+       $used_glossary_terms = array_unique($used_glossary_terms);
+       sort($used_glossary_terms);
+       reset($used_glossary_terms);
+
+       $terms_xml = '';
+       foreach ($used_glossary_terms as $term) {
+               $term_key = urlencode($term);
+               $glossary[$term_key] = str_replace('&', '&amp;', $glossary[$term_key]);
+               $escaped_term = str_replace('&', '&amp;', $term);
+               $terms_xml .= str_replace(      array('{TERM}', '{DEFINITION}'),
+                                                                       array($escaped_term, $glossary[$term_key]),
+                                                                       $glossary_term_xml);
+
+               $terms_html .= str_replace(     array('{ENCODED_TERM}', '{TERM}', '{DEFINITION}'),
+                                                                       array($term_key, $term, $glossary[$term_key]),
+                                                                       $glossary_term_html);
+       }
+
+       $glossary_body_html = str_replace('{BODY}', $terms_html, $glossary_body_html);
+
+       $glossary_xml = str_replace(array('{GLOSSARY_TERMS}', '{COURSE_PRIMARY_LANGUAGE_CHARSET}'),
+                                                           array($terms_xml, $course_language_charset),
+                                                               $glossary_xml);
+       $glossary_html = str_replace(   array('{CONTENT}', '{KEYWORDS}', '{TITLE}', '{COURSE_PRIMARY_LANGUAGE_CHARSET}', '{COURSE_PRIMARY_LANGUAGE_CODE}'),
+                                                                       array($glossary_body_html, '', 'Glossary', $course_language_charset, $course_language_code),
+                                                                       $html_template);
+       $toc_html .= '<ul><li><a href="glossary.html" target="body">'._AT('glossary').'</a></li></ul>';
+} else {
+       unset($glossary_xml);
+}
+
+$toc_html = str_replace(array('{TOC}', '{COURSE_PRIMARY_LANGUAGE_CHARSET}', '{COURSE_PRIMARY_LANGUAGE_CODE}'),
+                                           array($toc_html, $course_language_charset, $course_language_code),
+                                               $html_toc);
+
+if ($first['content_path']) {
+       $first['content_path'] .= '/';
+}
+$frame = str_replace(  array('{COURSE_TITLE}',         '{FIRST_ID}', '{PATH}', '{COURSE_PRIMARY_LANGUAGE_CHARSET}', '{COURSE_PRIMARY_LANGUAGE_CODE}'),
+                                               array($ims_course_title, $first['content_id'], $first['content_path'], $course_language_charset, $course_language_code),
+                                               $html_frame);
+
+$html_mainheader = str_replace(array('{COURSE_TITLE}', '{COURSE_PRIMARY_LANGUAGE_CHARSET}', '{COURSE_PRIMARY_LANGUAGE_CODE}'),
+                                                          array($ims_course_title, $course_language_charset, $course_language_code),
+                                                          $html_mainheader);
+
+
+
+/* append the Organizations and Resources to the imsmanifest */
+$imsmanifest_xml .= str_replace(       array('{ORGANIZATIONS}',        '{RESOURCES}', '{COURSE_TITLE}'),
+                                                                       array($organizations_str,       $resources, $ims_course_title),
+                                                                       $ims_template_xml['final']);
+
+
+/* generate the vcard for the instructor/author */
+$sql = "SELECT first_name, last_name, email, website, login, phone FROM ".TABLE_PREFIX."members WHERE member_id=$instructor_id";
+$result = mysql_query($sql, $db);
+$vcard = new vCard();
+if ($row = mysql_fetch_assoc($result)) {
+       $vcard->setName($row['last_name'], $row['first_name'], $row['login']);
+       $vcard->setEmail($row['email']);
+       $vcard->setNote('Originated from an ATutor at '.AT_BASE_HREF.'. See ATutor.ca for additional information.');
+       $vcard->setURL($row['website']);
+
+       $imsmanifest_xml = str_replace('{VCARD}', $vcard->getVCard(), $imsmanifest_xml);
+} else {
+       $imsmanifest_xml = str_replace('{VCARD}', '', $imsmanifest_xml);
+}
+
+/* save the imsmanifest.xml file */
+
+$zipfile->add_file($frame,                      'index.html');
+$zipfile->add_file($toc_html,           'toc.html');
+$zipfile->add_file($imsmanifest_xml, 'imsmanifest.xml');
+$zipfile->add_file($html_mainheader, 'header.html');
+if ($glossary_xml) {
+       $zipfile->add_file($glossary_xml,  'glossary.xml');
+       $zipfile->add_file($glossary_html, 'glossary.html');
+}
+$zipfile->add_file(file_get_contents(AT_INCLUDE_PATH.'ims/adlcp_rootv1p2.xsd'), 'adlcp_rootv1p2.xsd');
+$zipfile->add_file(file_get_contents(AT_INCLUDE_PATH.'ims/ims_xml.xsd'), 'ims_xml.xsd');
+$zipfile->add_file(file_get_contents(AT_INCLUDE_PATH.'ims/imscp_rootv1p1p2.xsd'), 'imscp_rootv1p1p2.xsd');
+$zipfile->add_file(file_get_contents(AT_INCLUDE_PATH.'ims/imsmd_rootv1p2p1.xsd'), 'imsmd_rootv1p2p1.xsd');
+$zipfile->add_file(file_get_contents(AT_INCLUDE_PATH.'ims/ims.css'), 'ims.css');
+$zipfile->add_file(file_get_contents(AT_INCLUDE_PATH.'ims/footer.html'), 'footer.html');
+$zipfile->add_file(file_get_contents('../../images/logo.gif'), 'logo.gif');
+
+$zipfile->close(); // this is optional, since send_file() closes it anyway
+
+$ims_course_title = str_replace(array(' ', ':'), '_', $ims_course_title);
+/**
+ * A problem here with the preg_replace below.
+ * Originally was designed to remove all werid symbols to avoid file corruptions.
+ * In UTF-8, all non-english chars are considered to be 'werid symbols'
+ * We can still replace it as is, or add fileid to the filename to avoid these problems
+ * Well then again people won't be able to tell what this file is about
+ * If we are going to take out the preg_replace, some OS might not be able to understand
+ * these characters and will have problems importing.
+ */
+$ims_course_title = preg_replace("{[^a-zA-Z0-9._-]}","", trim($ims_course_title));
+$zipfile->send_file($ims_course_title . '_ims');
+
+exit;
+?>
\ No newline at end of file
diff --git a/tools/ims/ims_import.php b/tools/ims/ims_import.php
new file mode 100644 (file)
index 0000000..7a63984
--- /dev/null
@@ -0,0 +1,607 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+require(AT_INCLUDE_PATH.'lib/filemanager.inc.php'); /* for clr_dir() and preImportCallBack and dirsize() */
+require(AT_INCLUDE_PATH.'classes/pclzip.lib.php');
+
+/* make sure we own this course that we're exporting */
+authenticate(AT_PRIV_CONTENT);
+
+/* to avoid timing out on large files */
+@set_time_limit(0);
+$_SESSION['done'] = 1;
+
+$html_head_tags = array("style", "script");
+
+$package_base_path = '';
+$xml_base_path = '';
+$element_path = array();
+$imported_glossary = array();
+
+       /* called at the start of en element */
+       /* builds the $path array which is the path from the root to the current element */
+       function startElement($parser, $name, $attrs) {
+               global $items, $path, $package_base_path;
+               global $element_path;
+               global $xml_base_path;
+               static $current_identifier;
+
+               if ($name == 'manifest' && isset($attrs['xml:base']) && $attrs['xml:base']) {
+                       $xml_base_path = $attrs['xml:base'];
+               } else if ($name == 'file') {
+                       // special case for webCT content packages that don't specify the `href` attribute 
+                       // with the `<resource>` element.
+                       // we take the `href` from the first `<file>` element.
+                       if (isset($items[$current_identifier]) && ($items[$current_identifier]['href'] == '')) {
+                               $items[$current_identifier]['href'] = $attrs['href'];
+
+                               $items[$current_identifier]['href'] = $attrs['href'];
+
+                               $temp_path = pathinfo($attrs['href']);
+                               $temp_path = explode('/', $temp_path['dirname']);
+
+                               if ($package_base_path == '') {
+                                       $package_base_path = $temp_path;
+                               } else {
+                                       $package_base_path = array_intersect($package_base_path, $temp_path);
+                               }
+
+                               $items[$current_identifier]['new_path'] = implode('/', $temp_path);
+                       }
+               } else if (($name == 'item') && ($attrs['identifierref'] != '')) {
+                       $path[] = $attrs['identifierref'];
+               } else if (($name == 'item') && ($attrs['identifier'])) {
+                       $path[] = $attrs['identifier'];
+               } else if (($name == 'resource') && is_array($items[$attrs['identifier']]))  {
+                       $current_identifier = $attrs['identifier'];
+
+                       if ($attrs['href']) {
+                               $items[$attrs['identifier']]['href'] = $attrs['href'];
+
+                               $temp_path = pathinfo($attrs['href']);
+                               $temp_path = explode('/', $temp_path['dirname']);
+                               if (!$package_base_path) {
+                                       $package_base_path = $temp_path;
+                               } else {
+                                       $package_base_path = array_intersect($package_base_path, $temp_path);
+                               }
+
+                               $items[$attrs['identifier']]['new_path'] = implode('/', $temp_path);
+                       }
+               }
+               array_push($element_path, $name);
+       }
+
+       /* called when an element ends */
+       /* removed the current element from the $path */
+       function endElement($parser, $name) {
+               global $path, $element_path, $my_data;
+
+               if ($name == 'item') {
+                       array_pop($path);
+               }
+
+               if ($element_path === array('manifest', 'metadata', 'imsmd:lom', 'imsmd:general', 'imsmd:title', 'imsmd:langstring')) {
+                       global $package_base_name;
+                       $package_base_name = trim($my_data);
+               }
+
+               array_pop($element_path);
+               $my_data = '';
+       }
+
+       /* called when there is character data within elements */
+       /* constructs the $items array using the last entry in $path as the parent element */
+       function characterData($parser, $data){
+               global $path, $items, $order, $my_data, $element_path;
+
+               $str_trimmed_data = trim($data);
+                               
+               if (!empty($str_trimmed_data)) {
+                       $size = count($path);
+                       if ($size > 0) {
+                               $current_item_id = $path[$size-1];
+                               if ($size > 1) {
+                                       $parent_item_id = $path[$size-2];
+                               } else {
+                                       $parent_item_id = 0;
+                               }
+                               if (is_array($items[$current_item_id])) {
+
+                                       /* this item already exists, append the title           */
+                                       /* this fixes {\n, \t, `, &} characters in elements */
+
+                                       /* horible kludge to fix the <ns2:objectiveDesc xmlns:ns2="http://www.utoronto.ca/atrc/tile/xsd/tile_objective"> */
+                                       /* from TILE */
+                                       if ($element_path[count($element_path)-1] != 'ns1:objectiveDesc') {
+                                               $items[$current_item_id]['title'] .= $data;
+                                       }
+       
+                               } else {
+                                       $order[$parent_item_id] ++;
+
+                                       $items[$current_item_id] = array('title'                        => $data,
+                                                                                                       'parent_content_id' => $parent_item_id,
+                                                                                                       'ordering'                      => $order[$parent_item_id]-1);
+                               }
+                       }
+               }
+
+
+               $my_data .= $data;
+       }
+
+       /* glossary parser: */
+       function glossaryStartElement($parser, $name, $attrs) {
+               global $element_path;
+
+               array_push($element_path, $name);
+       }
+
+       /* called when an element ends */
+       /* removed the current element from the $path */
+       function glossaryEndElement($parser, $name) {
+               global $element_path, $my_data, $imported_glossary;
+               static $current_term;
+
+               if ($element_path === array('glossary', 'item', 'term')) {
+                       $current_term = $my_data;
+
+               } else if ($element_path === array('glossary', 'item', 'definition')) {
+                       $imported_glossary[trim($current_term)] = trim($my_data);
+               }
+
+               array_pop($element_path);
+               $my_data = '';
+       }
+
+       function glossaryCharacterData($parser, $data){
+               global $my_data;
+
+               $my_data .= $data;
+       }
+
+if (!isset($_POST['submit']) && !isset($_POST['cancel'])) {
+       /* just a catch all */
+       
+       $errors = array('FILE_MAX_SIZE', ini_get('post_max_size'));
+       $msg->addError($errors);
+
+       header('Location: ./index.php');
+       exit;
+} else if (isset($_POST['cancel'])) {
+       $msg->addFeedback('IMPORT_CANCELLED');
+
+       header('Location: ./index.php');
+       exit;
+}
+
+$cid = intval($_POST['cid']);
+
+if (isset($_POST['url']) && ($_POST['url'] != 'http://') ) {
+       if ($content = @file_get_contents($_POST['url'])) {
+
+               // save file to /content/
+               $filename = substr(time(), -6). '.zip';
+               $full_filename = AT_CONTENT_DIR . $filename;
+
+               if (!$fp = fopen($full_filename, 'w+b')) {
+                       echo "Cannot open file ($filename)";
+                       exit;
+               }
+
+               if (fwrite($fp, $content, strlen($content) ) === FALSE) {
+                       echo "Cannot write to file ($filename)";
+                       exit;
+               }
+               fclose($fp);
+       }       
+       $_FILES['file']['name']     = $filename;
+       $_FILES['file']['tmp_name'] = $full_filename;
+       $_FILES['file']['size']     = strlen($content);
+       unset($content);
+       $url_parts = pathinfo($_POST['url']);
+       $package_base_name_url = $url_parts['basename'];
+}
+$ext = pathinfo($_FILES['file']['name']);
+$ext = $ext['extension'];
+
+if ($ext != 'zip') {
+       $msg->addError('IMPORTDIR_IMS_NOTVALID');
+} else if ($_FILES['file']['error'] == 1) {
+       $errors = array('FILE_MAX_SIZE', ini_get('upload_max_filesize'));
+       $msg->addError($errors);
+} else if ( !$_FILES['file']['name'] || (!is_uploaded_file($_FILES['file']['tmp_name']) && !$_POST['url'])) {
+       $msg->addError('FILE_NOT_SELECTED');
+} else if ($_FILES['file']['size'] == 0) {
+       $msg->addError('IMPORTFILE_EMPTY');
+} 
+
+if ($msg->containsErrors()) {
+       if (isset($_GET['tile'])) {
+               header('Location: '.$_base_path.'tools/tile/index.php');
+       } else {
+               header('Location: index.php');
+       }
+       exit;
+}
+
+/* check if ../content/import/ exists */
+$import_path = AT_CONTENT_DIR . 'import/';
+$content_path = AT_CONTENT_DIR;
+
+if (!is_dir($import_path)) {
+       if (!@mkdir($import_path, 0700)) {
+               $msg->addError('IMPORTDIR_FAILED');
+       }
+}
+
+$import_path .= $_SESSION['course_id'].'/';
+if (is_dir($import_path)) {
+       clr_dir($import_path);
+}
+
+if (!@mkdir($import_path, 0700)) {
+       $msg->addError('IMPORTDIR_FAILED');
+}
+
+if ($msg->containsErrors()) {
+       if (isset($_GET['tile'])) {
+               header('Location: '.$_base_path.'tools/tile/index.php');
+       } else {
+               header('Location: index.php');
+       }
+       exit;
+}
+
+/* extract the entire archive into AT_COURSE_CONTENT . import/$course using the call back function to filter out php files */
+error_reporting(0);
+$archive = new PclZip($_FILES['file']['tmp_name']);
+if ($archive->extract( PCLZIP_OPT_PATH,        $import_path,
+                                               PCLZIP_CB_PRE_EXTRACT,  'preImportCallBack') == 0) {
+       $msg->addError('IMPORT_FAILED');
+       echo 'Error : '.$archive->errorInfo(true);
+       clr_dir($import_path);
+       header('Location: index.php');
+       exit;
+}
+error_reporting(AT_ERROR_REPORTING);
+
+/* get the course's max_quota */
+$sql   = "SELECT max_quota FROM ".TABLE_PREFIX."courses WHERE course_id=$_SESSION[course_id]";
+$result = mysql_query($sql, $db);
+$q_row = mysql_fetch_assoc($result);
+
+if ($q_row['max_quota'] != AT_COURSESIZE_UNLIMITED) {
+
+       if ($q_row['max_quota'] == AT_COURSESIZE_DEFAULT) {
+               $q_row['max_quota'] = $MaxCourseSize;
+       }
+       $totalBytes   = dirsize($import_path);
+       $course_total = dirsize(AT_CONTENT_DIR . $_SESSION['course_id'].'/');
+       $total_after  = $q_row['max_quota'] - $course_total - $totalBytes + $MaxCourseFloat;
+
+       if ($total_after < 0) {
+               /* remove the content dir, since there's no space for it */
+               $errors = array('NO_CONTENT_SPACE', number_format(-1*($total_after/AT_KBYTE_SIZE), 2 ) );
+               $msg->addError($errors);
+               
+               clr_dir($import_path);
+
+               if (isset($_GET['tile'])) {
+                       header('Location: '.$_base_path.'tools/tile/index.php');
+               } else {
+                       header('Location: index.php');
+               }
+               exit;
+       }
+}
+
+
+$items = array(); /* all the content pages */
+$order = array(); /* keeps track of the ordering for each content page */
+$path  = array();  /* the hierarchy path taken in the menu to get to the current item in the manifest */
+
+/*
+$items[content_id/resource_id] = array(
+                                                                       'title'
+                                                                       'real_content_id' // calculated after being inserted
+                                                                       'parent_content_id'
+                                                                       'href'
+                                                                       'ordering'
+                                                                       );
+*/
+
+$ims_manifest_xml = @file_get_contents($import_path.'imsmanifest.xml');
+
+if ($ims_manifest_xml === false) {
+       $msg->addError('NO_IMSMANIFEST');
+
+       if (file_exists($import_path . 'atutor_backup_version')) {
+               $msg->addError('NO_IMS_BACKUP');
+       }
+
+       clr_dir($import_path);
+
+       if (isset($_GET['tile'])) {
+               header('Location: '.$_base_path.'tools/tile/index.php');
+       } else {
+               header('Location: index.php');
+       }
+       exit;
+}
+
+$xml_parser = xml_parser_create();
+
+xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false); /* conform to W3C specs */
+xml_set_element_handler($xml_parser, 'startElement', 'endElement');
+xml_set_character_data_handler($xml_parser, 'characterData');
+
+if (!xml_parse($xml_parser, $ims_manifest_xml, true)) {
+       die(sprintf("XML error: %s at line %d",
+                               xml_error_string(xml_get_error_code($xml_parser)),
+                               xml_get_current_line_number($xml_parser)));
+}
+
+
+xml_parser_free($xml_parser);
+//debug($items);
+
+/* check if the glossary terms exist */
+if (file_exists($import_path . 'glossary.xml')){
+       $glossary_xml = @file_get_contents($import_path.'glossary.xml');
+       $element_path = array();
+
+       $xml_parser = xml_parser_create();
+
+       /* insert the glossary terms into the database (if they're not in there already) */
+       /* parse the glossary.xml file and insert the terms */
+       xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false); /* conform to W3C specs */
+       xml_set_element_handler($xml_parser, 'glossaryStartElement', 'glossaryEndElement');
+       xml_set_character_data_handler($xml_parser, 'glossaryCharacterData');
+
+       if (!xml_parse($xml_parser, $glossary_xml, true)) {
+               debug($glossary_xml);
+               die(sprintf("XML error: %s at line %d",
+                                       xml_error_string(xml_get_error_code($xml_parser)),
+                                       xml_get_current_line_number($xml_parser)));
+       }
+       xml_parser_free($xml_parser);
+       $contains_glossary_terms = true;
+       foreach ($imported_glossary as $term => $defn) {
+               if (!$glossary[urlencode($term)]) {
+                       $sql = "INSERT INTO ".TABLE_PREFIX."glossary VALUES (NULL, $_SESSION[course_id], '$term', '$defn', 0)";
+                       mysql_query($sql, $db); 
+               }
+       }
+}
+
+
+/* generate a unique new package base path based on the package file name and date as needed. */
+/* the package name will be the dir where the content for this package will be put, as a result */
+/* the 'content_path' field in the content table will be set to this path. */
+/* $package_base_name_url comes from the URL file name (NOT the file name of the actual file we open)*/
+if (!$package_base_name && $package_base_name_url) {
+       $package_base_name = substr($package_base_name_url, 0, -4);
+} else if (!$package_base_name) {
+       $package_base_name = substr($_FILES['file']['name'], 0, -4);
+}
+
+$package_base_name = strtolower($package_base_name);
+$package_base_name = str_replace(array('\'', '"', ' ', '|', '\\', '/', '<', '>', ':'), '_' , $package_base_name);
+$package_base_name = preg_replace("/[^A-Za-z0-9._\-]/", '', $package_base_name);
+
+if (is_dir(AT_CONTENT_DIR . $_SESSION['course_id'].'/'.$package_base_name)) {
+       $package_base_name .= '_'.date('ymdHis');
+}
+
+
+if ($package_base_path) {
+       $package_base_path = implode('/', $package_base_path);
+}
+if ($xml_base_path) {
+       $package_base_path = $xml_base_path . $package_base_path;
+
+       mkdir(AT_CONTENT_DIR .$_SESSION['course_id'].'/'.$xml_base_path);
+       $package_base_name = $xml_base_path . $package_base_name;
+}
+reset($items);
+
+/* get the top level content ordering offset */
+$sql   = "SELECT MAX(ordering) AS ordering FROM ".TABLE_PREFIX."content WHERE course_id=$_SESSION[course_id] AND content_parent_id=$cid";
+$result = mysql_query($sql, $db);
+$row   = mysql_fetch_assoc($result);
+$order_offset = intval($row['ordering']); /* it's nice to have a real number to deal with */
+       
+       foreach ($items as $item_id => $content_info) {
+               if (isset($content_info['href'], $xml_base_path)) {
+                       $content_info['href'] = $xml_base_path . $content_info['href'];
+               }
+               if (!isset($content_info['href'])) {
+                       // this item doesn't have an identifierref. so create an empty page.
+                       $content = '';
+                       $ext = '';
+                       $last_modified = date('Y-m-d H:i:s');
+               } else {
+                       $file_info = @stat(AT_CONTENT_DIR . 'import/'.$_SESSION['course_id'].'/'.$content_info['href']);
+                       if ($file_info === false) {
+                               continue;
+                       }
+               
+                       $path_parts = pathinfo(AT_CONTENT_DIR . 'import/'.$_SESSION['course_id'].'/'.$content_info['href']);
+                       $ext = strtolower($path_parts['extension']);
+
+                       $last_modified = date('Y-m-d H:i:s', $file_info['mtime']);
+               }
+               if (in_array($ext, array('gif', 'jpg', 'bmp', 'png', 'jpeg'))) {
+                       /* this is an image */
+                       $content = '<img src="'.$content_info['href'].'" alt="'.$content_info['title'].'" />';
+               } else if ($ext == 'swf') {
+                       /* this is flash */
+            /* Using default size of 550 x 400 */
+
+                       $content = '<object type="application/x-shockwave-flash" data="' . $content_info['href'] . '" width="550" height="400"><param name="movie" value="'. $content_info['href'] .'" /></object>';
+
+               } else if ($ext == 'mov') {
+                       /* this is a quicktime movie  */
+            /* Using default size of 550 x 400 */
+
+                       $content = '<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" width="550" height="400" codebase="http://www.apple.com/qtactivex/qtplugin.cab"><param name="src" value="'. $content_info['href'] . '" /><param name="autoplay" value="true" /><param name="controller" value="true" /><embed src="' . $content_info['href'] .'" width="550" height="400" controller="true" pluginspage="http://www.apple.com/quicktime/download/"></embed></object>';
+               } else if ($ext == 'mp3') {
+                       $content = '<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" width="200" height="15" codebase="http://www.apple.com/qtactivex/qtplugin.cab"><param name="src" value="'. $content_info['href'] . '" /><param name="autoplay" value="false" /><embed src="' . $content_info['href'] .'" width="200" height="15" autoplay="false" pluginspage="http://www.apple.com/quicktime/download/"></embed></object>';
+               } else if (in_array($ext, array('wav', 'au'))) {
+                       $content = '<embed SRC="'.$content_info['href'].'" autostart="false" width="145" height="60"><noembed><bgsound src="'.$content_info['href'].'"></noembed></embed>';
+
+               } else if (in_array($ext, array('txt', 'css', 'html', 'htm', 'csv', 'asc', 'tsv', 'xml', 'xsl'))) {
+                       /* this is a plain text file */
+                       $content = file_get_contents(AT_CONTENT_DIR . 'import/'.$_SESSION['course_id'].'/'.$content_info['href']);
+                       if ($content === false) {
+                               /* if we can't stat() it then we're unlikely to be able to read it */
+                               /* so we'll never get here. */
+                               continue;
+                       }
+
+                       // get the contents of the 'head' element
+                       $head = get_html_head_by_tag($content, $html_head_tags);
+                       
+                       // Specifically handle eXe package
+                       // NOTE: THIS NEEDS WORK! TO FIND A WAY APPLY EXE .CSS FILES ONLY ON COURSE CONTENT PART.
+                       // NOW USE OUR OWN .CSS CREATED SOLELY FOR EXE
+                       $isExeContent = false;
+
+                       // check xml file in eXe package
+                       if (preg_match("/<organization[ ]*identifier=\"eXe*>*/", $ims_manifest_xml))
+                       {
+                               $isExeContent = true;
+                       }
+
+                       // use ATutor's eXe style sheet as the ones from eXe conflicts with ATutor's style sheets
+                       if ($isExeContent)
+                       {
+                               $head = preg_replace ('/(<style.*>)(.*)(<\/style>)/ms', '\\1@import url(/docs/exestyles.css);\\3', $head);
+                       }
+
+                       // end of specifically handle eXe package
+
+                       $content = get_html_body($content);
+                       if ($contains_glossary_terms) 
+                       {
+                               // replace glossary content package links to real glossary mark-up using [?] [/?]
+                               $content = preg_replace('/<a href="([.\w\d\s]+[^"]+)" target="body" class="at-term">([.\w\d\s&;"]+)<\/a>/i', '[?]\\2[/?]', $content);
+                       }
+
+                       /* potential security risk? */
+                       if ( strpos($content_info['href'], '..') === false) {
+                               @unlink(AT_CONTENT_DIR . 'import/'.$_SESSION['course_id'].'/'.$content_info['href']);
+                       }
+               } else if ($ext) {
+                       /* non text file, and can't embed (example: PDF files) */
+                       $content = '<a href="'.$content_info['href'].'">'.$content_info['title'].'</a>';
+               }
+
+               $content_parent_id = $cid;
+               if ($content_info['parent_content_id'] !== 0) {
+                       $content_parent_id = $items[$content_info['parent_content_id']]['real_content_id'];
+               }
+
+               $my_offset = 0;
+               if ($content_parent_id == $cid) {
+                       $my_offset = $order_offset;
+               }
+
+               /* replace the old path greatest common denomiator with the new package path. */
+               /* we don't use str_replace, b/c there's no knowing what the paths may be         */
+               /* we only want to replace the first part of the path.                                            */
+               if ($package_base_path != '') {
+                       $content_info['new_path']       = $package_base_name . substr($content_info['new_path'], strlen($package_base_path));
+               } else {
+                       $content_info['new_path'] = $package_base_name;
+               }
+               
+               $head = addslashes($head);
+               $content_info['title'] = addslashes($content_info['title']);
+               $content = addslashes($content);
+
+               $sql= 'INSERT INTO '.TABLE_PREFIX.'content'
+                     . '(course_id, 
+                         content_parent_id, 
+                         ordering,
+                         last_modified, 
+                         revision, 
+                         formatting, 
+                         release_date,
+                         head,
+                         use_customized_head,
+                         keywords, 
+                         content_path, 
+                         title, 
+                         text) 
+                      VALUES 
+                                    ('.$_SESSION['course_id'].','                                                                                                                      
+                                    .$content_parent_id.','            
+                                    .($content_info['ordering'] + $my_offset + 1).','
+                                    .'"'.$last_modified.'",                                                                                                    
+                                     0,
+                                     1,
+                                     NOW(),"'
+                                    . $head .'",
+                                    1,
+                                     "",'
+                                    .'"'.$content_info['new_path'].'",'
+                                    .'"'.$content_info['title'].'",'
+                                    .'"'.$content.'")';
+
+               $result = mysql_query($sql, $db) or die(mysql_error());
+
+               /* get the content id and update $items */
+               $items[$item_id]['real_content_id'] = mysql_insert_id($db);
+       }
+
+       if ($package_base_path == '.') {
+               $package_base_path = '';
+       }
+
+       if (@rename(AT_CONTENT_DIR . 'import/'.$_SESSION['course_id'].'/'.$package_base_path, AT_CONTENT_DIR .$_SESSION['course_id'].'/'.$package_base_name) === false) {
+               if (!$msg->containsErrors()) {
+                       $msg->addError('IMPORT_FAILED');
+               }
+       }
+       clr_dir(AT_CONTENT_DIR . 'import/'.$_SESSION['course_id']);
+
+       if (isset($_POST['url'])) {
+               @unlink($full_filename);
+       }
+
+
+if ($_POST['s_cid']){
+       if (!$msg->containsErrors()) {
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       }
+       header('Location: ../../editor/edit_content.php?cid='.intval($_POST['cid']));
+       exit;
+} else {
+       if (!$msg->containsErrors()) {
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       }
+       if ($_GET['tile']) {
+               header('Location: '.AT_BASE_HREF.'tools/tile/index.php');
+       } else {
+               header('Location: ./index.php?cid='.intval($_POST['cid']));
+       }
+       exit;
+}
+
+?>
\ No newline at end of file
diff --git a/tools/ims/index.php b/tools/ims/index.php
new file mode 100644 (file)
index 0000000..345542d
--- /dev/null
@@ -0,0 +1,158 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if (!isset($_main_menu)) {
+       $_main_menu = $contentManager->getContent();
+}
+
+function print_menu_sections(&$menu, $parent_content_id = 0, $depth = 0, $ordering = '') {
+       $my_children = $menu[$parent_content_id];
+       $cid = $_GET['cid'];
+
+       if (!is_array($my_children)) {
+               return;
+       }
+       foreach ($my_children as $children) {
+               echo '<option value="'.$children['content_id'].'"';
+               if ($cid == $children['content_id']) {
+                       echo ' selected="selected"';
+               }
+               echo '>';
+               echo str_pad('', $depth, '-') . ' ';
+               if ($parent_content_id == 0) {
+                       $new_ordering = $children['ordering'];
+                       echo $children['ordering'];
+               } else {
+                       $new_ordering = $ordering.'.'.$children['ordering'];
+                       echo $ordering . '.'. $children['ordering'];
+               }
+               echo ' '.$children['title'].'</option>';
+
+               print_menu_sections($menu, $children['content_id'], $depth+1, $new_ordering);
+       }
+}
+
+if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && ($_SESSION['packaging'] == 'none')) {
+       echo '<p>'._AT('content_packaging_disabled').'</p>';
+       require (AT_INCLUDE_PATH.'footer.inc.php'); 
+       exit;
+} else if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && ($_SESSION['packaging'] == 'top')) {
+       $_main_menu = array($_main_menu[0]);
+}
+?>
+<form method="post" action="tools/ims/ims_export.php">
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('export_content'); ?></legend>
+       <div class="row">
+               <p><?php echo _AT('export_content_info'); ?></p>
+       </div>
+
+<?php if ($_main_menu[0]): ?>
+       <div class="row">
+               <label for="select_cid"><?php echo _AT('export_content_package_what'); ?></label><br />
+               <select name="cid" id="select_cid">
+                       <option value="0"><?php echo _AT('export_entire_course_or_chap'); ?></option>
+                       <option value="0"></option>
+                       <?php
+                               print_menu_sections($_main_menu);
+                       ?>
+               </select>
+       </div>
+
+       <?php if (authenticate(AT_PRIV_ADMIN, AT_PRIV_RETURN)): ?>
+                       <div class="row">
+                               <input type="checkbox" name="to_tile" id="to_tile" value="1" />
+                               <label for="to_tile"><?php echo _AT('tile_export'); ?></label>
+                       </div>
+       <?php endif; ?>
+       
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('export'); ?>" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+<?php else: ?>
+       <div class="row">
+               <strong><?php echo _AT('none_found'); ?></strong>
+       </div>
+<?php endif; ?>
+
+</div>
+</form>
+
+<?php if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
+               require (AT_INCLUDE_PATH.'footer.inc.php'); 
+               exit;
+}
+?>
+<br /><br />
+
+
+<form name="form1" method="post" action="tools/ims/ims_import.php" enctype="multipart/form-data" onsubmit="openWindow('<?php echo AT_BASE_HREF; ?>tools/prog.php');">
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('import_content'); ?></legend>
+       <div class="row">
+
+               <p><?php echo _AT('import_content_info'); ?></p>
+       </div>
+
+       <div class="row">
+               <label for="select_cid2"><?php echo _AT('import_content_package_where'); ?></label><br />
+               <select name="cid" id="select_cid2">
+                       <option value="0"><?php echo _AT('import_content_package_bottom_subcontent'); ?></option>
+                       <option value="0"></option>
+                       <?php
+                               print_menu_sections($_main_menu);
+                       ?>
+               </select>
+       </div>
+       
+       <div class="row">
+               <label for="to_file"><?php echo _AT('upload_content_package'); ?></label><br />
+               <input type="file" name="file" id="to_file" />
+       </div>
+
+       <div class="row">
+               <label for="to_url"><?php echo _AT('specify_url_to_content_package'); ?></label><br />
+               <input type="text" name="url" value="http://" size="40" id="to_url" />
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" onclick="setClickSource('submit');" value="<?php echo _AT('import'); ?>" />
+               <input type="submit" name="cancel" onclick="document.form1.enctype='';setClickSource('cancel');" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+</div>
+</form>
+
+<script language="javascript" type="text/javascript">
+
+var but_src;
+function setClickSource(name) {
+       but_src = name;
+}
+
+function openWindow(page) {
+       if (but_src != "cancel") {
+               newWindow = window.open(page, "progWin", "width=400,height=200,toolbar=no,location=no");
+               newWindow.focus();
+       }
+}
+</script>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/index.php b/tools/index.php
new file mode 100644 (file)
index 0000000..2ee490e
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$module_list = $moduleFactory->getModules(AT_MODULE_STATUS_ENABLED, 0, TRUE);
+$keys = array_keys($module_list);
+
+echo '<ol id="tools">';
+foreach ($keys as $module_name) {
+       $module =& $module_list[$module_name];
+       if ($module->getPrivilege() && authenticate($module->getPrivilege(), AT_PRIV_RETURN) && ($parent = $module->getChildPage('tools/index.php'))) {
+               echo '<li class="top-tool"><a href="' . $parent . '">' . $module->getName() . '</a>  ';
+               if (isset($_pages[$parent]['children'])) {
+                       echo '<ul class="child-top-tool">';
+                       foreach ($_pages[$parent]['children'] as $child) {
+                               echo '<li class="child-tool"><a href="'.$child.'">'._AT($_pages[$child]['title_var']).'</a></li>';
+                       }
+                       echo '</ul>';
+               }
+               echo '</li>';
+       }
+}
+echo '</ol>';
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/tools/links/add.php b/tools/links/add.php
new file mode 100644 (file)
index 0000000..491b260
--- /dev/null
@@ -0,0 +1,173 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+require (AT_INCLUDE_PATH.'lib/links.inc.php');
+
+if (!manage_links()) {
+       $msg->addError('ACCESS_DENIED');
+       header('Location: '.AT_BASE_HREF.'links/index.php');
+       exit;
+}
+
+if (!isset($_POST['approved'])) {
+       $_POST['approved'] = 1;
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'tools/links/index.php');
+       exit;
+} 
+
+if (isset($_POST['add_link']) && isset($_POST['submit'])) {
+
+       //check category_id and see if user is allowed..
+       $cat = explode('-', $_POST['cat']);
+       $cat_id = intval($cat[0]);
+       $owner_type = intval($cat[1]);
+       $owner_id = intval($cat[2]);
+
+       if (!links_authenticate($owner_type, $owner_id)) {
+               $msg->addError('ACCESS_DENIED');
+               header('Location: '.AT_BASE_HREF.'links/index.php');
+               exit;
+       }
+
+       $missing_fields = array();
+       if ($_POST['cat'] == 0 || $_POST['cat'] == '') {
+               $missing_fields[] = _AT('category');
+       }
+       if (trim($_POST['title']) == '') {
+               $missing_fields[] = _AT('title');
+       }
+       if (trim($_POST['url']) == '' || $_POST['url'] == 'http://') {
+               $missing_fields[] = _AT('url');
+       }
+       if (trim($_POST['description']) == '') {
+               $missing_fields[] = _AT('description');
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       if (!$msg->containsErrors() && isset($_POST['submit'])) {
+               $_POST['title']  = $addslashes($_POST['title']);
+               $_POST['url'] == $addslashes($_POST['url']);
+               $_POST['description']  = $addslashes($_POST['description']);
+
+               //Check length of the post, if it's exceeded 64 as defined in the db. 
+               $_POST['title'] = validate_length($_POST['title'], 64);
+               $_POST['description'] = validate_length($_POST['description'], 250);
+               
+               $name = get_display_name($_SESSION['member_id']);
+               $email = '';
+
+               $approved = intval($_POST['approved']);
+
+               $sql = "INSERT INTO ".TABLE_PREFIX."links VALUES (NULL, $cat_id, '$_POST[url]', '$_POST[title]', '$_POST[description]', $approved, '$name', '$email', NOW(), 0)";
+               mysql_query($sql, $db);
+       
+               $msg->addFeedback('LINK_ADDED');
+
+               header('Location: '.AT_BASE_HREF.'tools/links/index.php');
+               exit;
+       } else {
+               $_POST['title']  = stripslashes($_POST['title']);
+               $_POST['url'] == stripslashes($_POST['url']);
+               $_POST['description']  = stripslashes($_POST['description']);
+       }
+}
+
+if (!isset($_POST['url'])) {
+       $_POST['url'] = 'http://';
+}
+
+$categories = get_link_categories(true);
+
+if (empty($categories)) {
+       $msg->addError('LINK_CAT_EMPTY');
+       header('Location: '.AT_BASE_HREF.'tools/links/index.php');
+       exit;
+}
+
+$onload = 'document.form.title.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$msg->printErrors();
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="add_link" value="true" />
+
+<div class="input-form">
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php echo _AT('title'); ?></label><br />
+               <input type="text" name="title" size="40" id="title" value="<?php echo $_POST['title']; ?>"/>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="cat"><?php echo _AT('category'); ?></label><br />
+               <select name="cat" id="cat"><?php
+                       if ($pcat_id) {
+                               $current_cat_id = $pcat_id;
+                               $exclude = false; /* don't exclude the children */
+                       } else {
+                               $current_cat_id = $cat_id;
+                               $exclude = true; /* exclude the children */
+                       }
+                       select_link_categories($categories, 0, $_POST['cat'], FALSE, '', TRUE);
+                       ?>
+               </select>
+       </div>
+       
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="url"><?php echo _AT('url'); ?></label><br />
+               <input type="text" name="url" size="40" id="url" value="<?php echo $_POST['url']; ?>" />
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="description"><?php echo _AT('description'); ?></label><br />
+               <textarea name="description" cols="55" rows="5" id="description" style="width:90%;"><?php echo $_POST['description']; ?></textarea>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('approve'); ?><br />
+               <?php
+                       if ($_POST['approved']) {
+                               $y = 'checked="checked"';
+                               $n = '';
+                       } else if (isset ($_POST['approved'])) {
+                               $n = 'checked="checked"';
+                               $y = '';
+                       } else {
+                               $y = 'checked="checked"';
+                               $n = '';
+                       }
+               ?>
+               <input type="radio" id="yes" name="approved" value="1" <?php echo $y; ?>><label for="yes"><?php echo _AT('yes'); ?></label>  <input type="radio" id="no" name="approved" value="0" <?php echo $n; ?>><label for="no"><?php echo _AT('no'); ?></label>
+       </div>
+       
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?> " />
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/links/categories.php b/tools/links/categories.php
new file mode 100644 (file)
index 0000000..7cb537a
--- /dev/null
@@ -0,0 +1,110 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2003 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require (AT_INCLUDE_PATH.'lib/links.inc.php');\r
+\r
+if (!manage_links()) {\r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: '.AT_BASE_HREF.'links/index.php');\r
+       exit;\r
+}\r
+\r
+if ((isset($_POST['delete']) || isset($_POST['edit'])) && !isset($_POST['cat_id'])) {\r
+               $msg->addError('NO_ITEM_SELECTED');\r
+} else if (isset($_POST['delete'])) {\r
+       //check if links are in the cat\r
+       $sql    = "SELECT link_id FROM ".TABLE_PREFIX."links WHERE cat_id=$_POST[cat_id]";\r
+       $result = mysql_query($sql, $db);\r
+    if ($row = mysql_fetch_assoc($result)) {\r
+               $msg->addError('LINK_CAT_NOT_EMPTY');\r
+       } else {\r
+               header('Location: categories_delete.php?cat_id='.$_POST['cat_id']);\r
+               exit;\r
+       }\r
+} else if (isset($_POST['edit'])) {\r
+       header('Location: categories_edit.php?cat_id='.$_POST['cat_id']);\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+\r
+\r
+?>\r
+<form name="form" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<table summary="" class="data" rules="cols" align="center" style="width: 70%;">\r
+<thead>\r
+<tr>\r
+       <th scope="col">&nbsp;</th>\r
+       <th scope="col"><?php echo _AT('name'); ?></th>\r
+       <th scope="col"><?php echo _AT('parent'); ?></th>\r
+</tr>\r
+</thead>\r
+\r
+<?php\r
+$categories = get_link_categories(true, true);\r
+\r
+if (!empty($categories)) { ?>\r
+       <tfoot>\r
+       <tr>\r
+               <td colspan="4">\r
+                       <div class="row buttons">\r
+                       <input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /> \r
+                       </div>\r
+               </td>\r
+       </tr>\r
+       </tfoot>\r
+       <tbody>\r
+\r
+<?php foreach ($categories as $id=>$row) {\r
+\r
+               if (!empty($row['cat_name'])) {\r
+\r
+               $parent_cat_name = '';\r
+               if ($row['cat_parent']) {\r
+                       $sql_cat        = "SELECT name, owner_id, owner_type FROM ".TABLE_PREFIX."links_categories WHERE cat_id=".$row['cat_parent'];\r
+                       $result_cat = mysql_query($sql_cat, $db);\r
+                       $row_cat = mysql_fetch_assoc($result_cat);\r
+                       $parent_cat_name = AT_print($row_cat['name'], 'links_categories.name');\r
+\r
+                       if (empty($parent_cat_name)) {\r
+                               $parent_cat_name = get_group_name($row_cat['owner_id']);\r
+                       }\r
+               } else {\r
+                       $parent_cat_name = '<em>'._AT('none').'</em>';\r
+               }\r
+       ?>\r
+               <tr onmousedown="document.form['m<?php echo $id; ?>'].checked = true;rowselect(this);" id="r_<?php echo $id; ?>">\r
+                       <td width="10"><input type="radio" name="cat_id" value="<?php echo $id; ?>" id="m<?php echo $id; ?>" /></td>\r
+                       <td><label for="m<?php echo $id; ?>"><?php echo AT_print($row['cat_name'], 'members.first_name'); ?></label></td>\r
+                       <td><?php echo $parent_cat_name; ?></td>\r
+               </tr>\r
+               </tbody>\r
+\r
+<?php\r
+               } \r
+       }?>\r
+<?php\r
+} else { ?>\r
+       <tr>\r
+               <td colspan="3"><?php echo _AT('none_found'); ?></td>\r
+       </tr>\r
+<?php } ?>\r
+\r
+\r
+</table>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/links/categories_create.php b/tools/links/categories_create.php
new file mode 100644 (file)
index 0000000..fb8103f
--- /dev/null
@@ -0,0 +1,124 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require (AT_INCLUDE_PATH.'lib/links.inc.php');\r
+\r
+if (!manage_links()) {\r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: '.AT_BASE_HREF.'links/index.php');\r
+       exit;\r
+}\r
+\r
+if (isset($_POST['submit'])) {\r
+       $cat_parent_id  = intval($_POST['cat_parent_id']);\r
+       $cat_name       = trim($_POST['cat_name']);\r
+       $cat_name               = $addslashes($cat_name);\r
+\r
+       if ($cat_name == '') {\r
+               $msg->addError(array('EMPTY_FIELDS', _AT('title')));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+\r
+               if (!empty($cat_parent_id)) {\r
+                       $cat_parent_id = explode('-', $_POST['cat_parent_id']);\r
+                       $parent_id = intval($cat_parent_id[0]);\r
+                       $owner_type = intval($cat_parent_id[1]);\r
+                       $owner_id = intval($cat_parent_id[2]);\r
+\r
+                       if (!links_authenticate($owner_type, $owner_id)) {\r
+                               $msg->addError('ACCESS_DENIED');\r
+                               header('Location: '.AT_BASE_HREF.'index.php');\r
+                               exit;\r
+                       }\r
+               } else {\r
+                       $owner_type = LINK_CAT_COURSE;\r
+                       $owner_id = $_SESSION['course_id'];\r
+                       $parent_id = 0;\r
+               }\r
+\r
+               //Check length of the post, if it's exceeded 100 as defined in the db. \r
+               if ($strlen($cat_name) > 100){\r
+                       $cat_name = $substr($cat_name, 0, 100);\r
+               }\r
+\r
+               $sql = "INSERT INTO ".TABLE_PREFIX."links_categories VALUES (NULL, $owner_type, $owner_id, '$cat_name', $parent_id)";\r
+               $result = mysql_query($sql, $db);\r
+\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+               \r
+               header('Location: categories.php');\r
+               exit;\r
+       }\r
+} else if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: categories.php');\r
+       exit;\r
+}\r
+\r
+\r
+/* $categories[category_id] = array(cat_name, cat_parent, num_courses, [array(children)]) */\r
+$categories = get_link_categories(true);\r
+\r
+$onload = 'document.form.category_name.focus();';\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php'); \r
+$msg->printAll();\r
+\r
+?>\r
+\r
+<form action ="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">\r
+\r
+<div class="input-form">\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="category_name"><?php echo _AT('title'); ?></label><br />\r
+               <input type="text" id="category_name" name="cat_name" value="<?php echo stripslashes(htmlspecialchars($categories[$cat_id]['cat_name'])); ?>" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <label for="category_parent"><?php echo _AT('cats_parent_category'); ?></label><br />\r
+               <?php if ($categories): ?>\r
+                       <select name="cat_parent_id" id="category_parent">\r
+                       <?php\r
+                               if ($pcat_id) {\r
+                                       $current_cat_id = $pcat_id;\r
+                                       $exclude = false; /* don't exclude the children */\r
+                               } else {\r
+                                       $current_cat_id = $cat_id;\r
+                                       $exclude = true; /* exclude the children */\r
+                               }\r
+                               \r
+                               $auth = manage_links();\r
+                               if ($auth == LINK_CAT_AUTH_ALL) {\r
+                                       echo '<option value="0"></option>';\r
+                               }\r
+\r
+                               select_link_categories($categories, 0, $current_cat_id, $exclude, 0, TRUE); \r
+                       ?>\r
+                       </select>\r
+               <?php else: \r
+                       echo _AT('cats_no_categories');\r
+               endif; ?>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>"  />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/links/categories_delete.php b/tools/links/categories_delete.php
new file mode 100644 (file)
index 0000000..f9be6ce
--- /dev/null
@@ -0,0 +1,78 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require (AT_INCLUDE_PATH.'lib/links.inc.php');\r
+\r
+if (!manage_links()) {\r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: '.AT_BASE_HREF.'links/index.php');\r
+       exit;\r
+}\r
+\r
+$cat_id = intval($_REQUEST['cat_id']);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: categories.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       /* delete has been confirmed, delete this category */\r
+       $owner_type     = intval($_POST['owner_type']);\r
+       $owner_id       = intval($_POST['owner_id']);\r
+       //OR get_cat_info() again incase data has ben tampered?\r
+\r
+       if (!links_authenticate($owner_type, $owner_id)) {\r
+               $msg->addError('ACCESS_DENIED');\r
+               header('Location: '.AT_BASE_HREF.'tools/links/categories.php');\r
+               exit;\r
+       }\r
+\r
+       //check if there are sub cats within this cat, or links\r
+       $sql = "SELECT C.cat_id, L.link_id FROM ".TABLE_PREFIX."links_categories C, ".TABLE_PREFIX."links L WHERE C.parent_id=$cat_id OR L.cat_id=$cat_id";\r
+       $result = mysql_query($sql, $db);\r
+       if (mysql_num_rows($result) == 0) {\r
+               $sql = "DELETE FROM ".TABLE_PREFIX."links_categories WHERE owner_id=$owner_id AND owner_type=$owner_type AND cat_id=$cat_id";\r
+               $result = mysql_query($sql, $db);\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       } else {\r
+               $msg->addError('LINK_CAT_NOT_EMPTY');\r
+       }\r
+\r
+       header('Location: categories.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+       $row = get_cat_info($cat_id);\r
+\r
+       if (empty($row)) {\r
+               $msg->printErrors('ITEM_NOT_FOUND');\r
+       } else {\r
+               $hidden_vars['cat_name']= $row['name'];\r
+               $hidden_vars['cat_id']  = $row['cat_id'];\r
+               $hidden_vars['owner_type']      = $row['owner_type'];\r
+               $hidden_vars['owner_id']        = $row['owner_id'];\r
+\r
+               $confirm = array('DELETE_CATEGORY', AT_print($row['name'], 'links_categories.name'));\r
+               $msg->addConfirm($confirm, $hidden_vars);\r
+               \r
+               $msg->printConfirm();\r
+       }\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+\r
+?>
\ No newline at end of file
diff --git a/tools/links/categories_edit.php b/tools/links/categories_edit.php
new file mode 100644 (file)
index 0000000..bc238eb
--- /dev/null
@@ -0,0 +1,125 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'lib/links.inc.php');\r
+\r
+if (!manage_links()) {\r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: '.AT_BASE_HREF.'links/index.php');\r
+       exit;\r
+}\r
+\r
+$cat_id = intval($_REQUEST['cat_id']);\r
+\r
+if (isset($_POST['submit'])) {\r
+\r
+       //check if cat name is empty\r
+       if ($_POST['cat_name'] == '') {\r
+               $msg->addError(array('EMPTY_FIELDS', _AT('title')));\r
+       }\r
+\r
+       if (!$msg->containsErrors()) {\r
+               //authorized cat parent?\r
+               $lid = explode('-', $_POST['cat_parent_id']);\r
+               $parent_id = intval($lid[0]);\r
+               $owner_type = intval($lid[1]);\r
+               $owner_id = intval($lid[2]);\r
+\r
+               if (!links_authenticate($owner_type, $owner_id)) {\r
+                       $msg->addError('ACCESS_DENIED');\r
+                       header('Location: '.AT_BASE_HREF.'tools/links/categories.php');\r
+                       exit;\r
+               }\r
+\r
+               $cat_name = $addslashes($_POST['cat_name']);\r
+               \r
+               //Check length of the post, if it's exceeded 100 as defined in the db. \r
+               $cat_name = validate_length($cat_name, 100);\r
+\r
+               $sql = "UPDATE ".TABLE_PREFIX."links_categories SET parent_id=$parent_id, name='$cat_name', owner_type=$owner_type, owner_id=$owner_id WHERE cat_id=".$cat_id;\r
+\r
+               $result = mysql_query($sql, $db);\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+               header('Location: categories.php');\r
+               exit;\r
+       }\r
+} else if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: categories.php');\r
+       exit;\r
+} else {\r
+       $row = get_cat_info($cat_id);\r
+\r
+       //authorized to edit this cat?\r
+       if (!links_authenticate($row['owner_type'], $row['owner_id'])) {\r
+               $msg->addError('ACCESS_DENIED');\r
+               header('Location: '.AT_BASE_HREF.'tools/links/categories.php');\r
+               exit;\r
+       }\r
+}\r
+\r
+/* get all the categories: */\r
+/* $categories[category_id] = array(cat_name, cat_parent, num_courses, [array(children)]) */\r
+$categories = get_link_categories(true);\r
+\r
+$onload = 'document.form.category_name.focus();';\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$current_cat_id = $categories[$cat_id]['cat_parent'];\r
+\r
+?>\r
+<form action ="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">\r
+<input type="hidden" name="cat_id" value="<?php echo $cat_id; ?>" />\r
+<input type="hidden" name="form_submit" value="1" />\r
+\r
+<div class="input-form">\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="category_name"><?php echo _AT('title'); ?></label><br />\r
+               <input type="text" id="category_name" name="cat_name" value="<?php echo stripslashes(htmlspecialchars($categories[$cat_id]['cat_name'])); ?>" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <label for="category_parent"><?php echo _AT('cats_parent_category'); ?></label><br />\r
+               <select name="cat_parent_id" id="category_parent"><?php\r
+                               $exclude = true; /* exclude the children */\r
+                               \r
+                               //remove the current cat_id and it's sub cats from list, don't want to print them out.\r
+                               if (is_array($categories[$current_cat_id]['children'])) {\r
+                                       foreach ($categories[$current_cat_id]['children'] as $id=>$child) {\r
+                                               if ($child == $cat_id) {\r
+                                                       unset($categories[$current_cat_id]['children'][$id]);\r
+                                               }\r
+                                       }\r
+                               }\r
+                               unset($categories[$cat_id]);\r
+\r
+                               $auth = manage_links();\r
+                               if ($auth == LINK_CAT_AUTH_ALL) {\r
+                                       echo '<option value="0-'.LINK_CAT_COURSE.'-'.$_SESSION['course_id'].'">&nbsp;&nbsp;&nbsp;[ '._AT('cats_none').' ]&nbsp;&nbsp;&nbsp;</option>';\r
+                                       echo '<option value="0-'.LINK_CAT_COURSE.'-'.$_SESSION['course_id'].'"></option>';\r
+                               }\r
+                               select_link_categories($categories, 0, $current_cat_id, $exclude, 0, TRUE);\r
+                       ?></select>\r
+       </div>\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>"  />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/links/delete.php b/tools/links/delete.php
new file mode 100644 (file)
index 0000000..1e250e8
--- /dev/null
@@ -0,0 +1,74 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require (AT_INCLUDE_PATH.'lib/links.inc.php');\r
+\r
+if (!manage_links()) {\r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: '.AT_BASE_HREF.'links/index.php');\r
+       exit;\r
+}\r
+\r
+$lid = explode('-', $_REQUEST['lid']);\r
+$link_id = intval($lid[0]);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.AT_BASE_HREF.'tools/links/index.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+\r
+       $row = get_cat_info(intval($_POST['cat_id']));\r
+\r
+       if (!links_authenticate($row['owner_type'], $row['owner_id'])) {\r
+               $msg->addError('ACCESS_DENIED');\r
+               header('Location: '.AT_BASE_HREF.'tools/links/index.php');\r
+               exit;\r
+       }\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."links WHERE link_id=$_POST[link_id]";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: '.AT_BASE_HREF.'tools/links/index.php');\r
+       exit;\r
+}\r
+\r
+$_section[0][0] = _AT('delete_link');\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+       $sql = "SELECT LinkName, cat_id FROM ".TABLE_PREFIX."links WHERE link_id=$link_id";\r
+\r
+       $result = mysql_query($sql,$db);\r
+       if (mysql_num_rows($result) == 0) {\r
+               $msg->printErrors('LINK_NOT_FOUND');\r
+       } else {\r
+               $row = mysql_fetch_assoc($result);\r
+\r
+               $hidden_vars['delete_link']  = TRUE;\r
+               $hidden_vars['link_id'] = $link_id;\r
+               $hidden_vars['cat_id'] = $row['cat_id'];\r
+               \r
+               $confirm = array('DELETE_LINK', AT_print($row['LinkName'], 'resource_links.LinkName'));\r
+               $msg->addConfirm($confirm, $hidden_vars);\r
+               \r
+               $msg->printConfirm();\r
+       }\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+\r
+?>
\ No newline at end of file
diff --git a/tools/links/edit.php b/tools/links/edit.php
new file mode 100644 (file)
index 0000000..e75f6ce
--- /dev/null
@@ -0,0 +1,158 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+require (AT_INCLUDE_PATH.'lib/links.inc.php');\r
+\r
+if (!manage_links()) {\r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: '.AT_BASE_HREF.'links/index.php');\r
+       exit;\r
+}\r
+\r
+$lid = explode('-', $_REQUEST['lid']);\r
+$link_id = intval($lid[0]);\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.AT_BASE_HREF.'tools/links/index.php');\r
+       exit;\r
+} else if (isset($_POST['edit_link']) && isset($_POST['submit'])) {\r
+\r
+       $missing_fields = array();\r
+       if ($_POST['cat'] == 0 || $_POST['cat'] == '') {\r
+               $missing_fields[] = _AT('category');\r
+       }\r
+       if (trim($_POST['title']) == '') {\r
+               $missing_fields[] = _AT('title');\r
+       }\r
+       if (trim($_POST['url']) == '' || $_POST['url'] == 'http://') {\r
+               $missing_fields[] = _AT('url');\r
+       }\r
+       if (trim($_POST['description']) == '') {\r
+               $missing_fields[] = _AT('description');\r
+       }\r
+\r
+       if ($missing_fields) {\r
+               $missing_fields = implode(', ', $missing_fields);\r
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));\r
+       }\r
+\r
+       if (!$msg->containsErrors() && isset($_POST['submit'])) {\r
+\r
+               $_POST['cat'] = intval($_POST['cat']);\r
+               $_POST['title']  = $addslashes($_POST['title']);\r
+               $_POST['url'] == $addslashes($_POST['url']);\r
+               $_POST['description']  = $addslashes($_POST['description']);\r
+               //Check length of the post, if it's exceeded 64 as defined in the db. \r
+               $_POST['title'] = validate_length($_POST['title'], 64);\r
+               $_POST['description'] = validate_length($_POST['description'], 250);\r
+\r
+               $name = get_display_name($_SESSION['member_id']);\r
+               $email = '';\r
+\r
+               //check if new cat is auth? -- shouldn't be a prob. since cat dropdown is already filtered\r
+\r
+               $sql    = "UPDATE ".TABLE_PREFIX."links SET cat_id=$_POST[cat], Url='$_POST[url]', LinkName='$_POST[title]', Description='$_POST[description]', SubmitName='$name', Approved=$_POST[approved] WHERE link_id=".$link_id;\r
+               mysql_query($sql, $db);\r
+       \r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+\r
+               header('Location: '.AT_BASE_HREF.'tools/links/index.php');\r
+               exit;\r
+       } else {\r
+               $_POST['title']  = $stripslashes($_POST['title']);\r
+               $_POST['url']    = $stripslashes($_POST['url']);\r
+               $_POST['description'] = $stripslashes($_POST['description']);\r
+       }\r
+} else {\r
+       $sql = "SELECT * FROM ".TABLE_PREFIX."links WHERE link_id=".$link_id;\r
+       $result = mysql_query($sql, $db);\r
+       if ($row = mysql_fetch_assoc($result)) {\r
+\r
+               //auth based on the link's cat\r
+               $cat_row = get_cat_info($row['cat_id']);\r
+\r
+               if (!links_authenticate($cat_row['owner_type'], $cat_row['owner_id'])) {\r
+                       $msg->addError('ACCESS_DENIED');\r
+                       header('Location: '.AT_BASE_HREF.'tools/links/index.php');\r
+                       exit;\r
+               }\r
+\r
+               $_POST['title']                 = $row['LinkName'];\r
+               $_POST['cat']                   = $row['cat_id'];\r
+               $_POST['url']                   = $row['Url'];\r
+               $_POST['description']   = $row['Description'];\r
+               $_POST['approved']              = $row['Approved'];\r
+       }\r
+}\r
+\r
+$onload = 'document.form.title.focus();';\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$categories = get_link_categories(true);\r
+\r
+$msg->printErrors();\r
+\r
+?>\r
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">\r
+<input type="hidden" name="edit_link" value="true" />\r
+<input type="hidden" name="lid" value="<?php echo $_REQUEST['lid']; ?>" />\r
+\r
+<div class="input-form">\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php echo _AT('title'); ?></label><br />\r
+               <input type="text" name="title" size="40" id="title" value="<?php echo $_POST['title']; ?>"/>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="cat"><?php echo _AT('category'); ?></label><br />\r
+               <select name="cat" id="cat">\r
+                       <?php select_link_categories($categories, 0, $_POST['cat'], FALSE);     ?>\r
+               </select>\r
+       </div>\r
+       \r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="url"><?php echo _AT('url'); ?></label><br />\r
+               <input type="text" name="url" size="40" id="url" value="<?php echo $_POST['url']; ?>" />\r
+       </div>\r
+\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="description"><?php echo _AT('description'); ?></label><br />\r
+               <textarea name="description" cols="55" rows="5" id="description" ><?php echo $_POST['description']; ?></textarea>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <?php echo _AT('approve'); ?><br />\r
+               <?php\r
+                       if ($_POST['approved']) {\r
+                               $y = 'checked="checked"';\r
+                               $n = '';\r
+                       } else {\r
+                               $n = 'checked="checked"';\r
+                               $y = '';\r
+                       }\r
+               ?>\r
+               <input type="radio" id="yes" name="approved" value="1" <?php echo $y; ?> /><label for="yes"><?php echo _AT('yes'); ?></label>  <input type="radio" id="no" name="approved" value="0" <?php echo $n; ?> /><label for="no"><?php echo _AT('no'); ?></label>\r
+       </div>\r
+       \r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />\r
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?> " />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/links/index.php b/tools/links/index.php
new file mode 100644 (file)
index 0000000..e81196a
--- /dev/null
@@ -0,0 +1,174 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+require (AT_INCLUDE_PATH.'lib/links.inc.php');\r
+\r
+if (!manage_links()) {\r
+       $msg->addError('ACCESS_DENIED');\r
+       header('Location: '.AT_BASE_HREF.'links/index.php');\r
+       exit;\r
+}\r
+\r
+if (isset($_POST['edit']) && isset($_POST['link_id'])) {\r
+       header('Location: edit.php?lid='.$_POST['link_id']);\r
+       exit;\r
+} else if (isset($_POST['delete']) && isset($_POST['link_id'])) {\r
+       header('Location: delete.php?lid='.$_POST['link_id']);\r
+       exit;\r
+} else if (isset($_POST['view']) && isset($_POST['link_id'])) {\r
+       $onload = 'window.open(\''.AT_BASE_HREF.'links/index.php?view='.$_POST['link_id'].'\',\'link\');';\r
+} else if (!empty($_POST)) {\r
+       $msg->addError('NO_ITEM_SELECTED');\r
+}\r
+\r
+$categories = get_link_categories(true);\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+if ($_GET['col']) {\r
+       $col = addslashes($_GET['col']);\r
+} else {\r
+       $col = 'LinkName';\r
+}\r
+\r
+if ($_GET['order']) {\r
+       $order = addslashes($_GET['order']);\r
+} else {\r
+       $order = 'asc';\r
+}\r
+\r
+if (!isset($_GET['cat_parent_id'])) {\r
+       $parent_id = 0; \r
+} else {\r
+       $parent_id = intval($_GET['cat_parent_id']);\r
+}\r
+\r
+if ($_SESSION['groups']) {\r
+       $groups = implode(',', $_SESSION['groups']);\r
+} else {\r
+       // not in any groups\r
+       $groups = 0;\r
+}\r
+\r
+$auth = manage_links();\r
+\r
+if ($auth == LINK_CAT_AUTH_ALL) {\r
+       $sql = "SELECT * FROM ".TABLE_PREFIX."links L INNER JOIN ".TABLE_PREFIX."links_categories C USING (cat_id) WHERE ((owner_id=$_SESSION[course_id] AND owner_type=".LINK_CAT_COURSE.") OR (owner_id IN ($groups) AND owner_type=".LINK_CAT_GROUP."))";\r
+} else if ($auth == LINK_CAT_AUTH_GROUP) {\r
+       $sql = "SELECT * FROM ".TABLE_PREFIX."links L INNER JOIN ".TABLE_PREFIX."links_categories C USING (cat_id) WHERE owner_id IN ($groups) AND owner_type=".LINK_CAT_GROUP;\r
+} else if ($auth == LINK_CAT_AUTH_COURSE) {\r
+       $sql = "SELECT * FROM ".TABLE_PREFIX."links L INNER JOIN ".TABLE_PREFIX."links_categories C USING (cat_id) WHERE ((owner_id=$_SESSION[course_id] AND owner_type=".LINK_CAT_COURSE.") OR (owner_id IN ($groups) AND owner_type=".LINK_CAT_GROUP."))";\r
+} \r
+\r
+if ($parent_id) {\r
+       $sql .= " AND L.cat_id=$parent_id";\r
+} \r
+$sql .= " ORDER BY $col $order";\r
+\r
+$result = mysql_query($sql, $db);\r
+\r
+if (!empty($categories)) {\r
+?>\r
+\r
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<div class="input-form">\r
+       <div class="row">\r
+               <h3><label for="category_parent"><?php echo _AT('select_cat'); ?></label></h3>\r
+       </div>\r
+\r
+       <div class="row">\r
+               <select name="cat_parent_id" id="category_parent"><?php\r
+\r
+                               if ($parent_id) {\r
+                                       $current_cat_id = $parent_id;\r
+                                       $exclude = false; /* don't exclude the children */\r
+                               } else {\r
+                                       $current_cat_id = $cat_id;\r
+                                       $exclude = true; /* exclude the children */\r
+                               }\r
+\r
+                               echo '<option value="0">&nbsp;&nbsp;&nbsp; '._AT('cats_all').' &nbsp;&nbsp;&nbsp;</option>';\r
+                               select_link_categories($categories, 0, $current_cat_id, FALSE);\r
+                       ?>\r
+               </select>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="cat_links" value="<?php echo _AT('cats_view_links'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+<?php } ?>\r
+\r
+<form name="form" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+\r
+<table class="data" summary="" rules="cols">\r
+<thead>\r
+<tr>\r
+       <th scope="col">&nbsp;</th>\r
+       <th scope="col"><?php echo _AT('title'); ?></th>\r
+       <th scope="col"><?php echo _AT('category'); ?></th>\r
+       <th scope="col"><?php echo _AT('submitted_by'); ?></th>\r
+       <th scope="col"><?php echo _AT('approved'); ?></th>\r
+       <th scope="col"><?php echo _AT('hit_count'); ?></th>\r
+</tr>\r
+</thead>\r
+\r
+<?php\r
+       if ($row = mysql_fetch_assoc($result)) {  ?>\r
+       <tfoot>\r
+       <tr>\r
+               <td colspan="6"><input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /> <input type="submit" name="view" value="<?php echo _AT('view'); ?>" /></td>\r
+       </tr>\r
+       </tfoot>\r
+       <tbody>\r
+<?php do {\r
+               if ($row['owner_type'] == LINK_CAT_GROUP) {\r
+                       $row['name'] = get_group_name($row['owner_id']);\r
+               }\r
+?>\r
+               <tr onmousedown="document.form['m<?php echo $row['link_id']; ?>'].checked = true;rowselect(this);" id="r_<?php echo $row['link_id'];?>">\r
+                       <td width="10"><input type="radio" name="link_id" value="<?php echo $row['link_id'].'-'.$row['owner_type'].'-'.$row['owner_id']; ?>" id="m<?php echo $row['link_id']; ?>" /></td>\r
+                       <td><label for="m<?php echo $row['link_id']; ?>"><?php echo AT_print($row['LinkName'], 'resource_links.LinkName'); ?></label></td>\r
+                       <td><?php echo AT_print($row['name'], 'resource_links.CatName'); ?></td>\r
+                       <td><?php echo AT_print($row['SubmitName'], 'resource_links.SubmitName'); ?></td>\r
+\r
+                       <td align="center"><?php \r
+                                       if($row['Approved']) { \r
+                                               echo _AT('yes'); \r
+                                       } else { \r
+                                               echo _AT('no'); \r
+                                       } ?></td>\r
+                       <td align="center"><?php echo $row['hits']; ?></td>\r
+               </tr>\r
+<?php \r
+       } while ($row = mysql_fetch_assoc($result));                                    \r
+} else {\r
+?>\r
+       <tbody>\r
+       <tr>\r
+               <td colspan="6"><?php echo _AT('none_found'); ?></td>\r
+       </tr>\r
+<?php\r
+}                                      \r
+?>\r
+\r
+</tbody>\r
+</table>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/modules.php b/tools/modules.php
new file mode 100644 (file)
index 0000000..2c21815
--- /dev/null
@@ -0,0 +1,195 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_STYLES);
+
+if (isset($_POST['up'])) {
+       $up = key($_POST['up']);
+       $_new_modules  = array();
+       if (isset($_POST['main'])) {
+               foreach ($_POST['main'] as $m) {
+                       if ($m == $up) {
+                               $last_m = array_pop($_new_modules);
+                               $_new_modules[] = $m;
+                               $_new_modules[] = $last_m;
+                       } else {
+                               $_new_modules[] = $m;
+                       }
+               }
+
+               $_POST['main'] = $_new_modules;
+       }
+
+       if (isset($_POST['home'])) {
+               $_new_modules  = array();
+               foreach ($_POST['home'] as $m) {
+                       if ($m == $up) {
+                               $last_m = array_pop($_new_modules);
+                               $_new_modules[] = $m;
+                               $_new_modules[] = $last_m;
+                       } else {
+                               $_new_modules[] = $m;
+                       }
+               }
+
+               $_POST['home'] = $_new_modules;
+       }
+
+       $_POST['submit'] = TRUE;
+} else if (isset($_POST['down'])) {
+       $_new_modules  = array();
+
+       $down = key($_POST['down']);
+
+       if (isset($_POST['main'])) {
+               foreach ($_POST['main'] as $m) {
+                       if ($m == $down) {
+                               $found = TRUE;
+                               continue;
+                       }
+                       $_new_modules[] = $m;
+                       if ($found) {
+                               $_new_modules[] = $down;
+                               $found = FALSE;
+                       }
+               }
+
+               $_POST['main'] = $_new_modules;
+       }
+
+       if (isset($_POST['home'])) {
+               $_new_modules  = array();
+               foreach ($_POST['home'] as $m) {
+                       if ($m == $down) {
+                               $found = TRUE;
+                               continue;
+                       }
+                       $_new_modules[] = $m;
+                       if ($found) {
+                               $_new_modules[] = $down;
+                               $found = FALSE;
+                       }
+               }
+
+               $_POST['home'] = $_new_modules;
+       }
+
+       $_POST['submit'] = TRUE;
+}
+
+// 'search.php',  removed
+if (isset($_POST['submit'])) {
+
+       if (isset($_POST['main'])) {
+               $_POST['main'] = array_intersect($_POST['main'], $_modules);
+               $_POST['main'] = array_unique($_POST['main']);
+               $main_links = implode('|', $_POST['main']);
+       } else {
+               $main_links = '';
+       }
+
+       if (isset($_POST['home'])) {
+               $_POST['home'] = array_intersect($_POST['home'], $_modules);
+               $_POST['home'] = array_unique($_POST['home']);
+               $home_links = implode('|', $_POST['home']);
+       } else {
+               $home_links = '';
+       }
+
+       $sql    = "UPDATE ".TABLE_PREFIX."courses SET home_links='$home_links', main_links='$main_links' WHERE course_id=$_SESSION[course_id]";
+       $result = mysql_query($sql, $db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: modules.php');
+       exit;
+}
+
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+
+//being displayed
+$_current_modules = array_slice($_pages[AT_NAV_COURSE], 1, -1); // removes index.php and tools/index.php
+$num_main    = count($_current_modules);
+//main and home merged
+$_current_modules = array_merge( (array) $_current_modules, array_diff($_pages[AT_NAV_HOME],$_pages[AT_NAV_COURSE]) );
+$num_modules = count($_current_modules);
+//all other mods
+$_current_modules = array_merge( (array) $_current_modules, array_diff($_modules, $_current_modules));
+
+$count = 0;
+
+?>
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<table class="data static" rules="rows" summary="">
+<thead>
+<tr>
+       <th scope="cols"><?php echo _AT('section'); ?></th>
+       <th><?php echo _AT('location'); ?></th>
+       <th><?php echo _AT('order'); ?></th>
+</tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="3" style="text-align:right;"><input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" /></td>
+</tr>
+</tfoot>
+<tbody>
+<?php foreach ($_current_modules as $module): ?>
+<?php $count++; ?>
+<tr>
+       <td><?php 
+               if (isset($_pages[$module]['title'])) {
+                       echo $_pages[$module]['title'];
+               } else {
+                       echo _AT($_pages[$module]['title_var']);
+               } ?></td>
+       <td>
+               <?php if (in_array($module, $_pages[AT_NAV_COURSE])): ?>
+                       <input type="checkbox" name="main[]" value="<?php echo $module; ?>" id="m<?php echo $count; ?>" checked="checked" /><label for="m<?php echo $count; ?>"><?php echo _AT('main_navigation'); ?></label>
+               <?php else: ?>
+                       <input type="checkbox" name="main[]" value="<?php echo $module; ?>" id="m<?php echo $count; ?>" /><label for="m<?php echo $count; ?>"><?php echo _AT('main_navigation'); ?></label>
+               <?php endif; ?>
+
+               <?php if (in_array($module, $_pages[AT_NAV_HOME])): ?>
+                       <input type="checkbox" name="home[]" value="<?php echo $module; ?>" id="h<?php echo $count; ?>" checked="checked" /><label for="h<?php echo $count; ?>"><?php echo _AT('home'); ?></label>
+               <?php else: ?>
+                       <input type="checkbox" name="home[]" value="<?php echo $module; ?>" id="h<?php echo $count; ?>" /><label for="h<?php echo $count; ?>"><?php echo _AT('home'); ?></label>
+               <?php endif; ?>
+       </td>
+       <td align="right">
+               <?php if (!in_array($module, $_pages[AT_NAV_HOME]) && !in_array($module, $_pages[AT_NAV_COURSE])): ?>
+                       &nbsp;
+               <?php else: ?>
+                       <?php if (($count != $num_main+1) && ($count > 1)): ?>
+                               <input type="submit" name="up[<?php echo $module; ?>]" value="<?php echo _AT('move_up'); ?>" title="<?php echo _AT('move_up'); ?>" style="background-color: white; border: 1px solid; padding: 0px;" />
+                       <?php else: ?>
+                               <img src="images/clr.gif" alt="" width="12" />
+                       <?php endif; ?>
+                       <?php if (($count != $num_main) && ($count < $num_modules)): ?>
+                               <input type="submit" name="down[<?php echo $module; ?>]" value="<?php echo _AT('move_down'); ?>" title="<?php echo _AT('move_down'); ?>" style="background-color: white; border: 1px solid; padding: 0px;"/>
+                       <?php else: ?>
+                               <img src="images/clr.gif" alt="" width="12" />
+                       <?php endif; ?>
+               <?php endif; ?>
+       </td>
+</tr>
+<?php endforeach; ?>
+</tbody>
+</table>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/my_tests.php b/tools/my_tests.php
new file mode 100644 (file)
index 0000000..eac4429
--- /dev/null
@@ -0,0 +1,170 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$sql   = "SELECT T.*, UNIX_TIMESTAMP(T.start_date) AS us, UNIX_TIMESTAMP(T.end_date) AS ue, COUNT(Q.weight) AS numquestions FROM ".TABLE_PREFIX."tests T, ".TABLE_PREFIX."tests_questions_assoc Q WHERE Q.test_id=T.test_id AND T.course_id=$_SESSION[course_id] GROUP BY T.test_id ORDER BY T.start_date, T.title";
+$result        = mysql_query($sql, $db);
+
+?>
+<table class="data static" summary="" rules="cols">
+<thead>
+<tr>
+       <th scope="col"><?php echo _AT('title');      ?></th>
+       <th scope="col"><?php echo _AT('status');     ?></th>
+       <th scope="col"><?php echo _AT('start_date'); ?></th>
+       <th scope="col"><?php echo _AT('end_date');   ?></th>
+       <th scope="col"><?php echo _AT('attempts');   ?></th>
+</tr>
+</thead>
+<tbody>
+
+<?php
+$count = 0;
+while ($row = mysql_fetch_assoc($result)) {
+       // this code hides tests from the user if they are not enrolled.
+       if (!$row['guests'] && !authenticate_test($row['test_id'])) {
+               continue;
+       }
+
+       $count++;
+       echo '<tr>';
+       echo '<td>';
+       $sql = "SELECT COUNT(test_id) AS cnt FROM ".TABLE_PREFIX."tests_results WHERE status=1 AND test_id=".$row['test_id']." AND member_id=".$_SESSION['member_id'];
+
+       $takes_result= mysql_query($sql, $db);
+       $takes = mysql_fetch_assoc($takes_result);
+       if ( ($row['us'] <= time() && $row['ue'] >= time()) && 
+          ( ($row['num_takes'] == AT_TESTS_TAKE_UNLIMITED) || ($takes['cnt'] < $row['num_takes']) )  ) {
+               echo '<strong><a href="'.url_rewrite('tools/test_intro.php?tid='.$row['test_id']).'">'.AT_print($row['title'], 'tests.title').'</a></strong>';
+       } else {
+               echo '<small class="bigspacer">'.AT_print($row['title'], 'tests.title').'';
+       }
+       echo '</td><td>';
+       if ( ($row['us'] <= time()) && ($row['ue'] >= time() ) ) {
+               echo '<em><strong>'._AT('ongoing').'</strong></em>';
+       } else if ($row['ue'] < time() ) {
+               echo '<em>'._AT('expired').'</em>';
+       } else if ($row['us'] > time() ) {
+               echo '<em>'._AT('pending').'</em>';
+       }
+       
+       $startend_date_long_format=_AT('startend_date_long_format');
+       echo '</td>';
+       echo '<td>'.AT_date( $startend_date_long_format, $row['start_date']).'</td>';
+       echo '<td>'.AT_date( $startend_date_long_format, $row['end_date']).'</td>';
+
+       if ($row['num_takes'] == AT_TESTS_TAKE_UNLIMITED) {
+               echo '<td>'.$takes['cnt'].'/'._AT('unlimited').'</td>';
+       } else  {
+               echo '<td>'.$takes['cnt'].'/'.$row['num_takes'].'</td>';
+       }
+
+/*
+       if ($row['random']) {
+               echo '<td>'.$row['num_questions'].'</td>';
+               echo '<td>'.$row['out_of'].'</td>';
+       } else {
+               echo '<td>'.$row['numquestions'].'</td>';
+               if ($row['out_of'] > 0) {
+                       echo '<td>'.$row['out_of'].'</td>';
+               } else {
+                       echo '<td><em>'._AT('na').'</em></td>';
+               }
+       }                       
+*/
+       echo '</tr>';
+
+}
+if (!$count) {
+       echo '<tr><td colspan="7">'._AT('none_found').'</td></tr>';
+}
+?>
+       </tbody>
+</table>
+<br />
+
+<?php if (!$_SESSION['enroll']): ?>
+       <?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
+       <?php exit; ?>
+<?php endif; ?>
+<h4><?php echo _AT('completed_tests'); ?></h4><br />
+<table class="data static" summary="" rules="cols">
+<thead>
+<tr>
+       <th scope="col"><?php echo _AT('title');      ?></th>
+       <th scope="col"><?php echo _AT('date_taken'); ?></th>
+       <th scope="col"><?php echo _AT('time_spent'); ?></th>
+       <th scope="col"><?php echo _AT('mark');       ?></th>
+       <th scope="col"><?php echo _AT('submission'); ?></th>
+</tr>
+</thead>
+<tbody>
+<?php
+
+
+$sql   = "SELECT T.*, R.*, (UNIX_TIMESTAMP(R.end_time) - UNIX_TIMESTAMP(R.date_taken)) AS diff FROM ".TABLE_PREFIX."tests T, ".TABLE_PREFIX."tests_results R, ".TABLE_PREFIX."tests_questions_assoc Q WHERE R.status=1 AND Q.test_id=T.test_id AND R.member_id=$_SESSION[member_id] AND R.test_id=T.test_id AND T.course_id=$_SESSION[course_id] GROUP BY R.result_id ORDER BY R.date_taken DESC";
+
+$result        = mysql_query($sql, $db);
+$num_results = mysql_num_rows($result);
+
+if ($row = mysql_fetch_assoc($result)) {
+       $this_course_id=0;
+
+       do {
+               echo '<tr>';
+               echo '<td><strong>'.AT_print($row['title'], 'tests.title').'</strong></td>';
+               echo '<td>'.substr($row['date_taken'], 0, -3).'</td>';
+               echo '<td>'.get_human_time($row['diff']).'</td>';
+               echo '<td>';
+
+               if ($row['out_of'] == 0) {
+                       echo _AT('na');
+               } elseif ($row['final_score'] == '') {
+                       echo _AT('unmarked');
+               } elseif (($row['final_score'] != '') && ($row['result_release']==AT_RELEASE_NEVER)) {
+                       echo _AT('unreleased');
+               } else {
+                       if ($row['random']) {
+                               $out_of = get_random_outof($row['test_id'], $row['result_id']);
+                       } else {
+                               $out_of = $row['out_of'];
+                       }
+
+                       echo '<strong>'.$row['final_score'].'</strong>/'.$out_of;
+               }
+               echo '</td>';
+
+               echo '<td>';
+
+               if ( ($row['result_release']==AT_RELEASE_IMMEDIATE) || (($row['final_score'] != '') && ($row['result_release']==AT_RELEASE_MARKED)) ) {
+                       echo '<a href="tools/view_results.php?tid='.$row['test_id'].SEP.'rid='.$row['result_id'].'">'._AT('view_results').'</a>';
+               } else {
+                       echo '<em>'._AT('no_results_yet').'</em>';
+               }
+               
+               echo '</td>';
+               echo '</tr>';
+       } while ($row = mysql_fetch_assoc($result));
+} else {
+       echo '<tr><td colspan="4">'._AT('none_found').'</td></tr>';
+}
+?>
+</tbody>
+</table>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
diff --git a/tools/news/index.php b/tools/news/index.php
new file mode 100644 (file)
index 0000000..794acb4
--- /dev/null
@@ -0,0 +1,95 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+$page = 'tools';\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_ANNOUNCEMENTS);\r
+\r
+if (isset($_GET['edit'], $_GET['aid'])) {\r
+       header('Location: '.AT_BASE_HREF.'editor/edit_news.php?aid='.intval($_GET['aid']));\r
+       exit;\r
+} else if (isset($_GET['delete'], $_GET['aid'])) {\r
+       header('Location: '.AT_BASE_HREF.'editor/delete_news.php?aid='.intval($_GET['aid']));\r
+       exit;\r
+} else if ((isset($_GET['edit']) || isset($_GET['delete']))) {\r
+       $msg->addError('NO_ITEM_SELECTED');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$orders = array('asc' => 'desc', 'desc' => 'asc');\r
+$cols   = array('title' => 1, 'date' => 1);\r
+\r
+if (isset($_GET['asc'])) {\r
+       $order = 'asc';\r
+       $col   = isset($cols[$_GET['asc']]) ? $_GET['asc'] : 'date';\r
+} else if (isset($_GET['desc'])) {\r
+       $order = 'desc';\r
+       $col   = isset($cols[$_GET['desc']]) ? $_GET['desc'] : 'date';\r
+} else {\r
+       // no order set\r
+       $order = 'desc';\r
+       $col   = 'date';\r
+}\r
+\r
+$sql   = "SELECT news_id, title, date FROM ".TABLE_PREFIX."news WHERE course_id=$_SESSION[course_id] ORDER BY $col $order";\r
+$result = mysql_query($sql, $db);\r
+\r
+?>\r
+<form name="form" method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<table class="data" summary="" rules="cols">\r
+<colgroup>\r
+       <?php if ($col == 'title'): ?>\r
+               <col />\r
+               <col class="sort" />\r
+               <col />\r
+       <?php elseif($col == 'date'): ?>\r
+               <col span="2" />\r
+               <col class="sort" />\r
+       <?php endif; ?>\r
+</colgroup>\r
+<thead>\r
+<tr>\r
+       <th scope="col">&nbsp;</th>\r
+       <th scope="col"><a href="tools/news/index.php?<?php echo $orders[$order]; ?>=title"><?php echo _AT('title'); ?></a></th>\r
+       <th scope="col"><a href="tools/news/index.php?<?php echo $orders[$order]; ?>=date"><?php echo _AT('date'); ?></a></th>\r
+</tr>\r
+</thead>\r
+<tfoot>\r
+<tr>\r
+       <td colspan="3"><input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" /> <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /></td>\r
+</tr>\r
+</tfoot>\r
+<tbody>\r
+       <?php if ($row = mysql_fetch_assoc($result)): ?>\r
+               <?php do { ?>\r
+                       <tr onmousedown="document.form['n<?php echo $row['news_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $row['news_id']; ?>">\r
+                       \r
+                               <td><input type="radio" name="aid" value="<?php echo $row['news_id']; ?>" id="n<?php echo $row['news_id']; ?>" /></td>\r
+                               \r
+                               <td><label for="n<?php echo $row['news_id']; ?>"><?php echo AT_print($row['title'], 'news.title'); ?></label></td>\r
+                               <td><?php echo AT_date(_AT('announcement_date_format'), $row['date'], AT_DATE_MYSQL_DATETIME); ?></td>\r
+                       </tr>\r
+               <?php } while ($row = mysql_fetch_assoc($result)); ?>\r
+       <?php else: ?>\r
+               <tr>\r
+                       <td colspan="3"><?php echo _AT('none_found'); ?></td>\r
+               </tr>\r
+       <?php endif; ?>\r
+</tbody>\r
+</table>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/packages/delete.php b/tools/packages/delete.php
new file mode 100644 (file)
index 0000000..82d66d8
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/*
+ * tools/packages/delete.php
+ *
+ * This file is part of ATutor, see http://www.atutor.ca
+ * 
+ * Copyright (C) 2005  Matthai Kurian 
+ * 
+ * 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+$ptypes = explode (',', AT_PACKAGE_TYPES);
+$plug = Array();
+foreach ($ptypes as $type) {
+       include ('./' . $type . '/lib.inc.php');
+}
+
+if (sizeOf ($_POST['goners']) > 0) {
+       foreach ($ptypes as $type) {
+               $plug[$type]->deletePackages ($_POST['goners']);
+       }
+}
+
+$sql = "SELECT package_id, ptype FROM ".TABLE_PREFIX."packages WHERE course_id = $_SESSION[course_id] ORDER BY package_id";
+$result = mysql_query($sql, $db);
+
+$num = 0;
+while ($row = mysql_fetch_assoc($result)) {
+       foreach ($plug[$row['ptype']]->getDeleteFormItems ($row['package_id'], $num) as $l) {
+               $p .= '<li>' . $l . '</li>' . "\n";
+               $num++;
+       }
+}
+
+if ($num == 0) {
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: index.php' );
+       exit;
+} 
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+
+<div class="input-form">       
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('delete_package'); ?></legend>
+       <form method="post" action="tools/packages/delete.php">
+               <ol>
+               <?php echo $p; ?>
+               </ol>
+               <div class="row buttons">
+                       <input type="submit" name="submit"  value="<?php echo _AT('delete_selected_package_s'); ?>" />
+               </div>
+       </form>
+       </fieldset>
+</div>
+
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
diff --git a/tools/packages/import.php b/tools/packages/import.php
new file mode 100644 (file)
index 0000000..a5c7174
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+/*
+ * tools/packages/import.php
+ *
+ * This file is part of ATutor, see http://www.atutor.ca
+ * 
+ * Copyright (C) 2005  Matthai Kurian 
+ * 
+ * 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+define('AT_INCLUDE_PATH', '../../include/');
+require_once(AT_INCLUDE_PATH.'vitals.inc.php');
+
+define ('PACKAGE_TYPES', 'scorm-1.2');
+
+if (isset ($_POST['type'])) {
+       require ($_POST['type'] . '/import.php');
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('import_package'); ?></legend>
+<form name="form1" method="post"
+      action="<?php echo $_SERVER['PHP_SELF']; ?>" enctype="multipart/form-data"
+      onsubmit="openWindow('<?php echo AT_BASE_HREF; ?>tools/prog.php');">
+
+       <?php echo _AT('package_type_info')?>
+       <div class="row">
+       <label for="type"><?php echo _AT('package_type')?></label>
+       <br />
+       <select name="type">
+
+       <?php
+       $ptypes = explode (',', PACKAGE_TYPES);
+       foreach ($ptypes as $type) {
+               echo '<option value="' . $type . '">' . $type . '</option>';
+       }
+       ?>
+       </select>
+       </div>
+
+       <?php echo _AT('package_upload_file_info')?>
+       <div class="row">
+       <label for="to_file"><?php echo _AT('package_upload_file'); ?></label>
+       <br />
+       <input type="file" name="file" id="to_file" />
+       </div>
+
+       <?php echo _AT('package_upload_url_info')?>
+       <div class="row">
+       <label for="to_url">
+       <?php echo _AT('package_upload_url'); ?>
+       </label><br />
+       <input type="text" name="url" value="http://" size="40" id="to_url" />
+       </div>
+
+       <div class="row buttons">
+       <input type="submit" name="submit" onClick="setClickSource('submit');" value="<?php echo _AT('import'); ?>" />
+       <input type="submit" name="cancel" onClick="setClickSource('cancel');" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+
+</fieldset>
+</form>
+</div>
+<script language="javascript" type="text/javascript">
+
+var but_src;
+function setClickSource(name) {
+       but_src = name;
+}
+
+function openWindow(page) {
+       if (but_src != "cancel") {
+               newWindow = window.open(page, "progWin",
+                       "width=400,height=200,toolbar=no,location=no"
+               );
+               newWindow.focus();
+       }
+}
+</script>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
diff --git a/tools/packages/index.php b/tools/packages/index.php
new file mode 100644 (file)
index 0000000..b508927
--- /dev/null
@@ -0,0 +1,62 @@
+<?php
+/*
+ * tools/packages/index.php
+ *
+ * This file is part of ATutor, see http://www.atutor.ca
+ * 
+ * Copyright (C) 2005  Matthai Kurian 
+ * 
+ * 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+require ('lib.inc.php');
+$pkgs = getPackagesManagerLinkList();
+
+if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
+       $_pages['tools/packages/index.php']['children'] = array (
+               'tools/packages/import.php'
+       );
+       /*
+       if (sizeOf ($pkgs) > 0) {
+               array_push ($_pages['tools/packages/index.php']['children'], 
+                                   'tools/packages/delete.php'
+               );
+               array_push ($_pages['tools/packages/index.php']['children'], 
+                                   'tools/packages/settings.php'
+               );
+       }
+       */
+}
+
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if (sizeOf ($pkgs) == 0) {
+       $msg->addInfo (NO_PACKAGES);
+       $msg->printAll();
+} else {
+       echo getScript();
+        echo '<ol>' . "\n";
+       foreach ($pkgs as $pk) {
+               echo '<li>' . $pk . '</li>' . "\n";
+       }
+       echo '</ol>' . "\n";
+}
+
+require (AT_INCLUDE_PATH.'footer.inc.php');
+?>
diff --git a/tools/packages/lib.inc.php b/tools/packages/lib.inc.php
new file mode 100644 (file)
index 0000000..7e54c30
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+/*
+ * tools/packages/lib.inc.php
+ *
+ * This file is part of ATutor, see http://www.atutor.ca
+ * 
+ * Copyright (C) 2005  Matthai Kurian 
+ * 
+ * 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+$ptypes = explode (',', AT_PACKAGE_TYPES);
+$plug = Array();
+foreach ($ptypes as $type) {
+       require ($type . '/lib.inc.php');
+}
+
+$sql_get_pkgs = "SELECT  package_id,
+               ptype
+       FROM  ".TABLE_PREFIX."packages
+       WHERE   course_id = $_SESSION[course_id]
+       ORDER   BY package_id
+";
+
+function getPackagesLearnerLinkList () {
+       global $db;
+       global $plug;
+       global $sql_get_pkgs;
+
+       $rv = Array();
+
+       $result = mysql_query($sql_get_pkgs, $db);
+
+       while ($row = mysql_fetch_assoc($result)) {
+               foreach ($plug[$row['ptype']]->getLearnerItemLinks(
+                       $row['package_id']) as $l) {
+                       array_push ($rv, $l);
+               }
+       }
+       return $rv;
+}
+
+function getPackagesManagerLinkList () {
+       global $db;
+       global $plug;
+       global $sql_get_pkgs;
+
+       $rv = Array();
+
+       $result = mysql_query($sql_get_pkgs, $db);
+
+       while ($row = mysql_fetch_assoc($result)) {
+               foreach ($plug[$row['ptype']]->getManagerItemLinks(
+                       $row['package_id']) as $l) {
+                       array_push ($rv, $l);
+               }
+       }
+       return $rv;
+}
+
+function getScript () {
+       return "
+<script>
+function getObj (o) {
+       if(document.getElementById) return document.getElementById(o);
+       if(document.all) return document.all[o];
+}
+function show (n) {
+       o = typeof(n)=='string'?getObj (n):n;
+       if (!o) return;
+       if(o.style) o.style.display = '';
+       else o.display='';
+}
+</script>
+";
+}
+
+?>
diff --git a/tools/packages/scorm-1.2/images/active.png b/tools/packages/scorm-1.2/images/active.png
new file mode 100644 (file)
index 0000000..a672fe6
Binary files /dev/null and b/tools/packages/scorm-1.2/images/active.png differ
diff --git a/tools/packages/scorm-1.2/images/asset.png b/tools/packages/scorm-1.2/images/asset.png
new file mode 100644 (file)
index 0000000..06dd447
Binary files /dev/null and b/tools/packages/scorm-1.2/images/asset.png differ
diff --git a/tools/packages/scorm-1.2/images/browsed.png b/tools/packages/scorm-1.2/images/browsed.png
new file mode 100644 (file)
index 0000000..c40d8d2
Binary files /dev/null and b/tools/packages/scorm-1.2/images/browsed.png differ
diff --git a/tools/packages/scorm-1.2/images/busy.png b/tools/packages/scorm-1.2/images/busy.png
new file mode 100644 (file)
index 0000000..a672fe6
Binary files /dev/null and b/tools/packages/scorm-1.2/images/busy.png differ
diff --git a/tools/packages/scorm-1.2/images/completed.png b/tools/packages/scorm-1.2/images/completed.png
new file mode 100644 (file)
index 0000000..c40d8d2
Binary files /dev/null and b/tools/packages/scorm-1.2/images/completed.png differ
diff --git a/tools/packages/scorm-1.2/images/failed.png b/tools/packages/scorm-1.2/images/failed.png
new file mode 100644 (file)
index 0000000..569c761
Binary files /dev/null and b/tools/packages/scorm-1.2/images/failed.png differ
diff --git a/tools/packages/scorm-1.2/images/incomplete.png b/tools/packages/scorm-1.2/images/incomplete.png
new file mode 100644 (file)
index 0000000..0586c28
Binary files /dev/null and b/tools/packages/scorm-1.2/images/incomplete.png differ
diff --git a/tools/packages/scorm-1.2/images/not-attempted.png b/tools/packages/scorm-1.2/images/not-attempted.png
new file mode 100644 (file)
index 0000000..4449980
Binary files /dev/null and b/tools/packages/scorm-1.2/images/not-attempted.png differ
diff --git a/tools/packages/scorm-1.2/images/passed.png b/tools/packages/scorm-1.2/images/passed.png
new file mode 100644 (file)
index 0000000..a17f560
Binary files /dev/null and b/tools/packages/scorm-1.2/images/passed.png differ
diff --git a/tools/packages/scorm-1.2/import.php b/tools/packages/scorm-1.2/import.php
new file mode 100644 (file)
index 0000000..613a30a
--- /dev/null
@@ -0,0 +1,489 @@
+<?php
+/*
+ * tools/packages/scorm-1.2/import.php
+ *
+ * This file is part of ATutor, see http://www.atutor.ca
+ * 
+ * Copyright (C) 2005  Matthai Kurian 
+ * 
+ * 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+define('AT_INCLUDE_PATH', '../../../include/');
+if (!isset ($_POST['type'])) {
+       require(AT_INCLUDE_PATH.'vitals.inc.php');
+} 
+
+@set_time_limit(0);
+$_SESSION['done'] = 1;
+
+require(AT_INCLUDE_PATH.'lib/filemanager.inc.php'); 
+require(AT_INCLUDE_PATH.'classes/pclzip.lib.php');
+
+authenticate(AT_PRIV_CONTENT);
+
+
+function chmodPackageDir ($path) {
+
+       if (!is_dir($path)) return;
+       else chmod ($path, 0755);
+
+       $h = opendir($path);
+       while ($f = readdir($h)) {
+               if ($f == '.' || $f == '..') continue;
+               $fpath = $path.'/'.$f;
+               if (!is_dir($fpath)) {
+                       chmod ($fpath, 0644);
+               } else {
+                       chmodPackageDir ($fpath);
+               }
+       }
+       closedir ($h);
+}
+
+$package_base_path = '';
+
+$idx      = '';                // the current item's index, 1, 1.1, 1.2, 2, 2.1 ...
+$idxs     = array();   // array containing the idx for all items
+$orgid    = 0;         // index of current organization 1...
+$depth    = 0;         // depth in organization tree
+$itemid   = array();   
+$files    = array();
+$orgitems = array();
+$idxs     = array();
+$text;
+$res;
+$ress     = array();
+$files    = array();
+$finfo;
+$totalsize = 0;
+
+if (!isset($_POST['submit'])) {
+       $msg->addFeedback('IMPORT_CANCELLED');
+       header('Location: ../index.php');
+       exit;
+}
+
+$cid = intval($_POST['cid']);
+
+
+if (isset($_POST['url']) && ($_POST['url'] != 'http://') ) {
+       if ($content = @file_get_contents($_POST['url'])) {
+               $filename = substr(time(), -6). '.zip';
+               $full_filename = AT_CONTENT_DIR . $filename;
+
+               if (!$fp = fopen($full_filename, 'w+b')) {
+                       echo "Cannot open file ($filename)";
+                       exit;
+               }
+
+               if (fwrite($fp, $content, strlen($content) ) === FALSE) {
+                       echo "Cannot write to file ($filename)";
+                       exit;
+               }
+               fclose($fp);
+       }       
+       $_FILES['file']['name']     = $filename;
+       $_FILES['file']['tmp_name'] = $full_filename;
+       $_FILES['file']['size']     = strlen($content);
+       unset($content);
+       $url_parts = pathinfo($_POST['url']);
+       $package_base_name_url = $url_parts['basename'];
+}
+$ext = pathinfo($_FILES['file']['name']);
+$ext = $ext['extension'];
+
+if ($_FILES['file']['error'] == 1) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $errors = array('FILE_MAX_SIZE', ini_get('upload_max_filesize'));
+       $msg->printErrors($errors);
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+if (!$_FILES['file']['name'] 
+       || (!is_uploaded_file($_FILES['file']['tmp_name']) && !$_POST['url']) 
+       || ($ext != 'zip')) {
+               require(AT_INCLUDE_PATH.'header.inc.php');
+               $msg->printErrors('FILE_NOT_SELECTED');
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+
+       if ($_FILES['file']['size'] == 0) {
+               require(AT_INCLUDE_PATH.'header.inc.php');
+               $msg->printErrors('IMPORTFILE_EMPTY');
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+                       
+       $package_path = AT_INCLUDE_PATH . '../sco/';
+
+       if (!is_dir($package_path)) {
+               if (!@mkdir($package_path, 0755)) {
+                       require(AT_INCLUDE_PATH.'header.inc.php');
+                       $msg->printErrors('PACKAGE_DIR_FAILED');
+                       require(AT_INCLUDE_PATH.'footer.inc.php');
+                       exit;
+               }
+               chmod ($package_path, 0755);
+       }
+
+       $package_path .= $_SESSION['course_id'].'/';
+       if (!is_dir($package_path)) {
+               if (!@mkdir($package_path, 0755)) {
+                       require(AT_INCLUDE_PATH.'header.inc.php');
+                       $msg->printErrors('PACKAGE_DIR_FAILED');
+                       require(AT_INCLUDE_PATH.'footer.inc.php');
+                       exit;
+               }
+               chmod ($package_path, 0755);
+       }
+
+       $package_path .= 'tmp/';
+       clr_dir($package_path);
+       if (!is_dir($package_path)) {
+               if (!@mkdir($package_path, 0755)) {
+                       require(AT_INCLUDE_PATH.'header.inc.php');
+                       $msg->printErrors('PACKAGE_DIR_FAILED');
+                       require(AT_INCLUDE_PATH.'footer.inc.php');
+                       exit;
+               }
+               chmod ($package_path, 0755);
+       }
+
+       $archive = new PclZip($_FILES['file']['tmp_name']);
+       if ($archive->extract (PCLZIP_OPT_PATH, $package_path) == 0) {
+
+               require(AT_INCLUDE_PATH.'header.inc.php');
+               echo 'Error : '.$archive->errorInfo(true);
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               clr_dir($package_path);
+               exit;
+       }
+
+       chmodPackageDir ($package_path);
+
+       $sql    = "SELECT max_quota
+                  FROM ".TABLE_PREFIX."courses
+                  WHERE  course_id=$_SESSION[course_id]";
+
+       $result = mysql_query($sql, $db);
+       $q_row  = mysql_fetch_assoc($result);
+
+       if ($q_row['max_quota'] != AT_COURSESIZE_UNLIMITED) {
+
+               if ($q_row['max_quota'] == AT_COURSESIZE_DEFAULT) {
+                       $q_row['max_quota'] = $MaxCourseSize;
+               }
+               $totalBytes   = dirsize($import_path);
+               $course_total = dirsize(AT_CONTENT_DIR . $_SESSION['course_id'].'/');
+               $total_after  = $q_row['max_quota'] - $course_total - $totalBytes + $MaxCourseFloat;
+
+               if ($total_after < 0) {
+                       require(AT_INCLUDE_PATH.'header.inc.php');
+                       $errors = array('NO_CONTENT_SPACE', number_format(-1*($total_after/AT_KBYTE_SIZE), 2 ) );
+                       $msg->printErrors($errors);
+                       
+                       require(AT_INCLUDE_PATH.'footer.inc.php');
+                       clr_dir($import_path);
+                       exit;
+               }
+       }
+
+
+parseManifest ($package_path);
+doValidation();
+doImport();
+
+
+if (isset($_POST['url'])) {
+      @unlink($full_filename);
+}
+$orgs = array();
+for ($i=1; $orgitems[$i]; $i++) {
+       array_push ($orgs, $orgitems[$i]['title']);
+}
+$oc = sizeOf($orgs);
+if ($oc == 1)  {
+       $msg->addFeedback(array('PACKAGE_IMPORT_SUCCESS', $orgs[0]));
+} else {
+       $l = '';
+       for ($i=0; $i<$oc; $i++) {
+               $l .= '<li>' . $orgs[$i] . '</li>';
+       }
+       $msg->addFeedback(array('PACKAGES_IMPORT_SUCCESS', $l));
+}
+
+header('Location: ./index.php');
+exit;
+
+
+function parseManifest ($import_path) {
+       global $msg;
+
+       $ims_manifest_xml = @file_get_contents($import_path.'imsmanifest.xml');
+
+       if ($ims_manifest_xml === false) {
+               require(AT_INCLUDE_PATH.'header.inc.php');
+               $msg->addError('NO_IMSMANIFEST');
+               $msg->printErrors();
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               clr_dir($import_path);
+               exit;
+       }
+
+       $xml_parser = xml_parser_create();
+
+       xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false);
+       xml_set_element_handler($xml_parser, 'startElement', 'endElement');
+       xml_set_character_data_handler($xml_parser, 'characterData');
+       
+       if (!xml_parse($xml_parser, $ims_manifest_xml, true)) {
+               die(sprintf("XML error: %s at line %d",
+               xml_error_string(xml_get_error_code($xml_parser)),
+               xml_get_current_line_number($xml_parser)));
+       }
+       
+       xml_parser_free($xml_parser);
+}
+
+function scormType ($i) {
+       global $idxs, $orgitems, $res;
+       $r = $res[$orgitems[$idxs[$i]]['identifierref']]['adlcp:scormtype'];
+       if ($r) return $r;
+       $o = explode ('.', $idxs[$i]);
+       if (sizeOf($o) > 1) return 'cluster';
+       return 'organization';  
+}  
+
+function doValidation () {
+       global $msg;
+       global $orgitems;
+       global $idxs;
+       global $res;
+       global $package_path;
+
+       $ic = sizeOf ($idxs);
+
+       $err  = 0;
+       $warn = 0;
+
+       for ($i=0; $i<$ic; $i++) {
+               $title = addslashes($orgitems[$idxs[$i]]['title']);
+
+               $href = $res[$orgitems[$idxs[$i]]['identifierref']]['href'];
+               $styp = $res[$orgitems[$idxs[$i]]['identifierref']]['adlcp:scormtype'];
+               $pre  = $orgitems[$idxs[$i]]['adlcp:prerequisites'];
+               $max  = $orgitems[$idxs[$i]]['adlcp:maxtimeallowed'];
+               $act  = $orgitems[$idxs[$i]]['adlcp:timelimitaction'];
+               $lms  = $orgitems[$idxs[$i]]['adlcp:datafromlms'];
+               $mas  = $orgitems[$idxs[$i]]['adlcp:masteryscore'];
+
+               if ($idxs[$i].'.1' == $idxs[$i+1]) { // cluster
+                       if ($href != '' && ++$warn)
+                           $msg->addWarning ('SCORM_ITEM_CLUSTER_HAS_OBJECT');
+               } else { 
+                       if ($styp == '' && ++$err)
+                           $msg->addError ('SCORM_ITEM_SCORMTYPE_MISSING');
+                       if ($href == '' && ++$err)
+                           $msg->addError ('SCORM_ITEM_HREF_MISSING');
+               }
+
+       }
+       if ($err) {
+               header('Location: ./index.php');
+               exit;
+       }
+
+}
+
+
+function doImport () {
+       global $db;
+       global $msg;
+       global $orgitems;
+       global $idxs;
+       global $res;
+       global $package_path;
+
+       $now = date('Y-m-d H:i:s');
+       $file = $_FILES['file']['name'];
+       $sql = "INSERT INTO ".TABLE_PREFIX."packages
+               VALUES (
+                       NULL,
+                       '$file',
+                       '$now',
+                       $_SESSION[course_id],
+                       'scorm-1.2'
+               )";
+
+       $result = mysql_query($sql, $db);
+       if (!$result) {
+               require(AT_INCLUDE_PATH.'header.inc.php');
+               $msg->addError('DB_NOT_UPDATED');
+               $msg->printAll();
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       } 
+
+       $pkg = mysql_insert_id($db);
+       rename ($package_path, dirname($package_path) . '/' . $pkg);
+
+       $ic = sizeOf ($idxs);
+
+       for ($i=0; $i<$ic; $i++) {
+               $title = addslashes($orgitems[$idxs[$i]]['title']);
+               $scormtype = scormType($i);
+
+               switch ($scormtype) {
+               case 'organization':
+                       $sql = "INSERT INTO ".TABLE_PREFIX."scorm_1_2_org (
+                                       package_id, title
+                               ) VALUES ( $pkg, '$title')";
+
+                       $result = mysql_query($sql, $db);
+                       if (!$result) {
+                               require(AT_INCLUDE_PATH.'header.inc.php');
+                               $msg->addError('DB_NOT_UPDATED');
+                               $msg->printAll();
+                               require(AT_INCLUDE_PATH.'footer.inc.php');
+                               exit;
+                       }
+                       $orgid = mysql_insert_id($db);
+                       $sql = "INSERT INTO ".TABLE_PREFIX."scorm_1_2_item
+                               VALUES (
+                                       0,
+                                       $orgid,
+                                       '$idxs[$i]',
+                                       '$title',
+                                       '',
+                                       '$scormtype',
+                                       '', '', '', '', ''
+                               )";
+                       $result = mysql_query($sql, $db);
+                       break;
+
+               case 'sco':
+                       if (!$orgitems[$idxs[$i]]['adlcp:timelimitaction'])
+                               $orgitems[$idxs[$i]]['adlcp:timelimitaction'] =
+                                       'continue, no message';
+               case 'asset':
+               case 'cluster':
+                       $href = $res[$orgitems[$idxs[$i]]['identifierref']]['href'];
+                       $pre  = $orgitems[$idxs[$i]]['adlcp:prerequisites'];
+                       $max  = $orgitems[$idxs[$i]]['adlcp:maxtimeallowed'];
+                       $act  = $orgitems[$idxs[$i]]['adlcp:timelimitaction'];
+                       $lms  = $orgitems[$idxs[$i]]['adlcp:datafromlms'];
+                       $mas  = $orgitems[$idxs[$i]]['adlcp:masteryscore'];
+                       $sql = "INSERT INTO ".TABLE_PREFIX."scorm_1_2_item
+                               VALUES (
+                                       0,
+                                       $orgid,
+                                       '$idxs[$i]',
+                                       '$title',
+                                       '$href',
+                                       '$scormtype',
+                                       '$pre',
+                                       '$max', '$act', '$lms', '$mas'
+                               )";
+                       $result = mysql_query($sql, $db);
+                       if (!$result) {
+                               require(AT_INCLUDE_PATH.'header.inc.php');
+                               $msg->addError('DB_NOT_UPDATED');
+                               $msg->printAll();
+                               require(AT_INCLUDE_PATH.'footer.inc.php');
+                               exit;
+                       }
+               }
+       }
+}
+
+
+function startElement($parser, $name, $h) {
+
+       global $orgid, $itemid,  $depth;
+       global $orgitems, $idx, $idxs;
+       global $res, $ress;
+       global $files, $finfo, $totalsize;
+
+       switch ($name) {
+               case 'organization':
+                               $orgid++;
+               case 'item':
+                               $itemid[$depth++]++;
+                               $idx = implode ('.', $itemid);
+                               array_push ($idxs, $idx);
+                               while (list($l, $r) = each($h)) {
+                                       $orgitems[$idx][$l]=$r;
+                               }
+                               break;
+               case 'title':
+                               break;
+
+               case 'resource':
+                               array_push ($ress, $h['identifier']);
+                               while (list($l, $r) = each($h)) {
+                                       $res[$h['identifier']][$l]=$r;
+                               }
+                               break;
+               case 'dependency':
+                               break;
+               case 'file':
+                               array_push ($files, $h['href']);
+                               $f=AT_CONTENT_DIR
+                                       .'import/'.$_SESSION['course_id']
+                                       .'/'.$h['href'];
+                               $finfo[$h['href']] = @stat($f);
+                               $totalsize +=  $finfo[$h['href']]['size'];
+                               break;
+       }
+}
+
+function endElement($parser, $name) {
+       global $orgid, $idx, $itemid, $depth, $text, $orgitems;
+
+       switch ($name) {
+               case 'organization':
+                               $depth=0;
+                               $itemid = array ($orgid);
+                               break;
+               case 'item':    
+                               while ($itemid[$depth]) {
+                                       array_pop($itemid);
+                               }
+                               $depth--;
+                               break;
+               case 'title':
+               case 'adlcp:datafromlms':
+               case 'adlcp:maxtimeallowed':
+               case 'adlcp:timelimitaction':
+               case 'adlcp:prerequisites':
+               case 'adlcp:masteryscore':
+                               $orgitems[$idx][$name] = trim($text);
+                               break;
+               case 'resource':
+
+       }
+       $text = '';
+}
+
+function characterData($parser, $data){
+       global $text;
+
+       $text .= $data;
+}
+
+?>
diff --git a/tools/packages/scorm-1.2/java/ATutorApiAdapterApplet.jar b/tools/packages/scorm-1.2/java/ATutorApiAdapterApplet.jar
new file mode 100644 (file)
index 0000000..0821db8
Binary files /dev/null and b/tools/packages/scorm-1.2/java/ATutorApiAdapterApplet.jar differ
diff --git a/tools/packages/scorm-1.2/java/ATutorApiAdapterApplet.java b/tools/packages/scorm-1.2/java/ATutorApiAdapterApplet.java
new file mode 100644 (file)
index 0000000..0ea5f9b
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * SCORM-1.2 API-Adapter Java Applet for ATutor
+ * Copyright (c) Matthai Kurian
+ *
+ * Made for ATutor, the same license terms as for ATutor itself apply.
+ *
+ * This Applet handles communication between ATutor and SCORM-1.2
+ * Sharable Content Objects (SCOs). Most communication is via Liveconnect.
+ * CMI (Computer Managed Instruction) data is sent to ATutor through http POST
+ * to an ATutor server side PHP script. SCORM-1.2 runtime behavior and CMI
+ * datamodel management is done by the PfPLMS SCORM-1.2 API-Adapter Core. 
+ */
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+import java.net.*;
+import java.io.*;
+
+public class ATutorApiAdapterApplet
+       extends java.applet.Applet
+       implements ch.ethz.pfplms.scorm.api.ApiAdapterInterface
+{
+       private ch.ethz.pfplms.scorm.api.ApiAdapter core;
+
+       private Hashtable ATutorScoCmi  = new Hashtable();
+
+       private String  ATutorStudentId;
+       private String  ATutorStudentName;
+
+       private String  ATutorScoId;
+       private String  ATutorPreparedScoId;
+
+       private boolean isVerbose   = false;
+
+       public ATutorApiAdapterApplet () {
+               core = new ch.ethz.pfplms.scorm.api.ApiAdapter ();
+       }
+
+       public  final void init () {
+               if (getParameter("verbose") != null) isVerbose = true;
+               ATutorStudentId     = getParameter ("student_id");
+               ATutorStudentName   = getParameter ("student_name");
+               say ("cmi.core.student_id=" +ATutorStudentId);
+               say ("cmi.core.student_name=" +ATutorStudentName);
+       }
+
+       private final void say (String s) {
+               if (isVerbose) System.out.println (s);
+       }
+
+       private final static String decode (String es) {
+
+               String s = es.replace('+', ' ');
+               int l = s.length();
+
+               int a = 0; 
+
+               StringBuffer rv = new StringBuffer(l);
+               byte[] b = null;
+
+               try {
+                       int i;
+                       while ((i = s.indexOf('%', a)) >= 0) {
+                               rv.append(s.substring(a, i));
+                               a = i;
+
+                               while (i+2 < l && s.charAt(i) == '%') i+=3;
+
+                               if (b == null || b.length < (i-a)/3) {
+                                       b = new byte[((i-a)/3)];
+                               }
+
+                               int x = 0;
+                               for (; a < i; a+=3) {
+                                       b[x++] = (byte) Integer.parseInt(
+                                               s.substring(a+1, a+3), 16
+                                       );
+                               }
+                               rv.append(new String(b, 0, x, "utf-8"));
+                       }
+
+                       if (a < l) rv.append(s.substring(a));
+                       return rv.toString();
+
+               } catch (Exception e) {
+                       return "";
+               }
+       }
+
+       /*
+        * Methods for ATutor to call via Liveconnect
+        */
+
+       public  final void ATutorPrepare (String sco_id) {
+               URLConnection po;
+               ATutorScoCmi.clear();
+               StringBuffer P = new StringBuffer();
+               P.append ("&sco_id="+sco_id);
+               say ("Retreiving cmi for sco="+sco_id+" from ATutor server");
+               try {
+                       //po = (HttpURLConnection) ( new java.net.URL (
+                       po = (URLConnection) ( new java.net.URL (
+                               getCodeBase().toString() + "read.php"
+                       )).openConnection();
+
+                       po.setRequestProperty (
+                               "Content-Type",
+                               "application/x-www-form-urlencoded"
+                       );
+                       po.setRequestProperty (
+                               "Content-Length",
+                               Integer.toString (P.length())
+                       );
+                       po.setDoOutput (true);
+                       po.setUseCaches (false);
+                       //po.setRequestMethod ("POST");
+                       po.setAllowUserInteraction (false);
+
+                       OutputStream os = po.getOutputStream();
+                       os.write (P.toString().getBytes());
+                       os.flush ();
+                       os.close ();
+
+                       BufferedReader br = new BufferedReader(
+                                       new InputStreamReader(
+                                               po.getInputStream ()
+                                       )
+                       );
+                       String s, l, r;
+                       while ((s=br.readLine())!=null) {
+                               if (s.indexOf('=') == -1) continue;
+                               l = s.substring (0, s.indexOf('='));
+                               r = s.substring (s.indexOf('=')+1, s.length());
+                               r = decode (r);
+                               say (" "+l + "="+r);
+                               ATutorScoCmi.put (l,r);
+                       }
+               } catch (Exception e) {
+                       say ("ATutor cmi retrieval failed.");
+                       say (e.toString());
+               }
+               ATutorPreparedScoId = sco_id;
+               say ("Done. Note: this was cmi for the next sco ("+sco_id+") to launch.");
+       }
+
+       public  final void ATutorReset (String s) {
+               if (s != null && s.equals(ATutorScoId)) {
+                       ATutorScoId = null;
+                       core.reset();
+                       say ("Reset by ATutor client.");
+               } 
+       }
+
+       private final String ATutorCommit (boolean fin) {
+
+               if (ATutorScoId == null) return "false"; 
+
+               core.transEnd();
+               StringBuffer P = new StringBuffer();
+               Hashtable ins = core.getTransNew ();
+               Hashtable mod = core.getTransMod ();
+               if (fin) {
+                       Object o = core.sysGet ("cmi.core.entry");
+                       if (o != null && o.toString().equals ("ab-initio")) {
+                               mod.put ("cmi.core.entry", "");
+                       }
+               } else {
+                       core.transBegin();
+               }
+
+               P.append ("&sco_id=" +ATutorScoId);
+
+               int i=0;
+               for (Enumeration e = ins.keys(); e.hasMoreElements(); i++) {
+                       Object l = e.nextElement();
+                       Object r = ins.get(l);
+                       P.append("&iL["+i+"]="+l.toString());
+                       P.append("&iR["+i+"]="+URLEncoder.encode(r.toString()));
+               }
+
+               int u=0;
+               for (Enumeration e = mod.keys(); e.hasMoreElements(); u++) {
+                       Object l = e.nextElement();
+                       Object r = mod.get(l);
+                       P.append("&uL["+u+"]="+l.toString());
+                       P.append("&uR["+u+"]="+URLEncoder.encode(r.toString()));
+               }
+
+               if (i == 0 && u == 0) {
+                       say ("Nothing to commit.");
+                       return "true";
+               }
+
+               //HttpURLConnection po;
+               URLConnection po;
+
+               try {
+                       //po = (HttpURLConnection) ( new java.net.URL (
+                       po = (URLConnection) ( new java.net.URL (
+                               getCodeBase().toString()
+                               + "write.php"
+                       )).openConnection();
+
+                       po.setRequestProperty (
+                               "Content-Type",
+                               "application/x-www-form-urlencoded"
+                       );
+                       po.setRequestProperty (
+                               "Content-Length",
+                               Integer.toString (P.length())
+                       );
+                       po.setDoOutput (true);
+                       po.setUseCaches (false);
+                       //po.setRequestMethod ("POST");
+                       po.setAllowUserInteraction (false);
+
+                       OutputStream os = po.getOutputStream();
+                       os.write (P.toString().getBytes());
+                       os.flush ();
+                       os.close ();
+
+                       BufferedReader r = new BufferedReader(
+                                       new InputStreamReader(
+                                               po.getInputStream ()
+                                       )
+                       );
+                       try {
+                               String s;
+                               while ((s=r.readLine())!=null) {
+                                       say(s);
+                               }
+                       } catch (EOFException ok) {}
+                       return "true";
+
+               } catch (Exception e) {
+                       say ("ATutor cmi storage failed.");
+                       say (e.toString());
+                       return "false";
+               }
+       }
+
+       public  final String ATutorGetValue (String l) {
+               String rv = core.LMSGetValue (l);
+               say ("ATutorGetValue("+l+")="+rv);
+               return rv;
+       }
+
+       /*
+        * Liveconnect interface methods for SCO
+        */
+
+       public  final String LMSInitialize (String s) { 
+               String rv = core.LMSInitialize(s);
+               say ("LMSInitialize("+s+")="+rv);
+               if (rv.equals("false")) return rv;
+               core.reset();
+               rv = core.LMSInitialize(s);
+               ATutorScoId = ATutorPreparedScoId;
+               core.sysPut ("cmi.core.student_id",   ATutorStudentId);
+               core.sysPut ("cmi.core.student_name", ATutorStudentName);
+               core.sysPut (ATutorScoCmi);
+               core.transBegin();
+               return rv;
+       }
+
+       public  final String LMSCommit (String s) {
+               String rv = core.LMSCommit(s);
+               if (rv.equals("false")) return rv;
+               rv = ATutorCommit(false); 
+               say ("LMSCommit("+s+")="+rv);
+               return rv;
+       }
+
+       public  final String LMSFinish (String s) {
+               String rv = core.LMSFinish(s);
+               say ("LMSFinish("+s+")="+rv);
+               if (rv.equals("false")) return rv;
+               rv = ATutorCommit(true);
+               ATutorScoId = null;
+               core.reset();
+               return rv;
+       }
+
+       public  final String LMSGetDiagnostic (String e) {
+               String rv = core.LMSGetDiagnostic (e);
+               say ("LMSGetDiagnostic("+e+")="+rv);
+               return rv;
+       }
+
+       public  final String LMSGetErrorString (String e) {
+               String rv = core.LMSGetErrorString (e);
+               say ("LMSGetErrorString("+e+")="+rv);
+               return rv;
+       }
+
+       public  final String LMSGetLastError () {
+               String rv = core.LMSGetLastError ();
+               say ("LMSLastError()="+rv);
+               return rv;
+       }
+
+       public  final String LMSGetValue (String l) {
+               String rv = core.LMSGetValue (l);
+               say ("LMSGetValue("+l+")="+rv);
+               return rv;
+       }
+
+       public  final String LMSSetValue (String l, String r) {
+               String rv = core.LMSSetValue (l, r);
+               say ("LMSSetValue("+l+"="+r+")="+rv);
+               return rv;
+       }
+}
diff --git a/tools/packages/scorm-1.2/java/PfPLMS-API-adapter-core.jar b/tools/packages/scorm-1.2/java/PfPLMS-API-adapter-core.jar
new file mode 100644 (file)
index 0000000..89f88ef
Binary files /dev/null and b/tools/packages/scorm-1.2/java/PfPLMS-API-adapter-core.jar differ
diff --git a/tools/packages/scorm-1.2/java/gnu.jar b/tools/packages/scorm-1.2/java/gnu.jar
new file mode 100644 (file)
index 0000000..660b496
Binary files /dev/null and b/tools/packages/scorm-1.2/java/gnu.jar differ
diff --git a/tools/packages/scorm-1.2/learner_view.php b/tools/packages/scorm-1.2/learner_view.php
new file mode 100644 (file)
index 0000000..dbd43ca
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+/*
+ * tools/packages/scorm-1.2/learner_view.php
+ *
+ * This file is part of ATutor, see http://www.atutor.ca
+ * 
+ * Copyright (C) 2005  Matthai Kurian 
+ * 
+ * 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+define('AT_INCLUDE_PATH', '../../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+$me = 'tools/packages/scorm-1.2/learner_view.php';
+$im = 'tools/packages/scorm-1.2/images/';
+
+$_pages[$me]['parent'] = 'packages/index.php';
+$_pages[$me]['children'] = array();
+
+$sql = "SELECT lvalue, rvalue
+       FROM  ".TABLE_PREFIX."cmi
+       WHERE   item_id = 0
+       AND     member_id = $_SESSION[member_id]
+       ";
+$result = mysql_query($sql, $db);
+while ($row = mysql_fetch_assoc($result)) {
+       $prefs[$row['lvalue']] = $row['rvalue'];
+}
+
+require ('./view.inc.php');
+require (AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/tools/packages/scorm-1.2/lib.inc.php b/tools/packages/scorm-1.2/lib.inc.php
new file mode 100644 (file)
index 0000000..ce3d575
--- /dev/null
@@ -0,0 +1,253 @@
+<?php
+/*
+ * tools/packages/scorm-1.2/lib.inc.php
+ *
+ * This file is part of ATutor, see http://www.atutor.ca
+ * 
+ * Copyright (C) 2005  Matthai Kurian 
+ * 
+ * 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+require(AT_INCLUDE_PATH.'lib/filemanager.inc.php');
+
+class package_handler_scorm_1_2 {
+
+       function getManagerItemLinks ($id) {
+               $result = $this->getOrgs ($id);
+               $rv = Array();
+               while ($row = mysql_fetch_assoc($result)) {
+                       array_push ($rv,
+                               '<div class="scormitem">'
+                               . '<a href="tools/packages/scorm-1.2/view.php?org_id='
+                               . $row['org_id'].'"'
+                               . ' title="ADL SCORM-1.2 Package"'
+                               . ' onclick="show(\'scorm_1_2_throb_' . $row['org_id'] . '\')"'
+                               . '>'
+                               .  $row['title'] .
+                               '</a></div>' . '
+                       <div class="scormfeedback" id="scorm_1_2_throb_'
+                       . $row['org_id']
+                       . '" style="display:none;position:absolute;">'
+                       . '<p>'
+                       . _AT(package_scorm_1_2_rte_loading)
+                       . '</p>'
+                       . '<img src="images/transfer.gif" height="20" width="90" alt="">'
+                       . '</div>'
+                               
+                       );
+               }
+               return $rv;
+       }
+
+       function getLearnerItemLinks ($id) {
+               $result = $this->getOrgs ($id);
+               $rv = Array();
+               while ($row = mysql_fetch_assoc($result)) {
+                       array_push ($rv, ''
+                               . '<div class="scormitem">'
+                               . '<a href="tools/packages/scorm-1.2/learner_view.php?org_id='
+                               . $row['org_id'].'"'
+                               . ' title="ADL SCORM-1.2 Package"'
+                               . ' onclick="show(\'scorm_1_2_throb_' . $row['org_id'] . '\')"'
+                               . '>'
+                               .  $row['title'] 
+                               . '</a>'
+                               . '</div>'
+
+                       . ' <div class="scormfeedback" id="scorm_1_2_throb_'
+                       . $row['org_id']
+                       . '" style="display:none;position:absolute;">'
+                       . '<p>'
+                       . _AT(package_scorm_1_2_rte_loading)
+                       . '</p>'
+                       . '<img src="images/transfer.gif" height="20" width="90" alt="">'
+                       . '</div>'
+                               
+                       );
+               }
+               return $rv;
+       }
+
+       function getCMILinks ($id) {
+               $result = $this->getOrgs ($id);
+               $rv = Array();
+               while ($row = mysql_fetch_assoc($result)) {
+                       array_push ($rv,
+                               '<div class="scormitem">'
+                               . '<a href="tools/packages/scorm-1.2/cmi.php?org_id='
+                               . $row['org_id'].'"'
+                               . ' title="SCORM-1.2 CMI Data"'
+                               . '>'
+                               .  $row['title'] .
+                               '</a></div>' 
+                       );
+               }
+               return $rv;
+       }
+
+       function getSettingsLinks ($id) {
+               $result = $this->getOrgs ($id);
+               $rv = Array();
+               while ($row = mysql_fetch_assoc($result)) {
+                       array_push ($rv,
+                               '<div class="scormitem">'
+                               . '<a href="tools/packages/scorm-1.2/settings.php?org_id='
+                               . $row['org_id'].'"'
+                               . ' title="ADL SCORM-1.2 Package"'
+                               . '>'
+                               .  $row['title'] .
+                               '</a></div>' 
+                       );
+               }
+               return $rv;
+       }
+
+       function getDeleteFormItems ($id, $i) {
+               $result = $this->getOrgs ($id);
+               $rv = Array();
+               while ($row = mysql_fetch_assoc($result)) {
+                       array_push ($rv, ''
+                               . '<input type="checkbox" '
+                               . 'id="goners['. $i . ']" '
+                               . 'name="goners[' . $i . ']" '
+                               . 'value="' . $row[org_id] . '" />'
+                               . '<label class="scorminput" '
+                               .  'for="goners['. $i .']">' . $row['title']
+                               .  '</label>'
+                               
+                       );
+                       $i++;
+               }
+               return $rv;
+       }
+
+       function getOrgs ($id) {
+
+               global $db;
+               $sql = "SELECT  o.org_id,
+                               o.title
+                       FROM    ".TABLE_PREFIX."packages p,
+                               ".TABLE_PREFIX."scorm_1_2_org o
+                       WHERE   p.package_id = $id
+                       AND     o.package_id = p.package_id
+                       ORDER   BY o.org_id
+               ";
+
+               return mysql_query($sql, $db);
+       }
+
+       function deletePackages ($pids) {
+               global $msg;
+               global $db;
+
+               /*
+                * Dangerous deleting begins here
+                */
+
+               foreach ($pids as $id) {
+                       $sql = "SELECT  p.package_id
+                               FROM    ".TABLE_PREFIX."packages p,
+                                       ".TABLE_PREFIX."scorm_1_2_org o
+                               WHERE   o.org_id = $id
+                               AND     o.package_id = p.package_id
+                               AND     p.ptype      = 'scorm-1.2'
+                               AND     p.course_id  = $_SESSION[course_id]
+                       ";
+
+                       $result = mysql_query($sql, $db);
+                       if (!$result) contunue;
+
+                       $row = mysql_fetch_assoc($result);
+                       $pkg = $row['package_id'];
+
+                       $sql = "SELECT  o.org_id
+                               FROM    ".TABLE_PREFIX."packages p,
+                                       ".TABLE_PREFIX."scorm_1_2_org o
+                               WHERE   p.package_id = $pkg
+                               AND     o.package_id = p.package_id
+                       ";
+
+                       $result = mysql_query($sql, $db);
+                       $orgs = array();
+                       while ($row = mysql_fetch_assoc($result)) {
+                               array_push ($orgs, $row['org_id']);     
+                       }
+
+                       $sql = "SELECT item_id
+                               FROM ".TABLE_PREFIX."scorm_1_2_item 
+                               WHERE  org_id = $id
+                               ";
+                       $result = mysql_query($sql, $db);
+                       $items = array('null');
+                       while ($row = mysql_fetch_assoc($result)) {
+                               array_push ($items, $row['item_id']);   
+                       }
+                       
+                       /*
+                        * Delete cmi data of all items in organization for
+                        * all learners
+                        */
+                       $sql = "DELETE  FROM ".TABLE_PREFIX."cmi
+                               WHERE   item_id in (" . implode (',', $items) . ")";
+
+                       $result = mysql_query ($sql, $db);
+
+       
+                       /*
+                        * Delete all items belonging to this organization
+                        */
+
+                       $sql = "DELETE  FROM ".TABLE_PREFIX."scorm_1_2_item
+                               WHERE   org_id = $id";
+
+                       $result = mysql_query ($sql, $db);
+
+                       /*
+                        * Delete the organization entry itself
+                        */
+
+                       $sql = "DELETE  FROM ".TABLE_PREFIX."scorm_1_2_org
+                               WHERE   org_id = $id";
+
+                       $result = mysql_query ($sql, $db);
+
+                       if (sizeOf ($orgs) == 1) {
+
+                               /*
+                                * There is no more organization left from
+                                * this  particular scorm-1.2 package, so
+                                * we delete the package entry and all files
+                                * which came with the package
+                                */
+
+                               $sql = "DELETE  FROM ".TABLE_PREFIX."packages WHERE package_id = $pkg";
+
+                               $result = mysql_query ($sql, $db);
+
+                               $pdir = AT_INCLUDE_PATH
+                               . '../sco/'
+                               . $_SESSION['course_id']
+                               . '/' . $pkg . '/';
+
+                               clr_dir ($pdir);
+                       }
+               }
+       }
+}
+
+$plug['scorm-1.2'] = new package_handler_scorm_1_2();
+
+?>
diff --git a/tools/packages/scorm-1.2/read.php b/tools/packages/scorm-1.2/read.php
new file mode 100644 (file)
index 0000000..4418788
--- /dev/null
@@ -0,0 +1,106 @@
+<?php
+/*
+ * tools/packages/scorm-1.2/read.php
+ *
+ * This file is part of ATutor, see http://www.atutor.ca
+ * 
+ * Copyright (C) 2005  Matthai Kurian 
+ * 
+ * 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+define('AT_INCLUDE_PATH', '../../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+
+       header('Content-Type: text/plain; charset=utf-8');
+
+       /*
+        * Get all stored cmi values
+        */
+       $sql = "SELECT lvalue, rvalue
+               FROM   ".TABLE_PREFIX."cmi
+               WHERE  member_id = ".$_SESSION['member_id']."
+               AND    item_id   = ".$_POST['sco_id'];
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_assoc($result)) {
+               $cmi[$row['lvalue']]=$row['rvalue'];
+       }
+
+       /*
+        * Insert default values
+        */
+       $defcmi['cmi.core.total_time']    = "0000:00:00.00";
+       $defcmi['cmi.core.lesson_status'] = "not attempted";
+       $defcmi['cmi.core.entry']         = "ab-initio";
+       while (list($l, $r) = each($defcmi)) {
+               if (!array_key_exists ($l, $cmi)) {
+                       $cmi[$l]=$r;
+                       $sql = "INSERT  INTO ".TABLE_PREFIX."cmi
+                               VALUES (0,
+                                       $_POST[sco_id],
+                                       $_SESSION[member_id],
+                                       '$l',
+                                       '$defcmi[$l]'
+                               )";
+                       $result = mysql_query($sql, $db);
+               }
+       }
+
+
+       /*
+        * Get cmi values which come from manifest
+        */
+       $sql = "SELECT  org_id,
+                       maxtimeallowed,
+                       timelimitaction,
+                       masteryscore,
+                       datafromlms
+               FROM    ".TABLE_PREFIX."scorm_1_2_item
+               WHERE   item_id = ".$_POST['sco_id'];
+
+       $result = mysql_query($sql, $db);
+       $row = mysql_fetch_assoc($result);
+
+       $cmi['cmi.launch_data']                    = $row['datafromlms'];
+       $cmi['cmi.student_data.max_time_allowed']  = $row['maxtimeallowed'];
+       $cmi['cmi.student_data.mastery_score']     = $row['masteryscore'];
+       $cmi['cmi.student_data.time_limit_action'] = $row['timelimitaction'];
+
+       $org_id = $row['org_id'];
+                       
+       /*
+        * Get lesson_mode and credit/no credit from organization.
+        * These values are set by the course owner
+        */
+       $sql = "SELECT  credit,
+                       lesson_mode
+               FROM    ".TABLE_PREFIX."scorm_1_2_org
+               WHERE   org_id = ".$org_id;
+       $result = mysql_query($sql, $db);
+       $row = mysql_fetch_assoc($result);
+       $cmi['cmi.core.credit']      = $row['credit'];
+       $cmi['cmi.core.lesson_mode'] = $row['lesson_mode'];
+
+       /*
+        * WE DON'T GIVE THE VALUE OF student_id !!!
+        * $cmi['cmi.core.student_id']=$_SESSION['member_id'];
+        */
+
+       while (list($l, $r) = each($cmi)) {
+               echo $l.'='. urlencode($r)."\n";
+       }
+?>
+
diff --git a/tools/packages/scorm-1.2/settings.php b/tools/packages/scorm-1.2/settings.php
new file mode 100644 (file)
index 0000000..2890579
--- /dev/null
@@ -0,0 +1,121 @@
+<?php
+/*
+ * tools/packages/scorm-1.2/settings.php
+ *
+ * This file is part of ATutor, see http://www.atutor.ca
+ * 
+ * Copyright (C) 2005  Matthai Kurian 
+ * 
+ * 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+define('AT_INCLUDE_PATH', '../../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
+       $_pages['tools/packages/scorm-1.2/settings.php']['parent'] =
+               'tools/packages/index.php';
+       $_pages['tools/packages/scorm-1.2/settings.php']['children'] = array ();
+}
+
+$org_id = $_GET['org_id'];
+if (isset($_POST[org_id])) {
+       $org_id = $_POST[org_id];
+       $sql = "UPDATE  ".TABLE_PREFIX."scorm_1_2_org
+               SET     lesson_mode = '$_POST[lesson_mode]',
+                       credit      = '$_POST[credit]'
+               WHERE   org_id = $org_id
+               ";
+       $result = mysql_query($sql, $db);
+       if ($result) {
+               $msg->addFeedback('SCORM_SETTINGS_SAVED');
+       } else {
+               $msg->addError('SCORM_SETTINGS_SAVE_ERROR');
+       }
+}
+
+$sql = "SELECT org_id, title, credit, lesson_mode
+       FROM    ".TABLE_PREFIX."scorm_1_2_org 
+       WHERE   org_id = $org_id
+       ";
+
+$result = mysql_query($sql, $db);
+
+if (mysql_num_rows($result) == 0) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->printInfos (NO_PACKAGES);
+       require (AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+} else {
+       $row = mysql_fetch_assoc($result);
+       $_pages['tools/packages/scorm-1.2/settings.php']['children'] = array();
+       $_pages['tools/packages/scorm-1.2/settings.php']['title']
+               = $row['title'];
+       $cr = $row['credit'];
+       $lm = $row['lesson_mode'];
+}
+
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<div class="input-form">
+<form name="form1" method="post"
+      action="tools/packages/scorm-1.2/settings.php"
+      enctype="multipart/form-data">
+
+<input type="hidden" name="org_id" value="<?php echo $org_id; ?>"
+
+<p> <?php echo _AT(scorm_credit_mode_info);?> </p>
+<p>
+      <?php echo _AT(scorm_credit_mode);?> <br />
+      <select name="credit">
+      <option value="credit" 
+       <?php if ($cr == 'credit') echo 'selected'; ?>><?php echo _AT('scorm_credit'); ?></option>
+      <option value="no-credit"
+       <?php if ($cr != 'credit') echo 'selected'; ?>><?php echo _AT('scorm_no_credit'); ?></option>
+      </select>
+</p>
+
+<p> <?php echo _AT(scorm_lesson_mode_info);?> </p>
+<p>
+      <?php echo _AT(scorm_lesson_mode);?> <br />
+      <select name="lesson_mode">
+      <option value="browse" <?php if ($lm == 'browse') echo 'selected'; ?>><?php echo _AT('scorm_browse'); ?></option>
+      <option value="normal" <?php if ($lm != 'browse') echo 'selected'; ?>><?php echo _AT('scorm_normal'); ?></option>
+      </select>
+</p>
+
+<div class="row buttons">
+      <input type="submit" name="submit" 
+            onClick="setClickSource('submit');"
+            value="<?php echo _AT('save'); ?>" />
+</div>
+
+</form>
+</div>
+
+
+<script language="javascript" type="text/javascript">
+
+var but_src;
+
+function setClickSource(name) {
+       but_src = name;
+}
+
+</script>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
diff --git a/tools/packages/scorm-1.2/view.inc.php b/tools/packages/scorm-1.2/view.inc.php
new file mode 100644 (file)
index 0000000..db0799c
--- /dev/null
@@ -0,0 +1,399 @@
+<?php
+/*
+ * tools/packages/scorm-1.2/view.inc.php
+ *
+ * This file is part of ATutor, see http://www.atutor.ca
+ * 
+ * Copyright (C) 2005  Matthai Kurian 
+ * 
+ * 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+function treeEl ($s) {
+       return '<img src="images/tree/tree_' . $s . '.gif" alt="">';
+}
+
+if (!$_GET['org_id']) {
+       header('Location: ../index.php');
+       exit;
+}  
+
+
+$sql = "SELECT first_name, last_name
+       FROM    ".TABLE_PREFIX."members
+       WHERE   member_id = ".$_SESSION['member_id'];
+
+$result = mysql_query($sql, $db);
+$q_row  = mysql_fetch_assoc($result);
+$student_name = $q_row['last_name'] . ', ' . $q_row['first_name'];
+
+//if ($student_name == ', ') $msg->addWarning('packages_no_student_name');
+
+       $sql = "SELECT  package_id
+               FROM    ".TABLE_PREFIX."scorm_1_2_org
+               WHERE   org_id = $_GET[org_id]";
+       $result = mysql_query($sql, $db);
+       $q_row  = mysql_fetch_assoc($result);
+       $pkg    = $q_row['package_id'];
+
+       $sql = "SELECT  item_id, scormtype, idx, title, href
+               FROM    ".TABLE_PREFIX."scorm_1_2_item
+               WHERE   org_id = $_GET[org_id]
+               ORDER   BY item_id
+       ";
+       $result = mysql_query($sql, $db);
+
+       $org = array();
+       $iid = array();
+       $ist = array();
+
+       $i=0;
+       while ($row = mysql_fetch_assoc($result)) {
+               $org[$i]['id']    = $row['item_id'];
+               $org[$i]['idx']   = $row['idx'];
+               $org[$i]['type']  = $row['scormtype'];
+               $org[$i]['title'] = $row['title'];
+               $org[$i]['href']  = $row['href'];
+               $iid[$row['item_id']] = $i;
+               $ist[$i] = 'not attempted';
+               $i++;
+       }
+       $c = sizeOf($org);
+
+       $sql = "SELECT  c.item_id,
+                       c.rvalue
+               FROM    ".TABLE_PREFIX."cmi c,
+                       ".TABLE_PREFIX."scorm_1_2_item i,
+                       ".TABLE_PREFIX."scorm_1_2_org  o
+               WHERE   o.org_id    = $_GET[org_id]
+               AND     i.org_id    = o.org_id
+               AND     i.item_id   = c.item_id
+               AND     c.member_id = $_SESSION[member_id]
+               AND     c.lvalue    = 'cmi.core.lesson_status'
+       ";
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_assoc($result)) {
+               $ist[$iid[$row['item_id']]] = $row['rvalue'];
+       }
+
+       $fil   = array();
+       $tree  = array();
+       $dtree = array();
+       $tidx  = explode ('.', $org[$c-1]['idx']);
+       $lvl   = sizeOf($tidx);
+       $llvl  = 42;
+
+       for ($l=0; $l<$lvl; $l++) array_push ($fil, treeEl ('space'));
+       array_push ($fil, treeEl('end'));
+
+       for ($i=$c-1; $i>=0; $i--) {
+               $tidx = explode ('.', $org[$i]['idx']);
+               $lvl = sizeOf($tidx);
+
+               switch ($org[$i]['type']) {
+               case 'organization':
+                       $_pages[$me]['title'] =$org[$i]['title'];
+
+               case 'cluster':
+                       array_pop ($fil);
+                       array_pop ($fil);
+                       array_push ($fil, treeEl('disabled'));
+                       break;
+
+               case 'sco':
+               case 'asset':
+                       if ($org[$i]['idx'].'.1' == $org[$i+1]['idx']) {
+                               // cluster with resource
+                               array_pop ($fil);
+                               array_pop ($fil);
+                               array_push ($fil, treeEl('disabled'));
+                               break;
+                       }
+                       
+                       array_pop ($fil);
+                       if ($lvl <  $llvl) array_push ($fil, treeEl('end'));
+                       if ($lvl == $llvl) array_push ($fil, treeEl ('split'));
+                       if ($lvl >  $llvl) {
+                                array_push ($fil, treeEl ('vertline'));
+                                array_push ($fil, treeEl ('end'));
+                       }
+                       break;
+               }
+
+               if ($org[$i]['href']) {
+                       if ($org[$i]['type'] == 'sco') {
+                               array_push ($tree,
+                                       implode ($fil) 
+                                       . '<img id="im' . $i
+                                       . '" name="im' . $i
+                                       . '" src="' . $im
+                                       . str_replace (' ', '-', $ist[$i])
+                                       . '.png" alt="' . $ist[$i]
+                                       . '" title="' . $ist[$i] . '">'
+                                       . '<a href="javascript:void(0)" '
+                                       . 'onclick="Launch(' . $i .');'
+                                       . 'return false;">'
+                                       . $org[$i]['title'] . '</a>'
+                               );
+                       } else {
+                               array_push ($tree,
+                                       implode ($fil) 
+                                       . '<img id="im' . $i
+                                       . '" name="im' . $i
+                                       . '" src="' . $im
+                                       . 'asset.png" alt="">'
+                                       . '<a href="javascript:void(0)" '
+                                       . 'onclick="Launch(' . $i .');'
+                                       . 'return false;">'
+                                       . $org[$i]['title'] . '</a>'
+                               );
+                       }
+               } else {
+                       array_push ($tree,
+                               implode ($fil)
+                               . '<b>' . $org[$i]['title'] . '</b>'
+                       );
+               }
+
+               $llvl = $lvl;
+       }
+
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       
+?>
+
+<div id="rte">
+<applet code="ATutorApiAdapterApplet" 
+id="RTE" name="RTE" mayscript="true"
+codebase="tools/packages/scorm-1.2"
+archive="java/ATutorApiAdapterApplet.jar,java/PfPLMS-API-adapter-core.jar,java/gnu.jar"
+width="0" height="0" >
+<param name="student_id"   value="<?php echo $_SESSION['member_id']?>" />
+<param name="student_name" value="<?php echo $student_name?>" />
+<?php  if ($prefs['show_rte_communication'] == 1) {
+               echo '<param name="verbose" value="1" />' . "\n";
+       }
+?>"
+               echo ($prefs['show_rte_communication'] == 1?'true':'false');
+</applet>
+</div>
+
+<script language="Javascript">
+
+function getObj (o) {
+       if(document.getElementById) return document.getElementById(o);
+       if(document.all) return document.all[o];
+}
+
+
+scHREF = new Array();
+scID   = new Array();
+scType = new Array();
+
+<?php
+       $c = sizeOf ($org);
+       for ($i=0; $i<=$c; $i++) {
+               echo 'scHREF[' . $i ."] = '";
+               if ($org[$i]['href'] != '') {
+                       echo AT_PACKAGE_URL_BASE
+                       . $_SESSION['course_id'] .'/' . $pkg .'/'
+                       . $org[$i]['href']
+                       ;
+               }
+               echo "';\n"
+               . 'scID[' . $i ."] = '" . $org[$i]['id'] . "';\n"
+               . 'scType[' . $i ."] = '" . $org[$i]['type'] . "';\n"
+               ;
+       }
+?>
+
+
+var scoidx      = 0;
+var nextscoidx  = 0;
+var autonext    = null;
+var scowindow   = null;
+var isRunning   = false;
+var isLaunching = false;
+var initstat    = '';
+
+var scoWidth  = 800;
+var scoHeight = 600;
+
+var auto_advance = <?php
+       echo ($prefs['auto_advance'] == 1 ?'true':'false');
+?>;
+var show_comm = <?php
+               echo ($prefs['show_rte_communication'] == 1?'true':'false');
+?>;
+
+function LMSInitialize (s) {
+       isRunning   = true;
+       isLaunching = false;
+
+       scoidx     = nextscoidx;
+       nextscoidx = null;
+       autonext   = null;
+
+       var o = getObj ('im'+scoidx);
+       o.src = '<?php echo $im;?>busy.png';
+       o.alt   = '<?php echo _AT('scorm_sco_is_running')?>';
+       o.title = '<?php echo _AT('scorm_sco_is_running')?>';
+       rv = window.document.RTE.LMSInitialize (s);
+       initstat = window.document.RTE.ATutorGetValue (
+               'cmi.core.lesson_status'
+       );
+       return rv;
+}
+
+function LMSFinish (s) {
+
+       checkResize();
+
+       var stat = window.document.RTE.ATutorGetValue ('cmi.core.lesson_status');
+       if (stat != '') {
+               var o = getObj ('im'+scoidx);
+               o.alt = stat;
+               o.title = stat;
+               if (stat == 'not attempted') stat = 'not-attempted';
+               o.src = '<?php echo $im;?>'+stat+'.png';
+               if (!autonext && auto_advance && !initstat.equals(stat)) {
+                       if (stat == 'completed' ||
+                           stat == 'passed'    ||
+                           stat == 'browsed') {
+                               for (i=scoidx+1; i<scHREF.length; i++) {
+                                       if (scHREF[i].length) {
+                                               autonext = i;
+                                               checkResize();
+                                               break;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       rv = window.document.RTE.LMSFinish (s);
+       if (rv == 'true') {
+               scowindow.close();
+               scowindow = null;
+               isRunning = false;
+               scoidx    = null;
+               if (autonext) setTimeout ('Launch (autonext)', 500);
+       }
+       return rv;
+}
+
+function LMSSetValue (l, r) {
+       return window.document.RTE.LMSSetValue (l, r);
+}
+
+function LMSGetValue (l) {
+       return window.document.RTE.LMSGetValue (l);
+}
+
+function LMSGetLastError () {
+       return window.document.RTE.LMSGetLastError ();
+}
+
+function LMSGetErrorString (s) {
+       return window.document.RTE.LMSGetErrorString (s);
+}
+
+function LMSGetDiagnostic (s) {
+       return window.document.RTE.LMSGetDiagnostic (s);
+}
+
+function LMSCommit (s) {
+       return window.document.RTE.LMSCommit (s);
+}
+
+
+function Launch (i) {
+       if (autonext && autonext != i) return;
+       nextscoidx = null; 
+       if (i == scoidx) return;
+
+       if (scowindow && scowindow.closed) {
+               isLaunching = false;
+               isRunning   = false;
+               scowindow   = null;
+               if (isRunning) {
+                       window.document.RTE.ATutorReset(scID[scoidx]);
+                       isRunning = false;
+               }
+       }
+
+       if (isLaunching) return;
+
+       if (scowindow != null) {
+              if (!isRunning) return;
+              scowindow.close();
+       }
+
+       isLaunching = true;
+       if (scType[i] == 'sco') {
+               try {
+                       window.document.RTE.ATutorPrepare(scID[i]);
+               } catch (Exception) {
+                       alert ('Sorry, LiveConnect does not work');
+                       return;
+               }
+               checkResize();
+               nextscoidx = i;
+       } else {
+               nextscoidx = null;
+       }
+
+       isLaunching = true;
+       scowindow = window.open (
+               scHREF[i],
+               'ATutorSCO',
+               'width='+scoWidth+',height='+scoHeight+','+
+               'toolbar=no,menubar=no,status=no,scrollbars=yes'
+       );
+       if (scType[i] == 'sco') {
+               this.API = this;
+               if (scowindow) scowindow.API = this;
+       }
+       scowindow.focus();
+}
+
+function cleanup () {
+       if (scowindow) scowindow.close();
+}
+
+function checkResize () {
+       try {
+               w = scowindow.innerWidth;
+               h = scowindow.innerHeight;
+               if (w >= 640 && h >= 480) {
+                       scoWidth  = w; 
+                       scoHeight = h;
+               }
+       } catch (Exception) {};
+}
+
+this.onunload=cleanup;
+</script>
+
+<?php
+       $p = "\n" . '<div id="scorm_1_2_toc" style="display:block">' . "\n";
+       for ($i=$c-1; $i>=0; $i--) {
+               $p .= $tree[$i] . '<br />' . "\n";
+       }
+       $p .= '</div>' . "\n";
+       echo utf8_decode($p); 
+?>
+
+
diff --git a/tools/packages/scorm-1.2/view.php b/tools/packages/scorm-1.2/view.php
new file mode 100644 (file)
index 0000000..b1c7a49
--- /dev/null
@@ -0,0 +1,411 @@
+<?php
+/*
+ * tools/packages/scorm-1.2/view.inc.php
+ *
+ * This file is part of ATutor, see http://www.atutor.ca
+ * 
+ * Copyright (C) 2005  Matthai Kurian 
+ * 
+ * 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+function treeEl ($s) {
+       return '<img src="images/tree/tree_' . $s . '.gif" alt="">';
+}
+
+define('AT_INCLUDE_PATH', '../../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+$me = 'tools/packages/scorm-1.2/view.php';
+$im = 'tools/packages/scorm-1.2/images/';
+
+if (!$_GET['org_id']) {
+       header('Location: ../index.php');
+       exit;
+}  
+
+
+$sql = "SELECT first_name, last_name
+       FROM    ".TABLE_PREFIX."members
+       WHERE   member_id = ".$_SESSION['member_id'];
+
+$result = mysql_query($sql, $db);
+$q_row  = mysql_fetch_assoc($result);
+$student_name = $q_row['last_name'] . ', ' . $q_row['first_name'];
+
+//if ($student_name == ', ') $msg->addWarning ('packages_no_student_name');
+
+       $sql = "SELECT  package_id
+               FROM    ".TABLE_PREFIX."scorm_1_2_org
+               WHERE   org_id = $_GET[org_id]";
+       $result = mysql_query($sql, $db);
+       $q_row  = mysql_fetch_assoc($result);
+       $pkg    = $q_row['package_id'];
+
+       $sql = "SELECT  item_id, scormtype, idx, title, href
+               FROM    ".TABLE_PREFIX."scorm_1_2_item
+               WHERE   org_id = $_GET[org_id]
+               ORDER   BY item_id
+       ";
+       $result = mysql_query($sql, $db);
+
+       $org = array();
+       $iid = array();
+       $ist = array();
+
+       $i=0;
+       while ($row = mysql_fetch_assoc($result)) {
+               $org[$i]['id']    = $row['item_id'];
+               $org[$i]['idx']   = $row['idx'];
+               $org[$i]['type']  = $row['scormtype'];
+               $org[$i]['title'] = $row['title'];
+               $org[$i]['href']  = $row['href'];
+               $iid[$row['item_id']] = $i;
+               $ist[$i] = 'not attempted';
+               $i++;
+       }
+       $c = sizeOf($org);
+
+       $sql = "SELECT  c.item_id,
+                       c.rvalue
+               FROM    ".TABLE_PREFIX."cmi c,
+                       ".TABLE_PREFIX."scorm_1_2_item i,
+                       ".TABLE_PREFIX."scorm_1_2_org  o
+               WHERE   o.org_id    = $_GET[org_id]
+               AND     i.org_id    = o.org_id
+               AND     i.item_id   = c.item_id
+               AND     c.member_id = $_SESSION[member_id]
+               AND     c.lvalue    = 'cmi.core.lesson_status'
+       ";
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_assoc($result)) {
+               $ist[$iid[$row['item_id']]] = $row['rvalue'];
+       }
+
+       $fil   = array();
+       $tree  = array();
+       $dtree = array();
+       $tidx  = explode ('.', $org[$c-1]['idx']);
+       $lvl   = sizeOf($tidx);
+       $llvl  = 42;
+
+       for ($l=0; $l<$lvl; $l++) array_push ($fil, treeEl ('space'));
+       array_push ($fil, treeEl('end'));
+
+       for ($i=$c-1; $i>=0; $i--) {
+               $tidx = explode ('.', $org[$i]['idx']);
+               $lvl = sizeOf($tidx);
+
+               switch ($org[$i]['type']) {
+               case 'organization':
+                       $_pages[$me]['title'] =$org[$i]['title'];
+
+               case 'cluster':
+                       array_pop ($fil);
+                       array_pop ($fil);
+                       array_push ($fil, treeEl('disabled'));
+                       break;
+
+               case 'sco':
+               case 'asset':
+                       if ($org[$i]['idx'].'.1' == $org[$i+1]['idx']) {
+                               // cluster with resource
+                               array_pop ($fil);
+                               array_pop ($fil);
+                               array_push ($fil, treeEl('disabled'));
+                               break;
+                       }
+                       
+                       array_pop ($fil);
+                       if ($lvl <  $llvl) array_push ($fil, treeEl('end'));
+                       if ($lvl == $llvl) array_push ($fil, treeEl ('split'));
+                       if ($lvl >  $llvl) {
+                                array_push ($fil, treeEl ('vertline'));
+                                array_push ($fil, treeEl ('end'));
+                       }
+                       break;
+               }
+
+               if ($org[$i]['href']) {
+                       if ($org[$i]['type'] == 'sco') {
+                               array_push ($tree,
+                                       implode ($fil) 
+                                       . '<img id="im' . $i
+                                       . '" name="im' . $i
+                                       . '" src="' . $im
+                                       . str_replace (' ', '-', $ist[$i])
+                                       . '.png" alt="' . $ist[$i]
+                                       . '" title="' . $ist[$i] . '">'
+                                       . '<a href="javascript:void(0)" '
+                                       . 'onclick="Launch(' . $i .');'
+                                       . 'return false;">'
+                                       . $org[$i]['title'] . '</a>'
+                               );
+                       } else {
+                               array_push ($tree,
+                                       implode ($fil) 
+                                       . '<img id="im' . $i
+                                       . '" name="im' . $i
+                                       . '" src="' . $im
+                                       . 'asset.png" alt="">'
+                                       . '<a href="javascript:void(0)" '
+                                       . 'onclick="Launch(' . $i .');'
+                                       . 'return false;">'
+                                       . $org[$i]['title'] . '</a>'
+                               );
+                       }
+               } else {
+                       array_push ($tree,
+                               implode ($fil)
+                               . '<b>' . $org[$i]['title'] . '</b>'
+                       );
+               }
+
+               $llvl = $lvl;
+       }
+
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       
+?>
+
+<div id="rte">
+<applet code="ATutorApiAdapterApplet" 
+id="RTE" name="RTE" mayscript="true"
+codebase="tools/packages/scorm-1.2"
+archive="java/ATutorApiAdapterApplet.jar,java/PfPLMS-API-adapter-core.jar,java/gnu.jar"
+width="0" height="0" >
+<param name="student_id"   value="<?php echo $_SESSION['member_id']?>" />
+<param name="student_name" value="<?php echo $student_name?>" />
+<?php  if ($prefs['show_rte_communication'] == 1) {
+               echo '<param name="verbose" value="1" />' . "\n";
+       }
+?>
+</applet>
+</div>
+
+<script language="Javascript">
+
+function getObj (o) {
+       if(document.getElementById) return document.getElementById(o);
+       if(document.all) return document.all[o];
+}
+
+
+scHREF = new Array();
+scID   = new Array();
+scType = new Array();
+
+<?php
+       $c = sizeOf ($org);
+       for ($i=0; $i<=$c; $i++) {
+               echo 'scHREF[' . $i ."] = '";
+               if ($org[$i]['href'] != '') {
+                       echo AT_PACKAGE_URL_BASE
+                       . $_SESSION['course_id'] .'/' . $pkg .'/'
+                       . $org[$i]['href']
+                       ;
+               }
+               echo "';\n"
+               . 'scID[' . $i ."] = '" . $org[$i]['id'] . "';\n"
+               . 'scType[' . $i ."] = '" . $org[$i]['type'] . "';\n"
+               ;
+       }
+?>
+
+
+var scoidx      = 0;
+var nextscoidx  = 0;
+var autonext    = null;
+var scowindow   = null;
+var isRunning   = false;
+var isLaunching = false;
+var initstat    = '';
+
+var scoWidth  = 800;
+var scoHeight = 600;
+
+var auto_advance = <?php
+       echo ($prefs['auto_advance'] == 1 ?'true':'false');
+?>;
+var show_comm = <?php
+               echo ($prefs['show_rte_communication'] == 1?'true':'false');
+?>;
+
+function LMSInitialize (s) {
+       rv = window.document.RTE.LMSInitialize (s);
+       if (rv != 'true') return rv;
+
+       isRunning   = true;
+       isLaunching = false;
+
+       scoidx     = nextscoidx;
+       nextscoidx = null;
+       autonext   = null;
+
+       var o = getObj ('im'+scoidx);
+       o.src = '<?php echo $im;?>busy.png';
+       o.alt   = '<?php echo _AT('scorm_sco_is_running')?>';
+       o.title = '<?php echo _AT('scorm_sco_is_running')?>';
+       initstat = window.document.RTE.ATutorGetValue (
+               'cmi.core.lesson_status'
+       );
+       return rv;
+}
+
+function LMSFinish (s) {
+
+       checkResize();
+
+       var stat = window.document.RTE.ATutorGetValue ('cmi.core.lesson_status');
+       if (stat != '') {
+               var o = getObj ('im'+scoidx);
+               o.alt = stat;
+               o.title = stat;
+               if (stat == 'not attempted') stat = 'not-attempted';
+               o.src = '<?php echo $im;?>'+stat+'.png';
+
+               if (!autonext && auto_advance && initstat != stat) {
+                       if (stat == 'completed' ||
+                           stat == 'passed'    ||
+                           stat == 'browsed') {
+                               for (i=scoidx+1; i<scHREF.length; i++) {
+                                       if (scHREF[i].length) {
+                                               autonext = i;
+                                               checkResize();
+                                               break;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       rv = window.document.RTE.LMSFinish (s);
+       if (rv == 'true') {
+               scowindow.close();
+               scowindow = null;
+               isRunning = false;
+               scoidx    = null;
+               if (autonext) setTimeout ('Launch (autonext)', 500);
+       }
+       return rv;
+}
+
+function LMSSetValue (l, r) {
+       return window.document.RTE.LMSSetValue (l, r);
+}
+
+function LMSGetValue (l) {
+       return window.document.RTE.LMSGetValue (l);
+}
+
+function LMSGetLastError () {
+       return window.document.RTE.LMSGetLastError ();
+}
+
+function LMSGetErrorString (s) {
+       return window.document.RTE.LMSGetErrorString (s);
+}
+
+function LMSGetDiagnostic (s) {
+       return window.document.RTE.LMSGetDiagnostic (s);
+}
+
+function LMSCommit (s) {
+       return window.document.RTE.LMSCommit (s);
+}
+
+
+function Launch (i) {
+       if (autonext && autonext != i) return;
+       nextscoidx = null; 
+       if (i == scoidx) return;
+
+       if (scowindow && scowindow.closed) {
+               isLaunching = false;
+               isRunning   = false;
+               scowindow   = null;
+               if (isRunning) {
+                       window.document.RTE.ATutorReset(scID[scoidx]);
+                       isRunning = false;
+               }
+       }
+
+       if (isLaunching) return;
+
+       if (scowindow != null) {
+              if (!isRunning) return;
+              scowindow.close();
+       }
+
+       isLaunching = true;
+       if (scType[i] == 'sco') {
+               try {
+                       window.document.RTE.ATutorPrepare(scID[i]);
+               } catch (Exception) {
+                       alert ('Sorry, LiveConnect does not work');
+                       return;
+               }
+               checkResize();
+               nextscoidx = i;
+       } else {
+               nextscoidx = null;
+       }
+
+       isLaunching = true;
+       scowindow = window.open (
+               scHREF[i],
+               'ATutorSCO',
+               'width='+scoWidth+',height='+scoHeight+','+
+               'toolbar=no,menubar=no,status=no,scrollbars=yes'
+       );
+       if (scType[i] == 'sco') {
+               this.API = this;
+               if (scowindow) scowindow.API = this;
+       }
+       scowindow.focus();
+}
+
+function cleanup () {
+       if (scowindow) scowindow.close();
+}
+
+function checkResize () {
+       try {
+               w = scowindow.innerWidth;
+               h = scowindow.innerHeight;
+               if (w >= 640 && h >= 480) {
+                       scoWidth  = w; 
+                       scoHeight = h;
+               }
+       } catch (Exception) {};
+}
+
+this.onunload=cleanup;
+</script>
+
+<?php
+       $p = "\n" . '<div id="scorm_1_2_toc" style="display:block">' . "\n";
+       for ($i=$c-1; $i>=0; $i--) {
+               $p .= $tree[$i] . '<br />' . "\n";
+       }
+       $p .= '</div>' . "\n";
+       echo utf8_decode($p); 
+?>
+<?php
+
+
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+
+?>
\ No newline at end of file
diff --git a/tools/packages/scorm-1.2/write.php b/tools/packages/scorm-1.2/write.php
new file mode 100644 (file)
index 0000000..71fd1b7
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+/*
+ * tools/packages/scorm-1.2/write.php
+ *
+ * This file is part of ATutor, see http://www.atutor.ca
+ * 
+ * Copyright (C) 2005  Matthai Kurian 
+ * 
+ * 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+define('AT_INCLUDE_PATH', '../../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+
+header('Content-Type: text/plain; charset=utf-8');
+$L = $_POST['iL'];
+$R = $_POST['iR'];
+$ic = sizeOf ($L);
+for ($i=0; $i<$ic; $i++) {
+       $sql = "INSERT INTO ".TABLE_PREFIX."cmi
+               VALUES (NULL,
+                        $_POST[sco_id],
+                        $_SESSION[member_id],
+                       '$L[$i]', '$R[$i]'
+               )";
+       $result = mysql_query($sql, $db);
+}
+
+$L = $_POST['uL'];
+$R = $_POST['uR'];
+$uc = sizeOf ($L);
+
+for ($i=0; $i<$uc; $i++) {
+       $sql = "UPDATE  ".TABLE_PREFIX."cmi
+               SET     rvalue    = '$R[$i]'
+               WHERE   item_id   = $_POST[sco_id]
+               AND     member_id =  $_SESSION[member_id]
+               AND     lvalue    = '$L[$i]'
+       ";
+       $result = mysql_query($sql, $db);
+
+}
+echo 'ATutor: '.$ic.' inserted '.$uc.' updated.'."\n";
+
+?>
+
diff --git a/tools/packages/settings.php b/tools/packages/settings.php
new file mode 100644 (file)
index 0000000..8473c1a
--- /dev/null
@@ -0,0 +1,65 @@
+<?php
+/*
+ * tools/packages/settings.php
+ *
+ * This file is part of ATutor, see http://www.atutor.ca
+ * 
+ * Copyright (C) 2005  Matthai Kurian 
+ * 
+ * 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+$ptypes = explode (',', AT_PACKAGE_TYPES);
+$plug = Array();
+foreach ($ptypes as $type) {
+       include ('./' . $type . '/lib.inc.php');
+}
+
+$sql = "SELECT package_id,
+               ptype
+       FROM    ".TABLE_PREFIX."packages
+       WHERE   course_id = $_SESSION[course_id]
+       ORDER   BY package_id
+       ";
+
+$result = mysql_query($sql, $db);
+       
+$p  = '<p><ol>';
+$num = 0;
+while ($row = mysql_fetch_assoc($result)) {
+       foreach ($plug[$row['ptype']]->getSettingsLinks($row['package_id']) as $l) {
+               $p .= '<li>' . $l . '</li>';
+               $num++;
+       }
+}
+if ($num == 0) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->addInfo (NO_PACKAGES);
+       $msg->printAll();
+       require (AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+} 
+
+$p .= '</ol>';
+$p .= '</p>';
+
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+echo $p;
+require (AT_INCLUDE_PATH.'footer.inc.php');
+?>
diff --git a/tools/polls/add.php b/tools/polls/add.php
new file mode 100644 (file)
index 0000000..214a7d1
--- /dev/null
@@ -0,0 +1,94 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+define('AT_INCLUDE_PATH', '../../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_POLLS);
+
+if ($_POST['cancel']) {
+       $msg->addFeedback('CANCELLED');
+       Header('Location: index.php');
+       exit;
+}
+
+if ($_POST['add_poll'] && (authenticate(AT_PRIV_POLLS, AT_PRIV_RETURN))) {
+       if (trim($_POST['question']) == '') {
+               $msg->addError(array('EMPTY_FIELDS', _AT('question')));
+       }
+
+       if ((trim($_POST['c1']) == '') || (trim($_POST['c2']) == '')) {
+               $msg->addError('POLL_QUESTION_MINIMUM');
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['question'] = $addslashes($_POST['question']);
+               //Check if the question has exceeded the words amount - 100, decided in the db
+               if ($strlen($_POST['question']) > 100){
+                       $_POST['question'] = $substr($_POST['question'], 0, 100);
+               }
+
+               for ($i=1; $i<= AT_NUM_POLL_CHOICES; $i++) {
+                       $trimmed_word = $addslashes($_POST['c' . $i]);
+                       if ($strlen($trimmed_word) > 100){
+                               $trimmed_word = $substr($trimmed_word, 0, 100);
+                       }
+                       $choices .= "'" . $trimmed_word . "',0,";
+               }
+               $choices = substr($choices, 0, -1);     //Remove the last comma.
+
+               $sql    = "INSERT INTO ".TABLE_PREFIX."polls VALUES (NULL, $_SESSION[course_id], '$_POST[question]', NOW(), 0, $choices)";
+               $result = mysql_query($sql,$db);
+               
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: index.php');
+               exit;
+       }
+       for ($i=1; $i<= AT_NUM_POLL_CHOICES; $i++) {
+               $_POST['c' . $i] = $stripslashes($_POST['c' . $i]);
+       }
+       $_POST['question'] = $stripslashes($_POST['question']);
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="add_poll" value="true" />
+
+<div class="input-form">       
+<fieldset class="group_form"><legend class="group_form"><?php echo _AT('add_poll'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="question"><?php  echo _AT('question'); ?></label><br />
+               <textarea name="question" cols="45" rows="3" id="question" style="width:90%;"><?php if (isset ($_POST['question'])) echo htmlspecialchars($_POST['question']);  ?></textarea>
+       </div>
+
+<?php for ($i=1; $i<= AT_NUM_POLL_CHOICES; $i++): ?>
+       <div class="row">
+               <?php if (($i==1) || ($i==2)) { ?>
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div>
+               <?php } ?>
+               <label for="c<?php echo $i; ?>"><?php echo _AT('choice'); ?> <?php echo $i; ?></label><br />
+               <input type="text" name="c<?php echo $i; ?>" value="<?php if (isset($_POST['c' . $i])) echo htmlspecialchars($_POST['c' . $i]);  ?>" size="50" id="c<?php echo $i; ?>" />
+       </div>
+<?php endfor; ?>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/polls/delete.php b/tools/polls/delete.php
new file mode 100644 (file)
index 0000000..9d5dcb0
--- /dev/null
@@ -0,0 +1,63 @@
+<?php\r
+/****************************************************************************/\r
+/* ATutor                                                                                                                                      */\r
+/****************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */\r
+/* Adaptive Technology Resource Centre / University of Toronto                         */\r
+/* http://atutor.ca                                                                                                                    */\r
+/*                                                                                                                                                     */\r
+/* This program is free software. You can redistribute it and/or                       */\r
+/* modify it under the terms of the GNU General Public License                         */\r
+/* as published by the Free Software Foundation.                                                       */\r
+/****************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+authenticate(AT_PRIV_POLLS);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       Header('Location: index.php');\r
+       exit;\r
+} else if (isset($_POST['submit_yes'])) {\r
+       $_POST['pid'] = intval($_POST['pid']);\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."polls WHERE poll_id=$_POST[pid] AND course_id=$_SESSION[course_id]";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."polls_members WHERE poll_id=$_POST[pid] AND course_id=$_SESSION[course_id]";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: index.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$msg->printErrors();\r
+\r
+$_GET['pid'] = intval($_GET['pid']); \r
+\r
+$sql = "SELECT * FROM ".TABLE_PREFIX."polls WHERE poll_id=$_GET[pid] AND course_id=$_SESSION[course_id]";\r
+\r
+$result = mysql_query($sql,$db);\r
+if (mysql_num_rows($result) == 0) {\r
+       $msg->addError('ITEM_NOT_FOUND');\r
+} else {\r
+       $row = mysql_fetch_assoc($result);\r
+\r
+       $hidden_vars['delete_poll'] = TRUE;\r
+       $hidden_vars['pid'] = $_GET['pid'];\r
+\r
+       $confirm = array('DELETE_POLL', AT_print($row['question'], 'polls.question'));\r
+       $msg->addConfirm($confirm, $hidden_vars);\r
+       $msg->printConfirm();\r
+\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+\r
+?>
\ No newline at end of file
diff --git a/tools/polls/edit.php b/tools/polls/edit.php
new file mode 100644 (file)
index 0000000..40cc126
--- /dev/null
@@ -0,0 +1,113 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_POLLS);
+
+
+if ($_POST['cancel']) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php');
+       exit;
+}
+
+if (isset($_GET['poll_id'])) {
+       $poll_id = intval($_GET['poll_id']);
+} else {
+       $poll_id = intval($_POST['poll_id']);
+}
+
+if ($_POST['edit_poll']) {
+       if (trim($_POST['question']) == '') {
+               $msg->addError(array('EMPTY_FIELDS', _AT('question')));
+       }
+
+       if ((trim($_POST['c1']) == '') || (trim($_POST['c2']) == '')) {
+               $msg->addError('POLL_QUESTION_MINIMUM');
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['question'] = $addslashes($_POST['question']);
+               //Check if the question has exceeded the words amount - 100, decided in the db
+               $_POST['question'] = validate_length($_POST['question'], 100);
+
+               for ($i=1; $i<= AT_NUM_POLL_CHOICES; $i++) {
+                       $trimmed_word = validate_length($_POST['c' . $i], 100);                 
+                       $trimmed_word = $addslashes($trimmed_word);
+                       $choices .= "choice$i = '" . $trimmed_word . "',";
+               }
+               $choices = substr($choices, 0, -1);
+
+               $sql = "UPDATE ".TABLE_PREFIX."polls SET question='$_POST[question]', created_date=created_date, $choices WHERE poll_id=$poll_id AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql,$db);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               Header('Location: index.php');
+               exit;
+       }
+       for ($i=1; $i<= AT_NUM_POLL_CHOICES; $i++) {
+               $_POST['c' . $i] = $stripslashes($_POST['c' . $i]);
+       }
+       $_POST['question'] = $stripslashes($_POST['question']);
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+       if ($poll_id == 0) {
+               $msg->printErrors('ITEM_NOT_FOUND');
+               require (AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+       
+       $sql = "SELECT * FROM ".TABLE_PREFIX."polls WHERE poll_id=$poll_id AND course_id=$_SESSION[course_id]";
+       $result = mysql_query($sql,$db);
+       if (!($row = mysql_fetch_assoc($result))) {
+               $msg->printErrors('ITEM_NOT_FOUND');
+               require (AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="edit_poll" value="true" />
+<input type="hidden" name="poll_id" value="<?php echo $row['poll_id']; ?>" />
+
+<div class="input-form">
+<fieldset class="group_form"><legend class="group_form"><?php echo _AT('edit_poll'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="question"><?php echo _AT('question'); ?>:</label><br />
+               <textarea name="question" cols="55" rows="3" id="question"><?php if (isset ($_POST['question'])) { echo htmlspecialchars($_POST['question']); } else { echo htmlspecialchars($row['question']); } ?></textarea>
+       </div>
+
+<?php
+       for ($i=1; $i<= AT_NUM_POLL_CHOICES; $i++): ?>
+               <div class="row">
+                       <?php if (($i==1) || ($i==2)) { ?>
+                               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div>
+                       <?php } ?>
+                       <label for="c<?php echo $i; ?>"><?php echo _AT('choice'); ?> <?php echo $i; ?>:</label><br />
+                       <input type="text" name="c<?php echo $i; ?>" id="c<?php echo $i; ?>" value="<?php if (isset ($_POST['c' . $i])) { echo htmlspecialchars($_POST['c' . $i]); } else { echo htmlspecialchars($row['choice' . $i]); }?>" size="40" />
+               </div>
+
+<?php endfor; ?>
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?> " />
+       </div>
+       </fieldset>
+</div>
+</form>
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/polls/index.php b/tools/polls/index.php
new file mode 100644 (file)
index 0000000..6ca08a7
--- /dev/null
@@ -0,0 +1,103 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_POLLS);
+
+if (isset($_POST['edit'], $_POST['poll'])) {
+       header('Location: edit.php?poll_id=' . $_POST['poll']);
+       exit;
+} else if (isset($_POST['delete'], $_POST['poll'])) { 
+       header('Location: delete.php?pid=' . $_POST['poll'] );
+       exit;
+} else if (!empty($_POST)) {
+       $msg->addError('NO_ITEM_SELECTED');
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+$orders = array('asc' => 'desc', 'desc' => 'asc');
+$cols   = array('question' => 1, 'created_date' => 1, 'total' => 1);
+
+if (isset($_GET['asc'])) {
+       $order = 'asc';
+       $col   = isset($cols[$_GET['asc']]) ? $_GET['asc'] : 'created_date';
+} else if (isset($_GET['desc'])) {
+       $order = 'desc';
+       $col   = isset($cols[$_GET['desc']]) ? $_GET['desc'] : 'created_date';
+} else {
+       // no order set
+       $order = 'desc';
+       $col   = 'created_date';
+}
+
+$sql   = "SELECT poll_id, question, created_date, total FROM ".TABLE_PREFIX."polls WHERE course_id=$_SESSION[course_id] ORDER BY $col $order";
+$result = mysql_query($sql, $db);
+
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<table class="data" summary="" rules="cols">
+<colgroup>
+       <?php if ($col == 'question'): ?>
+               <col />
+               <col class="sort" />
+               <col span="2" />
+       <?php elseif($col == 'created_date'): ?>
+               <col span="2" />
+               <col class="sort" />
+               <col />
+       <?php elseif($col == 'total'): ?>
+               <col span="3" />
+               <col class="sort" />
+       <?php endif; ?>
+</colgroup>
+<thead>
+<tr>
+       <th scope="col">&nbsp;</th>
+       <th scope="col"><a href="tools/polls/index.php?<?php echo $orders[$order]; ?>=question"><?php echo _AT('question'); ?></a></th>
+       <th scope="col"><a href="tools/polls/index.php?<?php echo $orders[$order]; ?>=created_date"><?php echo _AT('created'); ?></a></th>
+       <th scope="col"><a href="tools/polls/index.php?<?php echo $orders[$order]; ?>=total"><?php echo _AT('total_votes'); ?></a></th>
+</tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="4">
+               <input type="submit" name="edit"   value="<?php echo _AT('edit'); ?>" />
+               <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" />
+       </td>
+</tr>
+</tfoot>
+<tbody>
+<?php if ($row = mysql_fetch_assoc($result)) : ?>
+       <?php do { ?>
+               <tr onmousedown="document.form['p_<?php echo $row['poll_id']; ?>'].checked = true; rowselect(this);" id="r_<?php echo $row['poll_id']; ?>">
+                       <td><input type="radio" id="p_<?php echo $row['poll_id']; ?>" name="poll" value="<?php echo $row['poll_id']; ?>" /></td>
+                       <td><label for="p_<?php echo $row['poll_id']; ?>"><?php echo AT_print($row['question'], 'polls.question'); ?></label></td>
+                       <td><?php echo $row['created_date']; ?></td>
+                       <td><?php echo $row['total']; ?></td>
+               </tr>
+       <?php } while($row = mysql_fetch_assoc($result)); ?>
+<?php else: ?>
+       <tr>
+               <td colspan="4"><?php echo _AT('none_found'); ?></td>
+       </tr>
+<?php endif; ?>
+</tbody>
+</table>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php');  ?>
\ No newline at end of file
diff --git a/tools/prog.php b/tools/prog.php
new file mode 100644 (file)
index 0000000..1c559dd
--- /dev/null
@@ -0,0 +1,88 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+sleep(1);
+$_user_location = 'prog';
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+session_write_close();
+if ($_GET['tile']) {
+       $lang_variable = 'tile_progress';
+} else {
+       $lang_variable = 'upload_progress';
+}
+
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html lang="<?php echo $myLang->getCode(); ?>">
+<head>
+       <title><?php echo _AT($lang_variable); ?></title>
+       <?php if ($_GET['frame']) { ?>
+               <META HTTP-EQUIV="refresh" content="3;URL=prog.php?frame=1"> 
+       <?php } ?>
+       <link rel="stylesheet" href="<?php echo $_base_path; ?>themes/<?php echo $_SESSION['prefs']['PREF_THEME']; ?>/styles.css" type="text/css" />
+       <meta http-equiv="Content-Type" content="text/html; <?php echo $myLang->getCharacterSet(); ?>" />
+</head>
+<body <?php
+       if ($_SESSION['done']) {
+               echo 'onload="parent.window.close();"';
+       }
+?>>
+<?php 
+if (!$_GET['frame']) {  ?>
+&nbsp;<a href="javascript:window.close();"><?php echo _AT('close'); ?></a>
+<h3><?php echo _AT($lang_variable); ?></h3>
+<p><small><?php echo _AT('window_auto_close'); ?></small></p>
+
+<br /><br />
+<table border="0" align="center">
+<tr>
+       <td><img src="<?php echo AT_BASE_HREF; ?>images/transfer.gif" height="20" width="90" alt="<?php echo _AT($lang_variable); ?>"></td>
+       <td valign="middle"><iframe src="prog.php?frame=1" width="100" height="25" frameborder="0" scrolling="no" marginwidth="0" marginheight="1">
+</iframe>
+<?php } else { 
+       $tmp_dir = ini_get('upload_tmp_dir') . DIRECTORY_SEPARATOR;
+       if (!$_GET['t']) {
+               $newest_file_name = '';
+               $newest_file_time = 0;
+               // get the name of the temp file.
+               if ($dir = @opendir($tmp_dir)) {
+                       while (($file = readdir($dir)) !== false) {
+                               if ((strlen($file) == 9) && (substr($file, 0, 3) == 'php')) {
+                                       $filedata = stat($tmp_dir . $file);
+                                       if ($filedata['mtime'] > $newest_file_time) {
+                                               $newest_file_time = $filedata['mtime'];
+                                               $newest_file_name = $file;
+                                               $size = $filedata['size'] / 1024;
+                                       }
+                               }
+                       }
+                       closedir($dir);
+               }
+       } else {
+               $filedata = stat($tmp_dir . $_GET['t']);
+               $size = $filedata['size'] / AT_KBYTE_SIZE;
+       }
+       // not sure where these are displayed in the progress popup
+       echo '<small>';
+       if ($size == '') {
+               echo '<em>'._AT('unknown').' </em>  '._AT('kb');
+       } else {
+               echo number_format($size, 2).' '._AT('kb');
+       }
+       echo '</small>';
+} ?></td>
+</tr>
+</table>
+</body>
+</html>
diff --git a/tools/side_menu.php b/tools/side_menu.php
new file mode 100644 (file)
index 0000000..024dc6f
--- /dev/null
@@ -0,0 +1,88 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_COURSE_TOOLS);
+
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: modules.php');
+       exit;
+       
+}
+
+if (isset($_POST['submit'])) {
+
+       $side_menu = '';
+       $_stack_names = array();
+
+       $_stack_names = array_keys($_stacks);
+
+       $_POST['stack'] = array_unique($_POST['stack']);
+       $_POST['stack'] = array_intersect($_POST['stack'], $_stack_names);
+
+       $side_menu = implode('|', $_POST['stack']);
+
+       $sql    = "UPDATE ".TABLE_PREFIX."courses SET side_menu='$side_menu' WHERE course_id=$_SESSION[course_id]";
+       $result = mysql_query($sql, $db);
+       $msg->addFeedback('COURSE_PREFS_SAVED');
+       header('Location: side_menu.php');
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="prefs">
+<div class="input-form" style="width:60%">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('side_menu'); ?></legend>
+       <div class="row">
+               <p><?php echo _AT('side_menu_text'); ?></p>
+       </div>
+
+       <div class="row">
+               <?php
+                       $num_stack = count($_stacks);
+                       $side_menu = explode("|", $system_courses[$_SESSION['course_id']]['side_menu']);                        
+
+                       for ($i=0; $i<$num_stack; $i++) {                               
+                               echo '<select name="stack['.$i.']">';
+                               echo '<option value=""></option>';
+                               foreach ($_stacks as $name=>$info) {
+                                       if (isset($info['title'])) {
+                                               $title = $info['title'];
+                                       } else {
+                                               $title = _AT($info['title_var']);
+                                       }
+                                       echo '<option value="'.$name.'"';
+                                       if (isset($side_menu[$i]) && ($name == $side_menu[$i])) {
+                                               echo ' selected="selected"';
+                                       }
+                                       echo '>'.$title.'</option>';
+                               }
+                               echo '</select>';
+                               echo '<br />'; 
+                       } ?>
+       </div>
+
+       <div class="buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('apply'); ?>" accesskey="s" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/take_test.php b/tools/take_test.php
new file mode 100644 (file)
index 0000000..93459ff
--- /dev/null
@@ -0,0 +1,230 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+require(AT_INCLUDE_PATH.'classes/testQuestions.class.php');
+
+$tid = intval($_REQUEST['tid']);
+
+//make sure max attempts not reached, and still on going
+$sql           = "SELECT *, UNIX_TIMESTAMP(start_date) AS start_date, UNIX_TIMESTAMP(end_date) AS end_date FROM ".TABLE_PREFIX."tests WHERE test_id=".$tid." AND course_id=".$_SESSION['course_id'];
+$result= mysql_query($sql, $db);
+$test_row = mysql_fetch_assoc($result);
+/* check to make sure we can access this test: */
+if (!$test_row['guests'] && ($_SESSION['enroll'] == AT_ENROLL_NO || $_SESSION['enroll'] == AT_ENROLL_ALUMNUS)) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->printInfos('NOT_ENROLLED');
+
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+if (!$test_row['guests'] && !authenticate_test($tid)) {
+       header('Location: '.url_rewrite('tools/my_tests.php', AT_PRETTY_URL_IS_HEADER));
+       exit;
+}
+
+// checks one/all questions per page, and forward user to the correct one
+if ($test_row['display']) {
+       header('Location: '.url_rewrite('tools/take_test_q.php?tid='.$tid, AT_PRETTY_URL_IS_HEADER));
+} 
+
+$out_of = $test_row['out_of'];
+
+$sql           = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."tests_results WHERE status=1 AND test_id=".$tid." AND member_id=".$_SESSION['member_id'];
+$takes_result= mysql_query($sql, $db);
+$takes = mysql_fetch_assoc($takes_result);     
+
+if ( (($test_row['start_date'] > time()) || ($test_row['end_date'] < time())) || 
+   ( ($test_row['num_takes'] != AT_TESTS_TAKE_UNLIMITED) && ($takes['cnt'] >= $test_row['num_takes']) )  ) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->printErrors('MAX_ATTEMPTS');
+       
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+if (isset($_POST['submit'])) {
+       // insert
+       if ($_SESSION['member_id']) {
+               $sql    = "SELECT result_id FROM ".TABLE_PREFIX."tests_results WHERE test_id=$tid AND member_id=$_SESSION[member_id] AND status=0";
+               $result = mysql_query($sql, $db);
+               $row    = mysql_fetch_assoc($result);
+               $result_id = $row['result_id'];
+       } else {
+               $sql    = "INSERT INTO ".TABLE_PREFIX."tests_results VALUES (NULL, $tid, 0, NOW(), '', 0, NOW(), 0)";
+               $result = mysql_query($sql, $db);
+               $result_id = mysql_insert_id($db);
+       }
+
+       $final_score     = 0;
+       $set_final_score = TRUE; // whether or not to save the final score in the results table.
+
+       $sql    = "SELECT TQA.weight, TQA.question_id, TQ.type, TQ.answer_0, TQ.answer_1, TQ.answer_2, TQ.answer_3, TQ.answer_4, TQ.answer_5, TQ.answer_6, TQ.answer_7, TQ.answer_8, TQ.answer_9 FROM ".TABLE_PREFIX."tests_questions_assoc TQA INNER JOIN ".TABLE_PREFIX."tests_questions TQ USING (question_id) WHERE TQA.test_id=$tid ORDER BY TQA.ordering, TQ.question_id";
+       $result = mysql_query($sql, $db);
+       while ($row = mysql_fetch_assoc($result)) {
+               if (isset($_POST['answers'][$row['question_id']])) {
+                       $obj = TestQuestions::getQuestion($row['type']);
+                       $score = $obj->mark($row);
+
+                       if ($_SESSION['member_id']) {
+                               $sql    = "UPDATE ".TABLE_PREFIX."tests_answers SET answer='{$_POST[answers][$row[question_id]]}', score='$score' WHERE result_id=$result_id AND question_id=$row[question_id]";
+                       } else {
+                               $sql    = "INSERT INTO ".TABLE_PREFIX."tests_answers VALUES ($result_id, $row[question_id], 0, '{$_POST[answers][$row[question_id]]}', '$score', '')";
+                       }
+                       mysql_query($sql, $db);
+
+                       $final_score += $score;
+               }
+       }
+
+       // update the final score
+       // update status to complate to fix refresh test issue.
+       $sql    = "UPDATE ".TABLE_PREFIX."tests_results SET final_score=$final_score, date_taken=date_taken, status=1, end_time=NOW() WHERE result_id=$result_id AND member_id=$_SESSION[member_id]";
+       $result = mysql_query($sql, $db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       if (!$_SESSION['enroll'] || $test_row['result_release']==AT_RELEASE_IMMEDIATE) {
+               header('Location: '.url_rewrite('tools/view_results.php?tid='.$tid.SEP.'rid='.$result_id, AT_PRETTY_URL_IS_HEADER));
+               exit;
+       }
+       header('Location: '.url_rewrite('tools/my_tests.php', AT_PRETTY_URL_IS_HEADER));
+       exit;           
+}
+
+if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+       $content_base_href = 'get.php/';
+} else {
+       $course_base_href = 'content/' . $_SESSION['course_id'] . '/';
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+/* Retrieve the content_id of this test */
+$num_questions = $test_row['num_questions'];
+$content_id = $test_row['content_id'];
+$anonymous = $test_row['anonymous'];
+$instructions = $test_row['instructions'];
+$title = $test_row['title'];
+
+$_letters = array(_AT('A'), _AT('B'), _AT('C'), _AT('D'), _AT('E'), _AT('F'), _AT('G'), _AT('H'), _AT('I'), _AT('J'));
+
+// first check if there's an 'in progress' test.
+// this is the only place in the code that makes sure there is only ONE 'in progress' test going on.
+$in_progress = false;
+$sql = "SELECT result_id FROM ".TABLE_PREFIX."tests_results WHERE member_id={$_SESSION['member_id']} AND test_id=$tid AND status=0";
+$result  = mysql_query($sql);
+if ($row = mysql_fetch_assoc($result)) {
+       $result_id = $row['result_id'];
+       $in_progress = true;
+
+       // retrieve the test questions that were saved to `tests_answers`
+
+       $sql    = "SELECT R.*, A.*, Q.* FROM ".TABLE_PREFIX."tests_answers R INNER JOIN ".TABLE_PREFIX."tests_questions_assoc A USING (question_id) INNER JOIN ".TABLE_PREFIX."tests_questions Q USING (question_id) WHERE R.result_id=$result_id AND A.test_id=$tid ORDER BY Q.question_id";
+       
+} else if ($test_row['random']) {
+       /* Retrieve 'num_questions' question_id randomly choosed from those who are related to this test_id*/
+
+       $non_required_questions = array();
+       $required_questions     = array();
+
+       $sql    = "SELECT question_id, required FROM ".TABLE_PREFIX."tests_questions_assoc WHERE test_id=$tid";
+       $result = mysql_query($sql, $db);
+       
+       while ($row = mysql_fetch_assoc($result)) {
+               if ($row['required'] == 1) {
+                       $required_questions[] = $row['question_id'];
+               } else {
+                       $non_required_questions[] = $row['question_id'];
+               }
+       }
+       
+       $num_required = count($required_questions);
+       if ($num_required < max(1, $num_questions)) {
+               shuffle($non_required_questions);
+               $required_questions = array_merge($required_questions, array_slice($non_required_questions, 0, $num_questions - $num_required));
+       }
+
+       $random_id_string = implode(',', $required_questions);
+
+       $sql = "SELECT TQ.*, TQA.* FROM ".TABLE_PREFIX."tests_questions TQ INNER JOIN ".TABLE_PREFIX."tests_questions_assoc TQA USING (question_id) WHERE TQ.course_id=$_SESSION[course_id] AND TQA.test_id=$tid AND TQA.question_id IN ($random_id_string) ORDER BY TQ.question_id";
+} else {
+       $sql    = "SELECT TQ.*, TQA.* FROM ".TABLE_PREFIX."tests_questions TQ INNER JOIN ".TABLE_PREFIX."tests_questions_assoc TQA USING (question_id) WHERE TQ.course_id=$_SESSION[course_id] AND TQA.test_id=$tid ORDER BY TQA.ordering, TQA.question_id";
+}
+
+$result        = mysql_query($sql, $db);
+
+$questions = array();
+while ($row = mysql_fetch_assoc($result)) {
+       $questions[] = $row;
+}
+
+if (!$result || !$questions) {
+       echo '<p>'._AT('no_questions').'</p>';
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+// save $questions with no response, and set status to 'in progress' in test_results <---
+if ($_SESSION['member_id'] && !$in_progress) {
+       $sql    = "INSERT INTO ".TABLE_PREFIX."tests_results VALUES (NULL, $tid, $_SESSION[member_id], NOW(), '', 0, NOW(), 0)";
+       $result = mysql_query($sql, $db);
+       $result_id = mysql_insert_id($db);
+}
+?>
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<input type="hidden" name="tid" value="<?php echo $tid; ?>" />
+<div class="input-form" style="width:80%">
+       <fieldset class="group_form"><legend class="group_form"><?php echo $title ?></legend>
+
+
+       <?php if ($instructions!=''): ?>
+               <div style="background-color: #f3f3f3; padding: 5px 10px; margin: 0px; border-top: 1px solid">
+                       <strong><?php echo _AT('instructions'); ?></strong>
+               </div>
+               <div class="row" style="padding-bottom: 20px"><?php echo $instructions; ?></div>
+       <?php endif; ?>
+
+       <?php if ($anonymous): ?>
+               <div class="row"><em><strong><?php echo _AT('test_anonymous'); ?></strong></em></div>
+       <?php endif; ?>
+
+       <?php
+       foreach ($questions as $row) {
+               if ($_SESSION['member_id'] && !$in_progress) {
+                       $sql    = "INSERT INTO ".TABLE_PREFIX."tests_answers VALUES ($result_id, $row[question_id], $_SESSION[member_id], '', '', '')";
+                       mysql_query($sql, $db);
+               }
+
+               $obj = TestQuestions::getQuestion($row['type']);
+               $obj->display($row);
+       }
+       ?>
+       <div style="background-color: #f3f3f3; padding: 5px 10px; margin: 0px; border-top: 1px solid">
+               <strong><?php echo _AT('done'); ?>!</strong>
+       </div>
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('submit'); ?>" accesskey="s" />
+       </div>
+</div>
+</form>
+<script type="text/javascript">
+//<!--
+function iframeSetHeight(id, height) {
+       document.getElementById("qframe" + id).style.height = (height + 20) + "px";
+}
+//-->
+</script>
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/take_test_q.php b/tools/take_test_q.php
new file mode 100644 (file)
index 0000000..923784e
--- /dev/null
@@ -0,0 +1,249 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+require(AT_INCLUDE_PATH.'classes/testQuestions.class.php');
+
+$tid = intval($_REQUEST['tid']);
+
+//make sure max attempts not reached, and still on going
+$sql           = "SELECT *, UNIX_TIMESTAMP(start_date) AS start_date, UNIX_TIMESTAMP(end_date) AS end_date FROM ".TABLE_PREFIX."tests WHERE test_id=".$tid." AND course_id=".$_SESSION['course_id'];
+$result= mysql_query($sql, $db);
+$test_row = mysql_fetch_assoc($result);
+/* check to make sure we can access this test: */
+if (!$test_row['guests'] && ($_SESSION['enroll'] == AT_ENROLL_NO || $_SESSION['enroll'] == AT_ENROLL_ALUMNUS)) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->printInfos('NOT_ENROLLED');
+
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+if (!$test_row['guests'] && !authenticate_test($tid)) {
+       header('Location: '.url_rewrite('tools/my_tests.php', AT_PRETTY_URL_IS_HEADER));
+       exit;
+}
+
+// checks one/all questions per page, and forward user to the correct one
+if (!$test_row['display']) {
+       header('Location: '.url_rewrite('tools/take_test.php?tid='.$tid, AT_PRETTY_URL_IS_HEADER));
+}
+
+$out_of = $test_row['out_of'];
+if (!$test_row['random']) {
+       $sql    = "SELECT COUNT(*) AS num_questions FROM ".TABLE_PREFIX."tests_questions_assoc WHERE test_id=$tid";
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)) {
+               $test_row['num_questions'] = $row['num_questions'];
+       } // else 0
+}      
+
+$sql           = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."tests_results WHERE status=1 AND test_id=".$tid." AND member_id=".$_SESSION['member_id'];
+$takes_result= mysql_query($sql, $db) or die(mysql_error());
+$takes = mysql_fetch_assoc($takes_result);     
+
+if ( (($test_row['start_date'] > time()) || ($test_row['end_date'] < time())) || 
+   ( ($test_row['num_takes'] != AT_TESTS_TAKE_UNLIMITED) && ($takes['cnt'] >= $test_row['num_takes']) )  ) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->printErrors('MAX_ATTEMPTS');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+if (!isset($_GET['pos'])) {
+       $pos = 0; // first question
+} else {
+       $pos = abs($_GET['pos']);
+}
+
+$max_pos = 0;
+
+// get and check for a valid result_id. if there is none then get all the questions and insert them as in progress.
+// note: for guests the result_id is stored in session, but no need to really know that here.
+$result_id = get_test_result_id($tid, $max_pos);
+
+// set position to allow users to return to a test they have partially completed, and continue from where they left of.
+if ($pos == 0 && $result_id > 0)
+{
+       $sql = "SELECT COUNT(*) pos FROM ".TABLE_PREFIX."tests_answers WHERE result_id = ". $result_id ." AND answer <> ''";
+       $answer_result = mysql_query($sql, $db) or die(mysql_error());
+       $answer = mysql_fetch_assoc($answer_result);
+       
+       $pos = $answer['pos'];
+}
+
+if ($result_id == 0) {
+       // there is no test in progress, yet.
+       // init this test.
+
+       // simple safety op to make sure nothing is being posted (as it shouldn't!)
+       // $_POST = array(); // don't need this because of the else-if
+       // basically, shouldn't be able to post to this page if there isn't a valid result_id first (how can someone post an answer
+       // to a question they haven't viewed? [unless they're trying to 'hack' something])
+
+       $result_id = init_test_result_questions($tid, (bool) $test_row['random'], $test_row['num_questions']);
+
+       if (!$_SESSION['member_id']) {
+               // this is a guest, so we store the result_id in SESSION
+               $_SESSION['test_result_id'] = $result_id;
+       }
+
+       $pos = 0; // force to always start at the first question
+               
+} else if (isset($_POST['next']) || isset($_POST['previous'])) {
+       // if the test isn't time limited, then what happens when only a few questions are answered? the test result
+       // will be inconsistant.
+       // need to keep track of the max(pos) answered, so that we know if a question is being re-answered.
+       // store 'max_pos' in session or db or form?
+
+       // assuming only one question is displayed      
+       $question_id = intval(key($_POST['answers']));
+
+       // get the old score (incase this question is being re-answered)
+       $sql = "SELECT score FROM ".TABLE_PREFIX."tests_answers WHERE result_id=$result_id AND question_id=$question_id";
+       $result = mysql_query($sql, $db);
+       $row = mysql_fetch_assoc($result);
+       $old_score = $row['score'];
+
+       $score = 0;
+
+       $sql = "SELECT TQA.weight, TQA.question_id, TQ.type, TQ.answer_0, TQ.answer_1, TQ.answer_2, TQ.answer_3, TQ.answer_4, TQ.answer_5, TQ.answer_6, TQ.answer_7, TQ.answer_8, TQ.answer_9 FROM ".TABLE_PREFIX."tests_questions_assoc TQA INNER JOIN ".TABLE_PREFIX."tests_questions TQ USING (question_id) WHERE TQA.test_id=$tid AND TQA.question_id=$question_id";
+       $result = mysql_query($sql, $db);
+
+       if ($row = mysql_fetch_assoc($result)) {
+               if (isset($_POST['answers'][$row['question_id']])) {
+                       $obj = TestQuestions::getQuestion($row['type']);
+                       $score = $obj->mark($row);
+
+                       $sql    = "UPDATE ".TABLE_PREFIX."tests_answers SET answer='{$_POST[answers][$row[question_id]]}', score='$score' WHERE result_id=$result_id AND question_id=$row[question_id]";
+                       mysql_query($sql, $db);
+               }
+       }
+
+       $pos++;
+
+       // update the final score
+       // update status to complate to fix refresh test issue.
+       if ($pos > $max_pos) {
+               $sql    = "UPDATE ".TABLE_PREFIX."tests_results SET final_score=final_score + $score, date_taken=date_taken, end_time=NOW(), max_pos=$pos WHERE result_id=$result_id";
+               $result = mysql_query($sql, $db);
+       } else {
+               // this question has already been answered, so we have to re-mark it, which means finding the OLD score for this question and adjusting
+               // $score with the positive or negative difference.
+               // no need to update max_pos b/c we're only updating a previously answered question.
+
+               $score = $old_score - $score;
+
+               $sql    = "UPDATE ".TABLE_PREFIX."tests_results SET final_score=final_score - $score, date_taken=date_taken, end_time=NOW() WHERE result_id=$result_id";
+               $result = mysql_query($sql, $db);
+       }
+
+       if (isset($_POST['previous'])) {
+               $pos-=2;
+               if ($pos < 0) {
+                       $pos = 0;
+               }
+       }
+
+       if ($pos >= $test_row['num_questions']) {
+               // end of the test.
+               $sql    = "UPDATE ".TABLE_PREFIX."tests_results SET status=1, date_taken=date_taken, end_time=NOW() WHERE result_id=$result_id";
+               $result = mysql_query($sql, $db);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               if (!$_SESSION['enroll'] || $test_row['result_release']==AT_RELEASE_IMMEDIATE) {
+                       header('Location: '.url_rewrite('tools/view_results.php?tid='.$tid.SEP.'rid='.$result_id, AT_PRETTY_URL_IS_HEADER));
+                       exit;
+               }
+               header('Location: '.url_rewrite('tools/my_tests.php', AT_PRETTY_URL_IS_HEADER));
+               exit;
+       } // else:
+       
+       header('Location: '.url_rewrite('tools/take_test_q.php?tid='.$tid.SEP.'pos='.$pos, AT_PRETTY_URL_IS_HEADER));
+       exit;
+}
+
+if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+       $content_base_href = 'get.php/';
+} else {
+       $course_base_href = 'content/' . $_SESSION['course_id'] . '/';
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+/* Retrieve the content_id of this test */
+$num_questions = $test_row['num_questions'];
+$content_id = $test_row['content_id'];
+$anonymous = $test_row['anonymous'];
+$instructions = $test_row['instructions'];
+$title = $test_row['title'];
+
+$_letters = array(_AT('A'), _AT('B'), _AT('C'), _AT('D'), _AT('E'), _AT('F'), _AT('G'), _AT('H'), _AT('I'), _AT('J'));
+
+// this is a kludge to get the question number incremented.
+// a diff approach could be to pass the position to the display() method.
+for ($i = 0; $i < $pos; $i++) {
+       TestQuestionCounter(true);
+}
+
+// retrieve the test questions that were saved to `tests_answers`
+if ($test_row['random']) {
+       $sql    = "SELECT R.*, A.*, Q.* FROM ".TABLE_PREFIX."tests_answers R INNER JOIN ".TABLE_PREFIX."tests_questions_assoc A USING (question_id) INNER JOIN ".TABLE_PREFIX."tests_questions Q USING (question_id) WHERE R.result_id=$result_id AND A.test_id=$tid ORDER BY Q.question_id LIMIT $pos, 1";
+} else {
+       $sql    = "SELECT R.*, A.*, Q.* FROM ".TABLE_PREFIX."tests_answers R INNER JOIN ".TABLE_PREFIX."tests_questions_assoc A USING (question_id) INNER JOIN ".TABLE_PREFIX."tests_questions Q USING (question_id) WHERE R.result_id=$result_id AND A.test_id=$tid ORDER BY A.ordering, Q.question_id LIMIT $pos, 1";
+}
+$result        = mysql_query($sql, $db);
+$question_row = mysql_fetch_assoc($result);
+
+if (!$result || !$question_row) {
+       echo '<p>'._AT('no_questions').'</p>';
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+?>
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>?pos=<?php echo $pos; ?>">
+<input type="hidden" name="tid" value="<?php echo $tid; ?>" />
+<div class="input-form" style="width:80%">
+
+       <fieldset class="group_form"><legend class="group_form"><?php echo $title ?> (<?php echo _AT('question').' '. ($pos+1).'/'.$test_row['num_questions']; ?>)</legend>
+
+       <?php
+       // retrieve the answer to re-populate the form (so we can edit our answer)
+       $sql = "SELECT answer FROM ".TABLE_PREFIX."tests_answers WHERE result_id=$result_id AND question_id=$question_row[question_id]";
+       $result = mysql_query($sql, $db);
+       $row = mysql_fetch_assoc($result);
+       
+       $obj = TestQuestions::getQuestion($question_row['type']);
+       $obj->display($question_row, $row['answer']);
+
+       ?>
+       <div class="row buttons">
+                <div style="display:none"><input type="submit" value="<?php echo _AT('next'); ?>" name="next"/></div>
+               <?php if ($pos > 0): ?>
+                       <input type="submit" name="previous" value="<?php echo _AT('previous'); ?>" />
+               <?php endif; ?>
+               <input type="submit" name="next" value="<?php echo _AT('next'); ?>" accesskey="s" />
+       </div>
+</div>
+</form>
+<script type="text/javascript">
+//<!--
+function iframeSetHeight(id, height) {
+       document.getElementById("qframe" + id).style.height = (height + 20) + "px";
+}
+//-->
+</script>
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/test_intro.php b/tools/test_intro.php
new file mode 100644 (file)
index 0000000..2533493
--- /dev/null
@@ -0,0 +1,134 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+// test authentication
+$tid = intval($_GET['tid']);
+
+
+// make sure max attempts not reached, and still on going
+$sql           = "SELECT *, UNIX_TIMESTAMP(start_date) AS start_date2, UNIX_TIMESTAMP(end_date) AS end_date2 FROM ".TABLE_PREFIX."tests WHERE test_id=".$tid." AND course_id=".$_SESSION['course_id'];
+$result = mysql_query($sql, $db);
+$test_row = mysql_fetch_assoc($result);
+/* check to make sure we can access this test: */
+if (!$test_row['guests'] && ($_SESSION['enroll'] == AT_ENROLL_NO || $_SESSION['enroll'] == AT_ENROLL_ALUMNUS)) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->printInfos('NOT_ENROLLED');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+if (!$test_row['guests'] && !authenticate_test($tid)) {
+       header('Location: my_tests.php');
+       exit;
+}
+
+// checks one/all questions per page, and forward user to the correct one
+if (isset($_GET['action']) && $_GET['action']=='cancel') {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.url_rewrite('tools/my_tests.php', AT_PRETTY_URL_IS_HEADER));
+       exit;
+} else if (isset($_GET['action']) && $_GET['action']=='begin') {
+       if ($test_row['display']) {
+               header('Location: '.url_rewrite('tools/take_test_q.php?tid='.$tid, AT_PRETTY_URL_IS_HEADER));
+       } else {
+               header('Location: '.url_rewrite('tools/take_test.php?tid='.$tid, AT_PRETTY_URL_IS_HEADER));
+       }
+       exit;
+}
+
+/* 
+ * If max attempted reached, then stop it.
+ * @3300
+ */
+$sql = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."tests_results WHERE status=1 AND test_id=".$tid." AND member_id=".$_SESSION['member_id'];
+if ( (($test_row['start_date2'] > time()) || ($test_row['end_date2'] < time())) || 
+   ( ($test_row['num_takes'] != AT_TESTS_TAKE_UNLIMITED) && ($takes['cnt'] >= $test_row['num_takes']) )  ) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->printErrors('MAX_ATTEMPTS');
+       
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+// get number of attempts
+$sql    = "SELECT COUNT(test_id) AS cnt FROM ".TABLE_PREFIX."tests_results WHERE status=1 AND test_id=$tid AND member_id={$_SESSION['member_id']}";
+$result = mysql_query($sql, $db);
+if ($row = mysql_fetch_assoc($result)) {
+       $num_takes = $row['cnt'];
+} else {
+       $num_takes = 0;
+}
+
+if (!$test_row['random']) {
+       $sql    = "SELECT COUNT(*) AS num_questions FROM ".TABLE_PREFIX."tests_questions_assoc WHERE test_id=$tid";
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_assoc($result)) {
+               $test_row['num_questions'] = $row['num_questions'];
+       } // else 0
+}      
+?>
+
+<div class="input-form">
+               <fieldset class="group_form"><legend class="group_form"><?php echo $test_row['title']; ?></legend><div class="row">
+
+
+       <div class="row">
+               <dl class="col-list">
+                       <dt><?php echo _AT('test_description'); ?></dt>
+                       <dd><?php echo $test_row['description']; ?></dd>
+
+                       <dt><?php echo _AT('questions'); ?></dt>
+                       <dd><?php echo $test_row['num_questions']; ?></dd>
+
+                       <dt><?php echo _AT('out_of'); ?></dt>
+                       <dd><?php echo $test_row['out_of']; ?></dd>
+       
+                       <dt><?php echo _AT('attempts'); ?></dt>
+                       <dd><?php echo $num_takes; ?> / <?php echo ($test_row['num_takes'] == AT_TESTS_TAKE_UNLIMITED) ? _AT('unlimited') : $test_row['num_takes']; ?></dd>
+                       
+                       <dt><?php echo _AT('start_date'); ?></dt>
+                       <dd><?php echo AT_date( _AT('announcement_date_format'), $test_row['start_date'], AT_DATE_MYSQL_DATETIME); ?></dd>
+
+                       <dt><?php echo _AT('end_date'); ?></dt>
+                       <dd><?php echo AT_date( _AT('announcement_date_format'), $test_row['end_date'], AT_DATE_MYSQL_DATETIME); ?></dd>
+
+                       <dt><?php echo _AT('anonymous'); ?></dt>
+                       <dd><?php echo $test_row['anonymous'] ? _AT('yes') : _AT('no'); ?></dd>
+
+                       <dt><?php echo _AT('display'); ?></dt>
+                       <dd><?php echo $test_row['display'] ? _AT('one_question_per_page') : _AT('all_questions_on_page'); ?></dd>
+               </dl>
+       </div>
+
+       <?php if ($test_row['instructions']): ?>
+       <div class="row">
+               <h3><?php echo _AT('instructions'); ?></h3>
+               <p><?php echo nl2br($test_row['instructions']); ?></p>
+       </div>
+       <?php endif; ?>
+
+       <div>
+               <a href="<?php echo url_rewrite($_SERVER['PHP_SELF'].'?tid='.$tid.SEP.'action=begin'); ?>" class="button" style="padding: 5px;"><?php echo _AT('start_test');?></a>
+               <a href="<?php echo url_rewrite($_SERVER['PHP_SELF'].'?tid='.$tid.SEP.'action=cancel'); ?>" class="button" style="padding: 5px;"><?php echo _AT('cancel');?></a>
+       </div>
+
+       </div>
+       </fieldset>
+</div>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/add_test_questions.php b/tools/tests/add_test_questions.php
new file mode 100644 (file)
index 0000000..bba0332
--- /dev/null
@@ -0,0 +1,39 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'classes/testQuestions.class.php');\r
+\r
+authenticate(AT_PRIV_TESTS);\r
+\r
+if (isset($_GET['submit_create'])) {\r
+       header('Location: create_question_'.$_GET['question_type'].'.php');\r
+       exit;\r
+}\r
+\r
+$_pages['tools/tests/questions.php?tid='.$_GET['tid']]['title_var']    = 'questions';\r
+$_pages['tools/tests/questions.php?tid='.$_GET['tid']]['parent']   = 'tools/tests/index.php';\r
+$_pages['tools/tests/questions.php?tid='.$_GET['tid']]['children'] = array('tools/tests/add_test_questions.php');\r
+\r
+$_pages['tools/tests/add_test_questions.php']['title_var']    = 'add_questions';\r
+$_pages['tools/tests/add_test_questions.php']['parent']   = 'tools/tests/questions.php?tid='.$_GET['tid'];\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+?>\r
+\r
+<?php $tid = intval($_GET['tid']); ?>\r
+\r
+<?php require(AT_INCLUDE_PATH.'html/tests_questions.inc.php'); ?>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/add_test_questions_confirm.php b/tools/tests/add_test_questions_confirm.php
new file mode 100644 (file)
index 0000000..f833be7
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+$page = 'tests';
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+
+$tid = intval($_POST['tid']);
+
+$_pages['tools/tests/questions.php?tid='.$tid]['title_var']    = 'questions';
+$_pages['tools/tests/questions.php?tid='.$tid]['parent']   = 'tools/tests/index.php';
+$_pages['tools/tests/questions.php?tid='.$tid]['children'] = array('tools/tests/add_test_questions.php?tid='.$tid);
+
+$_pages['tools/tests/add_test_questions.php?tid='.$tid]['title_var']  = 'add_questions';
+$_pages['tools/tests/add_test_questions.php?tid='.$tid]['parent'] = 'tools/tests/questions.php?tid='.$tid;
+
+$_pages['tools/tests/add_test_questions_confirm.php']['title_var'] = 'add_questions';
+$_pages['tools/tests/add_test_questions_confirm.php']['parent']    = 'tools/tests/questions.php?tid='.$tid;
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: questions.php?tid='.$tid);
+       exit;
+} else if (isset($_POST['submit_yes'])) {
+       //get order
+       $sql = "SELECT MAX(ordering) AS max_ordering FROM ".TABLE_PREFIX."tests_questions_assoc WHERE test_id=".$tid;
+       $result = mysql_query($sql, $db);
+       $order  = mysql_fetch_assoc($result);
+       $order = $order['max_ordering'];
+
+       $sql = "REPLACE INTO ".TABLE_PREFIX."tests_questions_assoc VALUES ";
+       foreach ($_POST['questions'] as $question) {
+               $order++;
+               $question = intval($question);
+               $sql .= '('.$tid.', '.$question.', 0, '.$order.', 0),';
+       }
+       $sql = substr($sql, 0, -1);
+       $result = mysql_query($sql, $db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: questions.php?tid='.$tid);
+       exit;
+} else if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: add_test_questions.php?tid='.$tid);
+       exit;
+}
+
+if (!is_array($_POST['questions']) || !count($_POST['questions'])) {
+       $msg->addError('NO_QUESTIONS_SELECTED');
+       header('Location: add_test_questions.php?tid='.$tid);
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+foreach ($_POST['questions'] as $id => $cat_array) {
+       foreach ($cat_array as $idx => $q) {
+               $_POST['questions'][$id][$idx] = intval($q);
+       }
+}
+foreach ($_POST['questions'] as $cat_array) {
+       $questions .= addslashes(implode(',',$cat_array)).',';
+}
+
+$questions = substr($questions, 0, -1);
+
+$sql = "SELECT question, question_id FROM ".TABLE_PREFIX."tests_questions WHERE question_id IN ($questions) AND course_id=$_SESSION[course_id] ORDER BY question";
+$result = mysql_query($sql, $db);
+
+$questions = '';
+while ($row = mysql_fetch_assoc($result)) {
+       $questions .= '<li>'.htmlspecialchars($row['question']).'</li>';
+       $questions_array['questions['.$row['question_id'].']'] = $row['question_id'];
+}
+$questions_array['tid'] = $_POST['tid'];
+$msg->addConfirm(array('ADD_TEST_QUESTIONS', $questions), $questions_array);
+
+$msg->printConfirm();
+?>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/create_question_likert.php b/tools/tests/create_question_likert.php
new file mode 100644 (file)
index 0000000..381f1ed
--- /dev/null
@@ -0,0 +1,215 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/likert_presets.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: question_db.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $_POST['required']    = intval($_POST['required']);
+       $_POST['question']    = trim($_POST['question']);
+       $_POST['category_id'] = intval($_POST['category_id']);
+
+       $empty_fields = array();
+       if ($_POST['question'] == ''){
+               $empty_fields[] = _AT('question');
+       }
+       if ($_POST['choice'][0] == '') {
+               $empty_fields[] = _AT('choice').' 1';
+       }
+
+       if ($_POST['choice'][1] == '') {
+               $empty_fields[] = _AT('choice').' 2';
+       }
+
+       if (!empty($empty_fields)) {
+               $msg->addError(array('EMPTY_FIELDS', implode(', ', $empty_fields)));
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['feedback']   = '';
+               $_POST['question']   = $addslashes($_POST['question']);
+
+               for ($i=0; $i<10; $i++) {
+                       $_POST['choice'][$i] = $addslashes(trim($_POST['choice'][$i]));
+                       $_POST['answer'][$i] = intval($_POST['answer'][$i]);
+
+                       if ($_POST['choice'][$i] == '') {
+                               /* an empty option can't be correct */
+                               $_POST['answer'][$i] = 0;
+                       }
+               }
+
+               $sql    = "INSERT INTO ".TABLE_PREFIX."tests_questions VALUES ( 0, 
+                       $_POST[category_id],
+                       $_SESSION[course_id],
+                       4,
+                       '$_POST[feedback]',
+                       '$_POST[question]',
+                       '{$_POST[choice][0]}',
+                       '{$_POST[choice][1]}',
+                       '{$_POST[choice][2]}',
+                       '{$_POST[choice][3]}',
+                       '{$_POST[choice][4]}',
+                       '{$_POST[choice][5]}',
+                       '{$_POST[choice][6]}',
+                       '{$_POST[choice][7]}',
+                       '{$_POST[choice][8]}',
+                       '{$_POST[choice][9]}',
+                       {$_POST[answer][0]},
+                       {$_POST[answer][1]},
+                       {$_POST[answer][2]},
+                       {$_POST[answer][3]},
+                       {$_POST[answer][4]},
+                       {$_POST[answer][5]},
+                       {$_POST[answer][6]},
+                       {$_POST[answer][7]},
+                       {$_POST[answer][8]},
+                       {$_POST[answer][9]},
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       0,
+                       0)";
+               $result = mysql_query($sql, $db);
+               
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: question_db.php');
+               exit;
+       }
+} else if (isset($_POST['preset'])) {
+       // load preset
+       $_POST['preset_num'] = intval($_POST['preset_num']);
+
+       if (isset($_likert_preset[$_POST['preset_num']])) {
+               $_POST['choice'] = $_likert_preset[$_POST['preset_num']];
+       } else if ($_POST['preset_num']) {
+               $sql    = "SELECT * FROM ".TABLE_PREFIX."tests_questions WHERE question_id=$_POST[preset_num] AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $db);
+               if ($row = mysql_fetch_assoc($result)){
+                       for ($i=0; $i<10; $i++) {
+                               $_POST['choice'][$i] = $row['choice_' . $i];
+                       }
+               }
+       }
+
+}
+
+$onload = 'document.form.category_id.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="required" value="1" />
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('preset_scales'); ?></legend>
+
+       <div class="row">
+               <select name="preset_num">
+                       <optgroup label="<?php echo _AT('presets'); ?>">
+               <?php
+                       //presets
+                       foreach ($_likert_preset as $val=>$preset) {
+                               echo '<option value="'.$val.'">'.$preset[0].' - '.$preset[count($preset)-1].'</option>';
+                       }
+                       echo '</optgroup>';
+                       //previously used
+
+                       $sql = "SELECT * FROM ".TABLE_PREFIX."tests_questions WHERE course_id=$_SESSION[course_id] AND type=4";
+                       $result = mysql_query($sql, $db);
+                       if ($row = mysql_fetch_assoc($result)) {
+                               echo '<optgroup label="'. _AT('prev_used').'">';
+                               $used_choices = array();
+                               do {
+                                       $choices = array_slice($row, 9, 10);
+                                       if (in_array($choices, $used_choices)) {
+                                               continue;
+                                       }
+
+                                       $used_choices[] = $choices;
+
+                                       for ($i=0; $i<=10; $i++) {
+                                               if ($row['choice_'.$i] == '') {
+                                                       $i--;
+                                                       break;
+                                               }
+                                       }
+                                       echo '<option value="'.$row['question_id'].'">'.$row['choice_0'].' - '.$row['choice_'.$i].'</option>';
+                               } while ($row = mysql_fetch_assoc($result));
+                               echo '</optgroup>';
+                       }
+               ?>
+               </select>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="preset" value="<?php echo _AT('set_preset'); ?>" class="button" />
+       </div>
+       </fieldset>
+</div>
+
+<br />
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('likert'); ?></legend>
+       <div class="row">
+               <label for="cats"><?php echo _AT('category'); ?></label><br />
+               <select name="category_id" id="cats">
+                       <?php print_question_cats($_POST['category_id']); ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="question"><?php echo _AT('question'); ?></label> 
+               <?php print_VE('question'); ?>
+               <textarea id="question" cols="50" rows="6" name="question" style="width:90%;"><?php 
+               echo htmlspecialchars(stripslashes($_POST['question'])); ?></textarea>
+       </div>
+
+
+<?php for ($i=0; $i<10; $i++) { ?>
+               <div class="row">
+                       <?php if ($i==0 || $i==1) { ?>
+                               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div>
+                       <?php } ?>
+                       <label for="choice_<?php echo $i; ?>">
+                       <?php echo _AT('choice'); ?> <?php echo ($i+1); ?></label><br />
+                       <input type="text" id="choice_<?php echo $i; ?>" size="40" name="choice[<?php echo $i; ?>]" value="<?php echo htmlspecialchars(stripslashes($_POST['choice'][$i])); ?>" />
+               </div>
+<?php } ?>
+
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save'); ?>"   name="submit" accesskey="s" />
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php');  ?>
\ No newline at end of file
diff --git a/tools/tests/create_question_long.php b/tools/tests/create_question_long.php
new file mode 100644 (file)
index 0000000..288d849
--- /dev/null
@@ -0,0 +1,139 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: question_db.php');
+       exit;
+} else if ($_POST['submit']) {
+       $_POST['feedback']    = trim($_POST['feedback']);
+       $_POST['question']    = trim($_POST['question']);
+       $_POST['category_id'] = intval($_POST['category_id']);
+       $_POST['properties']  = intval($_POST['properties']);
+
+       if ($_POST['question'] == ''){
+               $msg->addError(array('EMPTY_FIELDS', _AT('question')));
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['feedback'] = $addslashes($_POST['feedback']);
+               $_POST['question'] = $addslashes($_POST['question']);
+       
+               $sql    = "INSERT INTO ".TABLE_PREFIX."tests_questions VALUES ( NULL,
+                       $_POST[category_id],
+                       $_SESSION[course_id],
+                       3,
+                       '$_POST[feedback]',
+                       '$_POST[question]',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       $_POST[properties],
+                       0)";
+               $result = mysql_query($sql, $db);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: question_db.php');
+               exit;
+       }
+}
+
+$onload = 'document.form.category_id.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if (!isset($_POST['properties'])) {
+       $_POST['properties'] = 1;
+}
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="required" value="1" />
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('test_open'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="cats"><?php echo _AT('category'); ?></label><br />
+               <select name="category_id" id="cats">
+                       <?php print_question_cats($_POST['category_id']); ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <label for="optional_feedback"><?php echo _AT('optional_feedback'); ?></label> 
+               <?php print_VE('optional_feedback'); ?>
+
+               <textarea id="optional_feedback" cols="50" rows="3" name="feedback"><?php 
+               echo htmlspecialchars(stripslashes($_POST['feedback'])); ?></textarea>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="question"><?php echo _AT('question'); ?></label> 
+               <?php print_VE('question'); ?>
+               <textarea id="question" cols="50" rows="6" name="question" style="width:90%;"><?php 
+               echo htmlspecialchars(stripslashes($_POST['question'])); ?></textarea>
+       </div>
+       
+       <div class="row">
+               <?php echo _AT('answer_size'); ?><br />
+               <input type="radio" name="properties" value="1" id="az1" <?php if ($_POST['properties'] == 1) { echo 'checked="checked"'; } ?> /><label for="az1"><?php echo _AT('one_word'); ?></label><br />
+               
+               <input type="radio" name="properties" value="2" id="az2" <?php if ($_POST['properties'] == 2) { echo 'checked="checked"'; } ?> /><label for="az2"><?php echo _AT('one_sentence'); ?></label><br />
+               
+               <input type="radio" name="properties" value="3" id="az3" <?php if ($_POST['properties'] == 3) { echo 'checked="checked"'; } ?> /><label for="az3"><?php echo _AT('short_paragraph'); ?></label><br />
+               
+               <input type="radio" name="properties" value="4" id="az4" <?php if ($_POST['properties'] == 4) { echo 'checked="checked"'; } ?> /><label for="az4"><?php echo _AT('one_page'); ?></label>
+       </div>
+       
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save'); ?>"   name="submit" accesskey="s" />
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/create_question_matching.php b/tools/tests/create_question_matching.php
new file mode 100644 (file)
index 0000000..5a3c35e
--- /dev/null
@@ -0,0 +1,177 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: question_db.php');
+       exit;
+} else if ($_POST['submit']) {
+       $_POST['feedback']    = trim($_POST['feedback']);
+       $_POST['instructions'] = trim($_POST['instructions']);
+       $_POST['category_id'] = intval($_POST['category_id']);
+
+       for ($i = 0 ; $i < 10; $i++) {
+               $_POST['question'][$i]        = $addslashes(trim($_POST['question'][$i]));
+               $_POST['question_answer'][$i] = (int) $_POST['question_answer'][$i];
+               $_POST['answer'][$i]          = $addslashes(trim($_POST['answer'][$i]));
+       }
+
+       if (!$_POST['question'][0] 
+               || !$_POST['question'][1] 
+               || !$_POST['answer'][0] 
+               || !$_POST['answer'][1]) {
+
+               $msg->addError('QUESTION_EMPTY');
+       }
+       
+
+       if (!$msg->containsErrors()) {
+               $_POST['feedback']     = $addslashes($_POST['feedback']);
+               $_POST['instructions'] = $addslashes($_POST['instructions']);
+       
+               $sql    = "INSERT INTO ".TABLE_PREFIX."tests_questions VALUES ( NULL,
+                       $_POST[category_id],
+                       $_SESSION[course_id],
+                       5,
+                       '$_POST[feedback]',
+                       '$_POST[instructions]',
+                       '{$_POST[question][0]}',
+                       '{$_POST[question][1]}',
+                       '{$_POST[question][2]}',
+                       '{$_POST[question][3]}',
+                       '{$_POST[question][4]}',
+                       '{$_POST[question][5]}',
+                       '{$_POST[question][6]}',
+                       '{$_POST[question][7]}',
+                       '{$_POST[question][8]}',
+                       '{$_POST[question][9]}',
+                       {$_POST[question_answer][0]},
+                       {$_POST[question_answer][1]},
+                       {$_POST[question_answer][2]},
+                       {$_POST[question_answer][3]},
+                       {$_POST[question_answer][4]},
+                       {$_POST[question_answer][5]},
+                       {$_POST[question_answer][6]},
+                       {$_POST[question_answer][7]},
+                       {$_POST[question_answer][8]},
+                       {$_POST[question_answer][9]},
+                       '{$_POST[answer][0]}',
+                       '{$_POST[answer][1]}',
+                       '{$_POST[answer][2]}',
+                       '{$_POST[answer][3]}',
+                       '{$_POST[answer][4]}',
+                       '{$_POST[answer][5]}',
+                       '{$_POST[answer][6]}',
+                       '{$_POST[answer][7]}',
+                       '{$_POST[answer][8]}',
+                       '{$_POST[answer][9]}',
+                       0,
+                       0)";
+
+               $result = mysql_query($sql, $db);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: question_db.php');
+               exit;
+       }
+}
+
+$onload = 'document.form.category_id.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+// for matching test questions
+$_letters = array(_AT('A'), _AT('B'), _AT('C'), _AT('D'), _AT('E'), _AT('F'), _AT('G'), _AT('H'), _AT('I'), _AT('J'));
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="required" value="1" />
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('test_matching'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="cats"><?php echo _AT('category'); ?></label><br />
+               <select name="category_id" id="cats">
+                       <?php print_question_cats($_POST['category_id']); ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <label for="optional_feedback"><?php echo _AT('optional_feedback'); ?></label> 
+               <?php print_VE('optional_feedback'); ?>
+
+               <textarea id="optional_feedback" cols="50" rows="3" name="feedback"><?php echo htmlspecialchars(stripslashes($_POST['feedback'])); ?></textarea>
+       </div>
+
+       <div class="row">
+               <label for="instructions"><?php echo _AT('instructions'); ?></label> 
+               <?php print_VE('instructions'); ?>
+               <textarea id="instructions" cols="50" rows="3" name="instructions"><?php 
+               echo htmlspecialchars(stripslashes($_POST['instructions'])); ?></textarea>
+       </div>
+
+       <div class="row">
+               <h2><?php echo _AT('questions');?></h2>
+       </div>
+<?php for ($i=0; $i<10; $i++): ?>
+       <div class="row">
+               <?php if ($i < 2) :?>
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div>
+               <?php endif; ?>
+               <?php echo _AT('question'); ?> <?php echo ($i+1); ?>
+               
+               <?php print_VE('question_' . $i); ?>
+               
+               <br />
+
+               <select name="question_answer[<?php echo $i; ?>]">
+                       <option value="-1">-</option>
+                       <?php foreach ($_letters as $key => $value): ?>
+                               <option value="<?php echo $key; ?>"><?php echo $value; ?></option>
+                       <?php endforeach; ?>
+               </select>
+               
+               <textarea id="question_<?php echo $i; ?>" cols="50" rows="2" name="question[<?php echo $i; ?>]"><?php echo htmlspecialchars(stripslashes($_POST['question'][$i])); ?></textarea> 
+       </div>
+<?php endfor; ?>
+       
+       <div class="row">
+               <h2><?php echo _AT('answers');?></h2>
+       </div>
+       <?php for ($i=0; $i<10; $i++): ?>
+               <div class="row">
+                       <?php if ($i < 2) :?>
+                               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div>
+                       <?php endif; ?>
+                       <?php echo _AT('answer'); ?> <?php echo $_letters[$i]; ?>
+                       <?php print_VE('answer_' . $i); ?>
+                       <br />
+                       <textarea id="answer_<?php echo $i; ?>" cols="50" rows="2" name="answer[<?php echo $i; ?>]"><?php echo htmlspecialchars(stripslashes($_POST['answer'][$i])); ?></textarea>
+               </div>
+       <?php endfor; ?>
+
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save'); ?>"   name="submit" accesskey="s" />
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/create_question_matchingdd.php b/tools/tests/create_question_matchingdd.php
new file mode 100644 (file)
index 0000000..73df113
--- /dev/null
@@ -0,0 +1,178 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id: create_question_matching.php 6706 2007-02-01 16:28:49Z joel $
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: question_db.php');
+       exit;
+} else if ($_POST['submit']) {
+       $_POST['feedback']    = trim($_POST['feedback']);
+       $_POST['instructions'] = trim($_POST['instructions']);
+       $_POST['category_id'] = intval($_POST['category_id']);
+
+       for ($i = 0 ; $i < 10; $i++) {
+               $_POST['question'][$i]        = $addslashes(trim($_POST['question'][$i]));
+               $_POST['question_answer'][$i] = (int) $_POST['question_answer'][$i];
+               $_POST['answer'][$i]          = $addslashes(trim($_POST['answer'][$i]));
+       }
+
+       if (!$_POST['question'][0] 
+               || !$_POST['question'][1] 
+               || !$_POST['answer'][0] 
+               || !$_POST['answer'][1]) {
+
+               $msg->addError('QUESTION_EMPTY');
+       }
+       
+
+       if (!$msg->containsErrors()) {
+               $_POST['feedback']     = $addslashes($_POST['feedback']);
+               $_POST['instructions'] = $addslashes($_POST['instructions']);
+       
+               $sql    = "INSERT INTO ".TABLE_PREFIX."tests_questions VALUES ( NULL,
+                       $_POST[category_id],
+                       $_SESSION[course_id],
+                       8,
+                       '$_POST[feedback]',
+                       '$_POST[instructions]',
+                       '{$_POST[question][0]}',
+                       '{$_POST[question][1]}',
+                       '{$_POST[question][2]}',
+                       '{$_POST[question][3]}',
+                       '{$_POST[question][4]}',
+                       '{$_POST[question][5]}',
+                       '{$_POST[question][6]}',
+                       '{$_POST[question][7]}',
+                       '{$_POST[question][8]}',
+                       '{$_POST[question][9]}',
+                       {$_POST[question_answer][0]},
+                       {$_POST[question_answer][1]},
+                       {$_POST[question_answer][2]},
+                       {$_POST[question_answer][3]},
+                       {$_POST[question_answer][4]},
+                       {$_POST[question_answer][5]},
+                       {$_POST[question_answer][6]},
+                       {$_POST[question_answer][7]},
+                       {$_POST[question_answer][8]},
+                       {$_POST[question_answer][9]},
+                       '{$_POST[answer][0]}',
+                       '{$_POST[answer][1]}',
+                       '{$_POST[answer][2]}',
+                       '{$_POST[answer][3]}',
+                       '{$_POST[answer][4]}',
+                       '{$_POST[answer][5]}',
+                       '{$_POST[answer][6]}',
+                       '{$_POST[answer][7]}',
+                       '{$_POST[answer][8]}',
+                       '{$_POST[answer][9]}',
+                       0,
+                       0)";
+
+               $result = mysql_query($sql, $db);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: question_db.php');
+               exit;
+       }
+}
+
+$onload = 'document.form.category_id.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+// for matching test questions
+$_letters = array(_AT('A'), _AT('B'), _AT('C'), _AT('D'), _AT('E'), _AT('F'), _AT('G'), _AT('H'), _AT('I'), _AT('J'));
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="required" value="1" />
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('test_matchingdd'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="cats"><?php echo _AT('category'); ?></label><br />
+               <select name="category_id" id="cats">
+                       <?php print_question_cats($_POST['category_id']); ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <label for="optional_feedback"><?php echo _AT('optional_feedback'); ?></label> 
+               <?php print_VE('optional_feedback'); ?>
+
+               <textarea id="optional_feedback" cols="50" rows="3" name="feedback"><?php echo htmlspecialchars(stripslashes($_POST['feedback'])); ?></textarea>
+       </div>
+
+       <div class="row">
+               <label for="instructions"><?php echo _AT('instructions'); ?></label> 
+               <?php print_VE('instructions'); ?>
+               <textarea id="instructions" cols="50" rows="3" name="instructions"><?php echo htmlspecialchars(stripslashes($_POST['instructions'])); ?></textarea>
+       </div>
+
+       <div class="row">
+               <h2><?php echo _AT('questions');?></h2>
+       </div>
+<?php for ($i=0; $i<10; $i++): ?>
+       <div class="row">
+               <?php if ($i < 2) :?>
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div>
+               <?php endif; ?>
+               <?php echo _AT('question'); ?> <?php echo ($i+1); ?>
+               
+               <?php print_VE('question_' . $i); ?>
+               
+               <br />
+
+               <select name="question_answer[<?php echo $i; ?>]">
+                       <option value="-1">-</option>
+                       <?php foreach ($_letters as $key => $value): ?>
+                               <option value="<?php echo $key; ?>"><?php echo $value; ?></option>
+                       <?php endforeach; ?>
+               </select>
+               
+               <textarea id="question_<?php echo $i; ?>" cols="50" rows="2" name="question[<?php echo $i; ?>]"><?php 
+               echo htmlspecialchars(stripslashes($_POST['question'][$i])); ?></textarea> 
+       </div>
+<?php endfor; ?>
+       
+       <div class="row">
+               <h2><?php echo _AT('answers');?></h2>
+       </div>
+       <?php for ($i=0; $i<10; $i++): ?>
+               <div class="row">
+                       <?php if ($i < 2) :?>
+                               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div>
+                       <?php endif; ?>
+                       <?php echo _AT('answer'); ?> <?php echo $_letters[$i]; ?>
+                       <?php print_VE('answer_' . $i); ?>
+                       <br />
+                       <textarea id="answer_<?php echo $i; ?>" cols="50" rows="2" name="answer[<?php echo $i; ?>]"><?php 
+                       echo htmlspecialchars(stripslashes($_POST['answer'][$i])); ?></textarea>
+               </div>
+       <?php endfor; ?>
+
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save'); ?>"   name="submit" accesskey="s" />
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/create_question_multi.php b/tools/tests/create_question_multi.php
new file mode 100644 (file)
index 0000000..0294a7c
--- /dev/null
@@ -0,0 +1,150 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+if (isset($_POST['cancel']) || isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: question_db.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $_POST['required'] = intval($_POST['required']);
+       $_POST['feedback'] = trim($_POST['feedback']);
+       $_POST['question'] = trim($_POST['question']);
+       $_POST['category_id'] = intval($_POST['category_id']);
+       $_POST['answer']      = intval($_POST['answer']);
+
+       if ($_POST['question'] == ''){
+               $msg->addError(array('EMPTY_FIELDS', _AT('question')));
+       }
+               
+       if (!$msg->containsErrors()) {
+               for ($i=0; $i<10; $i++) {
+                       $_POST['choice'][$i] = $addslashes(trim($_POST['choice'][$i]));
+               }
+
+               $answers = array_fill(0, 10, 0);
+               $answers[$_POST['answer']] = 1;
+
+               $_POST['feedback']   = $addslashes($_POST['feedback']);
+               $_POST['question']   = $addslashes($_POST['question']);
+
+               $sql    = "INSERT INTO ".TABLE_PREFIX."tests_questions VALUES ( NULL, 
+                               $_POST[category_id],
+                               $_SESSION[course_id],
+                               1,
+                               '$_POST[feedback]',
+                               '$_POST[question]',
+                               '{$_POST[choice][0]}',
+                               '{$_POST[choice][1]}',
+                               '{$_POST[choice][2]}',
+                               '{$_POST[choice][3]}',
+                               '{$_POST[choice][4]}',
+                               '{$_POST[choice][5]}',
+                               '{$_POST[choice][6]}',
+                               '{$_POST[choice][7]}',
+                               '{$_POST[choice][8]}',
+                               '{$_POST[choice][9]}',
+                               {$answers[0]},
+                               {$answers[1]},
+                               {$answers[2]},
+                               {$answers[3]},
+                               {$answers[4]},
+                               {$answers[5]},
+                               {$answers[6]},
+                               {$answers[7]},
+                               {$answers[8]},
+                               {$answers[9]}, 
+                               '',
+                               '',
+                               '',
+                               '',
+                               '',
+                               '',
+                               '',
+                               '',
+                               '',
+                               '',
+                               5,
+                               0)";
+               $result = mysql_query($sql, $db);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: question_db.php');
+               exit;
+       }
+} else {
+       $_POST['answer'] = 0;
+}
+
+$onload = 'document.form.category_id.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$msg->printConfirm();
+?>
+<form action="tools/tests/create_question_multi.php" method="post" name="form">
+<input type="hidden" name="required" value="1" />
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('test_mc'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="cats"><?php echo _AT('category'); ?></label><br />
+               <select name="category_id" id="cats">
+                       <?php print_question_cats($_POST['category_id']); ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <label for="optional_feedback"><?php echo _AT('optional_feedback'); ?></label>
+               <?php print_VE('optional_feedback'); ?> 
+               <textarea id="optional_feedback" cols="50" rows="3" name="feedback"><?php echo htmlspecialchars(stripslashes($_POST['feedback'])); ?></textarea>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="question"><?php echo _AT('question'); ?></label>
+               <?php print_VE('question'); ?>
+               <textarea id="question" cols="50" rows="4" name="question" style="width:90%;"><?php 
+               echo htmlspecialchars(stripslashes($_POST['question'])); ?></textarea>
+       </div>
+
+<?php
+       for ($i=0; $i<10; $i++) {
+?>
+       <div class="row">
+               <?php echo _AT('choice'); ?> <?php echo ($i+1); ?>
+               
+               <?php print_VE('choice_' . $i); ?>
+               
+               <br />
+
+               <small><input type="radio" name="answer" id="answer_<?php echo $i; ?>" value="<?php echo $i; ?>" <?php if($_POST['answer'] == $i) { echo 'checked="checked"';} ?>><label for="answer_<?php echo $i; ?>"><?php echo _AT('correct_answer'); ?></label></small>                    
+               
+               <textarea id="choice_<?php echo $i; ?>" cols="50" rows="2" name="choice[<?php echo $i; ?>]"><?php 
+               echo htmlspecialchars(stripslashes($_POST['choice'][$i])); ?></textarea> 
+       </div>
+       <?php } ?>
+
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save'); ?>" name="submit" accesskey="s" />
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/create_question_multianswer.php b/tools/tests/create_question_multianswer.php
new file mode 100644 (file)
index 0000000..8a7b986
--- /dev/null
@@ -0,0 +1,186 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id: create_question_multi.php 6706 2007-02-01 16:28:49Z joel $
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+if (isset($_POST['cancel']) || isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: question_db.php');
+       exit;
+} else if ($_POST['submit']) {
+       $_POST['required'] = intval($_POST['required']);
+       $_POST['feedback'] = trim($_POST['feedback']);
+       $_POST['question'] = trim($_POST['question']);
+       $_POST['category_id'] = intval($_POST['category_id']);
+
+       if ($_POST['question'] == ''){
+               $msg->addError(array('EMPTY_FIELDS', _AT('question')));
+       }
+               
+       if (!$msg->containsErrors()) {
+               $choice_new = array(); // stores the non-blank choices
+               $answer_new = array(); // stores the associated "answer" for the choices
+               for ($i=0; $i<10; $i++) {
+                       /**
+                        * Db defined it to be 255 length, chop strings off it it's less than that
+                        * @harris
+                        */
+                       $_POST['choice'][$i] = validate_length($_POST['choice'][$i], 255);
+                       $_POST['choice'][$i] = $addslashes(trim($_POST['choice'][$i]));
+                       $_POST['answer'][$i] = intval($_POST['answer'][$i]);
+
+                       if ($_POST['choice'][$i] == '') {
+                               /* an empty option can't be correct */
+                               $_POST['answer'][$i] = 0;
+                       } else {
+                               /* filter out empty choices/ remove gaps */
+                               $choice_new[] = $_POST['choice'][$i];
+                               $answer_new[] = $_POST['answer'][$i];
+
+                               if ($_POST['answer'][$i] != 0)
+                                       $has_answer = TRUE;
+                       }
+               }
+                       
+               if ($has_answer != TRUE) {
+       
+                       $hidden_vars['required']    = htmlspecialchars($_POST['required']);
+                       $hidden_vars['feedback']    = htmlspecialchars($_POST['feedback']);
+                       $hidden_vars['question']    = htmlspecialchars($_POST['question']);
+                       $hidden_vars['category_id'] = htmlspecialchars($_POST['category_id']);
+
+                       for ($i = 0; $i < count($choice_new); $i++) {
+                               $hidden_vars['answer['.$i.']'] = htmlspecialchars($answer_new[$i]);
+                               $hidden_vars['choice['.$i.']'] = htmlspecialchars($choice_new[$i]);
+                       }
+
+                       $msg->addConfirm('NO_ANSWER', $hidden_vars);
+               } else {
+               
+                       //add slahes throughout - does that fix it?
+                       $_POST['answer'] = $answer_new;
+                       $_POST['choice'] = $choice_new;
+                       $_POST['answer'] = array_pad($_POST['answer'], 10, 0);
+                       $_POST['choice'] = array_pad($_POST['choice'], 10, '');
+               
+                       $_POST['feedback'] = $addslashes($_POST['feedback']);
+                       $_POST['question'] = $addslashes($_POST['question']);
+
+                       $sql    = "INSERT INTO ".TABLE_PREFIX."tests_questions VALUES ( NULL, 
+                               $_POST[category_id],
+                               $_SESSION[course_id],
+                               7,
+                               '$_POST[feedback]',
+                               '$_POST[question]',
+                               '{$_POST[choice][0]}',
+                               '{$_POST[choice][1]}',
+                               '{$_POST[choice][2]}',
+                               '{$_POST[choice][3]}',
+                               '{$_POST[choice][4]}',
+                               '{$_POST[choice][5]}',
+                               '{$_POST[choice][6]}',
+                               '{$_POST[choice][7]}',
+                               '{$_POST[choice][8]}',
+                               '{$_POST[choice][9]}',
+                               {$_POST[answer][0]},
+                               {$_POST[answer][1]},
+                               {$_POST[answer][2]},
+                               {$_POST[answer][3]},
+                               {$_POST[answer][4]},
+                               {$_POST[answer][5]},
+                               {$_POST[answer][6]},
+                               {$_POST[answer][7]},
+                               {$_POST[answer][8]},
+                               {$_POST[answer][9]},
+                               '',
+                               '',
+                               '',
+                               '',
+                               '',
+                               '',
+                               '',
+                               '',
+                               '',
+                               '',
+                               0,
+                               0)";
+
+                       $result = mysql_query($sql, $db);
+
+                       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+                       header('Location: question_db.php');
+                       exit;
+               }
+       }
+}
+
+$onload = 'document.form.category_id.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$msg->printConfirm();
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="required" value="1" />
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('test_ma'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="cats"><?php echo _AT('category'); ?></label><br />
+               <select name="category_id" id="cats">
+                       <?php print_question_cats($_POST['category_id']); ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <label for="optional_feedback"><?php echo _AT('optional_feedback'); ?></label>
+               <?php print_VE('optional_feedback'); ?> 
+               <textarea id="optional_feedback" cols="50" rows="3" name="feedback"><?php echo htmlspecialchars(stripslashes($_POST['feedback'])); ?></textarea>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="question"><?php echo _AT('question'); ?></label>
+               <?php print_VE('question'); ?>
+               <textarea id="question" cols="50" rows="4" name="question" style="width:90%;"><?php echo htmlspecialchars(stripslashes($_POST['question'])); ?></textarea>
+       </div>
+
+<?php
+       for ($i=0; $i<10; $i++) {
+?>
+       <div class="row">
+               <?php echo _AT('choice'); ?> <?php echo ($i+1); ?>
+               
+               <?php print_VE('choice_' . $i); ?>
+               
+               <br />
+
+               <small><input type="checkbox" name="answer[<?php echo $i; ?>]" id="answer_<?php echo $i; ?>" value="1" <?php if($_POST['answer'][$i]) { echo 'checked="checked"';} ?>><label for="answer_<?php echo $i; ?>"><?php echo _AT('correct_answer'); ?></label></small>                        
+               
+               <textarea id="choice_<?php echo $i; ?>" cols="50" rows="2" name="choice[<?php echo $i; ?>]"><?php 
+               echo htmlspecialchars(stripslashes($_POST['choice'][$i])); ?></textarea> 
+       </div>
+       <?php } ?>
+
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save'); ?>" name="submit" accesskey="s" />
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/create_question_multichoice.php b/tools/tests/create_question_multichoice.php
new file mode 100644 (file)
index 0000000..9d24a9c
--- /dev/null
@@ -0,0 +1 @@
+<?php require('create_question_multi.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/create_question_ordering.php b/tools/tests/create_question_ordering.php
new file mode 100644 (file)
index 0000000..45e6a78
--- /dev/null
@@ -0,0 +1,169 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: question_db.php');
+       exit;
+} else if ($_POST['submit']) {
+       $missing_fields = array();
+
+       $_POST['feedback']    = trim($_POST['feedback']);
+       $_POST['question']    = trim($_POST['question']);
+       $_POST['category_id'] = intval($_POST['category_id']);
+
+       if ($_POST['question'] == ''){
+               $missing_fields[] = _AT('question');
+       }
+
+       if (trim($_POST['choice'][0]) == '') {
+               $missing_fields[] = _AT('item').' 1';
+       }
+       if (trim($_POST['choice'][1]) == '') {
+               $missing_fields[] = _AT('item').' 2';
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       if (!$msg->containsErrors()) {
+               $choice_new = array(); // stores the non-blank choices
+               $answer_new = array(); // stores the non-blank answers
+               $order = 0; // order count
+               for ($i=0; $i<10; $i++) {
+                       /**
+                        * Db defined it to be 255 length, chop strings off it it's less than that
+                        * @harris
+                        */
+                       $_POST['choice'][$i] = validate_length($_POST['choice'][$i], 255);
+                       $_POST['choice'][$i] = $addslashes(trim($_POST['choice'][$i]));
+
+                       if ($_POST['choice'][$i] != '') {
+                               /* filter out empty choices/ remove gaps */
+                               $choice_new[] = $_POST['choice'][$i];
+                               $answer_new[] = $order++;
+                       }
+               }
+
+               $_POST['choice']   = array_pad($choice_new, 10, '');
+               $answer_new        = array_pad($answer_new, 10, 0);
+               $_POST['feedback'] = $addslashes($_POST['feedback']);
+               $_POST['question'] = $addslashes($_POST['question']);
+       
+               $sql    = "INSERT INTO ".TABLE_PREFIX."tests_questions VALUES ( NULL,
+                       $_POST[category_id],
+                       $_SESSION[course_id],
+                       6,
+                       '$_POST[feedback]',
+                       '$_POST[question]',
+                       '{$_POST[choice][0]}',
+                       '{$_POST[choice][1]}',
+                       '{$_POST[choice][2]}',
+                       '{$_POST[choice][3]}',
+                       '{$_POST[choice][4]}',
+                       '{$_POST[choice][5]}',
+                       '{$_POST[choice][6]}',
+                       '{$_POST[choice][7]}',
+                       '{$_POST[choice][8]}',
+                       '{$_POST[choice][9]}',
+                       $answer_new[0],
+                       $answer_new[1],
+                       $answer_new[2],
+                       $answer_new[3],
+                       $answer_new[4],
+                       $answer_new[5],
+                       $answer_new[6],
+                       $answer_new[7],
+                       $answer_new[8],
+                       $answer_new[9],
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       0,
+                       0)";
+
+               $result = mysql_query($sql, $db);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: question_db.php');
+               exit;
+       }
+}
+
+$onload = 'document.form.category_id.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="required" value="1" />
+<div class="input-form">
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="cats"><?php echo _AT('category'); ?></label><br />
+               <select name="category_id" id="cats">
+                       <?php print_question_cats($_POST['category_id']); ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <label for="optional_feedback"><?php echo _AT('optional_feedback'); ?></label> 
+               <?php print_VE('optional_feedback'); ?>
+
+               <textarea id="optional_feedback" cols="50" rows="3" name="feedback"><?php echo htmlspecialchars(stripslashes($_POST['feedback'])); ?></textarea>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="question"><?php echo _AT('question'); ?></label> 
+               <?php print_VE('question'); ?>
+               <textarea id="question" cols="50" rows="6" name="question" style="width:90%;"><?php 
+               echo htmlspecialchars(stripslashes($_POST['question'])); ?></textarea>
+       </div>
+       
+       <?php for ($i=0; $i<10; $i++): ?>
+               <div class="row">
+                       <?php if ($i < 2): ?>
+                               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div>
+                       <?php endif; ?> <?php echo _AT('item'); ?> <?php echo ($i+1); ?>
+                       
+                       <?php print_VE('choice_' . $i); ?>
+                       
+                       <br />
+       
+                       <textarea id="choice_<?php echo $i; ?>" cols="50" rows="2" name="choice[<?php echo $i; ?>]"><?php echo htmlspecialchars(stripslashes($_POST['choice'][$i])); ?></textarea> 
+               </div>
+       <?php endfor; ?>
+       
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save'); ?>"   name="submit" accesskey="s" />
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       </div>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/create_question_tf.php b/tools/tests/create_question_tf.php
new file mode 100644 (file)
index 0000000..e1829bd
--- /dev/null
@@ -0,0 +1,135 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: question_db.php');
+       exit;
+} else if ($_POST['submit']) {
+       $_POST['required']     = 1; //intval($_POST['required']);
+       $_POST['feedback']     = trim($_POST['feedback']);
+       $_POST['question']     = trim($_POST['question']);
+       $_POST['category_id']  = intval($_POST['category_id']);
+       $_POST['answer']       = intval($_POST['answer']);
+
+       if ($_POST['question'] == ''){
+               $msg->addError(array('EMPTY_FIELDS', _AT('statement')));
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['feedback'] = $addslashes($_POST['feedback']);
+               $_POST['question'] = $addslashes($_POST['question']);
+
+               /*
+               $sql = 'SELECT content_id FROM '.TABLE_PREFIX."tests WHERE test_id=$_POST[tid]";
+               $result = mysql_query($sql, $db);                       
+               $row = mysql_fetch_assoc($result);
+               */
+
+               $sql = "INSERT INTO ".TABLE_PREFIX."tests_questions VALUES ( NULL,
+                       $_POST[category_id],
+                       $_SESSION[course_id],
+                       2,
+                       '$_POST[feedback]',
+                       '$_POST[question]',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       $_POST[answer],
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       '',
+                       5,
+                       0)";
+               $result = mysql_query($sql, $db);
+               
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: question_db.php');
+       }
+}
+
+$onload = 'document.form.category_id.focus();';
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<form action="tools/tests/create_question_tf.php" method="post" name="form">
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('test_tf'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="cats"><?php echo _AT('category'); ?></label><br />
+               <select name="category_id" id="cats">
+                       <?php print_question_cats($_POST['category_id']); ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <label for="optional_feedback"><?php echo _AT('optional_feedback'); ?></label>          
+               <?php print_VE('optional_feedback'); ?>
+               <br />
+       
+               <textarea id="optional_feedback" cols="50" rows="3" name="feedback"><?php echo htmlspecialchars($stripslashes($_POST['feedback'])); ?></textarea>
+       </div>
+       
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="question"><?php echo _AT('statement'); ?></label>
+               <?php print_VE('question'); ?>
+               <br />
+
+               <textarea id="question" cols="50" rows="6" name="question" style="width:90%;"><?php echo htmlspecialchars($stripslashes($_POST['question'])); ?></textarea>
+       </div>
+       
+       <div class="row">
+               <?php echo _AT('answer'); ?><br />
+               <input type="radio" name="answer" value="1" id="answer1" /><label for="answer1"><?php echo _AT('true'); ?></label>, 
+               <input type="radio" name="answer" value="2" id="answer2" checked="checked" /><label for="answer2"><?php echo _AT('false'); ?></label>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save'); ?>"   name="submit" accesskey="s" />
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/create_question_truefalse.php b/tools/tests/create_question_truefalse.php
new file mode 100644 (file)
index 0000000..6b69b01
--- /dev/null
@@ -0,0 +1 @@
+<?php require('create_question_tf.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/create_test.php b/tools/tests/create_test.php
new file mode 100644 (file)
index 0000000..deabb60
--- /dev/null
@@ -0,0 +1,481 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+$page = 'tests';
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+
+$test_type = 'normal';
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $missing_fields        = array();
+       $_POST['title']        = $addslashes(trim($_POST['title']));
+       $_POST['description']  = $addslashes(trim($_POST['description']));
+       $_POST['num_questions'] = intval($_POST['num_questions']);
+       $_POST['num_takes']        = intval($_POST['num_takes']);
+       $_POST['content_id']   = intval($_POST['content_id']);
+       $_POST['passpercent']   = intval($_POST['passpercent']);
+       $_POST['passscore']     = intval($_POST['passscore']);
+       $_POST['passfeedback']  = $addslashes(trim($_POST['passfeedback']));
+       $_POST['failfeedback']  = $addslashes(trim($_POST['failfeedback']));
+       $_POST['num_takes']    = intval($_POST['num_takes']);
+       $_POST['anonymous']    = intval($_POST['anonymous']);
+       $_POST['allow_guests'] = $_POST['allow_guests'] ? 1 : 0;
+       $_POST['instructions'] = $addslashes($_POST['instructions']);
+       $_POST['display']          = intval($_POST['display']);
+
+       // currently these options are ignored for tests:
+       $_POST['format']       = intval($_POST['format']);
+       $_POST['order']        = 1;  //intval($_POST['order']);
+       $_POST['difficulty']   = 0;  //intval($_POST['difficulty']);    /* avman */
+           
+       if ($_POST['title'] == '') {
+               $missing_fields[] = _AT('title');
+       }
+
+       if ($_POST['random'] && !$_POST['num_questions']) {
+               $missing_fields[] = _AT('num_questions_per_test');
+       }
+
+       if ($_POST['pass_score']==1 && !$_POST['passpercent']) {
+               $missing_fields[] = _AT('percentage_score');
+       }
+
+       if ($_POST['pass_score']==2 && !$_POST['passscore']) {
+               $missing_fields[] = _AT('points_score');
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       $day_start      = intval($_POST['day_start']);
+       $month_start= intval($_POST['month_start']);
+       $year_start     = intval($_POST['year_start']);
+       $hour_start     = intval($_POST['hour_start']);
+       $min_start      = intval($_POST['min_start']);
+
+       $day_end        = intval($_POST['day_end']);
+       $month_end      = intval($_POST['month_end']);
+       $year_end       = intval($_POST['year_end']);
+       $hour_end       = intval($_POST['hour_end']);
+       $min_end        = intval($_POST['min_end']);
+
+       if (!checkdate($month_start, $day_start, $year_start)) {
+               $msg->addError('START_DATE_INVALID');
+       }
+
+       if (!checkdate($month_end, $day_end, $year_end)) {
+               $msg->addError('END_DATE_INVALID');
+       }
+
+       if (mktime($hour_end,   $min_end,   0, $month_end,   $day_end,   $year_end) < 
+               mktime($hour_start, $min_start, 0, $month_start, $day_start, $year_start)) {
+                       $msg->addError('END_DATE_INVALID');
+       }
+
+       if (!$msg->containsErrors()) {
+               if (strlen($month_start) == 1){
+                       $month_start = "0$month_start";
+               }
+               if (strlen($day_start) == 1){
+                       $day_start = "0$day_start";
+               }
+               if (strlen($hour_start) == 1){
+                       $hour_start = "0$hour_start";
+               }
+               if (strlen($min_start) == 1){
+                       $min_start = "0$min_start";
+               }
+
+               if (strlen($month_end) == 1){
+                       $month_end = "0$month_end";
+               }
+               if (strlen($day_end) == 1){
+                       $day_end = "0$day_end";
+               }
+               if (strlen($hour_end) == 1){
+                       $hour_end = "0$hour_end";
+               }
+               if (strlen($min_end) == 1){
+                       $min_end = "0$min_end";
+               }
+
+               $start_date = "$year_start-$month_start-$day_start $hour_start:$min_start:00";
+               $end_date       = "$year_end-$month_end-$day_end $hour_end:$min_end:00";
+
+               //If title exceeded database defined length, truncate it.
+               $_POST['title'] = validate_length($_POST['title'], 100);
+
+               $sql = "INSERT INTO ".TABLE_PREFIX."tests " .
+                      "(test_id,
+             course_id,
+             title,
+             description,
+             format,
+             start_date,
+             end_date,
+             randomize_order,
+             num_questions,
+             instructions,
+             content_id,
+             passscore,
+             passpercent,
+             passfeedback,
+             failfeedback,
+             result_release,
+             random,
+             difficulty,
+             num_takes,
+             anonymous,
+             out_of,
+             guests,
+             display)" .
+                      "VALUES 
+                       (NULL, 
+                        $_SESSION[course_id], 
+                        '$_POST[title]', 
+                        '$_POST[description]', 
+                        $_POST[format], 
+                        '$start_date', 
+                        '$end_date', 
+                        $_POST[order], 
+                        $_POST[num_questions], 
+                        '$_POST[instructions]', 
+                        $_POST[content_id], 
+                        $_POST[passscore], 
+                        $_POST[passpercent], 
+                        '$_POST[passfeedback]', 
+                        '$_POST[failfeedback]', 
+                        $_POST[result_release], 
+                        $_POST[random], 
+                        $_POST[difficulty], 
+                        $_POST[num_takes], 
+                        $_POST[anonymous], 
+                        '', 
+                        $_POST[allow_guests], 
+                        $_POST[display])";
+
+               $result = mysql_query($sql, $db);
+               $tid = mysql_insert_id($db);
+               
+               if (isset($_POST['groups']) && $tid) {
+                       $sql = "INSERT INTO ".TABLE_PREFIX."tests_groups VALUES ";
+                       foreach ($_POST['groups'] as $group) {
+                               $group = intval($group);
+                               $sql .= "($tid, $group),";
+                       }
+                       $sql = substr($sql, 0, -1);
+                       $result = mysql_query($sql, $db);
+               }
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: index.php');
+               exit;
+       }
+}
+
+if (isset($_POST['num_questions']) && ($_POST['num_questions'] === 0)) {
+       $_POST['num_questions'] = '';
+}
+
+$onload = 'document.form.title.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$msg->printErrors();
+
+?>
+<script language="javascript" type="text/javascript">
+function disable_texts (name) {
+       if (name == 'both')
+       {
+               document.form['passpercent'].disabled=true;
+               document.form['passscore'].disabled=true;
+               document.form['passpercent'].value=0;
+               document.form['passscore'].value=0;
+       }
+       else if (name == 'percentage')
+       {
+               document.form['passpercent'].disabled=true;
+               document.form['passpercent'].value=0;
+               document.form['passscore'].disabled=false;
+       }
+       else if (name == 'points')
+       {
+               document.form['passpercent'].disabled=false;
+               document.form['passscore'].disabled=true;
+               document.form['passscore'].value=0;
+       }
+}
+</script>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="test_type" value="<?php echo $test_type; ?>" />
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('create_test'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php echo _AT('title'); ?></label><br />
+               <input type="text" name="title" id="title" size="30" value="<?php echo $_POST['title']; ?>" />
+       </div>
+
+       <div class="row">
+               <label for="description"><?php echo _AT('test_description'); ?></label><br />
+               <textarea name="description" cols="35" rows="3" id="description"><?php echo htmlspecialchars($_POST['description']); ?></textarea>
+       </div>
+
+       <div class="row">
+               <label for="num_t"><?php echo _AT('num_takes_test'); ?></label><br />
+               <select name="num_takes" id="num_t">
+                       <option value="<?php echo AT_TESTS_TAKE_UNLIMITED; ?>" <?php if ($_POST['num_takes'] == AT_TESTS_TAKE_UNLIMITED) { echo 'selected="selected"'; } ?>><?php echo _AT('unlimited'); ?></option>
+               
+                       <option value="1"<?php if ($_POST['num_takes'] == 1) { echo ' selected="selected"'; } ?>>1</option>
+                       <option value="2"<?php if ($_POST['num_takes'] == 2) { echo ' selected="selected"'; } ?>>2</option>
+                       <option value="3"<?php if ($_POST['num_takes'] == 3) { echo ' selected="selected"'; } ?>>3</option>
+                       <option value="4"<?php if ($_POST['num_takes'] == 4) { echo ' selected="selected"'; } ?>>4</option>
+                       <option value="5"<?php if ($_POST['num_takes'] == 5) { echo ' selected="selected"'; } ?>>5</option>
+                       <option value="6"<?php if ($_POST['num_takes'] == 6) { echo ' selected="selected"'; } ?>>6</option>
+                       <option value="7"<?php if ($_POST['num_takes'] == 7) { echo ' selected="selected"'; } ?>>7</option>
+                       <option value="8"<?php if ($_POST['num_takes'] == 8) { echo ' selected="selected"'; } ?>>8</option>
+                       <option value="9"<?php if ($_POST['num_takes'] == 9) { echo ' selected="selected"'; } ?>>9</option>
+                       <option value="10"<?php if ($_POST['num_takes'] == 10) { echo ' selected="selected"'; } ?>>10</option>
+                       <option value="15"<?php if ($_POST['num_takes'] == 15) { echo ' selected="selected"'; } ?>>15</option>
+                       <option value="20"<?php if ($_POST['num_takes'] >= 20) { echo ' selected="selected"'; } ?>>20</option>
+               </select>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('available_on_my_courses'); ?><br />
+               <?php 
+                       if ($_POST['format'] == 1) {
+                               $y = 'checked="checked"';
+                               $n = '';
+                       } else {
+                               $y = '';
+                               $n = 'checked="checked"';
+                       }
+               ?>
+               <input type="radio" name="format" id="formatN" value="0" <?php echo $n; ?> /><label for="formatN"><?php echo _AT('no'); ?></label> 
+               <input type="radio" name="format" id="formatY" value="1" <?php echo $y; ?> /><label for="formatY"><?php echo _AT('yes'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('anonymous_test'); ?><br />
+               <?php 
+                       if ($_POST['anonymous'] == 1) {
+                               $y = 'checked="checked"';
+                               $n = '';
+                       } else {
+                               $y = '';
+                               $n = 'checked="checked"';
+                       }
+               ?>
+
+               <input type="radio" name="anonymous" id="anonN" value="0" <?php echo $n; ?> /><label for="anonN"><?php echo _AT('no'); ?></label> 
+               <input type="radio" name="anonymous" value="1" id="anonY" <?php echo $y; ?> /><label for="anonY"><?php echo _AT('yes'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('allow_guests'); ?><br />
+               <?php 
+                       if ($_POST['allow_guests'] == 1) {
+                               $y = 'checked="checked"';
+                               $n = '';
+                       } else {
+                               $y = '';
+                               $n = 'checked="checked"';
+                       }
+               ?>
+
+               <input type="radio" name="allow_guests" id="allow_guestsN" value="0" <?php echo $n; ?> /><label for="allow_guestsN"><?php echo _AT('no'); ?></label> 
+               <input type="radio" name="allow_guests" value="1" id="allow_guestsY" <?php echo $y; ?> /><label for="allow_guestsY"><?php echo _AT('yes'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('display'); ?><br />
+               <?php 
+                       if ($_POST['display'] == 1) {
+                               $y = 'checked="checked"';
+                               $n = '';
+                       } else {
+                               $y = '';
+                               $n = 'checked="checked"';
+                       }
+               ?>
+
+               <input type="radio" name="display" id="displayN" value="0" <?php echo $n; ?> /><label for="displayN"><?php echo _AT('all_questions_on_page'); ?></label> 
+               <input type="radio" name="display" id="displayY" value="1" <?php echo $y; ?> /><label for="displayY"><?php echo _AT('one_question_per_page'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('pass_score'); ?><br />
+               <input type="radio" name="pass_score" value="0" id="no" <?php if ($_POST['passpercent'] == 0 && $_POST['passscore'] == 0){echo 'checked="true"';} ?> 
+                onfocus="disable_texts('both');" />
+
+               <label for="no" title="<?php echo _AT('pass_score'). ': '. _AT('no_pass_score');  ?>"><?php echo _AT('no_pass_score'); ?></label><br />
+
+               <input type="radio" name="pass_score" value="1" id="percentage"  <?php if ($_POST['passpercent'] <> 0){echo 'checked="true"';} ?>
+                onfocus="disable_texts('points');" />
+
+               <input type="text" name="passpercent" id="passpercent" size="2" value="<?php echo $_POST['passpercent']; ?>" 
+                <?php if ($_POST['passpercent'] == 0){echo 'disabled="true"';} ?> /> 
+               <label for="percentage" title="<?php echo _AT('pass_score'). ': '. _AT('percentage_score');  ?>"><?php  echo '% ' . _AT('percentage_score'); ?></label><br />
+
+               <input type="radio" name="pass_score" value="2" id="points"  <?php if ($_POST['passscore'] <> 0){echo 'checked="true"';} ?>
+                onfocus="disable_texts('percentage');" />
+
+               <input type="text" name="passscore" id="passscore" size="2" value="<?php echo $_POST['passscore']; ?>" 
+                <?php if ($_POST['passscore'] == 0){echo 'disabled="true"';} ?>/> 
+               <label for="points" title="<?php echo _AT('pass_score'). ': '. _AT('points_score');  ?>"><?php  echo _AT('points_score'); ?></label>
+       </div>
+
+       <div class="row">
+               <label for="passfeedback"><?php echo _AT('pass_feedback'); ?></label><br />
+               <textarea name="passfeedback" cols="35" rows="1" id="passfeedback"><?php echo htmlspecialchars($_POST['passfeedback']); ?></textarea>
+       </div>
+
+       <div class="row">
+               <label for="failfeedback"><?php echo _AT('fail_feedback'); ?></label><br />
+               <textarea name="failfeedback" cols="35" rows="1" id="failfeedback"><?php echo htmlspecialchars($_POST['failfeedback']); ?></textarea>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('result_release'); ?><br />
+               <?php 
+                       if ($_POST['result_release'] == AT_RELEASE_IMMEDIATE) {
+                               $check_marked = $check_never = '';
+                               $check_immediate = 'checked="checked"';
+               
+                       } else if ($_POST['result_release'] == AT_RELEASE_MARKED) {
+                               $check_immediate = $check_never = '';
+                               $check_marked = 'checked="checked"';
+
+                       } else if ($_POST['result_release'] == AT_RELEASE_NEVER) {
+                               $check_immediate = $check_marked = '';
+                               $check_never = 'checked="checked"';
+                       }
+               ?>
+               <input type="radio" name="result_release" id="release1" value="<?php echo AT_RELEASE_IMMEDIATE; ?>" <?php echo $check_immediate; ?> /><label for="release1"><?php echo _AT('release_immediate'); ?></label><br />
+               <input type="radio" name="result_release" id="release2" value="<?php echo AT_RELEASE_MARKED; ?>" <?php echo $check_marked; ?> /><label for="release2"><?php echo _AT('release_marked'); ?></label><br />
+               <input type="radio" name="result_release" id="release3" value="<?php echo AT_RELEASE_NEVER; ?>" <?php echo $check_never; ?>/><label for="release3"><?php echo _AT('release_never'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('randomize_questions'); ?><br />
+               <?php 
+                       if ($_POST['random'] == 1) {
+                               $y = 'checked="checked"';
+                               $n = $disabled = '';
+                       } else {
+                               $y = '';
+                               $n = 'checked="checked"';
+                               $disabled = 'disabled="disabled" ';
+                       }
+               ?>
+               <input type="radio" name="random" id="random" value="0" checked="checked" onfocus="document.form.num_questions.disabled=true;" /><label for="random"><?php echo _AT('no'); ?></label>. <input type="radio" name="random" value="1" id="ry" onfocus="document.form.num_questions.disabled=false;" <?php echo $y; ?> /><label for="ry"><?php echo _AT('yes'); ?></label>, <input type="text" name="num_questions" id="num_questions" size="2" value="<?php echo $_POST['num_questions']; ?>" <?php echo $disabled . $n; ?> /> <label for="num_questions"><?php echo _AT('num_questions_per_test'); ?></label>
+       </div>
+
+
+       <div class="row">
+               <?php echo _AT('start_date');  ?><br />
+               <?php
+                       if (!isset($_POST['submit'])) {
+                               $today_day  = date('d');
+                               $today_mon  = date('m');
+                               $today_year = date('Y');
+                               $today_hour = date('H');
+                               $today_min  = 0;
+                       } else {
+                               $today_day  = intval($day_start);
+                               $today_mon  = intval($month_start);
+                               $today_year = intval($year_start);
+                               $today_hour = intval($hour_start);
+                               $today_min  = intval($min_start);
+                       }
+
+                       $name = '_start';
+                       require(AT_INCLUDE_PATH.'html/release_date.inc.php');
+
+               ?>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('end_date');  ?><br />
+               <?php
+                       if (!isset($_POST['submit'])) {
+                               $today_day  = date('d');
+                               $today_mon  = date('m');
+                               $today_year = date('Y');
+                               $today_hour = date('H');
+                               $today_min  = 0;
+                       } else {
+                               $today_day  = intval($day_end);
+                               $today_mon  = intval($month_end);
+                               $today_year = intval($year_end);
+                               $today_hour = intval($hour_end);
+                               $today_min  = intval($min_end);
+                       }
+                                       
+                       $name = '_end';
+                       require(AT_INCLUDE_PATH.'html/release_date.inc.php');
+               ?>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('limit_to_group'); ?><br />
+               <?php
+                       //show groups
+                       $sql    = "SELECT * FROM ".TABLE_PREFIX."groups_types WHERE course_id=$_SESSION[course_id] ORDER BY title";
+                       $result = mysql_query($sql, $db);
+                       if (mysql_num_rows($result)) {
+                               while ($row = mysql_fetch_assoc($result)) {
+                                       echo '<em>'.$row['title'].'</em><br />';
+
+                                       $sql    = "SELECT * FROM ".TABLE_PREFIX."groups WHERE type_id=$row[type_id] ORDER BY title";
+                                       $g_result = mysql_query($sql, $db);
+                                       while ($grow = mysql_fetch_assoc($g_result)) {
+                                               echo '&nbsp;<label><input type="checkbox" value="'.$grow['group_id'].'" name="groups['.$grow['group_id'].']" '; 
+                                               if (is_array($current_groups) && in_array($grow['group_id'], $current_groups)) {
+                                                       echo 'checked="checked"';
+                                               }
+                                               echo '/>'.$grow['title'].'</label><br />';
+                                       }
+                               }
+                       } else {
+                               echo _AT('none_found');
+                       }
+               ?>
+       </div>
+
+       <div class="row">
+               <label for="inst"><?php echo _AT('instructions'); ?></label><br />
+               <textarea name="instructions" cols="35" rows="3" id="inst"><?php echo htmlspecialchars($_POST['instructions']); ?></textarea>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save'); ?>" name="submit" accesskey="s" />
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/dd.php b/tools/tests/dd.php
new file mode 100644 (file)
index 0000000..f376a95
--- /dev/null
@@ -0,0 +1,210 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+       $content_base_href = 'get.php/';
+} else {
+       $content_base_href = 'content/' . $_SESSION['course_id'] . '/';
+}
+session_write_close();
+$_GET['qid'] = intval($_GET['qid']);
+$sql = "SELECT * FROM ".TABLE_PREFIX."tests_questions WHERE question_id=$_GET[qid]";
+$result = mysql_query($sql, $db);
+$row = mysql_fetch_assoc($result);
+
+$_letters = array(_AT('A'), _AT('B'), _AT('C'), _AT('D'), _AT('E'), _AT('F'), _AT('G'), _AT('H'), _AT('I'), _AT('J'));
+$_colours = array('#FF9900', '#00FF00', '#0000FF', '#F23AA3', '#9999CC', '#990026', '#0099CC', '#22C921', '#007D48', '#00248F');
+
+$num_options = 0;
+for ($i=0; $i < 10; $i++) {
+       if ($row['option_'. $i] != '') {
+               $num_options++;
+       }
+}
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html lang="<?php echo $_SESSION['lang']; ?>">
+<head>
+       <title><?php echo SITE_NAME; ?> : <?php echo AT_print($row['question'], 'tests_questions.question'); ?></title>
+       <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $myLang->getCharacterSet(); ?>" />
+       <meta name="Generator" content="ATutor - Copyright 2007 by http://atutor.ca" />
+       <base href="<?php echo AT_BASE_HREF . $content_base_href; ?>" />
+       <script type="text/javascript" src="<?php echo AT_BASE_HREF; ?>jscripts/jquery.js"></script>
+       <script type="text/javascript" src="<?php echo AT_BASE_HREF; ?>jscripts/interface.js"></script>
+       <script type="text/javascript" src="<?php echo AT_BASE_HREF; ?>jscripts/wz_jsgraphics.js"></script>
+       <link rel="stylesheet" href="<?php echo AT_BASE_HREF; ?>themes/default/styles.css" type="text/css" />
+<style type="text/css">
+* {
+       margin: 0px;
+       padding: 0px;
+}
+body {
+       background-color: #fdfdfd;
+}
+option {
+       padding-right: 5px;
+}
+li {
+       padding: 5px;
+       border: 1px solid #ccc;
+       margin: 8px;
+}
+li.question {
+       width: 180px;
+       overflow: auto;
+}
+li.question:hover {
+       cursor: move;
+}
+li.answer {
+       width: 180px;
+       overflow: auto;
+       padding: 8px;
+       margin: 8px;
+}
+.dropactive {
+       background-color: #fc9;
+}
+.drophover {
+       background-color: #ffc;
+}
+</style>
+</head>
+<body>
+
+<?php $response = explode('|', $_GET['response']); ?>
+
+<?php for ($i=0; $i < 10; $i++): ?>
+       <?php if ($row['choice_'. $i] != ''): ?>
+               <div id="container<?php echo $i; ?>" style="position: absolute; top: 0px; left: 0px; width: 100%"></div>
+       <?php endif; ?>
+<?php endfor; ?>
+
+<form method="get">
+       <ul style="position: absolute; top: 10px; left: 5px" id="q">
+               <?php for ($i=0; $i < 10; $i++): ?>
+                       <?php if ($row['choice_'. $i] != ''): ?>
+                               <li class="question" id="q<?php echo $i; ?>" value="<?php echo $i; ?>">
+                                       <select name="s<?php echo $i; ?>" onchange="selectLine(this.value, '<?php echo $i; ?>');" id="s<?php echo $i; ?>">
+                                               <option value="-1">-</option>
+                                               <?php for ($j=0; $j < $num_options; $j++): ?>
+                                                       <option value="<?php echo $j; ?>" <?php if($response[$i] == $j): ?>selected="selected"<?php endif; ?>><?php echo $_letters[$j]; ?></option>
+                                               <?php endfor; ?>
+                                       </select>
+                               
+                               <?php echo $row['choice_'.$i]; ?></li>
+                       <?php endif; ?>
+               <?php endfor; ?>
+       </ul>
+
+       <ol style="position: absolute; list-style-type: upper-alpha; top: 10px; left: 310px" id="a">
+               <?php for ($i=0; $i < 10; $i++): ?>
+                       <?php if ($row['option_'. $i] != ''): ?>
+                               <li class="answer" id="a<?php echo $i; ?>" value="<?php echo $i; ?>"><?php echo $_letters[$i]; ?>. <?php echo $row['option_'.$i]; ?></li>
+                       <?php endif; ?>
+               <?php endfor; ?>
+       </ol>
+</form>
+<script type="text/javascript">
+// <!--
+if($.browser.msie) {
+       var padding = 8;
+} else {
+       var padding = 15;
+}
+var jg = Array(10);
+<?php for ($i=0; $i < 10; $i++): ?>
+       <?php if ($row['choice_'. $i] != ''): ?>
+               jg[<?php echo $i; ?>] = new jsGraphics("container<?php echo $i; ?>");
+               jg[<?php echo $i; ?>].setStroke(3);
+               jg[<?php echo $i; ?>].setColor("<?php echo $_colours[$i]; ?>");
+       <?php endif; ?>
+<?php endfor; ?>
+
+var container_html = $("#container0").html();
+
+$(document).ready(
+       function() {
+       
+               $('#q>li').Draggable(
+                       {
+                               containment: "document",
+                               zIndex:         1000,
+                               ghosting:       true,
+                               opacity:        1,
+                               revert:     true,
+                               fx: 0 // doesn't update select menu in FF if > 0
+                       }
+               ); // end draggable
+
+               $('#a>li').Droppable(
+                       {
+                               accept : 'question', 
+                               activeclass: 'dropactive', 
+                               hoverclass:     'drophover',
+                               tolerance: "pointer",
+                               ondrop: function (drag)  {
+                                       var lx = drag.offsetLeft + $("#" + drag.id).width() + padding;
+                                       var ly = drag.offsetTop  + $("#" + drag.id).height()/2 + 10;
+                                       var rx = this.offsetLeft + 310;
+                                       var ry = this.offsetTop  + $("#" + this.id).height()/2 + 10;
+
+                                       document.getElementById('s' + drag.value).selectedIndex =  this.value + 1;
+
+                                       window.top.document.getElementById("<?php echo $_GET['qid']; ?>q" + drag.value).value = this.value;
+
+                                       $("#container" + drag.value).html(container_html);
+
+                                       jg[drag.value].drawLine(lx, ly , rx, ry );
+                                       jg[drag.value].paint();
+
+                                       return true;
+                               }
+                       }
+               ); // end droppable
+
+        parent.iframeSetHeight(<?php echo $_GET['qid']; ?>, Math.max($("#q").height(), $("#a").height()));
+               <?php foreach ($response as $id => $value): ?>
+               selectLine(<?php echo $value; ?>, <?php echo $id; ?>);
+               <?php endforeach; ?>
+       }
+)
+
+function selectLine(value, id) {
+       if (value == -1) {
+               window.top.document.getElementById("<?php echo $_GET['qid']; ?>q" + id).value = "-1";
+               $("#container" + id).html(container_html);
+
+               return true;
+       }
+
+       var lx = document.getElementById("q" + id).offsetLeft + $("#q" + id).width() + padding;
+       var ly = document.getElementById("q" + id).offsetTop  + $("#q" + id).height()/2 + 10;
+       var rx = document.getElementById("a" + value).offsetLeft + 310;
+       var ry = document.getElementById("a" + value).offsetTop + $("#a" + value).height()/2 + 10;
+
+       window.top.document.getElementById("<?php echo $_GET['qid']; ?>q" + id).value = value;
+
+       $("#container" + id).html(container_html);
+       jg[id].drawLine(lx, ly , rx, ry );
+       jg[id].paint();
+
+       return true;
+}
+// -->
+</script>
+
+</body>
\ No newline at end of file
diff --git a/tools/tests/delete_question.php b/tools/tests/delete_question.php
new file mode 100644 (file)
index 0000000..9b4d345
--- /dev/null
@@ -0,0 +1,62 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_TESTS);
+
+$tid = intval($_REQUEST['tid']);
+
+if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: question_db.php');
+       exit;
+} else if (isset($_POST['submit_yes'])) {
+       $_POST['qid'] = explode(',', $_POST['qid']);
+
+       foreach ($_POST['qid'] as $id) {
+               $id = intval($id);
+
+               $sql    = "DELETE FROM ".TABLE_PREFIX."tests_questions WHERE question_id=$id AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $db) or die(mysql_error());
+
+               if (mysql_affected_rows($db) == 1) {
+                       $sql    = "DELETE FROM ".TABLE_PREFIX."tests_questions_assoc WHERE question_id=$id";
+                       $result = mysql_query($sql, $db) or die(mysql_error());
+               }
+       }
+
+       $msg->addFeedback('QUESTION_DELETED');
+       header('Location: question_db.php');
+       exit;
+} /* else: */
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$these_questions= split(",", $_REQUEST['qid']);
+
+foreach($these_questions as $this_question){
+       $sql = "SELECT question FROM ".TABLE_PREFIX."tests_questions WHERE question_id = '$this_question' ";
+       $result = mysql_query($sql, $db);
+       $row = mysql_fetch_assoc($result);
+       $confirm .= "<li>".$row['question']."</li>";
+}
+
+$confirm = array('DELETE', $confirm);
+$hidden_vars['qid'] = $_REQUEST['qid'];
+
+$msg->addConfirm($confirm, $hidden_vars);
+$msg->printConfirm();
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/tools/tests/delete_result.php b/tools/tests/delete_result.php
new file mode 100644 (file)
index 0000000..0feeb7a
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+
+$tid = intval($_REQUEST['tid']);
+$rid = intval($_REQUEST['rid']);
+
+if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'tools/tests/results.php?tid='.$tid);
+       exit;
+
+} else if (isset($_POST['submit_yes'])) {
+               
+       $sql    = "DELETE FROM ".TABLE_PREFIX."tests_answers WHERE result_id=$rid";
+       $result = mysql_query($sql, $db);
+
+       $sql    = "DELETE FROM ".TABLE_PREFIX."tests_results WHERE result_id=$rid";
+       $result = mysql_query($sql, $db);
+               
+       $msg->addFeedback('RESULT_DELETED');
+       header('Location: '.AT_BASE_HREF.'tools/tests/results.php?tid='.$tid);
+       exit;
+} 
+
+$_pages['tools/tests/delete_result.php']['title_var']  = 'delete_results';
+$_pages['tools/tests/delete_result.php']['parent'] = 'tools/tests/results.php?tid='.$tid;
+
+$_pages['tools/tests/results.php?tid='.$tid]['title_var'] = 'submissions';
+$_pages['tools/tests/results.php?tid='.$tid]['parent'] = 'tools/tests/index.php';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+unset($hidden_vars);
+$hidden_vars['tid'] = $tid;
+$hidden_vars['rid'] = $rid;
+$msg->addConfirm('DELETE', $hidden_vars);
+
+$msg->printConfirm();
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/tools/tests/delete_test.php b/tools/tests/delete_test.php
new file mode 100644 (file)
index 0000000..fbb882f
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+$page = 'tests';
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_TESTS);
+
+
+       
+       if (isset($_POST['submit_no'])) {
+               $msg->addFeedback('CANCELLED');
+               header('Location: index.php');
+               exit;
+       } else if (isset($_POST['submit_yes'])) {
+               
+               $tid = intval($_POST['tid']);
+
+               $sql    = "DELETE FROM ".TABLE_PREFIX."tests WHERE test_id=$tid AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $db);
+
+               if (mysql_affected_rows($db) == 1) {
+                       $sql    = "DELETE FROM ".TABLE_PREFIX."tests_questions_assoc WHERE test_id=$tid";
+                       $result = mysql_query($sql, $db);
+
+                       /* it has to delete the results as well... */
+                       $sql    = "SELECT result_id FROM ".TABLE_PREFIX."tests_results WHERE test_id=$tid";
+                       $result = mysql_query($sql, $db);
+                       if ($row = mysql_fetch_array($result)) {
+                               $result_list = '('.$row['result_id'];
+
+                               while ($row = mysql_fetch_array($result)) {
+                                       $result_list .= ','.$row['result_id'];
+                               }
+                               $result_list .= ')';
+                       }
+
+                       if ($result_list != '') {
+                               $sql    = "DELETE FROM ".TABLE_PREFIX."tests_answers WHERE result_id IN $result_list";
+                               $result = mysql_query($sql, $db);
+
+
+                               $sql    = "DELETE FROM ".TABLE_PREFIX."tests_results WHERE test_id=$tid";
+                               $result = mysql_query($sql, $db);
+                       }
+               }
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: '.AT_BASE_HREF.'tools/tests/index.php');
+               exit;
+
+       } /* else: */
+
+       require(AT_INCLUDE_PATH.'header.inc.php');
+
+       $_GET['tid'] = intval($_GET['tid']);
+
+       $sql    = "SELECT title FROM ".TABLE_PREFIX."tests WHERE test_id=$_GET[tid] AND course_id=$_SESSION[course_id]";
+       $result = mysql_query($sql, $db);
+       $row    = mysql_fetch_array($result);
+
+       unset($hidden_vars);
+       $hidden_vars['tid'] = $_GET['tid'];
+
+       $msg->addConfirm(array('DELETE_TEST', $row['title']), $hidden_vars);
+       $msg->printConfirm();
+
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/tools/tests/edit_question_likert.php b/tools/tests/edit_question_likert.php
new file mode 100644 (file)
index 0000000..eb75a84
--- /dev/null
@@ -0,0 +1,233 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/likert_presets.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+$qid = intval($_GET['qid']);
+if ($qid == 0){
+       $qid = intval($_POST['qid']);
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       if ($_POST['tid']) {
+               header('Location: questions.php?tid='.$_POST['tid']);                   
+       } else {
+               header('Location: question_db.php');
+       }
+       exit;
+} else if (isset($_POST['submit'])) {
+       $_POST['required']    = intval($_POST['required']);
+       $_POST['question']    = trim($_POST['question']);
+       $_POST['category_id'] = intval($_POST['category_id']);
+       $_POST['alignment']   = intval($_POST['alignment']);
+
+       $empty_fields = array();
+       if ($_POST['question'] == ''){
+               $empty_fields[] = _AT('question');
+       }
+       if ($_POST['choice'][0] == '') {
+               $empty_fields[] = _AT('choice').' 1';
+       }
+
+       if ($_POST['choice'][1] == '') {
+               $empty_fields[] = _AT('choice').' 2';
+       }
+
+       if (!empty($empty_fields)) {
+               $msg->addError(array('EMPTY_FIELDS', implode(', ', $empty_fields)));
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['question'] = $addslashes($_POST['question']);
+
+               for ($i=0; $i<10; $i++) {
+                       $_POST['choice'][$i] = $addslashes(trim($_POST['choice'][$i]));
+                       $_POST['answer'][$i] = intval($_POST['answer'][$i]);
+
+                       if ($_POST['choice'][$i] == '') {
+                               /* an empty option can't be correct */
+                               $_POST['answer'][$i] = 0;
+                       }
+               }               
+               $sql    = "UPDATE ".TABLE_PREFIX."tests_questions SET
+                       category_id=$_POST[category_id],
+                       feedback='',
+                       question='$_POST[question]',
+                       choice_0='{$_POST[choice][0]}',
+                       choice_1='{$_POST[choice][1]}',
+                       choice_2='{$_POST[choice][2]}',
+                       choice_3='{$_POST[choice][3]}',
+                       choice_4='{$_POST[choice][4]}',
+                       choice_5='{$_POST[choice][5]}',
+                       choice_6='{$_POST[choice][6]}',
+                       choice_7='{$_POST[choice][7]}',
+                       choice_8='{$_POST[choice][8]}',
+                       choice_9='{$_POST[choice][9]}',
+                       answer_0={$_POST[answer][0]},
+                       answer_1={$_POST[answer][1]},
+                       answer_2={$_POST[answer][2]},
+                       answer_3={$_POST[answer][3]},
+                       answer_4={$_POST[answer][4]},
+                       answer_5={$_POST[answer][5]},
+                       answer_6={$_POST[answer][6]},
+                       answer_7={$_POST[answer][7]},
+                       answer_8={$_POST[answer][8]},
+                       answer_9={$_POST[answer][9]}
+
+                       WHERE question_id=$_POST[qid] AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $db);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               if ($_POST['tid']) {
+                       header('Location: questions.php?tid='.$_POST['tid']);                   
+               } else {
+                       header('Location: question_db.php');
+               }
+               exit;
+       }
+} else if (isset($_POST['preset'])) {
+       // load preset
+       $_POST['preset_num'] = intval($_POST['preset_num']);
+
+       if (isset($_likert_preset[$_POST['preset_num']])) {
+               $_POST['choice'] = $_likert_preset[$_POST['preset_num']];
+       } else if ($_POST['preset_num']) {
+               $sql    = "SELECT * FROM ".TABLE_PREFIX."tests_questions WHERE question_id=$_POST[preset_num] AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $db);
+               if ($row = mysql_fetch_assoc($result)){
+                       for ($i=0; $i<10; $i++) {
+                               $_POST['choice'][$i] = $row['choice_' . $i];
+                       }
+               }
+       }
+
+} else {
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."tests_questions WHERE question_id=$qid AND course_id=$_SESSION[course_id] AND type=4";
+       $result = mysql_query($sql, $db);
+
+       if (!($row = mysql_fetch_array($result))){
+               require(AT_INCLUDE_PATH.'header.inc.php');
+               $msg->printErrors('ITEM_NOT_FOUND');
+               require (AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+       $_POST['required']              = $row['required'];
+       $_POST['question']              = $row['question'];
+       $_POST['category_id']   = $row['category_id'];
+
+       for ($i=0; $i<10; $i++) {
+               $_POST['choice'][$i] = $row['choice_'.$i];
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="qid" value="<?php echo $qid; ?>" />
+<input type="hidden" name="tid" value="<?php echo $_REQUEST['tid']; ?>" />
+<input type="hidden" name="required" value="1" />
+       <fieldset class="group_form" style="width:88%;margin-left:auto;margin-right:auto;"><legend class="group_form"><?php echo _AT('preset_scales'); ?></legend>
+<table cellspacing="1" cellpadding="0" border="0" class="bodyline" summary="" align="center">
+<tr>
+       <th align="left"><?php echo _AT('preset_scales'); ?> </th>
+</tr>
+<tr>
+       <td class="row1" nowrap="nowrap">
+               <select name="preset_num">
+                               <option value="0"></option>
+                       <optgroup label="<?php echo _AT('presets'); ?>"><?php
+                               // presets
+                               foreach ($_likert_preset as $val => $preset) {
+                                       echo '<option value="'.$val.'">'.$preset[0].' - '.$preset[count($preset)-1].'</option>';
+                               }
+                       //previously used
+                       echo '</optgroup>';
+
+                       $sql = "SELECT * FROM ".TABLE_PREFIX."tests_questions WHERE course_id=$_SESSION[course_id] AND type=4";
+                       $result = mysql_query($sql, $db);
+                       if ($row = mysql_fetch_assoc($result)) {
+                               echo '<optgroup label="'. _AT('prev_used').'">';
+                               $used_choices = array();
+                               do {
+                                       $choices = array_slice($row, 9, 10);
+                                       if (in_array($choices, $used_choices)) {
+                                               continue;
+                                       }
+
+                                       $used_choices[] = $choices;
+
+                                       for ($i=0; $i<=10; $i++) {
+                                               if ($row['choice_'.$i] == '') {
+                                                       $i--;
+                                                       break;
+                                               }
+                                       }
+                                       echo '<option value="'.$row['question_id'].'">'.$row['choice_0'].' - '.$row['choice_'.$i].'</option>';
+                               } while ($row = mysql_fetch_assoc($result));
+                               echo '</optgroup>';
+                       }
+               ?>
+               </select> 
+               <input type="submit" name="preset" value="<?php echo _AT('set_preset'); ?>" class="button" />
+       </td>
+</tr>
+</table>
+</fieldset>
+<br />
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('question'); ?></legend>
+       <div class="row">
+               <label for="cats"><?php echo _AT('category'); ?></label><br />
+               <select name="category_id" id="cats">
+                       <?php print_question_cats($_POST['category_id']); ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="question"><?php echo _AT('question'); ?></label> 
+               
+               <?php print_VE('question'); ?>
+               
+               <textarea id="question" cols="50" rows="6" name="question"><?php echo htmlspecialchars(stripslashes($_POST['question'])); ?></textarea>
+       </div>
+
+<?php
+       for ($i=0; $i<10; $i++) { ?>
+               <div class="row">
+                       <?php if ($i==0 || $i==1) { ?>
+                               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div>
+                       <?php } ?>
+
+                       <label for="choice_<?php echo $i; ?>">
+                       <?php echo _AT('choice'); ?> <?php echo ($i+1); ?></label><br />
+                       <input type="text" id="choice_<?php echo $i; ?>" size="40" name="choice[<?php echo $i; ?>]" value="<?php echo htmlspecialchars(stripslashes($_POST['choice'][$i])); ?>" />
+               </div>
+<?php } ?>
+
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save'); ?>"   name="submit" accesskey="s" />
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php');  ?>
\ No newline at end of file
diff --git a/tools/tests/edit_question_long.php b/tools/tests/edit_question_long.php
new file mode 100644 (file)
index 0000000..a72206a
--- /dev/null
@@ -0,0 +1,136 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+$qid = intval($_GET['qid']);
+if ($qid == 0){
+       $qid = intval($_POST['qid']);
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       if ($_POST['tid']) {
+               header('Location: questions.php?tid='.$_POST['tid']);                   
+       } else {
+               header('Location: question_db.php');
+       }
+       exit;
+} else if (isset($_POST['submit'])) {
+       $_POST['feedback']    = trim($_POST['feedback']);
+       $_POST['question']    = trim($_POST['question']);
+       $_POST['category_id'] = intval($_POST['category_id']);
+       $_POST['properties']  = intval($_POST['properties']);
+
+       if ($_POST['question'] == ''){
+               $msg->addError(array('EMPTY_FIELDS', _AT('question')));
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['question'] = $addslashes($_POST['question']);
+
+               for ($i=0; $i<10; $i++) {
+                       $_POST['choice'][$i] = trim($_POST['choice'][$i]);
+                       $_POST['answer'][$i] = intval($_POST['answer'][$i]);
+
+                       if ($_POST['choice'][$i] == '') {
+                               /* an empty option can't be correct */
+                               $_POST['answer'][$i] = 0;
+                       }
+               }
+
+               $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET      category_id=$_POST[category_id],
+                       feedback='$_POST[feedback]',
+                       question='$_POST[question]',
+                       properties=$_POST[properties]
+               WHERE question_id=$_POST[qid] AND course_id=$_SESSION[course_id]";
+
+               $result = mysql_query($sql, $db);
+
+               $msg->addFeedback('QUESTION_UPDATED');
+               if ($_POST['tid']) {
+                       header('Location: questions.php?tid='.$_POST['tid']);                   
+               } else {
+                       header('Location: question_db.php');
+               }
+               exit;
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if (!isset($_POST['submit'])) {
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."tests_questions WHERE question_id=$qid AND course_id=$_SESSION[course_id] AND type=3";
+       $result = mysql_query($sql, $db);
+       if (!($row = mysql_fetch_assoc($result))){
+               $msg->printErrors('ITEM_NOT_FOUND');
+               require (AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+
+       $_POST  = $row;
+}
+
+$msg->printErrors();
+?>
+<form action="tools/tests/edit_question_long.php" method="post" name="form">
+<input type="hidden" name="required" value="1" />
+<input type="hidden" name="tid" value="<?php echo $_REQUEST['tid']; ?>" />
+<input type="hidden" name="qid" value="<?php echo $qid; ?>" />
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('test_open'); ?></legend>
+       <div class="row">
+               <label for="cats"><?php echo _AT('category'); ?></label>
+               <select name="category_id" id="cats">
+                       <?php print_question_cats($_POST['category_id']); ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <label for="optional_feedback"><?php echo _AT('optional_feedback'); ?></label> 
+               <?php print_VE('optional_feedback'); ?>
+
+               <textarea id="optional_feedback" cols="50" rows="3" name="feedback"><?php echo htmlspecialchars(stripslashes($_POST['feedback'])); ?></textarea>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="question"><?php echo _AT('question'); ?></label> 
+               <?php print_VE('question'); ?>
+
+               <textarea id="question" cols="50" rows="6" name="question"><?php 
+               echo htmlspecialchars(stripslashes($_POST['question'])); ?></textarea>
+       </div>
+       
+       <div class="row">
+               <?php echo _AT('answer_size'); ?><br />
+               <input type="radio" name="properties" value="1" id="az1" <?php if ($_POST['properties'] == 1) { echo 'checked="checked"'; } ?> /><label for="az1"><?php echo _AT('one_word'); ?></label><br />
+               <input type="radio" name="properties" value="2" id="az2" <?php if ($_POST['properties'] == 2) { echo 'checked="checked"'; } ?> /><label for="az2"><?php echo _AT('one_sentence'); ?></label><br />
+               <input type="radio" name="properties" value="3" id="az3" <?php if ($_POST['properties'] == 3) { echo 'checked="checked"'; } ?> /><label for="az3"><?php echo _AT('short_paragraph'); ?></label><br />
+               <input type="radio" name="properties" value="4" id="az4" <?php if ($_POST['properties'] == 4) { echo 'checked="checked"'; } ?> /><label for="az4"><?php echo _AT('one_page'); ?></label>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save'); ?>"   name="submit" accesskey="s" />
+               <input type="submit" value="<?php echo _AT('cancel'); ?>"name="cancel" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/edit_question_matching.php b/tools/tests/edit_question_matching.php
new file mode 100644 (file)
index 0000000..c7e4ac0
--- /dev/null
@@ -0,0 +1,213 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/likert_presets.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+// for matching test questions
+$_letters = array(_AT('A'), _AT('B'), _AT('C'), _AT('D'), _AT('E'), _AT('F'), _AT('G'), _AT('H'), _AT('I'), _AT('J'));
+
+
+$qid = intval($_GET['qid']);
+if ($qid == 0){
+       $qid = intval($_POST['qid']);
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       if ($_POST['tid']) {
+               header('Location: questions.php?tid='.$_POST['tid']);                   
+       } else {
+               header('Location: question_db.php');
+       }
+       exit;
+} else if (isset($_POST['submit'])) {
+       $_POST['tid']          = intval($_POST['tid']);
+       $_POST['qid']          = intval($_POST['qid']);
+       $_POST['feedback']     = trim($_POST['feedback']);
+       $_POST['instructions'] = trim($_POST['instructions']);
+       $_POST['category_id']  = intval($_POST['category_id']);
+
+       for ($i = 0 ; $i < 10; $i++) {
+               $_POST['question'][$i]        = $addslashes(trim($_POST['question'][$i]));
+               $_POST['question_answer'][$i] = (int) $_POST['question_answer'][$i];
+               $_POST['answer'][$i]          = $addslashes(trim($_POST['answer'][$i]));
+       }
+
+       if (!$_POST['question'][0] 
+               || !$_POST['question'][1] 
+               || !$_POST['answer'][0] 
+               || !$_POST['answer'][1]) {
+
+               $msg->addError('QUESTION_EMPTY');
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['feedback']     = $addslashes($_POST['feedback']);
+               $_POST['instructions'] = $addslashes($_POST['instructions']);
+               
+               $sql    = "UPDATE ".TABLE_PREFIX."tests_questions SET
+                       category_id=$_POST[category_id],
+                       feedback='$_POST[feedback]',
+                       question='$_POST[instructions]',
+                       choice_0='{$_POST[question][0]}',
+                       choice_1='{$_POST[question][1]}',
+                       choice_2='{$_POST[question][2]}',
+                       choice_3='{$_POST[question][3]}',
+                       choice_4='{$_POST[question][4]}',
+                       choice_5='{$_POST[question][5]}',
+                       choice_6='{$_POST[question][6]}',
+                       choice_7='{$_POST[question][7]}',
+                       choice_8='{$_POST[question][8]}',
+                       choice_9='{$_POST[question][9]}',
+                       answer_0={$_POST[question_answer][0]},
+                       answer_1={$_POST[question_answer][1]},
+                       answer_2={$_POST[question_answer][2]},
+                       answer_3={$_POST[question_answer][3]},
+                       answer_4={$_POST[question_answer][4]},
+                       answer_5={$_POST[question_answer][5]},
+                       answer_6={$_POST[question_answer][6]},
+                       answer_7={$_POST[question_answer][7]},
+                       answer_8={$_POST[question_answer][8]},
+                       answer_9={$_POST[question_answer][9]},
+                       option_0='{$_POST[answer][0]}',
+                       option_1='{$_POST[answer][1]}',
+                       option_2='{$_POST[answer][2]}',
+                       option_3='{$_POST[answer][3]}',
+                       option_4='{$_POST[answer][4]}',
+                       option_5='{$_POST[answer][5]}',
+                       option_6='{$_POST[answer][6]}',
+                       option_7='{$_POST[answer][7]}',
+                       option_8='{$_POST[answer][8]}',
+                       option_9='{$_POST[answer][9]}'
+
+                       WHERE question_id=$_POST[qid] AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $db);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               if ($_POST['tid']) {
+                       header('Location: questions.php?tid='.$_POST['tid']);                   
+               } else {
+                       header('Location: question_db.php');
+               }
+               exit;
+       }
+} else {
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."tests_questions WHERE question_id=$qid AND course_id=$_SESSION[course_id] AND type=5";
+       $result = mysql_query($sql, $db);
+
+       if (!($row = mysql_fetch_assoc($result))){
+               require(AT_INCLUDE_PATH.'header.inc.php');
+               $msg->printErrors('ITEM_NOT_FOUND');
+               require (AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+       $_POST['feedback']              = $row['feedback'];
+       $_POST['instructions']  = $row['question'];
+       $_POST['category_id']   = $row['category_id'];
+
+       for ($i=0; $i<10; $i++) {
+               $_POST['question'][$i]        = $row['choice_'.$i];
+               $_POST['question_answer'][$i] = $row['answer_'.$i];
+               $_POST['answer'][$i]          = $row['option_'.$i];
+       }
+       
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="qid" value="<?php echo $qid; ?>" />
+<input type="hidden" name="tid" value="<?php echo $_REQUEST['tid']; ?>" />
+
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('test_matching'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="cats"><?php echo _AT('category'); ?></label><br />
+               <select name="category_id" id="cats">
+                       <?php print_question_cats($_POST['category_id']); ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <label for="optional_feedback"><?php echo _AT('optional_feedback'); ?></label> 
+               <?php print_VE('optional_feedback'); ?>
+
+               <textarea id="optional_feedback" cols="50" rows="3" name="feedback"><?php 
+               echo htmlspecialchars(stripslashes($_POST['feedback'])); ?></textarea>
+       </div>
+
+       <div class="row">
+               <label for="instructions"><?php echo _AT('instructions'); ?></label> 
+               <?php print_VE('instructions'); ?>
+               <textarea id="instructions" cols="50" rows="3" name="instructions"><?php 
+               echo htmlspecialchars(stripslashes($_POST['instructions'])); ?></textarea>
+       </div>
+
+       <div class="row">
+               <h2><?php echo _AT('questions');?></h2>
+       </div>
+<?php for ($i=0; $i<10; $i++): ?>
+       <div class="row">
+               <?php if ($i < 2) :?>
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div>
+               <?php endif; ?>
+               <?php echo _AT('question'); ?> <?php echo ($i+1); ?>
+               
+               <?php print_VE('question_' . $i); ?>
+               
+               <br />
+
+               <select name="question_answer[<?php echo $i; ?>]">
+                       <option value="-1">-</option>
+                       <?php foreach ($_letters as $key => $value): ?>
+                               <option value="<?php echo $key; ?>" <?php if ($key == $_POST['question_answer'][$i]) { echo 'selected="selected"'; }?>><?php echo $value; ?></option>
+                       <?php endforeach; ?>
+               </select>
+               
+               <textarea id="question_<?php echo $i; ?>" cols="50" rows="2" name="question[<?php echo $i; ?>]"><?php 
+               echo htmlspecialchars(stripslashes($_POST['question'][$i])); ?></textarea> 
+       </div>
+<?php endfor; ?>
+       
+       <div class="row">
+               <h2><?php echo _AT('answers');?></h2>
+       </div>
+       <?php for ($i=0; $i<10; $i++): ?>
+               <div class="row">
+                       <?php if ($i < 2) :?>
+                               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div>
+                       <?php endif; ?>
+                       <?php echo _AT('answer'); ?> <?php echo $_letters[$i]; ?>
+                       <?php print_VE('answer' . $i); ?>
+                       <br />
+                       <textarea id="answer_<?php echo $i; ?>" cols="50" rows="2" name="answer[<?php echo $i; ?>]"><?php 
+                       echo htmlspecialchars(stripslashes($_POST['answer'][$i])); ?></textarea>
+               </div>
+       <?php endfor; ?>
+
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save'); ?>"   name="submit" accesskey="s" />
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php');  ?>
\ No newline at end of file
diff --git a/tools/tests/edit_question_matchingdd.php b/tools/tests/edit_question_matchingdd.php
new file mode 100644 (file)
index 0000000..7ceed31
--- /dev/null
@@ -0,0 +1,213 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: edit_question_matching.php 6713 2007-02-01 21:27:03Z joel $
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/likert_presets.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+// for matching test questions
+$_letters = array(_AT('A'), _AT('B'), _AT('C'), _AT('D'), _AT('E'), _AT('F'), _AT('G'), _AT('H'), _AT('I'), _AT('J'));
+
+
+$qid = intval($_GET['qid']);
+if ($qid == 0){
+       $qid = intval($_POST['qid']);
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       if ($_POST['tid']) {
+               header('Location: questions.php?tid='.$_POST['tid']);                   
+       } else {
+               header('Location: question_db.php');
+       }
+       exit;
+} else if (isset($_POST['submit'])) {
+       $_POST['tid']          = intval($_POST['tid']);
+       $_POST['qid']          = intval($_POST['qid']);
+       $_POST['feedback']     = trim($_POST['feedback']);
+       $_POST['instructions'] = trim($_POST['instructions']);
+       $_POST['category_id']  = intval($_POST['category_id']);
+
+       for ($i = 0 ; $i < 10; $i++) {
+               $_POST['question'][$i]        = $addslashes(trim($_POST['question'][$i]));
+               $_POST['question_answer'][$i] = (int) $_POST['question_answer'][$i];
+               $_POST['answer'][$i]          = $addslashes(trim($_POST['answer'][$i]));
+       }
+
+       if (!$_POST['question'][0] 
+               || !$_POST['question'][1] 
+               || !$_POST['answer'][0] 
+               || !$_POST['answer'][1]) {
+
+               $msg->addError('QUESTION_EMPTY');
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['feedback']     = $addslashes($_POST['feedback']);
+               $_POST['instructions'] = $addslashes($_POST['instructions']);
+               
+               $sql    = "UPDATE ".TABLE_PREFIX."tests_questions SET
+                       category_id=$_POST[category_id],
+                       feedback='$_POST[feedback]',
+                       question='$_POST[instructions]',
+                       choice_0='{$_POST[question][0]}',
+                       choice_1='{$_POST[question][1]}',
+                       choice_2='{$_POST[question][2]}',
+                       choice_3='{$_POST[question][3]}',
+                       choice_4='{$_POST[question][4]}',
+                       choice_5='{$_POST[question][5]}',
+                       choice_6='{$_POST[question][6]}',
+                       choice_7='{$_POST[question][7]}',
+                       choice_8='{$_POST[question][8]}',
+                       choice_9='{$_POST[question][9]}',
+                       answer_0={$_POST[question_answer][0]},
+                       answer_1={$_POST[question_answer][1]},
+                       answer_2={$_POST[question_answer][2]},
+                       answer_3={$_POST[question_answer][3]},
+                       answer_4={$_POST[question_answer][4]},
+                       answer_5={$_POST[question_answer][5]},
+                       answer_6={$_POST[question_answer][6]},
+                       answer_7={$_POST[question_answer][7]},
+                       answer_8={$_POST[question_answer][8]},
+                       answer_9={$_POST[question_answer][9]},
+                       option_0='{$_POST[answer][0]}',
+                       option_1='{$_POST[answer][1]}',
+                       option_2='{$_POST[answer][2]}',
+                       option_3='{$_POST[answer][3]}',
+                       option_4='{$_POST[answer][4]}',
+                       option_5='{$_POST[answer][5]}',
+                       option_6='{$_POST[answer][6]}',
+                       option_7='{$_POST[answer][7]}',
+                       option_8='{$_POST[answer][8]}',
+                       option_9='{$_POST[answer][9]}'
+
+                       WHERE question_id=$_POST[qid] AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $db);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               if ($_POST['tid']) {
+                       header('Location: questions.php?tid='.$_POST['tid']);                   
+               } else {
+                       header('Location: question_db.php');
+               }
+               exit;
+       }
+} else {
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."tests_questions WHERE question_id=$qid AND course_id=$_SESSION[course_id] AND type=8";
+       $result = mysql_query($sql, $db);
+
+       if (!($row = mysql_fetch_assoc($result))){
+               require(AT_INCLUDE_PATH.'header.inc.php');
+               $msg->printErrors('ITEM_NOT_FOUND');
+               require (AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+       $_POST['feedback']              = $row['feedback'];
+       $_POST['instructions']  = $row['question'];
+       $_POST['category_id']   = $row['category_id'];
+
+       for ($i=0; $i<10; $i++) {
+               $_POST['question'][$i]        = $row['choice_'.$i];
+               $_POST['question_answer'][$i] = $row['answer_'.$i];
+               $_POST['answer'][$i]          = $row['option_'.$i];
+       }
+       
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="qid" value="<?php echo $qid; ?>" />
+<input type="hidden" name="tid" value="<?php echo $_REQUEST['tid']; ?>" />
+
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('test_matchingdd'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="cats"><?php echo _AT('category'); ?></label><br />
+               <select name="category_id" id="cats">
+                       <?php print_question_cats($_POST['category_id']); ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <label for="optional_feedback"><?php echo _AT('optional_feedback'); ?></label> 
+               <?php print_VE('optional_feedback'); ?>
+
+               <textarea id="optional_feedback" cols="50" rows="3" name="feedback"><?php 
+               echo htmlspecialchars(stripslashes($_POST['feedback'])); ?></textarea>
+       </div>
+
+       <div class="row">
+               <label for="instructions"><?php echo _AT('instructions'); ?></label> 
+               <?php print_VE('instructions'); ?>
+               <textarea id="instructions" cols="50" rows="3" name="instructions"><?php 
+               echo htmlspecialchars(stripslashes($_POST['instructions'])); ?></textarea>
+       </div>
+
+       <div class="row">
+               <h2><?php echo _AT('questions');?></h2>
+       </div>
+<?php for ($i=0; $i<10; $i++): ?>
+       <div class="row">
+               <?php if ($i < 2) :?>
+                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div>
+               <?php endif; ?>
+               <?php echo _AT('question'); ?> <?php echo ($i+1); ?>
+               
+               <?php print_VE('question_' . $i); ?>
+               
+               <br />
+
+               <select name="question_answer[<?php echo $i; ?>]">
+                       <option value="-1">-</option>
+                       <?php foreach ($_letters as $key => $value): ?>
+                               <option value="<?php echo $key; ?>" <?php if ($key == $_POST['question_answer'][$i]) { echo 'selected="selected"'; }?>><?php echo $value; ?></option>
+                       <?php endforeach; ?>
+               </select>
+               
+               <textarea id="question_<?php echo $i; ?>" cols="50" rows="2" name="question[<?php echo $i; ?>]"><?php 
+               echo htmlspecialchars(stripslashes($_POST['question'][$i])); ?></textarea> 
+       </div>
+<?php endfor; ?>
+       
+       <div class="row">
+               <h2><?php echo _AT('answers');?></h2>
+       </div>
+       <?php for ($i=0; $i<10; $i++): ?>
+               <div class="row">
+                       <?php if ($i < 2) :?>
+                               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div>
+                       <?php endif; ?>
+                       <?php echo _AT('answer'); ?> <?php echo $_letters[$i]; ?>
+                       <?php print_VE('answer_' . $i); ?>
+                       <br />
+                       <textarea id="answer_<?php echo $i; ?>" cols="50" rows="2" name="answer[<?php echo $i; ?>]"><?php 
+                       echo htmlspecialchars(stripslashes($_POST['answer'][$i])); ?></textarea>
+               </div>
+       <?php endfor; ?>
+
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save'); ?>"   name="submit" accesskey="s" />
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php');  ?>
\ No newline at end of file
diff --git a/tools/tests/edit_question_multi.php b/tools/tests/edit_question_multi.php
new file mode 100644 (file)
index 0000000..53780dc
--- /dev/null
@@ -0,0 +1,171 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+$qid = intval($_GET['qid']);
+if ($qid == 0){
+       $qid = intval($_POST['qid']);
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       if ($_POST['tid']) {
+               header('Location: questions.php?tid='.$_POST['tid']);                   
+       } else {
+               header('Location: question_db.php');
+       }
+       exit;
+} else if (isset($_POST['submit'])) {
+       $_POST['required'] = intval($_POST['required']);
+       $_POST['feedback'] = trim($_POST['feedback']);
+       $_POST['question'] = trim($_POST['question']);
+       $_POST['tid']      = intval($_POST['tid']);
+       $_POST['qid']      = intval($_POST['qid']);
+       $_POST['weight']   = intval($_POST['weight']);
+       $_POST['answer']   = intval($_POST['answer']);
+
+       if ($_POST['question'] == ''){
+               $msg->addError(array('EMPTY_FIELDS', _AT('question')));
+       }
+
+       if (!$msg->containsErrors()) {
+               $answers    = array_fill(0, 10, 0);
+               $answers[$_POST['answer']] = 1;
+
+               for ($i=0; $i<10; $i++) {
+                       $_POST['choice'][$i] = $addslashes(trim($_POST['choice'][$i]));
+               }
+
+               $_POST['feedback']   = $addslashes($_POST['feedback']);
+               $_POST['question']   = $addslashes($_POST['question']);
+
+               $sql    = "UPDATE ".TABLE_PREFIX."tests_questions SET
+            category_id=$_POST[category_id],
+                   feedback='$_POST[feedback]',
+                       question='$_POST[question]',
+                       choice_0='{$_POST[choice][0]}',
+                       choice_1='{$_POST[choice][1]}',
+                       choice_2='{$_POST[choice][2]}',
+                       choice_3='{$_POST[choice][3]}',
+                       choice_4='{$_POST[choice][4]}',
+                       choice_5='{$_POST[choice][5]}',
+                       choice_6='{$_POST[choice][6]}',
+                       choice_7='{$_POST[choice][7]}',
+                       choice_8='{$_POST[choice][8]}',
+                       choice_9='{$_POST[choice][9]}',
+                       answer_0={$answers[0]},
+                       answer_1={$answers[1]},
+                       answer_2={$answers[2]},
+                       answer_3={$answers[3]},
+                       answer_4={$answers[4]},
+                       answer_5={$answers[5]},
+                       answer_6={$answers[6]},
+                       answer_7={$answers[7]},
+                       answer_8={$answers[8]},
+                       answer_9={$answers[9]}
+
+                       WHERE question_id=$_POST[qid] AND course_id=$_SESSION[course_id]";
+
+               $result = mysql_query($sql, $db);
+
+               $msg->addFeedback('QUESTION_UPDATED');
+               if ($_POST['tid']) {
+                       header('Location: questions.php?tid='.$_POST['tid']);                   
+               } else {
+                       header('Location: question_db.php');
+               }
+               exit;
+       }
+}
+
+if (!isset($_POST['submit'])) {
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."tests_questions WHERE question_id=$qid AND course_id=$_SESSION[course_id] AND type=1";
+       $result = mysql_query($sql, $db);
+
+       if (!($row = mysql_fetch_array($result))){
+               require(AT_INCLUDE_PATH.'header.inc.php');
+               $msg->printErrors('ITEM_NOT_FOUND');
+               require (AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+       $_POST['category_id'] = $row['category_id'];
+       $_POST['feedback']        = $row['feedback'];
+       $_POST['required']        = $row['required'];
+       $_POST['weight']          = $row['weight'];
+       $_POST['question']        = $row['question'];
+
+       for ($i=0; $i<10; $i++) {
+               $_POST['choice'][$i] = $row['choice_'.$i];
+               $_POST['answer'][$i] = $row['answer_'.$i];
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<form action="tools/tests/edit_question_multi.php" method="post" name="form">
+<input type="hidden" name="tid" value="<?php echo $_REQUEST['tid']; ?>" />
+<input type="hidden" name="qid" value="<?php echo $qid; ?>" />
+<input type="hidden" name="required" value="1" />
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('test_mc'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="cats"><?php echo _AT('category'); ?></label>
+               <select name="category_id" id="cats">
+                       <?php print_question_cats($_POST['category_id']); ?>
+               </select>
+       </div>
+       
+       <div class="row">
+               <label for="optional_feedback"><?php echo _AT('optional_feedback'); ?></label> 
+               <?php print_VE('optional_feedback'); ?> 
+
+               <textarea id="optional_feedback" cols="50" rows="3" name="feedback"><?php echo htmlspecialchars(stripslashes($_POST['feedback'])); ?></textarea>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="question"><?php echo _AT('question'); ?></label> 
+               <?php print_VE('question'); ?>          
+               <textarea id="question" cols="50" rows="4" name="question"><?php 
+                       echo htmlspecialchars(stripslashes($_POST['question'])); ?></textarea>
+       </div>
+
+       <?php 
+       for ($i=0; $i<10; $i++) { ?>
+               <div class="row">
+                       <label for="choice_<?php echo $i; ?>"><?php echo _AT('choice'); ?> <?php echo ($i+1); ?></label> 
+                       <?php print_VE('choice_' . $i); ?>
+                       <br />
+                       <small><input type="radio" name="answer" id="answer_<?php echo $i; ?>" value="<?php echo $i; ?>" <?php if($_POST['answer'][$i]) { echo 'checked="checked"';} ?>><label for="answer_<?php echo $i; ?>"><?php echo _AT('correct_answer'); ?></label></small>
+                       
+
+                       <textarea id="choice_<?php echo $i; ?>" cols="50" rows="2" name="choice[<?php echo $i; ?>]" class="formfield"><?php echo htmlspecialchars(stripslashes($_POST['choice'][$i])); ?></textarea>
+               </div>
+       <?php } ?>
+
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save'); ?>"   name="submit" accesskey="s" />
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/edit_question_multianswer.php b/tools/tests/edit_question_multianswer.php
new file mode 100644 (file)
index 0000000..2cff89d
--- /dev/null
@@ -0,0 +1,190 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: edit_question_multi.php 6656 2006-11-09 20:02:42Z heidi $
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+$qid = intval($_GET['qid']);
+if ($qid == 0){
+       $qid = intval($_POST['qid']);
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       if ($_POST['tid']) {
+               header('Location: questions.php?tid='.$_POST['tid']);                   
+       } else {
+               header('Location: question_db.php');
+       }
+       exit;
+} else if (isset($_POST['submit'])) {
+       $_POST['required'] = intval($_POST['required']);
+       $_POST['feedback'] = trim($_POST['feedback']);
+       $_POST['question'] = trim($_POST['question']);
+       $_POST['tid']      = intval($_POST['tid']);
+       $_POST['qid']      = intval($_POST['qid']);
+       $_POST['weight']   = intval($_POST['weight']);
+
+       if ($_POST['question'] == ''){
+               $msg->addError(array('EMPTY_FIELDS', _AT('question')));
+       }
+
+       if (!$msg->containsErrors()) {
+               $choice_new = array(); // stores the non-blank choices
+               $answer_new = array(); // stores the associated "answer" for the choices
+
+               for ($i=0; $i<10; $i++) {
+                       $_POST['choice'][$i] = $addslashes(trim($_POST['choice'][$i]));
+                       /**
+                        * Db defined it to be 255 length, chop strings off it it's less than that
+                        * @harris
+                        */
+                       $_POST['choice'][$i] = validate_length($_POST['choice'][$i], 255);
+                       $_POST['answer'][$i] = intval($_POST['answer'][$i]);
+
+                       if ($_POST['choice'][$i] == '') {
+                               /* an empty option can't be correct */
+                               $_POST['answer'][$i] = 0;
+                       } else {
+                               /* filter out empty choices/ remove gaps */
+                               $choice_new[] = $_POST['choice'][$i];
+                               $answer_new[] = $_POST['answer'][$i];
+                       }
+               }
+
+               $_POST['answer'] = $answer_new;
+               $_POST['choice'] = $choice_new;
+               $_POST['answer'] = array_pad($_POST['answer'], 10, 0);
+               $_POST['choice'] = array_pad($_POST['choice'], 10, '');
+
+               $_POST['feedback']   = $addslashes($_POST['feedback']);
+               $_POST['question']   = $addslashes($_POST['question']);
+
+               $sql    = "UPDATE ".TABLE_PREFIX."tests_questions SET
+            category_id=$_POST[category_id],
+                   feedback='$_POST[feedback]',
+                       question='$_POST[question]',
+                       choice_0='{$_POST[choice][0]}',
+                       choice_1='{$_POST[choice][1]}',
+                       choice_2='{$_POST[choice][2]}',
+                       choice_3='{$_POST[choice][3]}',
+                       choice_4='{$_POST[choice][4]}',
+                       choice_5='{$_POST[choice][5]}',
+                       choice_6='{$_POST[choice][6]}',
+                       choice_7='{$_POST[choice][7]}',
+                       choice_8='{$_POST[choice][8]}',
+                       choice_9='{$_POST[choice][9]}',
+                       answer_0={$_POST[answer][0]},
+                       answer_1={$_POST[answer][1]},
+                       answer_2={$_POST[answer][2]},
+                       answer_3={$_POST[answer][3]},
+                       answer_4={$_POST[answer][4]},
+                       answer_5={$_POST[answer][5]},
+                       answer_6={$_POST[answer][6]},
+                       answer_7={$_POST[answer][7]},
+                       answer_8={$_POST[answer][8]},
+                       answer_9={$_POST[answer][9]}
+
+                       WHERE question_id=$_POST[qid] AND course_id=$_SESSION[course_id]";
+
+               $result = mysql_query($sql, $db);
+
+               $msg->addFeedback('QUESTION_UPDATED');
+               if ($_POST['tid']) {
+                       header('Location: questions.php?tid='.$_POST['tid']);                   
+               } else {
+                       header('Location: question_db.php');
+               }
+               exit;
+       }
+}
+
+if (!isset($_POST['submit'])) {
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."tests_questions WHERE question_id=$qid AND course_id=$_SESSION[course_id] AND type=7";
+       $result = mysql_query($sql, $db);
+
+       if (!($row = mysql_fetch_array($result))){
+               require(AT_INCLUDE_PATH.'header.inc.php');
+               $msg->printErrors('ITEM_NOT_FOUND');
+               require (AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+       $_POST['category_id'] = $row['category_id'];
+       $_POST['feedback']        = $row['feedback'];
+       $_POST['required']        = $row['required'];
+       $_POST['weight']          = $row['weight'];
+       $_POST['question']        = $row['question'];
+
+       for ($i=0; $i<10; $i++) {
+               $_POST['choice'][$i] = $row['choice_'.$i];
+               $_POST['answer'][$i] = $row['answer_'.$i];
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="tid" value="<?php echo $_REQUEST['tid']; ?>" />
+<input type="hidden" name="qid" value="<?php echo $qid; ?>" />
+<input type="hidden" name="required" value="1" />
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('test_ma'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="cats"><?php echo _AT('category'); ?></label>
+               <select name="category_id" id="cats">
+                       <?php print_question_cats($_POST['category_id']); ?>
+               </select>
+       </div>
+       
+       <div class="row">
+               <label for="optional_feedback"><?php echo _AT('optional_feedback'); ?></label> 
+               <?php print_VE('optional_feedback'); ?> 
+
+               <textarea id="optional_feedback" cols="50" rows="3" name="feedback"><?php echo htmlspecialchars(stripslashes($_POST['feedback'])); ?></textarea>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="question"><?php echo _AT('question'); ?></label> 
+               <?php print_VE('question'); ?>          
+               <textarea id="question" cols="50" rows="4" name="question"><?php 
+                       echo htmlspecialchars(stripslashes($_POST['question'])); ?></textarea>
+       </div>
+
+       <?php 
+       for ($i=0; $i<10; $i++) { ?>
+               <div class="row">
+                       <label for="choice_<?php echo $i; ?>"><?php echo _AT('choice'); ?> <?php echo ($i+1); ?></label> 
+                       <?php print_VE('choice_'.$i); ?>                        
+                       <br />
+                       <small><input type="checkbox" name="answer[<?php echo $i; ?>]" id="answer_<?php echo $i; ?>" value="1" <?php if($_POST['answer'][$i]) { echo 'checked="checked"';} ?>><label for="answer_<?php echo $i; ?>"><?php echo _AT('correct_answer'); ?></label></small>
+                       
+
+                       <textarea id="choice_<?php echo $i; ?>" cols="50" rows="2" name="choice[<?php echo $i; ?>]" class="formfield"><?php echo htmlspecialchars(stripslashes($_POST['choice'][$i])); ?></textarea>
+               </div>
+       <?php } ?>
+
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save'); ?>"   name="submit" accesskey="s" />
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/edit_question_multichoice.php b/tools/tests/edit_question_multichoice.php
new file mode 100644 (file)
index 0000000..10e7bf1
--- /dev/null
@@ -0,0 +1 @@
+<?php require('edit_question_multi.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/edit_question_ordering.php b/tools/tests/edit_question_ordering.php
new file mode 100644 (file)
index 0000000..e3c841f
--- /dev/null
@@ -0,0 +1,181 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/likert_presets.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+$qid = intval($_GET['qid']);
+if ($qid == 0){
+       $qid = intval($_POST['qid']);
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       if ($_POST['tid']) {
+               header('Location: questions.php?tid='.$_POST['tid']);                   
+       } else {
+               header('Location: question_db.php');
+       }
+       exit;
+} else if (isset($_POST['submit'])) {
+       $missing_fields = array();
+
+       $_POST['feedback']    = trim($_POST['feedback']);
+       $_POST['question']    = trim($_POST['question']);
+       $_POST['category_id'] = intval($_POST['category_id']);
+
+       if ($_POST['question'] == ''){
+               $missing_fields[] = _AT('question');
+       }
+
+       if (trim($_POST['choice'][0]) == '') {
+               $missing_fields[] = _AT('item').' 1';
+       }
+       if (trim($_POST['choice'][1]) == '') {
+               $missing_fields[] = _AT('item').' 2';
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+       if (!$msg->containsErrors()) {
+               $_POST['question'] = $addslashes($_POST['question']);
+
+               $choice_new = array(); // stores the non-blank choices
+               $answer_new = array(); // stores the non-blank answers
+               $order = 0; // order count
+               for ($i=0; $i<10; $i++) {
+                       /**
+                        * Db defined it to be 255 length, chop strings off it it's less than that
+                        * @harris
+                        */
+                       $_POST['choice'][$i] = validate_length($_POST['choice'][$i], 255);
+                       $_POST['choice'][$i] = $addslashes(trim($_POST['choice'][$i]));
+
+                       if ($_POST['choice'][$i] != '') {
+                               /* filter out empty choices/ remove gaps */
+                               $choice_new[] = $_POST['choice'][$i];
+                               $answer_new[] = $order++;
+                       }
+               }
+               
+               $_POST['choice']   = array_pad($choice_new, 10, '');
+               $answer_new        = array_pad($answer_new, 10, 0);
+
+               $sql    = "UPDATE ".TABLE_PREFIX."tests_questions SET
+                       category_id=$_POST[category_id],
+                       feedback='$_POST[feedback]',
+                       question='$_POST[question]',
+                       choice_0='{$_POST[choice][0]}',
+                       choice_1='{$_POST[choice][1]}',
+                       choice_2='{$_POST[choice][2]}',
+                       choice_3='{$_POST[choice][3]}',
+                       choice_4='{$_POST[choice][4]}',
+                       choice_5='{$_POST[choice][5]}',
+                       choice_6='{$_POST[choice][6]}',
+                       choice_7='{$_POST[choice][7]}',
+                       choice_8='{$_POST[choice][8]}',
+                       choice_9='{$_POST[choice][9]}',
+                       answer_0=$answer_new[0],
+                       answer_0=$answer_new[1],
+                       answer_0=$answer_new[2],
+                       answer_0=$answer_new[3],
+                       answer_0=$answer_new[4],
+                       answer_0=$answer_new[5],
+                       answer_0=$answer_new[6],
+                       answer_0=$answer_new[7],
+                       answer_0=$answer_new[8],
+                       answer_0=$answer_new[9]
+
+                       WHERE question_id=$_POST[qid] AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $db);
+
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               if ($_POST['tid']) {
+                       header('Location: questions.php?tid='.$_POST['tid']);                   
+               } else {
+                       header('Location: question_db.php');
+               }
+               exit;
+       }
+} else {
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."tests_questions WHERE question_id=$qid AND course_id=$_SESSION[course_id] AND type=6";
+       $result = mysql_query($sql, $db);
+
+       if (!($row = mysql_fetch_assoc($result))){
+               require(AT_INCLUDE_PATH.'header.inc.php');
+               $msg->printErrors('ITEM_NOT_FOUND');
+               require (AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+
+       $_POST['required']              = $row['required'];
+       $_POST['question']              = $row['question'];
+       $_POST['category_id']   = $row['category_id'];
+
+       for ($i=0; $i<10; $i++) {
+               $_POST['choice'][$i] = $row['choice_'.$i];
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="qid" value="<?php echo $qid; ?>" />
+<input type="hidden" name="tid" value="<?php echo $_REQUEST['tid']; ?>" />
+
+<div class="input-form">
+       <div class="row">
+               <label for="cats"><?php echo _AT('category'); ?></label><br />
+               <select name="category_id" id="cats">
+                       <?php print_question_cats($_POST['category_id']); ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="question"><?php echo _AT('question'); ?></label> 
+               
+               <?php print_VE('question'); ?>
+               
+               <textarea id="question" cols="50" rows="6" name="question"><?php echo htmlspecialchars(stripslashes($_POST['question'])); ?></textarea>
+       </div>
+
+       <?php for ($i=0; $i<10; $i++): ?>
+               <div class="row">
+                       <?php if ($i < 2): ?>
+                               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div>
+                       <?php endif; ?> <?php echo _AT('item'); ?> <?php echo ($i+1); ?>
+                       
+                       <?php print_VE('choice_' . $i); ?>
+                       
+                       <br />
+       
+                       <textarea id="choice_<?php echo $i; ?>" cols="50" rows="2" name="choice[<?php echo $i; ?>]"><?php 
+                       echo htmlspecialchars(stripslashes($_POST['choice'][$i])); ?></textarea> 
+               </div>
+       <?php endfor; ?>
+
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save'); ?>"   name="submit" accesskey="s" />
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       </div>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php');  ?>
\ No newline at end of file
diff --git a/tools/tests/edit_question_tf.php b/tools/tests/edit_question_tf.php
new file mode 100644 (file)
index 0000000..8f7a913
--- /dev/null
@@ -0,0 +1,150 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+$page = 'tests';
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_TESTS);
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+$qid = intval($_GET['qid']);
+if ($qid == 0){
+       $qid = intval($_POST['qid']);
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       if ($_POST['tid']) {
+               header('Location: questions.php?tid='.$_POST['tid']);                   
+       } else {
+               header('Location: question_db.php');
+       }
+       exit;
+} else if (isset($_POST['submit'])) {
+
+       $_POST['question'] = trim($_POST['question']);
+
+       if ($_POST['question'] == ''){
+               $msg->addError(array('EMPTY_FIELDS', _AT('statement')));
+       }
+
+       if (!$msg->containsErrors()) {
+               $_POST['feedback']    = $addslashes(trim($_POST['feedback']));
+               $_POST['question']    = $addslashes($_POST['question']);
+               $_POST['qid']         = intval($_POST['qid']);
+               $_POST['category_id'] = intval($_POST['category_id']);
+               $_POST['answer']      = intval($_POST['answer']);
+
+               $sql    = "UPDATE ".TABLE_PREFIX."tests_questions SET   category_id=$_POST[category_id],
+                       feedback='$_POST[feedback]',
+                       question='$_POST[question]',
+                       answer_0={$_POST[answer]}
+                       WHERE question_id=$_POST[qid] AND course_id=$_SESSION[course_id]";
+
+               $result = mysql_query($sql, $db);
+               
+               $msg->addFeedback('QUESTION_UPDATED');
+               if ($_POST['tid']) {
+                       header('Location: questions.php?tid='.$_POST['tid']);                   
+               } else {
+                       header('Location: question_db.php');
+               }
+               exit;
+       }
+}
+require(AT_INCLUDE_PATH.'header.inc.php'); 
+
+if (!$_POST['submit']) {
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."tests_questions WHERE question_id=$qid AND course_id=$_SESSION[course_id] AND type=2";
+       $result = mysql_query($sql, $db);
+
+       if (!($row = mysql_fetch_array($result))){
+               $msg->printErrors('ITEM_NOT_FOUND');
+               require (AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+
+       $_POST  = $row;
+}
+
+if ($_POST['required'] == 1) {
+       $req_yes = ' checked="checked"';
+} else {
+       $req_no  = ' checked="checked"';
+}
+
+if ($_POST['answer'] == '') {
+       if ($_POST['answer_0'] == 1) {
+               $ans_yes = ' checked="checked"';
+       } else if ($_POST['answer_0'] == 2){
+               $ans_no  = ' checked="checked"';
+       } else if ($_POST['answer_0'] == 3) {
+               $ans_yes1 = ' checked="checked"';
+       } else {
+               $ans_no1  = ' checked="checked"';
+       }
+} else {
+       if ($_POST['answer'] == 1) {
+               $ans_yes = ' checked="checked"';
+       } else if($_POST['answer'] == 2){
+               $ans_no  = ' checked="checked"';
+       } else if ($_POST['answer'] == 3) {
+               $ans_yes1 = ' checked="checked"';
+       } else {
+               $ans_no1  = ' checked="checked"';
+       }
+}
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="qid" value="<?php echo $qid; ?>" />
+<input type="hidden" name="tid" value="<?php echo $_REQUEST['tid']; ?>" />
+<input type="hidden" name="required" value="1" />
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('test_tf'); ?></legend>
+       <div class="row">
+               <label for="cats"><?php echo _AT('category'); ?></label>
+               <select name="category_id" id="cats">
+                       <?php print_question_cats($_POST['category_id']); ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <label for="optional_feedback"><?php echo _AT('optional_feedback'); ?></label> 
+               <?php print_VE('optional_feedback'); ?>
+               <textarea id="optional_feedback" cols="50" rows="3" name="feedback"><?php echo htmlspecialchars(stripslashes($_POST['feedback'])); ?></textarea>
+       </div>
+
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="question"><?php echo _AT('statement'); ?></label> 
+               <?php print_VE('question'); ?>  
+               <textarea id="question" cols="50" rows="6" name="question"><?php 
+                       echo htmlspecialchars(stripslashes($_POST['question'])); ?></textarea>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('answer'); ?><br />
+               <input type="radio" name="answer" value="1" id="answer1"<?php echo $ans_yes; ?> /><label for="answer1"><?php echo _AT('true'); ?></label>, <input type="radio" name="answer" value="2" id="answer2"<?php echo $ans_no; ?> /><label for="answer2"><?php echo _AT('false'); ?></label>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save'); ?>"   name="submit" accesskey="s"/>
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/edit_question_truefalse.php b/tools/tests/edit_question_truefalse.php
new file mode 100644 (file)
index 0000000..f2e0659
--- /dev/null
@@ -0,0 +1 @@
+<?php require('edit_question_tf.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/edit_test.php b/tools/tests/edit_test.php
new file mode 100644 (file)
index 0000000..5e593bb
--- /dev/null
@@ -0,0 +1,491 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+$page = 'tests';
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+
+$tid = intval($_REQUEST['tid']);
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php');
+       exit;
+} else if (isset($_POST['submit'])) {
+       $missing_fields             = array();
+       $_POST['title']                         = $addslashes(trim($_POST['title']));
+       $_POST['description']  = $addslashes(trim($_POST['description']));
+       $_POST['format']                        = intval($_POST['format']);
+       $_POST['randomize_order']       = intval($_POST['randomize_order']);
+       $_POST['num_questions']         = intval($_POST['num_questions']);
+       $_POST['passpercent']   = intval($_POST['passpercent']);
+       $_POST['passscore']     = intval($_POST['passscore']);
+       $_POST['passfeedback']  = $addslashes(trim($_POST['passfeedback']));
+       $_POST['failfeedback']  = $addslashes(trim($_POST['failfeedback']));
+       $_POST['num_takes']                     = intval($_POST['num_takes']);
+       $_POST['anonymous']                     = intval($_POST['anonymous']);
+       $_POST['display']                       = intval($_POST['display']);
+       $_POST['allow_guests']      = $_POST['allow_guests'] ? 1 : 0;
+       $_POST['instructions']      = $addslashes($_POST['instructions']);
+
+       /* this doesn't actually get used: */
+       $_POST['difficulty'] = intval($_POST['difficulty']);
+       if ($_POST['difficulty'] == '') {
+               $_POST['difficulty'] = 0;
+       }
+
+       $_POST['content_id'] = intval($_POST['content_id']);
+       if ($_POST['content_id'] == '') {
+               $_POST['content_id'] = 0;
+       }
+
+
+       $_POST['instructions'] = trim($_POST['instructions']);
+
+       if ($_POST['title'] == '') {
+               $missing_fields[] = 'title';
+       }
+
+       if ($_POST['random'] && !$_POST['num_questions']) {
+               $missing_fields[] = 'num_questions_per_test';
+       }
+
+       if ($_POST['pass_score']==1 && !$_POST['passpercent']) {
+               $missing_fields[] = _AT('percentage_score');
+       }
+
+       if ($_POST['pass_score']==2 && !$_POST['passscore']) {
+               $missing_fields[] = _AT('points_score');
+       }
+
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+
+       $day_start      = intval($_POST['day_start']);
+       $month_start= intval($_POST['month_start']);
+       $year_start     = intval($_POST['year_start']);
+       $hour_start     = intval($_POST['hour_start']);
+       $min_start      = intval($_POST['min_start']);
+
+       $day_end        = intval($_POST['day_end']);
+       $month_end      = intval($_POST['month_end']);
+       $year_end       = intval($_POST['year_end']);
+       $hour_end       = intval($_POST['hour_end']);
+       $min_end        = intval($_POST['min_end']);
+
+       if (!checkdate($month_start, $day_start, $year_start)) {
+               $msg->addError('START_DATE_INVALID');
+       }
+
+       if (!checkdate($month_end, $day_end, $year_end)) {
+               $msg->addError('END_DATE_INVALID');
+       }
+
+       if (mktime($hour_end,   $min_end,   0, $month_end,   $day_end,   $year_end) < 
+               mktime($hour_start, $min_start, 0, $month_start, $day_start, $year_start)) {
+                       $msg->addError('END_DATE_INVALID');
+       }
+
+       if (strlen($month_start) == 1){
+               $month_start = "0$month_start";
+       }
+       if (strlen($day_start) == 1){
+               $day_start = "0$day_start";
+       }
+       if (strlen($hour_start) == 1){
+               $hour_start = "0$hour_start";
+       }
+       if (strlen($min_start) == 1){
+               $min_start = "0$min_start";
+       }
+       if (strlen($month_end) == 1){
+               $month_end = "0$month_end";
+       }
+       if (strlen($day_end) == 1){
+               $day_end = "0$day_end";
+       }
+       if (strlen($hour_end) == 1){
+               $hour_end = "0$hour_end";
+       }
+       if (strlen($min_end) == 1){
+               $min_end = "0$min_end";
+       }
+
+       $start_date = "$year_start-$month_start-$day_start $hour_start:$min_start:00";
+       $end_date       = "$year_end-$month_end-$day_end $hour_end:$min_end:00";
+
+       if (!$msg->containsErrors()) {
+               // just to make sure we own this test:
+               $sql    = "SELECT * FROM ".TABLE_PREFIX."tests WHERE test_id=$tid AND course_id=$_SESSION[course_id]";
+               $result = mysql_query($sql, $db);
+
+               if ($row = mysql_fetch_assoc($result)) {
+                       if ($_POST['random']) {
+                               $total_weight = get_total_weight($tid, $_POST['num_questions']);
+                       } else {
+                               $total_weight = get_total_weight($tid);
+                       }
+                       //If title exceeded database defined length, truncate it.
+                       $_POST['title'] = validate_length($_POST['title'], 100);
+
+                       $sql = "UPDATE ".TABLE_PREFIX."tests " . 
+                              "SET title='$_POST[title]', 
+                                   description='$_POST[description]', 
+                                   format=$_POST[format], 
+                                   start_date='$start_date', 
+                                   end_date='$end_date', 
+                                   randomize_order=$_POST[randomize_order], 
+                                   num_questions=$_POST[num_questions], 
+                                   instructions='$_POST[instructions]', 
+                                   content_id=$_POST[content_id],  
+                                   passscore=$_POST[passscore], 
+                             passpercent=$_POST[passpercent], 
+                             passfeedback='$_POST[passfeedback]', 
+                             failfeedback='$_POST[failfeedback]', 
+                                   result_release=$_POST[result_release], 
+                                   random=$_POST[random], 
+                                   difficulty=$_POST[difficulty], 
+                                   num_takes=$_POST[num_takes], 
+                                   anonymous=$_POST[anonymous], 
+                                   guests=$_POST[allow_guests], 
+                                   out_of=$total_weight, 
+                                   display=$_POST[display] 
+                               WHERE test_id=$tid 
+                               AND course_id=$_SESSION[course_id]";
+                               
+                       $result = mysql_query($sql, $db);
+
+                       $sql = "DELETE FROM ".TABLE_PREFIX."tests_groups WHERE test_id=$tid";
+                       $result = mysql_query($sql, $db);       
+                       
+                       if (isset($_POST['groups'])) {
+                               $sql = "INSERT INTO ".TABLE_PREFIX."tests_groups VALUES ";
+                               foreach ($_POST['groups'] as $group) {
+                                       $group = intval($group);
+                                       $sql .= "($tid, $group),";
+                               }
+                               $sql = substr($sql, 0, -1);
+                               $result = mysql_query($sql, $db);
+                       }
+               }
+               
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');             
+               
+               header('Location: index.php');
+               exit;
+       }
+}
+
+$onload = 'document.form.title.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if (!isset($_POST['submit'])) {
+       $sql    = "SELECT *, DATE_FORMAT(start_date, '%Y-%m-%d %H:%i:00') AS start_date, DATE_FORMAT(end_date, '%Y-%m-%d %H:%i:00') AS end_date FROM ".TABLE_PREFIX."tests WHERE test_id=$tid AND course_id=$_SESSION[course_id]";
+       $result = mysql_query($sql, $db);
+
+       if (!($row = mysql_fetch_assoc($result))){
+               $msg->printErrors('ITEM_NOT_FOUND');
+               require (AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+
+       $_POST  = $row;
+       $_POST['allow_guests'] = $row['guests'];
+} else {
+       $_POST['start_date'] = $start_date;
+       $_POST['end_date']       = $end_date;
+}
+       
+$msg->printErrors();
+
+?>
+
+<script language="javascript" type="text/javascript">
+function disable_texts (name) {
+       if (name == 'both')
+       {
+               document.form['passpercent'].disabled=true;
+               document.form['passscore'].disabled=true;
+               document.form['passpercent'].value=0;
+               document.form['passscore'].value=0;
+       }
+       else if (name == 'percentage')
+       {
+               document.form['passpercent'].disabled=true;
+               document.form['passpercent'].value=0;
+               document.form['passscore'].disabled=false;
+       }
+       else if (name == 'points')
+       {
+               document.form['passpercent'].disabled=false;
+               document.form['passscore'].disabled=true;
+               document.form['passscore'].value=0;
+       }
+}
+</script>
+
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="tid" value="<?php echo $tid; ?>" />
+<input type="hidden" name="randomize_order" value="1" />
+<input type="hidden" name="instructions" value="" />
+<input type="hidden" name="difficulty" value="0" />
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('edit_test'); ?></legend>
+       <div class="row">
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="title"><?php echo _AT('title'); ?></label><br />
+               <input type="text" name="title" id="title" size="40" value="<?php echo stripslashes(htmlspecialchars($_POST['title'])); ?>" />
+       </div>
+       
+       <div class="row">
+               <label for="description"><?php echo _AT('test_description'); ?></label><br />
+               <textarea name="description" cols="35" rows="3" id="description"><?php echo htmlspecialchars($_POST['description']); ?></textarea>
+       </div>
+
+       <div class="row">       
+               <label for="num_t"><?php echo _AT('num_takes_test'); ?></label><br />
+               <select name="num_takes" id="num_t">
+                       <option value="<?php echo AT_TESTS_TAKE_UNLIMITED; ?>" <?php if ($_POST['num_takes'] == AT_TESTS_TAKE_UNLIMITED) { echo 'selected="selected"'; } ?>><?php echo _AT('unlimited'); ?></option>
+               
+                       <option value="1"<?php if ($_POST['num_takes'] == 1) { echo ' selected="selected"'; } ?>>1</option>
+                       <option value="2"<?php if ($_POST['num_takes'] == 2) { echo ' selected="selected"'; } ?>>2</option>
+                       <option value="3"<?php if ($_POST['num_takes'] == 3) { echo ' selected="selected"'; } ?>>3</option>
+                       <option value="4"<?php if ($_POST['num_takes'] == 4) { echo ' selected="selected"'; } ?>>4</option>
+                       <option value="5"<?php if ($_POST['num_takes'] == 5) { echo ' selected="selected"'; } ?>>5</option>
+                       <option value="6"<?php if ($_POST['num_takes'] == 6) { echo ' selected="selected"'; } ?>>6</option>
+                       <option value="7"<?php if ($_POST['num_takes'] == 7) { echo ' selected="selected"'; } ?>>7</option>
+                       <option value="8"<?php if ($_POST['num_takes'] == 8) { echo ' selected="selected"'; } ?>>8</option>
+                       <option value="9"<?php if ($_POST['num_takes'] == 9) { echo ' selected="selected"'; } ?>>9</option>
+                       <option value="10"<?php if ($_POST['num_takes'] == 10) { echo ' selected="selected"'; } ?>>10</option>
+                       <option value="15"<?php if ($_POST['num_takes'] == 15) { echo ' selected="selected"'; } ?>>15</option>
+                       <option value="20"<?php if ($_POST['num_takes'] >= 20) { echo ' selected="selected"'; } ?>>20</option>
+               </select>
+       </div>
+       
+       <div class="row">
+               <?php echo _AT('available_on_my_courses'); ?><br />
+               <?php 
+                       if ($_POST['format'] == 1) {
+                               $y = 'checked="checked"';
+                               $n = '';
+                       } else {
+                               $y = '';
+                               $n = 'checked="checked"';
+                       }
+               ?>
+               <input type="radio" name="format" id="formatN" value="0" <?php echo $n; ?> /><label for="formatN"><?php echo _AT('no'); ?></label> 
+               <input type="radio" name="format" id="formatY" value="1" <?php echo $y; ?> /><label for="formatY"><?php echo _AT('yes'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('anonymous_test'); ?><br />
+               <?php 
+                       if ($_POST['anonymous'] == 1) {
+                               $y = 'checked="checked"';
+                               $n = '';
+                       } else {
+                               $y = '';
+                               $n = 'checked="checked"';
+                       }
+               ?>
+               <input type="radio" name="anonymous" id="anonN" value="0" <?php echo $n; ?> /><label for="anonN"><?php echo _AT('no'); ?></label>
+               <input type="radio" name="anonymous" value="1" id="anonY" <?php echo $y; ?> /><label for="anonY"><?php echo _AT('yes'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('allow_guests'); ?><br />
+               <?php 
+                       if ($_POST['allow_guests'] == 1) {
+                               $y = 'checked="checked"';
+                               $n = '';
+                       } else {
+                               $y = '';
+                               $n = 'checked="checked"';
+                       }
+               ?>
+
+               <input type="radio" name="allow_guests" id="allow_guestsN" value="0" <?php echo $n; ?> /><label for="allow_guestsN"><?php echo _AT('no'); ?></label> 
+               <input type="radio" name="allow_guests" value="1" id="allow_guestsY" <?php echo $y; ?> /><label for="allow_guestsY"><?php echo _AT('yes'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('display'); ?><br />
+               <?php 
+                       if ($_POST['display'] == 1) {
+                               $y = 'checked="checked"';
+                               $n = '';
+                       } else {
+                               $y = '';
+                               $n = 'checked="checked"';
+                       }
+               ?>
+
+               <input type="radio" name="display" id="displayN" value="0" <?php echo $n; ?> /><label for="displayN"><?php echo _AT('all_questions_on_page'); ?></label> 
+               <input type="radio" name="display" id="displayY" value="1" <?php echo $y; ?> /><label for="displayY"><?php echo _AT('one_question_per_page'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('pass_score'); ?><br />
+               <input type="radio" name="pass_score" value="0" id="no" <?php if ($_POST['passpercent'] == 0 && $_POST['passscore'] == 0){echo 'checked="true"';} ?> 
+                onfocus="disable_texts('both');" />
+
+               <label for="no" title="<?php echo _AT('pass_score'). ': '. _AT('no_pass_score');  ?>"><?php echo _AT('no_pass_score'); ?></label><br />
+
+               <input type="radio" name="pass_score" value="1" id="percentage"  <?php if ($_POST['passpercent'] <> 0){echo 'checked="true"';} ?>
+                onfocus="disable_texts('points');" />
+
+               <input type="text" name="passpercent" id="passpercent" size="2" value="<?php echo $_POST['passpercent']; ?>" 
+                <?php if ($_POST['passpercent'] == 0){echo 'disabled="true"';} ?> /> 
+               <label for="percentage" title="<?php echo _AT('pass_score'). ': '. _AT('percentage_score');  ?>"><?php  echo '% ' . _AT('percentage_score'); ?></label><br />
+
+               <input type="radio" name="pass_score" value="2" id="points"  <?php if ($_POST['passscore'] <> 0){echo 'checked="true"';} ?>
+                onfocus="disable_texts('percentage');" />
+
+               <input type="text" name="passscore" id="passscore" size="2" value="<?php echo $_POST['passscore']; ?>" 
+                <?php if ($_POST['passscore'] == 0){echo 'disabled="true"';} ?>/> 
+               <label for="points" title="<?php echo _AT('pass_score'). ': '. _AT('points_score');  ?>"><?php  echo _AT('points_score'); ?></label>
+       </div>
+
+       <div class="row">
+               <label for="passfeedback"><?php echo _AT('pass_feedback'); ?></label><br />
+               <textarea name="passfeedback" cols="35" rows="1" id="passfeedback"><?php echo htmlspecialchars($_POST['passfeedback']); ?></textarea>
+       </div>
+
+       <div class="row">
+               <label for="failfeedback"><?php echo _AT('fail_feedback'); ?></label><br />
+               <textarea name="failfeedback" cols="35" rows="1" id="failfeedback"><?php echo htmlspecialchars($_POST['failfeedback']); ?></textarea>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('result_release'); ?><br />
+               <?php 
+                       if ($_POST['result_release'] == AT_RELEASE_IMMEDIATE) {
+                               $check_marked = $check_never = '';
+                               $check_immediate = 'checked="checked"';
+
+                       } else if ($_POST['result_release'] == AT_RELEASE_MARKED) {
+                               $check_immediate = $check_never = '';
+                               $check_marked = 'checked="checked"';
+
+                       } else if ($_POST['result_release'] == AT_RELEASE_NEVER) {
+                               $check_immediate = $check_marked = '';
+                               $check_never = 'checked="checked"';
+                       }
+               ?>
+
+               <input type="radio" name="result_release" id="release1" value="<?php echo AT_RELEASE_IMMEDIATE; ?>" <?php echo $check_immediate; ?> /><label for="release1"><?php echo _AT('release_immediate'); ?></label><br />
+               <input type="radio" name="result_release" id="release2" value="<?php echo AT_RELEASE_MARKED; ?>" <?php echo $check_marked; ?> /><label for="release2"><?php echo _AT('release_marked'); ?></label><br />
+               <input type="radio" name="result_release" id="release3" value="<?php echo AT_RELEASE_NEVER; ?>" <?php echo $check_never; ?>/><label for="release3"><?php echo _AT('release_never'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('randomize_questions'); ?><br />
+               <?php 
+                       if ($_POST['random'] == 1) {
+                               $y = 'checked="checked"';
+                               $n = $disabled = '';
+                       } else {
+                               $y = '';
+                               $n = 'checked="checked"';
+                               $disabled = 'disabled="disabled" ';
+                       }
+               ?>
+               <input type="radio" name="random" id="random" value="0" checked="checked" onfocus="document.form.num_questions.disabled=true;" /><label for="random"><?php echo _AT('no'); ?></label>. <input type="radio" name="random" value="1" id="ry" onfocus="document.form.num_questions.disabled=false;" <?php echo $y; ?> /><label for="ry"><?php echo _AT('yes'); ?></label>, <input type="text" name="num_questions" id="num_questions" size="2" value="<?php echo $_POST['num_questions']; ?>" <?php echo $disabled . $n; ?> /> <label for="num_questions"><?php echo _AT('num_questions_per_test'); ?></label>
+       </div>
+
+       <div class="row">
+               <?php echo _AT('start_date'); ?><br />
+               <?php
+                       $today_day   = substr($_POST['start_date'], 8, 2);
+                       $today_mon   = substr($_POST['start_date'], 5, 2);
+                       $today_year  = substr($_POST['start_date'], 0, 4);
+
+                       $today_hour  = substr($_POST['start_date'], 11, 2);
+                       $today_min   = substr($_POST['start_date'], 14, 2);
+
+                       $name = '_start';
+                       require(AT_INCLUDE_PATH.'html/release_date.inc.php');
+               ?>
+       </div>
+       <div class="row">
+               <?php echo _AT('end_date'); ?><br />
+               <?php
+                       $today_day   = substr($_POST['end_date'], 8, 2);
+                       $today_mon   = substr($_POST['end_date'], 5, 2);
+                       $today_year  = substr($_POST['end_date'], 0, 4);
+
+                       $today_hour  = substr($_POST['end_date'], 11, 2);
+                       $today_min   = substr($_POST['end_date'], 14, 2);
+
+                       $name = '_end';
+                       require(AT_INCLUDE_PATH.'html/release_date.inc.php');
+               ?>
+       </div>
+
+       <div class="row">
+               <label for="inst"><?php echo _AT('limit_to_group'); ?></label><br />
+               <?php
+                       //show groups
+                       //get groups currently allowed
+                       $current_groups = array();
+                       $sql    = "SELECT group_id FROM ".TABLE_PREFIX."tests_groups WHERE test_id=$tid";
+                       $result = mysql_query($sql, $db);
+                       while ($row = mysql_fetch_assoc($result)) {
+                               $current_groups[] = $row['group_id'];
+                       }
+
+                       //show groups
+                       $sql    = "SELECT * FROM ".TABLE_PREFIX."groups_types WHERE course_id=$_SESSION[course_id] ORDER BY title";
+                       $result = mysql_query($sql, $db);
+                       if (mysql_num_rows($result)) {
+                               while ($row = mysql_fetch_assoc($result)) {
+                                       echo '<em>'.$row['title'].'</em><br />';
+
+                                       $sql    = "SELECT * FROM ".TABLE_PREFIX."groups WHERE type_id=$row[type_id] ORDER BY title";
+                                       $g_result = mysql_query($sql, $db);
+                                       while ($grow = mysql_fetch_assoc($g_result)) {
+                                               echo '&nbsp;<label><input type="checkbox" value="'.$grow['group_id'].'" name="groups['.$grow['group_id'].']" '; 
+                                               if (is_array($current_groups) && in_array($grow['group_id'], $current_groups)) {
+                                                       echo 'checked="checked"';
+                                               }
+                                               echo '/>'.$grow['title'].'</label><br />';
+                                       }
+                               }
+                       } else {
+                               echo _AT('none_found');
+                       }
+               ?>
+       </div>
+
+       <div class="row">
+               <label for="inst"><?php echo _AT('instructions'); ?></label><br />
+               <textarea name="instructions" cols="35" rows="3" id="inst"><?php echo htmlspecialchars($_POST['instructions']); ?></textarea>
+       </div>
+
+
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('save');  ?>"  name="submit" accesskey="s" />
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/form_editor.php b/tools/tests/form_editor.php
new file mode 100644 (file)
index 0000000..960957f
--- /dev/null
@@ -0,0 +1,124 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+$page = 'form_editor';\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+require(AT_INCLUDE_PATH.'lib/tinymce.inc.php');\r
+\r
+authenticate(AT_PRIV_TESTS);\r
+\r
+$area = $_GET['area'];\r
+$number = null;\r
+\r
+$parts = explode('_', $area, 2);\r
+if (is_numeric($parts[1])) {\r
+       $parts[1]++;\r
+       $title = _AT($parts[0]) . ' ' . $parts[1];\r
+} else {\r
+       $title = _AT($area);\r
+}\r
+\r
+$onload = 'onload="init();"';\r
+\r
+\r
+global $myLang;\r
+global $page;\r
+global $savant;\r
+global $errors, $onload;\r
+global $_user_location;\r
+global $_base_path;\r
+global $cid;\r
+global $contentManager;\r
+global $_section;\r
+global $addslashes;\r
+\r
+\r
+if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {\r
+       $_tmp_base_href = AT_BASE_HREF . 'get.php/';\r
+} else {\r
+       $_tmp_base_href = 'content/' . $_SESSION['course_id'] . '/';\r
+}\r
+\r
+?>\r
+\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r
+<html lang="en">\r
+<head>\r
+       <title><?php echo _AT('form_editor'); ?></title>\r
+\r
+       <link rel="stylesheet" href="<?php echo $_base_path.'themes/'.$_SESSION['prefs']['PREF_THEME']; ?>/styles.css" type="text/css" />\r
+       <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />\r
+               <base href="<?php echo AT_BASE_HREF; ?>" />\r
+\r
+</head>\r
+\r
+<body <?php echo $onload; ?> >\r
+\r
+<script type="text/javascript"><!--\r
+function init() {\r
+       tinyMCE.activeEditor.setContent(window.opener.document.getElementById("<?php echo $area; ?>"). value);\r
+}\r
+//--></script>\r
+\r
+<?php load_editor(); ?>\r
+\r
+\r
+<div align="right"><br /><a href="javascript:window.close()"><?php echo _AT('close_window'); ?></a></div>\r
+<form name="form">\r
+       <table cellspacing="1" cellpadding="0" width="99%" border="0" class="bodyline" align="center" summary="">\r
+               <tr>\r
+                       <th class="cyan"><?php echo $title; ?></th>\r
+               </tr>\r
+               <tr>\r
+                       <td colspan="2" valign="top" align="left" class="row1">\r
+                               <table cellspacing="0" cellpadding="0" width="98%" border="0" summary="">\r
+                               <tr>\r
+                                       <td class="row1" align="left">  \r
+                                               <textarea name="body_text" id="body_text" rows="15" class="formfield" style="width: 99%;"></textarea>\r
+                                       </td>\r
+                               </tr>\r
+                               </table>\r
+                       </td>\r
+               </tr>\r
+               <tr>\r
+                       <td height="1" class="row2" colspan="2"></td>\r
+               </tr>\r
+               <tr>\r
+                       <td colspan="2" valign="top" align="center" class="row1">\r
+                               <input type="button" name="paste"  value="<?php echo _AT('paste');  ?>" class="button" onclick="javascript:insertTo('<?php echo $area; ?>');" />\r
+                       </td>\r
+               </tr>\r
+       </table>\r
+</form>\r
+<br />\r
+\r
+\r
+<script type="text/javascript">\r
+<!--\r
+function insertTo(field) {\r
+               if (window.opener.document.getElementById(field)) {\r
+                       window.opener.document.getElementById(field).value = tinyMCE.activeEditor.getContent({format : 'raw'});\r
+               }\r
+}\r
+-->\r
+</script>\r
+\r
+\r
+<iframe src="<?php echo $_base_path; ?>tools/filemanager/index.php?framed=1<?php echo SEP; ?>popup=1" name="filemanager" width="98%" height="480">\r
+</iframe>\r
+\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/tools/tests/index.php b/tools/tests/index.php
new file mode 100644 (file)
index 0000000..c4b407b
--- /dev/null
@@ -0,0 +1,157 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+$page = 'tests';
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_TESTS);
+
+if (isset($_GET['edit'], $_GET['id'])) {
+       header('Location: edit_test.php?tid='.$_GET['id']);
+       exit;
+} else if (isset($_GET['preview'], $_GET['id'])) {
+       header('Location: preview.php?tid='.$_GET['id']);
+       exit;
+} else if (isset($_GET['questions'], $_GET['id'])) {
+       header('Location: questions.php?tid='.$_GET['id']);
+       exit;
+} else if (isset($_GET['submissions'], $_GET['id'])) {
+       header('Location: results.php?tid='.$_GET['id']);
+       exit;
+} else if (isset($_GET['statistics'], $_GET['id'])) {
+       header('Location: results_all_quest.php?tid='.$_GET['id']);
+       exit;
+} else if (isset($_GET['delete'], $_GET['id'])) {
+       header('Location: delete_test.php?tid='.$_GET['id']);
+       exit;
+} else if (isset($_GET['edit']) 
+               || isset($_GET['preview']) 
+               || isset($_GET['questions']) 
+               || isset($_GET['submissions']) 
+               || isset($_GET['statistics']) 
+               || isset($_GET['delete'])) {
+
+       $msg->addError('NO_ITEM_SELECTED');
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+
+/* get a list of all the tests we have, and links to create, edit, delete, preview */
+
+$sql   = "SELECT *, UNIX_TIMESTAMP(start_date) AS us, UNIX_TIMESTAMP(end_date) AS ue FROM ".TABLE_PREFIX."tests WHERE course_id=$_SESSION[course_id] ORDER BY start_date DESC";
+$result        = mysql_query($sql, $db);
+$num_tests = mysql_num_rows($result);
+
+$cols=6;
+?>
+<form name="form" method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<table class="data" summary="" style="width: 90%" rules="cols">
+<thead>
+<tr>
+       <th scope="col">&nbsp;</th>
+       <th scope="col"><?php echo _AT('title');          ?></th>
+       <th scope="col"><?php echo _AT('status');         ?></th>
+       <th scope="col"><?php echo _AT('availability');   ?></th>
+       <th scope="col"><?php echo _AT('result_release'); ?></th>
+       <th scope="col"><?php echo _AT('submissions'); ?></th>
+       <th scope="col"><?php echo _AT('assigned_to'); ?></th>
+</tr>
+</thead>
+
+<?php if ($num_tests): ?>
+       <tfoot>
+       <tr>
+               <td colspan="7">
+                       <input type="submit" name="edit" value="<?php echo _AT('edit'); ?>" />
+                       <input type="submit" name="preview" value="<?php echo _AT('preview'); ?>" />
+                       <input type="submit" name="questions" value="<?php echo _AT('questions'); ?>" />
+               </td>
+       </tr>
+       <tr>    
+               <td colspan="7" style="padding-left:38px;">
+                       <input type="submit" name="submissions" value="<?php echo _AT('submissions'); ?>" />
+                       <input type="submit" name="statistics" value="<?php echo _AT('statistics'); ?>" />
+                       <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" />
+               </td>
+       </tr>
+       </tfoot>
+       <tbody>
+
+       <?php while ($row = mysql_fetch_assoc($result)) : ?>
+               <tr onmousedown="document.form['t<?php echo $row['test_id']; ?>'].checked = true;rowselect(this);" id="r_<?php echo $row['test_id']; ?>">
+                       <td><input type="radio" name="id" value="<?php echo $row['test_id']; ?>" id="t<?php echo $row['test_id']; ?>" /></td>
+                       <td><label for="t<?php echo $row['test_id']; ?>"><?php echo $row['title']; ?></label></td>
+                       <td><?php
+                               if ( ($row['us'] <= time()) && ($row['ue'] >= time() ) ) {
+                                       echo '<em>'._AT('ongoing').'</em>';
+                               } else if ($row['ue'] < time() ) {
+                                       echo '<em>'._AT('expired').'</em>';
+                               } else if ($row['us'] > time() ) {
+                                       echo '<em>'._AT('pending').'</em>';
+                               } ?></td>
+                       <td><?php $startend_date_format=_AT('startend_date_format'); echo AT_date( $startend_date_format, $row['start_date'], AT_DATE_MYSQL_DATETIME). ' ' ._AT('to_2').' ';
+                               echo AT_date($startend_date_format, $row['end_date'], AT_DATE_MYSQL_DATETIME); ?></td>
+
+                       <td><?php
+                               if ($row['result_release'] == AT_RELEASE_IMMEDIATE) {
+                                       echo _AT('release_immediate');
+                               } else if ($row['result_release'] == AT_RELEASE_MARKED) {
+                                       echo _AT('release_marked');
+                               } else if ($row['result_release'] == AT_RELEASE_NEVER) {
+                                       echo _AT('release_never');
+                               }
+                       ?></td>
+                       <td><?php
+                               //get # marked submissions
+                               $sql_sub = "SELECT COUNT(*) AS sub_cnt FROM ".TABLE_PREFIX."tests_results WHERE status=1 AND test_id=".$row['test_id'];
+                               $result_sub     = mysql_query($sql_sub, $db);
+                               $row_sub = mysql_fetch_assoc($result_sub);
+                               echo $row_sub['sub_cnt'].' '._AT('submissions').', ';
+
+                               //get # submissions
+                               $sql_sub = "SELECT COUNT(*) AS marked_cnt FROM ".TABLE_PREFIX."tests_results WHERE status=1 AND test_id=".$row['test_id']." AND final_score=''";
+                               $result_sub     = mysql_query($sql_sub, $db);
+                               $row_sub = mysql_fetch_assoc($result_sub);
+                               echo $row_sub['marked_cnt'].' '._AT('unmarked');
+                               ?>
+                       </td>
+                       <td><?php
+                               //get assigned groups
+                               $sql_sub = "SELECT G.title FROM ".TABLE_PREFIX."groups G INNER JOIN ".TABLE_PREFIX."tests_groups T USING (group_id) WHERE T.test_id=".$row['test_id'];
+                               $result_sub     = mysql_query($sql_sub, $db);
+                               if (mysql_num_rows($result_sub) == 0) {
+                                       echo _AT('everyone');
+                               } else {
+                                       $row_sub = mysql_fetch_assoc($result_sub);
+                                       echo $row_sub['title'];
+                                       do {
+                                               echo ', '.$row_sub['title'];
+                                       } while ($row_sub = mysql_fetch_assoc($result_sub));
+                               }                               
+                               ?>
+                       </td>
+               </tr>
+       <?php endwhile; ?>
+<?php else: ?>
+       <tbody>
+       <tr>
+               <td colspan="7"><?php echo _AT('none_found'); ?></td>
+       </tr>
+<?php endif; ?>
+</tbody>
+</table>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/preview.php b/tools/tests/preview.php
new file mode 100644 (file)
index 0000000..db6b5de
--- /dev/null
@@ -0,0 +1,141 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'classes/testQuestions.class.php');
+
+authenticate(AT_PRIV_TESTS);
+$_letters = array(_AT('A'), _AT('B'), _AT('C'), _AT('D'), _AT('E'), _AT('F'), _AT('G'), _AT('H'), _AT('I'), _AT('J'));
+
+if ($_POST['back']) {
+       header('Location: index.php');
+       exit;
+} 
+
+if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+       $content_base_href = 'get.php/';
+} else {
+       $content_base_href = 'content/' . $_SESSION['course_id'] . '/';
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$tid = intval($_GET['tid']);
+
+/* Retrieve the content_id of this test */
+$sql = "SELECT title, random, num_questions, instructions FROM ".TABLE_PREFIX."tests WHERE test_id=$tid";
+$result        = mysql_query($sql, $db); 
+if (!($test_row = mysql_fetch_assoc($result))) {
+       $msg->printErrors('ITEM_NOT_FOUND');
+       require (AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+$num_questions = $test_row['num_questions'];
+$rand_err = false;
+
+if ($row['random']) {
+       /* !NOTE! this is a really awful way of randomizing questions !NOTE! */
+
+       /* Retrieve 'num_questions' question_id randomly choosed from  
+       those who are related to this content_id*/
+       $sql    = "SELECT question_id FROM ".TABLE_PREFIX."tests_questions_assoc WHERE test_id=$tid";
+       $result = mysql_query($sql, $db); 
+       $i = 0;
+       $row2 = mysql_fetch_assoc($result);
+       /* Store all related question in cr_questions */
+       while ($row2['question_id'] != '') {
+               $cr_questions[$i] = $row2['question_id'];
+               $row2 = mysql_fetch_assoc($result);
+               $i++;
+       }
+       if ($i < $num_questions) {
+               /* this if-statement is misleading. */
+               /* one should still be able to preview a test before all its questions have been added. */
+               /* ie. preview as questions are added. */
+               /* bug # 0000615 */
+               $rand_err = true;
+       } else {
+               /* Randomly choose only 'num_question' question */
+               $random_idx = rand(0, $i-1);
+               $random_id_string = $cr_questions[$random_idx];
+               $j = 0;
+               $extracted[$j] = $random_idx;
+               $j++;
+               $num_questions--;
+               while ($num_questions > 0) {
+                       $done = false;
+                       while (!$done) {
+                               $random_idx = rand(0, $i-1);
+                               $done = true;
+                               for ($k=0;$k<$j;$k++) {
+                                       if ($extracted[$k]== $random_idx) {
+                                               $done = false;
+                                               break;
+                                       }
+                               }
+                       }
+                       $extracted[$j] = $random_idx;
+                       $j++;
+                       $random_id_string = $random_id_string.','.$cr_questions[$random_idx];
+                       $num_questions--;
+               }
+               $sql = "SELECT TQ.*, TQA.* FROM ".TABLE_PREFIX."tests_questions TQ INNER JOIN ".TABLE_PREFIX."tests_questions_assoc TQA USING (question_id) WHERE TQ.course_id=$_SESSION[course_id] AND TQA.test_id=$tid AND TQA.question_id IN ($random_id_string) ORDER BY TQA.ordering, TQA.question_id";
+       }
+} else {
+       $sql    = "SELECT TQ.*, TQA.* FROM ".TABLE_PREFIX."tests_questions TQ INNER JOIN ".TABLE_PREFIX."tests_questions_assoc TQA USING (question_id) WHERE TQ.course_id=$_SESSION[course_id] AND TQA.test_id=$tid ORDER BY TQA.ordering, TQA.question_id";
+}
+$result        = mysql_query($sql, $db);
+$count = 1;
+echo '<form method="post" action="'.$_SERVER['PHP_SELF'].'" name="preview">';
+
+if (($row = mysql_fetch_assoc($result)) && !$rand_err) {
+       ?>
+       <div class="input-form" style="width:80%">
+       <div class="row"><h2><?php echo $test_row['title']; ?></h2></div>
+
+
+       <?php if ($test_row['instructions'] != ''): ?>
+               <div style="background-color: #f3f3f3; padding: 5px 10px; margin: 0px; border-top: 1px solid">
+                       <strong><?php echo _AT('instructions'); ?></strong>
+               </div>
+               <div class="row" style="padding-bottom: 20px"><?php echo $test_row['instructions']; ?></div>
+       <?php endif; ?>
+       
+       <?php
+       do {
+               $o = TestQuestions::getQuestion($row['type']);
+               $o->display($row);
+       } while ($row = mysql_fetch_assoc($result));
+       ?>
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('back'); ?>" name="back" />
+       </div>
+
+       </div>
+       </form>
+<script type="text/javascript">
+//<!--
+function iframeSetHeight(id, height) {
+       document.getElementById("qframe" + id).style.height = (height + 20) + "px";
+}
+//-->
+</script>
+<?php
+} else {
+       $msg->printErrors('NO_QUESTIONS');
+}
+
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/tools/tests/preview_question.php b/tools/tests/preview_question.php
new file mode 100644 (file)
index 0000000..8bf7eb4
--- /dev/null
@@ -0,0 +1,57 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'classes/testQuestions.class.php');\r
+authenticate(AT_PRIV_TESTS);\r
+\r
+$_letters = array(_AT('A'), _AT('B'), _AT('C'), _AT('D'), _AT('E'), _AT('F'), _AT('G'), _AT('H'), _AT('I'), _AT('J'));\r
+\r
+if (isset($_GET['submit'])) {\r
+       header('Location: '.AT_BASE_HREF.'tools/tests/question_db.php');\r
+       exit;\r
+}\r
+\r
+if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {\r
+       $content_base_href = 'get.php/';\r
+} else {\r
+       $content_base_href = 'content/' . $_SESSION['course_id'] . '/';\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$qid = $addslashes($_GET['qid']);\r
+$sql = "SELECT * FROM ".TABLE_PREFIX."tests_questions WHERE course_id=$_SESSION[course_id] AND question_id IN ($qid)";\r
+$result        = mysql_query($sql, $db);\r
+?>\r
+\r
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">\r
+<div class="input-form">\r
+       <?php\r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               $obj = TestQuestions::getQuestion($row['type']);\r
+               $obj->display($row);\r
+       }\r
+       ?>\r
+       <div class="row buttons"><input type="submit" name="submit" value="<?php echo _AT('back'); ?>"/></div>\r
+</div>\r
+</form>\r
+<script type="text/javascript">\r
+//<!--\r
+function iframeSetHeight(id, height) {\r
+       document.getElementById("qframe" + id).style.height = (height + 30) + "px";\r
+}\r
+//-->\r
+</script>\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/question_cats.php b/tools/tests/question_cats.php
new file mode 100644 (file)
index 0000000..8b23c60
--- /dev/null
@@ -0,0 +1,63 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+$page = 'tests';\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+authenticate(AT_PRIV_TESTS);\r
+\r
+if (isset($_POST['edit'], $_POST['category'])) {\r
+       header('Location: question_cats_manage.php?catid='.$_POST['category']);\r
+       exit;\r
+} else if (isset($_POST['delete'], $_POST['category'])) {\r
+       header('Location: question_cats_delete.php?catid='.$_POST['category']);\r
+       exit;\r
+} else if (!empty($_POST)) {\r
+       $msg->addError('NO_ITEM_SELECTED');\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$sql   = "SELECT * FROM ".TABLE_PREFIX."tests_questions_categories WHERE course_id=$_SESSION[course_id] ORDER BY title";\r
+$result        = mysql_query($sql, $db);\r
+\r
+if ($row = mysql_fetch_assoc($result)) {\r
+?>\r
+       <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">\r
+       <div class="input-form">\r
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('question_categories'); ?></legend>\r
+<?php  do { ?>\r
+                       <div class="row">\r
+                               <input type="radio" id="cat_<?php echo $row['category_id']; ?>" name="category" value="<?php echo $row['category_id']; ?>" />   <label for="cat_<?php echo $row['category_id']; ?>"><?php echo AT_print($row['title'], 'tests_questions_categories.title'); ?></label>\r
+                       </div>\r
+<?php \r
+               } while ($row = mysql_fetch_assoc($result));\r
+?>\r
+\r
+               <div class="row buttons">\r
+                       <input type="submit" value="<?php echo _AT('edit'); ?>"   name="edit" />\r
+                       <input type="submit" value="<?php echo _AT('delete'); ?>" name="delete" />\r
+               </div>\r
+       </div>\r
+       </form>\r
+<?php\r
+\r
+       } else {\r
+               echo '<p>'._AT('cats_no_categories').'</p>';\r
+       }\r
+?>\r
+\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/question_cats_delete.php b/tools/tests/question_cats_delete.php
new file mode 100644 (file)
index 0000000..c4ea93d
--- /dev/null
@@ -0,0 +1,62 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+$page = 'tests';\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+authenticate(AT_PRIV_TESTS);\r
+if (isset($_POST['submit_yes'])) {\r
+       $_POST['catid'] = intval($_POST['catid']);\r
+\r
+       //remove cat\r
+       $sql = "DELETE FROM ".TABLE_PREFIX."tests_questions_categories WHERE course_id=$_SESSION[course_id] AND category_id=".$_POST['catid'];\r
+       $result = mysql_query($sql, $db);\r
+\r
+       //set all q's that use this cat to have cat=0\r
+       $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET category_id=0 WHERE course_id=$_SESSION[course_id] AND category_id=".$_POST['catid'];\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: '.AT_BASE_HREF.'tools/tests/question_cats.php');\r
+       exit;\r
+\r
+} else if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: '.AT_BASE_HREF.'tools/tests/question_cats.php');\r
+       exit;\r
+} else if (!isset($_GET['catid'])) {\r
+       require(AT_INCLUDE_PATH.'header.inc.php');\r
+       $msg->addError('ITEM_NOT_FOUND');\r
+       $msg->printErrors();\r
+       require(AT_INCLUDE_PATH.'footer.inc.php');\r
+       exit;\r
+} \r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$_GET['catid'] = intval($_GET['catid']);\r
+\r
+$sql   = "SELECT title FROM ".TABLE_PREFIX."tests_questions_categories WHERE course_id=$_SESSION[course_id] AND category_id=$_GET[catid]";\r
+$result        = mysql_query($sql, $db);\r
+$row = mysql_fetch_array($result);\r
+\r
+$hidden_vars['catid'] = $_GET['catid'];\r
+\r
+$msg->addConfirm(array('DELETE_TEST_CATEGORY', $row['title']), $hidden_vars);\r
+       \r
+$msg->printConfirm();\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/tools/tests/question_cats_manage.php b/tools/tests/question_cats_manage.php
new file mode 100644 (file)
index 0000000..f675729
--- /dev/null
@@ -0,0 +1,82 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+$page = 'tests';\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+authenticate(AT_PRIV_TESTS);\r
+\r
+if (isset($_POST['cancel'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: question_cats.php');\r
+       exit;\r
+} else if (isset($_POST['submit'])) {\r
+\r
+       $_POST['title'] = trim($_POST['title']);\r
+\r
+       if (!empty($_POST['title']) && !isset($_POST['catid'])) {\r
+               $_POST['title'] = $addslashes($_POST['title']);\r
+               $sql    = "INSERT INTO ".TABLE_PREFIX."tests_questions_categories VALUES (NULL, $_SESSION[course_id], '$_POST[title]')";\r
+               $result = mysql_query($sql, $db);\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+               header('Location: question_cats.php');\r
+               exit;\r
+       } else if (!empty($_POST['title']) && isset($_POST['catid']))  {\r
+               $_POST['title'] = $addslashes($_POST['title']);\r
+               $sql    = "REPLACE INTO ".TABLE_PREFIX."tests_questions_categories VALUES ($_POST[catid], $_SESSION[course_id], '$_POST[title]')";\r
+               $result = mysql_query($sql, $db);\r
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+               header('Location: question_cats.php');\r
+               exit;\r
+       } else {\r
+               $msg->addError(array('EMPTY_FIELDS', _AT('title')));\r
+       }\r
+}\r
+\r
+if (isset($_GET['catid'])) {\r
+       $sql = "SELECT title FROM ".TABLE_PREFIX."tests_questions_categories WHERE category_id=$_GET[catid]";\r
+       $result = mysql_query($sql, $db);\r
+       $row = mysql_fetch_assoc($result);\r
+\r
+       $_POST['title'] = $row['title'];\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$msg->printErrors();\r
+\r
+?>\r
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">\r
+<?php \r
+if (isset($_REQUEST['catid'])) {\r
+       echo '<input type="hidden" value="'.$_REQUEST['catid'].'" name="catid" />';\r
+}\r
+?>\r
+<div class="input-form">\r
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('create_category'); ?></legend>\r
+       <div class="row">\r
+               <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="cat"><?php echo _AT('title'); ?></label><br />\r
+               <input type="text" name="title" id="cat" value="<?php echo htmlspecialchars($_POST['title']); ?>" />\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" value="<?php echo _AT('save'); ?>"   name="submit" accesskey="s" />\r
+               <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />\r
+       </div>\r
+       </fieldset>\r
+</div>\r
+</form>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/question_db.php b/tools/tests/question_db.php
new file mode 100644 (file)
index 0000000..0c75161
--- /dev/null
@@ -0,0 +1,115 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'classes/testQuestions.class.php');
+authenticate(AT_PRIV_TESTS);
+
+// converts array entries to ints
+function intval_array ( & $value, $key) { $value = (int) $value; }
+
+if ( (isset($_GET['edit']) || isset($_GET['delete']) || isset($_GET['export']) || isset($_GET['preview']) || isset($_GET['add'])) && !isset($_GET['questions'])){
+       $msg->addError('NO_ITEM_SELECTED');
+} else if (isset($_GET['submit_create'], $_GET['question_type'])) {
+       header('Location: '.AT_BASE_HREF.'tools/tests/create_question_'.$addslashes($_GET['question_type']).'.php');
+       exit;
+} else if (isset($_GET['edit'])) {
+       $id  = current($_GET['questions']);
+       $num_selected = count($id);
+
+       if ($num_selected == 1) {
+               $ids = explode('|', $id[0], 2);
+               $o = TestQuestions::getQuestion($ids[1]);
+               if ($name = $o->getPrefix()) {
+                       header('Location: '.AT_BASE_HREF.'tools/tests/edit_question_'.$name.'.php?qid='.intval($ids[0]));
+                       exit;
+               } else {
+                       header('Location: '.AT_BASE_HREF.'tools/tests/index.php');
+                       exit;
+               }
+       } else {
+               $msg->addError('SELECT_ONE_ITEM');
+       }
+
+} else if (isset($_GET['delete'])) {
+       $id  = current($_GET['questions']);
+       $ids = array();
+       foreach ($_GET['questions'] as $category_questions) {
+               $ids = array_merge($ids, $category_questions);
+       }
+
+       array_walk($ids, 'intval_array');
+       $ids = implode(',',$ids);
+
+       header('Location: '.AT_BASE_HREF.'tools/tests/delete_question.php?qid='.$ids);
+       exit;
+} else if (isset($_GET['preview'])) {
+       $ids = array();
+       foreach ($_GET['questions'] as $category_questions) {
+               $ids = array_merge($ids, $category_questions);
+       }
+
+       array_walk($ids, 'intval_array');
+       $ids = implode(',',$ids);
+
+       header('Location: '.AT_BASE_HREF.'tools/tests/preview_question.php?qid='.$ids);
+       exit;
+} else if (isset($_GET['add'])) {
+       $id  = current($_GET['questions']);
+       $ids = explode('|', $id[0], 2);
+} else if (isset($_GET['export'])) {
+
+       $ids = array();
+       foreach ($_GET['questions'] as $category_questions) {
+               $ids = array_merge($ids, $category_questions);
+       }
+
+       array_walk($ids, 'intval_array');
+
+       test_question_qti_export($ids);
+
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+?>
+
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<input type="hidden" name="tid" value="<?php echo $tid; ?>" />
+
+<div class="input-form" style="width: 40%">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('create_new_question'); ?></legend>
+       <div class="row">
+               <label for="question"><?php echo _AT('create_new_question'); ?></label><br />
+               <?php $questions = TestQuestions::getQuestionPrefixNames(); ?>
+               <select name="question_type" class="dropdown" id="question" size="8">
+                       <?php foreach ($questions as $type => $name): ?>
+                               <option value="<?php echo $type; ?>"><?php echo $name; ?></option>
+                       <?php endforeach; ?>
+               </select>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit_create" value="<?php echo _AT('create'); ?>" />
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php $tid = 0; ?>
+
+<?php require(AT_INCLUDE_PATH.'html/tests_questions.inc.php'); ?>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/question_remove.php b/tools/tests/question_remove.php
new file mode 100644 (file)
index 0000000..fd3008f
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+$page = 'tests';
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+
+$tid = intval($_REQUEST['tid']);
+$qid = intval($_REQUEST['qid']);
+
+if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: questions.php?tid=' . $tid);
+       exit;
+} else if (isset($_POST['submit_yes'])) {
+       $sql    = "DELETE FROM ".TABLE_PREFIX."tests_questions_assoc WHERE question_id=$qid AND test_id=$tid";
+       $result = mysql_query($sql, $db);
+               
+       $msg->addFeedback('QUESTION_REMOVED');
+       header('Location: questions.php?tid=' . $tid);
+       exit;
+
+} /* else: */
+
+$_pages['tools/tests/questions.php?tid='.$_GET['tid']]['title_var']    = 'questions';
+$_pages['tools/tests/questions.php?tid='.$_GET['tid']]['parent']   = 'tools/tests/index.php';
+$_pages['tools/tests/questions.php?tid='.$_GET['tid']]['children'] = array('tools/tests/add_test_questions.php?tid='.$_GET['tid']);
+
+$_pages['tools/tests/add_test_questions.php?tid='.$_GET['tid']]['title_var']    = 'add_questions';
+$_pages['tools/tests/add_test_questions.php?tid='.$_GET['tid']]['parent']   = 'tools/tests/questions.php?tid='.$_GET['tid'];
+
+$_pages['tools/tests/question_remove.php']['title_var'] = 'remove_question';
+$_pages['tools/tests/question_remove.php']['parent']    = 'tools/tests/questions.php?tid='.$_GET['tid'];
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+unset($hidden_vars);
+$hidden_vars['qid'] = $_GET['qid'];
+$hidden_vars['tid'] = $_GET['tid'];
+$msg->addConfirm('REMOVE_TEST_QUESTION', $hidden_vars);
+
+$msg->printConfirm();
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/tools/tests/questions.php b/tools/tests/questions.php
new file mode 100644 (file)
index 0000000..fc6517b
--- /dev/null
@@ -0,0 +1,251 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+$page = 'tests';
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'classes/testQuestions.class.php');
+
+authenticate(AT_PRIV_TESTS);
+
+$_pages['tools/tests/questions.php']['title_var']    = 'questions';
+$_pages['tools/tests/questions.php']['parent']   = 'tools/tests/index.php';
+$_pages['tools/tests/questions.php']['children'] = array('tools/tests/add_test_questions.php?tid='.$_GET['tid']);
+
+$_pages['tools/tests/add_test_questions.php?tid='.$_GET['tid']]['title_var']    = 'add_questions';
+$_pages['tools/tests/add_test_questions.php?tid='.$_GET['tid']]['parent']   = 'tools/tests/questions.php?tid='.$_GET['tid'];
+
+$_pages['tools/tests/questions.php']['guide']    = 'instructor/?p=add_questions.php';
+
+
+$tid = intval($_REQUEST['tid']);
+
+if (isset($_POST['submit'])) {
+       $sql    = "SELECT test_id, random, num_questions FROM ".TABLE_PREFIX."tests WHERE test_id=$tid AND course_id=$_SESSION[course_id]";
+       $result = mysql_query($sql, $db);
+       if (!($row = mysql_fetch_assoc($result))) { exit; }
+
+       // #1760
+       // for each question that isn't required
+       if ($row['random']) {
+               foreach ($_POST['weight'] as $qid => $weight) {
+                       if ($_POST['required'][$qid]) { continue; }
+                       if (!$current_weight) { $current_weight = $weight; }
+
+                       if ($current_weight != $weight) {
+                               // the weights aren't the same.
+                               $msg->addError('RAND_TEST_Q_WEIGHT');
+                               break;
+                       }
+               }
+       }
+
+       if (!$msg->containsErrors()) {
+               //update the weights & order
+               $total_weight = 0;
+               $total_required_weight = 0;
+               $total_required_num = 0;
+               $optional_weight = 0;
+               $count = 1;
+               foreach ($_POST['weight'] as $qid => $weight) {
+                       $weight = $addslashes($weight);
+                       if ($_POST['required'][$qid]) {
+                               $required = 1;
+                       } else {
+                               $required = 0;
+                       }
+
+                       if ($row['random']) {
+                               if ($required) {
+                                       $total_required_weight += $weight;
+                                       $total_required_num++;
+                               } else {
+                                       $optional_weight = $weight; // what each optional question weights.
+                               }
+                       } else {
+                               $total_weight += $weight; // not random, so just sum the weights
+                       }
+                               
+                       if (!$row['random']) {
+                               $orders = $_POST['ordering'];
+                               asort($orders);
+                               $orders = array_keys($orders);
+                               $orders = array_flip($orders);
+                               $sql    = "UPDATE ".TABLE_PREFIX."tests_questions_assoc SET weight=$weight, required=$required, ordering=".($orders[$qid]+1)." WHERE question_id=$qid AND test_id=".$tid;
+                       } else {
+                               $sql    = "UPDATE ".TABLE_PREFIX."tests_questions_assoc SET weight=$weight, required=$required, ordering=$count WHERE question_id=$qid AND test_id=".$tid;
+                       }
+
+                       $result = mysql_query($sql, $db);
+                       $count++;
+               }
+
+               $num_questions_sql = '';
+               if ($row['random']) {
+                       $row['num_questions'] -= $total_required_num;
+                       if ($row['num_questions'] > 0) {
+                               // how much do the optional questions add up to: (assume they all weight the same)
+                               $total_weight = $total_required_weight + $optional_weight * $row['num_questions'];
+                       } else {
+                               $total_weight = $total_required_weight; // there are no more optional questions
+                               $num_questions_sql = ', num_questions='.$total_required_num;
+                       }
+               }
+
+
+               $sql    = "UPDATE ".TABLE_PREFIX."tests SET out_of='$total_weight' $num_questions_sql WHERE test_id=$tid";
+               $result = mysql_query($sql, $db);
+
+               $total_weight = 0;
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: '.$_SERVER['PHP_SELF'] .'?tid='.$tid);
+               exit;
+       }
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$sql   = "SELECT title, random FROM ".TABLE_PREFIX."tests WHERE test_id=$tid";
+$result        = mysql_query($sql, $db);
+$row   = mysql_fetch_assoc($result);
+echo '<h3>'._AT('questions_for').' '.AT_print($row['title'], 'tests.title').'</h3>';
+$random = $row['random'];
+
+$sql   = "SELECT count(*) as cnt FROM ".TABLE_PREFIX."tests_questions_assoc QA, ".TABLE_PREFIX."tests_questions Q WHERE QA.test_id=$tid AND QA.weight=0 AND QA.question_id=Q.question_id AND Q.type<>4";
+$result        = mysql_query($sql, $db);
+$row = mysql_fetch_array($result);
+if ($row['cnt']) {
+       $msg->printWarnings('QUESTION_WEIGHT');
+}
+
+$msg->printAll();
+
+$sql   = "SELECT * FROM ".TABLE_PREFIX."tests_questions Q, ".TABLE_PREFIX."tests_questions_assoc TQ WHERE Q.course_id=$_SESSION[course_id] AND Q.question_id=TQ.question_id AND TQ.test_id=$tid ORDER BY TQ.ordering";
+$result        = mysql_query($sql, $db);
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>?tid=<?php echo $tid; ?>" method="post" name="form">
+<input type="hidden" name="tid" value="<?php echo $tid; ?>" />
+<table class="data static" summary="" rules="rows">
+<thead>
+<tr>
+       <th scope="col"><?php echo _AT('num');      ?></th>
+       <th scope="col"><?php echo _AT('points');   ?></th>
+       <th scope="col"><?php echo _AT('order'); ?></th>
+       <th scope="col"><?php echo _AT('question'); ?></th>
+       <th scope="col"><?php echo _AT('type');     ?></th>
+       <th scope="col"><?php echo _AT('category'); ?></th>
+       <?php if ($random): ?>
+               <th scope="col"><?php echo _AT('required'); ?></th>
+       <?php endif; ?>
+       <th scope="col">&nbsp;</th>
+</tr>
+</thead>
+<?php
+if ($row = mysql_fetch_assoc($result)) {
+       $sql    = "SELECT title, category_id FROM ".TABLE_PREFIX."tests_questions_categories WHERE course_id=".$_SESSION['course_id'];
+       $cat_result     = mysql_query($sql, $db);
+       $cats    = array();
+       $cats[0] = _AT('cats_uncategorized');
+       while ($cat_row = mysql_fetch_assoc($cat_result)) {
+               $cats[$cat_row['category_id']] = $cat_row['title'];
+       }
+
+       do {
+               $count++;
+               echo '<tr>';
+               echo '<td class="row1" align="center"><strong>'.$count.'</strong></td>';
+               echo '<td class="row1" align="center">';
+               
+               if (isset($_POST['submit'])) {
+                       $row['weight'] = $_POST['weight'][$row['question_id']];
+                       $row['required'] = (isset($_POST['required'][$row['question_id']]) ? 1 : 0);
+               }
+
+               if ($row['type'] == 4) {
+                       echo ''._AT('na').'';
+                       echo '<input type="hidden" value="0" name="weight['.$row['question_id'].']" />';
+               } else {
+                       echo '<input type="text" value="'.$row['weight'].'" name="weight['.$row['question_id'].']" size="2" />';
+               }
+               echo '</td>';
+
+               if ($random) {
+                       echo '<td class="row1" align="center">'._AT('na').'</td>';
+               } else {
+                       echo '<td class="row1" align="center"><input type="text" name="ordering['.$row['question_id'].']" value="'.$row['ordering'].'" size="2" /></td>';
+               }
+
+               echo '<td class="row1">';
+               if ($strlen($row['question']) > 45) {
+                       echo htmlspecialchars(AT_print($substr($row['question'], 0, 43), 'tests_questions.question'), ENT_COMPAT, "UTF-8") . '...';
+               } else {
+                       echo AT_print(htmlspecialchars($row['question'], ENT_COMPAT, "UTF-8"), 'tests_questions.question');
+               }
+
+               echo '</td>';
+               echo '<td nowrap="nowrap">';
+               $o = TestQuestions::getQuestion($row['type']);
+               echo $o->printName();
+               echo '</td>';
+
+               $link = 'tools/tests/edit_question_'.$o->getPrefix().'.php?tid='.$tid.SEP.'qid='.$row['question_id'];
+
+               echo '<td align="center">'.$cats[$row['category_id']].'</td>';
+
+               if ($random) {
+                       echo '<td align="center" nowrap="nowrap"><input type="checkbox" name="required['.$row['question_id'].']" value="1"';
+                       if ($row['required']) {
+                               echo ' checked="checked"';
+                       }
+                       echo ' id="q'.$row['question_id'].'" /><label for="q'.$row['question_id'].'">'._AT('required').'</label></td>';
+               }
+
+               echo '<td nowrap="nowrap">';
+               echo '<a href="' . $link . '">' . _AT('edit').'</a> | ';
+               echo '<a href="tools/tests/question_remove.php?tid=' . $tid . SEP . 'qid=' . $row['question_id'] . '">' . _AT('remove') . '</a>';
+               echo '</td>';
+
+               echo '</tr>';
+       } while ($row = mysql_fetch_assoc($result));
+
+       //total weight
+       echo '<tfoot>';
+       echo '<tr><td>&nbsp;</td>';
+       echo '<td colspan="';
+       if ($random) {
+               echo 7;
+       } else {
+               echo 6;
+       }
+
+       echo '" align="left" nowrap="nowrap">';
+       echo '<input type="submit" value="'._AT('update').'" name="submit" /> </td>';
+       echo '</tr>';
+       echo '</tfoot>';
+} else {
+       echo '<tr><td colspan="';
+       if ($random) {
+               echo 7;
+       } else {
+               echo 6;
+       }
+
+       echo '" >'._AT('none_found').'</td></tr>';
+}
+
+echo '</table><br /></form>';
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/tools/tests/results.php b/tools/tests/results.php
new file mode 100644 (file)
index 0000000..dc5d198
--- /dev/null
@@ -0,0 +1,227 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_TESTS);
+
+$tid = intval($_REQUEST['tid']);
+
+
+if (isset($_GET['delete'], $_GET['id'])) {
+       header('Location:delete_result.php?tid='.$tid.SEP.'rid='.$_GET['id']);
+       exit;
+} else if (isset($_GET['edit'], $_GET['id'])) {
+       header('Location:view_results.php?tid='.$tid.SEP.'rid='.$_GET['id']);
+       exit;
+} else if (isset($_GET['edit']) && !$_GET['id'] && !$_GET['asc'] && !$_GET['desc'] && !$_GET['filter'] && !$_GET['reset_filter']) {
+       $msg->addError('NO_ITEM_SELECTED');
+}
+
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+if ($_GET['reset_filter']) {
+       unset($_GET);
+}
+
+$orders = array('asc' => 'desc', 'desc' => 'asc');
+$cols   = array('login' => 1, 'full_name' => 1, 'date_taken' => 1, 'fs' => 1, 'time_spent' => 1);
+
+if (isset($_GET['asc'])) {
+       $order = 'asc';
+       $col   = isset($cols[$_GET['asc']]) ? $_GET['asc'] : 'login';
+} else if (isset($_GET['desc'])) {
+       $order = 'desc';
+       $col   = isset($cols[$_GET['desc']]) ? $_GET['desc'] : 'login';
+} else {
+       // no order set
+       $order = 'asc';
+       $col   = 'login';
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if (isset($_GET['status']) && ($_GET['status'] != '') && ($_GET['status'] != 2)) {
+       if ($_GET['status'] == 0) {
+               $status = " AND R.final_score=''";
+       } else {
+               $status = " AND R.final_score<>''";
+       }
+       $page_string .= SEP.'status='.$_GET['status'];
+} else {
+       $status = '';
+}
+
+//get test info
+$sql   = "SELECT out_of, anonymous, random, title FROM ".TABLE_PREFIX."tests WHERE test_id=$tid AND course_id=$_SESSION[course_id]";
+$result        = mysql_query($sql, $db);
+if (!($row = mysql_fetch_array($result))){
+       $msg->printErrors('ITEM_NOT_FOUND');
+       require (AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+$out_of = $row['out_of'];
+$anonymous = $row['anonymous'];
+$random = $row['random'];
+
+//count total
+$sql   = "SELECT count(*) as cnt FROM ".TABLE_PREFIX."tests_results R LEFT JOIN ".TABLE_PREFIX."members M USING (member_id) WHERE R.test_id=$tid AND R.status=1";
+$result        = mysql_query($sql, $db);
+$row   = mysql_fetch_array($result);
+$num_sub = $row['cnt'];
+
+//get results based on filtre and sorting
+if ($anonymous == 1) {
+       $sql    = "SELECT R.*, (UNIX_TIMESTAMP(R.end_time) - UNIX_TIMESTAMP(R.date_taken)) AS time_spent, '<em>"._AT('anonymous')."</em>' AS login FROM ".TABLE_PREFIX."tests_results R WHERE R.test_id=$tid AND R.status=1 $status ORDER BY $col $order";
+} else {       
+       $sql    = "SELECT R.*, login, (UNIX_TIMESTAMP(R.end_time) - UNIX_TIMESTAMP(R.date_taken)) AS time_spent, CONCAT(first_name, ' ', second_name, ' ', last_name) AS full_name, R.final_score+0.0 AS fs FROM ".TABLE_PREFIX."tests_results R LEFT JOIN  ".TABLE_PREFIX."members M USING (member_id) WHERE R.test_id=$tid AND R.status=1 $status ORDER BY $col $order, R.final_score $order";
+}
+
+$result = mysql_query($sql, $db);
+if ($anonymous == 1) {
+       $guest_text = '<em>'._AT('anonymous').'</em>';
+} else {
+       $guest_text = '- '._AT('guest').' -';
+}
+while ($row = mysql_fetch_assoc($result)) {
+       $row['full_name'] = $row['full_name'] ? $row['full_name'] : $guest_text;
+       $row['login']     = $row['login']     ? $row['login']     : $guest_text;
+       $rows[$row['result_id']] = $row;
+}
+
+$num_results = mysql_num_rows($result);
+
+//count unmarked: no need to do this query if filtre is already getting unmarked
+if (isset($_GET['status']) && ($_GET['status'] != '') && ($_GET['status'] == 0)) {
+       $num_unmarked = $num_results;
+} else {
+       $sql            = "SELECT count(*) as cnt FROM ".TABLE_PREFIX."tests_results R, ".TABLE_PREFIX."members M WHERE R.test_id=$tid AND R.status=1 AND R.member_id=M.member_id AND R.final_score=''";
+       $result = mysql_query($sql, $db);
+       $row = mysql_fetch_array($result);
+       $num_unmarked = $row['cnt'];
+}
+
+?>
+<h3><?php echo AT_print($row['title'], 'tests.title'); ?></h3><br />
+
+<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+       <input type="hidden" name="tid" value="<?php echo $tid; ?>" />
+
+       <div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('filter'); ?></legend>
+               <div class="row">
+                       <h3><?php echo _AT('results_found', $num_results); ?></h3>
+               </div>
+
+               <div class="row">
+                       <?php echo _AT('status'); ?><br />
+                       <input type="radio" name="status" value="1" id="s0" <?php if ($_GET['status'] == 1) { echo 'checked="checked"'; } ?> /><label for="s0"><?php echo _AT('marked_label', $num_sub - $num_unmarked); ?></label> 
+
+                       <input type="radio" name="status" value="0" id="s1" <?php if ($_GET['status'] == 0) { echo 'checked="checked"'; } ?> /><label for="s1"><?php echo _AT('unmarked_label', $num_unmarked); ?></label> 
+
+                       <input type="radio" name="status" value="2" id="s2" <?php if (!isset($_GET['status']) || ($_GET['status'] != 0 && $_GET['status'] != 1)) { echo 'checked="checked"'; } ?> /><label for="s2"><?php echo _AT('all_label', $num_sub); ?></label> 
+
+               </div>
+
+               <div class="row buttons">
+                       <input type="submit" name="filter" value="<?php echo _AT('filter'); ?>" />
+                       <input type="submit" name="reset_filter" value="<?php echo _AT('reset_filter'); ?>" />
+               </div>
+               </fieldset>
+       </div>
+</form>
+
+<form name="form" method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<input type="hidden" name="tid" value="<?php echo $tid; ?>" />
+
+<table class="data" summary="" rules="cols">
+<colgroup>
+       <?php if ($col == 'login'): ?>
+               <col />
+               <col class="sort" />
+               <col span="4" />
+       <?php elseif ($col == 'full_name'): ?>
+               <col span="2" />
+               <col class="sort" />
+               <col span="3" />
+       <?php elseif($col == 'date_taken'): ?>
+               <col span="3" />
+               <col class="sort" />
+               <col span="2" />
+       <?php elseif($col == 'time_spent'): ?>
+               <col span="4" />
+               <col class="sort" />
+               <col span="1" />
+       <?php elseif($col == 'fs'): ?>
+               <col span="5" />
+               <col class="sort" />
+       <?php endif; ?>
+</colgroup>
+<thead>
+<tr>
+       <th scope="col" width="1%">&nbsp;</th>
+       <th scope="col"><a href="tools/tests/results.php?tid=<?php echo $tid.$page_string.SEP.$orders[$order]; ?>=login"><?php echo _AT('login_name'); ?></a></th>
+       <th scope="col"><a href="tools/tests/results.php?tid=<?php echo $tid.$page_string.SEP.$orders[$order]; ?>=full_name"><?php echo _AT('full_name'); ?></a></th>
+       <th scope="col"><a href="tools/tests/results.php?tid=<?php echo $tid.$page_string.SEP.$orders[$order]; ?>=date_taken"><?php echo _AT('date_taken'); ?></a></th>
+       <th scope="col"><a href="tools/tests/results.php?tid=<?php echo $tid.$page_string.SEP.$orders[$order]; ?>=time_spent"><?php echo _AT('time_spent'); ?></a></th>
+       <th scope="col"><a href="tools/tests/results.php?tid=<?php echo $tid.$page_string.SEP.$orders[$order]; ?>=fs"><?php echo _AT('mark'); ?></a></th>
+</tr>
+</thead>
+<tfoot>
+<tr>
+       <td colspan="6"><input type="submit" name="edit" value="<?php echo _AT('view_mark_test'); ?>" /> <input type="submit" name="delete" value="<?php echo _AT('delete'); ?>" /></td>
+</tr>
+</tfoot>
+<tbody>
+<?php if ($rows): ?>
+       <?php foreach ($rows as $row): ?>
+               <tr onmousedown="document.form['r<?php echo $row['result_id']; ?>'].checked = true;rowselect(this);" id="r_<?php echo $row['result_id']; ?>">
+                       <td><input type="radio" name="id" value="<?php echo $row['result_id']; ?>" id="r<?php echo $row['result_id']; ?>" /></td>
+                       <td><label for="r<?php echo $row['result_id']; ?>"><?php echo $row['login']; ?></label></td>
+                       <td><?php 
+                               if ($anonymous == 1){
+                                       echo AT_print($guest_text, 'members.full_name');
+                               } else {
+                                       echo AT_print(get_display_name($row['member_id']), 'members.full_name'); /*$row['full_name'] */ 
+                               }
+                               ?></td>
+                       <td><?php $startend_date_format=_AT('startend_date_format'); echo AT_date( $startend_date_format, $row['date_taken'], AT_DATE_MYSQL_DATETIME); ?></td>
+                       <td><?php echo get_human_time($row['time_spent']); ?></td>
+
+                       <td align="center">
+                               <?php if ($out_of) {
+                                       if ($random) {
+                                               $out_of = get_random_outof($tid, $row['result_id']);
+                                       }
+
+                                       if ($row['final_score'] != '') { 
+                                               echo $row['final_score'].'/'.$out_of;
+                                       } else {
+                                               echo _AT('unmarked');
+                                       }
+                               } else {
+                                       echo _AT('na');
+                               }
+                               ?>
+                       </td>
+               </tr>
+       <?php endforeach; ?>
+<?php else: ?>
+       <tr>
+               <td colspan="6"><?php echo _AT('none_found'); ?></td>
+       </tr>
+<?php endif; ?>
+</tbody>
+</table>
+</form>
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tests/results_all.php b/tools/tests/results_all.php
new file mode 100644 (file)
index 0000000..6a686ae
--- /dev/null
@@ -0,0 +1,362 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+
+// Validate date
+function isValidDate($date)
+{
+    if (preg_match("/^(\d{4})-(\d{2})-(\d{2})$/", $date, $matches)) 
+    {
+        if (checkdate($matches[2], $matches[3], $matches[1])) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+function display_test_info($row)
+{
+               global $random, $num_questions, $total_weight, $questions, $total_score, $table_content, $csv_content;
+               global $passscore, $passpercent;
+               global $q_sql, $db;
+               
+               $row['login'] = $row['login'] ? $row['login'] : '- '._AT('guest').' -';
+               $table_content .= '<tr>';
+                       
+               if($anonymous == 1){
+                               $table_content .= '<td align="center">'._AT('anonymous').'</td>';
+                               $csv_content .= quote_csv(_AT('anonymous')).', ';
+               }else{
+                               $table_content .= '<td align="center">'.$row['login'].'</td>';
+                               $csv_content .= quote_csv($row['login']).', ';
+               }
+               $startend_date_format=_AT('startend_date_format');
+               $table_content .= '<td align="center">'.AT_date( $startend_date_format, $row['date_taken'], AT_DATE_MYSQL_DATETIME).'</td>';
+               $csv_content .= quote_csv($row['date_taken']).', ';
+
+               if ($passscore <> 0)
+               {
+                       $table_content .= '<td align="center">'.$passscore.'</td>';
+                       $csv_content .= $passscore.', ';
+               }
+               elseif ($passpercent <> 0)
+               {
+                       $table_content .= '<td align="center">'.$passpercent.'%</td>';
+                       $csv_content .= $passpercent . '%, ';
+               }
+
+               $table_content .= '<td align="center">'.$row['final_score'].'/'.$total_weight.'</td>';
+               $csv_content .= $row['final_score'].'/'.$total_weight;
+
+               $total_score += $row['final_score'];
+
+               $answers = array(); /* need this, because we dont know which order they were selected in */
+
+               //get answers for this test result
+               $sql = "SELECT question_id, score FROM ".TABLE_PREFIX."tests_answers WHERE result_id=$row[result_id] AND question_id IN ($q_sql)";
+               $result2 = mysql_query($sql, $db);
+               while ($row2 = mysql_fetch_assoc($result2)) {
+                       $answers[$row2['question_id']] = $row2['score'];
+               }
+
+               //print answers out for each question
+               for($i = 0; $i < $num_questions; $i++) {
+                       $questions[$i]['score'] += $answers[$questions[$i]['question_id']];
+                       $table_content .= '<td align="center">';
+                       if ($answers[$questions[$i]['question_id']] == '') {
+                               $table_content .= '<span style="color:#ccc;">-</span>';
+                               $csv_content .= ', -';
+                       } else {
+                               $table_content .= $answers[$questions[$i]['question_id']];
+                               $csv_content .= ', '.$answers[$questions[$i]['question_id']];
+                               
+                               if ($random) {
+                                       $questions[$i]['count']++;
+                               }
+                       }
+                       $table_content .= '</td>';
+               }
+
+               $table_content .= '</tr>';
+               $csv_content .= "\n";
+}
+
+function quote_csv($line) {
+       $line = str_replace('"', '""', $line);
+       $line = str_replace("\n", '\n', $line);
+       $line = str_replace("\r", '\r', $line);
+       $line = str_replace("\x00", '\0', $line);
+
+       return '"'.$line.'"';
+}
+
+$tid = intval($_REQUEST['tid']);
+
+$_pages['tools/tests/results_all.php']['title_var']  = 'mark_statistics';
+$_pages['tools/tests/results_all.php']['parent'] = 'tools/tests/results_all_quest.php?tid='.$tid;
+
+$_pages['tools/tests/results_all_quest.php?tid='.$tid]['title_var'] = 'question_statistics';
+$_pages['tools/tests/results_all_quest.php?tid='.$tid]['parent'] = 'tools/tests/index.php';
+$_pages['tools/tests/results_all_quest.php?tid='.$tid]['children'] = array('tools/tests/results_all.php');
+
+if (isset($_POST['reset_filter'])) {
+       unset($_POST['start_date']);
+       unset($_POST['end_date']);
+       unset($_POST['student_type']);
+}
+
+if (!isset($_POST['student_type'])) {
+       $_POST['student_type'] = 'all';
+}
+
+if (isset($_POST["start_date"])) $start_date = trim($_POST["start_date"]);
+if (isset($_POST["end_date"]))$end_date = trim($_POST["end_date"]);
+
+if ($start_date != "" && !isValidDate($start_date)) {
+       $msg->addError('START_DATE_INVALID');
+}
+
+if ($end_date != "" && !isValidDate($end_date)) {
+       $msg->addError('END_DATE_INVALID');
+}
+
+$table_content = "";
+$csv_content = "";
+
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+$sql   = "SELECT title, out_of, result_release, randomize_order, passscore, passpercent FROM ".TABLE_PREFIX."tests WHERE test_id=$tid";
+$result        = mysql_query($sql, $db);
+$row = mysql_fetch_array($result);
+$out_of = $row['out_of'];
+$random = $row['randomize_order'];
+$passscore = $row['passscore'];
+$passpercent = $row['passpercent'];
+$test_title = str_replace (' ', '_', str_replace(array('"', '<', '>'), '', $row['title']));
+
+$table_content .= '<h3>'.$row['title'].'</h3><br />';
+
+$sql   = "SELECT TQ.*, TQA.* FROM ".TABLE_PREFIX."tests_questions TQ INNER JOIN ".TABLE_PREFIX."tests_questions_assoc TQA USING (question_id) WHERE TQ.course_id=$_SESSION[course_id] AND TQA.test_id=$tid ORDER BY TQA.ordering, TQA.question_id";
+
+//$sql = "SELECT * FROM ".TABLE_PREFIX."tests_questions Q WHERE Q.test_id=$tid AND Q.course_id=$_SESSION[course_id] ORDER BY ordering";
+$result        = mysql_query($sql, $db);
+$questions = array();
+$total_weight = 0;
+$i = 0;
+
+while ($row = mysql_fetch_assoc($result)) {
+       $row['score']   = 0;
+       $questions[$i]  = $row;
+       $questions[$i]['count'] = 0;
+       $q_sql .= $row['question_id'].',';
+       $total_weight += $row['weight'];
+       $i++;
+}
+$q_sql = substr($q_sql, 0, -1);
+$num_questions = count($questions);
+
+//get all the marked tests for this test
+$sql   = "SELECT R.*, M.login FROM ".TABLE_PREFIX."tests_results R LEFT JOIN ".TABLE_PREFIX."members M USING (member_id) WHERE R.status=1 AND R.test_id=$tid AND R.final_score<>'' ";
+
+if ($start_date)     $sql .= " AND R.date_taken >= '" . $start_date . "'";
+if ($end_date)     $sql .= " AND R.date_taken <= '" . $end_date . "'";
+
+$sql .= " ORDER BY M.login, R.date_taken";
+
+$result = mysql_query($sql, $db);
+$num_results = mysql_num_rows($result);
+if ($row = mysql_fetch_assoc($result)) {
+       $total_score = 0;
+
+       // generate table/csv header line
+       $table_content .= '<table class="data static" summary="" style="width: 90%" rules="cols">';
+       $table_content .= '<thead>';
+       $table_content .= '<tr>';
+       $table_content .= '<th scope="col">'._AT('login_name').'</th>';
+       $table_content .= '<th scope="col">'._AT('date_taken').'</th>';
+       $table_content .= '<th scope="col">'._AT('pass_score').'</th>';
+       $table_content .= '<th scope="col">'._AT('mark').'</th>';
+
+       $csv_content .= quote_csv(_AT('login_name')).', ';
+       $csv_content .= quote_csv(_AT('date_taken')).', ';
+       $csv_content .= quote_csv(_AT('pass_score')).', ';
+       $csv_content .= quote_csv(_AT('mark'));
+
+       for($i = 0; $i< $num_questions; $i++) {
+               $table_content .= '<th scope="col">Q'.($i+1).' /'.$questions[$i]['weight'].'</th>';
+
+               $csv_content .= ', '.quote_csv('Q'.($i+1).'/'.$questions[$i]['weight']);
+       }
+       $table_content .= '</tr>';
+       $table_content .= '</thead>';
+       $table_content .= '<tbody>';
+       
+       $csv_content .= "\n";
+       
+       $sql2   = "SELECT anonymous FROM ".TABLE_PREFIX."tests WHERE test_id=$tid AND course_id=$_SESSION[course_id]";
+       $result2        = mysql_query($sql2, $db);
+       while($row2 =mysql_fetch_array($result2)){
+                       $anonymous = $row2['anonymous'];
+       }
+
+       do {
+               if ($random) {
+                       $total_weight = get_random_outof($row['test_id'], $row['result_id']);
+               }
+               
+               // display passed student
+               if ($_POST['student_type'] == 'all' ||
+                   $_POST['student_type'] == 'passed' &&
+                   (($passscore<>0 && $row['final_score']>=$passscore) ||
+                          ($passpercent<>0 && ($row['final_score']/$total_weight*100)>=$passpercent)))
+                       display_test_info($row);
+               elseif ($_POST['student_type'] == 'all' ||
+                       $_POST['student_type'] == 'failed' &&
+                       (($passscore<>0 && $row['final_score']<$passscore) ||
+                              ($passpercent<>0 && ($row['final_score']/$total_weight*100)<$passpercent)))
+                       display_test_info($row);
+               elseif ($_POST['student_type'] == 'all')
+                       display_test_info($row);
+
+       } while ($row = mysql_fetch_assoc($result));
+       $table_content .= '</tbody>';
+
+       $table_content .= '<tfoot>';
+       $table_content .= '<tr>';
+       $table_content .= '<td colspan="3" align="right"><strong>'._AT('average').':</strong></td>';
+       $table_content .= '<td align="center"><strong>'.number_format($total_score/$num_results, 1).'</strong></td>';
+
+       for($i = 0; $i < $num_questions; $i++) {
+               $table_content .= '<td class="row1" align="center"><strong>';
+                       if ($random) {
+                               $count = $questions[$i]['count'];
+                       }
+                       if ($questions[$i]['weight'] && $count) {
+                                       $table_content .= number_format($questions[$i]['score']/$count, 1);
+                       } else {
+                               $table_content .= '0.0';
+                       }
+                       $table_content .= '</strong></td>';
+       }
+       $table_content .= '</tr>';
+
+       $table_content .= '<tr>';
+       $table_content .= '<td colspan="3">&nbsp;</td>';
+       $table_content .= '<td align="center"><strong>';
+       if ($total_weight) {
+               $table_content .= number_format($total_score/$num_results/$total_weight*100, 1).'%';
+       }
+       $table_content .= '</strong></td>';
+
+       for($i = 0; $i < $num_questions; $i++) {
+               $table_content .= '<td align="center"><strong>';
+                       if ($random) {
+                               $count = $questions[$i]['count'];
+                       }
+
+                       if ($questions[$i]['weight'] && $count) {
+                               $table_content .= number_format($questions[$i]['score']/$count/$questions[$i]['weight']*100, 1).'%';
+                       } else {
+                               $table_content .= '00.0%';
+                       }
+               $table_content .= '</strong></td>';
+       }
+       $table_content .= '</tr>';
+       $table_content .= '</tfoot>';
+} else {
+       $table_content .= '<em>'._AT('no_results_available').'</em>';
+       $no_result_found = true;
+}
+
+// header info has to be in front of any other output, so download
+// before display page
+if ($_POST['download']){
+       if ($no_result_found)
+       {
+               require (AT_INCLUDE_PATH.'header.inc.php');
+               $msg->printErrors('ITEM_NOT_FOUND');
+               require (AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+
+       header('Content-Type: application/x-excel');
+       header('Content-Disposition: inline; filename="'.$test_title.'.csv"');
+       header('Expires: 0');
+       header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+       header('Pragma: public');
+       
+       echo $csv_content;
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$msg->printErrors();
+
+?>
+<script type='text/javascript' src='calendar.js'></script>
+
+<div class="input-form">
+<form method="post" action="<?php echo $_SERVER['PHP_SELF'] . '?tid='.$tid; ?>">
+       <div class="row">
+               <label for="start_date"><?php echo _AT('start_date'); ?>(YYYY-MM-DD)</label>
+               <input id='start_date' name='start_date' type='text' value='<?php echo $start_date?>' />
+               <img src='images/calendar.gif' style="vertical-align: middle; cursor: pointer;" onclick="scwShow(scwID('start_date'),event);" />
+
+               <label for="end_date"><?php echo _AT('end_date'); ?>(YYYY-MM-DD)</label>
+               <input id='end_date' name='end_date' type='text' value='<?php echo $end_date?>' />
+               <img src='images/calendar.gif' style="vertical-align: middle; cursor: pointer;" onclick="scwShow(scwID('end_date'),event);" />
+       </div>
+
+<?php
+// display options for passed/failed students when pass score/percentage is defined
+if ($passscore <> 0 || $passpercent <> 0)
+{
+?>
+       <div class="row">
+               <?php echo _AT('students'); ?><br />
+               <input type="radio" name="student_type" value="all" id="all" <?php if ($_POST['student_type'] == 'all'){echo 'checked="true"';} ?> />
+               <label for="all" title="<?php echo _AT('all_students');  ?>"><?php echo _AT('all_students'); ?></label>
+
+               <input type="radio" name="student_type" value="passed" id="passed" <?php if ($_POST['student_type'] == 'passed'){echo 'checked="true"';} ?> />
+               <label for="passed" title="<?php echo _AT('all_passed_students');  ?>"><?php echo _AT('all_passed_students'); ?></label>
+
+               <input type="radio" name="student_type" value="failed" id="failed" <?php if ($_POST['student_type'] == 'failed'){echo 'checked="true"';} ?> />
+               <label for="failed" title="<?php echo _AT('all_failed_students');  ?>"><?php echo _AT('all_failed_students'); ?></label>
+       </div>
+<?php
+}
+?>
+
+       <div class="row buttons">
+               <input type="submit" name="filter" value="<?php echo _AT('filter'); ?>" />
+               <input type="submit" name="reset_filter" value="<?php echo _AT('reset_filter'); ?>" />
+               <input type="submit" name="download" value="<?php echo _AT('download_test_csv'); ?>" />
+               <input type="hidden" name="test_id" value="<?php echo $tid; ?>" />
+       </div>
+</form>
+</div>
+
+
+<?php 
+echo $table_content;
+?>
+
+</table>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
diff --git a/tools/tests/results_all_csv.php b/tools/tests/results_all_csv.php
new file mode 100644 (file)
index 0000000..2be15f3
--- /dev/null
@@ -0,0 +1,136 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+authenticate(AT_PRIV_TESTS);
+
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+
+function quote_csv($line) {
+       $line = str_replace('"', '""', $line);
+       $line = str_replace("\n", '\n', $line);
+       $line = str_replace("\r", '\r', $line);
+       $line = str_replace("\x00", '\0', $line);
+
+       return '"'.$line.'"';
+}
+
+$tid = intval($_GET['tid']);
+
+//get test info
+$sql   = "SELECT title, randomize_order FROM ".TABLE_PREFIX."tests WHERE test_id=$tid AND course_id=$_SESSION[course_id]";
+$result        = mysql_query($sql, $db);
+
+if (!($row = mysql_fetch_array($result))){
+       require (AT_INCLUDE_PATH.'header.inc.php');
+       $msg->printErrors('ITEM_NOT_FOUND');
+       require (AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+$test_title = str_replace(array('"', '<', '>'), '', $row['title']);
+$test_title = str_replace (' ', '_', $test_title);
+$random = $row['randomize_order'];
+
+//get test questions
+$sql   = "SELECT TQ.*, TQA.* FROM ".TABLE_PREFIX."tests_questions TQ INNER JOIN ".TABLE_PREFIX."tests_questions_assoc TQA USING (question_id) WHERE TQ.course_id=$_SESSION[course_id] AND TQA.test_id=$tid ORDER BY TQA.ordering, TQA.question_id";
+$result        = mysql_query($sql, $db);
+$num_questions = mysql_num_rows($result);
+$questions = array();
+$total_weight = 0;
+$i=0;
+while ($row = mysql_fetch_array($result)) {
+       $row['score']   = 0;
+       $questions[$i]  = $row;
+       $questions[$i]['count'] = 0;
+       $q_sql .= $row['question_id'].',';
+       $total_weight += $row['weight'];
+       $i++;
+}
+$q_sql = substr($q_sql, 0, -1);
+
+
+header('Content-Type: application/x-excel');
+header('Content-Disposition: inline; filename="'.$test_title.'.csv"');
+header('Expires: 0');
+header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+header('Pragma: public');
+
+$nl = "\n";
+
+echo quote_csv(_AT('login_name')).', ';
+echo quote_csv(_AT('date_taken')).', ';
+echo quote_csv(_AT('mark'));
+for($i = 0; $i< $num_questions; $i++) {
+       echo ', '.quote_csv('Q'.($i+1).'/'.$questions[$i]['weight']);
+}
+echo $nl;
+
+$guest_text = '- '._AT('guest').' -';
+
+//get test results
+$sql   = "SELECT R.*, M.login FROM ".TABLE_PREFIX."tests_results R LEFT JOIN ".TABLE_PREFIX."members M USING (member_id) WHERE R.status=1 AND R.test_id=$tid AND R.final_score<>'' ORDER BY M.login, R.date_taken";
+$result = mysql_query($sql, $db);
+$num_results = mysql_num_rows($result);
+
+
+
+
+
+if ($row = mysql_fetch_array($result)) {
+       $sql2   = "SELECT anonymous FROM ".TABLE_PREFIX."tests WHERE test_id=$tid AND course_id=$_SESSION[course_id]";
+       $result2        = mysql_query($sql2, $db);
+       while($row2 =mysql_fetch_array($result2)){
+                       $anonymous = $row2['anonymous'];
+       }
+
+       do {
+               $row['login']     = $row['login']     ? $row['login']     : $guest_text;
+               if($anonymous ==1){
+                               echo quote_csv(_AT('anonymous')).', ';
+               }else{
+                               echo quote_csv($row['login']).', ';
+               }
+               echo quote_csv($row['date_taken']).', ';
+
+               if ($random) {
+                       $total_weight = get_random_outof($row['test_id'], $row['result_id']);
+               }
+               echo $row['final_score'].'/'.$total_weight;
+
+               $answers = array(); /* need this, because we dont know which order they were selected in */
+               $sql = "SELECT question_id, score FROM ".TABLE_PREFIX."tests_answers WHERE result_id=$row[result_id] AND question_id IN ($q_sql)";
+               $result2 = mysql_query($sql, $db);
+               while ($row2 = mysql_fetch_array($result2)) {
+                       $answers[$row2['question_id']] = $row2['score'];
+               }
+               for($i = 0; $i < $num_questions; $i++) {
+                       $questions[$i]['score'] += $answers[$questions[$i]['question_id']];
+                       if ($answers[$questions[$i]['question_id']] == '') {
+                               echo ', -';
+                       } else {
+                               echo ', '.$answers[$questions[$i]['question_id']];
+                               if ($random) {
+                                       $questions[$i]['count']++;
+                               }
+                       }                       
+               }
+
+               echo $nl;
+       } while ($row = mysql_fetch_array($result));
+
+       echo $nl;
+}
+
+?>
diff --git a/tools/tests/results_all_quest.php b/tools/tests/results_all_quest.php
new file mode 100644 (file)
index 0000000..c513f27
--- /dev/null
@@ -0,0 +1,93 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+require(AT_INCLUDE_PATH.'classes/testQuestions.class.php');\r
+\r
+authenticate(AT_PRIV_TESTS);\r
+\r
+\r
+$tid = intval($_REQUEST['tid']);\r
+\r
+$_pages['tools/tests/results_all_quest.php']['title_var']  = 'question_statistics';\r
+$_pages['tools/tests/results_all_quest.php']['parent']  = 'tools/tests/index.php';\r
+$_pages['tools/tests/results_all_quest.php']['children'] = array('tools/tests/results_all.php?tid='.$tid);\r
+\r
+$_pages['tools/tests/results_all.php?tid='.$tid]['title_var']  = 'mark_statistics';\r
+$_pages['tools/tests/results_all.php?tid='.$tid]['parent'] = 'tools/tests/results_all_quest.php';\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$sql   = "SELECT TQ.*, TQA.* FROM ".TABLE_PREFIX."tests_questions TQ INNER JOIN ".TABLE_PREFIX."tests_questions_assoc TQA USING (question_id) WHERE TQ.course_id=$_SESSION[course_id] AND TQA.test_id=$tid ORDER BY TQA.ordering, TQA.question_id";\r
+$result        = mysql_query($sql, $db);\r
+$questions = array();\r
+while ($row = mysql_fetch_array($result)) {\r
+       $row['score']   = 0;\r
+       $questions[]    = $row;\r
+       $q_sql .= $row['question_id'].',';\r
+}\r
+$q_sql = substr($q_sql, 0, -1);\r
+$num_questions = count($questions);\r
+\r
+//check if survey\r
+$sql   = "SELECT out_of, title, randomize_order FROM ".TABLE_PREFIX."tests WHERE test_id=$tid";\r
+$result = mysql_query($sql, $db);\r
+$row = mysql_fetch_assoc($result);\r
+$tt = $row['title'];\r
+$random = $row['randomize_order'];\r
+\r
+echo '<h3>'.$row['title'].'</h3><br />';\r
+\r
+//get all the questions in this test, store them\r
+$sql   = "SELECT TQ.*, TQA.* FROM ".TABLE_PREFIX."tests_questions TQ INNER JOIN ".TABLE_PREFIX."tests_questions_assoc TQA USING (question_id) WHERE TQ.course_id=$_SESSION[course_id] AND TQA.test_id=$tid ORDER BY TQA.ordering, TQA.question_id";\r
+\r
+$result = mysql_query($sql, $db);\r
+$questions = array();  \r
+while ($row = mysql_fetch_assoc($result)) {\r
+       $questions[$row['question_id']] = $row;\r
+}\r
+$long_qs = substr($long_qs, 0, -1);\r
+\r
+//get the answers:  count | q_id | answer\r
+$sql = "SELECT count(*), A.question_id, A.answer, A.score\r
+               FROM ".TABLE_PREFIX."tests_answers A, ".TABLE_PREFIX."tests_results R\r
+               WHERE R.status=1 AND R.result_id=A.result_id AND R.final_score<>'' AND R.test_id=$tid\r
+               GROUP BY A.question_id, A.answer\r
+               ORDER BY A.question_id, A.answer";\r
+$result = mysql_query($sql, $db);\r
+\r
+echo '<img src="images/checkmark.gif" alt="'._AT('correct_answer').'" />- '._AT('correct_answer').'<br /></p>';\r
+\r
+$ans = array();        \r
+while ($row = mysql_fetch_assoc($result)) {\r
+       $ans[$row['question_id']][$row['answer']] = array('count'=>$row['count(*)'], 'score'=>$row['score']);\r
+}\r
+\r
+//print out rows\r
+foreach ($questions as $q_id => $q) {\r
+       /* for random: num_results is going to be specific to each question.\r
+        * This is a randomized test which means that it is possible each question has been answered a \r
+        * different number of times.  Statistics are therefore based on the number of times each \r
+        * question was answered, not the number of times the test has been taken.\r
+        */\r
+\r
+       //catch random unanswered\r
+       if($ans[$q_id]) {\r
+               $obj = TestQuestions::getQuestion($q['type']);\r
+               $obj->displayResultStatistics($q, $ans[$q_id]);\r
+       }\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/tools/tests/results_quest_long.php b/tools/tests/results_quest_long.php
new file mode 100644 (file)
index 0000000..f8baa01
--- /dev/null
@@ -0,0 +1,75 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+$page = 'tests';\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+authenticate(AT_PRIV_TESTS);\r
+$tid = $_REQUEST['tid'];\r
+\r
+$_pages['tools/tests/results_quest_long.php']['title_var']  = 'view_responses';\r
+$_pages['tools/tests/results_quest_long.php']['parent'] = 'tools/tests/results_all_quest.php?tid='.$tid;\r
+\r
+$_pages['tools/tests/results_all_quest.php?tid='.$tid]['title_var']  = 'question_statistics';\r
+$_pages['tools/tests/results_all_quest.php?tid='.$tid]['parent']  = 'tools/tests/index.php';\r
+$_pages['tools/tests/results_all_quest.php?tid='.$tid]['children'] = array('tools/tests/results_all.php?tid='.$tid);\r
+\r
+$_pages['tools/tests/results_all.php?tid='.$tid]['title_var']  = 'mark_statistics';\r
+$_pages['tools/tests/results_all.php?tid='.$tid]['parent']  = 'tools/tests/results_all_quest.php';\r
+\r
+\r
+if ($_POST['back']) {\r
+       header('Location: results_all_quest.php?tid='.$tid);\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$sql   = "SELECT title FROM ".TABLE_PREFIX."tests WHERE test_id=$_GET[tid]";\r
+$result = mysql_query($sql, $db);\r
+$row = mysql_fetch_array($result);\r
+\r
+echo '<form method="post" action="'.$_SERVER['PHP_SELF'].'">';\r
+echo '<input type="hidden" name="tid" value="'.$tid.'">';\r
+\r
+echo '<div class="input-form">';\r
+echo '<h2>'.AT_print($row['title'], 'tests.title').'</h2>';\r
+\r
+echo '<br /><p>'._AT('response_text').' <strong>'.AT_print(urldecode($_GET['q']), 'tests_questions.question').'</strong></p>';\r
+\r
+//get the answers\r
+$sql = "SELECT count(*), A.answer\r
+               FROM ".TABLE_PREFIX."tests_answers A, ".TABLE_PREFIX."tests_results R\r
+               WHERE A.question_id=".$_GET['qid']." AND R.result_id=A.result_id AND R.final_score<>'' AND R.test_id=".$_GET['tid']."\r
+               GROUP BY A.answer\r
+               ORDER BY A.answer";\r
+\r
+$result = mysql_query($sql, $db);\r
+\r
+while ($row = mysql_fetch_assoc($result)) {\r
+       if ($row['answer'] != -1 && $row['answer'] != '') {\r
+               echo '<div class="row">';\r
+               echo '-'.AT_print($row['answer'], 'tests_answers.answer');\r
+               echo '</div>';\r
+       }\r
+} \r
+\r
+echo '<div class="row buttons">';\r
+       echo '<input type="submit" value="'._AT('back').'" name="back" />';\r
+echo '</div>';\r
+\r
+echo '</div></form>';\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+?>
\ No newline at end of file
diff --git a/tools/tests/view_results.php b/tools/tests/view_results.php
new file mode 100644 (file)
index 0000000..0d2c20a
--- /dev/null
@@ -0,0 +1,130 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_TESTS);
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
+require(AT_INCLUDE_PATH.'classes/testQuestions.class.php');
+$_letters = array(_AT('A'), _AT('B'), _AT('C'), _AT('D'), _AT('E'), _AT('F'), _AT('G'), _AT('H'), _AT('I'), _AT('J'));
+
+$tid = intval($_GET['tid']);
+if ($tid == 0){
+       $tid = intval($_POST['tid']);
+}
+
+$_pages['tools/tests/view_results.php']['title_var']  = 'view_results';
+$_pages['tools/tests/view_results.php']['parent'] = 'tools/tests/results.php?tid='.$tid;
+
+$_pages['tools/tests/results.php?tid='.$tid]['title_var'] = 'submissions';
+$_pages['tools/tests/results.php?tid='.$tid]['parent'] = 'tools/tests/index.php';
+
+
+if ($_POST['cancel']) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: results.php?tid='.$tid);
+       exit;
+} else if ($_POST['back']) {
+       header('Location: results.php?tid='.$tid);
+       exit;
+} else if ($_POST['submit']) {
+       $tid = intval($_POST['tid']);
+       $rid = intval($_POST['rid']);
+       
+       $final_score = 0;
+       if (is_array($_POST['scores'])) {
+               foreach ($_POST['scores'] as $qid => $score) {
+                       $qid          = intval($qid);
+                       $score            = floatval($score);
+                       $final_score += $score;
+
+                       $sql    = "UPDATE ".TABLE_PREFIX."tests_answers SET score='$score' WHERE result_id=$rid AND question_id=$qid";
+                       $result = mysql_query($sql, $db);
+               }
+       }
+
+       $sql    = "UPDATE ".TABLE_PREFIX."tests_results SET final_score='$final_score', date_taken=date_taken, end_time=end_time WHERE result_id=$rid AND status=1";
+       $result = mysql_query($sql, $db);
+
+       $msg->addFeedback('RESULTS_UPDATED');
+       header('Location: results.php?tid='.$tid);
+       exit;
+}
+
+if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+       $content_base_href = 'get.php/';
+} else {
+       $course_base_href = 'content/' . $_SESSION['course_id'] . '/';
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+       
+$sql   = "SELECT * FROM ".TABLE_PREFIX."tests WHERE test_id=$tid AND course_id=$_SESSION[course_id]";
+$result        = mysql_query($sql, $db);
+
+if (!($row = mysql_fetch_array($result))){
+       $msg->printErrors('ITEM_NOT_FOUND');
+       require (AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+$test_title = $row['title'];
+$out_of                = $row['out_of'];
+
+$tid = intval($_GET['tid']);
+$rid = intval($_GET['rid']);
+
+$sql   = "SELECT TQ.*, TQA.* FROM ".TABLE_PREFIX."tests_questions TQ INNER JOIN ".TABLE_PREFIX."tests_questions_assoc TQA USING (question_id) WHERE TQ.course_id=$_SESSION[course_id] AND TQA.test_id=$tid ORDER BY TQA.ordering";
+$result        = mysql_query($sql, $db);
+
+if (mysql_num_rows($result) == 0) {
+       echo '<p>'._AT('no_questions').'</p>';
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+?>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<input type="hidden" name="tid" value="<?php echo $tid; ?>">
+<input type="hidden" name="rid" value="<?php echo $rid; ?>">
+
+<div class="input-form">
+       <fieldset class="group_form"><legend class="group_form"><?php echo AT_print($test_title, 'tests.title'); ?></legend>
+
+       <?php while ($row = mysql_fetch_assoc($result)) {
+               /* get the results for this question */
+               $sql            = "SELECT C.* FROM ".TABLE_PREFIX."tests_answers C WHERE C.result_id=$rid AND C.question_id=$row[question_id]";
+               $result_a       = mysql_query($sql, $db);
+               if ($answer_row = mysql_fetch_assoc($result_a)) {
+                       $obj = TestQuestions::getQuestion($row['type']);
+                       $obj->displayResult($row, $answer_row, TRUE);
+
+                       if ($row['feedback']) {
+                               echo '<div class="row"><p><strong>'._AT('feedback').':</strong> ';
+                               echo nl2br($row['feedback']).'</p></div>';
+                       }
+               }
+       }
+       ?>
+
+       <div class="row buttons">
+       <?php if ($out_of): ?>
+               <input type="submit" value="<?php echo _AT('save'); ?>" name="submit" accesskey="s" /> <input type="submit" value="<?php echo _AT('cancel'); ?>" name="cancel" />
+       <?php else: ?>
+               <input type="submit" value="<?php echo _AT('back'); ?>" name="back" />
+       <?php endif; ?>
+       </div>
+       </fieldset>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tile/import.php b/tools/tile/import.php
new file mode 100644 (file)
index 0000000..a69b983
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_CONTENT);
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if (!isset($_main_menu)) {
+       $_main_menu = $contentManager->getContent();
+}
+
+function print_menu_sections(&$menu, $parent_content_id = 0, $depth = 0, $ordering = '') {
+       $my_children = $menu[$parent_content_id];
+       $cid = $_GET['cid'];
+
+       if (!is_array($my_children)) {
+               return;
+       }
+       foreach ($my_children as $children) {
+               echo '<option value="'.$children['content_id'].'"';
+               if ($cid == $children['content_id']) {
+                       echo ' selected="selected"';
+               }
+               echo '>';
+               echo str_pad('', $depth, '-') . ' ';
+               if ($parent_content_id == 0) {
+                       $new_ordering = $children['ordering'];
+                       echo $children['ordering'];
+               } else {
+                       $new_ordering = $ordering.'.'.$children['ordering'];
+                       echo $ordering . '.'. $children['ordering'];
+               }
+               echo ' '.$children['title'].'</option>';
+
+               print_menu_sections($menu, $children['content_id'], $depth+1, $new_ordering);
+       }
+}
+
+
+?>
+
+<form name="form1" method="post" action="tools/ims/ims_import.php?tile=1" onsubmit="openWindow('<?php echo AT_BASE_HREF; ?>tools/prog.php?tile=1');">
+       <input type="hidden" name="url" value="<?php echo AT_TILE_EXPORT; ?>?cp=<?php echo $_GET['cp']; ?>" />
+<br />
+<div class="input-form">
+
+       <div class="row">
+               <?php echo _AT('tile_import_content_package_about'); ?>
+       </div>
+
+       <div class="row">
+       <strong><?php echo _AT('import_content_package_where'); ?>:</strong> <select name="cid">
+                                                       <option value="0"><?php echo _AT('import_content_package_bottom_subcontent'); ?></option>
+                                                       <option>--------------------------</option>
+                                                       <?php
+                                                               print_menu_sections($_main_menu);
+                                                       ?>
+                                                       </select>
+       </div>
+
+       <div class="row">
+               <strong><?php echo _AT('import_content_package'); ?>:</strong> <?php echo urldecode($stripslashes($_GET['title'])); ?>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('import'); ?>" /> <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+</div>
+</form>
+
+<script language="javascript" type="text/javascript">
+function openWindow(page) {
+       newWindow = window.open(page, "progWin", "width=400,height=200,toolbar=no,location=no");
+       newWindow.focus();
+}
+</script>
+
+<?php require (AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tile/index.php b/tools/tile/index.php
new file mode 100644 (file)
index 0000000..dda06fe
--- /dev/null
@@ -0,0 +1,165 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../../include/');
+require (AT_INCLUDE_PATH.'vitals.inc.php');
+authenticate(AT_PRIV_CONTENT);
+
+$path = array();
+
+/* called at the start of en element */
+/* builds the $path array which is the path from the root to the current element */
+function startElement($parser, $name, $attrs) {
+       global $path;
+       array_push($path, $name);
+}
+
+/* called when an element ends */
+/* removed the current element from the $path */
+function endElement($parser, $name) {
+       global $my_data, $path, $tile_title, $tile_description, $tile_identifier;
+
+       if ($path == array('lom', 'general', 'title', 'langstring')) {
+               $tile_title = $my_data;
+       } else if ($path == array('lom', 'general', 'description', 'langstring')) {
+               $tile_description = $my_data;
+       } else if ($path == array('lom', 'general', 'identifier')) {
+               $tile_identifier = $my_data;
+       }
+
+       $my_data = '';
+       array_pop($path);
+}
+
+/* called when there is character data within elements */
+/* constructs the $items array using the last entry in $path as the parent element */
+function characterData($parser, $data){
+       global $my_data;
+       $my_data .= $data;
+}
+
+require (AT_INCLUDE_PATH.'header.inc.php');
+       
+
+$msg->printAll();
+
+?>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>#search_results" method="get" name="form">
+
+<div class="input-form" style="width: 60%">
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('search'); ?></legend>
+       <div class="row">
+               <label for="words2"><?php echo _AT('search_words'); ?></label><br />
+               <input type="text" name="query" size="40" id="words2" value="<?php echo stripslashes(htmlspecialchars($_GET['query'])); ?>" />
+       </div>
+
+       <div class="row">
+               <?php echo _AT('search_in'); ?></label><br />
+
+               <input type="radio" name="field" value="anyField" id="taf" <?php if (!isset($_GET['field']) || ($_GET['field'] == 'anyField')) { echo 'checked="checked"'; } ?> /><label for="taf"><?php echo _AT('tile_any_field'); ?></label><br />
+               <input type="radio" name="field" value="title" id="tt" <?php if ($_GET['field'] == 'title') { echo 'checked="checked"'; } ?> /><label for="tt"><?php echo _AT('title'); ?></label><br />
+               <input type="radio" name="field" value="author" id="ta" <?php if ($_GET['field'] == 'author') { echo 'checked="checked"'; } ?> /><label for="ta"><?php echo _AT('tile_author'); ?></label><br />
+               <input type="radio" name="field" value="subject" id="tk" <?php if ($_GET['field'] == 'subject') { echo 'checked="checked"'; } ?> /><label for="tk"><?php echo _AT('tile_keyword'); ?></label><br />
+               <input type="radio" name="field" value="description" id="td" <?php if ($_GET['field'] == 'description') { echo 'checked="checked"'; } ?> /><label for="td"><?php echo _AT('description'); ?></label><br />
+               <input type="radio" name="field" value="technicalFormat" id="tf" <?php if ($_GET['field'] == 'technicalFormat') { echo 'checked="checked"'; } ?> /><label for="tf"><?php echo _AT('tile_technical_format'); ?></label>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('search'); ?>" />
+       </div>
+</div>
+</form>
+<br />
+<?php
+
+if (isset($_GET['query'])) {
+       if (!extension_loaded('soap')) {
+               require(AT_INCLUDE_PATH . 'classes/nusoap.php');
+               // Create the client instance
+               $client = new nusoapclient(AT_TILE_WSDL, true);
+
+               // Check for an error
+               $error = $client->getError();
+               if ($error) {
+                       // Display the error
+
+                       $msg->addError('TILE_UNAVAILABLE');
+                       $msg->printAll();
+
+                       require(AT_INCLUDE_PATH.'footer.inc.php');
+                       exit;
+               }
+
+               // Create the proxy
+               $proxy = $client->getProxy();
+       } else {
+               // Create the client instance
+               $proxy = new soapclient(AT_TILE_WSDL);
+       }
+
+
+       $search_input = array('query' => $_GET['query'], 'field' => $_GET['field'], 'content' => 'contentPackage');
+
+       $results = $proxy->doSearch($search_input);
+
+       if ($results) {
+               $num_results = count($results);
+       } else {
+               $num_results = 0;
+       }
+       echo '<h3>'. _AT('results_found', $num_results).'</h3>';
+       echo '<ol>';
+       if ($num_results) {
+               foreach ($results as $result) {
+
+                       $xml_parser = xml_parser_create();
+
+                       xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false); /* conform to W3C specs */
+                       xml_set_element_handler($xml_parser, 'startElement', 'endElement');
+                       xml_set_character_data_handler($xml_parser, 'characterData');
+
+                       if (!xml_parse($xml_parser, $result, true)) {
+                               die(sprintf("XML error: %s at line %d",
+                                                       xml_error_string(xml_get_error_code($xml_parser)),
+                                                       xml_get_current_line_number($xml_parser)));
+                       }
+
+                       xml_parser_free($xml_parser);
+
+                       $tile_title = str_replace('<', '&lt;', $tile_title);
+
+                       echo '<li><strong>' . $tile_title . '</strong> - ';
+                       echo '<a href="'.AT_TILE_PREVIEW .'cp='.$tile_identifier.'&item='.$tile_identifier.'" target="_new">'._AT('preview').'</a>';
+                       echo ' | <a href="'.AT_TILE_EXPORT.'?cp='.$tile_identifier.'">'._AT('download').'</a>';
+                       if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
+                               echo ' | <a href="tools/tile/import.php?cp='.$tile_identifier.SEP.'title='.urlencode($tile_title).'">'._AT('import').'</a>';
+                       }
+                       echo '<br />';
+                       if (strlen($tile_description) > 200) {
+                               echo '<small>' . $tile_description  . '</small>';
+                       } else {
+                               echo $tile_description;
+                       }
+
+                       echo '<br /></li>';
+
+                       unset($tile_title);
+                       unset($tile_description);
+                       unset($tile_identifier);
+               }
+       }
+       echo '</ol>';
+}
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/tools/tracker.php b/tools/tracker.php
new file mode 100644 (file)
index 0000000..7a3c5f9
--- /dev/null
@@ -0,0 +1,64 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+$_section[0][0] = _AT('tools');
+$member_id=$_SESSION['member_id'];
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+
+//get names for member_ids
+$sql14 = "select member_id, login, first_name, last_name from ".TABLE_PREFIX."members";
+$result14=mysql_query($sql14, $db);
+while($row=mysql_fetch_array($result14)){
+       if($row['first_name'] && $row['last_name']){
+               $this_user[$row['member_id']]= $row['first_name'].' '. $row['last_name'];
+       }else{
+               $this_user[$row['member_id']]= $row['login'];
+       }
+}
+
+/////////////////////////////
+// Top of the page
+//see if tracking is turned on
+$sql="SELECT tracking FROM ".TABLE_PREFIX."courses where course_id=$_SESSION[course_id]";
+$result=mysql_query($sql, $db);
+while($row= mysql_fetch_array($result)){
+       if($row['tracking']== "off"){
+               if(authenticate(AT_PRIV_ADMIN, AT_PRIV_RETURN)){
+                       $msg->printInfos('TRACKING_OFFIN');
+               } else {
+                       $msg->printInfos('TRACKING_OFFST');
+               }
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+       }
+}
+if ($_GET['coverage'] == 'raw'){
+       echo '&nbsp;&nbsp;<a href="'.$_SERVER['PHP_SELF'].'">'._AT('show_summary_tracking').'</a><br /><br />';
+} else {
+       echo '&nbsp;&nbsp;<a href="'.$_SERVER['PHP_SELF'].'?coverage=raw">'._AT('show_raw_tracking').'</a><br /><br />';
+}
+
+if (authenticate(AT_PRIV_ADMIN, AT_PRIV_RETURN)) {
+       $msg->printInfos('TRACKING_NO_INST1');
+} else if ($_GET['coverage'] == 'raw') {
+       require(AT_INCLUDE_PATH.'lib/tracker.inc.php');
+} else{
+       require(AT_INCLUDE_PATH.'lib/tracker2.inc.php');
+}
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/tools/tracker/export.php b/tools/tracker/export.php
new file mode 100644 (file)
index 0000000..5a8d5f2
--- /dev/null
@@ -0,0 +1,61 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+authenticate(AT_PRIV_CONTENT);\r
+\r
+       function quote_csv($line) {\r
+               $line = str_replace('"', '""', $line);\r
+\r
+               $line = str_replace("\n", '\n', $line);\r
+               $line = str_replace("\r", '\r', $line);\r
+               $line = str_replace("\x00", '\0', $line);\r
+\r
+               return '"'.$line.'"';\r
+       }\r
+\r
+       $name = ereg_replace(" ", "_", $_SESSION['course_title']);\r
+       $name = ereg_replace("'", "", $name);\r
+\r
+       header('Content-Type: text/csv');\r
+       header('Content-Disposition: inline; filename="'.$name.'_tracking.csv"');\r
+       header('Expires: 0');\r
+       header('Cache-Control: must-revalidate, post-check=0, pre-check=0');\r
+       header('Pragma: public');\r
+       \r
+       $file_row = "page,member,visits,duration,timestamp";\r
+       $file_row .= "\n";\r
+\r
+       $sql = "SELECT C.title, M.login, MT.counter, SEC_TO_TIME(MT.duration) AS time, MT.last_accessed\r
+                       FROM ".TABLE_PREFIX."content C, ".TABLE_PREFIX."members M, ".TABLE_PREFIX."member_track MT\r
+                       WHERE M.member_id=MT.member_id AND C.content_id=MT.content_id AND C.course_id=$_SESSION[course_id]\r
+                       ORDER BY C.title, M.login ASC";\r
+\r
+       $result = mysql_query($sql, $db);\r
+       \r
+       while ($row = mysql_fetch_assoc($result)) {\r
+               $file_row .= quote_csv($row['title'])   .",";\r
+               $file_row .= quote_csv($row['login'])  .",";\r
+               $file_row .= quote_csv($row['counter']) .",";\r
+               $file_row .= quote_csv($row['time']) .",";\r
+               $file_row .= AT_date(_AT('forum_date_format'), $row['last_accessed']).",";\r
+               $file_row .= "\n";\r
+       }\r
+\r
+\r
+       echo $file_row;\r
+       exit;\r
+?>
\ No newline at end of file
diff --git a/tools/tracker/index.php b/tools/tracker/index.php
new file mode 100644 (file)
index 0000000..ce7f16b
--- /dev/null
@@ -0,0 +1,128 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto         */\r
+/* http://atutor.ca                                                    */\r
+/*                                                                     */\r
+/* This program is free software. You can redistribute it and/or       */\r
+/* modify it under the terms of the GNU General Public License         */\r
+/* as published by the Free Software Foundation.                       */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_CONTENT);\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+\r
+$orders = array('asc' => 'desc', 'desc' => 'asc');\r
+$cols   = array('total_hits' => 1, 'unique_hits' => 1, 'average_duration' => 1, 'total_duration' => 1);\r
+\r
+if (isset($_GET['asc'])) {\r
+       $order = 'asc';\r
+       $col   = isset($cols[$_GET['asc']]) ? $_GET['asc'] : 'total_hits';\r
+} else if (isset($_GET['desc'])) {\r
+       $order = 'desc';\r
+       $col   = isset($cols[$_GET['desc']]) ? $_GET['desc'] : 'total_hits';\r
+} else {\r
+       // no order set\r
+       $order = 'desc';\r
+       $col   = 'total_hits';\r
+}\r
+\r
+$page_string = SEP.$order.'='.$col;\r
+\r
+if (!isset($_GET['cnt'])) {\r
+       $sql    = "SELECT COUNT(DISTINCT content_id) AS cnt FROM ".TABLE_PREFIX."member_track WHERE course_id=$_SESSION[course_id]";\r
+       $result = mysql_query($sql, $db);\r
+       $row = mysql_fetch_assoc($result);\r
+       $cnt = $row['cnt'];\r
+} else {\r
+       $cnt = intval($_GET['cnt']);\r
+}\r
+\r
+$num_results = $cnt;\r
+$results_per_page = 15;\r
+$num_pages = max(ceil($num_results / $results_per_page), 1);\r
+$page = intval($_GET['p']);\r
+if (!$page) {\r
+       $page = 1;\r
+}      \r
+$count = (($page-1) * $results_per_page) + 1;\r
+\r
+$offset = ($page-1)*$results_per_page;\r
+\r
+/*create a table that lists all the content pages and the number of time they were viewed*/\r
+$sql = "SELECT content_id, COUNT(*) AS unique_hits, SUM(counter) AS total_hits, SEC_TO_TIME(SUM(duration)/SUM(counter)) AS average_duration, SEC_TO_TIME(SUM(duration)) AS total_duration FROM ".TABLE_PREFIX."member_track WHERE course_id=$_SESSION[course_id] GROUP BY content_id ORDER BY $col $order LIMIT $offset, $results_per_page";\r
+$result = mysql_query($sql, $db);\r
+\r
+?>\r
+<div class="paging">\r
+       <ul>\r
+       <?php for ($i=1; $i<=$num_pages; $i++): ?>\r
+               <li>\r
+                       <?php if ($i == $page) : ?>\r
+                               <a class="current" href="<?php echo $_SERVER['PHP_SELF']; ?>?p=<?php echo $i.$page_string; ?>"><em><?php echo $i; ?></em></a>\r
+                       <?php else: ?>\r
+                               <a href="<?php echo $_SERVER['PHP_SELF']; ?>?p=<?php echo $i.$page_string; ?>"><?php echo $i; ?></a>\r
+                       <?php endif; ?>\r
+               </li>\r
+       <?php endfor; ?>\r
+       </ul>\r
+</div>\r
+\r
+<table class="data" rules="cols" summary="">\r
+<colgroup>\r
+       <?php if ($col == 'total_hits'): ?>\r
+               <col />\r
+               <col class="sort" />\r
+               <col span="4" />\r
+       <?php elseif($col == 'unique_hits'): ?>\r
+               <col span="2" />\r
+               <col class="sort" />\r
+               <col span="3" />\r
+       <?php elseif($col == 'average_duration'): ?>\r
+               <col span="3" />\r
+               <col class="sort" />\r
+               <col span="2" />\r
+       <?php elseif($col == 'total_duration'): ?>\r
+               <col span="4" />\r
+               <col class="sort" />\r
+               <col />\r
+       <?php endif; ?>\r
+</colgroup>\r
+<thead>\r
+<tr>\r
+       <th scope="col"><?php echo _AT('page'); ?></th>\r
+       <th scope="col"><a href="tools/tracker/index.php?<?php echo $orders[$order]; ?>=total_hits"><?php echo _AT('visits');             ?></a></th>\r
+       <th scope="col"><a href="tools/tracker/index.php?<?php echo $orders[$order]; ?>=unique_hits"><?php echo _AT('unique_visits');     ?></a></th>\r
+       <th scope="col"><a href="tools/tracker/index.php?<?php echo $orders[$order]; ?>=average_duration"><?php echo _AT('avg_duration'); ?></a></th>\r
+       <th scope="col"><a href="tools/tracker/index.php?<?php echo $orders[$order]; ?>=total_duration"><?php echo _AT('duration');       ?></a></th>\r
+       <th scope="col"><?php echo _AT('details');       ?></th>\r
+</tr>\r
+</thead>\r
+<tbody>\r
+<?php if ($row = mysql_fetch_assoc($result)): ?>\r
+       <?php do { ?>\r
+               <tr onmousedown="document.location='<?php echo AT_BASE_HREF; ?>tools/tracker/page_student_stats.php?content_id=<?php echo $row['content_id']; ?>'" title="<?php echo _AT('details'); ?>">\r
+                       <td><?php echo $contentManager->_menu_info[$row['content_id']]['title']; ?></td>\r
+                       <td><?php echo $row['total_hits'];       ?></td>\r
+                       <td><?php echo $row['unique_hits'];      ?></td>\r
+                       <td><?php echo $row['average_duration']; ?></td>\r
+                       <td><?php echo $row['total_duration'];   ?></td>\r
+                       <td><a href="tools/tracker/page_student_stats.php?content_id=<?php echo $row['content_id']; ?>"><?php echo _AT('details'); ?></a></td>\r
+               </tr>\r
+       <?php } while ($row = mysql_fetch_assoc($result)); ?>\r
+<?php else: ?>\r
+       <tr>\r
+               <td colspan="6"><?php echo _AT('none_found'); ?></td>\r
+       </tr>\r
+<?php endif; ?>\r
+</tbody>\r
+</table>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tracker/page_student_stats.php b/tools/tracker/page_student_stats.php
new file mode 100644 (file)
index 0000000..0679b8e
--- /dev/null
@@ -0,0 +1,59 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+authenticate(AT_PRIV_CONTENT);\r
+\r
+/* Getting content id from page that reffered */\r
+$content_id = intval($_GET['content_id']);\r
+\r
+$_pages['tools/tracker/page_student_stats.php']['title'] = $contentManager->_menu_info[$content_id]['title'];\r
+$_pages['tools/tracker/page_student_stats.php']['parent'] = 'tools/tracker/index.php';\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$sql = "SELECT counter, content_id, member_id, SEC_TO_TIME(duration) AS total, SEC_TO_TIME(duration/counter) AS average FROM ".TABLE_PREFIX."member_track WHERE course_id=$_SESSION[course_id] AND content_id=$content_id ORDER BY total DESC";\r
+$result = mysql_query($sql, $db);\r
+\r
+?>\r
+<table class="data" rules="cols" summary="">\r
+<thead>\r
+<tr>\r
+       <th scope="col"><?php echo _AT('login_name'); ?></th>\r
+       <th scope="col"><?php echo _AT('visits'); ?></th>\r
+       <th scope="col"><?php echo _AT('avg_duration'); ?></th>\r
+       <th scope="col"><?php echo _AT('duration'); ?></th>\r
+</tr>\r
+</thead>\r
+<tbody>\r
+<?php if ($row = mysql_fetch_assoc($result)) : ?>\r
+       <?php do { ?>\r
+       <tr onmousedown="document.location='<?php echo AT_BASE_HREF; ?>tools/tracker/student_usage.php?id=<?php echo $row['member_id']; ?>'" title="<?php echo _AT('member_stats'); ?>">\r
+               <td><a href="<?php echo AT_BASE_HREF; ?>tools/tracker/student_usage.php?id=<?php echo $row['member_id']; ?>"><?php echo get_display_name($row['member_id']); ?></a></td>\r
+               <td><?php echo $row['counter']; ?></td>\r
+               <td><?php echo $row['average']; ?></td>\r
+               <td><?php echo $row['total']; ?></td>\r
+       </tr>\r
+       <?php } while ($row = mysql_fetch_assoc($result)); ?>\r
+<?php else: ?>\r
+       <tr>\r
+               <td colspan="4"><?php echo _AT('none_found'); ?></td>\r
+       </tr>\r
+<?php endif; ?>\r
+</tbody>\r
+</table>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/tracker/reset.php b/tools/tracker/reset.php
new file mode 100644 (file)
index 0000000..e93ce99
--- /dev/null
@@ -0,0 +1,46 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto         */\r
+/* http://atutor.ca                                                    */\r
+/*                                                                     */\r
+/* This program is free software. You can redistribute it and/or       */\r
+/* modify it under the terms of the GNU General Public License         */\r
+/* as published by the Free Software Foundation.                       */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+authenticate(AT_PRIV_CONTENT);\r
+\r
+if (isset($_POST['submit_no'])) {\r
+       $msg->addFeedback('CANCELLED');\r
+       header('Location: ./index.php');\r
+       exit;\r
+}\r
+\r
+else if (isset($_POST['submit_yes'])) {\r
+       //clean up the db\r
+       $sql    = "DELETE FROM ".TABLE_PREFIX."member_track WHERE course_id=$_SESSION[course_id]";\r
+       $result = mysql_query($sql, $db);\r
+\r
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');\r
+       header('Location: ./index.php');\r
+       exit;\r
+}\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+       //print confirmation\r
+       $hidden_vars['all'] = TRUE;\r
+\r
+       $msg->addConfirm('DELETE_TRACKING', $hidden_vars);\r
+       $msg->printConfirm();\r
+\r
+require(AT_INCLUDE_PATH.'footer.inc.php');\r
+\r
+?>
\ No newline at end of file
diff --git a/tools/tracker/student_usage.php b/tools/tracker/student_usage.php
new file mode 100644 (file)
index 0000000..82dc7ac
--- /dev/null
@@ -0,0 +1,84 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+authenticate(AT_PRIV_CONTENT);\r
+\r
+require(AT_INCLUDE_PATH.'header.inc.php');\r
+\r
+$sql   = "SELECT M.member_id, M.login, CONCAT(M.first_name, ' ', M.second_name, ' ', M.last_name) AS full_name\r
+                       FROM ".TABLE_PREFIX."members M, ".TABLE_PREFIX."course_enrollment C \r
+                       WHERE M.member_id=C.member_id AND C.course_id=$_SESSION[course_id]";\r
+$result = mysql_query($sql, $db);\r
+\r
+$_GET['id'] = intval($_GET['id']);\r
+\r
+?>\r
+<form name="form" action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get">\r
+<div class="input-form">\r
+       <div class="row">\r
+               <label for="id"><?php echo _AT('select_member'); ?></label><br />\r
+               <select name="id" id="id">\r
+                       <?php\r
+                               while ($row = mysql_fetch_assoc($result)) {\r
+                                       $sender = get_display_name($row['member_id']);\r
+                                       echo '<option value="'.$row['member_id'].'"';\r
+                                       if ($row['member_id'] == $_GET['id']) {\r
+                                               echo ' selected="selected"';\r
+                                       }\r
+                                       echo '>'.$sender.'</option>';\r
+                               }\r
+                       ?>\r
+               </select>\r
+       </div>\r
+\r
+       <div class="row buttons">\r
+               <input type="submit" name="submit" value="<?php echo _AT('view'); ?>" />\r
+       </div>\r
+</div>\r
+</form>\r
+\r
+<?php if ($_GET['id']) : ?>\r
+<?php\r
+       $sql = "SELECT counter, content_id, SEC_TO_TIME(duration) AS total FROM ".TABLE_PREFIX."member_track WHERE member_id=$_GET[id] AND course_id=$_SESSION[course_id] ORDER BY counter DESC";\r
+       $result = mysql_query($sql, $db);\r
+?>\r
+       <table class="data static" rules="cols" summary="">\r
+       <thead>\r
+       <tr>\r
+               <th scope="col"><?php echo _AT('page'); ?></th>\r
+               <th scope="col"><?php echo _AT('visits'); ?></th>\r
+               <th scope="col"><?php echo _AT('duration'); ?></th>\r
+       </tr>\r
+       </thead>\r
+       <tbody>\r
+       <?php if ($row = mysql_fetch_assoc($result)): ?>\r
+               <?php do { ?>\r
+                       <tr>\r
+                               <td><?php echo $contentManager->_menu_info[$row['content_id']]['title']; ?></td>\r
+                               <td><?php echo $row['counter']; ?></td>\r
+                               <td><?php echo $row['total']; ?></td>\r
+                       </tr>\r
+               <?php } while ($row = mysql_fetch_assoc($result)); ?>\r
+       <?php else: ?>\r
+               <tr>\r
+                       <td colspan="3"><?php echo _AT('none_found'); ?></td>\r
+               </tr>\r
+       <?php endif; ?>\r
+</tbody>\r
+</table>\r
+<?php endif; ?>\r
+\r
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/tools/view_results.php b/tools/view_results.php
new file mode 100644 (file)
index 0000000..a7fced1
--- /dev/null
@@ -0,0 +1,178 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php'); // for print_result and print_score
+require(AT_INCLUDE_PATH.'classes/testQuestions.class.php');
+$_letters = array(_AT('A'), _AT('B'), _AT('C'), _AT('D'), _AT('E'), _AT('F'), _AT('G'), _AT('H'), _AT('I'), _AT('J'));
+
+if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
+       $content_base_href = 'get.php/';
+} else {
+       $course_base_href = 'content/' . $_SESSION['course_id'] . '/';
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$tid = intval($_GET['tid']);
+$rid = intval($_GET['rid']);
+
+$sql   = "SELECT title, random, passfeedback, failfeedback, passscore, passpercent FROM ".TABLE_PREFIX."tests WHERE test_id=$tid AND course_id=$_SESSION[course_id]";
+$result        = mysql_query($sql, $db);
+$row   = mysql_fetch_array($result);
+$test_title    = $row['title'];
+$passfeedback  = $row['passfeedback'];
+$failfeedback  = $row['failfeedback'];
+$passscore     = $row['passscore'];
+$passpercent   = $row['passpercent'];
+$is_random  = $row['random'];
+
+$mark_right = ' <img src="'.$_base_path.'images/checkmark.gif" alt="'._AT('correct_answer').'" title="'._AT('correct_answer').'" />';
+$mark_wrong = ' <img src="'.$_base_path.'images/x.gif" alt="'._AT('wrong_answer').'" title="'._AT('wrong_answer').'" />';
+
+$sql   = "SELECT * FROM ".TABLE_PREFIX."tests_results WHERE result_id=$rid AND member_id=$_SESSION[member_id]";
+$result        = mysql_query($sql, $db); 
+if (!$row = mysql_fetch_assoc($result)){
+       $msg->printErrors('ITEM_NOT_FOUND');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+$final_score= $row['final_score'];
+
+//make sure they're allowed to see results now
+$sql   = "SELECT result_release, out_of FROM ".TABLE_PREFIX."tests WHERE test_id=$tid AND course_id=$_SESSION[course_id]";
+$result        = mysql_query($sql, $db); 
+$row = mysql_fetch_assoc($result);
+
+if ( ($row['result_release']==AT_RELEASE_NEVER) || ($row['result_release']==AT_RELEASE_MARKED && $final_score=='') ) {
+       $msg->printErrors('RESULTS_NOT_RELEASED');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+$out_of = $row['out_of'];
+
+/* Retrieve randomly choosed questions */
+$sql   = "SELECT question_id FROM ".TABLE_PREFIX."tests_answers WHERE result_id=$rid";
+$result        = mysql_query($sql, $db); 
+$row = mysql_fetch_array($result);
+$random_id_string = $row[question_id];
+$row = mysql_fetch_array($result);     
+while ($row['question_id'] != '') {
+       $random_id_string = $random_id_string.','.$row['question_id'];
+       $row = mysql_fetch_array($result);
+}
+if (!$random_id_string) {
+       $random_id_string = 0;
+}
+
+if ($is_random) {
+       $sql    = "SELECT TQ.*, TQA.* FROM ".TABLE_PREFIX."tests_questions TQ INNER JOIN ".TABLE_PREFIX."tests_questions_assoc TQA USING (question_id) WHERE TQA.test_id=$tid AND TQ.question_id IN ($random_id_string) ORDER BY TQ.question_id";
+} else {
+       $sql    = "SELECT TQ.*, TQA.* FROM ".TABLE_PREFIX."tests_questions TQ INNER JOIN ".TABLE_PREFIX."tests_questions_assoc TQA USING (question_id) WHERE TQA.test_id=$tid AND TQ.question_id IN ($random_id_string) ORDER BY TQA.ordering, TQ.question_id";
+}
+$result        = mysql_query($sql, $db); 
+
+if (mysql_num_rows($result) == 0) {
+       echo '<p>'._AT('no_questions').'</p>';
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+// calculate test/my total score to display pass/fail feedback
+$sql_test_total = "SELECT sum(TQA.weight) test_total_score FROM ".TABLE_PREFIX."tests_questions TQ INNER JOIN ".TABLE_PREFIX."tests_questions_assoc TQA USING (question_id) WHERE TQA.test_id=$tid AND TQ.question_id IN ($random_id_string)";
+$result_test_total     = mysql_query($sql_test_total, $db);
+$row_test_total = mysql_fetch_array($result_test_total);
+$test_total_score = $row_test_total["test_total_score"];
+
+while ($row = mysql_fetch_assoc($result)) {
+       $sql_this_score = "SELECT * FROM ".TABLE_PREFIX."tests_answers WHERE result_id=$rid AND question_id=$row[question_id] AND member_id=$_SESSION[member_id]";
+       $result_this_score      = mysql_query($sql_this_score, $db); 
+       $this_score = mysql_fetch_assoc($result_this_score);
+
+       $my_score+=$this_score['score'];
+       $this_total += $row['weight'];
+}
+?>
+<form method="get" action="<?php echo AT_BASE_HREF; ?>tools/my_tests.php">
+<div class="input-form">
+       <div class="row">
+               <h2><?php echo AT_print($test_title, 'tests.title'); ?></h2>
+       </div>
+
+       <div class="row">
+               <h3 align="center">
+                       <?php 
+                               // don't display any feedback if test is created as "no pass score"
+                               if (($passscore == 0 && $passpercent == 0) || ($passpercent <> 0 && $this_total == 0))
+                                       echo '';
+                               // display pass feedback for passed students
+                               elseif (($passscore<>0 && $my_score>=$passscore) ||
+                                   ($passpercent<>0 && ($my_score/$this_total*100)>=$passpercent))
+                                       echo '<font color="green">' . $passfeedback . '</font>';
+                               // otherwise, display fail feedback
+                               else
+                                       echo '<font color="red">' . $failfeedback . '</font>'; 
+                       ?>
+               </h3>
+       </div>
+
+       <?php if ($row['instructions'] != ''): ?>
+               <div style="background-color: #f3f3f3; padding: 5px 10px; margin: 0px; border-top: 1px solid">
+                       <strong><?php echo _AT('instructions'); ?></strong>
+               </div>
+               <div class="row" style="padding-bottom: 20px"><?php echo $row['instructions']; ?></div>
+       <?php endif; ?>
+
+       <?php
+       // reset the result cursor to beginning
+       mysql_data_seek ($result, 0);
+       
+       while ($row = mysql_fetch_assoc($result)) {
+               $sql            = "SELECT * FROM ".TABLE_PREFIX."tests_answers WHERE result_id=$rid AND question_id=$row[question_id] AND member_id=$_SESSION[member_id]";
+               $result_a       = mysql_query($sql, $db); 
+               $answer_row = mysql_fetch_assoc($result_a);
+
+               $obj = TestQuestions::getQuestion($row['type']);
+               $obj->displayResult($row, $answer_row);
+
+               if ($row['feedback']) {
+                       echo '<div class="row"><p><strong>'._AT('feedback').':</strong> ';
+                       echo nl2br($row['feedback']).'</p></div>';
+               }
+       }
+       ?>
+
+       <?php if ($this_total): ?>
+               <div style="background-color: #f3f3f3; padding: 5px 10px; margin: 0px; border-top: 1px solid">
+                       <strong>
+                               <span style="float: right"><?php echo $my_score .' / '.$this_total; ?> <?php echo _AT('points'); ?></span>
+                               <?php echo _AT('final_score'); ?>:
+                       </strong>
+               </div>
+       <?php else: ?>
+               <div style="background-color: #f3f3f3; padding: 5px 10px; margin: 0px; border-top: 1px solid">
+                       <strong>
+                               <?php echo _AT('done'); ?>!
+                       </strong>
+               </div>
+       <?php endif; ?>
+
+       <div class="row buttons">
+               <input type="submit" value="<?php echo _AT('back'); ?>" name="back" />
+       </div>
+</div>
+</form>
+
+<?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/users/browse.php b/users/browse.php
new file mode 100644 (file)
index 0000000..8e3aa9a
--- /dev/null
@@ -0,0 +1,24 @@
+<?php\r
+/****************************************************************/\r
+/* ATutor                                                                                                              */\r
+/****************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */\r
+/* Adaptive Technology Resource Centre / University of Toronto  */\r
+/* http://atutor.ca                                                                                            */\r
+/*                                                              */\r
+/* This program is free software. You can redistribute it and/or*/\r
+/* modify it under the terms of the GNU General Public License  */\r
+/* as published by the Free Software Foundation.                               */\r
+/****************************************************************/\r
+// $Id$\r
+\r
+$page = 'browse_courses';\r
+$_user_location        = 'users';\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+require(AT_INCLUDE_PATH.'vitals.inc.php');\r
+\r
+\r
+require(AT_INCLUDE_PATH.'html/browse.inc.php');\r
+\r
+?>
\ No newline at end of file
diff --git a/users/contact_instructor.php b/users/contact_instructor.php
new file mode 100644 (file)
index 0000000..6d25932
--- /dev/null
@@ -0,0 +1,174 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+if ($_REQUEST['from_browse']) {
+       $page = 'browse_courses';
+} else {
+       $page = 'my_courses';
+}
+
+$_user_location        = 'users';
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+if ($_POST['cancel']) {
+       if ($_POST['from_browse']) {
+               header('Location: browse.php');
+       } else {
+               header('Location: index.php');
+       }
+       exit;
+}
+
+       require(AT_INCLUDE_PATH.'header.inc.php');
+
+       echo '<h2>'._AT('contact_instructor').'</h2>';
+
+       $sql    = "SELECT first_name, last_name, email FROM ".TABLE_PREFIX."members WHERE member_id=$_SESSION[member_id]";
+       $result = mysql_query($sql, $db);
+       if ($row = mysql_fetch_array($result)) {
+               $student_name = $row['last_name'];
+               $student_name .= ($row['first_name'] ? ', '.$row['first_name'] : '');
+
+               $student_email = $row['email'];
+       } else {
+               $msg->printErrors('STUD_INFO_NOT_FOUND');
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+
+       if ($_GET['course']) {
+               $course = intval($_GET['course']);
+       } else {
+               $course = intval($_POST['course']);
+       }
+
+       $sql    = "SELECT M.first_name, M.last_name, M.email, C.title FROM ".TABLE_PREFIX."members M, ".TABLE_PREFIX."courses C WHERE M.member_id=C.member_id AND C.course_id=$course";
+       $result = mysql_query($sql, $db);
+
+       if ($row = mysql_fetch_array($result)) {
+               $instructor_name = $row['last_name'];
+               $instructor_name .= ($row['first_name'] ? ', '.$row['first_name'] : '');
+
+               $instructor_email = $row['email'];
+       } else {
+               $msg->printErrors('INST_INFO_NOT_FOUND');
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+
+       if ($_POST['submit']) {
+               $missing_fields = array();
+
+               $to_email = $instructor_email;
+               $_POST['subject'] = trim($_POST['subject']);
+               $_POST['body']    = trim($_POST['body']);
+
+               if ($_POST['subject'] == '') {
+                       $missing_fields[] = _AT('subject');
+               }
+               if ($_POST['body'] == '') {
+                       $missing_fields[] = _AT('body');
+               }
+               
+               if ($missing_fields) {
+                       $missing_fields = implode(', ', $missing_fields);
+                       $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+               }
+               if (!$msg->containsErrors()) {
+                       $tmp_message = _AT('from_atutor', $row['title'])."\n\n";
+                       $tmp_message .= $_POST['body']."\n\n";
+
+                       if ($to_email != '') {
+                               require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+
+                               $mail = new ATutorMailer;
+
+                               $mail->From     = $_POST['from_email'];
+                               $mail->FromName = $_POST['from'];
+                               $mail->AddAddress($to_email);
+                               $mail->Subject = $_POST['subject'];
+                               $mail->Body    = $tmp_message;
+
+                               if(!$mail->Send()) {
+                                  //echo 'There was an error sending the message';
+                                  $msg->printErrors('SENDING_ERROR');
+                                  exit;
+                               }
+
+                               unset($mail);
+
+                               $msg->printFeedbacks('ACTION_COMPLETED_SUCCESSFULLY');
+                               require(AT_INCLUDE_PATH.'footer.inc.php');
+                               exit;
+                       }
+               }
+       }
+
+$msg->printErrors();
+
+?>
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<input type="hidden" name="course" value="<?php echo $course; ?>" />
+<input type="hidden" name="from_browse" value="<?php echo $_REQUEST['from_browse']; ?>" />
+<table cellspacing="1" cellpadding="0" border="0" summary="" width="85%" class="bodyline" align="center">
+<tr>
+       <th colspan="2" align="left" class="cyan"><?php echo _AT('instructor_contact_form'); ?></th>
+</tr>
+<tr>
+       <td class="row1" align="right"><b><?php echo _AT('contact_name'); ?>:</b></td>
+       <td class="row1"><?php echo $row[title]; ?></td>
+</tr>
+<tr><td height="1" class="row2" colspan="2"></td></tr>
+<tr>
+       <td class="row1" align="right"><b><?php echo _AT('to_name'); ?>:</b></td>
+       <td class="row1"><?php echo $instructor_name; ?> (<?php echo _AT('course_instructor'); ?>)</td>
+</tr>
+<tr><td height="1" class="row2" colspan="2"></td></tr>
+<tr>
+       <td class="row1" align="right"><b><?php echo _AT('to_email'); ?>:</b></td>
+       <td class="row1"><i><?php echo _AT('hidden'); ?></i></td>
+</tr>
+<tr><td height="1" class="row2" colspan="2"></td></tr>
+<tr>
+       <td class="row1" align="right"><label for="from"><b><?php echo _AT('from_name'); ?>:</b></label></td>
+       <td class="row1"><input type="text" class="formfield" name="from" id="from" size="40" value="<?php echo $student_name;?>" /></td>
+</tr>
+<tr><td height="1" class="row2" colspan="2"></td></tr>
+<tr>
+       <td class="row1" align="right"><label for="from_email"><b><?php echo _AT('from_email'); ?>:</b></label></td>
+       <td class="row1"><input type="text" class="formfield" name="from_email" id="from_email" size="40" value="<?php echo $student_email;?>" /></td>
+</tr>
+<tr><td height="1" class="row2" colspan="2"></td></tr>
+<tr>
+       <td class="row1" align="right"><label for="subject"><b><?php echo _AT('subject'); ?>:</b></label></td>
+       <td class="row1"><input type="text"  class="formfield" name="subject" id="subject" size="40" value="<?php echo $_POST['subject']; ?>" /></td>
+</tr>
+<tr><td height="1" class="row2" colspan="2"></td></tr>
+<tr>
+       <td class="row1" align="right" valign="top"><label for="body"><b><?php echo _AT('body'); ?>:</b></label></td>
+       <td class="row1"><textarea class="formfield" cols="55" rows="15" id="body" name="body"><?php echo $_POST['body']; ?></textarea><br /><br /></td>
+</tr>
+<tr><td height="1" class="row2" colspan="2"></td></tr>
+<tr><td height="1" class="row2" colspan="2"></td></tr>
+<tr>
+       <td class="row1" align="center" colspan="2"><input type="submit" name="submit" class="button" value="<?php echo _AT('send'); ?> [Alt-s]" accesskey="s" /> <input type="submit" name="cancel" class="button" value="<?php echo _AT('cancel'); ?>" /></td>
+</tr>
+</table>
+</form>
+<br />
+
+<?php
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/users/course_stats.php b/users/course_stats.php
new file mode 100644 (file)
index 0000000..83737db
--- /dev/null
@@ -0,0 +1,224 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+$page = 'my_courses';
+$_user_location        = 'users';
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+       $thiscourse = intval($_GET['course']);
+
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."courses WHERE member_id=$_SESSION[member_id] AND course_id=$thiscourse";
+       $result = mysql_query($sql,$db);
+       if (!($row = mysql_fetch_array($result))) {
+               $msg->printErrors('NOT_OWNER');
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       }
+       $course_title = $row['title'];
+       $year  = intval($_GET['year']);
+       $month = intval($_GET['month']);
+
+       if ($month == 0) {
+               $month = date('m');
+               $year  = date('Y');
+       }
+
+       $days   = array();
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."course_stats WHERE course_id=$thiscourse AND MONTH(login_date)=$month AND YEAR(login_date)=$year ORDER BY login_date ASC";
+       $result = mysql_query($sql, $db);
+       //$today  = 1; /* we start on the 1st of the month */
+       $max_total_logins = 0;
+       $min_total_logins = (int) 99999999;
+       $total_logins = 0;
+
+       $empty = true;
+       while ($row = mysql_fetch_array($result)) {
+               $empty = false;
+               $row_day = substr($row['login_date'], 8, 2);
+
+               if (substr($row_day, 0,1) == '0') {
+                       $row_day = substr($row_day, 1, 1);
+               }
+               
+               while ($today < $row_day-1) {
+                       $today++;
+                       $days[$today] = array(0, 0);
+                       $min_total_logins = 0;
+               }
+
+               $today = $row_day; /* skip this day in the fill-in-the-blanks-loop */
+                               
+               $days[$row_day] = array($row['guests'], $row['members']);
+
+               if ($max_total_logins < $row['guests']+$row['members']) {
+                       $max_total_logins = $row['guests']+$row['members'];
+               }
+
+               if ($min_total_logins > $row['guests']+$row['members']) {
+                       $min_total_logins = $row['guests']+$row['members'];
+               }
+
+               $total_logins += $row['guests']+$row['members'];
+       }
+
+       /* add zeros to the end of the month, only if it isn't the current month */
+       $now_month = date('m');
+       $now_year  = date('Y');
+       if ( (($month < $now_month) && ($now_year == $year)) || ($now_year < $year) ) {
+               $today++;
+               while (checkdate($month, $today,$year)) {
+                       $days[$today] = array(0, 0);
+                       $today++;
+               }
+       }
+       $num_days = count($days);
+
+       if ($total_logins > 0) {
+               $avg_total_logins = $total_logins/$num_days;
+       } else {
+               $avg_total_logins = 0;
+       }
+
+       $block_height           = 10;
+       $multiplyer_height  = 5; /* should be multiples of 5 */
+
+       if ($month == 12) {
+               $next_month = 1;
+               $next_year  = $year + 1;
+       } else {
+               $next_month = $month + 1;
+               $next_year  = $year;
+       }
+
+       if ($month == 1) {
+               $last_month = 12;
+               $last_year  = $year - 1;
+       } else {
+               $last_month = $month - 1;
+               $last_year  = $year;
+       }
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+$title = _AT('login_statistics', AT_date('%F', $month, AT_DATE_INDEX_VALUE ), $course_title);
+
+echo "<h2>".$title."</h2><br />";
+?>
+       <table cellspacing="1" cellpadding="1" border="0" class="bodyline" summary="" align="center">
+       <tr>
+               <th colspan="2" class="cyan"><small class="bigspacer"><?php
+                       echo '<a href="users/course_stats.php?course='.$thiscourse.SEP.'month='.($last_month).SEP.'year='.$last_year.'">';
+                       echo ' '.AT_date('%F', $last_month, AT_DATE_INDEX_VALUE ); ?></a> |</small>
+                       <?php echo AT_date('%F', $month, AT_DATE_INDEX_VALUE ); ?> <small class="bigspacer">| <?php
+                       echo '<a href="users/course_stats.php?course='.$thiscourse.SEP.'month='.$next_month.SEP.'year='.$next_year.'">';
+                       echo AT_date('%F', $next_month, AT_DATE_INDEX_VALUE); ?> </a></small></th>
+       </tr>
+<?php
+               if (($num_days == 0) || ($empty)) {
+                       echo '<tr>';
+                       echo '<td class="row1" colspan="2">'._AT('no_month_data').'</td>';
+                       echo '</tr>';
+                       echo '</table>';
+                       require(AT_INCLUDE_PATH.'footer.inc.php');
+                       exit;
+               }
+?>
+       <tr>
+               <td class="row1" valign="top" align="right"><strong><?php echo _AT('total'); ?>:</strong></td>
+               <td class="row1"><?php echo $total_logins; ?></td>
+       </tr>
+       <tr><td height="1" class="row2" colspan="2"></td></tr>
+       <tr>
+               <td class="row1" valign="top" align="right"><strong><?php echo _AT('maximum'); ?>:</strong></td>
+               <td class="row1"><?php echo $max_total_logins; ?></td>
+       </tr>
+       <tr><td height="1" class="row2" colspan="2"></td></tr>
+
+       <tr>
+               <td class="row1" valign="top" align="right"><strong><?php echo _AT('minimum'); ?>:</strong></td>
+               <td class="row1"><?php
+               if ($min_total_logins < 99999999) {
+                       echo $min_total_logins; 
+               } else {
+                       echo '0';
+               } ?></td>
+       </tr>
+       <tr><td height="1" class="row2" colspan="2"></td></tr>
+       <tr>
+               <td class="row1" valign="top" align="right"><strong><?php   echo _AT('average'); ?>:</strong></td>
+               <td class="row1"><?php echo number_format($avg_total_logins, 1); ?> <?php   echo _AT('per_day'); ?></td>
+       </tr>
+       <tr><td height="1" class="row2" colspan="2"></td></tr>
+
+       <tr>
+               <td class="row1" valign="top" align="right"><strong><?php   echo _AT('graph'); ?>:</strong></td>
+               <td class="row1">
+                       <table border="0" cellspacing="0" cellpadding="0">
+                       <tr>
+                               <td valign="top" class="graph1"><small><?php echo $max_total_logins; ?></small></td>
+
+<?php
+                       foreach ($days as $day => $logins) {
+                       $dd++;
+                               echo '<td valign="bottom" class="graph"><img src="images/clr.gif" height="'.(($max_total_logins*$multiplyer_height) % $block_height + $block_height).'" width="10" alt="" /><br /><img src="images/blue.gif" height="'.($logins[0]*$multiplyer_height).'" width="9" alt="'.$logins[0].' '._AT('guests').' ('.($logins[0]+$logins[1]).' '._AT('total').')" /><br /><img src="images/red.gif" height="'.($logins[1]*$multiplyer_height).'" width="9" alt="'.$logins[1].' '._AT('members').' ('.($logins[1]+$logins[0]).' '._AT('total').')" /><br /><small>'.$dd.'&nbsp;</small></td>';
+
+                       } while ($row = mysql_fetch_array($result));
+?>
+
+                       </tr>
+                       <tr>
+                               <td valign="top"><small>0</small></td>
+                       </tr>
+                       </table>
+
+                       <small><?php  echo _AT('legend'); ?>: <img src="images/red.gif" height="10" width="10" alt="<?php echo _AT('red_members'); ?>" /> <?php   echo _AT('members'); ?>,
+                               <img src="images/blue.gif" height="10" width="10" alt="<?php echo _AT('blue_guests'); ?>" /> <?php echo _AT('guests'); ?>.</small>
+               </td>
+       </tr>
+       <tr><td height="1" class="row2" colspan="2"></td></tr>
+
+       <tr>
+               <td class="row1" valign="top" align="right"><strong><?php echo _AT('raw_data'); ?>:</strong></td>
+               <td class="row1" align="center">
+       
+               <table cellspacing="1" cellpadding="1" border="0" class="bodyline" summary="">
+               <tr>
+                       <th scope="col" class="cyan"><small><?php echo _AT('date'); ?></small></th>
+                       <th scope="col" class="cyan"><small><?php echo _AT('guests'); ?></small></th>
+                       <th scope="col" class="cyan"><small><?php echo _AT('members'); ?></small></th>
+               </tr>
+<?php
+               $short_name = $month_name_con['en'][$month-1];
+               foreach ($days as $day => $logins) {
+                       $counter++;
+                       echo '<tr>';
+                       echo '<td class="row1"><small>'.$short_name.' '.$day.'</small></td>';
+                       echo '<td class="row1" align="right"><small>'.$logins[0].'</small></td>';
+                       echo '<td class="row1" align="right"><small>'.$logins[1].'</small></td>';
+                       echo '</tr>';
+                       
+                       if ($counter < $num_days) {
+                               echo '<tr><td height="1" class="row2" colspan="3"></td></tr>';
+                       }
+               }
+?>
+                       </table>
+
+               </td>
+       </tr>
+       </table>
+<?php
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/users/create_course.php b/users/create_course.php
new file mode 100644 (file)
index 0000000..2042a7f
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+$_user_location        = 'users';
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'classes/Backup/Backup.class.php');
+require(AT_INCLUDE_PATH.'lib/course.inc.php');
+
+/* verify that this user has status to create courses */
+
+if (get_instructor_status() === FALSE) {
+       if (!$msg->containsErrors()) {
+               $msg->addError('CREATE_NOPERM');
+       }
+
+       require(AT_INCLUDE_PATH.'header.inc.php');
+
+       if (defined('ALLOW_INSTRUCTOR_REQUESTS') && ALLOW_INSTRUCTOR_REQUESTS) {
+               $sql    = "SELECT member_id FROM ".TABLE_PREFIX."instructor_approvals WHERE member_id=$_SESSION[member_id]";
+               $result = mysql_query($sql, $db);
+               if (!($row = mysql_fetch_array($result))) : ?>
+                       <form action="users/request_instructor.php" method="post">
+                       <input type="hidden" name="form_request_instructor" value="true" />
+                       <div class="input-form">
+                               <div class="row">
+                                       <p><?php echo _AT('request_instructor'); ?></p>
+                               </div>
+
+                               <div class="row">
+                                       <div class="required" title="<?php echo _AT('required_field'); ?>">*</div><label for="desc"><?php echo _AT('give_description'); ?></label><br />
+                                       <textarea cols="40" rows="2" id="desc" name="description"></textarea>
+                               </div>
+
+                               <div class="row buttons">
+                                       <input type="submit" name="submit" value="<?php echo _AT('send'); ?>" />
+                                       <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+                               </div>
+                       </div>
+                       </form>
+               <?php else : ?>
+                       <div class="input-form">
+                               <div class="row">
+                                       <p><?php echo _AT('request_instructor_pending'); ?></p>
+                               </div>
+                       </div>
+               <?php endif; ?>
+<?php
+       }
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+$course = 0;
+$isadmin   = FALSE;
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php');
+       exit;
+}else if (isset($_POST['form_course']) && $_POST['submit'] != '') {
+       $_POST['instructor'] = $_SESSION['member_id'];
+
+               $errors = add_update_course($_POST);
+
+       if ($errors !== FALSE) {
+               $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               header('Location: '.AT_BASE_HREF.'bounce.php?course='.$addslashes($errors).SEP.'p='.urlencode('index.php'));
+               exit;
+       }
+
+}
+
+$onload = 'document.course_form.title.focus();';
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+require(AT_INCLUDE_PATH.'html/course_properties.inc.php');
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/users/email_change.php b/users/email_change.php
new file mode 100644 (file)
index 0000000..7edf776
--- /dev/null
@@ -0,0 +1,130 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: profile.php 6025 2006-03-28 20:13:55Z joel $
+
+$page = 'profile';
+$_user_location        = 'users';
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+
+if ($_SESSION['valid_user'] !== true) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $info = array('INVALID_USER', $_SESSION['course_id']);
+       $msg->printInfos($info);
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       Header('Location: profile.php');
+       exit;
+}
+
+if (!isset($_SESSION['token']) || !$_SESSION['token']) {
+       $_SESSION['token'] = md5(mt_rand());
+}
+
+if (isset($_POST['submit'])) {
+
+       $this_password = $_POST['form_password_hidden'];
+
+       // password check
+       if (!empty($this_password)) {
+               //check if old password entered is correct
+               $sql    = "SELECT password FROM ".TABLE_PREFIX."members WHERE member_id=$_SESSION[member_id]";
+               $result = mysql_query($sql,$db);
+               if ($row = mysql_fetch_assoc($result)) {
+                       if ($row['password'] != $this_password) {
+                               $msg->addError('WRONG_PASSWORD');
+                               Header('Location: email_change.php');
+                               exit;
+                       }
+               }
+       } else {
+               $msg->addError(array('EMPTY_FIELDS', _AT('password')));
+               header('Location: email_change.php');
+               exit;
+       }
+               
+       // email check
+       if ($_POST['email'] == '') {
+               $msg->addError(array('EMPTY_FIELDS', _AT('email')));
+       } else {
+               if(!eregi("^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$", $_POST['email'])) {
+                       $msg->addError('EMAIL_INVALID');
+               }
+               $result = mysql_query("SELECT * FROM ".TABLE_PREFIX."members WHERE email='$_POST[email]' AND member_id<>$_SESSION[member_id]",$db);
+               if(mysql_num_rows($result) != 0) {
+                       $msg->addError('EMAIL_EXISTS');
+               }
+       }
+
+       if (!$msg->containsErrors()) {                  
+               if (defined('AT_EMAIL_CONFIRMATION') && AT_EMAIL_CONFIRMATION) {
+                       //send confirmation email
+                       $sql    = "SELECT email, creation_date FROM ".TABLE_PREFIX."members WHERE member_id=$_SESSION[member_id]";
+                       $result = mysql_query($sql, $db);
+                       $row    = mysql_fetch_assoc($result);
+
+                       if ($row['email'] != $_POST['email']) {
+                               $code = substr(md5($_POST['email'] . $row['creation_date'] . $_SESSION['member_id']), 0, 10);
+                               $confirmation_link = AT_BASE_HREF . 'confirm.php?id='.$_SESSION['member_id'].SEP .'e='.urlencode($_POST['email']).SEP.'m='.$code;
+
+                               /* send the email confirmation message: */
+                               require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+                               $mail = new ATutorMailer();
+
+                               $mail->From     = $_config['contact_email'];
+                               $mail->AddAddress($_POST['email']);
+                               $mail->Subject = SITE_NAME . ' - ' . _AT('email_confirmation_subject');
+                               $mail->Body    = _AT('email_confirmation_message2', $_config['site_name'], $confirmation_link);
+
+                               $mail->Send();
+
+                               $msg->addFeedback('CONFIRM_EMAIL');
+                       } else {
+                               $msg->addFeedback('CANCELLED');
+                       }
+               } else {
+
+                       //insert into database
+                       $sql = "UPDATE ".TABLE_PREFIX."members SET email='$_POST[email]', creation_date=creation_date, last_login=last_login WHERE member_id=$_SESSION[member_id]";
+                       $result = mysql_query($sql,$db);
+                       if (!$result) {
+                               $msg->printErrors('DB_NOT_UPDATED');
+                               exit;
+                       }
+
+                       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+               }
+               header('Location: ./profile.php');
+               exit;
+       }
+}
+
+$sql   = 'SELECT email FROM '.TABLE_PREFIX.'members WHERE member_id='.$_SESSION['member_id'];
+$result = mysql_query($sql,$db);
+$row = mysql_fetch_assoc($result);
+
+if (!isset($_POST['submit'])) {
+       $_POST = $row;
+}
+
+/* template starts here */
+$savant->assign('row', $row);
+$savant->display('users/email_change.tmpl.php');
+
+?>
\ No newline at end of file
diff --git a/users/index.php b/users/index.php
new file mode 100644 (file)
index 0000000..318a056
--- /dev/null
@@ -0,0 +1,103 @@
+<?php
+/****************************************************************************/
+/* ATutor                                                                                                                                      */
+/****************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton       */
+/* Adaptive Technology Resource Centre / University of Toronto                         */
+/* http://atutor.ca                                                                                                                    */
+/*                                                                                                                                                     */
+/* 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.                                                       */
+/****************************************************************************/
+// $Id$
+
+$page = 'my_courses';
+$_user_location        = 'users';
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+if ($_SESSION['valid_user'] !== true) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+
+       $info = array('INVALID_USER', $_SESSION['course_id']);
+       $msg->printInfos($info);
+       
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+$title = _AT('home'); 
+
+// Get the course catagories
+$sql = "SELECT * FROM ".TABLE_PREFIX."course_cats ORDER BY cat_name";
+$result = mysql_query($sql,$db);
+if(mysql_num_rows($result) != 0){
+       while($row = mysql_fetch_assoc($result)){
+               $current_cats[$row['cat_id']] = $row['cat_name'];
+               $parent_cats[$row['cat_id']] =  $row['cat_parent'];
+               $cat_cats[$row['cat_id']] = $row['cat_id'];
+       }
+}
+
+//is this section used on this page?
+if (isset($_GET['auto']) && ($_GET['auto'] == 'disable')) {
+
+       $parts = parse_url(AT_BASE_HREF);
+
+       setcookie('ATLogin', '', time()-172800, $parts['path'], $parts['host'], 0);
+       setcookie('ATPass',  '', time()-172800, $parts['path'], $parts['host'], 0);
+       
+       $msg->addFeedback('AUTO_DISABLED');
+       header('Location: index.php');
+       exit;
+} else if (isset($_GET['auto']) && ($_GET['auto'] == 'enable')) {
+       $parts = parse_url(AT_BASE_HREF);
+
+       $sql    = "SELECT PASSWORD(password) AS pass FROM ".TABLE_PREFIX."members WHERE member_id=$_SESSION[member_id]";
+       $result = mysql_query($sql, $db);
+       $row    = mysql_fetch_array($result);
+
+       setcookie('ATLogin', $_SESSION['login'], time()+172800, $parts['path'], $parts['host'], 0);
+       setcookie('ATPass',  $row['pass'], time()+172800, $parts['path'], $parts['host'], 0);
+
+       $msg->addFeedback('AUTO_ENABLED');
+       header('Location: index.php');
+       exit;
+}
+
+
+//get courses
+$sql = "SELECT E.approved, E.last_cid, C.* FROM ".TABLE_PREFIX."course_enrollment E, ".TABLE_PREFIX."courses C WHERE E.member_id=$_SESSION[member_id] AND E.course_id=C.course_id ORDER BY C.title";
+$result = mysql_query($sql,$db);
+
+$courses = array();
+while ($row = mysql_fetch_assoc($result)) {
+       /* get tests for these courses: */
+       $tests['tests'] = array();
+       $sql3   = "SELECT test_id, title FROM ".TABLE_PREFIX."tests WHERE course_id=$row[course_id] AND (TO_DAYS(start_date) <= TO_DAYS(NOW()) AND TO_DAYS(end_date) >= TO_DAYS(NOW())) AND format=1";
+       $result3 = mysql_query($sql3,$db);
+       while ($row3 = mysql_fetch_assoc($result3)) {
+               $tests['tests'][] = $row3;
+       }
+
+       $courses[] = array_merge($row, (array) $tests);
+}
+
+function get_category_name($cat_id) {
+       global $db;
+       $sql    = "SELECT cat_name FROM ".TABLE_PREFIX."course_cats WHERE cat_id=".$cat_id;
+       $result = mysql_query($sql,$db);
+       $row = mysql_fetch_assoc($result);
+
+       if ($row['cat_name'] == '') {
+               $row['cat_name'] = _AT('cats_uncategorized');
+       } 
+       return $row['cat_name'];
+}
+
+$savant->assign('courses', $courses);
+
+$savant->display('users/index.tmpl.php');
+?>
\ No newline at end of file
diff --git a/users/password_change.php b/users/password_change.php
new file mode 100644 (file)
index 0000000..f3b2da2
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id: profile.php 6025 2006-03-28 20:13:55Z joel $
+
+$page = 'profile';
+$_user_location        = 'users';
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+if ($_SESSION['valid_user'] !== true) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $info = array('INVALID_USER', $_SESSION['course_id']);
+       $msg->printInfos($info);
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       Header('Location: profile.php');
+       exit;
+}
+
+if (isset($_POST['submit'])) {
+       if (!empty($_POST['form_old_password_hidden'])) {
+               //check if old password entered is correct
+               $sql    = "SELECT password FROM ".TABLE_PREFIX."members WHERE member_id=$_SESSION[member_id]";
+               $result = mysql_query($sql,$db);
+               if ($row = mysql_fetch_assoc($result)) {
+                       if ($row['password'] != $_POST['form_old_password_hidden']) {
+                               $msg->addError('WRONG_PASSWORD');
+                               Header('Location: password_change.php');
+                               exit;
+                       }
+               }
+       } else {
+               $msg->addError(array('EMPTY_FIELDS', _AT('password')));
+               header('Location: password_change.php');
+               exit;
+       }
+
+       /* password check: password is verified front end by javascript. here is to handle the errors from javascript */
+       if ($_POST['password_error'] <> "")
+       {
+               $pwd_errors = explode(",", $_POST['password_error']);
+
+               foreach ($pwd_errors as $pwd_error)
+               {
+                       if ($pwd_error == "missing_password")
+                               $missing_fields[] = _AT('password');
+                       else
+                               $msg->addError($pwd_error);
+               }
+       }
+
+       if (!$msg->containsErrors()) {                  
+               // insert into the db.
+               $password   = $addslashes($_POST['form_password_hidden']);
+
+               $sql = "UPDATE ".TABLE_PREFIX."members SET password='$password', creation_date=creation_date, last_login=last_login WHERE member_id=$_SESSION[member_id]";
+               $result = mysql_query($sql,$db);
+               if (!$result) {
+                       require(AT_INCLUDE_PATH.'header.inc.php');
+                       $msg->printErrors('DB_NOT_UPDATED');
+                       require(AT_INCLUDE_PATH.'footer.inc.php');
+                       exit;
+               }
+
+               $msg->addFeedback('PASSWORD_CHANGED');
+               header('Location: ./profile.php');
+               exit;
+       }
+}
+
+/* template starts here */
+$savant->display('users/password_change.tmpl.php');
+
+?>
\ No newline at end of file
diff --git a/users/preferences.php b/users/preferences.php
new file mode 100644 (file)
index 0000000..b168cac
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+$_user_location        = 'users';
+define('AT_INCLUDE_PATH', '../include/');
+
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+require(AT_INCLUDE_PATH.'lib/themes.inc.php');
+
+/* whether or not, any settings are being changed when this page loads. */
+/* ie. is ANY action being performed right now?                                                        */
+$action = false;
+
+if (!$_SESSION['valid_user']) {                                
+       /* we're not logged in */
+       $msg->addFeedback('PREFS_LOGIN');
+}
+
+if (isset($_GET['submit'])) {
+       /* custom prefs */
+
+       $temp_prefs['PREF_NUMBERING']      = intval($_GET['numbering']);
+       $temp_prefs['PREF_THEME']              = $addslashes($_GET['theme']);
+       $temp_prefs['PREF_JUMP_REDIRECT']  = intval($_GET['use_jump_redirect']);
+       $temp_prefs['PREF_FORM_FOCUS']     = intval($_GET['form_focus']);
+       $temp_prefs['PREF_CONTENT_EDITOR'] = intval($_GET['content_editor']);
+
+       /* we do this instead of assigning to the $_SESSION directly, b/c       */
+       /* assign_session_prefs functionality might change slightly.            */
+       assign_session_prefs($temp_prefs);
+
+       /* save as pref for ALL courses */
+       save_prefs();
+
+       //update auto-login settings
+       if (isset($_GET['auto']) && ($_GET['auto'] == 'disable')) {
+               $parts = parse_url(AT_BASE_HREF);
+               setcookie('ATLogin', '', time()-172800, $parts['path'], $parts['host'], 0);
+               setcookie('ATPass',  '', time()-172800, $parts['path'], $parts['host'], 0);             
+       } else if (isset($_GET['auto']) && ($_GET['auto'] == 'enable')) {
+               $parts = parse_url(AT_BASE_HREF);
+               $sql    = "SELECT password FROM ".TABLE_PREFIX."members WHERE member_id=$_SESSION[member_id]";
+               $result = mysql_query($sql, $db);
+               $row    = mysql_fetch_assoc($result);
+               $password = sha1($row['password'] . '-' . DB_PASSWORD);
+               setcookie('ATLogin', $_SESSION['login'], time()+172800, $parts['path'], $parts['host'], 0);
+               setcookie('ATPass',  $password, time()+172800, $parts['path'], $parts['host'], 0);
+       }
+
+       /* also update message notification pref */
+       $_GET['mnot'] = intval($_GET['mnot']);
+       $sql = "UPDATE ".TABLE_PREFIX."members SET inbox_notify = $_GET[mnot], creation_date=creation_date, last_login=last_login WHERE member_id = $_SESSION[member_id]";
+       $result = mysql_query($sql, $db);
+
+       $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
+       header('Location: '.AT_BASE_HREF.'users/preferences.php');
+       exit;
+}
+
+$sql   = "SELECT inbox_notify FROM ".TABLE_PREFIX."members WHERE member_id=$_SESSION[member_id]";
+$result = mysql_query($sql, $db);
+$row_notify = mysql_fetch_assoc($result);
+
+/* page contents starts here */
+$savant->assign('notify', $row_notify['inbox_notify']);
+
+$savant->display('users/preferences.tmpl.php');
+?>
\ No newline at end of file
diff --git a/users/private_enroll.php b/users/private_enroll.php
new file mode 100644 (file)
index 0000000..f271839
--- /dev/null
@@ -0,0 +1,126 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+$_user_location        = 'users';
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+if (!$_SESSION['valid_user']) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+       $msg->printErrors('LOGIN_ENROL');
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+$course = intval($_REQUEST['course']);
+if ($course == 0) {
+       exit;
+}
+
+$sql   = "SELECT access, member_id FROM ".TABLE_PREFIX."courses WHERE course_id=$course";
+$result = mysql_query($sql, $db);
+$course_info = mysql_fetch_assoc($result);
+
+if ($_POST['submit']) {
+       $_SESSION['enroll'] = AT_ENROLL_YES;
+
+       if ($course_info['access'] == 'private') {
+               $sql    = "INSERT INTO ".TABLE_PREFIX."course_enrollment VALUES ($_SESSION[member_id], $course, 'n', 0, '"._AT('student')."', 0)";
+               $result = mysql_query($sql, $db);
+
+               // send the email - if needed
+               if ($system_courses[$course]['notify'] == 1) {
+                       $mail_list = array();   //initialize an array to store all the pending emails
+
+                       //Get the list of students with enrollment privilege
+                       $module =& $moduleFactory->getModule('_core/enrolment');
+                       $sql    = "SELECT email, first_name, last_name, privileges FROM ".TABLE_PREFIX."members m INNER JOIN ".TABLE_PREFIX."course_enrollment ce ON m.member_id=ce.member_id WHERE ce.privileges > 0 AND ce.course_id=$course";
+                       $result = mysql_query($sql, $db);
+                       while ($row     = mysql_fetch_assoc($result)){
+                               if (query_bit($row['privileges'], $module->getPrivilege())){
+                                       unset($row['privileges']);      //we don't need the privilege to flow around
+                                       $mail_list[] = $row;
+                               }
+                       }
+                       
+                       //Get instructor information
+                       $ins_id = $system_courses[$course]['member_id'];
+                       $sql    = "SELECT email, first_name, last_name FROM ".TABLE_PREFIX."members WHERE member_id=$ins_id";
+                       $result = mysql_query($sql, $db);
+                       $row    = mysql_fetch_assoc($result);
+                       $mail_list[] = $row;
+
+                       //Send email notification to both assistants with privileges & Instructor
+                       foreach ($mail_list as $row){
+                               $to_email = $row['email'];
+                               $tmp_message  = $row['first_name']  .' ' . $row['last_name']."\n\n";
+                               $tmp_message .= _AT('enrol_messagenew', $system_courses[$course]['title'], AT_BASE_HREF );
+                               if ($to_email != '') {
+                                       require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+
+                                       $mail = new ATutorMailer;
+                                       $mail->From     = $_config['contact_email'];
+                                       $mail->FromName = $_config['site_name'];
+                                       $mail->AddAddress($to_email);
+                                       $mail->Subject = _AT('enrol_message3');
+                                       $mail->Body    = $tmp_message;
+
+                                       if (!$mail->Send()) {
+                                          require(AT_INCLUDE_PATH.'header.inc.php');
+                                          $msg->printErrors('SENDING_ERROR');
+                                          require(AT_INCLUDE_PATH.'footer.inc.php');
+                                          exit;
+                                       }
+                                       unset($mail);
+                               }
+                       }
+               }
+               require(AT_INCLUDE_PATH.'header.inc.php');
+               $msg->printFeedbacks('APPROVAL_PENDING');
+               require(AT_INCLUDE_PATH.'footer.inc.php');
+               exit;
+       } else {
+               $sql    = "INSERT INTO ".TABLE_PREFIX."course_enrollment VALUES ($_SESSION[member_id], $course, 'y', 0, '"._AT('student')."', 0)";
+               $result = mysql_query($sql, $db);
+       }
+}
+
+$sql   = "SELECT * FROM ".TABLE_PREFIX."course_enrollment WHERE member_id=$_SESSION[member_id] AND course_id=$course";
+$result = mysql_query($sql, $db);
+$row_in = mysql_fetch_assoc($result);
+
+// request has already been made
+if ($row_in['member_id'] == $_SESSION['member_id'] ) {
+       $msg->addFeedback('ALREADY_REQUESTED');
+       header('Location: ./index.php');
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+?>
+
+<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+<input type="hidden" name="course" value="<?php echo $course; ?>">
+<div class="input-form">
+       <div class="row">
+               <?php echo _AT('private_enroll'); ?>
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('request_enrollment'); ?>" />
+       </div>
+</div>
+</form>
+
+<?php  require(AT_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
diff --git a/users/profile.php b/users/profile.php
new file mode 100644 (file)
index 0000000..7cc2b91
--- /dev/null
@@ -0,0 +1,148 @@
+<?php
+/************************************************************************/
+/* ATutor                                                                                                                              */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
+/* Adaptive Technology Resource Centre / University of Toronto                 */
+/* http://atutor.ca                                                                                                            */
+/*                                                                                                                                             */
+/* 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.                                               */
+/************************************************************************/
+// $Id$
+
+$_user_location        = 'users';
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+if ($_SESSION['valid_user'] !== true) {
+       require(AT_INCLUDE_PATH.'header.inc.php');
+
+       $info = array('INVALID_USER', $_SESSION['course_id']);
+       $msg->printInfos($info);
+       
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+       exit;
+}
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       Header('Location: profile.php');
+       exit;
+}
+
+if (isset($_POST['submit'])) {
+       $missing_fields = array();
+
+       if (!$_POST['first_name']) { 
+               $missing_fields[] = _AT('first_name');
+       }
+
+       if (!$_POST['last_name']) { 
+               $missing_fields[] = _AT('last_name');
+       }
+
+       $_POST['first_name'] = str_replace('<', '', $_POST['first_name']);
+       $_POST['second_name'] = str_replace('<', '', $_POST['second_name']);
+       $_POST['last_name'] = str_replace('<', '', $_POST['last_name']);
+
+       // check if first+last is unique
+       if ($_POST['first_name'] && $_POST['last_name']) {
+               $first_name_sql  = $addslashes($_POST['first_name']);
+               $last_name_sql   = $addslashes($_POST['last_name']);
+               $second_name_sql = $addslashes($_POST['second_name']);
+
+               $sql = "SELECT member_id FROM ".TABLE_PREFIX."members WHERE first_name='$first_name_sql' AND second_name='$second_name_sql' AND last_name='$last_name_sql' AND member_id<>$_SESSION[member_id] LIMIT 1";
+               $result = mysql_query($sql, $db);
+               if (mysql_fetch_assoc($result)) {
+                       $msg->addError('FIRST_LAST_NAME_UNIQUE');
+               }
+       }
+
+       //check date of birth
+       $mo = intval($_POST['month']);
+       $day = intval($_POST['day']);
+       $yr = intval($_POST['year']);
+
+       /* let's us take (one or) two digit years (ex. 78 = 1978, 3 = 2003) */
+       if ($yr < date('y')) { 
+               $yr += 2000; 
+       } else if ($yr < 1900) { 
+               $yr += 1900; 
+       } 
+
+       $dob = $yr.'-'.$mo.'-'.$day;
+
+       if ($mo && $day && $yr && !checkdate($mo, $day, $yr)) { 
+               $msg->addError('DOB_INVALID');
+       } else if (!$mo || !$day || !$yr) {
+               $dob = '0000-00-00';
+               $yr = $mo = $day = 0;
+       }
+
+       if (($_POST['gender'] != 'm') && ($_POST['gender'] != 'f')) {
+               $_POST['gender'] = 'n'; // not specified
+       }
+       
+       
+       if ($missing_fields) {
+               $missing_fields = implode(', ', $missing_fields);
+               $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+       }
+       $login = strtolower($_POST['login']);
+       if (!$msg->containsErrors()) {                  
+               if (($_POST['website']) && (!ereg('://',$_POST['website']))) { $_POST['website'] = 'http://'.$_POST['website']; }
+               if ($_POST['website'] == 'http://') { $_POST['website'] = ''; }
+
+               if (isset($_POST['private_email'])) {
+                       $_POST['private_email'] = 1;
+               } else {
+                       $_POST['private_email'] = 0;
+               }
+
+               // insert into the db.
+               $_POST['website']    = $addslashes($_POST['website']);
+               $_POST['first_name'] = $addslashes($_POST['first_name']);
+               $_POST['second_name']= $addslashes($_POST['second_name']);
+               $_POST['last_name']  = $addslashes($_POST['last_name']);
+               $_POST['address']    = $addslashes($_POST['address']);
+               $_POST['postal']     = $addslashes($_POST['postal']);
+               $_POST['city']       = $addslashes($_POST['city']);
+               $_POST['province']   = $addslashes($_POST['province']);
+               $_POST['country']    = $addslashes($_POST['country']);
+               $_POST['phone']      = $addslashes($_POST['phone']);
+
+               $sql = "UPDATE ".TABLE_PREFIX."members SET website='$_POST[website]', first_name='$_POST[first_name]', second_name='$_POST[second_name]', last_name='$_POST[last_name]', dob='$dob', gender='$_POST[gender]', address='$_POST[address]', postal='$_POST[postal]', city='$_POST[city]', province='$_POST[province]', country='$_POST[country]', phone='$_POST[phone]', language='$_SESSION[lang]', private_email=$_POST[private_email], creation_date=creation_date, last_login=last_login WHERE member_id=$_SESSION[member_id]";
+
+               $result = mysql_query($sql,$db);
+               if (!$result) {
+                       $msg->printErrors('DB_NOT_UPDATED');
+                       exit;
+               }
+
+               $msg->addFeedback('PROFILE_UPDATED');
+
+               header('Location: ./profile.php');
+               exit;
+       }
+}
+
+$sql   = 'SELECT * FROM '.TABLE_PREFIX.'members WHERE member_id='.$_SESSION['member_id'];
+$result = mysql_query($sql,$db);
+$row = mysql_fetch_assoc($result);
+
+if (!isset($_POST['submit'])) {
+       $_POST = $row;
+       list($_POST['year'],$_POST['month'],$_POST['day']) = explode('-', $row['dob']);
+}
+
+/* template starts here */
+
+$savant->assign('row', $row);
+$onload = 'document.form.first_name.focus();';
+
+//$savant->display('registration.tmpl.php');
+$savant->display('users/profile.tmpl.php');
+?>
\ No newline at end of file
diff --git a/users/profile_picture.php b/users/profile_picture.php
new file mode 100644 (file)
index 0000000..ab70365
--- /dev/null
@@ -0,0 +1,20 @@
+<?php\r
+/************************************************************************/\r
+/* ATutor                                                                                                                              */\r
+/************************************************************************/\r
+/* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
+/* Adaptive Technology Resource Centre / University of Toronto                 */\r
+/* http://atutor.ca                                                                                                            */\r
+/*                                                                                                                                             */\r
+/* This program is free software. You can redistribute it and/or               */\r
+/* modify it under the terms of the GNU General Public License                 */\r
+/* as published by the Free Software Foundation.                                               */\r
+/************************************************************************/\r
+// $Id$\r
+\r
+define('AT_INCLUDE_PATH', '../include/');\r
+$_user_location        = 'users';\r
+require (AT_INCLUDE_PATH.'vitals.inc.php');\r
+$member_id = $_SESSION['member_id'];\r
+\r
+require(AT_INCLUDE_PATH.'html/profile_picture.inc.php'); ?>
\ No newline at end of file
diff --git a/users/prog.php b/users/prog.php
new file mode 100644 (file)
index 0000000..1c8015c
--- /dev/null
@@ -0,0 +1,87 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+$_user_location        = 'users';
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html lang="en">
+<head>
+       <title><?php echo _AT('upload_progress'); ?></title>
+       <?php if ($_GET['frame']) { ?>
+               <META HTTP-EQUIV="refresh" content="3;URL=prog.php?frame=1"> 
+       <?php } ?>
+       <link rel="stylesheet" href="../stylesheet.css" type="text/css" />
+       <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+</head>
+<body <?php
+       if ($_SESSION['done']) {
+               echo 'onLoad="parent.window.close();"';
+       }
+
+?>>
+
+<?php if (!$_GET['frame']) { 
+       
+       $_SESSION['done'] = 0;
+       session_write_close();
+?>
+&nbsp;<a href="javascript:window.close();"><?php echo _AT('close'); ?></a>
+<h3><?php echo _AT('upload_progress'); ?></h3>
+<p><small><?php echo _AT('window_auto_close'); ?></small></p>
+
+<br /><br />
+<table border="0" align="center">
+<tr>
+       <td><img src="../images/transfer.gif" height="20" width="90" alt="file upload in progress..."></td>
+       <td valign="middle"><iframe src="prog.php?frame=1" width="100" height="25" frameborder="0" scrolling=no marginwidth="0" marginheight="1">
+</iframe>
+<?php } else { 
+       if (!$_GET['t']) {
+               $newest_file_name = '';
+               $newest_file_time = 0;
+               // get the name of the temp file.
+               if ($dir = @opendir('/tmp')) {
+                       while (($file = readdir($dir)) !== false) {
+                               if ((strlen($file) == 9) && (substr($file, 0, 3) == 'php')) {
+                                       $filedata = stat('/tmp/'.$file);
+                                       if ($filedata['mtime'] > $newest_file_time) {
+                                               $newest_file_time = $filedata['mtime'];
+                                               $newest_file_name = $file;
+                                               $size = $filedata['size'] / 1024;
+                                       }
+                               }
+                       }
+                       closedir($dir);
+               }
+       } else {
+               $filedata = stat('/tmp/'.$_GET['t']);
+               $size = $filedata['size'] / 1024;
+       }
+
+       echo '<small>';
+       // not sure where these are displayed in the progress popup
+       if ($size == '') {
+               echo '<em>Unknown</em> '._AT('kb');
+       } else {
+               echo $size.' '._AT('kb');
+       }
+       echo '</small>';
+} ?></td>
+</tr>
+</table>
+</body>
+</html>
diff --git a/users/remove_course.php b/users/remove_course.php
new file mode 100644 (file)
index 0000000..14a161a
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+$_user_location        = 'users';
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+if (isset($_POST['submit_no'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: index.php');
+       exit;
+} else if (isset($_POST['submit_yes'])) {
+       $course = intval($_POST['course']);
+       if ($system_courses[$course]['member_id'] != $_SESSION['member_id']) {
+               $sql    = "DELETE FROM ".TABLE_PREFIX."course_enrollment WHERE member_id=$_SESSION[member_id] AND course_id=$course";
+               $result = mysql_query($sql, $db) or die(mysql_error());
+
+               // Unsubscribe from forums and threads of the course
+               $sql    = "DELETE FROM ".TABLE_PREFIX."forums_subscriptions 
+                        WHERE forum_id IN (SELECT forum_id FROM ".TABLE_PREFIX."forums_courses WHERE course_id=$course)
+                          AND member_id=".$_SESSION[member_id];
+               $result = mysql_query($sql, $db) or die(mysql_error());
+
+               $sql    = "UPDATE ".TABLE_PREFIX."forums_accessed 
+                          SET subscribe = 0
+                        WHERE post_id IN (SELECT distinct t.post_id FROM ".TABLE_PREFIX."forums_courses c, ".TABLE_PREFIX."forums_threads t WHERE c.course_id=$course)
+                          AND member_id=".$_SESSION[member_id];
+               $result = mysql_query($sql, $db) or die(mysql_error());
+
+               $msg->addFeedback('COURSE_REMOVED');
+       }
+       header("Location: ".AT_BASE_HREF."users/index.php");
+       exit;
+}
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+unset($hidden_vars);
+$hidden_vars['course'] = $_GET['course'];
+$msg->addConfirm(array('UNENROLL', $system_courses[$_GET['course']]['title']), $hidden_vars);
+
+$msg->printConfirm();
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file
diff --git a/users/request_instructor.php b/users/request_instructor.php
new file mode 100644 (file)
index 0000000..dce2b57
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+/****************************************************************/
+/* ATutor                                                                                                              */
+/****************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
+/* Adaptive Technology Resource Centre / University of Toronto  */
+/* http://atutor.ca                                                                                            */
+/*                                                              */
+/* 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.                               */
+/****************************************************************/
+// $Id$
+
+$_user_location        = 'users';
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+$_POST['description'] = trim($_POST['description']);
+
+if (isset($_POST['cancel'])) {
+       $msg->addFeedback('CANCELLED');
+       header('Location: '.AT_BASE_HREF.'users/index.php');
+       exit;
+
+} else if ($_POST['description'] == ''){
+       $msg->addError(array('EMPTY_FIELDS', _AT('description')));
+       header('Location: '.AT_BASE_HREF.'users/create_course.php');
+       exit;
+} else if (isset($_POST['form_request_instructor'])) {
+        if (defined('AUTO_APPROVE_INSTRUCTORS') && AUTO_APPROVE_INSTRUCTORS) {
+               $sql    = "UPDATE ".TABLE_PREFIX."members SET status=".AT_STATUS_INSTRUCTOR.", creation_date=creation_date, last_login=last_login WHERE member_id=$_SESSION[member_id]";
+               $result = mysql_query($sql, $db);
+
+               $msg->addFeedback('ACCOUNT_APPROVED');
+
+       } else {
+
+               $_POST['description'] = $addslashes($_POST['description']);
+
+               $sql    = "INSERT INTO ".TABLE_PREFIX."instructor_approvals VALUES ($_SESSION[member_id], NOW(), '$_POST[description]')";
+               $result = mysql_query($sql, $db);
+               /* email notification send to admin upon instructor request */
+
+               if (EMAIL_NOTIFY && ($_config['contact_email'] != '')) {
+
+                       $sql    = "SELECT login, email FROM ".TABLE_PREFIX."members WHERE member_id=$_SESSION[member_id]";
+                       $result = mysql_query($sql, $db);                               
+                       if ($row = mysql_fetch_assoc($result)) {
+                               $email = $row['email'];
+                       }
+                       $tmp_message = _AT('req_message_instructor', get_display_name($_SESSION['member_id']), $_POST['description'], AT_BASE_HREF);
+
+                       require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php');
+
+                       $mail = new ATutorMailer;
+
+                       $mail->From     = $email;
+                       $mail->AddAddress($_config['contact_email']);
+                       $mail->Subject = _AT('req_message9');
+                       $mail->Body    = stripslashes($tmp_message);
+
+                       if(!$mail->Send()) {
+                          //echo 'There was an error sending the message';
+                          $msg->printErrors('SENDING_ERROR');
+                          exit;
+                       }
+
+                       unset($mail);
+
+               }
+               $msg->addFeedback('APPROVAL_PENDING');
+       }
+
+       header('Location: ./index.php');
+       exit;
+} 
+
+$title = _AT('request_instructor_account');
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+if ($msg->containsErrors()) { $msg->printErrors(); }
+
+if (ALLOW_INSTRUCTOR_REQUESTS && ($row['status'] != AT_STATUS_INSTRUCTOR) ) {
+       $sql    = "SELECT * FROM ".TABLE_PREFIX."instructor_approvals WHERE member_id=$_SESSION[member_id]";
+       $result = mysql_query($sql, $db);
+       if (!($row = mysql_fetch_array($result))) {
+               $msg->printInfos('REQUEST_ACCOUNT');
+?>
+               <br /><form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
+               <p align="center">
+                       <input type="hidden" name="form_request_instructor" value="true" />
+                       <label for="desc"><?php echo _AT('give_description'); ?></label><br /><br />
+                       <textarea cols="40" rows="3" class="formfield" id="desc" name="description" scroll="no"></textarea><br /><br />
+                       <input type="submit" name="submit" value="<?php echo _AT('request_instructor_account'); ?>" class="button" />
+               </p>
+               </form>
+<?php
+       } else {
+               /* already waiting for approval */
+               $msg->printInfos('APPROVAL_PENDING');
+       }
+} 
+
+       require(AT_INCLUDE_PATH.'footer.inc.php');
+
+?>
\ No newline at end of file
diff --git a/users/search.php b/users/search.php
new file mode 100644 (file)
index 0000000..f5ab3b6
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+exit('no longer used');
+/************************************************************************/
+/* ATutor                                                                                                                      */
+/************************************************************************/
+/* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg & Boon-Hau Teh */
+/* Adaptive Technology Resource Centre / University of Toronto          */
+/* http://atutor.ca                                                                                                    */
+/*                                                                      */
+/* 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.                                       */
+/************************************************************************/
+// $Id$
+
+$_user_location = 'users';
+
+define('AT_INCLUDE_PATH', '../include/');
+require(AT_INCLUDE_PATH.'vitals.inc.php');
+
+require(AT_INCLUDE_PATH.'lib/search.inc.php');
+
+require(AT_INCLUDE_PATH.'header.inc.php');
+
+require(AT_INCLUDE_PATH.'html/search.inc.php');
+
+require(AT_INCLUDE_PATH.'footer.inc.php');
+?>
\ No newline at end of file